@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/index.js CHANGED
@@ -120,21 +120,26 @@ function getHue(str) {
120
120
  }
121
121
 
122
122
  // src/PostMessageWebSocket.ts
123
- var PostMessageWebSocket = class {
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
- (_d = this.onclose) == null ? void 0 : _d.call(
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(relations).length > 0) {
1514
- const firstRel = relations[Object.keys(relations)[0]];
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 relations) {
1608
- const relMeta = relations[relName];
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: relMeta.predicate
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
- relShape.adder = [{
1620
- action: "addLink",
1621
- source: "this",
1622
- predicate: relMeta.predicate,
1623
- target: "value",
1624
- ...relMeta.local && { local: true }
1625
- }];
1626
- relShape.remover = [{
1627
- action: "removeLink",
1628
- source: "this",
1629
- predicate: relMeta.predicate,
1630
- target: "value",
1631
- ...relMeta.local && { local: true }
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.where) {
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, shapeJson) {
2337
- return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelQuery(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson, shapeJson);
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, shapeJson, propertyNames) {
2340
- return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").evaluateGetters(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, instanceIds, shapeJson, propertyNames);
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, shapeJson) {
2343
- return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelSubscribe(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson, shapeJson);
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, shapeJson) {
3391
- const resultJson = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelQuery", { uuid, class_name: className, query_json: queryJson, shape_json: shapeJson });
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, shapeJson, propertyNames) {
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, shapeJson) {
3405
- const response = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelSubscribe", { uuid, class_name: className, query_json: queryJson, shape_json: shapeJson });
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, shapeJson } = ctor.prepareModelQueryParams(this.queryParams, this.modelClassName);
9534
- const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson, shapeJson);
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, shapeJson } = this.ctor.prepareModelQueryParams(countParams, this.modelClassName);
9632
- const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson, shapeJson);
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, shapeJson } = ctor.prepareModelQueryParams(subscriptionParams, this.modelClassName);
9708
- const { subscriptionId } = await this.perspective.modelSubscribe(className, queryJson, shapeJson);
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.targetShape && relMeta?.target) {
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.targetShape = targetMeta;
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, shapeJson } = this.prepareModelQueryParams(query, classNameOverride);
10330
- const result = await perspective.modelQuery(className, queryJson, shapeJson);
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 = {}, _engine) {
10345
- if (query.properties && query.properties.length === 0) {
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, query);
10326
+ const { results } = await this.executeModelQuery(perspective, q);
10349
10327
  return results;
10350
10328
  }
10351
- static async findOne(perspective, query = {}, _engine) {
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 = {}, _engine) {
10357
- return await this.executeModelQuery(perspective, query);
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, _engine) {
10360
- const paginationQuery = { ...query || {}, limit: pageSize, offset: pageSize * (pageNumber - 1), count: true };
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, shapeJson, propertyNames);
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 (this.options.allowedOrigins && this.options.allowedOrigins.length > 0) {
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: PostMessageWebSocket }
11235
+ { webSocketImpl: wsImpl }
11259
11236
  );
11260
11237
  this.notifyConnectionChange("connected");
11261
11238
  yield this.checkAuth();