@coasys/ad4m-connect 0.13.0-postmessage-ws-proxy.0 → 0.13.0-postmessage-ws-proxy.2
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/PostMessageWebSocket.d.ts +5 -1
- package/dist/core.js +239 -262
- package/dist/core.js.map +3 -3
- package/dist/index.js +257 -280
- package/dist/index.js.map +3 -3
- package/dist/web.js +206 -271
- package/dist/web.js.map +3 -3
- package/package.json +16 -16
package/dist/index.js
CHANGED
|
@@ -120,21 +120,26 @@ function getHue(str) {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
// src/PostMessageWebSocket.ts
|
|
123
|
-
var
|
|
124
|
-
constructor(_url) {
|
|
123
|
+
var _PostMessageWebSocket = class {
|
|
124
|
+
constructor(_url, targetOrigin) {
|
|
125
125
|
this.readyState = 0;
|
|
126
126
|
this.onopen = null;
|
|
127
127
|
this.onmessage = null;
|
|
128
128
|
this.onerror = null;
|
|
129
129
|
this.onclose = null;
|
|
130
|
+
this._connectTimeout = null;
|
|
131
|
+
this._targetOrigin = targetOrigin;
|
|
130
132
|
this._messageHandler = (e7) => {
|
|
131
|
-
var _a, _b, _c, _d;
|
|
133
|
+
var _a, _b, _c, _d, _e;
|
|
132
134
|
if (e7.source !== window.parent)
|
|
133
135
|
return;
|
|
136
|
+
if (e7.origin !== this._targetOrigin)
|
|
137
|
+
return;
|
|
134
138
|
const msg = e7.data;
|
|
135
139
|
if (!msg || typeof msg.type !== "string")
|
|
136
140
|
return;
|
|
137
141
|
if (msg.type === "AD4M_PROXY_WS_OPEN") {
|
|
142
|
+
this._clearConnectTimeout();
|
|
138
143
|
this.readyState = 1;
|
|
139
144
|
(_a = this.onopen) == null ? void 0 : _a.call(this, new Event("open"));
|
|
140
145
|
return;
|
|
@@ -144,12 +149,17 @@ var PostMessageWebSocket = class {
|
|
|
144
149
|
return;
|
|
145
150
|
}
|
|
146
151
|
if (msg.type === "AD4M_PROXY_WS_ERROR") {
|
|
152
|
+
this._clearConnectTimeout();
|
|
153
|
+
this.readyState = _PostMessageWebSocket.CLOSED;
|
|
154
|
+
window.removeEventListener("message", this._messageHandler);
|
|
147
155
|
(_c = this.onerror) == null ? void 0 : _c.call(this, new Event("error"));
|
|
156
|
+
(_d = this.onclose) == null ? void 0 : _d.call(this, new CloseEvent("close", { code: 1006, reason: "WebSocket error", wasClean: false }));
|
|
148
157
|
return;
|
|
149
158
|
}
|
|
150
159
|
if (msg.type === "AD4M_PROXY_WS_CLOSED") {
|
|
160
|
+
this._clearConnectTimeout();
|
|
151
161
|
this.readyState = 3;
|
|
152
|
-
(
|
|
162
|
+
(_e = this.onclose) == null ? void 0 : _e.call(
|
|
153
163
|
this,
|
|
154
164
|
new CloseEvent("close", {
|
|
155
165
|
code: typeof msg.code === "number" ? msg.code : 1e3,
|
|
@@ -161,21 +171,37 @@ var PostMessageWebSocket = class {
|
|
|
161
171
|
}
|
|
162
172
|
};
|
|
163
173
|
window.addEventListener("message", this._messageHandler);
|
|
164
|
-
window.parent.postMessage({ type: "AD4M_PROXY_WS_CONNECT" },
|
|
174
|
+
window.parent.postMessage({ type: "AD4M_PROXY_WS_CONNECT" }, this._targetOrigin);
|
|
175
|
+
this._connectTimeout = setTimeout(() => {
|
|
176
|
+
var _a, _b;
|
|
177
|
+
this._connectTimeout = null;
|
|
178
|
+
window.removeEventListener("message", this._messageHandler);
|
|
179
|
+
this.readyState = 3;
|
|
180
|
+
(_a = this.onerror) == null ? void 0 : _a.call(this, new Event("error"));
|
|
181
|
+
(_b = this.onclose) == null ? void 0 : _b.call(this, new CloseEvent("close", { code: 1006, reason: "Connection timeout", wasClean: false }));
|
|
182
|
+
}, _PostMessageWebSocket.CONNECT_TIMEOUT_MS);
|
|
183
|
+
}
|
|
184
|
+
_clearConnectTimeout() {
|
|
185
|
+
if (this._connectTimeout !== null) {
|
|
186
|
+
clearTimeout(this._connectTimeout);
|
|
187
|
+
this._connectTimeout = null;
|
|
188
|
+
}
|
|
165
189
|
}
|
|
166
190
|
send(data) {
|
|
167
|
-
window.parent.postMessage({ type: "AD4M_PROXY_WS_SEND", data },
|
|
191
|
+
window.parent.postMessage({ type: "AD4M_PROXY_WS_SEND", data }, this._targetOrigin);
|
|
168
192
|
}
|
|
169
193
|
close(code2, reason) {
|
|
170
194
|
this.readyState = 2;
|
|
171
|
-
window.parent.postMessage({ type: "AD4M_PROXY_WS_CLOSE", code: code2, reason },
|
|
195
|
+
window.parent.postMessage({ type: "AD4M_PROXY_WS_CLOSE", code: code2, reason }, this._targetOrigin);
|
|
172
196
|
window.removeEventListener("message", this._messageHandler);
|
|
173
197
|
}
|
|
174
198
|
};
|
|
199
|
+
var PostMessageWebSocket = _PostMessageWebSocket;
|
|
175
200
|
PostMessageWebSocket.CONNECTING = 0;
|
|
176
201
|
PostMessageWebSocket.OPEN = 1;
|
|
177
202
|
PostMessageWebSocket.CLOSING = 2;
|
|
178
203
|
PostMessageWebSocket.CLOSED = 3;
|
|
204
|
+
PostMessageWebSocket.CONNECT_TIMEOUT_MS = 3e4;
|
|
179
205
|
|
|
180
206
|
// ../core/lib/index.js
|
|
181
207
|
var RpcError = class extends Error {
|
|
@@ -1171,6 +1197,41 @@ var SHACLShape = class {
|
|
|
1171
1197
|
target: `literal:string:${JSON.stringify(prop.in)}`
|
|
1172
1198
|
});
|
|
1173
1199
|
}
|
|
1200
|
+
if (prop.relationKind) {
|
|
1201
|
+
links.push({
|
|
1202
|
+
source: propShapeId,
|
|
1203
|
+
predicate: "ad4m://relationKind",
|
|
1204
|
+
target: `literal:string:${prop.relationKind}`
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
if (prop.targetClassName) {
|
|
1208
|
+
links.push({
|
|
1209
|
+
source: propShapeId,
|
|
1210
|
+
predicate: "ad4m://targetClassName",
|
|
1211
|
+
target: `literal:string:${prop.targetClassName}`
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
if (prop.whereFilter !== void 0 && prop.whereFilter !== null) {
|
|
1215
|
+
links.push({
|
|
1216
|
+
source: propShapeId,
|
|
1217
|
+
predicate: "ad4m://whereFilter",
|
|
1218
|
+
target: `literal:string:${JSON.stringify(prop.whereFilter)}`
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
if (prop.wherePredicates && Object.keys(prop.wherePredicates).length > 0) {
|
|
1222
|
+
links.push({
|
|
1223
|
+
source: propShapeId,
|
|
1224
|
+
predicate: "ad4m://wherePredicates",
|
|
1225
|
+
target: `literal:string:${JSON.stringify(prop.wherePredicates)}`
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
if (prop.filter !== void 0) {
|
|
1229
|
+
links.push({
|
|
1230
|
+
source: propShapeId,
|
|
1231
|
+
predicate: "ad4m://filter",
|
|
1232
|
+
target: `literal:${prop.filter}`
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1174
1235
|
}
|
|
1175
1236
|
return links;
|
|
1176
1237
|
}
|
|
@@ -1319,6 +1380,40 @@ var SHACLShape = class {
|
|
|
1319
1380
|
} catch (e7) {
|
|
1320
1381
|
}
|
|
1321
1382
|
}
|
|
1383
|
+
const relationKindLink = links.find((l5) => l5.source === propShapeId && l5.predicate === "ad4m://relationKind");
|
|
1384
|
+
if (relationKindLink) {
|
|
1385
|
+
const val = relationKindLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
|
|
1386
|
+
if (val === "hasMany" || val === "hasOne" || val === "belongsToOne" || val === "belongsToMany") {
|
|
1387
|
+
prop.relationKind = val;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
const targetClassNameLink = links.find((l5) => l5.source === propShapeId && l5.predicate === "ad4m://targetClassName");
|
|
1391
|
+
if (targetClassNameLink) {
|
|
1392
|
+
prop.targetClassName = targetClassNameLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
|
|
1393
|
+
}
|
|
1394
|
+
const whereFilterLink = links.find((l5) => l5.source === propShapeId && l5.predicate === "ad4m://whereFilter");
|
|
1395
|
+
if (whereFilterLink) {
|
|
1396
|
+
try {
|
|
1397
|
+
const jsonStr = whereFilterLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
|
|
1398
|
+
prop.whereFilter = JSON.parse(jsonStr);
|
|
1399
|
+
} catch (e7) {
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
const wherePredicatesLink = links.find((l5) => l5.source === propShapeId && l5.predicate === "ad4m://wherePredicates");
|
|
1403
|
+
if (wherePredicatesLink) {
|
|
1404
|
+
try {
|
|
1405
|
+
const jsonStr = wherePredicatesLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
|
|
1406
|
+
prop.wherePredicates = JSON.parse(jsonStr);
|
|
1407
|
+
} catch (e7) {
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
const filterLink = links.find((l5) => l5.source === propShapeId && l5.predicate === "ad4m://filter");
|
|
1411
|
+
if (filterLink) {
|
|
1412
|
+
let val = filterLink.target.replace(/^literal:\/\/|^literal:/, "");
|
|
1413
|
+
if (val.startsWith("boolean:"))
|
|
1414
|
+
val = val.substring(8);
|
|
1415
|
+
prop.filter = val === "true";
|
|
1416
|
+
}
|
|
1322
1417
|
shape.addProperty(prop);
|
|
1323
1418
|
}
|
|
1324
1419
|
return shape;
|
|
@@ -1348,7 +1443,12 @@ var SHACLShape = class {
|
|
|
1348
1443
|
getter: p2.getter,
|
|
1349
1444
|
conformance_conditions: p2.conformanceConditions,
|
|
1350
1445
|
class: p2.class,
|
|
1351
|
-
in: p2.in
|
|
1446
|
+
in: p2.in,
|
|
1447
|
+
relation_kind: p2.relationKind,
|
|
1448
|
+
target_class_name: p2.targetClassName,
|
|
1449
|
+
where_filter: p2.whereFilter,
|
|
1450
|
+
where_predicates: p2.wherePredicates,
|
|
1451
|
+
filter: p2.filter
|
|
1352
1452
|
})),
|
|
1353
1453
|
constructor_actions: this.constructor_actions,
|
|
1354
1454
|
destructor_actions: this.destructor_actions
|
|
@@ -1377,7 +1477,12 @@ var SHACLShape = class {
|
|
|
1377
1477
|
getter: p2.getter,
|
|
1378
1478
|
conformanceConditions: p2.conformance_conditions,
|
|
1379
1479
|
class: p2.class,
|
|
1380
|
-
in: p2.in
|
|
1480
|
+
in: p2.in,
|
|
1481
|
+
relationKind: p2.relation_kind,
|
|
1482
|
+
targetClassName: p2.target_class_name,
|
|
1483
|
+
whereFilter: p2.where_filter,
|
|
1484
|
+
wherePredicates: p2.where_predicates,
|
|
1485
|
+
filter: p2.filter
|
|
1381
1486
|
});
|
|
1382
1487
|
}
|
|
1383
1488
|
if (json.constructor_actions) {
|
|
@@ -1394,114 +1499,9 @@ var SHACLShape = class {
|
|
|
1394
1499
|
return shape;
|
|
1395
1500
|
}
|
|
1396
1501
|
};
|
|
1397
|
-
function formatList(list) {
|
|
1398
|
-
if (!list?.length) {
|
|
1399
|
-
return "";
|
|
1400
|
-
}
|
|
1401
|
-
if (list.length === 1) {
|
|
1402
|
-
return list.toString();
|
|
1403
|
-
}
|
|
1404
|
-
if (list.length === 2) {
|
|
1405
|
-
return list.join(" and ");
|
|
1406
|
-
}
|
|
1407
|
-
return list.slice(0, -1).join(", ") + ", and " + list.slice(-1);
|
|
1408
|
-
}
|
|
1409
|
-
function capSentence(cap) {
|
|
1410
|
-
const can = cap.can.includes("*") ? ["READ", "WRITE", "UPDATE"] : cap.can;
|
|
1411
|
-
const domain = cap.with.domain === "*" ? "" : cap.with.domain;
|
|
1412
|
-
const pointers = cap.with.pointers.includes("*") ? ["all AD4M data"] : cap.with.pointers;
|
|
1413
|
-
return `${formatList(can)} your ${domain} actions, with access to ${formatList(pointers)}`;
|
|
1414
|
-
}
|
|
1415
|
-
function escapeQueryString(value) {
|
|
1416
|
-
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
1417
|
-
}
|
|
1418
|
-
function buildWhereCondition(predicate, condition, opts) {
|
|
1419
|
-
const escapedPredicate = escapeQueryString(predicate);
|
|
1420
|
-
const isLiteral = !opts?.resolveLanguage || opts.resolveLanguage === "literal";
|
|
1421
|
-
const varSuffix = opts?.varIndex ?? 0;
|
|
1422
|
-
function formatValue(v2) {
|
|
1423
|
-
if (typeof v2 === "string") {
|
|
1424
|
-
return isLiteral ? `<literal:string:${escapeQueryString(v2)}>` : `<${escapeQueryString(v2)}>`;
|
|
1425
|
-
}
|
|
1426
|
-
return `<literal:string:${v2}>`;
|
|
1427
|
-
}
|
|
1428
|
-
function formatLiteralFilter(varName, v2) {
|
|
1429
|
-
const raw = escapeQueryString(String(v2));
|
|
1430
|
-
const encoded = encodeURIComponent(String(v2)).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A");
|
|
1431
|
-
if (typeof v2 === "string") {
|
|
1432
|
-
return `FILTER(STR(${varName}) = "${raw}" || STR(${varName}) = "literal:string:${encoded}")`;
|
|
1433
|
-
} else if (typeof v2 === "number") {
|
|
1434
|
-
return `FILTER(STR(${varName}) = "${v2}" || STR(${varName}) = "literal:number:${v2}")`;
|
|
1435
|
-
} else if (typeof v2 === "boolean") {
|
|
1436
|
-
return `FILTER(STR(${varName}) = "${v2}" || STR(${varName}) = "literal:boolean:${v2}")`;
|
|
1437
|
-
}
|
|
1438
|
-
return `FILTER(STR(${varName}) = "${raw}")`;
|
|
1439
|
-
}
|
|
1440
|
-
if (Array.isArray(condition)) {
|
|
1441
|
-
if (isLiteral) {
|
|
1442
|
-
const varName = `?_wc${varSuffix}`;
|
|
1443
|
-
const inValues = condition.flatMap((v2) => {
|
|
1444
|
-
const raw = escapeQueryString(String(v2));
|
|
1445
|
-
const encoded = encodeURIComponent(String(v2)).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A");
|
|
1446
|
-
return [`"${raw}"`, `"literal:string:${encoded}"`];
|
|
1447
|
-
}).join(", ");
|
|
1448
|
-
return `?target <${escapedPredicate}> ${varName} . FILTER(STR(${varName}) IN (${inValues}))`;
|
|
1449
|
-
}
|
|
1450
|
-
const formattedValues = condition.map(formatValue).join(", ");
|
|
1451
|
-
return `FILTER EXISTS { ?target <${escapedPredicate}> ?_val . FILTER(?_val IN (${formattedValues})) }`;
|
|
1452
|
-
} else if (typeof condition === "object" && condition !== null) {
|
|
1453
|
-
const ops = condition;
|
|
1454
|
-
const parts = [];
|
|
1455
|
-
if (ops.not !== void 0) {
|
|
1456
|
-
if (Array.isArray(ops.not)) {
|
|
1457
|
-
const formattedValues = ops.not.map((v2) => formatValue(v2)).join(", ");
|
|
1458
|
-
parts.push(`FILTER NOT EXISTS { ?target <${escapedPredicate}> ?_nval . FILTER(?_nval IN (${formattedValues})) }`);
|
|
1459
|
-
} else {
|
|
1460
|
-
parts.push(`FILTER NOT EXISTS { ?target <${escapedPredicate}> ${formatValue(ops.not)} }`);
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
const hasComparisonOps = ops.gt !== void 0 || ops.gte !== void 0 || ops.lt !== void 0 || ops.lte !== void 0 || ops.between !== void 0 || ops.contains !== void 0;
|
|
1464
|
-
if (hasComparisonOps) {
|
|
1465
|
-
parts.push(`FILTER EXISTS { ?target <${escapedPredicate}> ?_cmp }`);
|
|
1466
|
-
}
|
|
1467
|
-
return parts.join(" ");
|
|
1468
|
-
} else {
|
|
1469
|
-
if (isLiteral) {
|
|
1470
|
-
const varName = `?_wc${varSuffix}`;
|
|
1471
|
-
return `?target <${escapedPredicate}> ${varName} . ${formatLiteralFilter(varName, condition)}`;
|
|
1472
|
-
}
|
|
1473
|
-
return `?target <${escapedPredicate}> ${formatValue(condition)} .`;
|
|
1474
|
-
}
|
|
1475
|
-
}
|
|
1476
|
-
function compileWhereClause(where, metadata) {
|
|
1477
|
-
const conditions = [];
|
|
1478
|
-
for (const [propertyName, condition] of Object.entries(where)) {
|
|
1479
|
-
if (["id", "author", "timestamp"].includes(propertyName))
|
|
1480
|
-
continue;
|
|
1481
|
-
let predicate;
|
|
1482
|
-
let resolveLanguage;
|
|
1483
|
-
if (metadata) {
|
|
1484
|
-
const propMeta = metadata.properties[propertyName];
|
|
1485
|
-
if (propMeta) {
|
|
1486
|
-
predicate = propMeta.predicate;
|
|
1487
|
-
resolveLanguage = propMeta.resolveLanguage;
|
|
1488
|
-
} else {
|
|
1489
|
-
predicate = propertyName;
|
|
1490
|
-
}
|
|
1491
|
-
} else {
|
|
1492
|
-
predicate = propertyName;
|
|
1493
|
-
}
|
|
1494
|
-
const cond = buildWhereCondition(predicate, condition, { resolveLanguage, varIndex: conditions.length });
|
|
1495
|
-
if (cond) {
|
|
1496
|
-
conditions.push(cond);
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
return conditions;
|
|
1500
|
-
}
|
|
1501
1502
|
function buildSHACL(subjectName, target, properties, allRelationsMeta, conformanceFilterFn) {
|
|
1502
1503
|
const obj = target.prototype;
|
|
1503
1504
|
let namespace = "ad4m://";
|
|
1504
|
-
const relations = Object.fromEntries(Object.entries(allRelationsMeta).filter(([, r4]) => r4.kind === "hasMany" || r4.kind === "belongsToMany"));
|
|
1505
1505
|
if (Object.keys(properties).length > 0) {
|
|
1506
1506
|
const firstProp = properties[Object.keys(properties)[0]];
|
|
1507
1507
|
if (firstProp.through) {
|
|
@@ -1510,8 +1510,8 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
|
|
|
1510
1510
|
namespace = match[1];
|
|
1511
1511
|
}
|
|
1512
1512
|
}
|
|
1513
|
-
} else if (Object.keys(
|
|
1514
|
-
const firstRel =
|
|
1513
|
+
} else if (Object.keys(allRelationsMeta).length > 0) {
|
|
1514
|
+
const firstRel = allRelationsMeta[Object.keys(allRelationsMeta)[0]];
|
|
1515
1515
|
if (firstRel.predicate) {
|
|
1516
1516
|
const match = firstRel.predicate.match(/^([^:]+:\/\/)/);
|
|
1517
1517
|
if (match) {
|
|
@@ -1573,6 +1573,9 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
|
|
|
1573
1573
|
if (propMeta.resolveLanguage) {
|
|
1574
1574
|
propShape.resolveLanguage = propMeta.resolveLanguage;
|
|
1575
1575
|
}
|
|
1576
|
+
if (propMeta.getter) {
|
|
1577
|
+
propShape.getter = propMeta.getter;
|
|
1578
|
+
}
|
|
1576
1579
|
if (propMeta.prologSetter) {
|
|
1577
1580
|
console.warn(`[SHACL Generation] Custom Prolog setter for property '${propName}' in class '${subjectName}' is not yet supported. The property will be created without setter actions. Consider using standard writable properties or provide explicit SHACL JSON.`);
|
|
1578
1581
|
} else if (propMeta.writable && propMeta.through) {
|
|
@@ -1604,46 +1607,47 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
|
|
|
1604
1607
|
}
|
|
1605
1608
|
shape.addProperty(propShape);
|
|
1606
1609
|
}
|
|
1607
|
-
for (const relName in
|
|
1608
|
-
const relMeta =
|
|
1609
|
-
if (!relMeta.predicate)
|
|
1610
|
+
for (const relName in allRelationsMeta) {
|
|
1611
|
+
const relMeta = allRelationsMeta[relName];
|
|
1612
|
+
if (!relMeta.predicate && !relMeta.getter)
|
|
1610
1613
|
continue;
|
|
1614
|
+
const synthesizedPath = relMeta.predicate || `ad4m://getter/${subjectName}/${relName}`;
|
|
1611
1615
|
const relShape = {
|
|
1612
1616
|
name: relName,
|
|
1613
|
-
path:
|
|
1617
|
+
path: synthesizedPath
|
|
1614
1618
|
};
|
|
1615
1619
|
relShape.nodeKind = "IRI";
|
|
1620
|
+
relShape.relationKind = relMeta.kind;
|
|
1621
|
+
if (relMeta.kind === "hasOne" || relMeta.kind === "belongsToOne") {
|
|
1622
|
+
relShape.maxCount = 1;
|
|
1623
|
+
} else if (relMeta.maxCount !== void 0) {
|
|
1624
|
+
relShape.maxCount = relMeta.maxCount;
|
|
1625
|
+
}
|
|
1626
|
+
if (relMeta.filter === false) {
|
|
1627
|
+
relShape.filter = false;
|
|
1628
|
+
}
|
|
1616
1629
|
if (relMeta.local !== void 0) {
|
|
1617
1630
|
relShape.local = relMeta.local;
|
|
1618
1631
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1632
|
+
if (relMeta.predicate) {
|
|
1633
|
+
relShape.adder = [{
|
|
1634
|
+
action: "addLink",
|
|
1635
|
+
source: "this",
|
|
1636
|
+
predicate: relMeta.predicate,
|
|
1637
|
+
target: "value",
|
|
1638
|
+
...relMeta.local && { local: true }
|
|
1639
|
+
}];
|
|
1640
|
+
relShape.remover = [{
|
|
1641
|
+
action: "removeLink",
|
|
1642
|
+
source: "this",
|
|
1643
|
+
predicate: relMeta.predicate,
|
|
1644
|
+
target: "value",
|
|
1645
|
+
...relMeta.local && { local: true }
|
|
1646
|
+
}];
|
|
1647
|
+
}
|
|
1633
1648
|
if (relMeta.getter) {
|
|
1634
1649
|
relShape.getter = relMeta.getter;
|
|
1635
|
-
} else if (relMeta.
|
|
1636
|
-
try {
|
|
1637
|
-
const TargetClass = relMeta.target?.();
|
|
1638
|
-
const targetMetadata = TargetClass ? TargetClass.getModelMetadata?.() ?? null : null;
|
|
1639
|
-
const conditions = compileWhereClause(relMeta.where, targetMetadata);
|
|
1640
|
-
if (conditions.length > 0) {
|
|
1641
|
-
const escapedPredicate = escapeQueryString(relMeta.predicate);
|
|
1642
|
-
relShape.getter = `SELECT ?target WHERE { <Base> <${escapedPredicate}> ?target . ${conditions.join(" ")} }`;
|
|
1643
|
-
}
|
|
1644
|
-
} catch (e7) {
|
|
1645
|
-
}
|
|
1646
|
-
} else if (relMeta.target && relMeta.filter !== false) {
|
|
1650
|
+
} else if (relMeta.target && relMeta.filter !== false && relMeta.kind !== "belongsToOne" && relMeta.kind !== "belongsToMany") {
|
|
1647
1651
|
const targetThunk = relMeta.target;
|
|
1648
1652
|
const predicate = relMeta.predicate;
|
|
1649
1653
|
let resolved = false;
|
|
@@ -1695,6 +1699,37 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
|
|
|
1695
1699
|
if (targetSHACL?.shape?.nodeShapeUri) {
|
|
1696
1700
|
relShape.class = targetSHACL.shape.nodeShapeUri;
|
|
1697
1701
|
}
|
|
1702
|
+
if (targetSHACL?.name) {
|
|
1703
|
+
relShape.targetClassName = targetSHACL.name;
|
|
1704
|
+
} else {
|
|
1705
|
+
const targetProto = TargetClass.prototype;
|
|
1706
|
+
if (targetProto?.className) {
|
|
1707
|
+
relShape.targetClassName = targetProto.className;
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
} catch (e7) {
|
|
1711
|
+
console.warn(`[shacl-gen] Failed to resolve target class for relation "${subjectName}.${relName}": ${e7 instanceof Error ? e7.message : String(e7)}`);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
if (relMeta.where) {
|
|
1715
|
+
relShape.whereFilter = relMeta.where;
|
|
1716
|
+
try {
|
|
1717
|
+
const TargetClass = relMeta.target?.();
|
|
1718
|
+
const targetMetadata = TargetClass ? TargetClass.getModelMetadata?.() ?? null : null;
|
|
1719
|
+
if (targetMetadata?.properties) {
|
|
1720
|
+
const predicates = {};
|
|
1721
|
+
for (const propName of Object.keys(relMeta.where)) {
|
|
1722
|
+
if (["id", "author", "timestamp"].includes(propName))
|
|
1723
|
+
continue;
|
|
1724
|
+
const propMeta = targetMetadata.properties[propName];
|
|
1725
|
+
if (propMeta?.predicate) {
|
|
1726
|
+
predicates[propName] = propMeta.predicate;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
if (Object.keys(predicates).length > 0) {
|
|
1730
|
+
relShape.wherePredicates = predicates;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1698
1733
|
} catch (e7) {
|
|
1699
1734
|
}
|
|
1700
1735
|
}
|
|
@@ -1707,6 +1742,27 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
|
|
|
1707
1742
|
name: subjectName
|
|
1708
1743
|
};
|
|
1709
1744
|
}
|
|
1745
|
+
function formatList(list) {
|
|
1746
|
+
if (!list?.length) {
|
|
1747
|
+
return "";
|
|
1748
|
+
}
|
|
1749
|
+
if (list.length === 1) {
|
|
1750
|
+
return list.toString();
|
|
1751
|
+
}
|
|
1752
|
+
if (list.length === 2) {
|
|
1753
|
+
return list.join(" and ");
|
|
1754
|
+
}
|
|
1755
|
+
return list.slice(0, -1).join(", ") + ", and " + list.slice(-1);
|
|
1756
|
+
}
|
|
1757
|
+
function capSentence(cap) {
|
|
1758
|
+
const can = cap.can.includes("*") ? ["READ", "WRITE", "UPDATE"] : cap.can;
|
|
1759
|
+
const domain = cap.with.domain === "*" ? "" : cap.with.domain;
|
|
1760
|
+
const pointers = cap.with.pointers.includes("*") ? ["all AD4M data"] : cap.with.pointers;
|
|
1761
|
+
return `${formatList(can)} your ${domain} actions, with access to ${formatList(pointers)}`;
|
|
1762
|
+
}
|
|
1763
|
+
function escapeQueryString(value) {
|
|
1764
|
+
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
1765
|
+
}
|
|
1710
1766
|
var propertyRegistry = /* @__PURE__ */ new WeakMap();
|
|
1711
1767
|
var relationRegistry = /* @__PURE__ */ new WeakMap();
|
|
1712
1768
|
var propertiesMetadataCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -2333,14 +2389,14 @@ var PerspectiveProxy = class {
|
|
|
2333
2389
|
setCachedResult(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, query, result);
|
|
2334
2390
|
return result;
|
|
2335
2391
|
}
|
|
2336
|
-
async modelQuery(className, queryJson
|
|
2337
|
-
return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelQuery(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson
|
|
2392
|
+
async modelQuery(className, queryJson) {
|
|
2393
|
+
return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelQuery(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson);
|
|
2338
2394
|
}
|
|
2339
|
-
async evaluateGetters(className, instanceIds,
|
|
2340
|
-
return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").evaluateGetters(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, instanceIds,
|
|
2395
|
+
async evaluateGetters(className, instanceIds, propertyNames) {
|
|
2396
|
+
return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").evaluateGetters(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, instanceIds, propertyNames);
|
|
2341
2397
|
}
|
|
2342
|
-
async modelSubscribe(className, queryJson
|
|
2343
|
-
return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelSubscribe(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson
|
|
2398
|
+
async modelSubscribe(className, queryJson) {
|
|
2399
|
+
return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelSubscribe(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson);
|
|
2344
2400
|
}
|
|
2345
2401
|
async add(link, status = "shared", batchId) {
|
|
2346
2402
|
const result = await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").addLink(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, link, status, batchId);
|
|
@@ -3387,22 +3443,21 @@ var PerspectiveClient = class {
|
|
|
3387
3443
|
}
|
|
3388
3444
|
return __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.disposeQuery", { uuid, subscriptionId });
|
|
3389
3445
|
}
|
|
3390
|
-
async modelQuery(uuid, className, queryJson
|
|
3391
|
-
const resultJson = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelQuery", { uuid, class_name: className, query_json: queryJson
|
|
3446
|
+
async modelQuery(uuid, className, queryJson) {
|
|
3447
|
+
const resultJson = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelQuery", { uuid, class_name: className, query_json: queryJson });
|
|
3392
3448
|
return JSON.parse(resultJson);
|
|
3393
3449
|
}
|
|
3394
|
-
async evaluateGetters(uuid, className, instanceIds,
|
|
3450
|
+
async evaluateGetters(uuid, className, instanceIds, propertyNames) {
|
|
3395
3451
|
const resultJson = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.evaluateGetters", {
|
|
3396
3452
|
uuid,
|
|
3397
3453
|
class_name: className,
|
|
3398
3454
|
instance_ids: instanceIds,
|
|
3399
|
-
shape_json: shapeJson,
|
|
3400
3455
|
...propertyNames && { property_names: propertyNames }
|
|
3401
3456
|
});
|
|
3402
3457
|
return JSON.parse(resultJson);
|
|
3403
3458
|
}
|
|
3404
|
-
async modelSubscribe(uuid, className, queryJson
|
|
3405
|
-
const response = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelSubscribe", { uuid, class_name: className, query_json: queryJson
|
|
3459
|
+
async modelSubscribe(uuid, className, queryJson) {
|
|
3460
|
+
const response = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelSubscribe", { uuid, class_name: className, query_json: queryJson });
|
|
3406
3461
|
return {
|
|
3407
3462
|
subscriptionId: response.subscription_id,
|
|
3408
3463
|
result: JSON.parse(response.result)
|
|
@@ -9507,9 +9562,6 @@ var ModelQueryBuilder = class {
|
|
|
9507
9562
|
this.modelClassName = className;
|
|
9508
9563
|
return this;
|
|
9509
9564
|
}
|
|
9510
|
-
engine(_eng) {
|
|
9511
|
-
return this;
|
|
9512
|
-
}
|
|
9513
9565
|
async get() {
|
|
9514
9566
|
return await this.executeSparqlQuery();
|
|
9515
9567
|
}
|
|
@@ -9530,8 +9582,8 @@ var ModelQueryBuilder = class {
|
|
|
9530
9582
|
async subscribe(callback) {
|
|
9531
9583
|
this.dispose();
|
|
9532
9584
|
const ctor = this.ctor;
|
|
9533
|
-
const { className, queryJson
|
|
9534
|
-
const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson
|
|
9585
|
+
const { className, queryJson } = ctor.prepareModelQueryParams(this.queryParams, this.modelClassName);
|
|
9586
|
+
const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson);
|
|
9535
9587
|
const parseResults = (raw) => {
|
|
9536
9588
|
return ctor.parseModelResult(this.perspective, raw, this.queryParams.include, this.queryParams.properties);
|
|
9537
9589
|
};
|
|
@@ -9628,8 +9680,8 @@ var ModelQueryBuilder = class {
|
|
|
9628
9680
|
async countSubscribe(callback) {
|
|
9629
9681
|
this.dispose();
|
|
9630
9682
|
const countParams = { ...this.queryParams, limit: 0 };
|
|
9631
|
-
const { className, queryJson
|
|
9632
|
-
const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson
|
|
9683
|
+
const { className, queryJson } = this.ctor.prepareModelQueryParams(countParams, this.modelClassName);
|
|
9684
|
+
const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson);
|
|
9633
9685
|
const parseCount = (raw) => {
|
|
9634
9686
|
const data = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
9635
9687
|
return data.totalCount ?? 0;
|
|
@@ -9704,8 +9756,8 @@ var ModelQueryBuilder = class {
|
|
|
9704
9756
|
const subscriptionParams = { ...this.queryParams || {} };
|
|
9705
9757
|
delete subscriptionParams.limit;
|
|
9706
9758
|
delete subscriptionParams.offset;
|
|
9707
|
-
const { className, queryJson
|
|
9708
|
-
const { subscriptionId } = await this.perspective.modelSubscribe(className, queryJson
|
|
9759
|
+
const { className, queryJson } = ctor.prepareModelQueryParams(subscriptionParams, this.modelClassName);
|
|
9760
|
+
const { subscriptionId } = await this.perspective.modelSubscribe(className, queryJson);
|
|
9709
9761
|
const paginatedQuery = {
|
|
9710
9762
|
...this.queryParams || {},
|
|
9711
9763
|
limit: pageSize,
|
|
@@ -9797,34 +9849,6 @@ function defaultFileDecode(resolved) {
|
|
|
9797
9849
|
}
|
|
9798
9850
|
return resolved;
|
|
9799
9851
|
}
|
|
9800
|
-
function enrichShapeForIncludes(metadata, include, allRelMeta) {
|
|
9801
|
-
for (const [relName, includeVal] of Object.entries(include)) {
|
|
9802
|
-
if (!includeVal)
|
|
9803
|
-
continue;
|
|
9804
|
-
const meta = allRelMeta[relName];
|
|
9805
|
-
if (!meta?.target)
|
|
9806
|
-
continue;
|
|
9807
|
-
const TargetClass = meta.target();
|
|
9808
|
-
const targetMeta = JSON.parse(JSON.stringify(TargetClass.getModelMetadata()));
|
|
9809
|
-
if (!metadata.relations[relName]) {
|
|
9810
|
-
metadata.relations[relName] = {
|
|
9811
|
-
name: relName,
|
|
9812
|
-
predicate: meta.predicate,
|
|
9813
|
-
direction: meta.kind === "belongsToMany" || meta.kind === "belongsToOne" ? "reverse" : "forward"
|
|
9814
|
-
};
|
|
9815
|
-
}
|
|
9816
|
-
const rel = metadata.relations[relName];
|
|
9817
|
-
rel.kind = meta.kind;
|
|
9818
|
-
rel.maxCount = meta.maxCount;
|
|
9819
|
-
rel.targetShape = targetMeta;
|
|
9820
|
-
rel.targetClassName = targetMeta.className;
|
|
9821
|
-
const nested = typeof includeVal === "object" && includeVal !== null ? includeVal.include : void 0;
|
|
9822
|
-
if (nested) {
|
|
9823
|
-
const targetRelMeta = getRelationsMetadata(TargetClass);
|
|
9824
|
-
enrichShapeForIncludes(targetMeta, nested, targetRelMeta);
|
|
9825
|
-
}
|
|
9826
|
-
}
|
|
9827
|
-
}
|
|
9828
9852
|
function jsonToModelInstance(ModelClass, perspective, json, include, properties) {
|
|
9829
9853
|
const instance = new ModelClass(perspective, json.id || json.baseExpression);
|
|
9830
9854
|
if (properties) {
|
|
@@ -10207,12 +10231,12 @@ var Ad4mModel = class {
|
|
|
10207
10231
|
const allRelMeta = getRelationsMetadata(this);
|
|
10208
10232
|
for (const [, proj] of Object.entries(projections)) {
|
|
10209
10233
|
const relMeta = allRelMeta[proj.from];
|
|
10210
|
-
if (!proj.
|
|
10234
|
+
if (!proj.targetClassName && relMeta?.target) {
|
|
10211
10235
|
try {
|
|
10212
10236
|
const TargetClass = relMeta.target();
|
|
10213
10237
|
const targetMeta = TargetClass.getModelMetadata?.();
|
|
10214
|
-
if (targetMeta) {
|
|
10215
|
-
proj.
|
|
10238
|
+
if (targetMeta?.className) {
|
|
10239
|
+
proj.targetClassName = targetMeta.className;
|
|
10216
10240
|
}
|
|
10217
10241
|
} catch (e7) {
|
|
10218
10242
|
console.debug(`prepareModelQueryParams: target class unavailable for projection:`, e7);
|
|
@@ -10234,56 +10258,9 @@ var Ad4mModel = class {
|
|
|
10234
10258
|
if (query.count !== void 0)
|
|
10235
10259
|
queryInput.count = query.count;
|
|
10236
10260
|
queryInput.deepQuery = query.deepQuery ?? true;
|
|
10237
|
-
if (queryInput.include) {
|
|
10238
|
-
const allRelMeta = getRelationsMetadata(this);
|
|
10239
|
-
enrichShapeForIncludes(metadata, queryInput.include, allRelMeta);
|
|
10240
|
-
}
|
|
10241
|
-
{
|
|
10242
|
-
const allRelMeta = getRelationsMetadata(this);
|
|
10243
|
-
for (const [relName, relMeta] of Object.entries(metadata.relations)) {
|
|
10244
|
-
const rel = relMeta;
|
|
10245
|
-
if (rel.getter || rel.direction === "reverse" || rel.filter === false)
|
|
10246
|
-
continue;
|
|
10247
|
-
const meta = allRelMeta[relName];
|
|
10248
|
-
if (!meta?.target)
|
|
10249
|
-
continue;
|
|
10250
|
-
try {
|
|
10251
|
-
const TargetClass = meta.target();
|
|
10252
|
-
const filter = buildConformanceFilter(meta.predicate, TargetClass);
|
|
10253
|
-
if (filter) {
|
|
10254
|
-
rel.getter = filter.getter;
|
|
10255
|
-
}
|
|
10256
|
-
if (rel.where) {
|
|
10257
|
-
try {
|
|
10258
|
-
const targetMetadata = TargetClass.getModelMetadata?.() ?? null;
|
|
10259
|
-
if (targetMetadata) {
|
|
10260
|
-
const predicates = {};
|
|
10261
|
-
for (const propName of Object.keys(rel.where)) {
|
|
10262
|
-
if (["id", "author", "timestamp"].includes(propName))
|
|
10263
|
-
continue;
|
|
10264
|
-
const propMeta = targetMetadata.properties[propName];
|
|
10265
|
-
if (propMeta?.predicate) {
|
|
10266
|
-
predicates[propName] = propMeta.predicate;
|
|
10267
|
-
}
|
|
10268
|
-
}
|
|
10269
|
-
if (Object.keys(predicates).length > 0) {
|
|
10270
|
-
rel.whereFilter = rel.where;
|
|
10271
|
-
rel.wherePredicates = predicates;
|
|
10272
|
-
}
|
|
10273
|
-
}
|
|
10274
|
-
} catch (e7) {
|
|
10275
|
-
console.debug(`prepareModelQueryParams: target metadata unavailable for relation '${relName}':`, e7);
|
|
10276
|
-
}
|
|
10277
|
-
}
|
|
10278
|
-
} catch (e7) {
|
|
10279
|
-
console.debug(`prepareModelQueryParams: target class unavailable for relation '${relName}':`, e7);
|
|
10280
|
-
}
|
|
10281
|
-
}
|
|
10282
|
-
}
|
|
10283
10261
|
return {
|
|
10284
10262
|
className,
|
|
10285
10263
|
queryJson: JSON.stringify(queryInput),
|
|
10286
|
-
shapeJson: JSON.stringify(metadata),
|
|
10287
10264
|
metadata
|
|
10288
10265
|
};
|
|
10289
10266
|
}
|
|
@@ -10326,8 +10303,8 @@ var Ad4mModel = class {
|
|
|
10326
10303
|
}));
|
|
10327
10304
|
}
|
|
10328
10305
|
static async executeModelQuery(perspective, query = {}, classNameOverride) {
|
|
10329
|
-
const { className, queryJson
|
|
10330
|
-
const result = await perspective.modelQuery(className, queryJson
|
|
10306
|
+
const { className, queryJson } = this.prepareModelQueryParams(query, classNameOverride);
|
|
10307
|
+
const result = await perspective.modelQuery(className, queryJson);
|
|
10331
10308
|
const instances = result.instances.map((json) => {
|
|
10332
10309
|
return jsonToModelInstance(this, perspective, json, query.include, query.properties);
|
|
10333
10310
|
});
|
|
@@ -10341,28 +10318,30 @@ var Ad4mModel = class {
|
|
|
10341
10318
|
totalCount: result.totalCount
|
|
10342
10319
|
};
|
|
10343
10320
|
}
|
|
10344
|
-
static async findAll(perspective, query
|
|
10345
|
-
|
|
10321
|
+
static async findAll(perspective, query) {
|
|
10322
|
+
const q = query ?? {};
|
|
10323
|
+
if (q.properties && q.properties.length === 0) {
|
|
10346
10324
|
throw new Error("properties[] must not be empty \u2014 omit the field to return all properties, or specify at least one field name");
|
|
10347
10325
|
}
|
|
10348
|
-
const { results } = await this.executeModelQuery(perspective,
|
|
10326
|
+
const { results } = await this.executeModelQuery(perspective, q);
|
|
10349
10327
|
return results;
|
|
10350
10328
|
}
|
|
10351
|
-
static async findOne(perspective, query
|
|
10352
|
-
const limitedQuery = { ...query, limit: 1 };
|
|
10329
|
+
static async findOne(perspective, query) {
|
|
10330
|
+
const limitedQuery = { ...query ?? {}, limit: 1 };
|
|
10353
10331
|
const results = await this.findAll(perspective, limitedQuery);
|
|
10354
10332
|
return results[0] ?? null;
|
|
10355
10333
|
}
|
|
10356
|
-
static async findAllAndCount(perspective, query
|
|
10357
|
-
|
|
10334
|
+
static async findAllAndCount(perspective, query) {
|
|
10335
|
+
const out = await this.executeModelQuery(perspective, query ?? {});
|
|
10336
|
+
return out;
|
|
10358
10337
|
}
|
|
10359
|
-
static async paginate(perspective, pageSize, pageNumber, query
|
|
10360
|
-
const paginationQuery = { ...query
|
|
10338
|
+
static async paginate(perspective, pageSize, pageNumber, query) {
|
|
10339
|
+
const paginationQuery = { ...query ?? {}, limit: pageSize, offset: pageSize * (pageNumber - 1), count: true };
|
|
10361
10340
|
const { results, totalCount } = await this.executeModelQuery(perspective, paginationQuery);
|
|
10362
10341
|
return { results, totalCount, pageSize, pageNumber };
|
|
10363
10342
|
}
|
|
10364
|
-
static async count(perspective, query
|
|
10365
|
-
const { totalCount } = await this.executeModelQuery(perspective, { ...query, limit: 0 });
|
|
10343
|
+
static async count(perspective, query) {
|
|
10344
|
+
const { totalCount } = await this.executeModelQuery(perspective, { ...query ?? {}, limit: 0 });
|
|
10366
10345
|
return totalCount;
|
|
10367
10346
|
}
|
|
10368
10347
|
async setProperty(key, value, batchId) {
|
|
@@ -10558,26 +10537,8 @@ var Ad4mModel = class {
|
|
|
10558
10537
|
if (instances.length === 0)
|
|
10559
10538
|
return;
|
|
10560
10539
|
const metadata = this.getModelMetadata();
|
|
10561
|
-
const allRelMeta = getRelationsMetadata(this);
|
|
10562
|
-
for (const [relName, relMeta] of Object.entries(metadata.relations)) {
|
|
10563
|
-
const rel = relMeta;
|
|
10564
|
-
if (rel.getter || rel.direction === "reverse" || rel.filter === false)
|
|
10565
|
-
continue;
|
|
10566
|
-
const meta = allRelMeta[relName];
|
|
10567
|
-
if (!meta?.target)
|
|
10568
|
-
continue;
|
|
10569
|
-
try {
|
|
10570
|
-
const TargetClass = meta.target();
|
|
10571
|
-
const filter = buildConformanceFilter(meta.predicate, TargetClass);
|
|
10572
|
-
if (filter)
|
|
10573
|
-
rel.getter = filter.getter;
|
|
10574
|
-
} catch (e7) {
|
|
10575
|
-
console.debug(`evaluateGetters: target class unavailable for relation '${relName}':`, e7);
|
|
10576
|
-
}
|
|
10577
|
-
}
|
|
10578
|
-
const shapeJson = JSON.stringify(metadata);
|
|
10579
10540
|
const instanceIds = instances.map((inst) => inst.id || inst._baseExpression);
|
|
10580
|
-
const result = await perspective.evaluateGetters(metadata.className, instanceIds,
|
|
10541
|
+
const result = await perspective.evaluateGetters(metadata.className, instanceIds, propertyNames);
|
|
10581
10542
|
const evaluatedPropertyNames = [];
|
|
10582
10543
|
for (const [propName, propMeta] of Object.entries(metadata.properties)) {
|
|
10583
10544
|
if (propMeta.getter) {
|
|
@@ -10711,7 +10672,7 @@ var Ad4mModel = class {
|
|
|
10711
10672
|
return result;
|
|
10712
10673
|
}
|
|
10713
10674
|
static query(perspective, query) {
|
|
10714
|
-
return new ModelQueryBuilder(perspective, this, query);
|
|
10675
|
+
return new ModelQueryBuilder(perspective, this, query ?? {});
|
|
10715
10676
|
}
|
|
10716
10677
|
static fromJSONSchema(schema, options) {
|
|
10717
10678
|
return buildModelFromJSONSchema(this, schema, options);
|
|
@@ -11232,7 +11193,18 @@ var Ad4mConnect = class extends EventTarget {
|
|
|
11232
11193
|
console.warn("[Ad4m Connect] Rejected AD4M_CONFIG from invalid source (not parent window)");
|
|
11233
11194
|
return;
|
|
11234
11195
|
}
|
|
11235
|
-
if (
|
|
11196
|
+
if (event.data.proxy) {
|
|
11197
|
+
if (!this.options.allowedOrigins || this.options.allowedOrigins.length === 0) {
|
|
11198
|
+
console.error("[Ad4m Connect] proxy mode requires allowedOrigins to be configured. Rejecting AD4M_CONFIG to prevent arbitrary sites from embedding this app.");
|
|
11199
|
+
this.rejectEmbedded(new Error("proxy mode requires allowedOrigins"));
|
|
11200
|
+
return;
|
|
11201
|
+
}
|
|
11202
|
+
if (!event.origin || !this.options.allowedOrigins.includes(event.origin)) {
|
|
11203
|
+
console.warn("[Ad4m Connect] Rejected AD4M_CONFIG from unauthorized origin:", event.origin);
|
|
11204
|
+
this.rejectEmbedded(new Error(`Unauthorized origin: ${event.origin}`));
|
|
11205
|
+
return;
|
|
11206
|
+
}
|
|
11207
|
+
} else if (this.options.allowedOrigins && this.options.allowedOrigins.length > 0) {
|
|
11236
11208
|
if (!event.origin || !this.options.allowedOrigins.includes(event.origin)) {
|
|
11237
11209
|
console.warn("[Ad4m Connect] Rejected AD4M_CONFIG from unauthorized origin:", event.origin);
|
|
11238
11210
|
this.rejectEmbedded(new Error(`Unauthorized origin: ${event.origin}`));
|
|
@@ -11250,12 +11222,17 @@ var Ad4mConnect = class extends EventTarget {
|
|
|
11250
11222
|
} else {
|
|
11251
11223
|
removeLocal("ad4m-token");
|
|
11252
11224
|
}
|
|
11225
|
+
if (!event.origin || event.origin === "null") {
|
|
11226
|
+
throw new Error("AD4M proxy mode requires a non-opaque parent origin. Ensure the host iframe is not sandboxed without allow-same-origin.");
|
|
11227
|
+
}
|
|
11228
|
+
const parentOrigin2 = event.origin;
|
|
11229
|
+
const wsImpl = (url) => new PostMessageWebSocket(url, parentOrigin2);
|
|
11253
11230
|
this.notifyConnectionChange("connecting");
|
|
11254
11231
|
this.ad4mClient = new Ad4mClient(
|
|
11255
11232
|
"http://proxy",
|
|
11256
11233
|
normalizedToken,
|
|
11257
11234
|
false,
|
|
11258
|
-
{ webSocketImpl:
|
|
11235
|
+
{ webSocketImpl: wsImpl }
|
|
11259
11236
|
);
|
|
11260
11237
|
this.notifyConnectionChange("connected");
|
|
11261
11238
|
yield this.checkAuth();
|