@actuate-media/cli 0.11.3 β†’ 0.12.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @actuate-media/cli@0.11.3 build /home/runner/work/actuatecms/actuatecms/packages/cli
2
+ > @actuate-media/cli@0.12.0 build /home/runner/work/actuatecms/actuatecms/packages/cli
3
3
  > tsc
4
4
 
@@ -1,16 +1,16 @@
1
1
 
2
- > @actuate-media/cli@0.11.3 test /home/runner/work/actuatecms/actuatecms/packages/cli
2
+ > @actuate-media/cli@0.12.0 test /home/runner/work/actuatecms/actuatecms/packages/cli
3
3
  > vitest run
4
4
 
5
5
 
6
6
   RUN  v4.1.8 /home/runner/work/actuatecms/actuatecms/packages/cli
7
7
 
8
- βœ“ dist/__tests__/db-sync.test.js (10 tests) 442ms
9
- βœ“ dist/__tests__/seed.test.js (10 tests) 78ms
10
- βœ“ src/__tests__/db-sync.test.ts (10 tests) 381ms
11
- βœ“ dist/__tests__/deployment-diagnostics.test.js (9 tests) 75ms
12
- βœ“ src/__tests__/seed.test.ts (10 tests) 144ms
13
- βœ“ src/__tests__/deployment-diagnostics.test.ts (9 tests) 61ms
8
+ βœ“ dist/__tests__/db-sync.test.js (10 tests) 233ms
9
+ βœ“ dist/__tests__/seed.test.js (10 tests) 128ms
10
+ βœ“ src/__tests__/db-sync.test.ts (10 tests) 219ms
11
+ βœ“ dist/__tests__/deployment-diagnostics.test.js (9 tests) 35ms
12
+ βœ“ src/__tests__/seed.test.ts (10 tests) 164ms
13
+ βœ“ src/__tests__/deployment-diagnostics.test.ts (9 tests) 49ms
14
14
  - Reading canonical Actuate schema...
15
15
  βœ” Actuate CMS models added to schema.
16
16
  - Running prisma generate...
@@ -18,43 +18,43 @@
18
18
  βœ” Prisma client generated.
19
19
  β„Ή Run `npx prisma migrate dev --name actuate-cms` to create the migration.
20
20
 
21
+ stdout | dist/__tests__/db-init.test.js > db:init (WS-D D5 β€” canonical schema, no stale fragment) > command > fails clearly when cms-core cannot be located
21
22
  - Reading canonical Actuate schema...
22
23
  βœ– Could not locate @actuate-media/cms-core.
23
- stdout | dist/__tests__/db-init.test.js > db:init (WS-D D5 β€” canonical schema, no stale fragment) > command > fails clearly when cms-core cannot be located
24
24
  β„Ή Install it first: `npm install @actuate-media/cms-core`.
25
25
 
26
26
  - Reading canonical Actuate schema...
27
27
  βœ” Actuate CMS models added to schema.
28
- - Running prisma generate...
29
28
  stdout | dist/__tests__/db-init.test.js > db:init (WS-D D5 β€” canonical schema, no stale fragment) > command > is idempotent without --force
30
29
  βœ” Prisma client generated.
30
+ - Running prisma generate...
31
31
  β„Ή Run `npx prisma migrate dev --name actuate-cms` to create the migration.
32
32
 
33
33
  - Reading canonical Actuate schema...
34
34
  β„Ή Actuate CMS models already present in schema. Use --force to overwrite.
35
- βœ“ dist/__tests__/db-init.test.js (4 tests) 170ms
35
+ βœ“ dist/__tests__/db-init.test.js (4 tests) 228ms
36
36
  - Reading canonical Actuate schema...
37
- βœ” Actuate CMS models added to schema.
38
- - Running prisma generate...
39
37
  stdout | src/__tests__/db-init.test.ts > db:init (WS-D D5 β€” canonical schema, no stale fragment) > command > injects canonical models with @@map and no duplicate datasource/generator
