@unito/integration-api 7.0.1 → 7.1.1

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.
@@ -49,7 +49,14 @@
49
49
  }
50
50
  },
51
51
  "reference": {
52
- "$ref": "https://unito.io/integration_api/referenceRelation.schema.json"
52
+ "oneOf": [
53
+ {
54
+ "$ref": "https://unito.io/integration_api/referenceRelation.schema.json"
55
+ },
56
+ {
57
+ "$ref": "https://unito.io/integration_api/relationPointer.schema.json"
58
+ }
59
+ ]
53
60
  },
54
61
  "info": {
55
62
  "type": "string"
@@ -0,0 +1,20 @@
1
+ {
2
+ "$id": "https://unito.io/integration_api/relationPointer.schema.json",
3
+ "title": "RelationPointer",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": ["itemPath", "relationName"],
7
+ "properties": {
8
+ "itemPath": {
9
+ "type": "string",
10
+ "format": "uri-reference",
11
+ "pattern": "^\/.*$"
12
+ },
13
+ "relationName": {
14
+ "type": "string",
15
+ "pattern": "^[a-zA-Z0-9_-]*$",
16
+ "minLength": 1,
17
+ "maxLength": 100
18
+ }
19
+ }
20
+ }
@@ -1,4 +1,16 @@
1
1
  import * as Api from './types.js';
2
+ /**
3
+ * Options for type guard functions.
4
+ */
5
+ export interface GuardOptions {
6
+ /**
7
+ * When false, validate structure only (values are strings) without checking enum membership.
8
+ * This allows forward compatibility when a newer integration-api adds Semantics or FieldValueTypes
9
+ * that the consumer doesn't know about yet.
10
+ * Defaults to true.
11
+ */
12
+ strict?: boolean;
13
+ }
2
14
  /**
3
15
  * Checks if the input is a record<unknown, unknown>
4
16
  * @param potentialObject - The value to check.
@@ -29,36 +41,42 @@ export declare function isItemSummary(potentialItemSummary: unknown): potentialI
29
41
  * @returns True if the value is an Item, false otherwise.
30
42
  */
31
43
  export declare function isItem(potentialItem: unknown): potentialItem is Api.Item;
44
+ /**
45
+ * Checks if the input is an Api.RelationPointer object.
46
+ * @param potentialRelationPointer - The value to check.
47
+ * @returns True if the value is a RelationPointer, false otherwise.
48
+ */
49
+ export declare function isRelationPointer(potentialRelationPointer: unknown): potentialRelationPointer is Api.RelationPointer;
32
50
  /**
33
51
  * Checks if the input is an Api.ReferenceRelation object.
34
52
  * @param potentialReferenceRelation - The value to check.
35
53
  * @returns True if the value is a ReferenceRelation, false otherwise.
36
54
  */
37
- export declare function isReferenceRelation(potentialReferenceRelation: unknown): potentialReferenceRelation is Api.ReferenceRelation;
55
+ export declare function isReferenceRelation(potentialReferenceRelation: unknown, options?: GuardOptions): potentialReferenceRelation is Api.ReferenceRelation;
38
56
  /**
39
57
  * Checks if the input is an Api.RelationSummary object.
40
58
  * @param potentialRelationSummary - The value to check.
41
59
  * @returns True if the value is a RelationSummary, false otherwise.
42
60
  */
43
- export declare function isRelationSummary(potentialRelationSummary: unknown): potentialRelationSummary is Api.RelationSummary;
61
+ export declare function isRelationSummary(potentialRelationSummary: unknown, options?: GuardOptions): potentialRelationSummary is Api.RelationSummary;
44
62
  /**
45
63
  * Checks if the input is an Api.Relation object.
46
64
  * @param potentialRelation - The value to check.
47
65
  * @returns True if the value is a Relation, false otherwise.
48
66
  */
49
- export declare function isRelation(potentialRelation: unknown): potentialRelation is Api.Relation;
67
+ export declare function isRelation(potentialRelation: unknown, options?: GuardOptions): potentialRelation is Api.Relation;
50
68
  /**
51
69
  * Checks if the input is an Api.RelationSchema object.
52
70
  * @param potentialRelationSchema - The value to check.
53
71
  * @returns True if the value is a RelationSchema, false otherwise.
54
72
  */
55
- export declare function isRelationSchema(potentialRelationSchema: unknown): potentialRelationSchema is Api.RelationSchema;
73
+ export declare function isRelationSchema(potentialRelationSchema: unknown, options?: GuardOptions): potentialRelationSchema is Api.RelationSchema;
56
74
  /**
57
75
  * Checks if the input is an Api.RelationSchema object or the string '__self'.
58
76
  * @param potentialRelationSchema - The value to check.
59
77
  * @returns True if the value is a RelationSchema or '__self', false otherwise.
60
78
  */
61
- export declare function isRelationSchemaOrSelf(potentialRelationSchemaOrSelf: unknown): potentialRelationSchemaOrSelf is Api.RelationSchema | '__self';
79
+ export declare function isRelationSchemaOrSelf(potentialRelationSchemaOrSelf: unknown, options?: GuardOptions): potentialRelationSchemaOrSelf is Api.RelationSchema | '__self';
62
80
  /**
63
81
  * Checks if the input is an Api.FieldValueType.
64
82
  * @param potentialFieldValueType - The value to check.
@@ -76,4 +94,4 @@ export declare function isSemantic(potentialSemantic: unknown): potentialSemanti
76
94
  * @param potentialFieldSchema - The value to check.
77
95
  * @returns True if the value is a FieldSchema, false otherwise.
78
96
  */
79
- export declare function isFieldSchema(potentialFieldSchema: unknown): potentialFieldSchema is Api.FieldSchema;
97
+ export declare function isFieldSchema(potentialFieldSchema: unknown, options?: GuardOptions): potentialFieldSchema is Api.FieldSchema;
@@ -44,64 +44,74 @@ export function isItem(potentialItem) {
44
44
  return (isObject(potentialItem) &&
45
45
  isObject(potentialItem['fields']) &&
46
46
  Array.isArray(potentialItem['relations']) &&
47
- potentialItem['relations'].every(isRelation));
47
+ potentialItem['relations'].every((r) => isRelation(r)));
48
+ }
49
+ /**
50
+ * Checks if the input is an Api.RelationPointer object.
51
+ * @param potentialRelationPointer - The value to check.
52
+ * @returns True if the value is a RelationPointer, false otherwise.
53
+ */
54
+ export function isRelationPointer(potentialRelationPointer) {
55
+ return (isObject(potentialRelationPointer) &&
56
+ isString(potentialRelationPointer['itemPath']) &&
57
+ isString(potentialRelationPointer['relationName']));
48
58
  }
