@takeshape/schema 11.89.0 → 11.91.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/refs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { NotFoundError } from '@takeshape/errors';
2
- import { isDefined, isIntegerLike, isRecord, visit } from '@takeshape/util';
2
+ import { deepCloneWith, isDefined, isIntegerLike, isIterableObject, isRecord, visit } from '@takeshape/util';
3
3
  import compact from 'lodash/compact.js';
4
4
  import assign from 'lodash/fp/assign.js';
5
5
  import omit from 'lodash/fp/omit.js';
@@ -7,15 +7,10 @@ import get from 'lodash/get.js';
7
7
  import isString from 'lodash/isString.js';
8
8
  import { isScalar } from "./scalars.js";
9
9
  import { getServiceNamespaces } from "./services/util.js";
10
- import { getRefType, isAllOfSchema, isExtendsSchema, isObjectSchema, isOneOfSchema, isRefSchema, isRefSchemaLegacy } from "./types/index.js";
10
+ import { isAllOfSchema, isExtendsSchema, isObjectSchema, isOneOfSchema, isRefSchema, isRefSchemaLegacy } from "./types/index.js";
11
11
  import { mergeDeepObjectSchemas, mergeObjectSchemas } from "./util/merge.js";
12
12
  import { getShape } from "./util/shapes.js";
13
- /**
14
- * Guard for RefItemWithPath. Tests for presence of all required props.
15
- */
16
- export function isRefItemWithPath(ref) {
17
- return Boolean(ref.typeName && ref.serviceKey && ref.path && isDefined(ref.isForeign));
18
- }
13
+ export const LOCAL_LAYER_ID = 'local';
19
14
  const templateShapeRegex = /^(\w+)<([\w:-]+)>$/;
20
15
  /**
21
16
  * Parse a template like `PaginatedList<Post>` and return both the template and the shape name.
@@ -27,17 +22,17 @@ export function parseTemplateShape(shapeExpression) {
27
22
  }
28
23
  return { shapeName: shapeExpression, template: undefined };
29
24
  }
30
- export function parseReturnShape(projectSchema, shape) {
25
+ export function parseReturnShape(context, shape) {
31
26
  if (typeof shape === 'object') {
32
27
  if (isRefSchema(shape.items)) {
33
- const ref = getRef(projectSchema, shape.items);
28
+ const ref = getRef(context, shape.items);
34
29
  if (!ref) {
35
30
  throw new Error(`Could not parse ${JSON.stringify(shape.items)}: invalid ref`);
36
31
  }
37
32
  return {
38
33
  isArray: true,
39
34
  ref,
40
- shapeName: refItemToNamespacedShapeName(ref)
35
+ shapeName: refItemToNamespacedShapeName(context, ref)
41
36
  };
42
37
  }
43
38
  if (typeof shape.items.type !== 'string') {
@@ -45,8 +40,8 @@ export function parseReturnShape(projectSchema, shape) {
45
40
  }
46
41
  return { isArray: true, shapeName: shape.items.type };
47
42
  }
48
- const ref = refExpressionToRefItem(projectSchema, shape);
49
- const shapeName = refItemToNamespacedShapeName(ref);
43
+ const ref = parseRef(context, shape);
44
+ const shapeName = refItemToNamespacedShapeName(context, ref);
50
45
  return { isArray: false, shapeName, ref, template: ref.template };
51
46
  }
52
47
  /**
@@ -58,7 +53,7 @@ export function returnShapeToSchema(projectSchema, returnShape) {
58
53
  return { type: returnShape };
59
54
  }
60
55
  return {
61
- '@ref': refItemToAtRef(refExpressionToRefItem(projectSchema, returnShape))
56
+ '@ref': serializeRef(parseRef(projectSchema, returnShape))
62
57
  };
63
58
  }
64
59
  return returnShape;
@@ -85,19 +80,12 @@ function $refToPath(ref) {
85
80
  function $refToShapeName(ref) {
86
81
  return $refToPath(ref)[1];
87
82
  }
88
- export function $refToAtRef($ref, service, namespace) {
89
- const shapeName = $refToShapeName($ref);
90
- if (service === 'local') {
91
- return `local:${shapeName}`;
92
- }
93
- return `${service}:${namespace === undefined ? shapeName : shapeName.replace(`${namespace}_`, '')}`;
94
- }
95
83
  export function refSchemaToPath(context, refSchema) {
96
84
  const refItem = getRef(context, refSchema);
97
85
  if (refItem === undefined) {
98
86
  throw new Error('Invalid ref in refSchemaToPath');
99
87
  }
100
- return refItemToShapePath(refItem);
88
+ return refItemToShapePath(context, refItem);
101
89
  }
102
90
  /**
103
91
  * Safely turn a "template" shape reference (`@args`, `args`, `shape`) into a `RefItem`
@@ -107,18 +95,25 @@ export function refSchemaToPath(context, refSchema) {
107
95
  * A ref expression might include "template" name and refer to a local or remote
108
96
  * shape, `Foo` or `CreateArgs<Foo>` or `CreateArgs<remote:Foo>`.*
109
97
  */