40
38
  βœ” Prisma client generated.
41
39
  β„Ή Run `npx prisma migrate dev --name actuate-cms` to create the migration.
42
40
 
41
+ βœ” Actuate CMS models added to schema.
42
+ - Running prisma generate...
43
43
  - Reading canonical Actuate schema...
44
- βœ– Could not locate @actuate-media/cms-core.
45
44
  stdout | src/__tests__/db-init.test.ts > db:init (WS-D D5 β€” canonical schema, no stale fragment) > command > fails clearly when cms-core cannot be located
45
+ βœ– Could not locate @actuate-media/cms-core.
46
46
  β„Ή Install it first: `npm install @actuate-media/cms-core`.
47
47
 
48
48
  - Reading canonical Actuate schema...
49
- βœ” Actuate CMS models added to schema.
50
- - Running prisma generate...
51
49
  stdout | src/__tests__/db-init.test.ts > db:init (WS-D D5 β€” canonical schema, no stale fragment) > command > is idempotent without --force
52
50
  βœ” Prisma client generated.
51
+ βœ” Actuate CMS models added to schema.
53
52
  β„Ή Run `npx prisma migrate dev --name actuate-cms` to create the migration.
53
+ - Running prisma generate...
54
54
 
55
55
  - Reading canonical Actuate schema...
56
56
  β„Ή Actuate CMS models already present in schema. Use --force to overwrite.
57
- βœ“ src/__tests__/db-init.test.ts (4 tests) 194ms
57
+ βœ“ src/__tests__/db-init.test.ts (4 tests) 246ms
58
58
  stdout | dist/__tests__/mcp-init.test.js > mcp:init > creates both editor configs with placeholder key and git-ignores them
59
59
  βœ” Created .cursor/mcp.json
60
60
 
@@ -183,7 +183,7 @@ Next steps
183
183
  3. Restart Cursor / VS Code so the MCP server is picked up
184
184
  Tip: pass --url https://your-site.com to target a deployed CMS instead.
185
185
 
186
- βœ“ dist/__tests__/mcp-init.test.js (6 tests) 255ms
186
+ βœ“ dist/__tests__/mcp-init.test.js (6 tests) 249ms
187
187
  stdout | src/__tests__/mcp-init.test.ts > mcp:init > creates both editor configs with placeholder key and git-ignores them
188
188
  βœ” Created .cursor/mcp.json
189
189
 
@@ -312,13 +312,13 @@ Next steps
312
312
  3. Restart Cursor / VS Code so the MCP server is picked up
313
313
  Tip: pass --url https://your-site.com to target a deployed CMS instead.
314
314
 
315
- βœ“ src/__tests__/mcp-init.test.ts (6 tests) 279ms
316
- βœ“ dist/__tests__/form-seed.test.js (10 tests) 47ms
317
- βœ“ src/__tests__/form-seed.test.ts (10 tests) 77ms
318
- βœ“ dist/__tests__/vercel-env-matrix.test.js (6 tests) 43ms
319
- βœ“ src/__tests__/vercel-env-matrix.test.ts (6 tests) 51ms
320
- βœ“ dist/__tests__/load-dotenv.test.js (3 tests) 54ms
321
- βœ“ src/__tests__/load-dotenv.test.ts (3 tests) 69ms
315
+ βœ“ src/__tests__/mcp-init.test.ts (6 tests) 134ms
316
+ βœ“ dist/__tests__/form-seed.test.js (10 tests) 31ms
317
+ βœ“ src/__tests__/form-seed.test.ts (10 tests) 34ms
318
+ βœ“ dist/__tests__/vercel-env-matrix.test.js (6 tests) 28ms
319
+ βœ“ src/__tests__/vercel-env-matrix.test.ts (6 tests) 30ms
320
+ βœ“ dist/__tests__/load-dotenv.test.js (3 tests) 37ms
321
+ βœ“ src/__tests__/load-dotenv.test.ts (3 tests) 44ms
322
322
  - Reading canonical Actuate schema...
