@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.js
CHANGED
|
@@ -332,6 +332,19 @@ var init_seed_loader = __esm({
|
|
|
332
332
|
if (records && records.length > 0) {
|
|
333
333
|
return String(records[0].id || records[0]._id);
|
|
334
334
|
}
|
|
335
|
+
if (targetField !== "id") {
|
|
336
|
+
const byId = { id: value };
|
|
337
|
+
if (organizationId) byId.organization_id = organizationId;
|
|
338
|
+
const idMatch = await this.engine.find(targetObject, {
|
|
339
|
+
where: byId,
|
|
340
|
+
fields: ["id"],
|
|
341
|
+
limit: 1,
|
|
342
|
+
context: { isSystem: true }
|
|
343
|
+
});
|
|
344
|
+
if (idMatch && idMatch.length > 0) {
|
|
345
|
+
return String(idMatch[0].id || idMatch[0]._id);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
335
348
|
} catch {
|
|
336
349
|
}
|
|
337
350
|
return null;
|
|
@@ -950,18 +963,16 @@ function applySystemFields(schema, opts) {
|
|
|
950
963
|
fields: { ...additions, ...schema.fields ?? {} }
|
|
951
964
|
};
|
|
952
965
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
return typeof pkg === "string" && pkg.length > 0 && pkg !== SYS_METADATA_OWNER;
|
|
966
|
+
function isShareableNamespace(ns) {
|
|
967
|
+
return RESERVED_NAMESPACES.has(ns) || ns === "sys";
|
|
956
968
|
}
|
|
957
|
-
var
|
|
958
|
-
constructor(
|
|
969
|
+
var NamespaceConflictError = class extends Error {
|
|
970
|
+
constructor(namespace, existingPackageId, incomingPackageId) {
|
|
959
971
|
super(
|
|
960
|
-
`
|
|
972
|
+
`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.`
|
|
961
973
|
);
|
|
962
|
-
this.name = "
|
|
963
|
-
this.
|
|
964
|
-
this.name_ = name;
|
|
974
|
+
this.name = "NamespaceConflictError";
|
|
975
|
+
this.namespace = namespace;
|
|
965
976
|
this.existingPackageId = existingPackageId;
|
|
966
977
|
this.incomingPackageId = incomingPackageId;
|
|
967
978
|
}
|
|
@@ -1317,17 +1328,6 @@ var SchemaRegistry = class {
|
|
|
1317
1328
|
if (collection.has(storageKey)) {
|
|
1318
1329
|
this.log(`[Registry] Overwriting ${type}: ${storageKey}`);
|
|
1319
1330
|
}
|
|
1320
|
-
if (isRealPackage(packageId)) {
|
|
1321
|
-
const conflictOwner = this.findOtherPackageOwner(collection, baseName, packageId);
|
|
1322
|
-
if (conflictOwner) {
|
|
1323
|
-
const err = new MetadataCollisionError(type, baseName, conflictOwner, packageId);
|
|
1324
|
-
if (this.collisionPolicy === "warn") {
|
|
1325
|
-
console.warn(`[Registry] ${err.message}`);
|
|
1326
|
-
} else {
|
|
1327
|
-
throw err;
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
1331
|
if (packageId && collection.has(baseName)) {
|
|
1332
1332
|
const dbOnly = collection.get(baseName);
|
|
1333
1333
|
if (dbOnly && !dbOnly._packageId) {
|
|
@@ -1339,22 +1339,6 @@ var SchemaRegistry = class {
|
|
|
1339
1339
|
collection.set(storageKey, item);
|
|
1340
1340
|
this.log(`[Registry] Registered ${type}: ${storageKey}`);
|
|
1341
1341
|
}
|
|
1342
|
-
/**
|
|
1343
|
-
* Find a code package OTHER than `incoming` that already owns `baseName` in
|
|
1344
|
-
* `collection` (ADR-0048 cross-package collision detection). Scans the live
|
|
1345
|
-
* collection — like {@link getItem} / {@link unregisterItem} — so it always
|
|
1346
|
-
* reflects current state with no parallel index to drift across
|
|
1347
|
-
* reset/unregister. Returns the conflicting owner's package id, or undefined
|
|
1348
|
-
* when the name is free or only held by the same package / a runtime overlay.
|
|
1349
|
-
*/
|
|
1350
|
-
findOtherPackageOwner(collection, baseName, incoming) {
|
|
1351
|
-
for (const [key, item] of collection) {
|
|
1352
|
-
if (key !== baseName && !key.endsWith(`:${baseName}`)) continue;
|
|
1353
|
-
const owner = item?._packageId;
|
|
1354
|
-
if (isRealPackage(owner) && owner !== incoming) return owner;
|
|
1355
|
-
}
|
|
1356
|
-
return void 0;
|
|
1357
|
-
}
|
|
1358
1342
|
/**
|
|
1359
1343
|
* Validate Metadata against Spec Zod Schemas
|
|
1360
1344
|
*/
|
|
@@ -1397,9 +1381,23 @@ var SchemaRegistry = class {
|
|
|
1397
1381
|
console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);
|
|
1398
1382
|
}
|
|
1399
1383
|
/**
|
|
1400
|
-
* Universal Get Method
|
|
1384
|
+
* Universal Get Method.
|
|
1385
|
+
*
|
|
1386
|
+
* ADR-0048 §3.3 — *package-scoped* resolution. When `currentPackageId` is
|
|
1387
|
+
* given (the package the caller is resolving within — known from the route /
|
|
1388
|
+
* `activeApp._packageId`), a bare name resolves to *that package's* item
|
|
1389
|
+
* before any cross-package fallback, so two packages shipping e.g.
|
|
1390
|
+
* `page/home` no longer resolve by registration order (first-match-wins).
|
|
1391
|
+
* Because package ids are globally unique this is unambiguous. Omitting
|
|
1392
|
+
* `currentPackageId` preserves the legacy resolution exactly (backward
|
|
1393
|
+
* compatible) and is best-effort: it returns the first match.
|
|
1394
|
+
*
|
|
1395
|
+
* Precedence (highest first):
|
|
1396
|
+
* 1. bare-key runtime/DB overlay (ADR-0005 sanctioned override) — unchanged
|
|
1397
|
+
* 2. the `currentPackageId` composite entry (prefer-local)
|
|
1398
|
+
* 3. first composite match (legacy first-registered-wins fallback)
|
|
1401
1399
|
*/
|
|
1402
|
-
getItem(type, name) {
|
|
1400
|
+
getItem(type, name, currentPackageId) {
|
|
1403
1401
|
if (type === "object" || type === "objects") {
|
|
1404
1402
|
return this.getObject(name);
|
|
1405
1403
|
}
|
|
@@ -1407,6 +1405,10 @@ var SchemaRegistry = class {
|
|
|
1407
1405
|
if (!collection) return void 0;
|
|
1408
1406
|
const direct = collection.get(name);
|
|
1409
1407
|
if (direct) return direct;
|
|
1408
|
+
if (currentPackageId) {
|
|
1409
|
+
const local = collection.get(`${currentPackageId}:${name}`);
|
|
1410
|
+
if (local) return local;
|
|
1411
|
+
}
|
|
1410
1412
|
for (const [key, item] of collection) {
|
|
1411
1413
|
if (key.endsWith(`:${name}`)) {
|
|
1412
1414
|
return item;
|
|
@@ -1428,13 +1430,17 @@ var SchemaRegistry = class {
|
|
|
1428
1430
|
* it (that masking is exactly the "registry pollution" bug where a
|
|
1429
1431
|
* locked app's `_lock` read back as undefined after a PUT+GET).
|
|
1430
1432
|
*/
|
|
1431
|
-
getArtifactItem(type, name) {
|
|
1433
|
+
getArtifactItem(type, name, currentPackageId) {
|
|
1432
1434
|
if (type === "object" || type === "objects") {
|
|
1433
1435
|
const obj = this.getObject(name);
|
|
1434
1436
|
return obj && obj._packageId && obj._packageId !== "sys_metadata" ? obj : void 0;
|
|
1435
1437
|
}
|
|
1436
1438
|
const collection = this.metadata.get(type);
|
|
1437
1439
|
if (!collection) return void 0;
|
|
1440
|
+
if (currentPackageId) {
|
|
1441
|
+
const local = collection.get(`${currentPackageId}:${name}`);
|
|
1442
|
+
if (local && local._packageId && local._packageId !== "sys_metadata") return local;
|
|
1443
|
+
}
|
|
1438
1444
|
for (const [key, item] of collection) {
|
|
1439
1445
|
if (key !== name && key.endsWith(`:${name}`)) {
|
|
1440
1446
|
const it = item;
|
|
@@ -1518,6 +1524,20 @@ var SchemaRegistry = class {
|
|
|
1518
1524
|
// Package Management
|
|
1519
1525
|
// ==========================================
|
|
1520
1526
|
installPackage(manifest, settings) {
|
|
1527
|
+
if (manifest.namespace && !isShareableNamespace(manifest.namespace)) {
|
|
1528
|
+
const conflictOwner = this.getNamespaceOwners(manifest.namespace).find(
|
|
1529
|
+
(owner) => owner !== manifest.id
|
|
1530
|
+
);
|
|
1531
|
+
if (conflictOwner) {
|
|
1532
|
+
if (this.collisionPolicy === "warn") {
|
|
1533
|
+
console.warn(
|
|
1534
|
+
`[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.`
|
|
1535
|
+
);
|
|
1536
|
+
} else {
|
|
1537
|
+
throw new NamespaceConflictError(manifest.namespace, conflictOwner, manifest.id);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1521
1541
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1522
1542
|
const disabled = this.initialDisabledPackageIds.has(manifest.id);
|
|
1523
1543
|
const pkg = {
|
|
@@ -1595,8 +1615,8 @@ var SchemaRegistry = class {
|
|
|
1595
1615
|
registerApp(app, packageId) {
|
|
1596
1616
|
this.registerItem("app", app, "name", packageId);
|
|
1597
1617
|
}
|
|
1598
|
-
getApp(name) {
|
|
1599
|
-
const app = this.getItem("app", name);
|
|
1618
|
+
getApp(name, currentPackageId) {
|
|
1619
|
+
const app = this.getItem("app", name, currentPackageId);
|
|
1600
1620
|
if (!app) return app;
|
|
1601
1621
|
return this.applyNavContributions(app);
|
|
1602
1622
|
}
|
|
@@ -1816,7 +1836,7 @@ var SysMetadataRepository = class {
|
|
|
1816
1836
|
this.assertOpen();
|
|
1817
1837
|
const state = opts?.state ?? "active";
|
|
1818
1838
|
const row = await this.engine.findOne("sys_metadata", {
|
|
1819
|
-
where: this.whereFor(ref, state)
|
|
1839
|
+
where: this.whereFor(ref, state, opts && "packageId" in opts ? opts.packageId ?? null : void 0)
|
|
1820
1840
|
});
|
|
1821
1841
|
if (!row) return null;
|
|
1822
1842
|
return this.rowToItem(ref, row);
|
|
@@ -1865,7 +1885,7 @@ var SysMetadataRepository = class {
|
|
|
1865
1885
|
const hash = (0, import_metadata_core.hashSpec)(body);
|
|
1866
1886
|
const result = await this.withTxn(async (ctx) => {
|
|
1867
1887
|
const existing = await this.engine.findOne("sys_metadata", {
|
|
1868
|
-
where: this.whereFor(ref, state),
|
|
1888
|
+
where: this.whereFor(ref, state, opts.packageId ?? null),
|
|
1869
1889
|
context: ctx
|
|
1870
1890
|
});
|
|
1871
1891
|
const existingHash = existing?.checksum ?? null;
|
|
@@ -2069,8 +2089,10 @@ var SysMetadataRepository = class {
|
|
|
2069
2089
|
*/
|
|
2070
2090
|
async promoteDraft(ref, opts) {
|
|
2071
2091
|
this.assertOpen();
|
|
2072
|
-
const
|
|
2073
|
-
|
|
2092
|
+
const draftRow = await this.engine.findOne("sys_metadata", {
|
|
2093
|
+
where: this.whereFor(ref, "draft")
|
|
2094
|
+
});
|
|
2095
|
+
if (!draftRow) {
|
|
2074
2096
|
const err = new Error(
|
|
2075
2097
|
`[no_draft] No pending draft exists for ${ref.type}/${ref.name} \u2014 nothing to publish.`
|
|
2076
2098
|
);
|
|
@@ -2078,7 +2100,9 @@ var SysMetadataRepository = class {
|
|
|
2078
2100
|
err.status = 404;
|
|
2079
2101
|
throw err;
|
|
2080
2102
|
}
|
|
2081
|
-
const
|
|
2103
|
+
const draftPackageId = draftRow.package_id ?? null;
|
|
2104
|
+
const draft = this.rowToItem(ref, draftRow);
|
|
2105
|
+
const currentActive = await this.get(ref, { state: "active", packageId: draftPackageId });
|
|
2082
2106
|
const result = await this.put(ref, draft.body, {
|
|
2083
2107
|
parentVersion: currentActive?.hash ?? null,
|
|
2084
2108
|
actor: opts.actor,
|
|
@@ -2086,7 +2110,8 @@ var SysMetadataRepository = class {
|
|
|
2086
2110
|
message: opts.message ?? `publish draft (hash ${draft.hash})`,
|
|
2087
2111
|
intent: opts.intent ?? "override-artifact",
|
|
2088
2112
|
state: "active",
|
|
2089
|
-
opType: "publish"
|
|
2113
|
+
opType: "publish",
|
|
2114
|
+
packageId: draftPackageId
|
|
2090
2115
|
});
|
|
2091
2116
|
try {
|
|
2092
2117
|
await this.delete(ref, {
|
|
@@ -2179,10 +2204,15 @@ var SysMetadataRepository = class {
|
|
|
2179
2204
|
*/
|
|
2180
2205
|
async listDrafts(filter) {
|
|
2181
2206
|
this.assertOpen();
|
|
2182
|
-
const where = {
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2207
|
+
const where = { state: "draft" };
|
|
2208
|
+
if (this.organizationId != null) {
|
|
2209
|
+
where.$or = [
|
|
2210
|
+
{ organization_id: this.organizationId },
|
|
2211
|
+
{ organization_id: null }
|
|
2212
|
+
];
|
|
2213
|
+
} else {
|
|
2214
|
+
where.organization_id = null;
|
|
2215
|
+
}
|
|
2186
2216
|
if (filter?.type) where.type = filter.type;
|
|
2187
2217
|
if (filter?.packageId) where.package_id = filter.packageId;
|
|
2188
2218
|
const rows = await this.engine.find("sys_metadata", { where });
|
|
@@ -2349,13 +2379,15 @@ var SysMetadataRepository = class {
|
|
|
2349
2379
|
err.status = 403;
|
|
2350
2380
|
throw err;
|
|
2351
2381
|
}
|
|
2352
|
-
whereFor(ref, state = "active") {
|
|
2353
|
-
|
|
2382
|
+
whereFor(ref, state = "active", packageId) {
|
|
2383
|
+
const where = {
|
|
2354
2384
|
type: ref.type,
|
|
2355
2385
|
name: ref.name,
|
|
2356
2386
|
organization_id: this.organizationId,
|
|
2357
2387
|
state
|
|
2358
2388
|
};
|
|
2389
|
+
if (packageId !== void 0) where.package_id = packageId;
|
|
2390
|
+
return where;
|
|
2359
2391
|
}
|
|
2360
2392
|
fullRef(ref) {
|
|
2361
2393
|
return {
|
|
@@ -3042,8 +3074,8 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3042
3074
|
await exec("DROP INDEX IF EXISTS idx_sys_metadata_overlay_active");
|
|
3043
3075
|
} catch {
|
|
3044
3076
|
}
|
|
3045
|
-
const partialSql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id) WHERE state = 'active'";
|
|
3046
|
-
const fallbackSql = "CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id)";
|
|
3077
|
+
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'";
|
|
3078
|
+
const fallbackSql = "CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_active ON sys_metadata (type, name, organization_id, package_id)";
|
|
3047
3079
|
try {
|
|
3048
3080
|
await exec(partialSql);
|
|
3049
3081
|
} catch (err) {
|
|
@@ -3055,7 +3087,11 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3055
3087
|
}
|
|
3056
3088
|
}
|
|
3057
3089
|
}
|
|
3058
|
-
|
|
3090
|
+
try {
|
|
3091
|
+
await exec("DROP INDEX IF EXISTS idx_sys_metadata_overlay_draft");
|
|
3092
|
+
} catch {
|
|
3093
|
+
}
|
|
3094
|
+
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'";
|
|
3059
3095
|
try {
|
|
3060
3096
|
await exec(draftPartialSql);
|
|
3061
3097
|
} catch (err) {
|
|
@@ -3063,7 +3099,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3063
3099
|
if (/partial|where clause|syntax/i.test(msg)) {
|
|
3064
3100
|
try {
|
|
3065
3101
|
await exec(
|
|
3066
|
-
"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft ON sys_metadata (type, name, organization_id)"
|
|
3102
|
+
"CREATE INDEX IF NOT EXISTS idx_sys_metadata_overlay_draft ON sys_metadata (type, name, organization_id, package_id)"
|
|
3067
3103
|
);
|
|
3068
3104
|
} catch {
|
|
3069
3105
|
}
|
|
@@ -3464,7 +3500,8 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3464
3500
|
items.map((it) => {
|
|
3465
3501
|
const a = this.lookupArtifactItem(
|
|
3466
3502
|
request.type,
|
|
3467
|
-
it?.name
|
|
3503
|
+
it?.name,
|
|
3504
|
+
packageId ?? it?._packageId
|
|
3468
3505
|
);
|
|
3469
3506
|
return mergeArtifactProtection(it, a);
|
|
3470
3507
|
})
|
|
@@ -3478,16 +3515,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3478
3515
|
if (request.previewDrafts && readState !== "draft") {
|
|
3479
3516
|
try {
|
|
3480
3517
|
const findDraft = async (oid) => {
|
|
3481
|
-
const
|
|
3482
|
-
|
|
3483
|
-
|
|
3518
|
+
const lookup = async (t) => {
|
|
3519
|
+
const base = {
|
|
3520
|
+
type: t,
|
|
3521
|
+
name: request.name,
|
|
3522
|
+
state: "draft",
|
|
3523
|
+
organization_id: oid
|
|
3524
|
+
};
|
|
3525
|
+
if (request.packageId) {
|
|
3526
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3527
|
+
where: { ...base, package_id: request.packageId }
|
|
3528
|
+
});
|
|
3529
|
+
if (scoped) return scoped;
|
|
3530
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3531
|
+
where: { ...base, package_id: null }
|
|
3532
|
+
});
|
|
3533
|
+
}
|
|
3534
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3535
|
+
};
|
|
3536
|
+
const rec = await lookup(request.type);
|
|
3484
3537
|
if (rec) return rec;
|
|
3485
3538
|
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3486
|
-
if (alt)
|
|
3487
|
-
return await this.engine.findOne("sys_metadata", {
|
|
3488
|
-
where: { type: alt, name: request.name, state: "draft", organization_id: oid }
|
|
3489
|
-
});
|
|
3490
|
-
}
|
|
3539
|
+
if (alt) return await lookup(alt);
|
|
3491
3540
|
return void 0;
|
|
3492
3541
|
};
|
|
3493
3542
|
const draftRec = (orgId ? await findDraft(orgId) : void 0) ?? await findDraft(null);
|
|
@@ -3505,24 +3554,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3505
3554
|
}
|
|
3506
3555
|
try {
|
|
3507
3556
|
const findOverlay = async (oid) => {
|
|
3508
|
-
const
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
state: readState,
|
|
3512
|
-
organization_id: oid
|
|
3513
|
-
};
|
|
3514
|
-
const rec = await this.engine.findOne("sys_metadata", { where });
|
|
3515
|
-
if (rec) return rec;
|
|
3516
|
-
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3517
|
-
if (alt) {
|
|
3518
|
-
const altWhere = {
|
|
3519
|
-
type: alt,
|
|
3557
|
+
const lookup = async (t) => {
|
|
3558
|
+
const base = {
|
|
3559
|
+
type: t,
|
|
3520
3560
|
name: request.name,
|
|
3521
3561
|
state: readState,
|
|
3522
3562
|
organization_id: oid
|
|
3523
3563
|
};
|
|
3524
|
-
|
|
3525
|
-
|
|
3564
|
+
if (request.packageId) {
|
|
3565
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3566
|
+
where: { ...base, package_id: request.packageId }
|
|
3567
|
+
});
|
|
3568
|
+
if (scoped) return scoped;
|
|
3569
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3570
|
+
where: { ...base, package_id: null }
|
|
3571
|
+
});
|
|
3572
|
+
}
|
|
3573
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3574
|
+
};
|
|
3575
|
+
const rec = await lookup(request.type);
|
|
3576
|
+
if (rec) return rec;
|
|
3577
|
+
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3578
|
+
if (alt) return await lookup(alt);
|
|
3526
3579
|
return void 0;
|
|
3527
3580
|
};
|
|
3528
3581
|
const record = (orgId ? await findOverlay(orgId) : void 0) ?? await findOverlay(null);
|
|
@@ -3551,13 +3604,13 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3551
3604
|
const services = this.getServicesRegistry?.();
|
|
3552
3605
|
const metadataService = services?.get("metadata");
|
|
3553
3606
|
if (metadataService && typeof metadataService.get === "function") {
|
|
3554
|
-
const fromService = await metadataService.get(request.type, request.name);
|
|
3607
|
+
const fromService = await metadataService.get(request.type, request.name, request.packageId);
|
|
3555
3608
|
if (fromService !== void 0 && fromService !== null) {
|
|
3556
3609
|
item = fromService;
|
|
3557
3610
|
} else {
|
|
3558
3611
|
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3559
3612
|
if (alt) {
|
|
3560
|
-
const altFromService = await metadataService.get(alt, request.name);
|
|
3613
|
+
const altFromService = await metadataService.get(alt, request.name, request.packageId);
|
|
3561
3614
|
if (altFromService !== void 0 && altFromService !== null) {
|
|
3562
3615
|
item = altFromService;
|
|
3563
3616
|
}
|
|
@@ -3568,16 +3621,16 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3568
3621
|
}
|
|
3569
3622
|
}
|
|
3570
3623
|
if (item === void 0) {
|
|
3571
|
-
item = this.engine.registry.getItem(request.type, request.name);
|
|
3624
|
+
item = this.engine.registry.getItem(request.type, request.name, request.packageId);
|
|
3572
3625
|
if (item === void 0) {
|
|
3573
3626
|
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3574
|
-
if (alt) item = this.engine.registry.getItem(alt, request.name);
|
|
3627
|
+
if (alt) item = this.engine.registry.getItem(alt, request.name, request.packageId);
|
|
3575
3628
|
}
|
|
3576
3629
|
}
|
|
3577
3630
|
if ((request.type === "app" || request.type === "apps") && item) {
|
|
3578
3631
|
item = this.engine.registry.applyNavContributions(item);
|
|
3579
3632
|
}
|
|
3580
|
-
const artifactItem = this.lookupArtifactItem(request.type, request.name);
|
|
3633
|
+
const artifactItem = this.lookupArtifactItem(request.type, request.name, request.packageId);
|
|
3581
3634
|
let decorated = decorateMetadataItem(
|
|
3582
3635
|
request.type,
|
|
3583
3636
|
mergeArtifactProtection(item, artifactItem)
|
|
@@ -3645,20 +3698,20 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3645
3698
|
const services = this.getServicesRegistry?.();
|
|
3646
3699
|
const metadataService = services?.get("metadata");
|
|
3647
3700
|
if (metadataService && typeof metadataService.get === "function") {
|
|
3648
|
-
let fromService = await metadataService.get(request.type, request.name);
|
|
3701
|
+
let fromService = await metadataService.get(request.type, request.name, request.packageId);
|
|
3649
3702
|
if (fromService === void 0 || fromService === null) {
|
|
3650
3703
|
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3651
|
-
if (alt) fromService = await metadataService.get(alt, request.name);
|
|
3704
|
+
if (alt) fromService = await metadataService.get(alt, request.name, request.packageId);
|
|
3652
3705
|
}
|
|
3653
3706
|
if (fromService !== void 0 && fromService !== null) code = fromService;
|
|
3654
3707
|
}
|
|
3655
3708
|
} catch {
|
|
3656
3709
|
}
|
|
3657
3710
|
if (code === null) {
|
|
3658
|
-
let regItem = this.lookupArtifactItem(request.type, request.name) ?? this.engine.registry.getItem(request.type, request.name);
|
|
3711
|
+
let regItem = this.lookupArtifactItem(request.type, request.name, request.packageId) ?? this.engine.registry.getItem(request.type, request.name, request.packageId);
|
|
3659
3712
|
if (regItem === void 0) {
|
|
3660
3713
|
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3661
|
-
if (alt) regItem = this.engine.registry.getItem(alt, request.name);
|
|
3714
|
+
if (alt) regItem = this.engine.registry.getItem(alt, request.name, request.packageId);
|
|
3662
3715
|
}
|
|
3663
3716
|
if (regItem !== void 0) code = regItem;
|
|
3664
3717
|
}
|
|
@@ -3666,20 +3719,28 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3666
3719
|
let overlayScope = null;
|
|
3667
3720
|
try {
|
|
3668
3721
|
const findOverlay = async (oid) => {
|
|
3669
|
-
const
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3722
|
+
const lookup = async (t) => {
|
|
3723
|
+
const base = {
|
|
3724
|
+
type: t,
|
|
3725
|
+
name: request.name,
|
|
3726
|
+
state: "active",
|
|
3727
|
+
organization_id: oid
|
|
3728
|
+
};
|
|
3729
|
+
if (request.packageId) {
|
|
3730
|
+
const scoped = await this.engine.findOne("sys_metadata", {
|
|
3731
|
+
where: { ...base, package_id: request.packageId }
|
|
3732
|
+
});
|
|
3733
|
+
if (scoped) return scoped;
|
|
3734
|
+
return await this.engine.findOne("sys_metadata", {
|
|
3735
|
+
where: { ...base, package_id: null }
|
|
3736
|
+
});
|
|
3737
|
+
}
|
|
3738
|
+
return await this.engine.findOne("sys_metadata", { where: base });
|
|
3674
3739
|
};
|
|
3675
|
-
let rec = await
|
|
3740
|
+
let rec = await lookup(request.type);
|
|
3676
3741
|
if (!rec) {
|
|
3677
3742
|
const alt = import_shared4.PLURAL_TO_SINGULAR[request.type] ?? import_shared4.SINGULAR_TO_PLURAL[request.type];
|
|
3678
|
-
if (alt)
|
|
3679
|
-
rec = await this.engine.findOne("sys_metadata", {
|
|
3680
|
-
where: { ...where, type: alt }
|
|
3681
|
-
});
|
|
3682
|
-
}
|
|
3743
|
+
if (alt) rec = await lookup(alt);
|
|
3683
3744
|
}
|
|
3684
3745
|
return rec;
|
|
3685
3746
|
};
|
|
@@ -4711,15 +4772,15 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
4711
4772
|
* type and its singular/plural twin. Returns `undefined` when the
|
|
4712
4773
|
* registry is unavailable or the item is not artifact-backed.
|
|
4713
4774
|
*/
|
|
4714
|
-
lookupArtifactItem(type, name) {
|
|
4775
|
+
lookupArtifactItem(type, name, currentPackageId) {
|
|
4715
4776
|
const registry = this.engine?.registry;
|
|
4716
4777
|
if (!registry) return void 0;
|
|
4717
4778
|
const singular = import_shared4.PLURAL_TO_SINGULAR[type] ?? type;
|
|
4718
4779
|
if (typeof registry.getArtifactItem === "function") {
|
|
4719
|
-
return registry.getArtifactItem(singular, name) ?? registry.getArtifactItem(type, name);
|
|
4780
|
+
return registry.getArtifactItem(singular, name, currentPackageId) ?? registry.getArtifactItem(type, name, currentPackageId);
|
|
4720
4781
|
}
|
|
4721
4782
|
if (typeof registry.getItem !== "function") return void 0;
|
|
4722
|
-
const item = registry.getItem(singular, name) ?? registry.getItem(type, name);
|
|
4783
|
+
const item = registry.getItem(singular, name, currentPackageId) ?? registry.getItem(type, name, currentPackageId);
|
|
4723
4784
|
if (!item || !item._packageId || item._packageId === "sys_metadata") {
|
|
4724
4785
|
return void 0;
|
|
4725
4786
|
}
|
|
@@ -5085,7 +5146,10 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
5085
5146
|
if (request.parentVersion !== void 0) {
|
|
5086
5147
|
parentVersion = request.parentVersion;
|
|
5087
5148
|
} else {
|
|
5088
|
-
const current = await repo.get(ref, {
|
|
5149
|
+
const current = await repo.get(ref, {
|
|
5150
|
+
state: mode === "draft" ? "draft" : "active",
|
|
5151
|
+
packageId: request.packageId ?? null
|
|
5152
|
+
});
|
|
5089
5153
|
parentVersion = current?.hash ?? null;
|
|
5090
5154
|
}
|
|
5091
5155
|
try {
|
|
@@ -9507,10 +9571,16 @@ var MetadataFacade = class {
|
|
|
9507
9571
|
}
|
|
9508
9572
|
}
|
|
9509
9573
|
/**
|
|
9510
|
-
* Get a metadata item by type and name
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9574
|
+
* Get a metadata item by type and name.
|
|
9575
|
+
*
|
|
9576
|
+
* `currentPackageId` (ADR-0048) opts into package-scoped resolution: when two
|
|
9577
|
+
* installed packages ship an item of the same `type`/`name`, the registry
|
|
9578
|
+
* prefers the one owned by `currentPackageId` (composite key
|
|
9579
|
+
* `${packageId}:${name}`) before falling back to first-match. Omit it for the
|
|
9580
|
+
* legacy context-free lookup.
|
|
9581
|
+
*/
|
|
9582
|
+
async get(type, name, currentPackageId) {
|
|
9583
|
+
const item = this.registry.getItem(type, name, currentPackageId);
|
|
9514
9584
|
return item?.content ?? item;
|
|
9515
9585
|
}
|
|
9516
9586
|
/**
|
|
@@ -9584,6 +9654,7 @@ var ObjectQLPlugin = class {
|
|
|
9584
9654
|
*/
|
|
9585
9655
|
this.startupTimeout = 12e4;
|
|
9586
9656
|
this.skipSchemaSync = false;
|
|
9657
|
+
this.hydrateMetadataFromDb = false;
|
|
9587
9658
|
/** Unsubscribe handles for metadata-event subscriptions (ADR-0008 PR-7). */
|
|
9588
9659
|
this.metadataUnsubscribes = [];
|
|
9589
9660
|
this.init = async (ctx) => {
|
|
@@ -9708,7 +9779,7 @@ var ObjectQLPlugin = class {
|
|
|
9708
9779
|
} else {
|
|
9709
9780
|
await this.syncRegisteredSchemas(ctx);
|
|
9710
9781
|
}
|
|
9711
|
-
if (this.environmentId === void 0) {
|
|
9782
|
+
if (this.environmentId === void 0 || this.hydrateMetadataFromDb) {
|
|
9712
9783
|
await this.restoreMetadataFromDb(ctx);
|
|
9713
9784
|
} else {
|
|
9714
9785
|
ctx.logger.info("Project kernel \u2014 skipping sys_metadata hydration (metadata sourced from artifact)");
|
|
@@ -9750,6 +9821,7 @@ var ObjectQLPlugin = class {
|
|
|
9750
9821
|
this.startupTimeout = opts.startupTimeout;
|
|
9751
9822
|
}
|
|
9752
9823
|
this.skipSchemaSync = typeof opts.skipSchemaSync === "boolean" ? opts.skipSchemaSync : process.env.OS_SKIP_SCHEMA_SYNC === "1";
|
|
9824
|
+
this.hydrateMetadataFromDb = opts.hydrateMetadataFromDb === true;
|
|
9753
9825
|
}
|
|
9754
9826
|
/**
|
|
9755
9827
|
* Subscribe to `object` metadata events from the metadata service and
|