@catapultjs/deploy 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +9 -1
  2. package/build/commands/list_revisions.js +12 -25
  3. package/build/commands/list_revisions.js.map +1 -1
  4. package/build/commands/status.d.ts +1 -0
  5. package/build/commands/status.js +36 -78
  6. package/build/commands/status.js.map +1 -1
  7. package/build/commands/version.js +3 -3
  8. package/build/commands/version.js.map +1 -1
  9. package/build/index.d.ts +3 -0
  10. package/build/index.js +3 -0
  11. package/build/index.js.map +1 -1
  12. package/build/recipes/astro.js +9 -13
  13. package/build/recipes/astro.js.map +1 -1
  14. package/build/recipes/astro_static.d.ts +1 -0
  15. package/build/recipes/astro_static.js +11 -0
  16. package/build/recipes/astro_static.js.map +1 -0
  17. package/build/recipes/deploy/update_code.js +5 -4
  18. package/build/recipes/deploy/update_code.js.map +1 -1
  19. package/build/recipes/nestjs.d.ts +1 -0
  20. package/build/recipes/nestjs.js +5 -0
  21. package/build/recipes/nestjs.js.map +1 -0
  22. package/build/recipes/nextjs.d.ts +1 -0
  23. package/build/recipes/nextjs.js +20 -0
  24. package/build/recipes/nextjs.js.map +1 -0
  25. package/build/recipes/nextjs_static.d.ts +1 -0
  26. package/build/recipes/nextjs_static.js +8 -0
  27. package/build/recipes/nextjs_static.js.map +1 -0
  28. package/build/recipes/nuxt_static.d.ts +1 -0
  29. package/build/recipes/nuxt_static.js +8 -0
  30. package/build/recipes/nuxt_static.js.map +1 -0
  31. package/build/recipes/pm2.js +15 -14
  32. package/build/recipes/pm2.js.map +1 -1
  33. package/build/recipes/tanstack.d.ts +1 -0
  34. package/build/recipes/tanstack.js +5 -0
  35. package/build/recipes/tanstack.js.map +1 -0
  36. package/build/src/api.d.ts +60 -0
  37. package/build/src/api.js +159 -0
  38. package/build/src/api.js.map +1 -0
  39. package/build/src/deployer.d.ts +7 -1
  40. package/build/src/deployer.js +19 -1
  41. package/build/src/deployer.js.map +1 -1
  42. package/build/src/status.d.ts +18 -0
  43. package/build/src/status.js +59 -0
  44. package/build/src/status.js.map +1 -0
  45. package/build/src/task/store.d.ts +4 -1
  46. package/build/src/task/store.js +8 -2
  47. package/build/src/task/store.js.map +1 -1
  48. package/build/src/task.d.ts +4 -1
  49. package/build/src/task.js +2 -2
  50. package/build/src/task.js.map +1 -1
  51. package/package.json +16 -7
  52. package/skills/catapultjs/SKILL.md +41 -0
  53. package/skills/catapultjs/references/api.md +70 -0
  54. package/skills/catapultjs/references/cli.md +160 -0
  55. package/skills/catapultjs/references/config.md +194 -0
  56. package/skills/catapultjs/references/github-actions.md +99 -0
  57. package/skills/catapultjs/references/recipe.md +115 -0
  58. package/skills/catapultjs/references/recipes.md +596 -0