49
59
  /**
50
60
  * Checks if the input is an Api.ReferenceRelation object.
51
61
  * @param potentialReferenceRelation - The value to check.
52
62
  * @returns True if the value is a ReferenceRelation, false otherwise.
53
63
  */
54
- export function isReferenceRelation(potentialReferenceRelation) {
64
+ export function isReferenceRelation(potentialReferenceRelation, options) {
55
65
  return (isObject(potentialReferenceRelation) &&
56
66
  isString(potentialReferenceRelation['name']) &&
57
67
  isString(potentialReferenceRelation['path']) &&
58
68
  isString(potentialReferenceRelation['label']) &&
59
- isRelationSchemaOrSelf(potentialReferenceRelation['schema']));
69
+ isRelationSchemaOrSelf(potentialReferenceRelation['schema'], options));
60
70
  }
61
71
  /**
62
72
  * Checks if the input is an Api.RelationSummary object.
63
73
  * @param potentialRelationSummary - The value to check.
64
74
  * @returns True if the value is a RelationSummary, false otherwise.
65
75
  */
66
- export function isRelationSummary(potentialRelationSummary) {
76
+ export function isRelationSummary(potentialRelationSummary, options) {
67
77
  return (isObject(potentialRelationSummary) &&
68
78
  isString(potentialRelationSummary['name']) &&
69
79
  isString(potentialRelationSummary['label']) &&
70
- isRelationSchemaOrSelf(potentialRelationSummary['schema']));
80
+ isRelationSchemaOrSelf(potentialRelationSummary['schema'], options));
71
81
  }
72
82
  /**
73
83
  * Checks if the input is an Api.Relation object.
74
84
  * @param potentialRelation - The value to check.
75
85
  * @returns True if the value is a Relation, false otherwise.
76
86
  */
77
- export function isRelation(potentialRelation) {
87
+ export function isRelation(potentialRelation, options) {
78
88
  return (isObject(potentialRelation) &&
79
89
  isString(potentialRelation['name']) &&
80
90
  isString(potentialRelation['path']) &&
81
91
  isString(potentialRelation['label']) &&
82
- isRelationSchema(potentialRelation['schema']));
92
+ isRelationSchema(potentialRelation['schema'], options));
83
93
  }
