See the best posts from any Bluesky account
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Replace mise dev tasks with concurrently for clean signal handling

mise's parallel task runner didn't propagate SIGINT cleanly, requiring
double Ctrl-C and leaving ghost node processes. Switched to concurrently
via pnpm scripts which handles process groups properly. Also added
.vite to .gitignore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+109 -60
+1
.gitignore
··· 7 7 # Build output 8 8 build/ 9 9 dist/ 10 + .vite 10 11 11 12 # Adonis tmp 12 13 tmp/*
+3 -13
AGENTS.md
··· 17 17 18 18 ## Commands 19 19 20 - Preferred workflow is via `mise` tasks (see `mise.toml`): 21 - 22 - ```bash 23 - mise run dev # ClickHouse + migrations + web + jetstream + queue (parallel) 24 - mise run db:wait # Start ClickHouse, wait for /ping 25 - mise run db:migrate # Run Lucid + ClickHouse migrations 26 - mise run dev:web # node ace serve --hmr 27 - mise run dev:jetstream # node ace jetstream:consume 28 - mise run dev:queue # node ace queue:work 29 - ``` 30 - 31 - Direct pnpm scripts: 20 + pnpm scripts: 32 21 33 22 ```bash 34 - pnpm dev # node ace serve --hmr 23 + pnpm dev # migrations, then web + jetstream + queue (via concurrently) 24 + pnpm migrate # Run SQLite + ClickHouse migrations 35 25 pnpm test # node ace test (Japa) 36 26 pnpm lint # eslint . 37 27 pnpm typecheck # tsc --noEmit
-46
mise.toml
··· 5 5 [env] 6 6 CLICKHOUSE_PASSWORD = "" 7 7 APP_KEY = "mise-task-placeholder" 8 - 9 - [tasks."db:wait"] 10 - description = "Start ClickHouse and wait for it to respond on /ping" 11 - run = ''' 12 - #!/usr/bin/env bash 13 - set -euo pipefail 14 - docker compose up -d clickhouse 15 - for i in $(seq 1 30); do 16 - if curl -sf http://localhost:8123/ping > /dev/null 2>&1; then 17 - echo "ClickHouse is ready" 18 - exit 0 19 - fi 20 - printf "." 21 - sleep 1 22 - done 23 - echo >&2 24 - echo "ClickHouse did not become ready within 30 seconds" >&2 25 - exit 1 26 - ''' 27 - 28 - [tasks."db:migrate"] 29 - description = "Run SQLite + ClickHouse migrations" 30 - depends = ["db:wait"] 31 - run = [ 32 - "node ace migration:run --force", 33 - "node ace clickhouse:migrate", 34 - ] 35 - 36 - [tasks."dev:web"] 37 - description = "Run the Adonis HTTP server with hot reload" 38 - run = "node ace serve --hmr" 39 - 40 - [tasks."dev:jetstream"] 41 - description = "Run the Jetstream consumer worker" 42 - run = "node ace jetstream:consume" 43 - 44 - [tasks."dev:queue"] 45 - description = "Run the queue worker (backfill jobs)" 46 - run = "node ace queue:work" 47 - 48 - [tasks.dev] 49 - description = "Spin up the full dev environment: ClickHouse, migrations, web + jetstream + queue workers" 50 - depends = ["db:migrate"] 51 - run = [ 52 - { tasks = ["dev:web", "dev:jetstream", "dev:queue"] }, 53 - ]
+3 -1
package.json
··· 17 17 "scripts": { 18 18 "start": "node bin/server.js", 19 19 "build": "node ace build", 20 - "dev": "node ace serve --hmr", 20 + "dev": "pnpm migrate && concurrently --kill-others -n web,jetstream,queue -c blue,green,yellow \"node ace serve --hmr\" \"node ace jetstream:consume\" \"node ace queue:work\"", 21 + "migrate": "node ace migration:run --force && node ace clickhouse:migrate", 21 22 "test": "node ace test", 22 23 "lint": "eslint .", 23 24 "format": "prettier --write .", ··· 58 59 "@types/alpinejs": "^3.13.11", 59 60 "@types/luxon": "^3.7.1", 60 61 "@types/node": "~25.5.0", 62 + "concurrently": "^9.2.1", 61 63 "eslint": "^10.1.0", 62 64 "execa": "^9.6.1", 63 65 "hot-hook": "^1.0.0",
+102
pnpm-lock.yaml
··· 99 99 '@types/node': 100 100 specifier: ~25.5.0 101 101 version: 25.5.2 102 + concurrently: 103 + specifier: ^9.2.1 104 + version: 9.2.1 102 105 eslint: 103 106 specifier: ^10.1.0 104 107 version: 10.2.0(jiti@2.6.1) ··· 1605 1608 resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} 1606 1609 engines: {node: '>=20'} 1607 1610 1611 + cliui@8.0.1: 1612 + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} 1613 + engines: {node: '>=12'} 1614 + 1608 1615 code-block-writer@13.0.3: 1609 1616 resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==} 1610 1617 ··· 1634 1641 1635 1642 component-emitter@1.3.1: 1636 1643 resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} 1644 + 1645 + concurrently@9.2.1: 1646 + resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==} 1647 + engines: {node: '>=18'} 1648 + hasBin: true 1637 1649 1638 1650 content-disposition@1.1.0: 1639 1651 resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} ··· 2060 2072 2061 2073 function-bind@1.1.2: 2062 2074 resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 2075 + 2076 + get-caller-file@2.0.5: 2077 + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 2078 + engines: {node: 6.* || 8.* || >= 10.*} 2063 2079 2064 2080 get-east-asian-width@1.5.0: 2065 2081 resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} ··· 2821 2837 resolution: {integrity: sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==} 2822 2838 hasBin: true 2823 2839 2840 + require-directory@2.1.1: 2841 + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 2842 + engines: {node: '>=0.10.0'} 2843 + 2824 2844 resolve-from@5.0.0: 2825 2845 resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 2826 2846 engines: {node: '>=8'} ··· 2860 2880 run-parallel@1.2.0: 2861 2881 resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 2862 2882 2883 + rxjs@7.8.2: 2884 + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} 2885 + 2863 2886 safe-buffer@5.2.1: 2864 2887 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 2865 2888 ··· 2900 2923 resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 2901 2924 engines: {node: '>=8'} 2902 2925 2926 + shell-quote@1.8.3: 2927 + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} 2928 + engines: {node: '>= 0.4'} 2929 + 2903 2930 side-channel-list@1.0.1: 2904 2931 resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} 2905 2932 engines: {node: '>= 0.4'} ··· 3027 3054 resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 3028 3055 engines: {node: '>=8'} 3029 3056 3057 + supports-color@8.1.1: 3058 + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} 3059 + engines: {node: '>=10'} 3060 + 3030 3061 supports-preserve-symlinks-flag@1.0.0: 3031 3062 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 3032 3063 engines: {node: '>= 0.4'} ··· 3104 3135 resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} 3105 3136 engines: {node: '>=14.16'} 3106 3137 3138 + tree-kill@1.2.2: 3139 + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 3140 + hasBin: true 3141 + 3107 3142 ts-api-utils@2.5.0: 3108 3143 resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} 3109 3144 engines: {node: '>=18.12'} ··· 3265 3300 wrap-ansi@10.0.0: 3266 3301 resolution: {integrity: sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==} 3267 3302 engines: {node: '>=20'} 3303 + 3304 + wrap-ansi@7.0.0: 3305 + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 3306 + engines: {node: '>=10'} 3268 3307 3269 3308 wrappy@1.0.2: 3270 3309 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} ··· 3273 3312 resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} 3274 3313 engines: {node: '>=20'} 3275 3314 3315 + y18n@5.0.8: 3316 + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 3317 + engines: {node: '>=10'} 3318 + 3319 + yargs-parser@21.1.1: 3320 + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} 3321 + engines: {node: '>=12'} 3322 + 3276 3323 yargs-parser@22.0.0: 3277 3324 resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} 3278 3325 engines: {node: ^20.19.0 || ^22.12.0 || >=23} 3326 + 3327 + yargs@17.7.2: 3328 + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} 3329 + engines: {node: '>=12'} 3279 3330 3280 3331 yocto-queue@0.1.0: 3281 3332 resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} ··· 4638 4689 slice-ansi: 8.0.0 4639 4690 string-width: 8.2.0 4640 4691 4692 + cliui@8.0.1: 4693 + dependencies: 4694 + string-width: 4.2.3 4695 + strip-ansi: 6.0.1 4696 + wrap-ansi: 7.0.0 4697 + 4641 4698 code-block-writer@13.0.3: {} 4642 4699 4643 4700 color-convert@2.0.1: ··· 4660 4717 4661 4718 component-emitter@1.3.1: {} 4662 4719 4720 + concurrently@9.2.1: 4721 + dependencies: 4722 + chalk: 4.1.2 4723 + rxjs: 7.8.2 4724 + shell-quote: 1.8.3 4725 + supports-color: 8.1.1 4726 + tree-kill: 1.2.2 4727 + yargs: 17.7.2 4728 + 4663 4729 content-disposition@1.1.0: {} 4664 4730 4665 4731 content-type@1.0.5: {} ··· 5091 5157 optional: true 5092 5158 5093 5159 function-bind@1.1.2: {} 5160 + 5161 + get-caller-file@2.0.5: {} 5094 5162 5095 5163 get-east-asian-width@1.5.0: {} 5096 5164 ··· 5750 5818 dependencies: 5751 5819 jsesc: 3.1.0 5752 5820 5821 + require-directory@2.1.1: {} 5822 + 5753 5823 resolve-from@5.0.0: {} 5754 5824 5755 5825 resolve-pkg-maps@1.0.0: {} ··· 5808 5878 dependencies: 5809 5879 queue-microtask: 1.2.3 5810 5880 5881 + rxjs@7.8.2: 5882 + dependencies: 5883 + tslib: 2.8.1 5884 + 5811 5885 safe-buffer@5.2.1: {} 5812 5886 5813 5887 safe-stable-stringify@2.5.0: {} ··· 5852 5926 shebang-regex: 3.0.0 5853 5927 5854 5928 shebang-regex@3.0.0: {} 5929 + 5930 + shell-quote@1.8.3: {} 5855 5931 5856 5932 side-channel-list@1.0.1: 5857 5933 dependencies: ··· 5987 6063 dependencies: 5988 6064 has-flag: 4.0.0 5989 6065 6066 + supports-color@8.1.1: 6067 + dependencies: 6068 + has-flag: 4.0.0 6069 + 5990 6070 supports-preserve-symlinks-flag@1.0.0: {} 5991 6071 5992 6072 synckit@0.11.12: ··· 6050 6130 '@borewit/text-codec': 0.2.2 6051 6131 '@tokenizer/token': 0.3.0 6052 6132 ieee754: 1.2.1 6133 + 6134 + tree-kill@1.2.2: {} 6053 6135 6054 6136 ts-api-utils@2.5.0(typescript@6.0.2): 6055 6137 dependencies: ··· 6171 6253 string-width: 8.2.0 6172 6254 strip-ansi: 7.2.0 6173 6255 6256 + wrap-ansi@7.0.0: 6257 + dependencies: 6258 + ansi-styles: 4.3.0 6259 + string-width: 4.2.3 6260 + strip-ansi: 6.0.1 6261 + 6174 6262 wrappy@1.0.2: {} 6175 6263 6176 6264 wsl-utils@0.3.1: 6177 6265 dependencies: 6178 6266 is-wsl: 3.1.1 6179 6267 powershell-utils: 0.1.0 6268 + 6269 + y18n@5.0.8: {} 6270 + 6271 + yargs-parser@21.1.1: {} 6180 6272 6181 6273 yargs-parser@22.0.0: {} 6274 + 6275 + yargs@17.7.2: 6276 + dependencies: 6277 + cliui: 8.0.1 6278 + escalade: 3.2.0 6279 + get-caller-file: 2.0.5 6280 + require-directory: 2.1.1 6281 + string-width: 4.2.3 6282 + y18n: 5.0.8 6283 + yargs-parser: 21.1.1 6182 6284 6183 6285 yocto-queue@0.1.0: {} 6184 6286