323
323
  βœ” Actuate CMS models added to schema.
324
324
  - Running prisma generate...
@@ -326,20 +326,20 @@ Next steps
326
326
  βœ” Prisma client generated.
327
327
  β„Ή Run `npx prisma migrate dev --name actuate-cms` to create the migration.
328
328
 
329
- βœ“ dist/__tests__/schema-fragment.test.js (1 test) 120ms
329
+ βœ“ dist/__tests__/schema-fragment.test.js (1 test) 80ms
330
330
  - Reading canonical Actuate schema...
331
331
  βœ” Actuate CMS models added to schema.
332
- - Running prisma generate...
333
332
  stdout | src/__tests__/schema-fragment.test.ts > db:init schema fragment > injects all deploy-critical Actuate models
334
333
  βœ” Prisma client generated.
334
+ - Running prisma generate...
335
335
  β„Ή Run `npx prisma migrate dev --name actuate-cms` to create the migration.
336
336
 
337
- βœ“ src/__tests__/schema-fragment.test.ts (1 test) 80ms
338
- βœ“ dist/__tests__/init.test.js (2 tests) 41ms
339
- βœ“ src/__tests__/init.test.ts (2 tests) 38ms
337
+ βœ“ src/__tests__/schema-fragment.test.ts (1 test) 66ms
338
+ βœ“ dist/__tests__/init.test.js (2 tests) 16ms
339
+ βœ“ src/__tests__/init.test.ts (2 tests) 15ms
340
340
 
341
341
   Test Files  20 passed (20)
342
342
   Tests  122 passed (122)
343
-  Start at  16:26:19
344
-  Duration  29.01s (transform 2.47s, setup 0ms, import 7.01s, tests 2.70s, environment 21ms)
343
+  Start at  05:27:27
344
+  Duration  21.87s (transform 2.20s, setup 0ms, import 5.83s, tests 2.07s, environment 21ms)
345
345
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @actuate-media/cli
2
2
 