84
94
  /**
85
95
  * Checks if the input is an Api.RelationSchema object.
86
96
  * @param potentialRelationSchema - The value to check.
87
97
  * @returns True if the value is a RelationSchema, false otherwise.
88
98
  */
89
- export function isRelationSchema(potentialRelationSchema) {
99
+ export function isRelationSchema(potentialRelationSchema, options) {
90
100
  return (isObject(potentialRelationSchema) &&
91
101
  isString(potentialRelationSchema['label']) &&
92
102
  Array.isArray(potentialRelationSchema['fields']) &&
93
- potentialRelationSchema['fields'].every(isFieldSchema) &&
103
+ potentialRelationSchema['fields'].every((f) => isFieldSchema(f, options)) &&
94
104
  (isUndefined(potentialRelationSchema['relations']) ||
95
105
  (Array.isArray(potentialRelationSchema['relations']) &&
96
- potentialRelationSchema['relations'].every(isRelationSummary))));
106
+ potentialRelationSchema['relations'].every((r) => isRelationSummary(r, options)))));
97
107
  }
98
108
  /**
99
109
  * Checks if the input is an Api.RelationSchema object or the string '__self'.
100
110
  * @param potentialRelationSchema - The value to check.
101
111
  * @returns True if the value is a RelationSchema or '__self', false otherwise.
102
112
  */
103
- export function isRelationSchemaOrSelf(potentialRelationSchemaOrSelf) {
104
- return isRelationSchema(potentialRelationSchemaOrSelf) || potentialRelationSchemaOrSelf === '__self';
113
+ export function isRelationSchemaOrSelf(potentialRelationSchemaOrSelf, options) {
114
+ return isRelationSchema(potentialRelationSchemaOrSelf, options) || potentialRelationSchemaOrSelf === '__self';
105
115
  }
106
116
  /**
107
117
  * Checks if the input is an Api.FieldValueType.
@@ -124,11 +134,13 @@ export function isSemantic(potentialSemantic) {
124
134
  * @param potentialFieldSchema - The value to check.
125
135
  * @returns True if the value is a FieldSchema, false otherwise.
126
136
  */
127
- export function isFieldSchema(potentialFieldSchema) {
137
+ export function isFieldSchema(potentialFieldSchema, options) {
138
+ const strict = options?.strict ?? true;
128
139
  return (isObject(potentialFieldSchema) &&
129
140
  isString(potentialFieldSchema['name']) &&
130
141
  isString(potentialFieldSchema['label']) &&
131
142
  isString(potentialFieldSchema['type']) &&
132
- isFieldValueType(potentialFieldSchema['type']) &&
133
- (isUndefined(potentialFieldSchema['semantic']) || isSemantic(potentialFieldSchema['semantic'])));
143
+ (strict ? isFieldValueType(potentialFieldSchema['type']) : true) &&
144
+ (isUndefined(potentialFieldSchema['semantic']) ||
145
+ (strict ? isSemantic(potentialFieldSchema['semantic']) : isString(potentialFieldSchema['semantic']))));
134
146
  }
@@ -161,64 +161,74 @@ function isItem(potentialItem) {
161
161
  return (isObject(potentialItem) &&
162
162
  isObject(potentialItem['fields']) &&
163
163
  Array.isArray(potentialItem['relations']) &&
164
- potentialItem['relations'].every(isRelation));
164
+ potentialItem['relations'].every((r) => isRelation(r)));
165
+ }
166
+ /**
167
+ * Checks if the input is an Api.RelationPointer object.
168
+ * @param potentialRelationPointer - The value to check.
169
+ * @returns True if the value is a RelationPointer, false otherwise.
170
+ */
171
+ function isRelationPointer(potentialRelationPointer) {
172
+ return (isObject(potentialRelationPointer) &&
173
+ isString(potentialRelationPointer['itemPath']) &&
174
+ isString(potentialRelationPointer['relationName']));
165
175
  }
166
176
  /**
167
177
  * Checks if the input is an Api.ReferenceRelation object.
168
178
  * @param potentialReferenceRelation - The value to check.
169
179
  * @returns True if the value is a ReferenceRelation, false otherwise.
170
180
  */
171
- function isReferenceRelation(potentialReferenceRelation) {
181
+ function isReferenceRelation(potentialReferenceRelation, options) {
172
182
  return (isObject(potentialReferenceRelation) &&
173
183
  isString(potentialReferenceRelation['name']) &&
174
184
  isString(potentialReferenceRelation['path']) &&
175
185
  isString(potentialReferenceRelation['label']) &&
176
- isRelationSchemaOrSelf(potentialReferenceRelation['schema']));
186
+ isRelationSchemaOrSelf(potentialReferenceRelation['schema'], options));
177
187
  }
