@momentumcms/migrations 0.5.6 → 0.5.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momentumcms/migrations",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
4
4
  "description": "Database migration system for Momentum CMS",
5
5
  "license": "MIT",
6
6
  "main": "./src/index.cjs",
@@ -1621,7 +1621,9 @@ async function loadMomentumConfig(configPath) {
1621
1621
  if (!raw.db?.adapter) {
1622
1622
  throw new Error(`Config at ${configPath} is missing db.adapter`);
1623
1623
  }
1624
- if (!raw.collections || raw.collections.length === 0) {
1624
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
1625
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
1626
+ if (!hasExplicitCollections && !hasPluginCollections) {
1625
1627
  throw new Error(`Config at ${configPath} has no collections`);
1626
1628
  }
1627
1629
  return raw;
@@ -1664,6 +1666,25 @@ function parseMigrationArgs(args) {
1664
1666
  skipCloneTest: args.includes("--skip-clone-test")
1665
1667
  };
1666
1668
  }
1669
+ function mergePluginCollections(config) {
1670
+ const collections = [...config.collections];
1671
+ const plugins = config.plugins ?? [];
1672
+ const slugs = new Set(collections.map((c) => c.slug));
1673
+ for (const plugin of plugins) {
1674
+ if (plugin.collections) {
1675
+ for (const col of plugin.collections) {
1676
+ if (!slugs.has(col.slug)) {
1677
+ collections.push(col);
1678
+ slugs.add(col.slug);
1679
+ }
1680
+ }
1681
+ }
1682
+ if (plugin.modifyCollections) {
1683
+ plugin.modifyCollections(collections);
1684
+ }
1685
+ }
1686
+ return collections;
1687
+ }
1667
1688
 
1668
1689
  // libs/migrations/src/cli/generate.ts
1669
1690
  async function main() {
@@ -1677,7 +1698,8 @@ async function main() {
1677
1698
  process.exit(1);
1678
1699
  }
1679
1700
  const directory = (0, import_node_path2.resolve)(migrationConfig.directory);
1680
- const desired = collectionsToSchema(config.collections, dialect);
1701
+ const allCollections = mergePluginCollections(config);
1702
+ const desired = collectionsToSchema(allCollections, dialect);
1681
1703
  let previous = readSnapshot(directory);
1682
1704
  if (!previous) {
1683
1705
  try {
@@ -1619,7 +1619,9 @@ async function loadMomentumConfig(configPath) {
1619
1619
  if (!raw.db?.adapter) {
1620
1620
  throw new Error(`Config at ${configPath} is missing db.adapter`);
1621
1621
  }
1622
- if (!raw.collections || raw.collections.length === 0) {
1622
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
1623
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
1624
+ if (!hasExplicitCollections && !hasPluginCollections) {
1623
1625
  throw new Error(`Config at ${configPath} has no collections`);
1624
1626
  }
1625
1627
  return raw;
@@ -1662,6 +1664,25 @@ function parseMigrationArgs(args) {
1662
1664
  skipCloneTest: args.includes("--skip-clone-test")
1663
1665
  };
1664
1666
  }
1667
+ function mergePluginCollections(config) {
1668
+ const collections = [...config.collections];
1669
+ const plugins = config.plugins ?? [];
1670
+ const slugs = new Set(collections.map((c) => c.slug));
1671
+ for (const plugin of plugins) {
1672
+ if (plugin.collections) {
1673
+ for (const col of plugin.collections) {
1674
+ if (!slugs.has(col.slug)) {
1675
+ collections.push(col);
1676
+ slugs.add(col.slug);
1677
+ }
1678
+ }
1679
+ }
1680
+ if (plugin.modifyCollections) {
1681
+ plugin.modifyCollections(collections);
1682
+ }
1683
+ }
1684
+ return collections;
1685
+ }
1665
1686
 
1666
1687
  // libs/migrations/src/cli/generate.ts
1667
1688
  async function main() {
@@ -1675,7 +1696,8 @@ async function main() {
1675
1696
  process.exit(1);
1676
1697
  }
1677
1698
  const directory = resolve(migrationConfig.directory);
1678
- const desired = collectionsToSchema(config.collections, dialect);
1699
+ const allCollections = mergePluginCollections(config);
1700
+ const desired = collectionsToSchema(allCollections, dialect);
1679
1701
  let previous = readSnapshot(directory);
1680
1702
  if (!previous) {
1681
1703
  try {
@@ -540,7 +540,9 @@ async function loadMomentumConfig(configPath) {
540
540
  if (!raw.db?.adapter) {
541
541
  throw new Error(`Config at ${configPath} is missing db.adapter`);
542
542
  }
543
- if (!raw.collections || raw.collections.length === 0) {
543
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
544
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
545
+ if (!hasExplicitCollections && !hasPluginCollections) {
544
546
  throw new Error(`Config at ${configPath} has no collections`);
545
547
  }
546
548
  return raw;
@@ -555,7 +557,9 @@ function resolveDialect(adapter) {
555
557
  }
556
558
  function buildTrackerFromAdapter(adapter) {
557
559
  if (!adapter.queryRaw || !adapter.executeRaw) {
558
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
560
+ throw new Error(
561
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
562
+ );
559
563
  }
560
564
  const queryRaw = adapter.queryRaw.bind(adapter);
561
565
  const executeRaw = adapter.executeRaw.bind(adapter);
@@ -538,7 +538,9 @@ async function loadMomentumConfig(configPath) {
538
538
  if (!raw.db?.adapter) {
539
539
  throw new Error(`Config at ${configPath} is missing db.adapter`);
540
540
  }
541
- if (!raw.collections || raw.collections.length === 0) {
541
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
542
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
543
+ if (!hasExplicitCollections && !hasPluginCollections) {
542
544
  throw new Error(`Config at ${configPath} has no collections`);
543
545
  }
544
546
  return raw;
@@ -553,7 +555,9 @@ function resolveDialect(adapter) {
553
555
  }
554
556
  function buildTrackerFromAdapter(adapter) {
555
557
  if (!adapter.queryRaw || !adapter.executeRaw) {
556
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
558
+ throw new Error(
559
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
560
+ );
557
561
  }
558
562
  const queryRaw = adapter.queryRaw.bind(adapter);
559
563
  const executeRaw = adapter.executeRaw.bind(adapter);
package/src/cli/run.cjs CHANGED
@@ -950,7 +950,9 @@ async function loadMomentumConfig(configPath) {
950
950
  if (!raw.db?.adapter) {
951
951
  throw new Error(`Config at ${configPath} is missing db.adapter`);
952
952
  }
953
- if (!raw.collections || raw.collections.length === 0) {
953
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
954
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
955
+ if (!hasExplicitCollections && !hasPluginCollections) {
954
956
  throw new Error(`Config at ${configPath} has no collections`);
955
957
  }
956
958
  return raw;
@@ -965,7 +967,9 @@ function resolveDialect(adapter) {
965
967
  }
966
968
  function buildTrackerFromAdapter(adapter) {
967
969
  if (!adapter.queryRaw || !adapter.executeRaw) {
968
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
970
+ throw new Error(
971
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
972
+ );
969
973
  }
970
974
  const queryRaw = adapter.queryRaw.bind(adapter);
971
975
  const executeRaw = adapter.executeRaw.bind(adapter);
@@ -1014,7 +1018,9 @@ function buildContextFromAdapter(adapter, dialect) {
1014
1018
  }
1015
1019
  function buildCloneDbFromAdapter(adapter) {
1016
1020
  if (!adapter.cloneDatabase || !adapter.dropClone) {
1017
- throw new Error("DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply");
1021
+ throw new Error(
1022
+ "DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply"
1023
+ );
1018
1024
  }
1019
1025
  return {
1020
1026
  cloneDatabase: adapter.cloneDatabase.bind(adapter),
package/src/cli/run.js CHANGED
@@ -956,7 +956,9 @@ async function loadMomentumConfig(configPath) {
956
956
  if (!raw.db?.adapter) {
957
957
  throw new Error(`Config at ${configPath} is missing db.adapter`);
958
958
  }
959
- if (!raw.collections || raw.collections.length === 0) {
959
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
960
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
961
+ if (!hasExplicitCollections && !hasPluginCollections) {
960
962
  throw new Error(`Config at ${configPath} has no collections`);
961
963
  }
962
964
  return raw;
@@ -971,7 +973,9 @@ function resolveDialect(adapter) {
971
973
  }
972
974
  function buildTrackerFromAdapter(adapter) {
973
975
  if (!adapter.queryRaw || !adapter.executeRaw) {
974
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
976
+ throw new Error(
977
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
978
+ );
975
979
  }
976
980
  const queryRaw = adapter.queryRaw.bind(adapter);
977
981
  const executeRaw = adapter.executeRaw.bind(adapter);
@@ -1020,7 +1024,9 @@ function buildContextFromAdapter(adapter, dialect) {
1020
1024
  }
1021
1025
  function buildCloneDbFromAdapter(adapter) {
1022
1026
  if (!adapter.cloneDatabase || !adapter.dropClone) {
1023
- throw new Error("DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply");
1027
+ throw new Error(
1028
+ "DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply"
1029
+ );
1024
1030
  }
1025
1031
  return {
1026
1032
  cloneDatabase: adapter.cloneDatabase.bind(adapter),
@@ -1,4 +1,4 @@
1
- import type { ResolvedMomentumConfig, DatabaseAdapter } from '@momentumcms/core';
1
+ import type { ResolvedMomentumConfig, DatabaseAdapter, CollectionConfig } from '@momentumcms/core';
2
2
  import type { DatabaseDialect } from '../lib/schema/column-type-map';
3
3
  import type { TrackerQueryFn } from '../lib/tracking/migration-tracker';
4
4
  import type { MigrationContext } from '../lib/migration.types';
@@ -55,3 +55,9 @@ export interface MigrationCliArgs {
55
55
  * Usage: npx tsx <command>.ts <configPath> [--name <name>] [--dry-run] [--test-only] [--skip-clone-test]
56
56
  */
57
57
  export declare function parseMigrationArgs(args: string[]): MigrationCliArgs;
58
+ /**
59
+ * Merge plugin-declared collections into the config collections array.
60
+ * Reads each plugin's static `collections` property and calls `modifyCollections()`
61
+ * to pick up field injections — all without running async `onInit`.
62
+ */
63
+ export declare function mergePluginCollections(config: ResolvedMomentumConfig): CollectionConfig[];
@@ -301,7 +301,9 @@ async function loadMomentumConfig(configPath) {
301
301
  if (!raw.db?.adapter) {
302
302
  throw new Error(`Config at ${configPath} is missing db.adapter`);
303
303
  }
304
- if (!raw.collections || raw.collections.length === 0) {
304
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
305
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
306
+ if (!hasExplicitCollections && !hasPluginCollections) {
305
307
  throw new Error(`Config at ${configPath} has no collections`);
306
308
  }
307
309
  return raw;
@@ -316,7 +318,9 @@ function resolveDialect(adapter) {
316
318
  }
317
319
  function buildTrackerFromAdapter(adapter) {
318
320
  if (!adapter.queryRaw || !adapter.executeRaw) {
319
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
321
+ throw new Error(
322
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
323
+ );
320
324
  }
321
325
  const queryRaw = adapter.queryRaw.bind(adapter);
322
326
  const executeRaw = adapter.executeRaw.bind(adapter);
package/src/cli/status.js CHANGED
@@ -299,7 +299,9 @@ async function loadMomentumConfig(configPath) {
299
299
  if (!raw.db?.adapter) {
300
300
  throw new Error(`Config at ${configPath} is missing db.adapter`);
301
301
  }
302
- if (!raw.collections || raw.collections.length === 0) {
302
+ const hasExplicitCollections = raw.collections && raw.collections.length > 0;
303
+ const hasPluginCollections = Array.isArray(raw.plugins) && raw.plugins.some((p) => Array.isArray(p.collections) && p.collections.length > 0);
304
+ if (!hasExplicitCollections && !hasPluginCollections) {
303
305
  throw new Error(`Config at ${configPath} has no collections`);
304
306
  }
305
307
  return raw;
@@ -314,7 +316,9 @@ function resolveDialect(adapter) {
314
316
  }
315
317
  function buildTrackerFromAdapter(adapter) {
316
318
  if (!adapter.queryRaw || !adapter.executeRaw) {
317
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
319
+ throw new Error(
320
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
321
+ );
318
322
  }
319
323
  const queryRaw = adapter.queryRaw.bind(adapter);
320
324
  const executeRaw = adapter.executeRaw.bind(adapter);
package/src/index.cjs CHANGED
@@ -2421,7 +2421,9 @@ function resolveDialect(adapter) {
2421
2421
  }
2422
2422
  function buildTrackerFromAdapter(adapter) {
2423
2423
  if (!adapter.queryRaw || !adapter.executeRaw) {
2424
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
2424
+ throw new Error(
2425
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
2426
+ );
2425
2427
  }
2426
2428
  const queryRaw = adapter.queryRaw.bind(adapter);
2427
2429
  const executeRaw = adapter.executeRaw.bind(adapter);
@@ -2481,7 +2483,9 @@ function buildPushDbFromAdapter(adapter) {
2481
2483
  }
2482
2484
  function buildCloneDbFromAdapter(adapter) {
2483
2485
  if (!adapter.cloneDatabase || !adapter.dropClone) {
2484
- throw new Error("DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply");
2486
+ throw new Error(
2487
+ "DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply"
2488
+ );
2485
2489
  }
2486
2490
  return {
2487
2491
  cloneDatabase: adapter.cloneDatabase.bind(adapter),
package/src/index.js CHANGED
@@ -2356,7 +2356,9 @@ function resolveDialect(adapter) {
2356
2356
  }
2357
2357
  function buildTrackerFromAdapter(adapter) {
2358
2358
  if (!adapter.queryRaw || !adapter.executeRaw) {
2359
- throw new Error("DatabaseAdapter must implement queryRaw and executeRaw for migration tracking");
2359
+ throw new Error(
2360
+ "DatabaseAdapter must implement queryRaw and executeRaw for migration tracking"
2361
+ );
2360
2362
  }
2361
2363
  const queryRaw = adapter.queryRaw.bind(adapter);
2362
2364
  const executeRaw = adapter.executeRaw.bind(adapter);
@@ -2416,7 +2418,9 @@ function buildPushDbFromAdapter(adapter) {
2416
2418
  }
2417
2419
  function buildCloneDbFromAdapter(adapter) {
2418
2420
  if (!adapter.cloneDatabase || !adapter.dropClone) {
2419
- throw new Error("DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply");
2421
+ throw new Error(
2422
+ "DatabaseAdapter must implement cloneDatabase and dropClone for clone-test-apply"
2423
+ );
2420
2424
  }
2421
2425
  return {
2422
2426
  cloneDatabase: adapter.cloneDatabase.bind(adapter),