@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/core.js CHANGED
@@ -73,21 +73,26 @@ function checkConnection(baseUrl, timeout = 1e4) {
73
73
  }
74
74
 
75
75
  // src/PostMessageWebSocket.ts
76
- var PostMessageWebSocket = class {
77
- constructor(_url) {
76
+ var _PostMessageWebSocket = class {
77
+ constructor(_url, targetOrigin) {
78
78
  this.readyState = 0;
79
79
  this.onopen = null;
80
80
  this.onmessage = null;
81
81
  this.onerror = null;
82
82
  this.onclose = null;
83
+ this._connectTimeout = null;
84
+ this._targetOrigin = targetOrigin;
83
85
  this._messageHandler = (e) => {
84
- var _a, _b, _c, _d;
86
+ var _a, _b, _c, _d, _e;
85
87
  if (e.source !== window.parent)
86
88
  return;
89
+ if (e.origin !== this._targetOrigin)
90
+ return;
87
91
  const msg = e.data;
88
92
  if (!msg || typeof msg.type !== "string")
89
93
  return;
90
94
  if (msg.type === "AD4M_PROXY_WS_OPEN") {
95
+ this._clearConnectTimeout();
91
96
  this.readyState = 1;
92
97
  (_a = this.onopen) == null ? void 0 : _a.call(this, new Event("open"));
93
98
  return;
@@ -97,12 +102,17 @@ var PostMessageWebSocket = class {
97
102
  return;
98
103
  }
99
104
  if (msg.type === "AD4M_PROXY_WS_ERROR") {
105
+ this._clearConnectTimeout();
106
+ this.readyState = _PostMessageWebSocket.CLOSED;
107
+ window.removeEventListener("message", this._messageHandler);
100
108
  (_c = this.onerror) == null ? void 0 : _c.call(this, new Event("error"));
109
+ (_d = this.onclose) == null ? void 0 : _d.call(this, new CloseEvent("close", { code: 1006, reason: "WebSocket error", wasClean: false }));
101
110
  return;
102
111
  }
103
112
  if (msg.type === "AD4M_PROXY_WS_CLOSED") {
113
+ this._clearConnectTimeout();
104
114
  this.readyState = 3;
105
- (_d = this.onclose) == null ? void 0 : _d.call(
115
+ (_e = this.onclose) == null ? void 0 : _e.call(
106
116
  this,
107
117
  new CloseEvent("close", {
108
118
  code: typeof msg.code === "number" ? msg.code : 1e3,
@@ -114,21 +124,37 @@ var PostMessageWebSocket = class {
114
124
  }
115
125
  };
116
126
  window.addEventListener("message", this._messageHandler);
117
- window.parent.postMessage({ type: "AD4M_PROXY_WS_CONNECT" }, "*");
127
+ window.parent.postMessage({ type: "AD4M_PROXY_WS_CONNECT" }, this._targetOrigin);
128
+ this._connectTimeout = setTimeout(() => {
129
+ var _a, _b;
130
+ this._connectTimeout = null;
131
+ window.removeEventListener("message", this._messageHandler);
132
+ this.readyState = 3;
133
+ (_a = this.onerror) == null ? void 0 : _a.call(this, new Event("error"));
134
+ (_b = this.onclose) == null ? void 0 : _b.call(this, new CloseEvent("close", { code: 1006, reason: "Connection timeout", wasClean: false }));
135
+ }, _PostMessageWebSocket.CONNECT_TIMEOUT_MS);
136
+ }
137
+ _clearConnectTimeout() {
138
+ if (this._connectTimeout !== null) {
139
+ clearTimeout(this._connectTimeout);
140
+ this._connectTimeout = null;
141
+ }
118
142
  }
119
143
  send(data) {
120
- window.parent.postMessage({ type: "AD4M_PROXY_WS_SEND", data }, "*");
144
+ window.parent.postMessage({ type: "AD4M_PROXY_WS_SEND", data }, this._targetOrigin);
121
145
  }
122
146
  close(code2, reason) {
123
147
  this.readyState = 2;
124
- window.parent.postMessage({ type: "AD4M_PROXY_WS_CLOSE", code: code2, reason }, "*");
148
+ window.parent.postMessage({ type: "AD4M_PROXY_WS_CLOSE", code: code2, reason }, this._targetOrigin);
125
149
  window.removeEventListener("message", this._messageHandler);
126
150
  }
127
151
  };
152
+ var PostMessageWebSocket = _PostMessageWebSocket;
128
153
  PostMessageWebSocket.CONNECTING = 0;
129
154
  PostMessageWebSocket.OPEN = 1;
130
155
  PostMessageWebSocket.CLOSING = 2;
131
156
  PostMessageWebSocket.CLOSED = 3;
157
+ PostMessageWebSocket.CONNECT_TIMEOUT_MS = 3e4;
132
158
 
133
159
  // ../core/lib/index.js
134
160
  var RpcError = class extends Error {
@@ -1124,6 +1150,41 @@ var SHACLShape = class {
1124
1150
  target: `literal:string:${JSON.stringify(prop.in)}`
1125
1151
  });
1126
1152
  }
1153
+ if (prop.relationKind) {
1154
+ links.push({
1155
+ source: propShapeId,
1156
+ predicate: "ad4m://relationKind",
1157
+ target: `literal:string:${prop.relationKind}`
1158
+ });
1159
+ }
1160
+ if (prop.targetClassName) {
1161
+ links.push({
1162
+ source: propShapeId,
1163
+ predicate: "ad4m://targetClassName",
1164
+ target: `literal:string:${prop.targetClassName}`
1165
+ });
1166
+ }
1167
+ if (prop.whereFilter !== void 0 && prop.whereFilter !== null) {
1168
+ links.push({
1169
+ source: propShapeId,
1170
+ predicate: "ad4m://whereFilter",
1171
+ target: `literal:string:${JSON.stringify(prop.whereFilter)}`
1172
+ });
1173
+ }
1174
+ if (prop.wherePredicates && Object.keys(prop.wherePredicates).length > 0) {
1175
+ links.push({
1176
+ source: propShapeId,
1177
+ predicate: "ad4m://wherePredicates",
1178
+ target: `literal:string:${JSON.stringify(prop.wherePredicates)}`
1179
+ });
1180
+ }
1181
+ if (prop.filter !== void 0) {
1182
+ links.push({
1183
+ source: propShapeId,
1184
+ predicate: "ad4m://filter",
1185
+ target: `literal:${prop.filter}`
1186
+ });
1187
+ }
1127
1188
  }
1128
1189
  return links;
1129
1190
  }
@@ -1272,6 +1333,40 @@ var SHACLShape = class {
1272
1333
  } catch (e) {
1273
1334
  }
1274
1335
  }
1336
+ const relationKindLink = links.find((l) => l.source === propShapeId && l.predicate === "ad4m://relationKind");
1337
+ if (relationKindLink) {
1338
+ const val = relationKindLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
1339
+ if (val === "hasMany" || val === "hasOne" || val === "belongsToOne" || val === "belongsToMany") {
1340
+ prop.relationKind = val;
1341
+ }
1342
+ }
1343
+ const targetClassNameLink = links.find((l) => l.source === propShapeId && l.predicate === "ad4m://targetClassName");
1344
+ if (targetClassNameLink) {
1345
+ prop.targetClassName = targetClassNameLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
1346
+ }
1347
+ const whereFilterLink = links.find((l) => l.source === propShapeId && l.predicate === "ad4m://whereFilter");
1348
+ if (whereFilterLink) {
1349
+ try {
1350
+ const jsonStr = whereFilterLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
1351
+ prop.whereFilter = JSON.parse(jsonStr);
1352
+ } catch (e) {
1353
+ }
1354
+ }
1355
+ const wherePredicatesLink = links.find((l) => l.source === propShapeId && l.predicate === "ad4m://wherePredicates");
1356
+ if (wherePredicatesLink) {
1357
+ try {
1358
+ const jsonStr = wherePredicatesLink.target.replace(/^literal:\/\/string:|^literal:string:/, "");
1359
+ prop.wherePredicates = JSON.parse(jsonStr);
1360
+ } catch (e) {
1361
+ }
1362
+ }
1363
+ const filterLink = links.find((l) => l.source === propShapeId && l.predicate === "ad4m://filter");
1364
+ if (filterLink) {
1365
+ let val = filterLink.target.replace(/^literal:\/\/|^literal:/, "");
1366
+ if (val.startsWith("boolean:"))
1367
+ val = val.substring(8);
1368
+ prop.filter = val === "true";
1369
+ }
1275
1370
  shape.addProperty(prop);
1276
1371
  }
1277
1372
  return shape;
@@ -1301,7 +1396,12 @@ var SHACLShape = class {
1301
1396
  getter: p.getter,
1302
1397
  conformance_conditions: p.conformanceConditions,
1303
1398
  class: p.class,
1304
- in: p.in
1399
+ in: p.in,
1400
+ relation_kind: p.relationKind,
1401
+ target_class_name: p.targetClassName,
1402
+ where_filter: p.whereFilter,
1403
+ where_predicates: p.wherePredicates,
1404
+ filter: p.filter
1305
1405
  })),
1306
1406
  constructor_actions: this.constructor_actions,
1307
1407
  destructor_actions: this.destructor_actions
@@ -1330,7 +1430,12 @@ var SHACLShape = class {
1330
1430
  getter: p.getter,
1331
1431
  conformanceConditions: p.conformance_conditions,
1332
1432
  class: p.class,
1333
- in: p.in
1433
+ in: p.in,
1434
+ relationKind: p.relation_kind,
1435
+ targetClassName: p.target_class_name,
1436
+ whereFilter: p.where_filter,
1437
+ wherePredicates: p.where_predicates,
1438
+ filter: p.filter
1334
1439
  });