3
+ ## 0.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - bc51a1d: Align SEO audit with live page meta output, expand audit checks, wire redirect/link signals, and add `actuate migrate:meta` for bulk meta backfill.
8
+
3
9
  ## 0.11.3
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerMigrateMetaCommand(program: Command): void;
3
+ //# sourceMappingURL=migrate-meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-meta.d.ts","sourceRoot":"","sources":["../../src/commands/migrate-meta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAgGnC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAUjE"}
@@ -0,0 +1,81 @@
1
+ import { resolve } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
+ import ora from 'ora';
4
+ import { connectProjectDatabase } from '../utils/database.js';
5
+ import { loadProjectEnv } from '../utils/load-dotenv.js';
6
+ import { logger } from '../utils/logger.js';
7
+ async function loadProjectConfig(configPath) {
8
+ try {
9
+ const { setActuateConfig } = await import('@actuate-media/cms-core');
10
+ const { tsImport } = await import('tsx/esm/api');
11
+ const abs = pathToFileURL(resolve(configPath)).href;
12
+ const mod = (await tsImport(abs, import.meta.url));
13
+ const config = mod.default ?? mod.config;
14
+ if (config && typeof config === 'object') {
15
+ setActuateConfig(config);
16
+ }
17
+ }
18
+ catch {
19
+ logger.warn(`Could not load ${configPath} β€” meta defaults will use collection slug heuristics only.`);
20
+ }
21
+ }
22
+ /** `actuate migrate:meta` β€” backfill metaTitle/metaDescription on content documents. */
23
+ async function runMigrateMeta(options) {
24
+ const dryRun = options.dryRun ?? false;
25
+ const batchSize = options.batchSize ? Number.parseInt(options.batchSize, 10) : undefined;
26
+ if (batchSize !== undefined && (!Number.isFinite(batchSize) || batchSize <= 0)) {
27
+ logger.error('--batch-size must be a positive integer.');
28
+ process.exit(1);
29
+ }
30
+ await loadProjectEnv(process.cwd()).then((env) => {
31
+ for (const [key, value] of Object.entries(env)) {
32
+ if (value !== undefined && process.env[key] === undefined) {
33
+ process.env[key] = value;
34
+ }
35
+ }
36
+ });
37
+ await loadProjectConfig(options.config ?? 'actuate.config.ts');
38
+ let connection = null;
39
+ const spinner = ora(dryRun ? 'Scanning content documents (dry run)…' : 'Backfilling meta title/description…').start();
40
+ try {
41
+ connection = await connectProjectDatabase();
42
+ const db = connection.db;
43
+ const { migrateMetaFields } = await import('@actuate-media/cms-core');
44
+ const admin = await db.user.findFirst({ where: { role: 'ADMIN' } });
45
+ if (!admin) {
46
+ spinner.fail('No ADMIN user found. Create an admin (setup wizard or seed) first.');
47
+ process.exit(1);
48
+ }
49
+ const ctx = { userId: admin.id, role: 'ADMIN', db: connection.db, locale: 'en' };
50
+ const result = await migrateMetaFields(ctx, { dryRun, batchSize });
51
+ spinner.succeed(dryRun
52
+ ? `Dry run complete β€” ${result.migrated} document(s) would be updated.`
53
+ : `Updated ${result.migrated} document(s).`);
54
+ logger.info(` Scanned: ${result.scanned}`);
55
+ logger.info(` Migrated: ${result.migrated}`);
56
+ logger.info(` Skipped: ${result.skipped}`);
57
+ if (result.migratedIds.length > 0) {
58
+ logger.info(` IDs: ${result.migratedIds.join(', ')}`);
59
+ }
60
+ logger.info('');
61
+ logger.info('Next: re-run the SEO audit in Settings β†’ SEO β†’ Audit.');
62
+ }
63
+ catch (err) {
64
+ const message = err instanceof Error ? err.message : String(err);
65
+ spinner.fail(`Meta migration failed: ${message}`);
66
+ process.exit(1);
67
+ }
68
+ finally {
69
+ await connection?.disconnect();
70
+ }
71
+ }
72
+ export function registerMigrateMetaCommand(program) {
73
+ program
74
+ .command('migrate:meta')
75
+ .description('Backfill metaTitle/metaDescription from title templates and key takeaways. Idempotent.')
76
+ .option('--dry-run', 'Report what would change without writing')
77
+ .option('--batch-size <n>', 'Documents to scan per DB page (default 100)')
78
+ .option('--config <path>', 'Path to actuate.config.ts', 'actuate.config.ts')
79
+ .action(runMigrateMeta);
80
+ }
81
+ //# sourceMappingURL=migrate-meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-meta.js","sourceRoot":"","sources":["../../src/commands/migrate-meta.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import { registerMigrateCommand } from './commands/migrate.js';
4
4
  import { registerMigrateSectionsCommand } from './commands/migrate-sections.js';
5
5
  import { registerMigrateSchemaCommand } from './commands/migrate-schema.js';
6
+ import { registerMigrateMetaCommand } from './commands/migrate-meta.js';
6
7
  import { registerGenerateCommand } from './commands/generate.js';
7
8
  import { registerSeedCommand } from './commands/seed.js';
8
9
  import { registerImportCommand } from './commands/import.js';
@@ -24,6 +25,7 @@ program
24
25
  registerMigrateCommand(program);
25
26
  registerMigrateSectionsCommand(program);
26
27
  registerMigrateSchemaCommand(program);
28
+ registerMigrateMetaCommand(program);
27
29
  registerGenerateCommand(program);
28
30
  registerSeedCommand(program);
