@_linked/core 2.34.0 → 2.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +54 -0
  3. package/lib/esm/index.d.ts +5 -1
  4. package/lib/esm/index.js +6 -0
  5. package/lib/esm/index.js.map +1 -1
  6. package/lib/esm/live/LiveQueryStore.d.ts +22 -0
  7. package/lib/esm/live/LiveQueryStore.js +88 -20
  8. package/lib/esm/live/LiveQueryStore.js.map +1 -1
  9. package/lib/esm/live/changes.d.ts +9 -1
  10. package/lib/esm/live/changes.js +7 -2
  11. package/lib/esm/live/changes.js.map +1 -1
  12. package/lib/esm/live/keys.d.ts +6 -0
  13. package/lib/esm/live/keys.js +10 -1
  14. package/lib/esm/live/keys.js.map +1 -1
  15. package/lib/esm/live/matcher.d.ts +4 -1
  16. package/lib/esm/live/matcher.js +10 -5
  17. package/lib/esm/live/matcher.js.map +1 -1
  18. package/lib/esm/queries/AskBuilder.d.ts +6 -0
  19. package/lib/esm/queries/AskBuilder.js +14 -0
  20. package/lib/esm/queries/AskBuilder.js.map +1 -1
  21. package/lib/esm/queries/CountBuilder.d.ts +6 -0
  22. package/lib/esm/queries/CountBuilder.js +14 -0
  23. package/lib/esm/queries/CountBuilder.js.map +1 -1
  24. package/lib/esm/queries/CreateBuilder.d.ts +4 -0
  25. package/lib/esm/queries/CreateBuilder.js +15 -1
  26. package/lib/esm/queries/CreateBuilder.js.map +1 -1
  27. package/lib/esm/queries/DeleteBuilder.d.ts +4 -0
  28. package/lib/esm/queries/DeleteBuilder.js +15 -1
  29. package/lib/esm/queries/DeleteBuilder.js.map +1 -1
  30. package/lib/esm/queries/FieldSet.d.ts +17 -0
  31. package/lib/esm/queries/FieldSet.js +110 -22
  32. package/lib/esm/queries/FieldSet.js.map +1 -1
  33. package/lib/esm/queries/IRLower.js +3 -2
  34. package/lib/esm/queries/IRLower.js.map +1 -1
  35. package/lib/esm/queries/IRMutation.js +15 -14
  36. package/lib/esm/queries/IRMutation.js.map +1 -1
  37. package/lib/esm/queries/MutationQuery.js +3 -2
  38. package/lib/esm/queries/MutationQuery.js.map +1 -1
  39. package/lib/esm/queries/MutationSerialization.js +2 -2
  40. package/lib/esm/queries/MutationSerialization.js.map +1 -1
  41. package/lib/esm/queries/PropertyPath.js +4 -3
  42. package/lib/esm/queries/PropertyPath.js.map +1 -1
  43. package/lib/esm/queries/QueryBuilder.d.ts +7 -0
  44. package/lib/esm/queries/QueryBuilder.js +42 -4
  45. package/lib/esm/queries/QueryBuilder.js.map +1 -1
  46. package/lib/esm/queries/QueryContext.js +2 -0
  47. package/lib/esm/queries/QueryContext.js.map +1 -1
  48. package/lib/esm/queries/SelectQuery.js +8 -3
  49. package/lib/esm/queries/SelectQuery.js.map +1 -1
  50. package/lib/esm/queries/UpdateBuilder.d.ts +4 -0
  51. package/lib/esm/queries/UpdateBuilder.js +15 -1
  52. package/lib/esm/queries/UpdateBuilder.js.map +1 -1
  53. package/lib/esm/queries/fromJSON.d.ts +12 -1
  54. package/lib/esm/queries/fromJSON.js +5 -1
  55. package/lib/esm/queries/fromJSON.js.map +1 -1
  56. package/lib/esm/queries/lower.js +12 -5
  57. package/lib/esm/queries/lower.js.map +1 -1
  58. package/lib/esm/queries/queryDependencies.js +14 -10
  59. package/lib/esm/queries/queryDependencies.js.map +1 -1
  60. package/lib/esm/queries/resolveShape.js +16 -3
  61. package/lib/esm/queries/resolveShape.js.map +1 -1
  62. package/lib/esm/shapes/Shape.js +2 -1
  63. package/lib/esm/shapes/Shape.js.map +1 -1
  64. package/lib/esm/shapes/nodeShapeData.js +7 -10
  65. package/lib/esm/shapes/nodeShapeData.js.map +1 -1
  66. package/lib/esm/shapes/registerRuntimeShape.js +3 -1
  67. package/lib/esm/shapes/registerRuntimeShape.js.map +1 -1
  68. package/lib/esm/shapes/syncShapes.d.ts +6 -2
  69. package/lib/esm/shapes/syncShapes.js +16 -9
  70. package/lib/esm/shapes/syncShapes.js.map +1 -1
  71. package/lib/esm/shapes/validation.js +10 -6
  72. package/lib/esm/shapes/validation.js.map +1 -1
  73. package/lib/esm/sparql/irToAlgebra.js +117 -52
  74. package/lib/esm/sparql/irToAlgebra.js.map +1 -1
  75. package/lib/esm/sparql/ownedLinkCheck.js +6 -1
  76. package/lib/esm/sparql/ownedLinkCheck.js.map +1 -1
  77. package/lib/esm/utils/LinkedStorage.d.ts +7 -0
  78. package/lib/esm/utils/LinkedStorage.js +39 -12
  79. package/lib/esm/utils/LinkedStorage.js.map +1 -1
  80. package/lib/esm/utils/ShapeCatalog.d.ts +57 -0
  81. package/lib/esm/utils/ShapeCatalog.js +86 -0
  82. package/lib/esm/utils/ShapeCatalog.js.map +1 -0
  83. package/lib/esm/utils/ShapeClass.d.ts +73 -8
  84. package/lib/esm/utils/ShapeClass.js +245 -66
  85. package/lib/esm/utils/ShapeClass.js.map +1 -1
  86. package/lib/esm/utils/linkedError.d.ts +35 -0
  87. package/lib/esm/utils/linkedError.js +52 -0
  88. package/lib/esm/utils/linkedError.js.map +1 -0
  89. package/lib/esm/utils/registryCache.d.ts +15 -0
  90. package/lib/esm/utils/registryCache.js +50 -0
  91. package/lib/esm/utils/registryCache.js.map +1 -0
  92. package/lib/esm/utils/sharedState.d.ts +25 -0
  93. package/lib/esm/utils/sharedState.js +34 -0
  94. package/lib/esm/utils/sharedState.js.map +1 -0
  95. package/lib/esm/utils/unresolvedShape.d.ts +42 -0
  96. package/lib/esm/utils/unresolvedShape.js +68 -0
  97. package/lib/esm/utils/unresolvedShape.js.map +1 -0
  98. package/package.json +1 -1