@@ -0,0 +1,596 @@
1
+ # Official Catapult recipes
2
+
3
+ Recipes are imported as side effects and register tasks into the pipeline automatically. Import order matters: `set()` calls that configure a recipe must appear **before** the recipe import.
4
+
5
+ Full docs: https://catapultjs.com/guide/recipes
6
+
7
+ ## Choosing a recipe
8
+
9
+ | Recipe | Delivers `deploy:update_code`? | Use when |
10
+ | --- | --- | --- |
11
+ | `recipes/git` | Yes | Server can reach the repo; build runs on the server |
12
+ | `recipes/rsync` | Yes | Local build, push artifacts via rsync |
13
+ | `recipes/astro` | No (pair with `git` or `rsync`) | Astro, build on the server |
14
+ | `recipes/astro_static` | Uses default SCP; `rsync` optional | Static Astro site, build locally |
15
+ | `recipes/vitepress` | Yes | VitePress site, build locally, upload dist |
16
+ | `recipes/adonisjs_local` | Yes | AdonisJS, build locally, upload artifact |
17
+ | `recipes/adonisjs` | No (pair with `git` or `rsync`) | AdonisJS, build on the server |
18
+ | `recipes/nestjs` | No (pair with `git` or `rsync`) | NestJS, build on the server |
19
+ | `recipes/nextjs` | No (pair with `git` or `rsync`) | Next.js, build on the server |
20
+ | `recipes/nextjs_static` | Uses default SCP; `rsync` optional | Static Next.js export, build locally |
21
+ | `recipes/nuxt` | No (pair with `git` or `rsync`) | Nuxt, build on the server |
22
+ | `recipes/nuxt_static` | Uses default SCP; `rsync` optional | Static Nuxt site, generate locally |
23
+ | `recipes/directus` | No (pair with `git` or `rsync`) | Directus, migrations and schema snapshots |
24
+ | `recipes/pm2` | No | Process management (add to any stack) |
25
+ | `recipes/redis` | No | Redis cache flush (add to any stack) |
26
+ | `recipes/tanstack` | No (pair with `git` or `rsync`) | TanStack Start, build on the server |
27
+
28
+ ---
29
+
30
+ ## `recipes/git`
31
+
32
+ ```typescript
33
+ import '@catapultjs/deploy/recipes/git'
34
+ ```
35
+
36
+ Requires `branch` on each host. `repository` is auto-detected from `git remote get-url origin`.
37
+
38
+ | Task | Inserted | Description |
39
+ | --- | --- | --- |
40
+ | `git:check` | after `deploy:lock` | Verifies the branch exists on the remote |
41
+ | `git:update` | before `deploy:update_code` | Clones a bare mirror into `.catapult/repo`, or fetches it |
42
+ | `deploy:update_code` | — | Clones or resets the branch from the local mirror into the release |
43
+
44
+ No store keys.
45
+
46
+ ---
47
+
48
+ ## `recipes/rsync`
49
+
50
+ ```typescript
51
+ import '@catapultjs/deploy/recipes/rsync'
52
+ ```
53
+
54
+ Always uses `--delete`. Trailing slash on the source is added automatically.
55
+
56
+ | Task | Inserted | Description |
57
+ | --- | --- | --- |
58
+ | `deploy:update_code` | — | Syncs a local directory into `releases/<release>/` via rsync |
59
+
60
+ | Key | Type | Default | Description |
61
+ | --- | --- | --- | --- |
62
+ | `rsync_source_path` | `string` | `./` | Local source directory |
63
+ | `source_path` | `string` | — | Fallback if `rsync_source_path` is not set |
64
+ | `rsync_excludes` | `string[]` | `[]` | Patterns passed to `--exclude` |
65
+
66
+ ```typescript
67
+ set('rsync_source_path', './dist')
68
+ set('rsync_excludes', ['.env'])
69
+ import '@catapultjs/deploy/recipes/rsync'
70
+ ```
71
+
72
+ ---
73
+
74
+ ## `recipes/astro`
75
+
76
+ ```typescript
77
+ import '@catapultjs/deploy/recipes/astro'
78
+ ```
79
+
80
+ Remote build. Does not override `deploy:update_code` — pair with `git` or `rsync`.
81
+
82
+ | Task | Inserted | Description |
83
+ | --- | --- | --- |
84
+ | `deploy:install` | after `deploy:update_code` | Installs dependencies in the release |
85
+ | `deploy:build` | after `deploy:shared` | Runs `astro build` on the server |
86
+
87
+ | Key | Type | Default | Description |
88
+ | --- | --- | --- | --- |
89
+ | `astro_path` | `string` | `''` | Sub-path to the Astro app (monorepo) |
90
+ | `source_path` | `string` | `''` | Used as default for `astro_path` |
91
+
92
+ ```typescript
93
+ set('astro_path', 'apps/web')
94
+ import '@catapultjs/deploy/recipes/astro'
95
+ ```
96
+
97
+ Enable standalone server output in `astro.config.mjs`:
98
+
99
+ ```typescript
100
+ import { defineConfig } from 'astro/config'
101
+ import node from '@astrojs/node'
102
+
103
+ export default defineConfig({
104
+ output: 'server',
105
+ adapter: node({
106
+ mode: 'standalone',
107
+ }),
108
+ })
109
+ ```
110
+
111
+ ---
112
+
113
+ ## `recipes/astro_static`
114
+
115
+ ```typescript
116
+ import '@catapultjs/deploy/recipes/astro_static'
117
+ ```
118
+
119
+ Local build for static Astro sites. Sets `source_path` to `./dist/.` and runs `astro build --mode <astro_mode>` before the remote lock step.
120
+
121
+ Uses the built-in `deploy:update_code` task by default, which transfers `source_path` via SCP. Import `rsync` only if rsync-based transfers are preferred. Do not combine with `git`.
122
+
123
+ | Task | Inserted | Description |
124
+ | --- | --- | --- |
125
+ | `deploy:build` | before `deploy:lock` | Runs `astro build --mode <astro_mode>` locally |
126
+
127
+ | Key | Type | Default | Description |
128
+ | --- | --- | --- | --- |
129
+ | `astro_mode` | `string \| Record<string, string>` | `'production'` | Build mode. String = same for all hosts; object = per host name |
130
+ | `source_path` | `string` | `'./dist/.'` | Local static output directory to transfer |
131
+
132
+ ```typescript
133
+ // Per-host modes
134
+ set('astro_mode', { production: 'production', staging: 'staging' })
135
+ import '@catapultjs/deploy/recipes/astro_static'
136
+ ```
137
+
138
+ Optional rsync transfer:
139
+
140
+ ```typescript
141
+ import '@catapultjs/deploy/recipes/astro_static'
142
+ import '@catapultjs/deploy/recipes/rsync'
143
+ ```
144
+
145
+ ---
146
+
147
+ ## `recipes/vitepress`
148
+
149
+ ```typescript
150
+ import '@catapultjs/deploy/recipes/vitepress'
151
+ ```
152
+
153
+ | Task | Inserted | Description |
154
+ | --- | --- | --- |
155
+ | `deploy:build` | before `deploy:lock` | Runs `vitepress build <vitepress_path>` locally |
156
+ | `deploy:update_code` | — | Uploads `<vitepress_path>.vitepress/dist` to `releases/<release>` via SCP |
157
+
158
+ | Key | Type | Default | Description |
159
+ | --- | --- | --- | --- |
160
+ | `vitepress_path` | `string` | `''` | Path passed to `vitepress build`; output read from `<path>.vitepress/dist` |
161
+ | `source_path` | `string` | `''` | Used as default for `vitepress_path` |
162
+
163
+ ```typescript
164
+ set('vitepress_path', 'docs/')
165
+ import '@catapultjs/deploy/recipes/vitepress'
166
+ ```
167
+
168
+ ---
169
+
170
+ ## `recipes/adonisjs`
171
+
172
+ ```typescript
173
+ import '@catapultjs/deploy/recipes/adonisjs'
174
+ ```
175
+
176
+ Remote build. Does not override `deploy:update_code` — pair with `git` or `rsync`.
177
+
178
+ | Task | Inserted | Description |
179
+ | --- | --- | --- |
180
+ | `deploy:install` | after `deploy:update_code` | Installs dependencies in the release |
181
+ | `deploy:build` | after `deploy:shared` | Runs `node ace build`, copies `package.json` + lockfile into `build/`, creates `build/tmp` |
182
+ | `ace:migration:run` | before `deploy:publish` | Runs `node ace migration:run --force` |
183
+ | `ace:migration:rollback` | manual | Runs `node ace migration:rollback` |
184
+ | `ace:migration:status` | manual | Runs `node ace migration:status` |
185
+ | `ace:list:routes` | manual | Runs `node ace list:routes` |
186
+
187
+ | Key | Type | Default | Description |
188
+ | --- | --- | --- | --- |
189
+ | `writable_dirs` | `string[]` | `['storage', 'logs', 'tmp']` | Created in `shared/` at setup |
190
+ | `shared_dirs` | `string[]` | `['storage', 'logs']` | Symlinked into each release |
191
+ | `shared_files` | `string[]` | `['.env']` | Symlinked into each release |
192
+ | `adonisjs_path` | `string` | `''` | Sub-path to the app within the repo (monorepo) |
193
+
194
+ ```typescript
195
+ set('adonisjs_path', 'apps/api')
196
+ set('shared_files', ['.env', '.env.production'])
197
+ import '@catapultjs/deploy/recipes/adonisjs'
198
+ ```
199
+
200
+ ---
201
+
202
+ ## `recipes/adonisjs_local`
203
+
204
+ ```typescript
205
+ import '@catapultjs/deploy/recipes/adonisjs_local'
206
+ ```
207
+
208
+ Local build + artifact upload. Same `ace:*` tasks as `adonisjs`. Copies `package.json`, lockfile, and optionally `pnpm-workspace.yaml`, `.npmrc`, `ecosystem.config.cjs` into the local `build/` before uploading.
209
+
210
+ | Task | Inserted | Description |
211
+ | --- | --- | --- |
212
+ | `deploy:build` | before `deploy:lock` | Runs `node ace build` locally |
213
+ | `deploy:update_code` | — | Uploads local build output to `releases/<release>` via SCP |
214
+ | `deploy:install` | after `deploy:shared` | Installs prod dependencies in the release |
215
+ | `ace:migration:run` | before `deploy:publish` | Runs `node ace migration:run --force` |
216
+ | `ace:migration:rollback` | manual | Runs `node ace migration:rollback` |
217
+ | `ace:migration:status` | manual | Runs `node ace migration:status` |
218
+ | `ace:list:routes` | manual | Runs `node ace list:routes` |
219
+
220
+ | Key | Type | Default | Description |
221
+ | --- | --- | --- | --- |
222
+ | `writable_dirs` | `string[]` | `['storage', 'logs', 'tmp']` | Created in `shared/` at setup |
223
+ | `shared_dirs` | `string[]` | `['storage', 'logs']` | Symlinked into each release |
224
+ | `shared_files` | `string[]` | `['.env']` | Symlinked into each release |
225
+ | `adonisjs_path` | `string` | `''` | Sub-path to the app (monorepo) |
226
+ | `source_path` | `string` | `<adonisjs_path>/build/.` | Local build directory to upload |
227
+
228
+ ---
229
+
230
+ ## `recipes/nestjs`
231
+
232
+ ```typescript
233
+ import '@catapultjs/deploy/recipes/nestjs'
234
+ ```
235
+
236
+ Remote build for NestJS applications. Does not override `deploy:update_code` — pair with `git` or `rsync`.
237
+
238
+ Uses the default Node.js install/build tasks: install dependencies in `{{release_path}}`, then run the package manager build script.
239
+
240
+ | Task | Inserted | Description |
241
+ | --- | --- | --- |
242
+ | `deploy:install` | after `deploy:update_code` | Installs dependencies in the release |
243
+ | `deploy:build` | after `deploy:install` | Runs the default `deploy:build` task (`<pm> run build`) |
244
+
245
+ | Key | Type | Default | Description |
246
+ | --- | --- | --- | --- |
247
+ | `shared_files` | `string[]` | `['.env']` | Symlinked into each release |
248
+
249
+ ```typescript
250
+ import '@catapultjs/deploy/recipes/git'
251
+ import '@catapultjs/deploy/recipes/nestjs'
252
+ import '@catapultjs/deploy/recipes/pm2'
253
+ ```
254
+
255
+ PM2 entry:
256
+
257
+ ```javascript
258
+ {
259
+ name: 'nest',
260
+ cwd: path.join(deployPath, 'current'),
261
+ script: 'node',
262
+ args: 'dist/main.js',
263
+ }
264
+ ```
265
+
266
+ ---
267
+
268
+ ## `recipes/tanstack`
269
+
270
+ ```typescript
271
+ import '@catapultjs/deploy/recipes/tanstack'
272
+ ```
273
+
274
+ Remote build for TanStack Start applications. Does not override `deploy:update_code` — pair with `git` or `rsync`.
275
+
276
+ Uses the default Node.js install/build tasks: install dependencies in `{{release_path}}`, then run the package manager build script. `.env` is shared by default.
277
+
278
+ For Vite-based TanStack Start deployments on Node.js, use Nitro with the `node-server` preset and start the generated `.output/server/index.mjs` file.
279
+
280
+ | Task | Inserted | Description |
281
+ | --- | --- | --- |
282
+ | `deploy:install` | after `deploy:update_code` | Installs dependencies in the release |
283
+ | `deploy:build` | after `deploy:install` | Runs the default `deploy:build` task (`<pm> run build`) |
284
+
285
+ | Key | Type | Default | Description |
286
+ | --- | --- | --- | --- |
287
+ | `shared_files` | `string[]` | `['.env']` | Symlinked into each release |
288
+
289
+ ```typescript
290
+ // vite.config.ts
291
+ import { defineConfig } from 'vite'
292
+ import { tanstackStart } from '@tanstack/react-start/plugin/vite'
293
+ import { nitro } from 'nitro/vite'
294
+ import viteReact from '@vitejs/plugin-react'
295
+
296
+ export default defineConfig({
297
+ plugins: [tanstackStart(), nitro({ preset: 'node-server' }), viteReact()],
298
+ })
299
+ ```
300
+
301
+ ```json
302
+ {
303
+ "scripts": {
304
+ "build": "vite build",
305
+ "start": "node .output/server/index.mjs"
306
+ }
307
+ }
308
+ ```
309
+
310
+ PM2 environment should pass host/port explicitly:
311
+
312
+ ```javascript
313
+ env: {
314
+ NODE_ENV: 'production',
315
+ HOST: '0.0.0.0',
316
+ HOSTNAME: '0.0.0.0',
317
+ NITRO_HOST: '0.0.0.0',
318
+ PORT: 3000,
319
+ NITRO_PORT: 3000,
320
+ }
321
+ ```
322
+
323
+ Upstream hosting docs: https://tanstack.com/start/latest/docs/framework/react/guide/hosting#nodejs--docker
324
+
325
+ ---
326
+
327
+ ## `recipes/nuxt`
328
+
329
+ ```typescript
330
+ import '@catapultjs/deploy/recipes/nuxt'
331
+ ```
332
+
333
+ Remote build. Does not override `deploy:update_code` — pair with `git` or `rsync`.
334
+
335
+ | Task | Inserted | Description |
336
+ | --- | --- | --- |
337
+ | `deploy:build` | — | Overrides the built-in build task, runs `nuxt build` |
338
+ | `nuxt:generate` | — | Runs `nuxt generate` (manual) |
339
+
340
+ | Key | Type | Default | Description |
341
+ | --- | --- | --- | --- |
342
+ | `shared_files` | `string[]` | `['.env']` | Symlinked into each release |
343
+ | `nuxt_path` | `string` | `''` | Sub-path to the Nuxt app (monorepo) |
344
+ | `source_path` | `string` | `''` | Used as default for `nuxt_path` |
345
+
346
+ ```typescript
347
+ set('nuxt_path', 'apps/web')
348
+ import '@catapultjs/deploy/recipes/nuxt'
349
+ ```
350
+
351
+ PM2 entry:
352
+
353
+ ```javascript
354
+ {
355
+ name: 'nuxt',
356
+ cwd: path.join(deployPath, 'current'),
357
+ script: '.output/server/index.mjs',
358
+ }
359
+ ```
360
+
361
+ For static Nuxt sites generated locally, use `recipes/nuxt_static`.
362
+
363
+ ---
364
+
365
+ ## `recipes/nuxt_static`
366
+
367
+ ```typescript
368
+ import '@catapultjs/deploy/recipes/nuxt_static'
369
+ ```
370
+
371
+ Local generation for static Nuxt sites. Sets `source_path` to `./.output/public/.` and runs `nuxt generate` before the remote lock step.
372
+
373
+ Uses the built-in `deploy:update_code` task by default, which transfers `source_path` via SCP. Import `rsync` only if rsync-based transfers are preferred. Do not combine with `git`.
374
+
375
+ | Task | Inserted | Description |
376
+ | --- | --- | --- |
377
+ | `deploy:build` | before `deploy:lock` | Runs `nuxt generate` locally |
378
+
379
+ | Key | Type | Default | Description |
380
+ | --- | --- | --- | --- |
381
+ | `source_path` | `string` | `'./.output/public/.'` | Local generated output directory to transfer |
382
+
383
+ ```typescript
384
+ import '@catapultjs/deploy/recipes/nuxt_static'
385
+ ```
386
+
387
+ Optional rsync transfer:
388
+
389
+ ```typescript
390
+ import '@catapultjs/deploy/recipes/nuxt_static'
391
+ import '@catapultjs/deploy/recipes/rsync'
392
+ ```
393
+
394
+ ---
395
+
396
+ ## `recipes/nextjs`
397
+
398
+ ```typescript
399
+ import '@catapultjs/deploy/recipes/nextjs'
400
+ ```
401
+
402
+ Remote build. Does not override `deploy:update_code` — pair with `git` or `rsync`.
403
+
404
+ After `next build`, the recipe symlinks `public` and `.next/static` into `.next/standalone/` when the standalone output directory exists.
405
+
406
+ | Task | Inserted | Description |
407
+ | --- | --- | --- |
408
+ | `deploy:build` | after `deploy:shared` | Runs `next build` and prepares standalone output symlinks |
409
+
410
+ | Key | Type | Default | Description |
411
+ | --- | --- | --- | --- |
412
+ | `shared_files` | `string[]` | `['.env']` | Symlinked into each release |
413
+ | `nextjs_path` | `string` | `''` | Sub-path to the Next.js app (monorepo) |
414
+ | `nextjs_out_path` | `string` | `'.next/standalone/'` | Standalone output path receiving `public` and `.next/static` symlinks |
415
+ | `source_path` | `string` | `''` | Used as default for `nextjs_path` |
416
+
417
+ ```typescript
418
+ set('nextjs_path', 'apps/web')
419
+ import '@catapultjs/deploy/recipes/nextjs'
420
+ ```
421
+
422
+ Enable standalone output in `next.config.*`:
423
+
424
+ ```typescript
425
+ export default {
426
+ output: 'standalone',
427
+ }
428
+ ```
429
+
430
+ Next.js creates `.next/standalone/server.js` for standalone deployments. It does not copy `public` or `.next/static` into the standalone directory by default; this recipe links them into the standalone output after the build.
431
+
432
+ PM2 entry:
433
+
434
+ ```javascript
435
+ {
436
+ name: 'next',
437
+ cwd: path.join(deployPath, 'current'),
438
+ script: '.next/standalone/server.js',
439
+ }
440
+ ```
441
+
442
+ Upstream output docs: https://nextjs.org/docs/pages/api-reference/config/next-config-js/output
443
+
444
+ ---
445
+
446
+ ## `recipes/nextjs_static`
447
+
448
+ ```typescript
449
+ import '@catapultjs/deploy/recipes/nextjs_static'
450
+ ```
451
+
452
+ Local build for static Next.js export. Sets `source_path` to `./out/.` and runs `next build` before the remote lock step.
453
+
454
+ Uses the built-in `deploy:update_code` task by default, which transfers `source_path` via SCP. Import `rsync` only if rsync-based transfers are preferred.
455
+
456
+ | Task | Inserted | Description |
457
+ | --- | --- | --- |
458
+ | `deploy:build` | before `deploy:lock` | Runs `next build` locally |
459
+
460
+ | Key | Type | Default | Description |
461
+ | --- | --- | --- | --- |
462
+ | `source_path` | `string` | `'./out/.'` | Local static export directory to transfer |
463
+
464
+ ```typescript
465
+ import '@catapultjs/deploy/recipes/nextjs_static'
466
+ ```
467
+
468
+ Optional rsync transfer:
469
+
470
+ ```typescript
471
+ import '@catapultjs/deploy/recipes/nextjs_static'
472
+ import '@catapultjs/deploy/recipes/rsync'
473
+ ```
474
+
475
+ Enable static export in `next.config.*`:
476
+
477
+ ```typescript
478
+ export default {
479
+ output: 'export',
480
+ }
481
+ ```
482
+
483
+ ---
484
+
485
+ ## `recipes/directus`
486
+
487
+ ```typescript
488
+ import '@catapultjs/deploy/recipes/directus'
489
+ ```
490
+
491
+ DB migrations and schema snapshots. Does not override `deploy:update_code` — pair with `git` or `rsync`. All tasks are manual (not inserted automatically).
492
+
493
+ | Task | Inserted | Description |
494
+ | --- | --- | --- |
495
+ | `directus:database:migrate` | manual | Runs `directus database migrate:latest` |
496
+ | `directus:snapshot:create` | manual | Runs `directus schema snapshot <directus_snapshot_path>` |
497
+ | `directus:snapshot:apply` | manual | Runs `directus schema apply -y <directus_snapshot_path>` |
498
+
499
+ | Key | Type | Default | Description |
500
+ | --- | --- | --- | --- |
501
+ | `writable_dirs` | `string[]` | `['uploads']` | Created in `shared/` at setup |
502
+ | `shared_dirs` | `string[]` | `['uploads']` | Symlinked into each release |
503
+ | `shared_files` | `string[]` | `['.env']` | Symlinked into each release |
504
+ | `directus_path` | `string` | `''` | Sub-path to the Directus app (monorepo) |
505
+ | `directus_snapshot_path` | `string` | `'./snapshot.yaml'` | Snapshot file path used by schema tasks |
506
+
507
+ ```typescript
508
+ set('directus_path', 'apps/cms')
509
+ set('directus_snapshot_path', './database/snapshot.yaml')
510
+ import '@catapultjs/deploy/recipes/directus'
511
+ ```
512
+
513
+ ---
514
+
515
+ ## `recipes/pm2`
516
+
517
+ ```typescript
518
+ import '@catapultjs/deploy/recipes/pm2'
519
+ ```
520
+
521
+ Requires an `ecosystem.config.cjs` at the release root. Use absolute paths inside that file resolving through `current/` to avoid stale release references after a new deploy.
522
+
523
+ | Task | Inserted | Description |
524
+ | --- | --- | --- |
525
+ | `pm2:startOrReload` | after `deploy:publish` | Starts or reloads via `startOrReload --update-env` |
526
+ | `pm2:save` | after `pm2:startOrReload` | Persists the PM2 process list |
527
+ | `pm2:start` | manual | Starts PM2 processes |
528
+ | `pm2:reload` | manual | Zero-downtime reload |
529
+ | `pm2:restart` | manual | Hard restart |
530
+ | `pm2:stop` | manual | Stops all processes |
531
+ | `pm2:delete` | manual | Deletes all processes from PM2 |
532
+ | `pm2:logs` | manual | Displays the last 50 lines of logs |
533
+ | `pm2:list` | manual | Lists PM2 processes |
534
+ | `pm2:show` | manual | Shows detailed info for each app in `ecosystem.config.cjs` |
535
+
536
+ No store keys. `onStatus` displays the PM2 version in `cata status`.
537
+
538
+ ```bash
539
+ npx cata task pm2:reload
540
+ npx cata task pm2:logs --host staging
541
+ ```
542
+
543
+ ---
544
+
545
+ ## `recipes/redis`
546
+
547
+ ```typescript
548
+ import '@catapultjs/deploy/recipes/redis'
549
+ ```
550
+
551
+ All tasks are manual (not inserted automatically).
552
+
553
+ | Task | Inserted | Description |
554
+ | --- | --- | --- |
555
+ | `redis:db:flush` | manual | Flushes the configured Redis DB(s) |
556
+ | `redis:db:flush_all` | manual | Runs `redis-cli FLUSHALL` |
557
+
558
+ | Key | Type | Default | Description |
559
+ | --- | --- | --- | --- |
560
+ | `redis_db` | `number \| number[]` | `1` | DB index(es) flushed by `redis:db:flush` |
561
+
562
+ ```typescript
563
+ set('redis_db', [0, 1, 2])
564
+ import '@catapultjs/deploy/recipes/redis'
565
+
566
+ // Insert before publish:
567
+ before('deploy:publish', 'redis:db:flush')
568
+ ```
569
+
570
+ ---
571
+
572
+ ## Monorepo pattern
573
+
574
+ Keep the transfer recipe (`git` or `rsync`) and override `deploy:install`/`deploy:build` paths via `set()`:
575
+
576
+ ```typescript
577
+ import { defineConfig, set, before } from '@catapultjs/deploy'
578
+ import '@catapultjs/deploy/recipes/git'
579
+ import '@catapultjs/deploy/recipes/nuxt'
580
+ import '@catapultjs/deploy/recipes/directus'
581
+ import '@catapultjs/deploy/recipes/pm2'
582
+ import '@catapultjs/deploy/recipes/redis'
583
+
584
+ set('nuxt_path', 'apps/web')
585
+ set('directus_path', 'apps/cms')
586
+ set('directus_snapshot_path', './database/snapshot.yaml')
587
+ set('redis_db', 2)
588
+
589
+ before('deploy:publish', 'redis:db:flush')
590
+
591
+ export default defineConfig({
592
+ hosts: [{ name: 'production', ssh: 'deploy@example.com', deployPath: '/home/deploy/acme', branch: 'main' }],
593
+ })
594
+ ```
595
+
596
+ `deploy:install` (inserted by `nuxt`/`directus`) runs at the workspace root `{{release_path}}` by default — no override needed for standard monorepos.