@objectstack/objectql 9.3.0 → 9.5.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 +181 -109
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +181 -109
- 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;
|
|
@@ -2005,8 +2025,10 @@ var SysMetadataRepository = class {
|
|
|
2005
2025
|
*/
|
|
2006
2026
|
async promoteDraft(ref, opts) {
|
|
2007
2027
|
this.assertOpen();
|
|
2008
|
-
const
|
|
2009
|
-
|
|
2028
|
+
const draftRow = await this.engine.findOne("sys_metadata", {
|
|
2029
|
+
where: this.whereFor(ref, "draft")
|
|
2030
|
+
});
|
|
2031
|
+
if (!draftRow) {
|
|
2010
2032
|
const err = new Error(
|
|
2011
2033
|
`[no_draft] No pending draft exists for ${ref.type}/${ref.name} \u2014 nothing to publish.`
|
|
2012
2034
|
);
|
|
@@ -2014,7 +2036,9 @@ var SysMetadataRepository = class {
|
|
|
2014
2036
|
err.status = 404;
|
|
2015
2037
|
throw err;
|
|
2016
2038
|
}
|
|
2017
|
-
const
|
|
2039
|
+
const draftPackageId = draftRow.package_id ?? null;
|
|
2040
|
+
const draft = this.rowToItem(ref, draftRow);
|
|
2041
|
+
const currentActive = await this.get(ref, { state: "active", packageId: draftPackageId });
|
|
2018
2042
|
const result = await this.put(ref, draft.body, {
|
|
2019
2043
|
parentVersion: currentActive?.hash ?? null,
|
|
2020
2044
|
actor: opts.actor,
|
|
@@ -2022,7 +2046,8 @@ var SysMetadataRepository = class {
|
|
|
2022
2046
|
message: opts.message ?? `publish draft (hash ${draft.hash})`,
|
|
2023
2047
|
intent: opts.intent ?? "override-artifact",
|
|
2024
2048
|
state: "active",
|
|
2025
|
-
opType: "publish"
|
|
2049
|
+
opType: "publish",
|
|
2050
|
+
packageId: draftPackageId
|
|
2026
2051
|
});
|
|
2027
2052
|
try {
|
|
2028
2053
|
await this.delete(ref, {
|
|
@@ -2115,10 +2140,15 @@ var SysMetadataRepository = class {
|
|
|
2115
2140
|
*/
|
|
2116
2141
|
async listDrafts(filter) {
|
|
2117
2142
|
this.assertOpen();
|
|
2118
|
-
const where = {
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2143
|
+
const where = { state: "draft" };
|
|
2144
|
+
if (this.organizationId != null) {
|
|
2145
|
+
where.$or = [
|
|
2146
|
+
{ organization_id: this.organizationId },
|
|
2147
|
+
{ organization_id: null }
|
|
2148
|
+
];
|
|
2149
|
+
} else {
|
|
2150
|
+
where.organization_id = null;
|
|
2151
|
+
}
|
|
2122
2152
|
if (filter?.type) where.type = filter.type;
|
|
2123
2153
|
if (filter?.packageId) where.package_id = filter.packageId;
|
|
2124
2154
|
const rows = await this.engine.find("sys_metadata", { where });
|
|
@@ -2285,13 +2315,15 @@ var SysMetadataRepository = class {
|
|
|
2285
2315
|
err.status = 403;
|
|
2286
2316
|
throw err;
|
|
2287
2317
|
}
|
|
2288
|
-
whereFor(ref, state = "active") {
|
|
2289
|
-
|
|
2318
|
+
whereFor(ref, state = "active", packageId) {
|
|
2319
|
+
const where = {
|
|
2290
2320
|
type: ref.type,
|
|
2291
2321
|
name: ref.name,
|
|
2292
2322
|
organization_id: this.organizationId,
|
|
2293
2323
|
state
|
|
2294
2324
|
};
|
|
2325
|
+
if (packageId !== void 0) where.package_id = packageId;
|
|
2326
|
+
return where;
|
|
2295
2327
|
}
|
|
2296
2328
|
fullRef(ref) {
|
|
2297
2329
|
return {
|
|
@@ -2983,8 +3015,8 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2983
3015
|
await exec("DROP INDEX IF EXISTS idx_sys_metadata_overlay_active");
|
|
2984
3016
|
} catch {
|
|
2985
3017
|
}
|
|
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)";
|
|
3018
|
+
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'";
|
|
3019
|
+
const fallbackSql = "CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id, package_id)";
|
|
2988
3020
|
try {
|
|
2989
3021
|
await exec(partialSql);
|
|
2990
3022
|
} catch (err) {
|
|
@@ -2996,7 +3028,11 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2996
3028
|
}
|
|
2997
3029
|
}
|
|
2998
3030
|
}
|
|
2999
|
-
|
|
3031
|
+
try {
|
|
3032
|
+
await exec("DROP INDEX IF EXISTS idx_sys_metadata_overlay_draft");
|
|
3033
|
+
} catch {
|
|
3034
|
+
}
|
|
3035
|
+
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
3036
|
try {
|
|
3001
3037
|
await exec(draftPartialSql);
|
|
3002
3038
|
} catch (err) {
|
|
@@ -3004,7 +3040,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3004
3040
|
if (/partial|where clause|syntax/i.test(msg)) {
|
|
3005
3041
|
try {
|
|
3006
3042
|
await exec(
|
|
3007
|
-
"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft ON sys_metadata (type, name, organization_id)"
|
|
3043
|
+
"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft ON sys_metadata (type, name, organization_id, package_id)"
|
|
3008
3044
|
);
|
|
3009
3045
|
} catch {
|
|
3010
3046
|
}
|
|
@@ -3405,7 +3441,8 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3405
3441
|
items.map((it) => {
|
|
3406
3442
|
const a = this.lookupArtifactItem(
|
|
3407
3443
|
request.type,
|
|
3408
|
-
it?.name
|
|
3444
|
+
it?.name,
|
|
3445
|
+
packageId ?? it?._packageId
|
|
3409
3446
|
);
|
|
3410
3447
|
return mergeArtifactProtection(it, a);
|
|
3411
3448
|
})
|
|
@@ -3419,16 +3456,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3419
3456
|
if (request.previewDrafts && readState !== "draft") {
|
|
3420
3457
|
try {
|
|
3421
3458
|
const findDraft = async (oid) => {
|
|
3422
|
-
const
|
|
3423
|
-
|
|
3424
|
-
|
|
3459
|
+
const lookup = async (t) => {
|
|
3460
|
+
const base = {
|
|
3461
|
+
type: t,
|
|
3462
|
+
name: request.name,
|
|
3463
|
+
state: "draft",
|
|
3464
|
+
organization_id: oid
|
|
3465
|
+
};
|
|
3466
|
+
if (request.packageId) {
|
|
3467
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3468
|
+
where: { ...base, package_id: request.packageId }
|
|
3469
|
+
});
|
|
3470
|
+
if (scoped) return scoped;
|
|
3471
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3472
|
+
where: { ...base, package_id: null }
|
|
3473
|
+
});
|
|
3474
|
+
}
|
|
3475
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3476
|
+
};
|
|
3477
|
+
const rec = await lookup(request.type);
|
|
3425
3478
|
if (rec) return rec;
|
|
3426
3479
|
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
|
-
}
|
|
3480
|
+
if (alt) return await lookup(alt);
|
|
3432
3481
|
return void 0;
|
|
3433
3482
|
};
|
|
3434
3483
|
const draftRec = (orgId ? await findDraft(orgId) : void 0) ?? await findDraft(null);
|
|
@@ -3446,24 +3495,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3446
3495
|
}
|
|
3447
3496
|
try {
|
|
3448
3497
|
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,
|
|
3498
|
+
const lookup = async (t) => {
|
|
3499
|
+
const base = {
|
|
3500
|
+
type: t,
|
|
3461
3501
|
name: request.name,
|
|
3462
3502
|
state: readState,
|
|
3463
3503
|
organization_id: oid
|
|
3464
3504
|
};
|
|
3465
|
-
|
|
3466
|
-
|
|
3505
|
+
if (request.packageId) {
|
|
3506
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3507
|
+
where: { ...base, package_id: request.packageId }
|
|
3508
|
+
});
|
|
3509
|
+
if (scoped) return scoped;
|
|
3510
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3511
|
+
where: { ...base, package_id: null }
|
|
3512
|
+
});
|
|
3513
|
+
}
|
|
3514
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3515
|
+
};
|
|
3516
|
+
const rec = await lookup(request.type);
|
|
3517
|
+
if (rec) return rec;
|
|
3518
|
+
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3519
|
+
if (alt) return await lookup(alt);
|
|
3467
3520
|
return void 0;
|
|
3468
3521
|
};
|
|
3469
3522
|
const record = (orgId ? await findOverlay(orgId) : void 0) ?? await findOverlay(null);
|
|
@@ -3492,13 +3545,13 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3492
3545
|
const services = this.getServicesRegistry?.();
|
|
3493
3546
|
const metadataService = services?.get("metadata");
|
|
3494
3547
|
if (metadataService && typeof metadataService.get === "function") {
|
|
3495
|
-
const fromService = await metadataService.get(request.type, request.name);
|
|
3548
|
+
const fromService = await metadataService.get(request.type, request.name, request.packageId);
|
|
3496
3549
|
if (fromService !== void 0 && fromService !== null) {
|
|
3497
3550
|
item = fromService;
|
|
3498
3551
|
} else {
|
|
3499
3552
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3500
3553
|
if (alt) {
|
|
3501
|
-
const altFromService = await metadataService.get(alt, request.name);
|
|
3554
|
+
const altFromService = await metadataService.get(alt, request.name, request.packageId);
|
|
3502
3555
|
if (altFromService !== void 0 && altFromService !== null) {
|
|
3503
3556
|
item = altFromService;
|
|
3504
3557
|
}
|
|
@@ -3509,16 +3562,16 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3509
3562
|
}
|
|
3510
3563
|
}
|
|
3511
3564
|
if (item === void 0) {
|
|
3512
|
-
item = this.engine.registry.getItem(request.type, request.name);
|
|
3565
|
+
item = this.engine.registry.getItem(request.type, request.name, request.packageId);
|
|
3513
3566
|
if (item === void 0) {
|
|
3514
3567
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3515
|
-
if (alt) item = this.engine.registry.getItem(alt, request.name);
|
|
3568
|
+
if (alt) item = this.engine.registry.getItem(alt, request.name, request.packageId);
|
|
3516
3569
|
}
|
|
3517
3570
|
}
|
|
3518
3571
|
if ((request.type === "app" || request.type === "apps") && item) {
|
|
3519
3572
|
item = this.engine.registry.applyNavContributions(item);
|
|
3520
3573
|
}
|
|
3521
|
-
const artifactItem = this.lookupArtifactItem(request.type, request.name);
|
|
3574
|
+
const artifactItem = this.lookupArtifactItem(request.type, request.name, request.packageId);
|
|
3522
3575
|
let decorated = decorateMetadataItem(
|
|
3523
3576
|
request.type,
|
|
3524
3577
|
mergeArtifactProtection(item, artifactItem)
|
|
@@ -3586,20 +3639,20 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3586
3639
|
const services = this.getServicesRegistry?.();
|
|
3587
3640
|
const metadataService = services?.get("metadata");
|
|
3588
3641
|
if (metadataService && typeof metadataService.get === "function") {
|
|
3589
|
-
let fromService = await metadataService.get(request.type, request.name);
|
|
3642
|
+
let fromService = await metadataService.get(request.type, request.name, request.packageId);
|
|
3590
3643
|
if (fromService === void 0 || fromService === null) {
|
|
3591
3644
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3592
|
-
if (alt) fromService = await metadataService.get(alt, request.name);
|
|
3645
|
+
if (alt) fromService = await metadataService.get(alt, request.name, request.packageId);
|
|
3593
3646
|
}
|
|
3594
3647
|
if (fromService !== void 0 && fromService !== null) code = fromService;
|
|
3595
3648
|
}
|
|
3596
3649
|
} catch {
|
|
3597
3650
|
}
|
|
3598
3651
|
if (code === null) {
|
|
3599
|
-
let regItem = this.lookupArtifactItem(request.type, request.name) ?? this.engine.registry.getItem(request.type, request.name);
|
|
3652
|
+
let regItem = this.lookupArtifactItem(request.type, request.name, request.packageId) ?? this.engine.registry.getItem(request.type, request.name, request.packageId);
|
|
3600
3653
|
if (regItem === void 0) {
|
|
3601
3654
|
const alt = PLURAL_TO_SINGULAR3[request.type] ?? SINGULAR_TO_PLURAL2[request.type];
|
|
3602
|
-
if (alt) regItem = this.engine.registry.getItem(alt, request.name);
|
|
3655
|
+
if (alt) regItem = this.engine.registry.getItem(alt, request.name, request.packageId);
|
|
3603
3656
|
}
|
|
3604
3657
|
if (regItem !== void 0) code = regItem;
|
|
3605
3658
|
}
|
|
@@ -3607,20 +3660,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3607
3660
|
let overlayScope = null;
|
|
3608
3661
|
try {
|
|
3609
3662
|
const findOverlay = async (oid) => {
|
|
3610
|
-
const
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3663
|
+
const lookup = async (t) => {
|
|
3664
|
+
const base = {
|
|
3665
|
+
type: t,
|
|
3666
|
+
name: request.name,
|
|
3667
|
+
state: "active",
|
|
3668
|
+
organization_id: oid
|
|
3669
|
+
};
|
|
3670
|
+
if (request.packageId) {
|
|
3671
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3672
|
+
where: { ...base, package_id: request.packageId }
|
|
3673
|
+
});
|
|
3674
|
+
if (scoped) return scoped;
|
|
3675
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3676
|
+
where: { ...base, package_id: null }
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3679
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3615
3680
|
};
|
|
3616
|
-
let rec = await
|
|
3681
|
+
let rec = await lookup(request.type);
|
|
3617
3682
|
if (!rec) {
|
|
3618
3683
|
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
|
-
}
|
|
3684
|
+
if (alt) rec = await lookup(alt);
|
|
3624
3685
|
}
|
|
3625
3686
|
return rec;
|
|
3626
3687
|
};
|
|
@@ -4652,15 +4713,15 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
4652
4713
|
* type and its singular/plural twin. Returns `undefined` when the
|
|
4653
4714
|
* registry is unavailable or the item is not artifact-backed.
|
|
4654
4715
|
*/
|
|
4655
|
-
lookupArtifactItem(type, name) {
|
|
4716
|
+
lookupArtifactItem(type, name, currentPackageId) {
|
|
4656
4717
|
const registry = this.engine?.registry;
|
|
4657
4718
|
if (!registry) return void 0;
|
|
4658
4719
|
const singular = PLURAL_TO_SINGULAR3[type] ?? type;
|
|
4659
4720
|
if (typeof registry.getArtifactItem === "function") {
|
|
4660
|
-
return registry.getArtifactItem(singular, name) ?? registry.getArtifactItem(type, name);
|
|
4721
|
+
return registry.getArtifactItem(singular, name, currentPackageId) ?? registry.getArtifactItem(type, name, currentPackageId);
|
|
4661
4722
|
}
|
|
4662
4723
|
if (typeof registry.getItem !== "function") return void 0;
|
|
4663
|
-
const item = registry.getItem(singular, name) ?? registry.getItem(type, name);
|
|
4724
|
+
const item = registry.getItem(singular, name, currentPackageId) ?? registry.getItem(type, name, currentPackageId);
|
|
4664
4725
|
if (!item || !item._packageId || item._packageId === "sys_metadata") {
|
|
4665
4726
|
return void 0;
|
|
4666
4727
|
}
|
|
@@ -5026,7 +5087,10 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
5026
5087
|
if (request.parentVersion !== void 0) {
|
|
5027
5088
|
parentVersion = request.parentVersion;
|
|
5028
5089
|
} else {
|
|
5029
|
-
const current = await repo.get(ref, {
|
|
5090
|
+
const current = await repo.get(ref, {
|
|
5091
|
+
state: mode === "draft" ? "draft" : "active",
|
|
5092
|
+
packageId: request.packageId ?? null
|
|
5093
|
+
});
|
|
5030
5094
|
parentVersion = current?.hash ?? null;
|
|
5031
5095
|
}
|
|
5032
5096
|
try {
|
|
@@ -9448,10 +9512,16 @@ var MetadataFacade = class {
|
|
|
9448
9512
|
}
|
|
9449
9513
|
}
|
|
9450
9514
|
/**
|
|
9451
|
-
* Get a metadata item by type and name
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9515
|
+
* Get a metadata item by type and name.
|
|
9516
|
+
*
|
|
9517
|
+
* `currentPackageId` (ADR-0048) opts into package-scoped resolution: when two
|
|
9518
|
+
* installed packages ship an item of the same `type`/`name`, the registry
|
|
9519
|
+
* prefers the one owned by `currentPackageId` (composite key
|
|
9520
|
+
* `${packageId}:${name}`) before falling back to first-match. Omit it for the
|
|
9521
|
+
* legacy context-free lookup.
|
|
9522
|
+
*/
|
|
9523
|
+
async get(type, name, currentPackageId) {
|
|
9524
|
+
const item = this.registry.getItem(type, name, currentPackageId);
|
|
9455
9525
|
return item?.content ?? item;
|
|
9456
9526
|
}
|
|
9457
9527
|
/**
|
|
@@ -9530,6 +9600,7 @@ var ObjectQLPlugin = class {
|
|
|
9530
9600
|
*/
|
|
9531
9601
|
this.startupTimeout = 12e4;
|
|
9532
9602
|
this.skipSchemaSync = false;
|
|
9603
|
+
this.hydrateMetadataFromDb = false;
|
|
9533
9604
|
/** Unsubscribe handles for metadata-event subscriptions (ADR-0008 PR-7). */
|
|
9534
9605
|
this.metadataUnsubscribes = [];
|
|
9535
9606
|
this.init = async (ctx) => {
|
|
@@ -9654,7 +9725,7 @@ var ObjectQLPlugin = class {
|
|
|
9654
9725
|
} else {
|
|
9655
9726
|
await this.syncRegisteredSchemas(ctx);
|
|
9656
9727
|
}
|
|
9657
|
-
if (this.environmentId === void 0) {
|
|
9728
|
+
if (this.environmentId === void 0 || this.hydrateMetadataFromDb) {
|
|
9658
9729
|
await this.restoreMetadataFromDb(ctx);
|
|
9659
9730
|
} else {
|
|
9660
9731
|
ctx.logger.info("Project kernel \u2014 skipping sys_metadata hydration (metadata sourced from artifact)");
|
|
@@ -9696,6 +9767,7 @@ var ObjectQLPlugin = class {
|
|
|
9696
9767
|
this.startupTimeout = opts.startupTimeout;
|
|
9697
9768
|
}
|
|
9698
9769
|
this.skipSchemaSync = typeof opts.skipSchemaSync === "boolean" ? opts.skipSchemaSync : process.env.OS_SKIP_SCHEMA_SYNC === "1";
|
|
9770
|
+
this.hydrateMetadataFromDb = opts.hydrateMetadataFromDb === true;
|
|
9699
9771
|
}
|
|
9700
9772
|
/**
|
|
9701
9773
|
* Subscribe to `object` metadata events from the metadata service and
|