@objectstack/objectql 9.3.0 → 9.4.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.
- package/dist/index.d.mts +62 -25
- package/dist/index.d.ts +62 -25
- package/dist/index.js +163 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +163 -101
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -310,6 +310,19 @@ var init_seed_loader = __esm({
|
|
|
310
310
|
if (records && records.length > 0) {
|
|
311
311
|
return String(records[0].id || records[0]._id);
|
|
312
312
|
}
|
|
313
|
+
if (targetField !== "id") {
|
|
314
|
+
const byId = { id: value };
|
|
315
|
+
if (organizationId) byId.organization_id = organizationId;
|
|
316
|
+
const idMatch = await this.engine.find(targetObject, {
|
|
317
|
+
where: byId,
|
|
318
|
+
fields: ["id"],
|
|
319
|
+
limit: 1,
|
|
320
|
+
context: { isSystem: true }
|
|
321
|
+
});
|
|
322
|
+
if (idMatch && idMatch.length > 0) {
|
|
323
|
+
return String(idMatch[0].id || idMatch[0]._id);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
313
326
|
} catch {
|
|
314
327
|
}
|
|
315
328
|
return null;
|
|
@@ -886,18 +899,16 @@ function applySystemFields(schema, opts) {
|
|
|
886
899
|
fields: { ...additions, ...schema.fields ?? {} }
|
|
887
900
|
};
|
|
888
901
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
return typeof pkg === "string" && pkg.length > 0 && pkg !== SYS_METADATA_OWNER;
|
|
902
|
+
function isShareableNamespace(ns) {
|
|
903
|
+
return RESERVED_NAMESPACES.has(ns) || ns === "sys";
|
|
892
904
|
}
|
|
893
|
-
var
|
|
894
|
-
constructor(
|
|
905
|
+
var NamespaceConflictError = class extends Error {
|
|
906
|
+
constructor(namespace, existingPackageId, incomingPackageId) {
|
|
895
907
|
super(
|
|
896
|
-
`
|
|
908
|
+
`Namespace conflict: namespace "${namespace}" is already owned by package "${existingPackageId}", so package "${incomingPackageId}" cannot be installed alongside it. A namespace is the mandatory prefix of every object name (e.g. "${namespace}_account") and the container that scopes a package's UI metadata, so it must be unique per installation. Choose a different namespace for "${incomingPackageId}", or uninstall "${existingPackageId}" first. If this is a deliberate migration, set OS_METADATA_COLLISION=warn to downgrade to a warning. See ADR-0048.`
|
|
897
909
|
);
|
|
898
|
-
this.name = "
|
|
899
|
-
this.
|
|
900
|
-
this.name_ = name;
|
|
910
|
+
this.name = "NamespaceConflictError";
|
|
911
|
+
this.namespace = namespace;
|
|
901
912
|
this.existingPackageId = existingPackageId;
|
|
902
913
|
this.incomingPackageId = incomingPackageId;
|
|
903
914
|
}
|
|
@@ -1253,17 +1264,6 @@ var SchemaRegistry = class {
|
|
|
1253
1264
|
if (collection.has(storageKey)) {
|
|
1254
1265
|
this.log(`[Registry] Overwriting ${type}: ${storageKey}`);
|
|
1255
1266
|
}
|
|
1256
|
-
if (isRealPackage(packageId)) {
|
|
1257
|
-
const conflictOwner = this.findOtherPackageOwner(collection, baseName, packageId);
|
|
1258
|
-
if (conflictOwner) {
|
|
1259
|
-
const err = new MetadataCollisionError(type, baseName, conflictOwner, packageId);
|
|
1260
|
-
if (this.collisionPolicy === "warn") {
|
|
1261
|
-
console.warn(`[Registry] ${err.message}`);
|
|
1262
|
-
} else {
|
|
1263
|
-
throw err;
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
1267
|
if (packageId && collection.has(baseName)) {
|
|
1268
1268
|
const dbOnly = collection.get(baseName);
|
|
1269
1269
|
if (dbOnly && !dbOnly._packageId) {
|
|
@@ -1275,22 +1275,6 @@ var SchemaRegistry = class {
|
|
|
1275
1275
|
collection.set(storageKey, item);
|
|
1276
1276
|
this.log(`[Registry] Registered ${type}: ${storageKey}`);
|
|
1277
1277
|
}
|
|
1278
|
-
/**
|
|
1279
|
-
* Find a code package OTHER than `incoming` that already owns `baseName` in
|
|
1280
|
-
* `collection` (ADR-0048 cross-package collision detection). Scans the live
|
|
1281
|
-
* collection — like {@link getItem} / {@link unregisterItem} — so it always
|
|
1282
|
-
* reflects current state with no parallel index to drift across
|
|
1283
|
-
* reset/unregister. Returns the conflicting owner's package id, or undefined
|
|
1284
|
-
* when the name is free or only held by the same package / a runtime overlay.
|
|
1285
|
-
*/
|
|
1286
|
-
findOtherPackageOwner(collection, baseName, incoming) {
|
|
1287
|
-
for (const [key, item] of collection) {
|
|
1288
|
-
if (key !== baseName && !key.endsWith(`:${baseName}`)) continue;
|
|
1289
|
-
const owner = item?._packageId;
|
|
1290
|
-
if (isRealPackage(owner) && owner !== incoming) return owner;
|
|
1291
|
-
}
|
|
1292
|
-
return void 0;
|
|
1293
|
-
}
|
|
1294
1278
|
/**
|
|
1295
1279
|
* Validate Metadata against Spec Zod Schemas
|
|
1296
1280
|
*/
|
|
@@ -1333,9 +1317,23 @@ var SchemaRegistry = class {
|
|
|
1333
1317
|
console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);
|
|
1334
1318
|
}
|
|
1335
1319
|
/**
|
|
1336
|
-
* Universal Get Method
|
|
1320
|
+
* Universal Get Method.
|
|
1321
|
+
*
|
|
1322
|
+
* ADR-0048 §3.3 — *package-scoped* resolution. When `currentPackageId` is
|
|
1323
|
+
* given (the package the caller is resolving within — known from the route /
|
|
1324
|
+
* `activeApp._packageId`), a bare name resolves to *that package's* item
|
|
1325
|
+
* before any cross-package fallback, so two packages shipping e.g.
|
|
1326
|
+
* `page/home` no longer resolve by registration order (first-match-wins).
|
|
1327
|
+
* Because package ids are globally unique this is unambiguous. Omitting
|
|
1328
|
+
* `currentPackageId` preserves the legacy resolution exactly (backward
|
|
1329
|
+
* compatible) and is best-effort: it returns the first match.
|
|
1330
|
+
*
|
|
1331
|
+
* Precedence (highest first):
|
|
1332
|
+
* 1. bare-key runtime/DB overlay (ADR-0005 sanctioned override) — unchanged
|
|
1333
|
+
* 2. the `currentPackageId` composite entry (prefer-local)
|
|
1334
|
+
* 3. first composite match (legacy first-registered-wins fallback)
|
|
1337
1335
|
*/
|
|
1338
|
-
getItem(type, name) {
|
|
1336
|
+
getItem(type, name, currentPackageId) {
|
|
1339
1337
|
if (type === "object" || type === "objects") {
|
|
1340
1338
|
return this.getObject(name);
|
|
1341
1339
|
}
|
|
@@ -1343,6 +1341,10 @@ var SchemaRegistry = class {
|
|
|
1343
1341
|
if (!collection) return void 0;
|
|
1344
1342
|
const direct = collection.get(name);
|
|
1345
1343
|
if (direct) return direct;
|
|
1344
|
+
if (currentPackageId) {
|
|
1345
|
+
const local = collection.get(`${currentPackageId}:${name}`);
|
|
1346
|
+
if (local) return local;
|
|
1347
|
+
}
|
|
1346
1348
|
for (const [key, item] of collection) {
|
|
1347
1349
|
if (key.endsWith(`:${name}`)) {
|
|
1348
1350
|
return item;
|
|
@@ -1364,13 +1366,17 @@ var SchemaRegistry = class {
|
|
|
1364
1366
|
* it (that masking is exactly the "registry pollution" bug where a
|
|
1365
1367
|
* locked app's `_lock` read back as undefined after a PUT+GET).
|
|
1366
1368
|
*/
|
|
1367
|
-
getArtifactItem(type, name) {
|
|
1369
|
+
getArtifactItem(type, name, currentPackageId) {
|
|
1368
1370
|
if (type === "object" || type === "objects") {
|
|
1369
1371
|
const obj = this.getObject(name);
|
|
1370
1372
|
return obj && obj._packageId && obj._packageId !== "sys_metadata" ? obj : void 0;
|
|
1371
1373
|
}
|
|
1372
1374
|
const collection = this.metadata.get(type);
|
|
1373
1375
|
if (!collection) return void 0;
|
|
1376
|
+
if (currentPackageId) {
|
|
1377
|
+
const local = collection.get(`${currentPackageId}:${name}`);
|
|
1378
|
+
if (local && local._packageId && local._packageId !== "sys_metadata") return local;
|
|
1379
|
+
}
|
|
1374
1380
|
for (const [key, item] of collection) {
|
|
1375
1381
|
if (key !== name && key.endsWith(`:${name}`)) {
|
|
1376
1382
|
const it = item;
|
|
@@ -1454,6 +1460,20 @@ var SchemaRegistry = class {
|
|
|
1454
1460
|
// Package Management
|
|
1455
1461
|
// ==========================================
|
|
1456
1462
|
installPackage(manifest, settings) {
|
|
1463
|
+
if (manifest.namespace && !isShareableNamespace(manifest.namespace)) {
|
|
1464
|
+
const conflictOwner = this.getNamespaceOwners(manifest.namespace).find(
|
|
1465
|
+
(owner) => owner !== manifest.id
|
|
1466
|
+
);
|
|
1467
|
+
if (conflictOwner) {
|
|
1468
|
+
if (this.collisionPolicy === "warn") {
|
|
1469
|
+
console.warn(
|
|
1470
|
+
`[Registry] Namespace conflict (downgraded to warning via OS_METADATA_COLLISION=warn): namespace "${manifest.namespace}" is already owned by "${conflictOwner}"; installing "${manifest.id}" anyway. See ADR-0048.`
|
|
1471
|
+
);
|
|
1472
|
+
} else {
|
|
1473
|
+
throw new NamespaceConflictError(manifest.namespace, conflictOwner, manifest.id);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1457
1477
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1458
1478
|
const disabled = this.initialDisabledPackageIds.has(manifest.id);
|
|
1459
1479
|
const pkg = {
|
|
@@ -1531,8 +1551,8 @@ var SchemaRegistry = class {
|
|
|
1531
1551
|
registerApp(app, packageId) {
|
|
1532
1552
|
this.registerItem("app", app, "name", packageId);
|
|
1533
1553
|
}
|
|
1534
|
-
getApp(name) {
|
|
1535
|
-
const app = this.getItem("app", name);
|
|
1554
|
+
getApp(name, currentPackageId) {
|
|
1555
|
+
const app = this.getItem("app", name, currentPackageId);
|
|
1536
1556
|
if (!app) return app;
|
|
1537
1557
|
return this.applyNavContributions(app);
|
|
1538
1558
|
}
|
|
@@ -1752,7 +1772,7 @@ var SysMetadataRepository = class {
|
|
|
1752
1772
|
this.assertOpen();
|
|
1753
1773
|
const state = opts?.state ?? "active";
|
|
1754
1774
|
const row = await this.engine.findOne("sys_metadata", {
|
|
1755
|
-
where: this.whereFor(ref, state)
|
|
1775
|
+
where: this.whereFor(ref, state, opts && "packageId" in opts ? opts.packageId ?? null : void 0)
|
|
1756
1776
|
});
|
|
1757
1777
|
if (!row) return null;
|
|
1758
1778
|
return this.rowToItem(ref, row);
|
|
@@ -1801,7 +1821,7 @@ var SysMetadataRepository = class {
|
|
|
1801
1821
|
const hash = hashSpec(body);
|
|
1802
1822
|
const result = await this.withTxn(async (ctx) => {
|
|
1803
1823
|
const existing = await this.engine.findOne("sys_metadata", {
|
|
1804
|
-
where: this.whereFor(ref, state),
|
|
1824
|
+
where: this.whereFor(ref, state, opts.packageId ?? null),
|
|
1805
1825
|
context: ctx
|
|
1806
1826
|
});
|
|
1807
1827
|
const existingHash = existing?.checksum ?? null;
|
|
@@ -2285,13 +2305,15 @@ var SysMetadataRepository = class {
|
|
|
2285
2305
|
err.status = 403;
|
|
2286
2306
|
throw err;
|
|
2287
2307
|
}
|
|
2288
|
-
whereFor(ref, state = "active") {
|
|
2289
|
-
|
|
2308
|
+
whereFor(ref, state = "active", packageId) {
|
|
2309
|
+
const where = {
|
|
2290
2310
|
type: ref.type,
|
|
2291
2311
|
name: ref.name,
|
|
2292
2312
|
organization_id: this.organizationId,
|
|
2293
2313
|
state
|
|
2294
2314
|
};
|
|
2315
|
+
if (packageId !== void 0) where.package_id = packageId;
|
|
2316
|
+
return where;
|
|
2295
2317
|
}
|
|
2296
2318
|
fullRef(ref) {
|
|
2297
2319
|
return {
|
|
@@ -2983,8 +3005,8 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2983
3005
|
await exec("DROP INDEX IF EXISTS idx_sys_metadata_overlay_active");
|
|
2984
3006
|
} catch {
|
|
2985
3007
|
}
|
|
2986
|
-
const partialSql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id) WHERE state = 'active'";
|
|
2987
|
-
const fallbackSql = "CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id)";
|
|
3008
|
+
const partialSql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id, COALESCE(package_id, '')) WHERE state = 'active'";
|
|
3009
|
+
const fallbackSql = "CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id, package_id)";
|
|
2988
3010
|
try {
|
|
2989
3011
|
await exec(partialSql);
|
|
2990
3012
|
} catch (err) {
|
|
@@ -2996,7 +3018,11 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2996
3018
|
}
|
|
2997
3019
|
}
|
|
2998
3020
|
}
|
|
2999
|
-
|
|
3021
|
+
try {
|
|
3022
|
+
await exec("DROP INDEX IF EXISTS idx_sys_metadata_overlay_draft");
|
|
3023
|
+
} catch {
|
|
3024
|
+
}
|
|
3025
|
+
const draftPartialSql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft ON sys_metadata (type, name, organization_id, COALESCE(package_id, '')) WHERE state = 'draft'";
|
|
3000
3026
|
try {
|
|
3001
3027
|
await exec(draftPartialSql);
|
|
3002
3028
|
} catch (err) {
|
|
@@ -3004,7 +3030,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3004
3030
|
if (/partial|where clause|syntax/i.test(msg)) {
|
|
3005
3031
|
try {
|
|
3006
3032
|
await exec(
|
|
3007
|
-
"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft ON sys_metadata (type, name, organization_id)"
|
|
3033
|
+
"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft ON sys_metadata (type, name, organization_id, package_id)"
|
|
3008
3034
|
);
|
|
3009
3035
|
} catch {
|
|
3010
3036
|
}
|
|
@@ -3405,7 +3431,8 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3405
3431
|
items.map((it) => {
|
|
3406
3432
|
const a = this.lookupArtifactItem(
|
|
3407
3433
|
request.type,
|
|
3408
|
-
it?.name
|
|
3434
|
+
it?.name,
|
|
3435
|
+
packageId ?? it?._packageId
|
|
3409
3436
|
);
|
|
3410
3437
|
return mergeArtifactProtection(it, a);
|
|
3411
3438
|
})
|
|
@@ -3419,16 +3446,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3419
3446
|
if (request.previewDrafts && readState !== "draft") {
|
|
3420
3447
|
try {
|
|
3421
3448
|
const findDraft = async (oid) => {
|
|
3422
|
-
const
|
|
3423
|
-
|
|
3424
|
-
|
|
3449
|
+
const lookup = async (t) => {
|
|
3450
|
+
const base = {
|
|
3451
|
+
type: t,
|
|
3452
|
+
name: request.name,
|
|
3453
|
+
state: "draft",
|
|
3454
|
+
organization_id: oid
|
|
3455
|
+
};
|
|
3456
|
+
if (request.packageId) {
|
|
3457
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3458
|
+
where: { ...base, package_id: request.packageId }
|
|
3459
|
+
});
|
|
3460
|
+
if (scoped) return scoped;
|
|
3461
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3462
|
+
where: { ...base, package_id: null }
|
|
3463
|
+
});
|
|
3464
|
+
}
|
|
3465
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3466
|
+
};
|
|
3467
|
+
const rec = await lookup(request.type);
|
|
3425
3468
|
if (rec) return rec;
|
|
3426
3469
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3427
|
-
if (alt)
|
|
3428
|
-
return await this.engine.findOne("sys_metadata", {
|
|
3429
|
-
where: { type: alt, name: request.name, state: "draft", organization_id: oid }
|
|
3430
|
-
});
|
|
3431
|
-
}
|
|
3470
|
+
if (alt) return await lookup(alt);
|
|
3432
3471
|
return void 0;
|
|
3433
3472
|
};
|
|
3434
3473
|
const draftRec = (orgId ? await findDraft(orgId) : void 0) ?? await findDraft(null);
|
|
@@ -3446,24 +3485,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3446
3485
|
}
|
|
3447
3486
|
try {
|
|
3448
3487
|
const findOverlay = async (oid) => {
|
|
3449
|
-
const
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
state: readState,
|
|
3453
|
-
organization_id: oid
|
|
3454
|
-
};
|
|
3455
|
-
const rec = await this.engine.findOne("sys_metadata", { where });
|
|
3456
|
-
if (rec) return rec;
|
|
3457
|
-
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3458
|
-
if (alt) {
|
|
3459
|
-
const altWhere = {
|
|
3460
|
-
type: alt,
|
|
3488
|
+
const lookup = async (t) => {
|
|
3489
|
+
const base = {
|
|
3490
|
+
type: t,
|
|
3461
3491
|
name: request.name,
|
|
3462
3492
|
state: readState,
|
|
3463
3493
|
organization_id: oid
|
|
3464
3494
|
};
|
|
3465
|
-
|
|
3466
|
-
|
|
3495
|
+
if (request.packageId) {
|
|
3496
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3497
|
+
where: { ...base, package_id: request.packageId }
|
|
3498
|
+
});
|
|
3499
|
+
if (scoped) return scoped;
|
|
3500
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3501
|
+
where: { ...base, package_id: null }
|
|
3502
|
+
});
|
|
3503
|
+
}
|
|
3504
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3505
|
+
};
|
|
3506
|
+
const rec = await lookup(request.type);
|
|
3507
|
+
if (rec) return rec;
|
|
3508
|
+
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3509
|
+
if (alt) return await lookup(alt);
|
|
3467
3510
|
return void 0;
|
|
3468
3511
|
};
|
|
3469
3512
|
const record = (orgId ? await findOverlay(orgId) : void 0) ?? await findOverlay(null);
|
|
@@ -3492,13 +3535,13 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3492
3535
|
const services = this.getServicesRegistry?.();
|
|
3493
3536
|
const metadataService = services?.get("metadata");
|
|
3494
3537
|
if (metadataService && typeof metadataService.get === "function") {
|
|
3495
|
-
const fromService = await metadataService.get(request.type, request.name);
|
|
3538
|
+
const fromService = await metadataService.get(request.type, request.name, request.packageId);
|
|
3496
3539
|
if (fromService !== void 0 && fromService !== null) {
|
|
3497
3540
|
item = fromService;
|
|
3498
3541
|
} else {
|
|
3499
3542
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3500
3543
|
if (alt) {
|
|
3501
|
-
const altFromService = await metadataService.get(alt, request.name);
|
|
3544
|
+
const altFromService = await metadataService.get(alt, request.name, request.packageId);
|
|
3502
3545
|
if (altFromService !== void 0 && altFromService !== null) {
|
|
3503
3546
|
item = altFromService;
|
|
3504
3547
|
}
|
|
@@ -3509,16 +3552,16 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3509
3552
|
}
|
|
3510
3553
|
}
|
|
3511
3554
|
if (item === void 0) {
|
|
3512
|
-
item = this.engine.registry.getItem(request.type, request.name);
|
|
3555
|
+
item = this.engine.registry.getItem(request.type, request.name, request.packageId);
|
|
3513
3556
|
if (item === void 0) {
|
|
3514
3557
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3515
|
-
if (alt) item = this.engine.registry.getItem(alt, request.name);
|
|
3558
|
+
if (alt) item = this.engine.registry.getItem(alt, request.name, request.packageId);
|
|
3516
3559
|
}
|
|
3517
3560
|
}
|
|
3518
3561
|
if ((request.type === "app" || request.type === "apps") && item) {
|
|
3519
3562
|
item = this.engine.registry.applyNavContributions(item);
|
|
3520
3563
|
}
|
|
3521
|
-
const artifactItem = this.lookupArtifactItem(request.type, request.name);
|
|
3564
|
+
const artifactItem = this.lookupArtifactItem(request.type, request.name, request.packageId);
|
|
3522
3565
|
let decorated = decorateMetadataItem(
|
|
3523
3566
|
request.type,
|
|
3524
3567
|
mergeArtifactProtection(item, artifactItem)
|
|
@@ -3586,20 +3629,20 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3586
3629
|
const services = this.getServicesRegistry?.();
|
|
3587
3630
|
const metadataService = services?.get("metadata");
|
|
3588
3631
|
if (metadataService && typeof metadataService.get === "function") {
|
|
3589
|
-
let fromService = await metadataService.get(request.type, request.name);
|
|
3632
|
+
let fromService = await metadataService.get(request.type, request.name, request.packageId);
|
|
3590
3633
|
if (fromService === void 0 || fromService === null) {
|
|
3591
3634
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3592
|
-
if (alt) fromService = await metadataService.get(alt, request.name);
|
|
3635
|
+
if (alt) fromService = await metadataService.get(alt, request.name, request.packageId);
|
|
3593
3636
|
}
|
|
3594
3637
|
if (fromService !== void 0 && fromService !== null) code = fromService;
|
|
3595
3638
|
}
|
|
3596
3639
|
} catch {
|
|
3597
3640
|
}
|
|
3598
3641
|
if (code === null) {
|
|
3599
|
-
let regItem = this.lookupArtifactItem(request.type, request.name) ?? this.engine.registry.getItem(request.type, request.name);
|
|
3642
|
+
let regItem = this.lookupArtifactItem(request.type, request.name, request.packageId) ?? this.engine.registry.getItem(request.type, request.name, request.packageId);
|
|
3600
3643
|
if (regItem === void 0) {
|
|
3601
3644
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3602
|
-
if (alt) regItem = this.engine.registry.getItem(alt, request.name);
|
|
3645
|
+
if (alt) regItem = this.engine.registry.getItem(alt, request.name, request.packageId);
|
|
3603
3646
|
}
|
|
3604
3647
|
if (regItem !== void 0) code = regItem;
|
|
3605
3648
|
}
|
|
@@ -3607,20 +3650,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3607
3650
|
let overlayScope = null;
|
|
3608
3651
|
try {
|
|
3609
3652
|
const findOverlay = async (oid) => {
|
|
3610
|
-
const
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3653
|
+
const lookup = async (t) => {
|
|
3654
|
+
const base = {
|
|
3655
|
+
type: t,
|
|
3656
|
+
name: request.name,
|
|
3657
|
+
state: "active",
|
|
3658
|
+
organization_id: oid
|
|
3659
|
+
};
|
|
3660
|
+
if (request.packageId) {
|
|
3661
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3662
|
+
where: { ...base, package_id: request.packageId }
|
|
3663
|
+
});
|
|
3664
|
+
if (scoped) return scoped;
|
|
3665
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3666
|
+
where: { ...base, package_id: null }
|
|
3667
|
+
});
|
|
3668
|
+
}
|
|
3669
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3615
3670
|
};
|
|
3616
|
-
let rec = await
|
|
3671
|
+
let rec = await lookup(request.type);
|
|
3617
3672
|
if (!rec) {
|
|
3618
3673
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3619
|
-
if (alt)
|
|
3620
|
-
rec = await this.engine.findOne("sys_metadata", {
|
|
3621
|
-
where: { ...where, type: alt }
|
|
3622
|
-
});
|
|
3623
|
-
}
|
|
3674
|
+
if (alt) rec = await lookup(alt);
|
|
3624
3675
|
}
|
|
3625
3676
|
return rec;
|
|
3626
3677
|
};
|
|
@@ -4652,15 +4703,15 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
4652
4703
|
* type and its singular/plural twin. Returns `undefined` when the
|
|
4653
4704
|
* registry is unavailable or the item is not artifact-backed.
|
|
4654
4705
|
*/
|
|
4655
|
-
lookupArtifactItem(type, name) {
|
|
4706
|
+
lookupArtifactItem(type, name, currentPackageId) {
|
|
4656
4707
|
const registry = this.engine?.registry;
|
|
4657
4708
|
if (!registry) return void 0;
|
|
4658
4709
|
const singular = PLURAL_TO_SINGULAR3[type] ?? type;
|
|
4659
4710
|
if (typeof registry.getArtifactItem === "function") {
|
|
4660
|
-
return registry.getArtifactItem(singular, name) ?? registry.getArtifactItem(type, name);
|
|
4711
|
+
return registry.getArtifactItem(singular, name, currentPackageId) ?? registry.getArtifactItem(type, name, currentPackageId);
|
|
4661
4712
|
}
|
|
4662
4713
|
if (typeof registry.getItem !== "function") return void 0;
|
|
4663
|
-
const item = registry.getItem(singular, name) ?? registry.getItem(type, name);
|
|
4714
|
+
const item = registry.getItem(singular, name, currentPackageId) ?? registry.getItem(type, name, currentPackageId);
|
|
4664
4715
|
if (!item || !item._packageId || item._packageId === "sys_metadata") {
|
|
4665
4716
|
return void 0;
|
|
4666
4717
|
}
|
|
@@ -5026,7 +5077,10 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
5026
5077
|
if (request.parentVersion !== void 0) {
|
|
5027
5078
|
parentVersion = request.parentVersion;
|
|
5028
5079
|
} else {
|
|
5029
|
-
const current = await repo.get(ref, {
|
|
5080
|
+
const current = await repo.get(ref, {
|
|
5081
|
+
state: mode === "draft" ? "draft" : "active",
|
|
5082
|
+
packageId: request.packageId ?? null
|
|
5083
|
+
});
|
|
5030
5084
|
parentVersion = current?.hash ?? null;
|
|
5031
5085
|
}
|
|
5032
5086
|
try {
|
|
@@ -9448,10 +9502,16 @@ var MetadataFacade = class {
|
|
|
9448
9502
|
}
|
|
9449
9503
|
}
|
|
9450
9504
|
/**
|
|
9451
|
-
* Get a metadata item by type and name
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9505
|
+
* Get a metadata item by type and name.
|
|
9506
|
+
*
|
|
9507
|
+
* `currentPackageId` (ADR-0048) opts into package-scoped resolution: when two
|
|
9508
|
+
* installed packages ship an item of the same `type`/`name`, the registry
|
|
9509
|
+
* prefers the one owned by `currentPackageId` (composite key
|
|
9510
|
+
* `${packageId}:${name}`) before falling back to first-match. Omit it for the
|
|
9511
|
+
* legacy context-free lookup.
|
|
9512
|
+
*/
|
|
9513
|
+
async get(type, name, currentPackageId) {
|
|
9514
|
+
const item = this.registry.getItem(type, name, currentPackageId);
|
|
9455
9515
|
return item?.content ?? item;
|
|
9456
9516
|
}
|
|
9457
9517
|
/**
|
|
@@ -9530,6 +9590,7 @@ var ObjectQLPlugin = class {
|
|
|
9530
9590
|
*/
|
|
9531
9591
|
this.startupTimeout = 12e4;
|
|
9532
9592
|
this.skipSchemaSync = false;
|
|
9593
|
+
this.hydrateMetadataFromDb = false;
|
|
9533
9594
|
/** Unsubscribe handles for metadata-event subscriptions (ADR-0008 PR-7). */
|
|
9534
9595
|
this.metadataUnsubscribes = [];
|
|
9535
9596
|
this.init = async (ctx) => {
|
|
@@ -9654,7 +9715,7 @@ var ObjectQLPlugin = class {
|
|
|
9654
9715
|
} else {
|
|
9655
9716
|
await this.syncRegisteredSchemas(ctx);
|
|
9656
9717
|
}
|
|
9657
|
-
if (this.environmentId === void 0) {
|
|
9718
|
+
if (this.environmentId === void 0 || this.hydrateMetadataFromDb) {
|
|
9658
9719
|
await this.restoreMetadataFromDb(ctx);
|
|
9659
9720
|
} else {
|
|
9660
9721
|
ctx.logger.info("Project kernel \u2014 skipping sys_metadata hydration (metadata sourced from artifact)");
|
|
@@ -9696,6 +9757,7 @@ var ObjectQLPlugin = class {
|
|
|
9696
9757
|
this.startupTimeout = opts.startupTimeout;
|
|
9697
9758
|
}
|
|
9698
9759
|
this.skipSchemaSync = typeof opts.skipSchemaSync === "boolean" ? opts.skipSchemaSync : process.env.OS_SKIP_SCHEMA_SYNC === "1";
|
|
9760
|
+
this.hydrateMetadataFromDb = opts.hydrateMetadataFromDb === true;
|
|
9699
9761
|
}
|
|
9700
9762
|
/**
|
|
9701
9763
|
* Subscribe to `object` metadata events from the metadata service and
|