@@ -1,10 +1,11 @@
1
1
  import { getUniquePropertyShapes, getPropertyShape } from '../shapes/nodeShapeData.js';
2
2
  import { PropertyPath, walkPropertyPath } from './PropertyPath.js';
3
- import { getShapeClass, getAllShapeClasses, getNodeShape } from '../utils/ShapeClass.js';
3
+ import { captureCatalog, getActiveShapeCatalog, getAllNodeShapes, getAllShapeClasses, getNodeShape, getShapeClass, withShapeCatalog, getQueryShapeClass, } from '../utils/ShapeClass.js';
4
4
  import { createProxiedPathBuilder } from './ProxiedPathBuilder.js';
5
5
  import { isExpressionNode, ExpressionNode } from '../expressions/ExpressionNode.js';
6
6
  import { encodeValueExpr, decodeValueExpr } from './DslJsonExpression.js';
7
7
  import { serializeWherePath, deserializeWherePath, } from './QueryBuilderSerialization.js';
8
+ import { topLevelDetails, unresolvedShapeError, unresolvedValueShapeError } from '../utils/unresolvedShape.js';
8
9
  const isQueryBuilderObject = (obj) => obj !== null &&
9
10
  typeof obj === 'object' &&
10
11
  'property' in obj &&
@@ -45,11 +46,33 @@ const RELATION_OPTION_KEYS = new Set([
45
46
  * Every mutation method returns a new FieldSet — the original is never modified.
46
47
  */
47
48
  export class FieldSet {
48
- constructor(shape, entries) {
49
+ constructor(shape, entries, catalog = FieldSet.captureFor(shape)) {
49
50
  this.shape = shape;
50
51
  this.entries = entries;
52
+ this._catalog = catalog;
53
+ }
54
+ /** The catalog this FieldSet resolves shapes in (undefined = the global registry). */
55
+ get catalog() {
56
+ return this._catalog;
57
+ }
58
+ /**
59
+ * The catalog a FieldSet rooted at `shape` captures: the active one for an IRI or a
60
+ * shape it holds, none for a shape it does not (an authored class built by code that
61
+ * runs inside a project scope), else the catalog an adapter class came from.
62
+ */
63
+ static captureFor(shape) {
64
+ if (typeof shape === 'function')
65
+ return captureCatalog(shape);
66
+ const active = getActiveShapeCatalog();
67
+ if (active === undefined || typeof shape === 'string')
68
+ return active;
69
+ return active.has(shape.id) ? active : undefined;
51
70
  }
52
71
  static for(shape, fieldsOrFn) {
72
+ const catalog = FieldSet.captureFor(shape);
73
+ if (catalog !== getActiveShapeCatalog()) {
74
+ return withShapeCatalog(catalog, () => FieldSet.for(shape, fieldsOrFn));
75
+ }
53
76
  const resolved = FieldSet.resolveShapeInput(shape);
54
77
  const resolvedShape = resolved.nodeShape;
55
78
  if (typeof fieldsOrFn === 'function') {
@@ -97,6 +120,10 @@ export class FieldSet {
97
120
  }
98
121
  static all(shape, opts) {
99
122
  var _a;
123
+ const catalog = FieldSet.captureFor(shape);
124
+ if (catalog !== getActiveShapeCatalog()) {
125
+ return withShapeCatalog(catalog, () => FieldSet.all(shape, opts));
126
+ }
100
127
  const depth = (_a = opts === null || opts === void 0 ? void 0 : opts.depth) !== null && _a !== void 0 ? _a : 1;
101
128
  if (depth < 1) {
102
129
  throw new Error('FieldSet.all() requires depth >= 1. Use a node reference ({id}) for depth 0.');
@@ -117,7 +144,7 @@ export class FieldSet {
117
144
  const entry = { path: new PropertyPath(nodeShape, [ps]) };
118
145
  // If depth > 1, recurse into nested shapes
119
146
  if (depth > 1 && ps.valueShape) {
120
- const nestedShapeClass = getShapeClass(ps.valueShape);
147
+ const nestedShapeClass = getQueryShapeClass(ps.valueShape);
121
148
  if ((nestedShapeClass === null || nestedShapeClass === void 0 ? void 0 : nestedShapeClass.shape) && !visited.has(nestedShapeClass.shape.id)) {
122
149
  visited.add(nestedShapeClass.shape.id);
123
150
  const nestedFs = FieldSet.allForShape(nestedShapeClass.shape, depth - 1, visited);
@@ -158,15 +185,19 @@ export class FieldSet {
158
185
  }
159
186
  }
160
187
  }
161
- return new FieldSet(shape, merged);
188
+ return new FieldSet(shape, merged, sets[0]._catalog);
162
189
  }
163
190
  // ---------------------------------------------------------------------------
164
191
  // Composition methods — each returns a new FieldSet
165
192
  // ---------------------------------------------------------------------------
166
193
  /** Returns a new FieldSet with only the given fields. */
167
194
  select(fields) {
195
+ const catalog = this._catalog;
196
+ if (catalog !== getActiveShapeCatalog()) {
197
+ return withShapeCatalog(catalog, () => this.select(fields));
198
+ }
168
199
  const entries = FieldSet.resolveInputs(this.shape, fields);
169
- return new FieldSet(this.shape, entries);
200
+ return new FieldSet(this.shape, entries, this._catalog);
170
201
  }
171
202
  /**
172
203
  * Clone this FieldSet, preserving the sub-select carrier fields
@@ -174,7 +205,7 @@ export class FieldSet {
174
205
  * applying the supplied overrides. Used by `.limit()`/`.offset()`/`.orderBy()`.
175
206
  */
176
207
  cloneWith(overrides) {
177
- const clone = new FieldSet(this.shape, this.entries);
208
+ const clone = new FieldSet(this.shape, this.entries, this._catalog);
178
209
  // The sub-select carrier fields are declared `readonly` (normally set once at
179
210
  // construction via `forSubSelect`). Copy this FieldSet's identity onto the
180
211
  // clone through a mutable view, then layer the pagination overrides on top.
@@ -201,6 +232,10 @@ export class FieldSet {
201
232
  * the rest of the DSL, or a property-name string (`.orderBy('name')`).
202
233
  */
203
234
  orderBy(paths, direction = 'ASC') {
235
+ const catalog = this._catalog;
236
+ if (catalog !== getActiveShapeCatalog()) {
237
+ return withShapeCatalog(catalog, () => this.orderBy(paths, direction));
238
+ }
204
239
  const orderBy = typeof paths === 'function'
205
240
  ? this.orderByFromProxy(paths, direction)
206
241
  : (Array.isArray(paths) ? paths : [paths]).map((label) => {
@@ -231,6 +266,10 @@ export class FieldSet {
231
266
  }
232
267
  /** Returns a new FieldSet with additional entries. */
233
268
  add(fields) {
269
+ const catalog = this._catalog;
270
+ if (catalog !== getActiveShapeCatalog()) {
271
+ return withShapeCatalog(catalog, () => this.add(fields));
272
+ }
234
273
  const newEntries = FieldSet.resolveInputs(this.shape, fields);
235
274
  // Deduplicate
236
275
  const existing = new Set(this.entries.map((e) => e.path.toString()));
@@ -240,24 +279,28 @@ export class FieldSet {
240
279
  combined.push(entry);
241
280
  }
242
281
  }
243
- return new FieldSet(this.shape, combined);
282
+ return new FieldSet(this.shape, combined, this._catalog);
244
283
  }
245
284
  /** Returns a new FieldSet without entries matching the given labels. */
246
285
  remove(labels) {
247
286
  const labelSet = new Set(labels);
248
287
  const filtered = this.entries.filter((e) => { var _a; return !labelSet.has((_a = e.path.terminal) === null || _a === void 0 ? void 0 : _a.label); });
249
- return new FieldSet(this.shape, filtered);
288
+ return new FieldSet(this.shape, filtered, this._catalog);
250
289
  }
251
290
  /** Synonym for replacing all entries — returns a new FieldSet with only the given fields. */
252
291
  set(fields) {
292
+ const catalog = this._catalog;
293
+ if (catalog !== getActiveShapeCatalog()) {
294
+ return withShapeCatalog(catalog, () => this.set(fields));
295
+ }
253
296
  const entries = FieldSet.resolveInputs(this.shape, fields);
254
- return new FieldSet(this.shape, entries);
297
+ return new FieldSet(this.shape, entries, this._catalog);
255
298
  }
256
299
  /** Returns a new FieldSet keeping only entries matching the given labels. */
257
300
  pick(labels) {
258
301
  const labelSet = new Set(labels);
259
302
  const filtered = this.entries.filter((e) => { var _a; return labelSet.has((_a = e.path.terminal) === null || _a === void 0 ? void 0 : _a.label); });
260
- return new FieldSet(this.shape, filtered);
303
+ return new FieldSet(this.shape, filtered, this._catalog);
261
304
  }
262
305
  /** Returns all PropertyPaths in this FieldSet. */
263
306
  paths() {
@@ -275,6 +318,10 @@ export class FieldSet {
275
318
  * Shape is identified by its IRI, paths by dot-separated labels.
276
319
  */
277
320
  toJSON() {
321
+ const catalog = this._catalog;
322
+ if (catalog !== getActiveShapeCatalog()) {
323
+ return withShapeCatalog(catalog, () => this.toJSON());
324
+ }
278
325
  return { shape: this.shape.id, fields: this.toFieldsJSON() };
279
326
  }
280
327
  /** Serialize just the field entries (used for nested relation sub-fields). */
@@ -337,7 +384,7 @@ export class FieldSet {
337
384
  var _a, _b;
338
385
  const seg = entry.path.segments[idx];
339
386
  const valueShapeId = (_a = seg === null || seg === void 0 ? void 0 : seg.valueShape) === null || _a === void 0 ? void 0 : _a.id;
340
- return (valueShapeId && ((_b = getShapeClass(valueShapeId)) === null || _b === void 0 ? void 0 : _b.shape)) || this.shape;
387
+ return (valueShapeId && ((_b = getQueryShapeClass(valueShapeId)) === null || _b === void 0 ? void 0 : _b.shape)) || this.shape;
341
388
  }
342
389
  /**
343
390
  * Reconstruct a FieldSet from a JSON object.
@@ -352,7 +399,7 @@ export class FieldSet {
352
399
  }
353
400
  /** Parse one field entry (string leaf / computed / relation-keyed) against `shape`. */
354
401
  static parseField(shape, raw) {
355
- var _a, _b, _c, _d, _e;
402
+ var _a, _b, _c, _d;
356
403
  // Leaf path (may carry inline `as(Shape)` casts).
357
404
  if (typeof raw === 'string') {
358
405
  return { path: FieldSet.walkPathWithCasts(shape, raw) };
@@ -392,7 +439,7 @@ export class FieldSet {
392
439
  const idx = (_a = opts.whereIndex) !== null && _a !== void 0 ? _a : path.segments.length - 1;
393
440
  const seg = path.segments[idx];
394
441
  const valueShapeId = (_b = seg === null || seg === void 0 ? void 0 : seg.valueShape) === null || _b === void 0 ? void 0 : _b.id;
395
- const scopedShape = (valueShapeId && ((_c = getShapeClass(valueShapeId)) === null || _c === void 0 ? void 0 : _c.shape)) || shape;
442
+ const scopedShape = (valueShapeId && ((_c = getQueryShapeClass(valueShapeId)) === null || _c === void 0 ? void 0 : _c.shape)) || shape;
396
443
  entry.scopedFilter = deserializeWherePath(scopedShape, opts.where);
397
444
  entry.scopedFilterIndex = idx;
398
445
  }
@@ -413,17 +460,37 @@ export class FieldSet {
413
460
  if (subFields) {
414
461
  const nested = opts.shape
415
462
  ? FieldSet.resolveShape(opts.shape)
416
- : (_e = FieldSet.nestedShapeOf(path)) !== null && _e !== void 0 ? _e : shape;
463
+ : FieldSet.requireNestedShapeOf(path, shape);
417
464
  entry.subSelect = FieldSet.fromFields(nested, subFields);
418
465
  }
419
466
  return entry;
420
467
  }
468
+ /**
469
+ * The shape sub-fields of `path` are read against: its terminal segment's value shape, or
470
+ * `shape` when that segment declares none. A declared value shape that does not resolve is
471
+ * an error: reading the sub-fields against `shape` instead would resolve them on the wrong
472
+ * shape (or fail with a message about the wrong property).
473
+ */
474
+ static requireNestedShapeOf(path, shape) {
475
+ var _a;
476
+ const nested = FieldSet.nestedShapeOf(path);
477
+ if (nested)
478
+ return nested;
479
+ const seg = path.segments[path.segments.length - 1];
480
+ if ((_a = seg === null || seg === void 0 ? void 0 : seg.valueShape) === null || _a === void 0 ? void 0 : _a.id) {
481
+ const owner = path.segments.length > 1
482
+ ? FieldSet.nestedShapeOf(new PropertyPath(path.rootShape, path.segments.slice(0, -1)))
483
+ : path.rootShape;
484
+ throw unresolvedValueShapeError(`Cannot resolve valueShape '${seg.valueShape.id}' for property '${seg.label}' in path '${path.toString()}'`, seg, owner);
485
+ }
486
+ return shape;
487
+ }
421
488
  /** The shape reached at the end of a relation path (its terminal segment's value shape). */
422
489
  static nestedShapeOf(path) {
423
490
  var _a, _b;
424
491
  const seg = path.segments[path.segments.length - 1];
425
492
  const valueShapeId = (_a = seg === null || seg === void 0 ? void 0 : seg.valueShape) === null || _a === void 0 ? void 0 : _a.id;
426
- return (valueShapeId && ((_b = getShapeClass(valueShapeId)) === null || _b === void 0 ? void 0 : _b.shape)) || undefined;
493
+ return (valueShapeId && ((_b = getQueryShapeClass(valueShapeId)) === null || _b === void 0 ? void 0 : _b.shape)) || undefined;
427
494
  }
428
495
  // ---------------------------------------------------------------------------
429
496
  // Private helpers
@@ -433,8 +500,21 @@ export class FieldSet {
433
500
  * Accepts: ShapeConstructor (class with .shape), NodeShapeData, or IRI string.
434
501
  */
435
502
  static resolveShapeInput(shape) {
503
+ var _a;
504
+ // Inside a catalog the catalog's data is the authority for every IRI it holds, so an
505
+ // authored class (or metadata) for one of them resolves to the catalog's shape — as
506
+ // `resolveShape` does for the builders.
507
+ const catalog = getActiveShapeCatalog();
508
+ if (catalog !== undefined && typeof shape !== 'string') {
509
+ const id = typeof shape === 'function' ? (_a = shape.shape) === null || _a === void 0 ? void 0 : _a.id : shape === null || shape === void 0 ? void 0 : shape.id;
510
+ const own = id ? catalog.get(id) : undefined;
511
+ if (own) {
512
+ const shapeClass = getQueryShapeClass(id);
513
+ return shapeClass ? { nodeShape: own, shapeClass } : { nodeShape: own };
514
+ }
515
+ }
436
516
  if (typeof shape === 'string') {
437
- const shapeClass = getShapeClass(shape);
517
+ const shapeClass = getQueryShapeClass(shape);
438
518
  if (shapeClass === null || shapeClass === void 0 ? void 0 : shapeClass.shape) {
439
519
  return { nodeShape: shapeClass.shape, shapeClass };
440
520
  }
@@ -442,7 +522,7 @@ export class FieldSet {
442
522
  // below is already supported, it just was not reachable from an IRI.
443
523
  const nodeShape = getNodeShape(shape);
444
524
  if (!nodeShape) {
445
- throw new Error(`Cannot resolve shape for '${shape}'`);
525
+ throw unresolvedShapeError(`Cannot resolve shape for '${shape}'`, topLevelDetails(shape));
446
526
  }
447
527
  return { nodeShape };
448
528
  }
@@ -452,7 +532,7 @@ export class FieldSet {
452
532
  }
453
533
  // NodeShapeData: has .id directly — try to look up its ShapeConstructor for full proxy support
454
534
  const nodeShape = shape;
455
- const shapeClass = nodeShape.id ? getShapeClass(nodeShape.id) : undefined;
535
+ const shapeClass = nodeShape.id ? getQueryShapeClass(nodeShape.id) : undefined;
456
536
  return shapeClass
457
537
  ? { nodeShape, shapeClass }
458
538
  : { nodeShape };
@@ -493,9 +573,9 @@ export class FieldSet {
493
573
  if (!(basePropertyShape === null || basePropertyShape === void 0 ? void 0 : basePropertyShape.valueShape)) {
494
574
  throw new Error(`Property '${key}' has no valueShape; cannot resolve nested fields`);
495
575
  }
496
- const nestedShapeClass = getShapeClass(basePropertyShape.valueShape);
576
+ const nestedShapeClass = getQueryShapeClass(basePropertyShape.valueShape);
497
577
  if (!nestedShapeClass || !nestedShapeClass.shape) {
498
- throw new Error(`Cannot resolve valueShape for property '${key}'`);
578
+ throw unresolvedValueShapeError(`Cannot resolve valueShape '${basePropertyShape.valueShape.id}' for property '${key}'`, basePropertyShape);
499
579
  }
500
580
  for (const nestedField of value) {
501
581
  const nestedPath = walkPropertyPath(nestedShapeClass.shape, nestedField);
@@ -656,11 +736,19 @@ export class FieldSet {
656
736
  return (_b = (_a = getShapeClass(id)) === null || _a === void 0 ? void 0 : _a.shape) !== null && _b !== void 0 ? _b : getNodeShape(id);
657
737
  }
658
738
  static shapeByLabel(label) {
739
+ // Inside a catalog every shape is data (core's built-ins aside), so scan its shapes;
740
+ // the global registry keeps scanning authored classes.
741
+ const matches = (shape) => !!shape && (shape.label === label || FieldSet.labelOfId(shape.id) === label);
742
+ if (getActiveShapeCatalog() !== undefined) {
743
+ for (const shape of getAllNodeShapes().values())
744
+ if (matches(shape))
745
+ return shape;
746
+ return undefined;
747
+ }
659
748
  for (const cls of getAllShapeClasses().values()) {
660
749
  const shape = cls.shape;
661
- if (shape && (shape.label === label || FieldSet.labelOfId(shape.id) === label)) {
750
+ if (matches(shape))
662
751
  return shape;
663
- }
664
752
  }
665
753
  return undefined;
666
754
  }