1335
1440
  }
1336
1441
  if (json.constructor_actions) {
@@ -1347,96 +1452,9 @@ var SHACLShape = class {
1347
1452
  return shape;
1348
1453
  }
1349
1454
  };
1350
- function escapeQueryString(value) {
1351
- return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
1352
- }
1353
- function buildWhereCondition(predicate, condition, opts) {
1354
- const escapedPredicate = escapeQueryString(predicate);
1355
- const isLiteral = !opts?.resolveLanguage || opts.resolveLanguage === "literal";
1356
- const varSuffix = opts?.varIndex ?? 0;
1357
- function formatValue(v) {
1358
- if (typeof v === "string") {
1359
- return isLiteral ? `<literal:string:${escapeQueryString(v)}>` : `<${escapeQueryString(v)}>`;
1360
- }
1361
- return `<literal:string:${v}>`;
1362
- }
1363
- function formatLiteralFilter(varName, v) {
1364
- const raw = escapeQueryString(String(v));
1365
- const encoded = encodeURIComponent(String(v)).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A");
1366
- if (typeof v === "string") {
1367
- return `FILTER(STR(${varName}) = "${raw}" || STR(${varName}) = "literal:string:${encoded}")`;
1368
- } else if (typeof v === "number") {
1369
- return `FILTER(STR(${varName}) = "${v}" || STR(${varName}) = "literal:number:${v}")`;
1370
- } else if (typeof v === "boolean") {
1371
- return `FILTER(STR(${varName}) = "${v}" || STR(${varName}) = "literal:boolean:${v}")`;
1372
- }
1373
- return `FILTER(STR(${varName}) = "${raw}")`;
1374
- }
1375
- if (Array.isArray(condition)) {
1376
- if (isLiteral) {
1377
- const varName = `?_wc${varSuffix}`;
1378
- const inValues = condition.flatMap((v) => {
1379
- const raw = escapeQueryString(String(v));
1380
- const encoded = encodeURIComponent(String(v)).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A");
1381
- return [`"${raw}"`, `"literal:string:${encoded}"`];
1382
- }).join(", ");
1383
- return `?target <${escapedPredicate}> ${varName} . FILTER(STR(${varName}) IN (${inValues}))`;
1384
- }
1385
- const formattedValues = condition.map(formatValue).join(", ");
1386
- return `FILTER EXISTS { ?target <${escapedPredicate}> ?_val . FILTER(?_val IN (${formattedValues})) }`;
1387
- } else if (typeof condition === "object" && condition !== null) {
1388
- const ops = condition;
1389
- const parts = [];
1390
- if (ops.not !== void 0) {
1391
- if (Array.isArray(ops.not)) {
1392
- const formattedValues = ops.not.map((v) => formatValue(v)).join(", ");
1393
- parts.push(`FILTER NOT EXISTS { ?target <${escapedPredicate}> ?_nval . FILTER(?_nval IN (${formattedValues})) }`);
1394
- } else {
1395
- parts.push(`FILTER NOT EXISTS { ?target <${escapedPredicate}> ${formatValue(ops.not)} }`);
1396
- }
1397
- }
1398
- 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;
1399
- if (hasComparisonOps) {
1400
- parts.push(`FILTER EXISTS { ?target <${escapedPredicate}> ?_cmp }`);
1401
- }
1402
- return parts.join(" ");
1403
- } else {
1404
- if (isLiteral) {
1405
- const varName = `?_wc${varSuffix}`;
1406
- return `?target <${escapedPredicate}> ${varName} . ${formatLiteralFilter(varName, condition)}`;
1407
- }
1408
- return `?target <${escapedPredicate}> ${formatValue(condition)} .`;
1409
- }
1410
- }
1411
- function compileWhereClause(where, metadata) {
1412
- const conditions = [];
1413
- for (const [propertyName, condition] of Object.entries(where)) {
1414
- if (["id", "author", "timestamp"].includes(propertyName))
1415
- continue;
1416
- let predicate;
1417
- let resolveLanguage;
1418
- if (metadata) {
1419
- const propMeta = metadata.properties[propertyName];
1420
- if (propMeta) {
1421
- predicate = propMeta.predicate;
1422
- resolveLanguage = propMeta.resolveLanguage;
1423
- } else {
1424
- predicate = propertyName;
1425
- }
1426
- } else {
1427
- predicate = propertyName;
1428
- }
1429
- const cond = buildWhereCondition(predicate, condition, { resolveLanguage, varIndex: conditions.length });
1430
- if (cond) {
1431
- conditions.push(cond);
1432
- }
1433
- }
1434
- return conditions;
1435
- }
1436
1455
  function buildSHACL(subjectName, target, properties, allRelationsMeta, conformanceFilterFn) {
1437
1456
  const obj = target.prototype;
1438
1457
  let namespace = "ad4m://";
1439
- const relations = Object.fromEntries(Object.entries(allRelationsMeta).filter(([, r]) => r.kind === "hasMany" || r.kind === "belongsToMany"));
1440
1458
  if (Object.keys(properties).length > 0) {
1441
1459
  const firstProp = properties[Object.keys(properties)[0]];
1442
1460
  if (firstProp.through) {
@@ -1445,8 +1463,8 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
1445
1463
  namespace = match[1];
1446
1464
  }
1447
1465
  }
1448
- } else if (Object.keys(relations).length > 0) {
1449
- const firstRel = relations[Object.keys(relations)[0]];
1466
+ } else if (Object.keys(allRelationsMeta).length > 0) {
1467
+ const firstRel = allRelationsMeta[Object.keys(allRelationsMeta)[0]];
1450
1468
  if (firstRel.predicate) {
1451
1469
  const match = firstRel.predicate.match(/^([^:]+:\/\/)/);
1452
1470
  if (match) {
@@ -1508,6 +1526,9 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
1508
1526
  if (propMeta.resolveLanguage) {
1509
1527
  propShape.resolveLanguage = propMeta.resolveLanguage;
1510
1528
  }
1529
+ if (propMeta.getter) {
1530
+ propShape.getter = propMeta.getter;
1531
+ }
1511
1532
  if (propMeta.prologSetter) {
1512
1533
  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.`);
1513
1534
  } else if (propMeta.writable && propMeta.through) {
@@ -1539,46 +1560,47 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
1539
1560
  }
1540
1561
  shape.addProperty(propShape);
1541
1562
  }
1542
- for (const relName in relations) {
1543
- const relMeta = relations[relName];
1544
- if (!relMeta.predicate)
1563
+ for (const relName in allRelationsMeta) {
1564
+ const relMeta = allRelationsMeta[relName];
1565
+ if (!relMeta.predicate && !relMeta.getter)
1545
1566
  continue;
1567
+ const synthesizedPath = relMeta.predicate || `ad4m://getter/${subjectName}/${relName}`;
1546
1568
  const relShape = {
1547
1569
  name: relName,
1548
- path: relMeta.predicate
1570
+ path: synthesizedPath
1549
1571
  };
1550
1572
  relShape.nodeKind = "IRI";
1573
+ relShape.relationKind = relMeta.kind;
1574
+ if (relMeta.kind === "hasOne" || relMeta.kind === "belongsToOne") {
1575
+ relShape.maxCount = 1;
1576
+ } else if (relMeta.maxCount !== void 0) {
1577
+ relShape.maxCount = relMeta.maxCount;
1578
+ }
1579
+ if (relMeta.filter === false) {
1580
+ relShape.filter = false;
1581
+ }
1551
1582
  if (relMeta.local !== void 0) {
1552
1583
  relShape.local = relMeta.local;
1553
1584
  }
1554
- relShape.adder = [{
1555
- action: "addLink",
1556
- source: "this",
1557
- predicate: relMeta.predicate,
1558
- target: "value",
1559
- ...relMeta.local && { local: true }
1560
- }];
1561
- relShape.remover = [{
1562
- action: "removeLink",
1563
- source: "this",
1564
- predicate: relMeta.predicate,
1565
- target: "value",
1566
- ...relMeta.local && { local: true }
1567
- }];
1585
+ if (relMeta.predicate) {
1586
+ relShape.adder = [{
1587
+ action: "addLink",
1588
+ source: "this",
1589
+ predicate: relMeta.predicate,
1590
+ target: "value",
1591
+ ...relMeta.local && { local: true }
1592
+ }];
1593
+ relShape.remover = [{
1594
+ action: "removeLink",
1595
+ source: "this",
1596
+ predicate: relMeta.predicate,
1597
+ target: "value",
1598
+ ...relMeta.local && { local: true }
1599
+ }];
1600
+ }
1568
1601
  if (relMeta.getter) {
1569
1602
  relShape.getter = relMeta.getter;
1570
- } else if (relMeta.where) {
1571
- try {
1572
- const TargetClass = relMeta.target?.();
1573
- const targetMetadata = TargetClass ? TargetClass.getModelMetadata?.() ?? null : null;
1574
- const conditions = compileWhereClause(relMeta.where, targetMetadata);
1575
- if (conditions.length > 0) {
1576
- const escapedPredicate = escapeQueryString(relMeta.predicate);
1577
- relShape.getter = `SELECT ?target WHERE { <Base> <${escapedPredicate}> ?target . ${conditions.join(" ")} }`;
1578
- }
1579
- } catch (e) {
1580
- }
1581
- } else if (relMeta.target && relMeta.filter !== false) {
1603
+ } else if (relMeta.target && relMeta.filter !== false && relMeta.kind !== "belongsToOne" && relMeta.kind !== "belongsToMany") {
1582
1604
  const targetThunk = relMeta.target;
1583
1605
  const predicate = relMeta.predicate;
1584
1606
  let resolved = false;
@@ -1630,6 +1652,37 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
1630
1652
  if (targetSHACL?.shape?.nodeShapeUri) {
1631
1653
  relShape.class = targetSHACL.shape.nodeShapeUri;
1632
1654
  }
1655
+ if (targetSHACL?.name) {
1656
+ relShape.targetClassName = targetSHACL.name;
1657
+ } else {
1658
+ const targetProto = TargetClass.prototype;
1659
+ if (targetProto?.className) {
1660
+ relShape.targetClassName = targetProto.className;
1661
+ }
1662
+ }
1663
+ } catch (e) {
1664
+ console.warn(`[shacl-gen] Failed to resolve target class for relation "${subjectName}.${relName}": ${e instanceof Error ? e.message : String(e)}`);
1665
+ }
1666
+ }
1667
+ if (relMeta.where) {
1668
+ relShape.whereFilter = relMeta.where;
1669
+ try {
1670
+ const TargetClass = relMeta.target?.();
1671
+ const targetMetadata = TargetClass ? TargetClass.getModelMetadata?.() ?? null : null;
1672
+ if (targetMetadata?.properties) {
1673
+ const predicates = {};
1674
+ for (const propName of Object.keys(relMeta.where)) {
1675
+ if (["id", "author", "timestamp"].includes(propName))
1676
+ continue;
1677
+ const propMeta = targetMetadata.properties[propName];
1678
+ if (propMeta?.predicate) {
1679
+ predicates[propName] = propMeta.predicate;
1680
+ }
1681
+ }
1682
+ if (Object.keys(predicates).length > 0) {
1683
+ relShape.wherePredicates = predicates;
1684
+ }
1685
+ }
1633
1686
  } catch (e) {
1634
1687
  }
1635
1688
  }
@@ -1642,6 +1695,9 @@ function buildSHACL(subjectName, target, properties, allRelationsMeta, conforman
1642
1695
  name: subjectName
1643
1696
  };
1644
1697
  }
1698
+ function escapeQueryString(value) {
1699
+ return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
1700
+ }
1645
1701
  var propertyRegistry = /* @__PURE__ */ new WeakMap();
1646
1702
  var relationRegistry = /* @__PURE__ */ new WeakMap();
1647
1703
  var propertiesMetadataCache = /* @__PURE__ */ new WeakMap();
@@ -2268,14 +2324,14 @@ var PerspectiveProxy = class {
2268
2324
  setCachedResult(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, query, result);
2269
2325
  return result;
2270
2326
  }
2271
- async modelQuery(className, queryJson, shapeJson) {
2272
- return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelQuery(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson, shapeJson);
2327
+ async modelQuery(className, queryJson) {
2328
+ return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelQuery(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson);
2273
2329
  }
2274
- async evaluateGetters(className, instanceIds, shapeJson, propertyNames) {
2275
- return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").evaluateGetters(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, instanceIds, shapeJson, propertyNames);
2330
+ async evaluateGetters(className, instanceIds, propertyNames) {
2331
+ return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").evaluateGetters(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, instanceIds, propertyNames);
2276
2332
  }
2277
- async modelSubscribe(className, queryJson, shapeJson) {
2278
- return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelSubscribe(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson, shapeJson);
2333
+ async modelSubscribe(className, queryJson) {
2334
+ return await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").modelSubscribe(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, className, queryJson);
2279
2335
  }
2280
2336
  async add(link, status = "shared", batchId) {
2281
2337
  const result = await __classPrivateFieldGet$a(this, _PerspectiveProxy_client, "f").addLink(__classPrivateFieldGet$a(this, _PerspectiveProxy_handle, "f").uuid, link, status, batchId);
@@ -3322,22 +3378,21 @@ var PerspectiveClient = class {
3322
3378
  }
3323
3379
  return __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.disposeQuery", { uuid, subscriptionId });
3324
3380
  }
3325
- async modelQuery(uuid, className, queryJson, shapeJson) {
3326
- const resultJson = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelQuery", { uuid, class_name: className, query_json: queryJson, shape_json: shapeJson });
3381
+ async modelQuery(uuid, className, queryJson) {
3382
+ const resultJson = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelQuery", { uuid, class_name: className, query_json: queryJson });
3327
3383
  return JSON.parse(resultJson);
3328
3384
  }
3329
- async evaluateGetters(uuid, className, instanceIds, shapeJson, propertyNames) {
3385
+ async evaluateGetters(uuid, className, instanceIds, propertyNames) {
3330
3386
  const resultJson = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.evaluateGetters", {
3331
3387
  uuid,
3332
3388
  class_name: className,
3333
3389
  instance_ids: instanceIds,
3334
- shape_json: shapeJson,
3335
3390
  ...propertyNames && { property_names: propertyNames }
3336
3391
  });
3337
3392
  return JSON.parse(resultJson);
3338
3393
  }
3339
- async modelSubscribe(uuid, className, queryJson, shapeJson) {
3340
- const response = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelSubscribe", { uuid, class_name: className, query_json: queryJson, shape_json: shapeJson });
3394
+ async modelSubscribe(uuid, className, queryJson) {
3395
+ const response = await __classPrivateFieldGet$9(this, _PerspectiveClient_apiClient, "f").call("perspective.modelSubscribe", { uuid, class_name: className, query_json: queryJson });
3341
3396
  return {
3342
3397
  subscriptionId: response.subscription_id,
3343
3398
  result: JSON.parse(response.result)
@@ -9442,9 +9497,6 @@ var ModelQueryBuilder = class {
9442
9497
  this.modelClassName = className;
9443
9498
  return this;
9444
9499
  }
9445
- engine(_eng) {
9446
- return this;
9447
- }
9448
9500
  async get() {
9449
9501
  return await this.executeSparqlQuery();
9450
9502
  }
@@ -9465,8 +9517,8 @@ var ModelQueryBuilder = class {
9465
9517
  async subscribe(callback) {
9466
9518
  this.dispose();
9467
9519
  const ctor = this.ctor;
9468
- const { className, queryJson, shapeJson } = ctor.prepareModelQueryParams(this.queryParams, this.modelClassName);
9469
- const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson, shapeJson);
9520
+ const { className, queryJson } = ctor.prepareModelQueryParams(this.queryParams, this.modelClassName);
9521
+ const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson);
9470
9522
  const parseResults = (raw) => {
9471
9523
  return ctor.parseModelResult(this.perspective, raw, this.queryParams.include, this.queryParams.properties);
9472
9524
  };
@@ -9563,8 +9615,8 @@ var ModelQueryBuilder = class {
9563
9615
  async countSubscribe(callback) {
9564
9616
  this.dispose();
9565
9617
  const countParams = { ...this.queryParams, limit: 0 };
9566
- const { className, queryJson, shapeJson } = this.ctor.prepareModelQueryParams(countParams, this.modelClassName);
9567
- const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson, shapeJson);
9618
+ const { className, queryJson } = this.ctor.prepareModelQueryParams(countParams, this.modelClassName);
9619
+ const { subscriptionId, result: initialModelResult } = await this.perspective.modelSubscribe(className, queryJson);
9568
9620
  const parseCount = (raw) => {
9569
9621
  const data = typeof raw === "string" ? JSON.parse(raw) : raw;
9570
9622
  return data.totalCount ?? 0;
@@ -9639,8 +9691,8 @@ var ModelQueryBuilder = class {
9639
9691
  const subscriptionParams = { ...this.queryParams || {} };
9640
9692
  delete subscriptionParams.limit;
9641
9693
  delete subscriptionParams.offset;
9642
- const { className, queryJson, shapeJson } = ctor.prepareModelQueryParams(subscriptionParams, this.modelClassName);
9643
- const { subscriptionId } = await this.perspective.modelSubscribe(className, queryJson, shapeJson);
9694
+ const { className, queryJson } = ctor.prepareModelQueryParams(subscriptionParams, this.modelClassName);
9695
+ const { subscriptionId } = await this.perspective.modelSubscribe(className, queryJson);
9644
9696
  const paginatedQuery = {
9645
9697
  ...this.queryParams || {},
9646
9698
  limit: pageSize,
@@ -9732,34 +9784,6 @@ function defaultFileDecode(resolved) {
9732
9784
  }
9733
9785
  return resolved;
9734
9786
  }
9735
- function enrichShapeForIncludes(metadata, include, allRelMeta) {
9736
- for (const [relName, includeVal] of Object.entries(include)) {
9737
- if (!includeVal)
9738
- continue;
9739
- const meta = allRelMeta[relName];
9740
- if (!meta?.target)
9741
- continue;
9742
- const TargetClass = meta.target();
9743
- const targetMeta = JSON.parse(JSON.stringify(TargetClass.getModelMetadata()));
9744
- if (!metadata.relations[relName]) {
9745
- metadata.relations[relName] = {
9746
- name: relName,
9747
- predicate: meta.predicate,
9748
- direction: meta.kind === "belongsToMany" || meta.kind === "belongsToOne" ? "reverse" : "forward"
9749
- };
9750
- }
9751
- const rel = metadata.relations[relName];
9752
- rel.kind = meta.kind;
9753
- rel.maxCount = meta.maxCount;
9754
- rel.targetShape = targetMeta;
9755
- rel.targetClassName = targetMeta.className;
9756
- const nested = typeof includeVal === "object" && includeVal !== null ? includeVal.include : void 0;
9757
- if (nested) {
9758
- const targetRelMeta = getRelationsMetadata(TargetClass);
9759
- enrichShapeForIncludes(targetMeta, nested, targetRelMeta);
9760
- }
9761
- }
9762
- }
9763
9787
  function jsonToModelInstance(ModelClass, perspective, json, include, properties) {
9764
9788
  const instance = new ModelClass(perspective, json.id || json.baseExpression);
9765
9789
  if (properties) {
@@ -10142,12 +10166,12 @@ var Ad4mModel = class {
10142
10166
  const allRelMeta = getRelationsMetadata(this);
10143
10167
  for (const [, proj] of Object.entries(projections)) {
10144
10168
  const relMeta = allRelMeta[proj.from];
10145
- if (!proj.targetShape && relMeta?.target) {
10169
+ if (!proj.targetClassName && relMeta?.target) {
10146
10170
  try {
10147
10171
  const TargetClass = relMeta.target();
10148
10172
  const targetMeta = TargetClass.getModelMetadata?.();
10149
- if (targetMeta) {
10150
- proj.targetShape = targetMeta;
10173
+ if (targetMeta?.className) {
10174
+ proj.targetClassName = targetMeta.className;
10151
10175
  }
10152
10176
  } catch (e) {
10153
10177
  console.debug(`prepareModelQueryParams: target class unavailable for projection:`, e);
@@ -10169,56 +10193,9 @@ var Ad4mModel = class {
10169
10193
  if (query.count !== void 0)
10170
10194
  queryInput.count = query.count;
10171
10195
  queryInput.deepQuery = query.deepQuery ?? true;
10172
- if (queryInput.include) {
10173
- const allRelMeta = getRelationsMetadata(this);
10174
- enrichShapeForIncludes(metadata, queryInput.include, allRelMeta);
10175
- }
10176
- {
10177
- const allRelMeta = getRelationsMetadata(this);
10178
- for (const [relName, relMeta] of Object.entries(metadata.relations)) {
10179
- const rel = relMeta;
10180
- if (rel.getter || rel.direction === "reverse" || rel.filter === false)
10181
- continue;
10182
- const meta = allRelMeta[relName];
10183
- if (!meta?.target)
10184
- continue;
10185
- try {
10186
- const TargetClass = meta.target();
10187
- const filter = buildConformanceFilter(meta.predicate, TargetClass);
10188
- if (filter) {
10189
- rel.getter = filter.getter;
10190
- }
10191
- if (rel.where) {
10192
- try {
10193
- const targetMetadata = TargetClass.getModelMetadata?.() ?? null;
10194
- if (targetMetadata) {
10195
- const predicates = {};
10196
- for (const propName of Object.keys(rel.where)) {
10197
- if (["id", "author", "timestamp"].includes(propName))
10198
- continue;
10199
- const propMeta = targetMetadata.properties[propName];
10200
- if (propMeta?.predicate) {
10201
- predicates[propName] = propMeta.predicate;
10202
- }
10203
- }
10204
- if (Object.keys(predicates).length > 0) {
10205
- rel.whereFilter = rel.where;
10206
- rel.wherePredicates = predicates;
10207
- }
10208
- }
10209
- } catch (e) {
10210
- console.debug(`prepareModelQueryParams: target metadata unavailable for relation '${relName}':`, e);
10211
- }
10212
- }
10213
- } catch (e) {
10214
- console.debug(`prepareModelQueryParams: target class unavailable for relation '${relName}':`, e);
10215
- }
10216
- }
10217
- }
10218
10196
  return {
10219
10197
  className,
10220
10198
  queryJson: JSON.stringify(queryInput),
10221
- shapeJson: JSON.stringify(metadata),
10222
10199
  metadata
10223
10200
  };
10224
10201
  }
@@ -10261,8 +10238,8 @@ var Ad4mModel = class {
10261
10238
  }));
10262
10239
  }
10263
10240
  static async executeModelQuery(perspective, query = {}, classNameOverride) {
10264
- const { className, queryJson, shapeJson } = this.prepareModelQueryParams(query, classNameOverride);
10265
- const result = await perspective.modelQuery(className, queryJson, shapeJson);
10241
+ const { className, queryJson } = this.prepareModelQueryParams(query, classNameOverride);
10242
+ const result = await perspective.modelQuery(className, queryJson);
10266
10243
  const instances = result.instances.map((json) => {
10267
10244
  return jsonToModelInstance(this, perspective, json, query.include, query.properties);
10268
10245
  });
@@ -10276,28 +10253,30 @@ var Ad4mModel = class {
10276
10253
  totalCount: result.totalCount
10277
10254
  };
10278
10255
  }
10279
- static async findAll(perspective, query = {}, _engine) {
10280
- if (query.properties && query.properties.length === 0) {
10256
+ static async findAll(perspective, query) {
10257
+ const q = query ?? {};
10258
+ if (q.properties && q.properties.length === 0) {
10281
10259
  throw new Error("properties[] must not be empty \u2014 omit the field to return all properties, or specify at least one field name");
10282
10260
  }
10283
- const { results } = await this.executeModelQuery(perspective, query);
10261
+ const { results } = await this.executeModelQuery(perspective, q);
10284
10262
  return results;
10285
10263
  }
10286
- static async findOne(perspective, query = {}, _engine) {
10287
- const limitedQuery = { ...query, limit: 1 };
10264
+ static async findOne(perspective, query) {
10265
+ const limitedQuery = { ...query ?? {}, limit: 1 };
10288
10266
  const results = await this.findAll(perspective, limitedQuery);
10289
10267
  return results[0] ?? null;
10290
10268
  }
10291
- static async findAllAndCount(perspective, query = {}, _engine) {
10292
- return await this.executeModelQuery(perspective, query);
10269
+ static async findAllAndCount(perspective, query) {
10270
+ const out = await this.executeModelQuery(perspective, query ?? {});
10271
+ return out;
10293
10272
  }
10294
- static async paginate(perspective, pageSize, pageNumber, query, _engine) {
10295
- const paginationQuery = { ...query || {}, limit: pageSize, offset: pageSize * (pageNumber - 1), count: true };
10273
+ static async paginate(perspective, pageSize, pageNumber, query) {
10274
+ const paginationQuery = { ...query ?? {}, limit: pageSize, offset: pageSize * (pageNumber - 1), count: true };
10296
10275
  const { results, totalCount } = await this.executeModelQuery(perspective, paginationQuery);
10297
10276
  return { results, totalCount, pageSize, pageNumber };
10298
10277
  }
10299
- static async count(perspective, query = {}) {
10300
- const { totalCount } = await this.executeModelQuery(perspective, { ...query, limit: 0 });
10278
+ static async count(perspective, query) {
10279
+ const { totalCount } = await this.executeModelQuery(perspective, { ...query ?? {}, limit: 0 });
10301
10280
  return totalCount;
10302
10281
  }
10303
10282
  async setProperty(key, value, batchId) {
@@ -10493,26 +10472,8 @@ var Ad4mModel = class {
10493
10472
  if (instances.length === 0)
10494
10473
  return;
10495
10474
  const metadata = this.getModelMetadata();
10496
- const allRelMeta = getRelationsMetadata(this);
10497
- for (const [relName, relMeta] of Object.entries(metadata.relations)) {
10498
- const rel = relMeta;
10499
- if (rel.getter || rel.direction === "reverse" || rel.filter === false)
10500
- continue;
10501
- const meta = allRelMeta[relName];
10502
- if (!meta?.target)
10503
- continue;
10504
- try {
10505
- const TargetClass = meta.target();
10506
- const filter = buildConformanceFilter(meta.predicate, TargetClass);
10507
- if (filter)
10508
- rel.getter = filter.getter;
10509
- } catch (e) {
10510
- console.debug(`evaluateGetters: target class unavailable for relation '${relName}':`, e);
10511
- }
10512
- }
10513
- const shapeJson = JSON.stringify(metadata);
10514
10475
  const instanceIds = instances.map((inst) => inst.id || inst._baseExpression);
10515
- const result = await perspective.evaluateGetters(metadata.className, instanceIds, shapeJson, propertyNames);
10476
+ const result = await perspective.evaluateGetters(metadata.className, instanceIds, propertyNames);
10516
10477
  const evaluatedPropertyNames = [];
10517
10478
  for (const [propName, propMeta] of Object.entries(metadata.properties)) {
10518
10479
  if (propMeta.getter) {
@@ -10646,7 +10607,7 @@ var Ad4mModel = class {
10646
10607
  return result;
10647
10608
  }
10648
10609
  static query(perspective, query) {
10649
- return new ModelQueryBuilder(perspective, this, query);
10610
+ return new ModelQueryBuilder(perspective, this, query ?? {});
10650
10611
  }
10651
10612
  static fromJSONSchema(schema, options) {
10652
10613
  return buildModelFromJSONSchema(this, schema, options);
@@ -11143,7 +11104,18 @@ var Ad4mConnect = class extends EventTarget {
11143
11104
  console.warn("[Ad4m Connect] Rejected AD4M_CONFIG from invalid source (not parent window)");
11144
11105
  return;
11145
11106
  }
11146
- if (this.options.allowedOrigins && this.options.allowedOrigins.length > 0) {
11107
+ if (event.data.proxy) {
11108
+ if (!this.options.allowedOrigins || this.options.allowedOrigins.length === 0) {
11109
+ console.error("[Ad4m Connect] proxy mode requires allowedOrigins to be configured. Rejecting AD4M_CONFIG to prevent arbitrary sites from embedding this app.");
11110
+ this.rejectEmbedded(new Error("proxy mode requires allowedOrigins"));
11111
+ return;
11112
+ }
11113
+ if (!event.origin || !this.options.allowedOrigins.includes(event.origin)) {
11114
+ console.warn("[Ad4m Connect] Rejected AD4M_CONFIG from unauthorized origin:", event.origin);
11115
+ this.rejectEmbedded(new Error(`Unauthorized origin: ${event.origin}`));
11116
+ return;
11117
+ }
11118
+ } else if (this.options.allowedOrigins && this.options.allowedOrigins.length > 0) {
11147
11119
  if (!event.origin || !this.options.allowedOrigins.includes(event.origin)) {
11148
11120
  console.warn("[Ad4m Connect] Rejected AD4M_CONFIG from unauthorized origin:", event.origin);
11149
11121
  this.rejectEmbedded(new Error(`Unauthorized origin: ${event.origin}`));
@@ -11161,12 +11133,17 @@ var Ad4mConnect = class extends EventTarget {
11161
11133
  } else {
11162
11134
  removeLocal("ad4m-token");
11163
11135
  }
11136
+ if (!event.origin || event.origin === "null") {
11137
+ throw new Error("AD4M proxy mode requires a non-opaque parent origin. Ensure the host iframe is not sandboxed without allow-same-origin.");
11138
+ }
11139
+ const parentOrigin2 = event.origin;
11140
+ const wsImpl = (url) => new PostMessageWebSocket(url, parentOrigin2);
11164
11141
  this.notifyConnectionChange("connecting");
11165
11142
  this.ad4mClient = new Ad4mClient(
11166
11143
  "http://proxy",
11167
11144
  normalizedToken,
11168
11145
  false,
11169
- { webSocketImpl: PostMessageWebSocket }
11146
+ { webSocketImpl: wsImpl }
11170
11147
  );
11171
11148
  this.notifyConnectionChange("connected");
11172
11149
  yield this.checkAuth();