29
31
  registerImportCommand(program);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAA;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAA;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAA;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,6DAA6D,CAAC;KAC1E,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,sBAAsB,CAAC,OAAO,CAAC,CAAA;AAC/B,8BAA8B,CAAC,OAAO,CAAC,CAAA;AACvC,4BAA4B,CAAC,OAAO,CAAC,CAAA;AACrC,uBAAuB,CAAC,OAAO,CAAC,CAAA;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAA;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAA;AAC/B,0BAA0B,CAAC,OAAO,CAAC,CAAA;AACnC,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAA;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAA;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,0BAA0B,CAAC,OAAO,CAAC,CAAA;AACnC,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,6BAA6B,CAAC,OAAO,CAAC,CAAA;AACtC,kBAAkB,CAAC,OAAO,CAAC,CAAA;AAE3B,OAAO,CAAC,KAAK,EAAE,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,gCAAgC,CAAA;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAA;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAA;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,6DAA6D,CAAC;KAC1E,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,sBAAsB,CAAC,OAAO,CAAC,CAAA;AAC/B,8BAA8B,CAAC,OAAO,CAAC,CAAA;AACvC,4BAA4B,CAAC,OAAO,CAAC,CAAA;AACrC,0BAA0B,CAAC,OAAO,CAAC,CAAA;AACnC,uBAAuB,CAAC,OAAO,CAAC,CAAA;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAA;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAA;AAC/B,0BAA0B,CAAC,OAAO,CAAC,CAAA;AACnC,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAA;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAA;AAC5B,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,0BAA0B,CAAC,OAAO,CAAC,CAAA;AACnC,qBAAqB,CAAC,OAAO,CAAC,CAAA;AAC9B,6BAA6B,CAAC,OAAO,CAAC,CAAA;AACtC,kBAAkB,CAAC,OAAO,CAAC,CAAA;AAE3B,OAAO,CAAC,KAAK,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuate-media/cli",
3
- "version": "0.11.3",
3
+ "version": "0.12.0",
4
4
  "description": "CLI for Actuate CMS β€” migrations, codegen, imports, exports, and upgrades",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  "devDependencies": {
29
29
  "typescript": "^5.7.0",
30
30
  "vitest": "^4.1.0",
31
- "@actuate-media/cms-core": "0.77.3"
31
+ "@actuate-media/cms-core": "0.78.0"
32
32
  },