178
188
  /**
179
189
  * Checks if the input is an Api.RelationSummary object.
180
190
  * @param potentialRelationSummary - The value to check.
181
191
  * @returns True if the value is a RelationSummary, false otherwise.
182
192
  */
183
- function isRelationSummary(potentialRelationSummary) {
193
+ function isRelationSummary(potentialRelationSummary, options) {
184
194
  return (isObject(potentialRelationSummary) &&
185
195
  isString(potentialRelationSummary['name']) &&
186
196
  isString(potentialRelationSummary['label']) &&
187
- isRelationSchemaOrSelf(potentialRelationSummary['schema']));
197
+ isRelationSchemaOrSelf(potentialRelationSummary['schema'], options));
188
198
  }
189
199
  /**
190
200
  * Checks if the input is an Api.Relation object.
191
201
  * @param potentialRelation - The value to check.
192
202
  * @returns True if the value is a Relation, false otherwise.
193
203
  */
194
- function isRelation(potentialRelation) {
204
+ function isRelation(potentialRelation, options) {
195
205
  return (isObject(potentialRelation) &&
196
206
  isString(potentialRelation['name']) &&
197
207
  isString(potentialRelation['path']) &&
198
208
  isString(potentialRelation['label']) &&
199
- isRelationSchema(potentialRelation['schema']));
209
+ isRelationSchema(potentialRelation['schema'], options));
200
210
  }
201
211
  /**
202
212
  * Checks if the input is an Api.RelationSchema object.
203
213
  * @param potentialRelationSchema - The value to check.
204
214
  * @returns True if the value is a RelationSchema, false otherwise.
205
215
  */
206
- function isRelationSchema(potentialRelationSchema) {
216
+ function isRelationSchema(potentialRelationSchema, options) {
207
217
  return (isObject(potentialRelationSchema) &&
208
218
  isString(potentialRelationSchema['label']) &&
209
219
  Array.isArray(potentialRelationSchema['fields']) &&
210
- potentialRelationSchema['fields'].every(isFieldSchema) &&
220
+ potentialRelationSchema['fields'].every((f) => isFieldSchema(f, options)) &&
211
221
  (isUndefined(potentialRelationSchema['relations']) ||
212
222
  (Array.isArray(potentialRelationSchema['relations']) &&
213
- potentialRelationSchema['relations'].every(isRelationSummary))));
223
+ potentialRelationSchema['relations'].every((r) => isRelationSummary(r, options)))));
214
224
  }
215
225
  /**
216
226
  * Checks if the input is an Api.RelationSchema object or the string '__self'.
217
227
  * @param potentialRelationSchema - The value to check.
218
228
  * @returns True if the value is a RelationSchema or '__self', false otherwise.
219
229
  */