110
- export function refExpressionToRefItem(context, refExpression) {
98
+ export function parseRef(context, refExpression) {
111
99
  const { shapeName, template } = parseTemplateShape(refExpression);
112
100
  if (shapeName.includes(':')) {
113
- return atRefToRefItem(context, shapeName, template);
101
+ return refExpressionToRefItem(shapeName, template);
114
102
  }
115
103
  return shapeNameToRefItem(context, shapeName, template);
116
104
  }
105
+ export function isRefEqual(context, a, b) {
106
+ const parsedA = typeof a === 'string' ? parseRef(context, a) : a;
107
+ const parsedB = typeof b === 'string' ? parseRef(context, b) : b;
108
+ return (parsedA.shapeName === parsedB.shapeName &&
109
+ parsedA.layerId === parsedB.layerId &&
110
+ parsedA.template === parsedB.template);
111
+ }
117
112
  /**
118
113
  * Converts a list of ref expressions into a list of ref items.
119
114
  */
120
115
  export function refExpressionListToRefItemList(context, refExpressionList) {
121
- return refExpressionList.map((ref) => refExpressionToRefItem(context, ref));
116
+ return refExpressionList.map((ref) => parseRef(context, ref));
122
117
  }
123
118
  /**
124
119
  * Sugar for converting a `refExpression` directly into a shape, without the
@@ -129,8 +124,8 @@ export function refExpressionListToRefItemList(context, refExpressionList) {
129
124
  * A ref expression might include "template" name and refer to a local or remote
130
125
  * shape, `Foo` or `CreateArgs<Foo>` or `CreateArgs<remote:Foo>`.
131
126
  */
132
- export function refExpressionToShape(context, refExpression) {
133
- return refItemToShape(context, refExpressionToRefItem(context, refExpression));
127
+ export function getShapeByRef(context, refExpression) {
128
+ return refItemToShape(context, parseRef(context, refExpression));
134
129
  }
135
130
  /**
136
131
  * Provided a service name and a referenced type. Supports 2 or 3 part
@@ -139,32 +134,30 @@ export function refExpressionToShape(context, refExpression) {
139
134
  * @returns
140
135
  * A 2 member array, where 0 is the service name, 1 is the referenced type.
141
136
  */
142
- export function splitAtRef(atRef) {
143
- const index = atRef.lastIndexOf(':');
144
- const serviceKey = index === -1 ? 'local' : atRef.substring(0, index);
145
- const referencedType = index === -1 ? atRef : atRef.substring(index + 1);
137
+ function splitRefExpression(ref) {
138
+ const index = ref.lastIndexOf(':');
139
+ const serviceKey = index === -1 ? LOCAL_LAYER_ID : ref.substring(0, index);
140
+ const referencedType = index === -1 ? ref : ref.substring(index + 1);
146
141
  return [serviceKey, referencedType];
147
142
  }
148
- function isValidServiceId(context, serviceId) {
149
- return serviceId === 'local' || Boolean(context.services?.[serviceId]);
143
+ export function isValidServiceId(context, serviceId) {
144
+ return serviceId === LOCAL_LAYER_ID || Boolean(context.services?.[serviceId]);
145
+ }
146
+ export function isValidRefItem(context) {
147
+ return (refItem) => {
148
+ return isValidServiceId(context, refItem.layerId);
149
+ };
150
150
  }
151
151
  /**
152
152
  * Parses and returns a typeName, serviceKey, and potentially a namespace for
153
153
  * the type.
154
154
  */
155
- export function atRefToRefItem(context, atRef, template) {
156
- const [serviceKey, typeName] = splitAtRef(atRef);
157
- // It's possible the service doesn't have a namespace, or is local and has
158
- // no service config.
159
- const serviceConfig = context.services?.[serviceKey];
160
- const serviceNamespace = serviceConfig?.namespace;
155
+ function refExpressionToRefItem(ref, template) {
156
+ const [serviceKey, typeName] = splitRefExpression(ref);
161
157
  return {
162
- typeName,
163
- serviceKey,
164
- serviceNamespace,
165
- template,
166
- isForeign: Boolean(serviceConfig),
167
- isValidService: isValidServiceId(context, serviceKey)
158
+ shapeName: typeName,
159
+ layerId: serviceKey,
160
+ template
168
161
  };
169
162
  }
170
163
  export function refToRefItem(context, $ref, template) {
@@ -175,39 +168,33 @@ export function refToRefItem(context, $ref, template) {
175
168
  */
176
169
  export function parseName(context, name) {
177
170
  const shapeNameParts = name.split('_');
178
- let serviceId;
179
- let namespace;
171
+ let layerId;
180
172
  if (shapeNameParts.length > 1) {
181
173
  const namespaces = getServiceNamespaces(context);
182
174
  const maybeNamespace = shapeNameParts[0];
183
- serviceId = namespaces.get(maybeNamespace);
184
- if (serviceId) {
175
+ layerId = namespaces.get(maybeNamespace);
176
+ if (layerId) {
185
177
  name = shapeNameParts.slice(1).join('_');
186
- namespace = maybeNamespace;
187
178
  }
188
179
  }
189
180
  return {
190
181
  name,
191
- serviceId: serviceId ?? 'local',
192
- namespace
182
+ layerId: layerId ?? LOCAL_LAYER_ID
193
183
  };
194
184
  }
195
185
  function shapeNameToRefItem(context, shapeName, template) {
196
186
  const parsed = parseName(context, shapeName);
197
187
  return {
198
- typeName: parsed.name,
199
- serviceKey: parsed.serviceId,
200
- serviceNamespace: parsed.namespace,
201
- template,
202
- isForeign: parsed.serviceId !== 'local',
203
- isValidService: isValidServiceId(context, parsed.serviceId)
188
+ shapeName: parsed.name,
189
+ layerId: parsed.layerId,
190
+ template
204
191
  };
205
192
  }
206
193
  export function shapeToRefItem(context, shape) {
207
194
  return shapeNameToRefItem(context, shape.name);
208
195
  }
209
196
  export function shapeToRefString(context, shape) {
210
- return refItemToAtRef(shapeNameToRefItem(context, shape.name));
197
+ return serializeRef(shapeNameToRefItem(context, shape.name));
211
198
  }
212
199
  /**
213
200
  * Given a property schema and project schema, finds a `@ref` or `$ref` and
@@ -217,21 +204,20 @@ export function getRef(context, refSchema) {
217
204
  if (refSchema['@ref']) {
218
205
  // @ref: my-service:ShapeName
219
206
  const { shapeName, template } = parseTemplateShape(refSchema['@ref']);
220
- return atRefToRefItem(context, shapeName, template);
207
+ return refExpressionToRefItem(shapeName, template);
221
208
  }
222
209
  if (refSchema.$ref) {
223
210
  // $ref: #/shapes/[ShapeName OR Namespace_TypeName]/schema
224
211
  return refToRefItem(context, refSchema.$ref);
225
212
  }
226
213
  }
227
- export function getRefWithPath(context, refSchema, schemaPath = [], isInterfaceRef = false) {
214
+ export function getRefWithPath(context, refSchema, schemaPath = []) {
228
215
  const refItem = getRef(context, refSchema);
229
216
  if (refItem) {
230
- const refType = getRefType(refSchema);
217
+ const refType = refSchema['@ref'] ? '@ref' : '$ref';
231
218
  return {
232
219
  ...refItem,
233
- path: schemaPath.concat([refType]),
234
- isInterfaceRef
220
+ path: schemaPath.concat([refType])
235
221
  };
236
222
  }
237
223
  }
@@ -272,28 +258,32 @@ export function getRefOrItemsRef(context, refSchema, schemaPath = []) {
272
258
  /**
273
259
  * Turns a `RefItem` into an `@ref`.
274
260
  */
275
- export function refItemToAtRef(refItem) {
276
- const shapeRef = `${refItem.serviceKey}:${refItem.typeName}`;
261
+ export function serializeRef(refItem) {
262
+ const shapeRef = formatShapeRef(refItem.layerId, refItem.shapeName);
277
263
  return refItem.template ? createTemplateShapeName(refItem.template, shapeRef) : shapeRef;
278
264
  }
279
265
  /**
280
266
  * Turns a `RefItem` into a standard shape name, namespacing if present.
281
267
  */
282
- export function refItemToNamespacedShapeName(refItem) {
283
- const { serviceNamespace, typeName } = refItem;
284
- return serviceNamespace ? `${serviceNamespace}_${typeName}` : typeName;
268
+ export function refItemToNamespacedShapeName(context, refItem) {
269
+ const { shapeName, layerId } = refItem;
270
+ const namespace = getNamespace(context, layerId);
271
+ return namespace ? `${namespace}_${shapeName}` : shapeName;
272
+ }
273
+ export function refExpressionToNamespacedName(context, refExpression) {
274
+ return refItemToNamespacedShapeName(context, parseRef(context, refExpression));
285
275
  }
286
276
  /**
287
277
  * Turns a `RefItem` into a path suitable for `lodash.get`.
288
278
  */
289
- export function refItemToShapePath(refItem) {
290
- return ['shapes', refItemToNamespacedShapeName(refItem)];
279
+ export function refItemToShapePath(context, refItem) {
280
+ return ['shapes', refItemToNamespacedShapeName(context, refItem)];
291
281
  }
292
282
  /**
293
283
  * Get a Shape referenced by a `RefItem`.
294
284
  */
295
285
  export function refItemToShape(context, refItem) {
296
- const shapePath = refItemToShapePath(refItem);
286
+ const shapePath = refItemToShapePath(context, refItem);
297
287
  return get(context, shapePath);
298
288
  }
299
289
  /**
@@ -306,7 +296,7 @@ export function refItemListToShapeList(context, refItems) {
306
296
  * Get a shape referenced by a `RefItem`, also returning the path to the new shape.
307
297
  */
308
298
  export function refItemToShapeWithPath(context, refItem) {
309
- const shapePath = refItemToShapePath(refItem);
299
+ const shapePath = refItemToShapePath(context, refItem);
310
300
  const shape = get(context, shapePath);
311
301
  return shape ? { shape, path: shapePath } : undefined;
312
302
  }
@@ -314,7 +304,7 @@ export function refItemToShapeWithPath(context, refItem) {
314
304
  * Get a Shape schema referenced by a `RefItem`.
315
305
  */
316
306
  export function refItemToShapeSchema(context, refItem) {
317
- const shapePath = refItemToShapePath(refItem);
307
+ const shapePath = refItemToShapePath(context, refItem);
318
308
  return get(context, [...shapePath, 'schema']);
319
309
  }
320
310
  /**
@@ -322,14 +312,14 @@ export function refItemToShapeSchema(context, refItem) {
322
312
  */
323
313
  export function getRefShapeName(context, refSchema) {
324
314
  const refItem = getRef(context, refSchema);
325
- return refItem ? refItemToNamespacedShapeName(refItem) : undefined;
315
+ return refItem ? refItemToNamespacedShapeName(context, refItem) : undefined;
326
316
  }
327
317
  /**
328
318
  * Sugar, for when you really just need a path...
329
319
  */
330
- export function anyRefToShapeSchemaPath(context, refSchema) {
320
+ export function refSchemaToShapeSchemaPath(context, refSchema) {
331
321
  const refItem = getRef(context, refSchema);
332
- return refItem ? [...refItemToShapePath(refItem), 'schema'] : undefined;
322
+ return refItem ? [...refItemToShapePath(context, refItem), 'schema'] : undefined;
333
323
  }
334
324
  /**
335
325
  * Helper fn to omit `ref` props from the target schema, and then extend it with the source schema.
@@ -369,7 +359,8 @@ export function hasRef(schema) {
369
359
  */
370
360
  export function hasResolvableRef(context, schema) {
371
361
  if (isRefSchema(schema) || isRefSchemaLegacy(schema)) {
372
- return Boolean(refItemToShapeSchema(context, getRef(context, schema)));
362
+ const ref = getRef(context, schema);
363
+ return Boolean(ref && refItemToShapeSchema(context, ref));
373
364
  }
374
365
  if (isAllOfSchema(schema)) {
375
366
  return Boolean(schema.allOf.find((s) => hasResolvableRef(context, s)));
@@ -440,29 +431,28 @@ export function dereferenceObjectSchema(context, shapeOrFieldSchema, schemaPath
440
431
  }
441
432
  return schema;
442
433
  }
443
- function getNamespace(context, serviceId) {
444
- return context.services?.[serviceId]?.namespace;
434
+ function getNamespace(context, layerId) {
435
+ return context.services?.[layerId]?.namespace;
445
436
  }
446
437
  export function createGetNamespace(context) {
447
- return (serviceId) => getNamespace(context, serviceId);
438
+ return (layerId) => getNamespace(context, layerId);
448
439
  }
449
440
  export function parsePropertyRef(refStr) {
450
- const [serviceId, coordinate] = splitAtRef(refStr);
441
+ const [layerId, coordinate] = splitRefExpression(refStr);
451
442
  const coordinateParts = coordinate.split('.');
452
443
  if (coordinateParts.length === 1) {
453
- return { serviceId, shapeName: 'Query', propertyName: coordinateParts[0] };
444
+ return { layerId, shapeName: 'Query', propertyName: coordinateParts[0] };
454
445
  }
455
446
  if (coordinateParts.length === 2) {
456
447
  return {
457
- serviceId,
448
+ layerId,
458
449
  shapeName: coordinateParts[0],
459
450
  propertyName: coordinateParts[1]
460
451
  };
461
452
  }
462
453
  }
463
- export function serializePropertyRef({ shapeName, propertyName, serviceId }) {
464
- const coordinate = `${shapeName}.${propertyName}`;
465
- return serviceId === 'local' ? coordinate : `${serviceId}:${coordinate}`;
454
+ export function serializePropertyRef({ shapeName, propertyName, layerId }) {
455
+ return formatShapeRef(layerId, `${shapeName}.${propertyName}`);
466
456
  }
467
457
  export function normalizePropertyRef(refStr) {
468
458
  const parsed = parsePropertyRef(refStr);
@@ -473,10 +463,10 @@ export function propertyRefToShapeRef(propertyRef) {
473
463
  if (!parsed) {
474
464
  throw new Error(`Invalid property ref "${propertyRef}`);
475
465
  }
476
- return formatShapeRef(parsed.serviceId, parsed.shapeName);
466
+ return formatShapeRef(parsed.layerId, parsed.shapeName);
477
467
  }
478
- export function formatShapeRef(serviceId, shapeName) {
479
- return `${serviceId}:${shapeName}`;
468
+ export function formatShapeRef(layerId, shapeName) {
469
+ return layerId === LOCAL_LAYER_ID ? shapeName : `${layerId}:${shapeName}`;
480
470
  }
481
471
  export function applyNamespace(namespace, name) {
482
472
  return namespace ? `${namespace}_${name}` : name;
@@ -489,25 +479,9 @@ export function propertyRefItemToArgsPath(getNamespace, item) {
489
479
  const path = propertyRefItemToPath(getNamespace, item);
490
480
  return path.concat(path[0] === 'shapes' ? '@args' : 'args');
491
481
  }
492
- export function propertyRefItemToLocalName(getNamespace, item) {
493
- const { shapeName, serviceId, propertyName } = item;
494
- if (shapeName === 'Query' || shapeName === 'Mutation') {
495
- const namespaced = applyNamespace(getNamespace(serviceId), propertyName);
496
- return `${shapeName}.${namespaced}`;
497
- }
498
- return propertyName;
499
- }
500
- export function queryRefToLocalName(context, queryRef) {
501
- const parsedQueryRef = parsePropertyRef(queryRef);
502
- if (parsedQueryRef) {
503
- return parsedQueryRef.serviceId === 'local'
504
- ? parsedQueryRef.propertyName
505
- : propertyRefItemToLocalName(createGetNamespace(context), parsedQueryRef);
506
- }
507
- }
508
482
  export function propertyRefItemToPath(getNamespace, item) {
509
- const { shapeName, serviceId, propertyName } = item;
510
- const namespace = getNamespace(serviceId);
483
+ const { shapeName, layerId, propertyName } = item;
484
+ const namespace = getNamespace(layerId);
511
485
  if (shapeName === 'Query' || shapeName === 'Mutation') {
512
486
  return [shapeName === 'Query' ? 'queries' : 'mutations', applyNamespace(namespace, propertyName)];
513
487
  }
@@ -524,7 +498,7 @@ export function propertyRefToArgs(projectSchema, ref) {
524
498
  * Get a ref to the given shape.
525
499
  */
526
500
  export function normalizeRefExpression(context, refExpression) {
527
- return refItemToAtRef(refExpressionToRefItem(context, refExpression));
501
+ return serializeRef(parseRef(context, refExpression));
528
502
  }
529
503
  export function normalizeLocalRefString(ref) {
530
504
  return ref.startsWith('local:') ? ref.substring(6) : ref;
@@ -588,38 +562,28 @@ export function ensureQuery(projectSchema, queryRef) {
588
562
  return query;
589
563
  }
590
564
  export function normalizeRefs(projectSchema, property) {
591
- let updatedProperty = {
592
- ...property
593
- };
594
- // Array items
595
- if (property.items) {
596
- return {
597
- ...updatedProperty,
598
- items: normalizeRefs(projectSchema, property.items)
599
- };
600
- }
601
- // Unions
602
- if (property.oneOf) {
603
- return {
604
- ...updatedProperty,
605
- oneOf: property.oneOf.map((item) => normalizeRefs(projectSchema, item))
606
- };
607
- }
608
- // Convert $ref to @ref
609
- const refItem = getRef(projectSchema, updatedProperty);
610
- if (refItem && updatedProperty.$ref) {
611
- updatedProperty = {
612
- ...omit(['$ref'], updatedProperty),
613
- '@ref': refItemToAtRef(refItem)
614
- };
615
- }
616
- return updatedProperty;
565
+ return deepCloneWith(property ?? projectSchema, (value, _key, _parent, clone) => {
566
+ if (isIterableObject(value)) {
567
+ const ref = getRef(projectSchema, value);
568
+ if (ref) {
569
+ const { $ref, '@output': output, '@input': input, ...newRefSchema } = value;
570
+ newRefSchema['@ref'] = serializeRef(ref);
571
+ if (output) {
572
+ newRefSchema['@output'] = clone(output, '@output', value);
573
+ }
574
+ if (input) {
575
+ newRefSchema['@input'] = clone(input, '@input', value);
576
+ }
577
+ return newRefSchema;
578
+ }
579
+ }
580
+ });
617
581
  }
618
582
  /**
619
583
  * Get a ShapeJSON from a RefItem, with the schema dereferenced.
620
584
  */
621
585
  export function getReferencedShape(projectSchema, refItem, namespace) {
622
- const shape = getShape(projectSchema, applyNamespace(namespace ?? getNamespace(projectSchema, refItem.serviceId), refItem.shapeName));
586
+ const shape = getShape(projectSchema, applyNamespace(namespace ?? getNamespace(projectSchema, refItem.layerId), refItem.shapeName));
623
587
  if (shape) {
624
588
  return {
625
589
  ...shape,
@@ -631,7 +595,7 @@ export function getReferencedShape(projectSchema, refItem, namespace) {
631
595
  * Get a PropertySchema from a RefItem.
632
596
  */
633
597
  export function getReferencedShapeProperty(projectSchema, refItem, namespace) {
634
- const shape = getReferencedShape(projectSchema, refItem, namespace ?? getNamespace(projectSchema, refItem.serviceId));
598
+ const shape = getReferencedShape(projectSchema, refItem, namespace ?? getNamespace(projectSchema, refItem.layerId));
635
599
  if (shape && isObjectSchema(shape.schema)) {
636
600
  return shape.schema.properties[refItem.propertyName];
637
601
  }
@@ -27,7 +27,7 @@ export declare function getLegacyRelationship(projectSchema: ProjectSchemaJSON,
27
27
  export declare function getRelationship(propertySchema: PropertySchema): Maybe<Relationship>;
28
28
  export declare function findExistingRelationships(projectSchema: ProjectSchemaJSON, shapes: ShapeMap): Record<string, RelationshipEnv[]>;
29
29
  /**
30
- * Test whether two PropertySchemas have equal realtionships
30
+ * Test whether two PropertySchemas have equal relationships
31
31
  */
32
32
  export declare function isEqualRelationship(a: PropertySchema, b: PropertySchema): boolean;
33
33
  /**
@@ -3,7 +3,7 @@ import camelCase from 'lodash/camelCase.js';
3
3
  import find from 'lodash/find.js';
4
4
  import uniq from 'lodash/uniq.js';
5
5
  import { builtInShapes } from "./builtin-schema.js";
6
- import { followRef, getRefShapeName } from "./refs.js";
6
+ import { followRef, getRefShapeName, getShapeByRef, shapeToRefString } from "./refs.js";
7
7
  import { isModelShape, isObjectSchema, isPropertySchemaWithRelationship } from "./types/index.js";
8
8
  import { isUnionSchema } from "./unions.js";
9
9
  import { getShapeById } from "./util/shapes.js";
@@ -28,7 +28,7 @@ export function getRelationshipSchema(projectSchema, relationship) {
28
28
  .map((shapeId) => {
29
29
  const shape = getShapeById(projectSchema, shapeId) ?? find(builtInShapes, (shape) => shape.id === shapeId);
30
30
  return (shape && {
31
- '@ref': `local:${shape.name}`
31
+ '@ref': shapeToRefString(projectSchema, shape)
32
32
  });
33
33
  })
34
34
  .filter(isDefined);
@@ -50,7 +50,7 @@ export function getRelationshipSchema(projectSchema, relationship) {
50
50
  '@input': {
51
51
  type: 'array',
52
52
  items: {
53
- '@ref': 'local:TSRelationship'
53
+ '@ref': 'TSRelationship'
54
54
  }
55
55
  }
56
56
  };
@@ -59,7 +59,7 @@ export function getRelationshipSchema(projectSchema, relationship) {
59
59
  ...propertySchema,
60
60
  ...shapeRefsSchema,
61
61
  '@input': {
62
- '@ref': 'local:TSRelationship'
62
+ '@ref': 'TSRelationship'
63
63
  }
64
64
  };
65
65
  }
@@ -81,25 +81,15 @@ export function getRelationshipShapeRefs(propertySchema) {
81
81
  * Get a list of shapes given a property schema with a relationship resolver.
82
82
  */
83
83
  export function getRelationshipShapes(shapes, refs) {
84
- return refs
85
- .map((ref) => {
86
- const shapeName = ref.split(':')[1];
87
- const shape = shapes[shapeName];
88
- return shape ? shape : undefined;
89
- })
90
- .filter(isDefined);
84
+ const context = { shapes };
85
+ return refs.map((ref) => getShapeByRef(context, ref)).filter(isDefined);
91
86
  }
92
87
  /**
93
88
  * Get a list of shape ids given a property schema with a relationship resolver.
94
89
  */
95
90
  export function getRelationshipShapeIds(shapes, refs) {
96
- return refs
97
- .map((ref) => {
98
- const shapeName = ref.split(':')[1];
99
- const shape = shapes[shapeName];
100
- return shape ? shape.id : undefined;
101
- })
102
- .filter(isDefined);
91
+ const context = { shapes };
92
+ return refs.map((ref) => getShapeByRef(context, ref)?.id).filter(isDefined);
103
93
  }
104
94
  /**
105
95
  * Turn a Relationship into a LegacyRelationship object.
@@ -193,7 +183,7 @@ export function findExistingRelationships(projectSchema, shapes) {
193
183
  return relationships;
194
184
  }
195
185
  /**
196
- * Test whether two PropertySchemas have equal realtionships
186
+ * Test whether two PropertySchemas have equal relationships
197
187
  */
198
188
  export function isEqualRelationship(a, b) {
199
189
  const relationshipA = getRelationship(a);
@@ -236,23 +226,24 @@ export function addRelatedFields(projectSchema, allRelationships) {
236
226
  const shape = getShapeById(projectSchema, shapeId);
237
227
  if (shape && isObjectSchema(shape.schema)) {
238
228
  const relatedShapeIds = getRelatedShapeIds(shapeRelationships);
239
- const relatedShapeNames = getShapes(projectSchema, relatedShapeIds).map((shape) => shape.name);
240
- if (relatedShapeNames.length) {
241
- let shapeName;
242
- if (relatedShapeNames.length === 1) {
229
+ const relatedShapeRefs = getShapes(projectSchema, relatedShapeIds).map((shape) => shapeToRefString(projectSchema, shape));
230
+ if (relatedShapeRefs.length) {
231
+ let shapeRef;
232
+ if (relatedShapeRefs.length === 1) {
243
233
  // If only one back reference exists, _references is a regular shape
244
- shapeName = relatedShapeNames[0];
234
+ shapeRef = relatedShapeRefs[0];
245
235
  }
246
236
  else {
247
237
  // If many back references exist, _references will be a union of referring shapes
248
- shapeName = `${shape.name}Reference`;
238
+ const shapeName = `${shape.name}Reference`;
239
+ shapeRef = shapeName;
249
240
  projectSchema.shapes[shapeName] = {
250
241
  id: shapeName,
251
242
  name: shapeName,
252
243
  title: shapeName,
253
244
  schema: {
254
- oneOf: relatedShapeNames.map((name) => ({
255
- '@ref': `local:${name}`
245
+ oneOf: relatedShapeRefs.map((name) => ({
246
+ '@ref': name
256
247
  }))
257
248
  }
258
249
  };
@@ -262,8 +253,8 @@ export function addRelatedFields(projectSchema, allRelationships) {
262
253
  // It is for convenience.
263
254
  if (shapeRelationships.some((rel) => rel.hasBackreference)) {
264
255
  shape.schema.properties._references = {
265
- '@args': `TSListArgs<local:${shapeName}>`,
266
- '@ref': `PaginatedList<local:${shapeName}>`,
256
+ '@args': `TSListArgs<${shapeRef}>`,
257
+ '@ref': `PaginatedList<${shapeRef}>`,
267
258
  '@resolver': {
268
259
  name: 'shapedb:list',
269
260
  service: 'shapedb',
@@ -286,8 +277,8 @@ export function addRelatedFields(projectSchema, allRelationships) {
286
277
  const relatedFieldName = relatedName ? relatedName : `${camelCase(relatedShape.name)}Set`;
287
278
  const filterField = relatedName ? relationship.path.concat('_id').join('.') : '_references';
288
279
  shape.schema.properties[relatedFieldName] = {
289
- '@args': `TSListArgs<local:${relatedShape.name}>`,
290
- '@ref': `PaginatedList<local:${relatedShape.name}>`,
280
+ '@args': `TSListArgs<${relatedShape.name}>`,
281
+ '@ref': `PaginatedList<${relatedShape.name}>`,
291
282
  '@resolver': {
292
283
  name: 'shapedb:list',
293
284
  service: 'shapedb',