33
33
  "scripts": {
34
34
  "build": "tsc",
@@ -0,0 +1,107 @@
1
+ import { Command } from 'commander'
2
+ import { resolve } from 'node:path'
3
+ import { pathToFileURL } from 'node:url'
4
+ import ora from 'ora'
5
+ import { connectProjectDatabase } from '../utils/database.js'
6
+ import { loadProjectEnv } from '../utils/load-dotenv.js'
7
+ import { logger } from '../utils/logger.js'
8
+
9
+ interface MigrateMetaOptions {
10
+ dryRun?: boolean
11
+ batchSize?: string
12
+ config?: string
13
+ }
14
+
15
+ async function loadProjectConfig(configPath: string): Promise<void> {
16
+ try {
17
+ const { setActuateConfig } = await import('@actuate-media/cms-core')
18
+ const { tsImport } = await import('tsx/esm/api')
19
+ const abs = pathToFileURL(resolve(configPath)).href
20
+ const mod = (await tsImport(abs, import.meta.url)) as {
21
+ default?: unknown
22
+ config?: unknown
23
+ }
24
+ const config = mod.default ?? mod.config
25
+ if (config && typeof config === 'object') {
26
+ setActuateConfig(config as never)
27
+ }
28
+ } catch {
29
+ logger.warn(
30
+ `Could not load ${configPath} β€” meta defaults will use collection slug heuristics only.`,
31
+ )
32
+ }
33
+ }
34
+
35
+ /** `actuate migrate:meta` β€” backfill metaTitle/metaDescription on content documents. */
36
+ async function runMigrateMeta(options: MigrateMetaOptions): Promise<void> {
37
+ const dryRun = options.dryRun ?? false
38
+ const batchSize = options.batchSize ? Number.parseInt(options.batchSize, 10) : undefined
39
+ if (batchSize !== undefined && (!Number.isFinite(batchSize) || batchSize <= 0)) {
40
+ logger.error('--batch-size must be a positive integer.')
41
+ process.exit(1)
42
+ }
43
+
44
+ await loadProjectEnv(process.cwd()).then((env) => {
45
+ for (const [key, value] of Object.entries(env)) {
46
+ if (value !== undefined && process.env[key] === undefined) {
47
+ process.env[key] = value
48
+ }
49
+ }
50
+ })
51
+ await loadProjectConfig(options.config ?? 'actuate.config.ts')
52
+
53
+ let connection: { db: unknown; disconnect: () => Promise<void> } | null = null
54
+ const spinner = ora(
55
+ dryRun ? 'Scanning content documents (dry run)…' : 'Backfilling meta title/description…',
56
+ ).start()
57
+
58
+ try {
59
+ connection = await connectProjectDatabase()
60
+ const db = connection.db as {
61
+ user: { findFirst: (args: unknown) => Promise<{ id: string } | null> }
62
+ }
63
+
64
+ const { migrateMetaFields } = await import('@actuate-media/cms-core')
65
+
66
+ const admin = await db.user.findFirst({ where: { role: 'ADMIN' } })
67
+ if (!admin) {
68
+ spinner.fail('No ADMIN user found. Create an admin (setup wizard or seed) first.')
69
+ process.exit(1)
70
+ }
71
+
72
+ const ctx = { userId: admin.id, role: 'ADMIN', db: connection.db, locale: 'en' }
73
+ const result = await migrateMetaFields(ctx, { dryRun, batchSize })
74
+
75
+ spinner.succeed(
76
+ dryRun
77
+ ? `Dry run complete β€” ${result.migrated} document(s) would be updated.`
78
+ : `Updated ${result.migrated} document(s).`,
79
+ )
80
+ logger.info(` Scanned: ${result.scanned}`)
81
+ logger.info(` Migrated: ${result.migrated}`)
82
+ logger.info(` Skipped: ${result.skipped}`)
83
+ if (result.migratedIds.length > 0) {
84
+ logger.info(` IDs: ${result.migratedIds.join(', ')}`)
85
+ }
86
+ logger.info('')
87
+ logger.info('Next: re-run the SEO audit in Settings β†’ SEO β†’ Audit.')
88
+ } catch (err) {
89
+ const message = err instanceof Error ? err.message : String(err)
90
+ spinner.fail(`Meta migration failed: ${message}`)
91
+ process.exit(1)
92
+ } finally {
93
+ await connection?.disconnect()
94
+ }
95
+ }
96
+
97
+ export function registerMigrateMetaCommand(program: Command): void {
98
+ program
99
+ .command('migrate:meta')
100
+ .description(
101
+ 'Backfill metaTitle/metaDescription from title templates and key takeaways. Idempotent.',
102
+ )
103
+ .option('--dry-run', 'Report what would change without writing')
104
+ .option('--batch-size <n>', 'Documents to scan per DB page (default 100)')
105
+ .option('--config <path>', 'Path to actuate.config.ts', 'actuate.config.ts')
106
+ .action(runMigrateMeta)
107
+ }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import { Command } from 'commander'
3
3
  import { registerMigrateCommand } from './commands/migrate.js'
4
4
  import { registerMigrateSectionsCommand } from './commands/migrate-sections.js'
5
5
  import { registerMigrateSchemaCommand } from './commands/migrate-schema.js'
6
+ import { registerMigrateMetaCommand } from './commands/migrate-meta.js'
6
7
  import { registerGenerateCommand } from './commands/generate.js'
7
8
  import { registerSeedCommand } from './commands/seed.js'
8
9
  import { registerImportCommand } from './commands/import.js'
@@ -31,6 +32,7 @@ program
31
32
  registerMigrateCommand(program)
32
33
  registerMigrateSectionsCommand(program)
33
34
  registerMigrateSchemaCommand(program)
35
+ registerMigrateMetaCommand(program)
34
36
  registerGenerateCommand(program)
35
37
  registerSeedCommand(program)
36
38
  registerImportCommand(program)