220
- function isRelationSchemaOrSelf(potentialRelationSchemaOrSelf) {
221
- return isRelationSchema(potentialRelationSchemaOrSelf) || potentialRelationSchemaOrSelf === '__self';
230
+ function isRelationSchemaOrSelf(potentialRelationSchemaOrSelf, options) {
231
+ return isRelationSchema(potentialRelationSchemaOrSelf, options) || potentialRelationSchemaOrSelf === '__self';
222
232
  }
223
233
  /**
224
234
  * Checks if the input is an Api.FieldValueType.
@@ -241,13 +251,15 @@ function isSemantic(potentialSemantic) {
241
251
  * @param potentialFieldSchema - The value to check.
242
252
  * @returns True if the value is a FieldSchema, false otherwise.
243
253
  */
244
- function isFieldSchema(potentialFieldSchema) {
254
+ function isFieldSchema(potentialFieldSchema, options) {
255
+ const strict = options?.strict ?? true;
245
256
  return (isObject(potentialFieldSchema) &&
246
257
  isString(potentialFieldSchema['name']) &&
247
258
  isString(potentialFieldSchema['label']) &&
248
259
  isString(potentialFieldSchema['type']) &&
249
- isFieldValueType(potentialFieldSchema['type']) &&
250
- (isUndefined(potentialFieldSchema['semantic']) || isSemantic(potentialFieldSchema['semantic'])));
260
+ (strict ? isFieldValueType(potentialFieldSchema['type']) : true) &&
261
+ (isUndefined(potentialFieldSchema['semantic']) ||
262
+ (strict ? isSemantic(potentialFieldSchema['semantic']) : isString(potentialFieldSchema['semantic']))));
251
263
  }
252
264
 
253
265
  const referenceToStringLikeConfiguration = {
@@ -662,15 +674,15 @@ function findRelationByJSONPath(item, query) {
662
674
  current = previousSchema;
663
675
  }
664
676
  const result = applyToken(current, token);
665
- if (isObject(result) && isRelationSchema(result['schema'])) {
677
+ if (isObject(result) && isRelationSchema(result['schema'], { strict: false })) {
666
678
  schemas.push(result['schema']);
667
679
  }
668
680
  current = result;
669
681
  }
670
- if (isRelation(current)) {
682
+ if (isRelation(current, { strict: false })) {
671
683
  return current;
672
684
  }
673
- if (isReferenceRelation(current) || isRelationSummary(current)) {
685
+ if (isReferenceRelation(current, { strict: false }) || isRelationSummary(current, { strict: false })) {
674
686
  const latestSchema = schemas[schemas.length - 1];
675
687
  if (latestSchema === undefined) {
676
688
  throw new Error(`No schema found for relation ${current.label}`);
@@ -828,6 +840,7 @@ exports.isItemSummary = isItemSummary;
828
840
  exports.isObject = isObject;
829
841
  exports.isReferenceRelation = isReferenceRelation;
830
842
  exports.isRelation = isRelation;
843
+ exports.isRelationPointer = isRelationPointer;
831
844
  exports.isRelationSchema = isRelationSchema;
832
845
  exports.isRelationSchemaOrSelf = isRelationSchemaOrSelf;
833
846
  exports.isRelationSummary = isRelationSummary;
@@ -15,15 +15,15 @@ export function findRelationByJSONPath(item, query) {
15
15
  current = previousSchema;
16
16
  }
17
17
  const result = applyToken(current, token);
18
- if (Guards.isObject(result) && Guards.isRelationSchema(result['schema'])) {
18
+ if (Guards.isObject(result) && Guards.isRelationSchema(result['schema'], { strict: false })) {
19
19
  schemas.push(result['schema']);
20
20
  }
21
21
  current = result;
22
22
  }
23
- if (Guards.isRelation(current)) {
23
+ if (Guards.isRelation(current, { strict: false })) {
24
24
  return current;
25
25
  }
26
- if (Guards.isReferenceRelation(current) || Guards.isRelationSummary(current)) {
26
+ if (Guards.isReferenceRelation(current, { strict: false }) || Guards.isRelationSummary(current, { strict: false })) {
27
27
  const latestSchema = schemas[schemas.length - 1];
28
28
  if (latestSchema === undefined) {
29
29
  throw new Error(`No schema found for relation ${current.label}`);
@@ -146,19 +146,33 @@ export interface BlobFieldSchema extends AbstractFieldSchema {
146
146
  interface UserReferenceFieldSchema extends AbstractFieldSchema {
147
147
  semantic: typeof Semantics.USER;
148
148
  type: typeof FieldValueTypes.REFERENCE;
149
- reference: ReferenceRelation;
149
+ reference: ReferenceRelation | RelationPointer;
150
150
  }
151
151
  interface ParentReferenceFieldSchema extends AbstractFieldSchema {
152
152
  semantic: typeof Semantics.PARENT;
153
153
  type: typeof FieldValueTypes.REFERENCE;
154
- reference: ReferenceRelation;
154
+ reference: ReferenceRelation | RelationPointer;
155
155
  }
156
156
  interface UnconstrainedReferenceFieldSchema extends AbstractFieldSchema {
157
157
  semantic?: never;
158
158
  type: typeof FieldValueTypes.REFERENCE;
159
- reference: ReferenceRelation;
159
+ reference: ReferenceRelation | RelationPointer;
160
160
  }
161
161
  export type ReferenceFieldSchema = UserReferenceFieldSchema | ParentReferenceFieldSchema | UnconstrainedReferenceFieldSchema;
162
+ /**
163
+ * A RelationPointer points to an existing relation elsewhere in the graph,
164
+ * avoiding the need to redeclare its schema inline.
165
+ */
166
+ export interface RelationPointer {
167
+ /**
168
+ * The path of the item that owns the target relation.
169
+ */
170
+ itemPath: string;
171
+ /**
172
+ * The name of the relation on that item.
173
+ */
174
+ relationName: string;
175
+ }
162
176
  /**
163
177
  * A ReferenceRelation describes a relation that can be used in a ReferenceFieldSchema.
164
178
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unito/integration-api",
3
- "version": "7.0.1",
3
+ "version": "7.1.1",
4
4
  "description": "The Unito Integration API",
5
5
  "type": "module",
6
6
  "types": "./dist/src/index.d.ts",