@objectstack/metadata 5.2.0 → 6.1.1

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/dist/index.cjs CHANGED
@@ -546,7 +546,7 @@ var LRUCache = class {
546
546
  // src/migrations/add-sys-metadata-overlay-index.ts
547
547
  var INDEX_NAME = "idx_sys_metadata_overlay_active";
548
548
  var TABLE = "sys_metadata";
549
- var COLUMNS = "(type, name, organization_id, project_id, scope)";
549
+ var COLUMNS = "(type, name, organization_id, environment_id, scope)";
550
550
  var WHERE = "state = 'active'";
551
551
  async function addSysMetadataOverlayIndex(driver) {
552
552
  const driverAny = driver;
@@ -585,6 +585,59 @@ async function addSysMetadataOverlayIndex(driver) {
585
585
  }
586
586
  }
587
587
 
588
+ // src/migrations/migrate-project-id-to-environment-id.ts
589
+ var AFFECTED_TABLES = [
590
+ "sys_metadata",
591
+ "sys_metadata_history"
592
+ ];
593
+ async function migrateProjectIdToEnvironmentId(driver) {
594
+ const driverAny = driver;
595
+ if (typeof driverAny.raw !== "function") {
596
+ throw new Error(
597
+ "migrateProjectIdToEnvironmentId: driver must expose a .raw(sql, bindings?) method. SqlDriver (better-sqlite3/knex) and TursoDriver both support this."
598
+ );
599
+ }
600
+ const results = [];
601
+ for (const table of AFFECTED_TABLES) {
602
+ try {
603
+ const hasColumn = await _columnExists(driverAny, table, "project_id");
604
+ const alreadyMigrated = await _columnExists(driverAny, table, "environment_id");
605
+ if (alreadyMigrated && !hasColumn) {
606
+ results.push({ table, status: "already_done" });
607
+ continue;
608
+ }
609
+ if (!hasColumn) {
610
+ results.push({ table, status: "table_missing" });
611
+ continue;
612
+ }
613
+ await driverAny.raw(
614
+ `ALTER TABLE "${table}" RENAME COLUMN project_id TO environment_id`
615
+ );
616
+ results.push({ table, status: "renamed" });
617
+ } catch (err) {
618
+ results.push({ table, status: "error", error: err?.message ?? String(err) });
619
+ }
620
+ }
621
+ return results;
622
+ }
623
+ async function _columnExists(driver, table, column) {
624
+ try {
625
+ const rows = await driver.raw(`PRAGMA table_info("${table}")`);
626
+ if (Array.isArray(rows) && rows.length > 0) {
627
+ const list2 = Array.isArray(rows[0]) ? rows[0] : rows;
628
+ return list2.some((r) => r?.name === column);
629
+ }
630
+ const result = await driver.raw(
631
+ `SELECT column_name FROM information_schema.columns WHERE table_name = ? AND column_name = ?`,
632
+ [table, column]
633
+ );
634
+ const list = Array.isArray(result[0]) ? result[0] : result;
635
+ return list.length > 0;
636
+ } catch {
637
+ return false;
638
+ }
639
+ }
640
+
588
641
  // src/loaders/database-loader.ts
589
642
  var DatabaseLoader = class {
590
643
  constructor(options) {
@@ -608,7 +661,7 @@ var DatabaseLoader = class {
608
661
  this.tableName = options.tableName ?? "sys_metadata";
609
662
  this.historyTableName = options.historyTableName ?? "sys_metadata_history";
610
663
  this.organizationId = options.organizationId;
611
- void options.projectId;
664
+ void options.environmentId;
612
665
  this.trackHistory = options.trackHistory !== false;
613
666
  const cacheOpts = options.cache;
614
667
  const cacheEnabled = cacheOpts?.enabled !== false;
@@ -740,6 +793,7 @@ var DatabaseLoader = class {
740
793
  }
741
794
  }
742
795
  if (driver) {
796
+ await migrateProjectIdToEnvironmentId(driver).catch(() => void 0);
743
797
  await addSysMetadataOverlayIndex(driver);
744
798
  }
745
799
  } catch {
@@ -752,6 +806,10 @@ var DatabaseLoader = class {
752
806
  name: this.tableName
753
807
  });
754
808
  this.schemaReady = true;
809
+ try {
810
+ await migrateProjectIdToEnvironmentId(this.driver);
811
+ } catch {
812
+ }
755
813
  try {
756
814
  await addSysMetadataOverlayIndex(this.driver);
757
815
  } catch {
@@ -782,7 +840,7 @@ var DatabaseLoader = class {
782
840
  }
783
841
  /**
784
842
  * Build base filter conditions for queries.
785
- * Filters by organizationId when configured. `projectId` is accepted
843
+ * Filters by organizationId when configured. `environmentId` is accepted
786
844
  * for back-compat but no longer constrains the query — see
787
845
  * ADR-0008 §0 (branch/project removal).
788
846
  */
@@ -881,7 +939,7 @@ var DatabaseLoader = class {
881
939
  owner: row.owner,
882
940
  state: row.state ?? "active",
883
941
  organizationId: row.organization_id,
884
- projectId: row.project_id,
942
+ environmentId: row.environment_id,
885
943
  version: row.version ?? 1,
886
944
  checksum: row.checksum,
887
945
  source: row.source,
@@ -1315,13 +1373,13 @@ var _MetadataManager = class _MetadataManager {
1315
1373
  *
1316
1374
  * @param driver - An IDataDriver instance for database operations
1317
1375
  * @param organizationId - Organization ID for multi-tenant isolation
1318
- * @param projectId - Project ID (undefined = platform-global)
1376
+ * @param environmentId - Project ID (undefined = platform-global)
1319
1377
  */
1320
- setDatabaseDriver(driver, organizationId, projectId) {
1321
- if (projectId !== void 0) {
1378
+ setDatabaseDriver(driver, organizationId, environmentId) {
1379
+ if (environmentId !== void 0) {
1322
1380
  this.logger.info("Project kernel \u2014 skipping DatabaseLoader for sys_metadata (control-plane only)", {
1323
1381
  organizationId,
1324
- projectId
1382
+ environmentId
1325
1383
  });
1326
1384
  return;
1327
1385
  }
@@ -1330,7 +1388,7 @@ var _MetadataManager = class _MetadataManager {
1330
1388
  driver,
1331
1389
  tableName,
1332
1390
  organizationId,
1333
- projectId,
1391
+ environmentId,
1334
1392
  cache: this.config.cache?.databaseLoader
1335
1393
  });
1336
1394
  this.registerLoader(dbLoader);
@@ -1344,13 +1402,13 @@ var _MetadataManager = class _MetadataManager {
1344
1402
  *
1345
1403
  * @param engine - An IDataEngine instance (typically the ObjectQL service)
1346
1404
  * @param organizationId - Organization ID for multi-tenant isolation
1347
- * @param projectId - Project ID (undefined = platform-global)
1405
+ * @param environmentId - Project ID (undefined = platform-global)
1348
1406
  */
1349
- setDataEngine(engine, organizationId, projectId) {
1350
- if (projectId !== void 0) {
1407
+ setDataEngine(engine, organizationId, environmentId) {
1408
+ if (environmentId !== void 0) {
1351
1409
  this.logger.info("Project kernel \u2014 skipping DatabaseLoader for sys_metadata (control-plane only)", {
1352
1410
  organizationId,
1353
- projectId
1411
+ environmentId
1354
1412
  });
1355
1413
  return;
1356
1414
  }
@@ -1359,7 +1417,7 @@ var _MetadataManager = class _MetadataManager {
1359
1417
  engine,
1360
1418
  tableName,
1361
1419
  organizationId,
1362
- projectId,
1420
+ environmentId,
1363
1421
  cache: this.config.cache?.databaseLoader
1364
1422
  });
1365
1423
  this.registerLoader(dbLoader);
@@ -3358,24 +3416,24 @@ var MetadataPlugin = class {
3358
3416
  * metadata items into the MetadataManager.
3359
3417
  */
3360
3418
  async _parseAndRegisterArtifact(ctx, raw, label) {
3361
- const { ProjectArtifactSchema } = await import("@objectstack/spec/cloud");
3419
+ const { EnvironmentArtifactSchema } = await import("@objectstack/spec/cloud");
3362
3420
  const { ObjectStackDefinitionSchema } = await import("@objectstack/spec");
3363
3421
  let metadata;
3364
3422
  const obj = raw;
3365
3423
  if (obj?.schemaVersion && obj?.commitId && obj?.metadata !== void 0) {
3366
- const artifact = ProjectArtifactSchema.parse(obj);
3424
+ const artifact = EnvironmentArtifactSchema.parse(obj);
3367
3425
  metadata = artifact.metadata;
3368
3426
  } else if (obj?.success && obj?.data?.metadata) {
3369
- const artifact = ProjectArtifactSchema.parse(obj.data);
3427
+ const artifact = EnvironmentArtifactSchema.parse(obj.data);
3370
3428
  metadata = artifact.metadata;
3371
3429
  } else {
3372
3430
  const def = ObjectStackDefinitionSchema.parse(obj);
3373
3431
  const canonical = JSON.stringify(def, Object.keys(def).sort());
3374
3432
  const checksum = (0, import_node_crypto2.createHash)("sha256").update(canonical).digest("hex");
3375
- const projectId = this.options.projectId ?? "proj_local";
3376
- ProjectArtifactSchema.parse({
3433
+ const environmentId = this.options.environmentId ?? "proj_local";
3434
+ EnvironmentArtifactSchema.parse({
3377
3435
  schemaVersion: "0.1",
3378
- projectId,
3436
+ environmentId,
3379
3437
  commitId: "local-dev",
3380
3438
  checksum,
3381
3439
  metadata: def
@@ -3431,13 +3489,13 @@ var MetadataPlugin = class {
3431
3489
  * P2: Load metadata from the cloud artifact API endpoint.
3432
3490
  */
3433
3491
  async _loadFromArtifactApi(ctx, src) {
3434
- const projectId = this.options.projectId;
3435
- if (!projectId) {
3436
- throw new Error("[MetadataPlugin] artifact-api source requires options.projectId to be set");
3492
+ const environmentId = this.options.environmentId;
3493
+ if (!environmentId) {
3494
+ throw new Error("[MetadataPlugin] artifact-api source requires options.environmentId to be set");
3437
3495
  }
3438
3496
  let artifactUrl = src.url.replace(/\/+$/, "");
3439
3497
  if (!/\/api\/v\d+\/cloud\/projects\//i.test(artifactUrl)) {
3440
- artifactUrl = `${artifactUrl}/api/v1/cloud/projects/${projectId}/artifact`;
3498
+ artifactUrl = `${artifactUrl}/api/v1/cloud/environments/${environmentId}/artifact`;
3441
3499
  }
3442
3500
  if (src.commitId) {
3443
3501
  artifactUrl += `${artifactUrl.includes("?") ? "&" : "?"}commit=${encodeURIComponent(src.commitId)}`;