@objectstack/objectql 6.7.0 → 6.8.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/LICENSE +93 -202
- package/README.md +1 -1
- package/dist/index.d.mts +194 -1
- package/dist/index.d.ts +194 -1
- package/dist/index.js +605 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +596 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -672,9 +672,26 @@ var SchemaRegistry = class {
|
|
|
672
672
|
// src/sys-metadata-repository.ts
|
|
673
673
|
var import_metadata_core = require("@objectstack/metadata-core");
|
|
674
674
|
var import_kernel2 = require("@objectstack/spec/kernel");
|
|
675
|
+
var import_shared = require("@objectstack/spec/shared");
|
|
675
676
|
var OVERLAY_ALLOWED_TYPES = new Set(
|
|
676
677
|
import_kernel2.DEFAULT_METADATA_TYPE_REGISTRY.filter((e) => e.allowOrgOverride).map((e) => e.type)
|
|
677
678
|
);
|
|
679
|
+
var _envWritableMetadataTypes = null;
|
|
680
|
+
function envWritableMetadataTypes() {
|
|
681
|
+
if (_envWritableMetadataTypes !== null) return _envWritableMetadataTypes;
|
|
682
|
+
const raw = typeof process !== "undefined" && process?.env?.OBJECTSTACK_METADATA_WRITABLE || "";
|
|
683
|
+
const set = /* @__PURE__ */ new Set();
|
|
684
|
+
for (const tok of raw.split(",")) {
|
|
685
|
+
const t = tok.trim();
|
|
686
|
+
if (!t) continue;
|
|
687
|
+
const singular = import_shared.PLURAL_TO_SINGULAR[t] ?? t;
|
|
688
|
+
set.add(singular);
|
|
689
|
+
const plural = import_shared.SINGULAR_TO_PLURAL[singular];
|
|
690
|
+
if (plural) set.add(plural);
|
|
691
|
+
}
|
|
692
|
+
_envWritableMetadataTypes = set;
|
|
693
|
+
return set;
|
|
694
|
+
}
|
|
678
695
|
var SysMetadataRepository = class {
|
|
679
696
|
constructor(opts) {
|
|
680
697
|
/**
|
|
@@ -1067,14 +1084,21 @@ var SysMetadataRepository = class {
|
|
|
1067
1084
|
if (this.closed) throw new Error("SysMetadataRepository is closed");
|
|
1068
1085
|
}
|
|
1069
1086
|
assertAllowed(type) {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1087
|
+
const singular = import_shared.PLURAL_TO_SINGULAR[type] ?? type;
|
|
1088
|
+
const allowedByRegistry = OVERLAY_ALLOWED_TYPES.has(singular) || OVERLAY_ALLOWED_TYPES.has(type);
|
|
1089
|
+
if (allowedByRegistry) return;
|
|
1090
|
+
const env = envWritableMetadataTypes();
|
|
1091
|
+
if (env.has(singular) || env.has(type)) return;
|
|
1092
|
+
const allowed = [
|
|
1093
|
+
...OVERLAY_ALLOWED_TYPES,
|
|
1094
|
+
...envWritableMetadataTypes()
|
|
1095
|
+
];
|
|
1096
|
+
const err = new Error(
|
|
1097
|
+
`[not_overridable] '${type}' is not allowOrgOverride in the registry. Allowed: ${Array.from(new Set(allowed)).join(", ") || "(none)"}. Set OBJECTSTACK_METADATA_WRITABLE to enable additional types at runtime.`
|
|
1098
|
+
);
|
|
1099
|
+
err.code = "not_overridable";
|
|
1100
|
+
err.status = 403;
|
|
1101
|
+
throw err;
|
|
1078
1102
|
}
|
|
1079
1103
|
whereFor(ref) {
|
|
1080
1104
|
return {
|
|
@@ -1178,12 +1202,170 @@ var SysMetadataRepository = class {
|
|
|
1178
1202
|
// src/protocol.ts
|
|
1179
1203
|
var import_metadata_core2 = require("@objectstack/metadata-core");
|
|
1180
1204
|
var import_data2 = require("@objectstack/spec/data");
|
|
1181
|
-
var
|
|
1205
|
+
var import_shared2 = require("@objectstack/spec/shared");
|
|
1182
1206
|
var import_ui2 = require("@objectstack/spec/ui");
|
|
1207
|
+
var import_identity = require("@objectstack/spec/identity");
|
|
1208
|
+
var import_security = require("@objectstack/spec/security");
|
|
1209
|
+
var import_system = require("@objectstack/spec/system");
|
|
1210
|
+
var import_ai = require("@objectstack/spec/ai");
|
|
1211
|
+
var import_automation = require("@objectstack/spec/automation");
|
|
1183
1212
|
var import_kernel3 = require("@objectstack/spec/kernel");
|
|
1213
|
+
var import_zod = require("zod");
|
|
1214
|
+
var TYPE_TO_SCHEMA = {
|
|
1215
|
+
object: import_data2.ObjectSchema,
|
|
1216
|
+
field: import_data2.FieldSchema,
|
|
1217
|
+
dashboard: import_ui2.DashboardSchema,
|
|
1218
|
+
app: import_ui2.AppSchema,
|
|
1219
|
+
page: import_ui2.PageSchema,
|
|
1220
|
+
report: import_ui2.ReportSchema,
|
|
1221
|
+
action: import_ui2.ActionSchema,
|
|
1222
|
+
role: import_identity.RoleSchema,
|
|
1223
|
+
permission: import_security.PermissionSetSchema,
|
|
1224
|
+
profile: import_security.PermissionSetSchema,
|
|
1225
|
+
email_template: import_system.EmailTemplateSchema,
|
|
1226
|
+
tool: import_ai.ToolSchema,
|
|
1227
|
+
skill: import_ai.SkillSchema,
|
|
1228
|
+
agent: import_ai.AgentSchema,
|
|
1229
|
+
flow: import_automation.FlowSchema,
|
|
1230
|
+
workflow: import_automation.WorkflowRuleSchema,
|
|
1231
|
+
approval: import_automation.ApprovalProcessSchema,
|
|
1232
|
+
hook: import_data2.HookSchema
|
|
1233
|
+
};
|
|
1234
|
+
var TYPE_TO_FORM = {
|
|
1235
|
+
object: import_data2.objectForm,
|
|
1236
|
+
field: import_data2.fieldForm,
|
|
1237
|
+
hook: import_data2.hookForm,
|
|
1238
|
+
report: import_ui2.reportForm,
|
|
1239
|
+
view: import_ui2.viewForm,
|
|
1240
|
+
app: import_ui2.appForm,
|
|
1241
|
+
dashboard: import_ui2.dashboardForm,
|
|
1242
|
+
role: import_identity.roleForm,
|
|
1243
|
+
action: import_ui2.actionForm,
|
|
1244
|
+
page: import_ui2.pageForm,
|
|
1245
|
+
agent: import_ai.agentForm,
|
|
1246
|
+
tool: import_ai.toolForm,
|
|
1247
|
+
skill: import_ai.skillForm,
|
|
1248
|
+
flow: import_automation.flowForm,
|
|
1249
|
+
workflow: import_automation.workflowForm,
|
|
1250
|
+
approval: import_automation.approvalForm,
|
|
1251
|
+
permission: import_security.permissionForm,
|
|
1252
|
+
profile: import_security.permissionForm,
|
|
1253
|
+
email_template: import_system.emailTemplateForm
|
|
1254
|
+
};
|
|
1255
|
+
var _jsonSchemaCache = /* @__PURE__ */ new WeakMap();
|
|
1256
|
+
function toJsonSchemaSafe(schema) {
|
|
1257
|
+
const cached = _jsonSchemaCache.get(schema);
|
|
1258
|
+
if (cached !== void 0) return cached ?? void 0;
|
|
1259
|
+
try {
|
|
1260
|
+
const result = import_zod.z.toJSONSchema(schema, { unrepresentable: "any" });
|
|
1261
|
+
_jsonSchemaCache.set(schema, result);
|
|
1262
|
+
return result;
|
|
1263
|
+
} catch {
|
|
1264
|
+
_jsonSchemaCache.set(schema, null);
|
|
1265
|
+
return void 0;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
var HAND_CRAFTED_SCHEMAS = {
|
|
1269
|
+
object: {
|
|
1270
|
+
type: "object",
|
|
1271
|
+
properties: {
|
|
1272
|
+
name: { type: "string" },
|
|
1273
|
+
label: { type: "string" },
|
|
1274
|
+
pluralLabel: { type: "string" },
|
|
1275
|
+
icon: { type: "string" },
|
|
1276
|
+
description: { type: "string" },
|
|
1277
|
+
tags: { type: "array", items: { type: "string" } },
|
|
1278
|
+
active: { type: "boolean", default: true },
|
|
1279
|
+
isSystem: { type: "boolean", default: false },
|
|
1280
|
+
abstract: { type: "boolean", default: false },
|
|
1281
|
+
datasource: { type: "string" },
|
|
1282
|
+
fields: {
|
|
1283
|
+
type: "array",
|
|
1284
|
+
default: [],
|
|
1285
|
+
items: {
|
|
1286
|
+
type: "object",
|
|
1287
|
+
properties: {
|
|
1288
|
+
name: { type: "string" },
|
|
1289
|
+
label: { type: "string" },
|
|
1290
|
+
type: { type: "string" },
|
|
1291
|
+
required: { type: "boolean", default: false },
|
|
1292
|
+
unique: { type: "boolean", default: false },
|
|
1293
|
+
defaultValue: {},
|
|
1294
|
+
description: { type: "string" }
|
|
1295
|
+
},
|
|
1296
|
+
required: ["name", "type"]
|
|
1297
|
+
}
|
|
1298
|
+
},
|
|
1299
|
+
capabilities: { type: "object", additionalProperties: true }
|
|
1300
|
+
},
|
|
1301
|
+
required: ["name"],
|
|
1302
|
+
additionalProperties: true
|
|
1303
|
+
},
|
|
1304
|
+
action: {
|
|
1305
|
+
type: "object",
|
|
1306
|
+
properties: {
|
|
1307
|
+
name: { type: "string" },
|
|
1308
|
+
label: { type: "string" },
|
|
1309
|
+
objectName: { type: "string" },
|
|
1310
|
+
icon: { type: "string" },
|
|
1311
|
+
type: { type: "string", enum: ["url", "flow", "api", "script"] },
|
|
1312
|
+
variant: { type: "string", enum: ["primary", "secondary", "danger", "ghost", "outline"] },
|
|
1313
|
+
target: { type: "string" },
|
|
1314
|
+
method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"] },
|
|
1315
|
+
body: {
|
|
1316
|
+
type: "array",
|
|
1317
|
+
default: [],
|
|
1318
|
+
items: {
|
|
1319
|
+
type: "object",
|
|
1320
|
+
properties: {
|
|
1321
|
+
line: { type: "string" }
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
},
|
|
1325
|
+
params: {
|
|
1326
|
+
type: "array",
|
|
1327
|
+
default: [],
|
|
1328
|
+
items: {
|
|
1329
|
+
type: "object",
|
|
1330
|
+
properties: {
|
|
1331
|
+
name: { type: "string" },
|
|
1332
|
+
label: { type: "string" },
|
|
1333
|
+
type: { type: "string" },
|
|
1334
|
+
required: { type: "boolean", default: false }
|
|
1335
|
+
},
|
|
1336
|
+
required: ["name"]
|
|
1337
|
+
}
|
|
1338
|
+
},
|
|
1339
|
+
confirmText: { type: "string" },
|
|
1340
|
+
successMessage: { type: "string" },
|
|
1341
|
+
refreshAfter: { type: "boolean", default: true },
|
|
1342
|
+
locations: {
|
|
1343
|
+
type: "array",
|
|
1344
|
+
default: [],
|
|
1345
|
+
items: {
|
|
1346
|
+
type: "object",
|
|
1347
|
+
properties: {
|
|
1348
|
+
location: { type: "string" }
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
},
|
|
1352
|
+
component: { type: "string" },
|
|
1353
|
+
visible: { type: "string" },
|
|
1354
|
+
disabled: { type: "string" },
|
|
1355
|
+
shortcut: { type: "string" },
|
|
1356
|
+
bulkEnabled: { type: "boolean", default: false },
|
|
1357
|
+
aiExposed: { type: "boolean", default: false },
|
|
1358
|
+
recordIdParam: { type: "string" },
|
|
1359
|
+
recordIdField: { type: "string" },
|
|
1360
|
+
bodyShape: { type: "string", enum: ["flat", "nested"] }
|
|
1361
|
+
},
|
|
1362
|
+
required: ["name", "label", "type"],
|
|
1363
|
+
additionalProperties: true
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1184
1366
|
var FORM_VIEW_TYPES = /* @__PURE__ */ new Set(["simple", "tabbed", "wizard", "split", "drawer", "modal"]);
|
|
1185
1367
|
function resolveOverlaySchema(type, item) {
|
|
1186
|
-
const singular =
|
|
1368
|
+
const singular = import_shared2.PLURAL_TO_SINGULAR[type] ?? type;
|
|
1187
1369
|
switch (singular) {
|
|
1188
1370
|
case "view": {
|
|
1189
1371
|
const t = item && typeof item === "object" && "type" in item ? String(item.type) : void 0;
|
|
@@ -1240,6 +1422,140 @@ var SERVICE_CONFIG = {
|
|
|
1240
1422
|
"file-storage": { route: "/api/v1/storage", plugin: "plugin-storage" },
|
|
1241
1423
|
search: { route: "/api/v1/search", plugin: "plugin-search" }
|
|
1242
1424
|
};
|
|
1425
|
+
var REFERENCE_PATHS = {
|
|
1426
|
+
object: [
|
|
1427
|
+
{ fromType: "view", paths: ["object", "objectName"], kind: "view" },
|
|
1428
|
+
{ fromType: "dashboard", paths: ["widgets[].object", "widgets[].objectName"], kind: "dashboard widget" },
|
|
1429
|
+
{ fromType: "flow", paths: ["object", "context.object", "trigger.object", "targetObject"], kind: "flow" },
|
|
1430
|
+
{ fromType: "workflow", paths: ["object", "targetObject"], kind: "workflow" },
|
|
1431
|
+
{ fromType: "permission", paths: ["objects[].name", "objects[].object"], kind: "permission" },
|
|
1432
|
+
{ fromType: "app", paths: ["navItems[].objectName", "navItems[].object", "tabs[].objectName", "tabs[].object"], kind: "app nav" },
|
|
1433
|
+
{ fromType: "page", paths: ["object", "objectName"], kind: "page" },
|
|
1434
|
+
{ fromType: "report", paths: ["object", "objectName"], kind: "report" },
|
|
1435
|
+
{ fromType: "action", paths: ["object", "objectName"], kind: "action" },
|
|
1436
|
+
{ fromType: "validation", paths: ["object", "objectName"], kind: "validation" },
|
|
1437
|
+
{ fromType: "hook", paths: ["object", "objectName"], kind: "hook" },
|
|
1438
|
+
{ fromType: "object", paths: ["fields[].referenceTo", "fields{}.referenceTo", "fields{}.reference"], kind: "field reference" }
|
|
1439
|
+
],
|
|
1440
|
+
view: [
|
|
1441
|
+
{ fromType: "dashboard", paths: ["widgets[].view", "widgets[].viewName"], kind: "dashboard widget" },
|
|
1442
|
+
{ fromType: "app", paths: ["navItems[].viewName", "tabs[].viewName"], kind: "app nav" },
|
|
1443
|
+
{ fromType: "page", paths: ["viewName"], kind: "page" }
|
|
1444
|
+
],
|
|
1445
|
+
tool: [
|
|
1446
|
+
{ fromType: "agent", paths: ["tools[]", "tools[].name"], kind: "agent tool" }
|
|
1447
|
+
],
|
|
1448
|
+
skill: [
|
|
1449
|
+
{ fromType: "agent", paths: ["skills[]", "skills[].name"], kind: "agent skill" }
|
|
1450
|
+
],
|
|
1451
|
+
flow: [
|
|
1452
|
+
{ fromType: "app", paths: ["navItems[].flowName", "tabs[].flowName"], kind: "app nav" }
|
|
1453
|
+
],
|
|
1454
|
+
dashboard: [
|
|
1455
|
+
{ fromType: "app", paths: ["navItems[].dashboardName", "tabs[].dashboardName"], kind: "app nav" }
|
|
1456
|
+
],
|
|
1457
|
+
page: [
|
|
1458
|
+
{ fromType: "app", paths: ["navItems[].pageName", "tabs[].pageName"], kind: "app nav" }
|
|
1459
|
+
]
|
|
1460
|
+
};
|
|
1461
|
+
function extractPathValues(item, path) {
|
|
1462
|
+
if (!item || typeof item !== "object") return [];
|
|
1463
|
+
const segments = path.split(".");
|
|
1464
|
+
let current = [item];
|
|
1465
|
+
for (const rawSeg of segments) {
|
|
1466
|
+
let kind = "value";
|
|
1467
|
+
let seg = rawSeg;
|
|
1468
|
+
if (seg.endsWith("[]")) {
|
|
1469
|
+
kind = "array";
|
|
1470
|
+
seg = seg.slice(0, -2);
|
|
1471
|
+
} else if (seg.endsWith("{}")) {
|
|
1472
|
+
kind = "record";
|
|
1473
|
+
seg = seg.slice(0, -2);
|
|
1474
|
+
}
|
|
1475
|
+
const next = [];
|
|
1476
|
+
for (const node of current) {
|
|
1477
|
+
if (!node || typeof node !== "object") continue;
|
|
1478
|
+
let value;
|
|
1479
|
+
if (seg === "") {
|
|
1480
|
+
value = node;
|
|
1481
|
+
} else {
|
|
1482
|
+
value = node[seg];
|
|
1483
|
+
}
|
|
1484
|
+
if (value === void 0 || value === null) continue;
|
|
1485
|
+
if (kind === "array") {
|
|
1486
|
+
if (Array.isArray(value)) {
|
|
1487
|
+
for (const v of value) next.push(v);
|
|
1488
|
+
}
|
|
1489
|
+
} else if (kind === "record") {
|
|
1490
|
+
if (Array.isArray(value)) {
|
|
1491
|
+
for (const v of value) next.push(v);
|
|
1492
|
+
} else if (typeof value === "object") {
|
|
1493
|
+
for (const v of Object.values(value)) next.push(v);
|
|
1494
|
+
}
|
|
1495
|
+
} else {
|
|
1496
|
+
next.push(value);
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
current = next;
|
|
1500
|
+
if (current.length === 0) return [];
|
|
1501
|
+
}
|
|
1502
|
+
const out = [];
|
|
1503
|
+
for (const v of current) {
|
|
1504
|
+
if (typeof v === "string" && v.length > 0) out.push(v);
|
|
1505
|
+
else if (v && typeof v === "object" && "name" in v && typeof v.name === "string") {
|
|
1506
|
+
out.push(v.name);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
return out;
|
|
1510
|
+
}
|
|
1511
|
+
function detectDestructiveObjectChanges(prev, next) {
|
|
1512
|
+
if (!prev || typeof prev !== "object" || !next || typeof next !== "object") return [];
|
|
1513
|
+
const prevFields = prev.fields && typeof prev.fields === "object" ? prev.fields : {};
|
|
1514
|
+
const nextFields = next.fields && typeof next.fields === "object" ? next.fields : {};
|
|
1515
|
+
const issues = [];
|
|
1516
|
+
for (const fname of Object.keys(prevFields)) {
|
|
1517
|
+
if (prevFields[fname]?.system) continue;
|
|
1518
|
+
if (!(fname in nextFields)) {
|
|
1519
|
+
issues.push({
|
|
1520
|
+
code: "field_removed",
|
|
1521
|
+
field: fname,
|
|
1522
|
+
message: `Field '${fname}' removed \u2014 existing data in this column will become inaccessible.`
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
const TYPE_COMPATIBILITY = {
|
|
1527
|
+
text: /* @__PURE__ */ new Set(["textarea", "markdown", "html", "code"]),
|
|
1528
|
+
number: /* @__PURE__ */ new Set([]),
|
|
1529
|
+
boolean: /* @__PURE__ */ new Set([]),
|
|
1530
|
+
date: /* @__PURE__ */ new Set(["datetime"]),
|
|
1531
|
+
datetime: /* @__PURE__ */ new Set(["date"])
|
|
1532
|
+
};
|
|
1533
|
+
for (const fname of Object.keys(nextFields)) {
|
|
1534
|
+
const prevField = prevFields[fname];
|
|
1535
|
+
const nextField = nextFields[fname];
|
|
1536
|
+
if (!prevField) continue;
|
|
1537
|
+
const prevType = prevField.type;
|
|
1538
|
+
const nextType = nextField.type;
|
|
1539
|
+
if (prevType && nextType && prevType !== nextType) {
|
|
1540
|
+
const compatible = TYPE_COMPATIBILITY[prevType]?.has(nextType);
|
|
1541
|
+
if (!compatible) {
|
|
1542
|
+
issues.push({
|
|
1543
|
+
code: "field_type_change",
|
|
1544
|
+
field: fname,
|
|
1545
|
+
message: `Field '${fname}' type changed from '${prevType}' to '${nextType}' \u2014 existing values may not convert cleanly.`
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
if (!prevField.required && nextField.required && nextField.defaultValue === void 0) {
|
|
1550
|
+
issues.push({
|
|
1551
|
+
code: "field_required_no_default",
|
|
1552
|
+
field: fname,
|
|
1553
|
+
message: `Field '${fname}' is now required but has no default value \u2014 existing rows with null values may fail validation.`
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
return issues;
|
|
1558
|
+
}
|
|
1243
1559
|
var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementation {
|
|
1244
1560
|
constructor(engine, getServicesRegistry, getFeedService, environmentId) {
|
|
1245
1561
|
/**
|
|
@@ -1441,7 +1757,52 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
1441
1757
|
} catch {
|
|
1442
1758
|
}
|
|
1443
1759
|
const allTypes = Array.from(/* @__PURE__ */ new Set([...schemaTypes, ...runtimeTypes]));
|
|
1444
|
-
|
|
1760
|
+
const writableOverrides = _ObjectStackProtocolImplementation.envWritableTypes();
|
|
1761
|
+
const registryByType = new Map(
|
|
1762
|
+
import_kernel3.DEFAULT_METADATA_TYPE_REGISTRY.map((e) => [e.type, e])
|
|
1763
|
+
);
|
|
1764
|
+
const entries = allTypes.map((type) => {
|
|
1765
|
+
const singular = import_shared2.PLURAL_TO_SINGULAR[type] ?? type;
|
|
1766
|
+
const zodSchema = singular === "view" ? import_ui2.ListViewSchema : TYPE_TO_SCHEMA[singular];
|
|
1767
|
+
const schema = (zodSchema ? toJsonSchemaSafe(zodSchema) : void 0) ?? HAND_CRAFTED_SCHEMAS[singular];
|
|
1768
|
+
const form = TYPE_TO_FORM[singular];
|
|
1769
|
+
const base = registryByType.get(singular);
|
|
1770
|
+
if (base) {
|
|
1771
|
+
const isEnvOverridden = writableOverrides.has(singular);
|
|
1772
|
+
return {
|
|
1773
|
+
...base,
|
|
1774
|
+
type: singular,
|
|
1775
|
+
schemaId: singular,
|
|
1776
|
+
// API client expects schemaId field
|
|
1777
|
+
allowOrgOverride: base.allowOrgOverride || isEnvOverridden,
|
|
1778
|
+
overrideSource: isEnvOverridden && !base.allowOrgOverride ? "env" : "registry",
|
|
1779
|
+
schema,
|
|
1780
|
+
form
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
return {
|
|
1784
|
+
type: singular,
|
|
1785
|
+
schemaId: singular,
|
|
1786
|
+
// API client expects schemaId field
|
|
1787
|
+
label: singular,
|
|
1788
|
+
description: void 0,
|
|
1789
|
+
filePatterns: [],
|
|
1790
|
+
supportsOverlay: false,
|
|
1791
|
+
allowOrgOverride: writableOverrides.has(singular),
|
|
1792
|
+
allowRuntimeCreate: true,
|
|
1793
|
+
supportsVersioning: false,
|
|
1794
|
+
executionPinned: false,
|
|
1795
|
+
loadOrder: 1e3,
|
|
1796
|
+
domain: "system",
|
|
1797
|
+
overrideSource: writableOverrides.has(singular) ? "env" : "registry",
|
|
1798
|
+
schema,
|
|
1799
|
+
form
|
|
1800
|
+
};
|
|
1801
|
+
}).sort((a, b) => {
|
|
1802
|
+
if (a.domain !== b.domain) return a.domain.localeCompare(b.domain);
|
|
1803
|
+
return a.type.localeCompare(b.type);
|
|
1804
|
+
});
|
|
1805
|
+
return { types: allTypes, entries };
|
|
1445
1806
|
}
|
|
1446
1807
|
async getMetaItems(request) {
|
|
1447
1808
|
const { packageId } = request;
|
|
@@ -1449,13 +1810,13 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
1449
1810
|
if (this.environmentId === void 0) {
|
|
1450
1811
|
items = [...this.engine.registry.listItems(request.type, packageId)];
|
|
1451
1812
|
if (items.length === 0) {
|
|
1452
|
-
const alt =
|
|
1813
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
1453
1814
|
if (alt) items = [...this.engine.registry.listItems(alt, packageId)];
|
|
1454
1815
|
}
|
|
1455
1816
|
} else {
|
|
1456
1817
|
items = [...this.engine.registry.listItems(request.type, packageId)];
|
|
1457
1818
|
if (items.length === 0) {
|
|
1458
|
-
const alt =
|
|
1819
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
1459
1820
|
if (alt) items = [...this.engine.registry.listItems(alt, packageId)];
|
|
1460
1821
|
}
|
|
1461
1822
|
}
|
|
@@ -1470,7 +1831,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
1470
1831
|
if (packageId) whereClause._packageId = packageId;
|
|
1471
1832
|
let rs = await this.engine.find("sys_metadata", { where: whereClause });
|
|
1472
1833
|
if (!rs || rs.length === 0) {
|
|
1473
|
-
const alt =
|
|
1834
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
1474
1835
|
if (alt) {
|
|
1475
1836
|
const altWhere = { type: alt, state: "active", organization_id: oid };
|
|
1476
1837
|
if (packageId) altWhere._packageId = packageId;
|
|
@@ -1553,7 +1914,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
1553
1914
|
};
|
|
1554
1915
|
const rec = await this.engine.findOne("sys_metadata", { where });
|
|
1555
1916
|
if (rec) return rec;
|
|
1556
|
-
const alt =
|
|
1917
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
1557
1918
|
if (alt) {
|
|
1558
1919
|
const altWhere = {
|
|
1559
1920
|
type: alt,
|
|
@@ -1580,7 +1941,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
1580
1941
|
if (fromService !== void 0 && fromService !== null) {
|
|
1581
1942
|
item = fromService;
|
|
1582
1943
|
} else {
|
|
1583
|
-
const alt =
|
|
1944
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
1584
1945
|
if (alt) {
|
|
1585
1946
|
const altFromService = await metadataService.get(alt, request.name);
|
|
1586
1947
|
if (altFromService !== void 0 && altFromService !== null) {
|
|
@@ -1595,7 +1956,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
1595
1956
|
if (item === void 0) {
|
|
1596
1957
|
item = this.engine.registry.getItem(request.type, request.name);
|
|
1597
1958
|
if (item === void 0) {
|
|
1598
|
-
const alt =
|
|
1959
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
1599
1960
|
if (alt) item = this.engine.registry.getItem(alt, request.name);
|
|
1600
1961
|
}
|
|
1601
1962
|
}
|
|
@@ -1605,6 +1966,91 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
1605
1966
|
item
|
|
1606
1967
|
};
|
|
1607
1968
|
}
|
|
1969
|
+
/**
|
|
1970
|
+
* Phase 3a-layered-get: return the 3 layers of a metadata item
|
|
1971
|
+
* separately — `code` (artifact-loaded baseline), `overlay` (per-org
|
|
1972
|
+
* customisation row, if any), and `effective` (what `getMetaItem`
|
|
1973
|
+
* would return, i.e. overlay-wins merge).
|
|
1974
|
+
*
|
|
1975
|
+
* Drives the "Code default vs Overlay vs Effective" diff tab in the
|
|
1976
|
+
* generic Metadata Resource Edit page. Admins can see exactly what
|
|
1977
|
+
* was customised and reset selectively.
|
|
1978
|
+
*
|
|
1979
|
+
* `code` is null if no artifact baseline exists; `overlay` is null if
|
|
1980
|
+
* no sys_metadata row exists for the requested scope; `effective` is
|
|
1981
|
+
* never null when either layer exists.
|
|
1982
|
+
*/
|
|
1983
|
+
async getMetaItemLayered(request) {
|
|
1984
|
+
const orgId = request.organizationId;
|
|
1985
|
+
let code = null;
|
|
1986
|
+
try {
|
|
1987
|
+
const services = this.getServicesRegistry?.();
|
|
1988
|
+
const metadataService = services?.get("metadata");
|
|
1989
|
+
if (metadataService && typeof metadataService.get === "function") {
|
|
1990
|
+
let fromService = await metadataService.get(request.type, request.name);
|
|
1991
|
+
if (fromService === void 0 || fromService === null) {
|
|
1992
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
1993
|
+
if (alt) fromService = await metadataService.get(alt, request.name);
|
|
1994
|
+
}
|
|
1995
|
+
if (fromService !== void 0 && fromService !== null) code = fromService;
|
|
1996
|
+
}
|
|
1997
|
+
} catch {
|
|
1998
|
+
}
|
|
1999
|
+
if (code === null) {
|
|
2000
|
+
let regItem = this.engine.registry.getItem(request.type, request.name);
|
|
2001
|
+
if (regItem === void 0) {
|
|
2002
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
2003
|
+
if (alt) regItem = this.engine.registry.getItem(alt, request.name);
|
|
2004
|
+
}
|
|
2005
|
+
if (regItem !== void 0) code = regItem;
|
|
2006
|
+
}
|
|
2007
|
+
let overlay = null;
|
|
2008
|
+
let overlayScope = null;
|
|
2009
|
+
try {
|
|
2010
|
+
const findOverlay = async (oid) => {
|
|
2011
|
+
const where = {
|
|
2012
|
+
type: request.type,
|
|
2013
|
+
name: request.name,
|
|
2014
|
+
state: "active",
|
|
2015
|
+
organization_id: oid
|
|
2016
|
+
};
|
|
2017
|
+
let rec = await this.engine.findOne("sys_metadata", { where });
|
|
2018
|
+
if (!rec) {
|
|
2019
|
+
const alt = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? import_shared2.SINGULAR_TO_PLURAL[request.type];
|
|
2020
|
+
if (alt) {
|
|
2021
|
+
rec = await this.engine.findOne("sys_metadata", {
|
|
2022
|
+
where: { ...where, type: alt }
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
return rec;
|
|
2027
|
+
};
|
|
2028
|
+
if (orgId) {
|
|
2029
|
+
const rec = await findOverlay(orgId);
|
|
2030
|
+
if (rec) {
|
|
2031
|
+
overlay = typeof rec.metadata === "string" ? JSON.parse(rec.metadata) : rec.metadata;
|
|
2032
|
+
overlayScope = "org";
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
if (overlay === null) {
|
|
2036
|
+
const rec = await findOverlay(null);
|
|
2037
|
+
if (rec) {
|
|
2038
|
+
overlay = typeof rec.metadata === "string" ? JSON.parse(rec.metadata) : rec.metadata;
|
|
2039
|
+
overlayScope = "env";
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
} catch {
|
|
2043
|
+
}
|
|
2044
|
+
const effective = overlay ?? code;
|
|
2045
|
+
return {
|
|
2046
|
+
type: request.type,
|
|
2047
|
+
name: request.name,
|
|
2048
|
+
code,
|
|
2049
|
+
overlay,
|
|
2050
|
+
overlayScope,
|
|
2051
|
+
effective
|
|
2052
|
+
};
|
|
2053
|
+
}
|
|
1608
2054
|
async getUiView(request) {
|
|
1609
2055
|
const schema = this.engine.registry.getObject(request.object);
|
|
1610
2056
|
if (!schema) throw new Error(`Object ${request.object} not found`);
|
|
@@ -2476,10 +2922,33 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2476
2922
|
...request.options
|
|
2477
2923
|
});
|
|
2478
2924
|
}
|
|
2925
|
+
static envWritableTypes() {
|
|
2926
|
+
if (this._envWritableTypes !== null) return this._envWritableTypes;
|
|
2927
|
+
const raw = typeof process !== "undefined" && process?.env?.OBJECTSTACK_METADATA_WRITABLE || "";
|
|
2928
|
+
const set = /* @__PURE__ */ new Set();
|
|
2929
|
+
for (const tok of raw.split(",")) {
|
|
2930
|
+
const t = tok.trim();
|
|
2931
|
+
if (!t) continue;
|
|
2932
|
+
const singular = import_shared2.PLURAL_TO_SINGULAR[t] ?? t;
|
|
2933
|
+
set.add(singular);
|
|
2934
|
+
const plural = import_shared2.SINGULAR_TO_PLURAL[singular];
|
|
2935
|
+
if (plural) set.add(plural);
|
|
2936
|
+
}
|
|
2937
|
+
this._envWritableTypes = set;
|
|
2938
|
+
return set;
|
|
2939
|
+
}
|
|
2940
|
+
/** Test hook — clear the memoised env-writable cache. */
|
|
2941
|
+
static resetEnvWritableCache() {
|
|
2942
|
+
this._envWritableTypes = null;
|
|
2943
|
+
}
|
|
2479
2944
|
/** Normalize plural→singular before consulting the allow-list. */
|
|
2480
2945
|
static isOverlayAllowed(type) {
|
|
2481
|
-
const singular =
|
|
2482
|
-
|
|
2946
|
+
const singular = import_shared2.PLURAL_TO_SINGULAR[type] ?? type;
|
|
2947
|
+
if (this.OVERLAY_ALLOWED_TYPES.has(singular) || this.OVERLAY_ALLOWED_TYPES.has(type)) {
|
|
2948
|
+
return true;
|
|
2949
|
+
}
|
|
2950
|
+
const env = this.envWritableTypes();
|
|
2951
|
+
return env.has(singular) || env.has(type);
|
|
2483
2952
|
}
|
|
2484
2953
|
/**
|
|
2485
2954
|
* Mirror an object-type overlay write into the in-memory engine
|
|
@@ -2509,12 +2978,38 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2509
2978
|
if (this.environmentId !== void 0 && !_ObjectStackProtocolImplementation.isOverlayAllowed(request.type)) {
|
|
2510
2979
|
const allowed = Array.from(_ObjectStackProtocolImplementation.OVERLAY_ALLOWED_TYPES).join(", ");
|
|
2511
2980
|
const err = new Error(
|
|
2512
|
-
`[not_overridable] Metadata type '${request.type}' has not opted into per-org overlay writes. Set allowOrgOverride: true on its DEFAULT_METADATA_TYPE_REGISTRY entry to enable. Currently allowed: ${allowed}. See docs/adr/0005-metadata-customization-overlay.md.`
|
|
2981
|
+
`[not_overridable] Metadata type '${request.type}' has not opted into per-org overlay writes. Set allowOrgOverride: true on its DEFAULT_METADATA_TYPE_REGISTRY entry to enable, or set the OBJECTSTACK_METADATA_WRITABLE env var (comma-separated singular type names) to opt in at runtime. Currently allowed: ${allowed}. See docs/adr/0005-metadata-customization-overlay.md.`
|
|
2513
2982
|
);
|
|
2514
2983
|
err.code = "not_overridable";
|
|
2515
2984
|
err.status = 403;
|
|
2516
2985
|
throw err;
|
|
2517
2986
|
}
|
|
2987
|
+
const singularType = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? request.type;
|
|
2988
|
+
if (!request.force && (singularType === "object" || singularType === "field")) {
|
|
2989
|
+
try {
|
|
2990
|
+
const existing = await this.getMetaItem({
|
|
2991
|
+
type: request.type,
|
|
2992
|
+
name: request.name,
|
|
2993
|
+
...request.organizationId ? { organizationId: request.organizationId } : {}
|
|
2994
|
+
});
|
|
2995
|
+
const prev = existing?.item;
|
|
2996
|
+
if (prev) {
|
|
2997
|
+
const issues = detectDestructiveObjectChanges(prev, request.item);
|
|
2998
|
+
if (issues.length > 0) {
|
|
2999
|
+
const summary = issues.slice(0, 3).map((i) => i.message).join("; ");
|
|
3000
|
+
const err = new Error(
|
|
3001
|
+
`[destructive_change] ${request.type}/${request.name} would drop or transform existing data: ${summary}` + (issues.length > 3 ? ` (+${issues.length - 3} more)` : "") + ` \u2014 re-submit with ?force=true to proceed.`
|
|
3002
|
+
);
|
|
3003
|
+
err.code = "destructive_change";
|
|
3004
|
+
err.status = 409;
|
|
3005
|
+
err.issues = issues;
|
|
3006
|
+
throw err;
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
} catch (err) {
|
|
3010
|
+
if (err?.code === "destructive_change") throw err;
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
2518
3013
|
{
|
|
2519
3014
|
const schema = resolveOverlaySchema(request.type, request.item);
|
|
2520
3015
|
if (schema) {
|
|
@@ -2537,7 +3032,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2537
3032
|
}
|
|
2538
3033
|
}
|
|
2539
3034
|
await this.ensureOverlayIndex();
|
|
2540
|
-
const singularTypeForRepo =
|
|
3035
|
+
const singularTypeForRepo = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? request.type;
|
|
2541
3036
|
if (_ObjectStackProtocolImplementation.isOverlayAllowed(singularTypeForRepo)) {
|
|
2542
3037
|
const orgId = request.organizationId ?? null;
|
|
2543
3038
|
const repo = this.getOverlayRepo(orgId);
|
|
@@ -2648,7 +3143,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2648
3143
|
* "no history" uniformly.
|
|
2649
3144
|
*/
|
|
2650
3145
|
async historyMetaItem(request) {
|
|
2651
|
-
const singularType =
|
|
3146
|
+
const singularType = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? request.type;
|
|
2652
3147
|
if (!_ObjectStackProtocolImplementation.isOverlayAllowed(singularType)) {
|
|
2653
3148
|
return { events: [] };
|
|
2654
3149
|
}
|
|
@@ -2681,7 +3176,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2681
3176
|
err.status = 403;
|
|
2682
3177
|
throw err;
|
|
2683
3178
|
}
|
|
2684
|
-
const singularTypeForRepo =
|
|
3179
|
+
const singularTypeForRepo = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? request.type;
|
|
2685
3180
|
const useRepoPath = _ObjectStackProtocolImplementation.isOverlayAllowed(singularTypeForRepo);
|
|
2686
3181
|
if (useRepoPath) {
|
|
2687
3182
|
const orgId = request.organizationId ?? null;
|
|
@@ -2801,7 +3296,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2801
3296
|
for (const record of records) {
|
|
2802
3297
|
try {
|
|
2803
3298
|
const data = typeof record.metadata === "string" ? JSON.parse(record.metadata) : record.metadata;
|
|
2804
|
-
const normalizedType =
|
|
3299
|
+
const normalizedType = import_shared2.PLURAL_TO_SINGULAR[record.type] ?? record.type;
|
|
2805
3300
|
if (normalizedType === "object") {
|
|
2806
3301
|
this.engine.registry.registerObject(data, record.packageId || "sys_metadata");
|
|
2807
3302
|
} else {
|
|
@@ -2821,6 +3316,68 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2821
3316
|
return { loaded, errors };
|
|
2822
3317
|
}
|
|
2823
3318
|
// ==========================================
|
|
3319
|
+
// Metadata References (Phase 3a-references)
|
|
3320
|
+
// ==========================================
|
|
3321
|
+
/**
|
|
3322
|
+
* Scan all loaded metadata for references pointing at the given
|
|
3323
|
+
* `{type, name}` target. Returns one row per referring artifact with
|
|
3324
|
+
* the path that produced the hit, so the admin UI can render an
|
|
3325
|
+
* "Used by" panel before destructive actions (rename / delete /
|
|
3326
|
+
* type-narrowing).
|
|
3327
|
+
*
|
|
3328
|
+
* Coverage is driven by the hand-curated {@link REFERENCE_PATHS}
|
|
3329
|
+
* registry. Types not present in the registry simply return no hits
|
|
3330
|
+
* — the engine never throws.
|
|
3331
|
+
*/
|
|
3332
|
+
async findReferencesToMeta(request) {
|
|
3333
|
+
const singularTarget = import_shared2.PLURAL_TO_SINGULAR[request.type] ?? request.type;
|
|
3334
|
+
const targetName = request.name;
|
|
3335
|
+
const matchers = REFERENCE_PATHS[singularTarget];
|
|
3336
|
+
if (!matchers || matchers.length === 0) {
|
|
3337
|
+
return { references: [] };
|
|
3338
|
+
}
|
|
3339
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3340
|
+
const out = [];
|
|
3341
|
+
await Promise.all(
|
|
3342
|
+
matchers.map(async (matcher) => {
|
|
3343
|
+
let items = [];
|
|
3344
|
+
try {
|
|
3345
|
+
const result = await this.getMetaItems({
|
|
3346
|
+
type: matcher.fromType,
|
|
3347
|
+
...request.organizationId ? { organizationId: request.organizationId } : {}
|
|
3348
|
+
});
|
|
3349
|
+
items = result?.items ?? [];
|
|
3350
|
+
} catch {
|
|
3351
|
+
return;
|
|
3352
|
+
}
|
|
3353
|
+
for (const raw of items) {
|
|
3354
|
+
if (!raw || typeof raw !== "object") continue;
|
|
3355
|
+
const sourceName = raw.name;
|
|
3356
|
+
if (!sourceName) continue;
|
|
3357
|
+
const isSelfReference = matcher.fromType === singularTarget && sourceName === targetName;
|
|
3358
|
+
for (const path of matcher.paths) {
|
|
3359
|
+
const values = extractPathValues(raw, path);
|
|
3360
|
+
if (!values.includes(targetName)) continue;
|
|
3361
|
+
if (isSelfReference && !path.includes("[]") && !path.includes("{}")) continue;
|
|
3362
|
+
const key = `${matcher.fromType}|${sourceName}|${path}`;
|
|
3363
|
+
if (seen.has(key)) continue;
|
|
3364
|
+
seen.add(key);
|
|
3365
|
+
const label = raw.label;
|
|
3366
|
+
out.push({
|
|
3367
|
+
type: matcher.fromType,
|
|
3368
|
+
name: sourceName,
|
|
3369
|
+
...label ? { label } : {},
|
|
3370
|
+
path,
|
|
3371
|
+
kind: matcher.kind
|
|
3372
|
+
});
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
})
|
|
3376
|
+
);
|
|
3377
|
+
out.sort((a, b) => a.type.localeCompare(b.type) || a.name.localeCompare(b.name));
|
|
3378
|
+
return { references: out };
|
|
3379
|
+
}
|
|
3380
|
+
// ==========================================
|
|
2824
3381
|
// Feed Operations
|
|
2825
3382
|
// ==========================================
|
|
2826
3383
|
async listFeed(request) {
|
|
@@ -2967,18 +3524,30 @@ _ObjectStackProtocolImplementation.OVERLAY_ALLOWED_TYPES = (() => {
|
|
|
2967
3524
|
for (const entry of import_kernel3.DEFAULT_METADATA_TYPE_REGISTRY) {
|
|
2968
3525
|
if (!entry.allowOrgOverride) continue;
|
|
2969
3526
|
out.add(entry.type);
|
|
2970
|
-
const plural =
|
|
3527
|
+
const plural = import_shared2.SINGULAR_TO_PLURAL[entry.type];
|
|
2971
3528
|
if (plural) out.add(plural);
|
|
2972
3529
|
}
|
|
2973
3530
|
return out;
|
|
2974
3531
|
})();
|
|
3532
|
+
/**
|
|
3533
|
+
* Phase 3a-env-writable: parse `OBJECTSTACK_METADATA_WRITABLE` once.
|
|
3534
|
+
* Comma-separated singular type names. When the env var is set, the
|
|
3535
|
+
* listed types get treated as `allowOrgOverride: true` regardless of
|
|
3536
|
+
* their static registry entry. This is the runtime escape hatch admins
|
|
3537
|
+
* use to enable Studio-side editing of types whose protocol-level flag
|
|
3538
|
+
* is still false (object, field, permission, …).
|
|
3539
|
+
*
|
|
3540
|
+
* Memoised at first call. Tests can override by clearing the cache via
|
|
3541
|
+
* {@link ObjectStackProtocolImplementation.resetEnvWritableCache}.
|
|
3542
|
+
*/
|
|
3543
|
+
_ObjectStackProtocolImplementation._envWritableTypes = null;
|
|
2975
3544
|
var ObjectStackProtocolImplementation = _ObjectStackProtocolImplementation;
|
|
2976
3545
|
|
|
2977
3546
|
// src/engine.ts
|
|
2978
3547
|
var import_kernel4 = require("@objectstack/spec/kernel");
|
|
2979
3548
|
var import_core = require("@objectstack/core");
|
|
2980
|
-
var
|
|
2981
|
-
var
|
|
3549
|
+
var import_system2 = require("@objectstack/spec/system");
|
|
3550
|
+
var import_shared3 = require("@objectstack/spec/shared");
|
|
2982
3551
|
var import_formula2 = require("@objectstack/formula");
|
|
2983
3552
|
|
|
2984
3553
|
// src/hook-wrappers.ts
|
|
@@ -3780,7 +4349,7 @@ var _ObjectQL = class _ObjectQL {
|
|
|
3780
4349
|
*/
|
|
3781
4350
|
getStatus() {
|
|
3782
4351
|
return {
|
|
3783
|
-
name:
|
|
4352
|
+
name: import_system2.CoreServiceName.enum.data,
|
|
3784
4353
|
status: "running",
|
|
3785
4354
|
version: "0.9.0",
|
|
3786
4355
|
features: ["crud", "query", "aggregate", "transactions", "metadata"]
|
|
@@ -4248,9 +4817,9 @@ var _ObjectQL = class _ObjectQL {
|
|
|
4248
4817
|
const itemName = resolveMetadataItemName(key, item);
|
|
4249
4818
|
if (itemName) {
|
|
4250
4819
|
const toRegister = item.name === itemName ? item : { ...item, name: itemName };
|
|
4251
|
-
this._registry.registerItem((0,
|
|
4820
|
+
this._registry.registerItem((0, import_shared3.pluralToSingular)(key), toRegister, "name", id);
|
|
4252
4821
|
} else {
|
|
4253
|
-
this.logger.warn(`Skipping ${(0,
|
|
4822
|
+
this.logger.warn(`Skipping ${(0, import_shared3.pluralToSingular)(key)} without a derivable name`, { id });
|
|
4254
4823
|
}
|
|
4255
4824
|
}
|
|
4256
4825
|
}
|
|
@@ -4377,7 +4946,7 @@ var _ObjectQL = class _ObjectQL {
|
|
|
4377
4946
|
const itemName = resolveMetadataItemName(key, item);
|
|
4378
4947
|
if (itemName) {
|
|
4379
4948
|
const toRegister = item.name === itemName ? item : { ...item, name: itemName };
|
|
4380
|
-
this._registry.registerItem((0,
|
|
4949
|
+
this._registry.registerItem((0, import_shared3.pluralToSingular)(key), toRegister, "name", ownerId);
|
|
4381
4950
|
}
|
|
4382
4951
|
}
|
|
4383
4952
|
}
|
|
@@ -4427,9 +4996,9 @@ var _ObjectQL = class _ObjectQL {
|
|
|
4427
4996
|
resolveObjectName(name) {
|
|
4428
4997
|
const schema = this._registry.getObject(name);
|
|
4429
4998
|
if (schema) {
|
|
4430
|
-
return
|
|
4999
|
+
return import_system2.StorageNameMapping.resolveTableName(schema);
|
|
4431
5000
|
}
|
|
4432
|
-
return
|
|
5001
|
+
return import_system2.StorageNameMapping.resolveTableName({ name });
|
|
4433
5002
|
}
|
|
4434
5003
|
/**
|
|
4435
5004
|
* Helper to get the target driver
|
|
@@ -5199,7 +5768,7 @@ var _ObjectQL = class _ObjectQL {
|
|
|
5199
5768
|
for (const obj of allObjects) {
|
|
5200
5769
|
const driver = this.getDriverForObject(obj.name);
|
|
5201
5770
|
if (!driver) continue;
|
|
5202
|
-
const tableName =
|
|
5771
|
+
const tableName = import_system2.StorageNameMapping.resolveTableName(obj);
|
|
5203
5772
|
if (typeof driver.syncSchemasBatch === "function" && driver.supports?.batchSchemaSync) {
|
|
5204
5773
|
}
|
|
5205
5774
|
if (typeof driver.syncSchema === "function") {
|
|
@@ -5535,7 +6104,7 @@ var MetadataFacade = class {
|
|
|
5535
6104
|
};
|
|
5536
6105
|
|
|
5537
6106
|
// src/plugin.ts
|
|
5538
|
-
var
|
|
6107
|
+
var import_system3 = require("@objectstack/spec/system");
|
|
5539
6108
|
function hasLoadMetaFromDb(service) {
|
|
5540
6109
|
return typeof service === "object" && service !== null && typeof service["loadMetaFromDb"] === "function";
|
|
5541
6110
|
}
|
|
@@ -5925,7 +6494,7 @@ var ObjectQLPlugin = class {
|
|
|
5925
6494
|
skipped++;
|
|
5926
6495
|
continue;
|
|
5927
6496
|
}
|
|
5928
|
-
const tableName =
|
|
6497
|
+
const tableName = import_system3.StorageNameMapping.resolveTableName(obj);
|
|
5929
6498
|
let group = driverGroups.get(driver);
|
|
5930
6499
|
if (!group) {
|
|
5931
6500
|
group = [];
|