@player-tools/xlr-utils 0.4.1 → 0.4.2--canary.63.1238

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -253,23 +253,39 @@ function makePropertyMap(node) {
253
253
  function isNode(obj) {
254
254
  return typeof obj !== "string" || typeof obj !== "number" || typeof obj !== "boolean";
255
255
  }
256
- function resolveConditional(conditional) {
257
- const { left, right } = conditional.check;
258
- if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
259
- let conditionalResult = conditional.value.false;
260
- if ((left.type === "any" || left.type === "unknown") && (right.type === "any" || right.type === "unknown")) {
261
- conditionalResult = conditional.value.true;
262
- } else if ((left.type === "null" || left.type === "undefined") && (right.type === "null" || right.type === "undefined")) {
263
- conditionalResult = conditional.value.true;
264
- } else if (left.type === right.type) {
265
- if (left.const && right.const) {
266
- if (left.const === right.const) {
267
- conditionalResult = conditional.value.true;
256
+ function computeExtends(a, b) {
257
+ if ((a.type === "any" || a.type === "unknown") && (b.type === "any" || b.type === "unknown")) {
258
+ return true;
259
+ }
260
+ if ((a.type === "null" || a.type === "undefined") && (b.type === "null" || b.type === "undefined")) {
261
+ return true;
262
+ }
263
+ if (a.type === b.type) {
264
+ if (isPrimitiveTypeNode(a) && isPrimitiveTypeNode(b)) {
265
+ if (a.const && b.const) {
266
+ if (a.const === b.const) {
267
+ return true;
268
268
  }
269
269
  } else {
270
- conditionalResult = conditional.value.true;
270
+ return true;
271
+ }
272
+ }
273
+ if (a.type === "object" && b.type === "object") {
274
+ for (const property in b.properties) {
275
+ const propertyNode = b.properties[property];
276
+ if (!a.properties[property] || !computeExtends(a.properties[property].node, propertyNode.node)) {
277
+ return false;
278
+ }
271
279
  }
280
+ return true;
272
281
  }
282
+ }
283
+ return false;
284
+ }
285
+ function resolveConditional(conditional) {
286
+ const { left, right } = conditional.check;
287
+ if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
288
+ const conditionalResult = conditional.value.false;
273
289
  if (isGenericNodeType(conditional)) {
274
290
  const genericMap = new Map();
275
291
  conditional.genericTokens.forEach((token) => {
@@ -324,10 +340,12 @@ function computeEffectiveObject(base, operand, errorOnOverlap = true) {
324
340
  newObject.properties[property] = operand.properties[property];
325
341
  }
326
342
  if (newObject.additionalProperties && operand.additionalProperties) {
327
- newObject.additionalProperties = {
328
- type: "and",
329
- and: [newObject.additionalProperties, operand.additionalProperties]
330
- };
343
+ if (!isPrimitiveTypeNode(newObject.additionalProperties) || !isPrimitiveTypeNode(operand.additionalProperties) || newObject.additionalProperties.type !== operand.additionalProperties.type) {
344
+ newObject.additionalProperties = {
345
+ type: "and",
346
+ and: [newObject.additionalProperties, operand.additionalProperties]
347
+ };
348
+ }
331
349
  } else if (operand.additionalProperties) {
332
350
  newObject.additionalProperties = operand.additionalProperties;
333
351
  }
@@ -545,6 +563,20 @@ function applyPartialOrRequiredToNodeType(baseObject, modifier) {
545
563
  }
546
564
  throw new Error(`Error: Can not apply ${modifier ? "Required" : "Partial"} to type ${baseObject.type}`);
547
565
  }
566
+ function applyExcludeToNodeType(baseObject, filters) {
567
+ const remainingMembers = baseObject.or.filter((type) => {
568
+ if (filters.type === "or") {
569
+ return !filters.or.some((filter) => !computeExtends(type, filter));
570
+ }
571
+ return !computeExtends(type, filters);
572
+ });
573
+ if (remainingMembers.length === 1) {
574
+ return remainingMembers[0];
575
+ }
576
+ return __spreadProps(__spreadValues({}, baseObject), {
577
+ or: remainingMembers
578
+ });
579
+ }
548
580
 
549
581
  function setupTestEnv(sourceCode, mockFileName = "filename.ts") {
550
582
  const fsMap = tsvfs__namespace.createDefaultMapFromNodeModules({}, ts__namespace);
@@ -751,10 +783,12 @@ function createDocString(node) {
751
783
  return symbolDisplayToString(createTSDocString(node));
752
784
  }
753
785
 
786
+ exports.applyExcludeToNodeType = applyExcludeToNodeType;
754
787
  exports.applyPartialOrRequiredToNodeType = applyPartialOrRequiredToNodeType;
755
788
  exports.applyPickOrOmitToNodeType = applyPickOrOmitToNodeType;
756
789
  exports.buildTemplateRegex = buildTemplateRegex;
757
790
  exports.computeEffectiveObject = computeEffectiveObject;
791
+ exports.computeExtends = computeExtends;
758
792
  exports.createDocString = createDocString;
759
793
  exports.createTSDocString = createTSDocString;
760
794
  exports.decorateNode = decorateNode;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as ts from 'typescript';
2
2
  import ts__default, { SymbolDisplayPart } from 'typescript';
3
- import { Annotations, NodeType, NodeTypeWithGenerics, NamedType, NamedTypeWithGenerics, PrimitiveTypes, ConditionalType, RefNode, ObjectType } from '@player-tools/xlr';
3
+ import { Annotations, NodeType, OrType, NodeTypeWithGenerics, NamedType, NamedTypeWithGenerics, PrimitiveTypes, ConditionalType, RefNode, ObjectType } from '@player-tools/xlr';
4
4
  import { Node } from 'jsonc-parser';
5
5
 
6
6
  /**
@@ -44,6 +44,8 @@ declare function fillInGenerics(xlrNode: NodeType, generics?: Map<string, NodeTy
44
44
  declare function applyPickOrOmitToNodeType(baseObject: NodeType, operation: 'Pick' | 'Omit', properties: Set<string>): NodeType | undefined;
45
45
  /** Applies the TS `Omit` type to an interface/union/intersection */
46
46
  declare function applyPartialOrRequiredToNodeType(baseObject: NodeType, modifier: boolean): NodeType;
47
+ /** Applies the TS `Exclude` type to a union */
48
+ declare function applyExcludeToNodeType(baseObject: OrType, filters: NodeType | OrType): NodeType;
47
49
 
48
50
  /**
49
51
  * Returns if the Object Property is optional
@@ -106,6 +108,10 @@ declare function makePropertyMap(node: Node): Map<string, Node>;
106
108
  * Checks if property is a leaf node or another node
107
109
  */
108
110
  declare function isNode(obj: Node | string | number | boolean): obj is Node;
111
+ /**
112
+ * Computes if the first arg extends the second arg
113
+ */
114
+ declare function computeExtends(a: NodeType, b: NodeType): boolean;
109
115
  /**
110
116
  * Attempts to resolve a conditional type
111
117
  */
@@ -153,4 +159,4 @@ declare function symbolDisplayToString(displayParts: Array<SymbolDisplayPart>):
153
159
  /** Create a documentation string from node */
154
160
  declare function createDocString(node: NodeType): string;
155
161
 
156
- export { PropertyNode, SetupReturnType, TopLevelDeclaration, TopLevelNode, applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, computeEffectiveObject, createDocString, createTSDocString, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelDeclaration, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, resolveReferenceNode, setupTestEnv, symbolDisplayToString, tsStripOptionalType };
162
+ export { PropertyNode, SetupReturnType, TopLevelDeclaration, TopLevelNode, applyExcludeToNodeType, applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, computeEffectiveObject, computeExtends, createDocString, createTSDocString, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelDeclaration, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, resolveReferenceNode, setupTestEnv, symbolDisplayToString, tsStripOptionalType };
package/dist/index.esm.js CHANGED
@@ -226,23 +226,39 @@ function makePropertyMap(node) {
226
226
  function isNode(obj) {
227
227
  return typeof obj !== "string" || typeof obj !== "number" || typeof obj !== "boolean";
228
228
  }
229
- function resolveConditional(conditional) {
230
- const { left, right } = conditional.check;
231
- if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
232
- let conditionalResult = conditional.value.false;
233
- if ((left.type === "any" || left.type === "unknown") && (right.type === "any" || right.type === "unknown")) {
234
- conditionalResult = conditional.value.true;
235
- } else if ((left.type === "null" || left.type === "undefined") && (right.type === "null" || right.type === "undefined")) {
236
- conditionalResult = conditional.value.true;
237
- } else if (left.type === right.type) {
238
- if (left.const && right.const) {
239
- if (left.const === right.const) {
240
- conditionalResult = conditional.value.true;
229
+ function computeExtends(a, b) {
230
+ if ((a.type === "any" || a.type === "unknown") && (b.type === "any" || b.type === "unknown")) {
231
+ return true;
232
+ }
233
+ if ((a.type === "null" || a.type === "undefined") && (b.type === "null" || b.type === "undefined")) {
234
+ return true;
235
+ }
236
+ if (a.type === b.type) {
237
+ if (isPrimitiveTypeNode(a) && isPrimitiveTypeNode(b)) {
238
+ if (a.const && b.const) {
239
+ if (a.const === b.const) {
240
+ return true;
241
241
  }
242
242
  } else {
243
- conditionalResult = conditional.value.true;
243
+ return true;
244
+ }
245
+ }
246
+ if (a.type === "object" && b.type === "object") {
247
+ for (const property in b.properties) {
248
+ const propertyNode = b.properties[property];
249
+ if (!a.properties[property] || !computeExtends(a.properties[property].node, propertyNode.node)) {
250
+ return false;
251
+ }
244
252
  }
253
+ return true;
245
254
  }
255
+ }
256
+ return false;
257
+ }
258
+ function resolveConditional(conditional) {
259
+ const { left, right } = conditional.check;
260
+ if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
261
+ const conditionalResult = conditional.value.false;
246
262
  if (isGenericNodeType(conditional)) {
247
263
  const genericMap = new Map();
248
264
  conditional.genericTokens.forEach((token) => {
@@ -297,10 +313,12 @@ function computeEffectiveObject(base, operand, errorOnOverlap = true) {
297
313
  newObject.properties[property] = operand.properties[property];
298
314
  }
299
315
  if (newObject.additionalProperties && operand.additionalProperties) {
300
- newObject.additionalProperties = {
301
- type: "and",
302
- and: [newObject.additionalProperties, operand.additionalProperties]
303
- };
316
+ if (!isPrimitiveTypeNode(newObject.additionalProperties) || !isPrimitiveTypeNode(operand.additionalProperties) || newObject.additionalProperties.type !== operand.additionalProperties.type) {
317
+ newObject.additionalProperties = {
318
+ type: "and",
319
+ and: [newObject.additionalProperties, operand.additionalProperties]
320
+ };
321
+ }
304
322
  } else if (operand.additionalProperties) {
305
323
  newObject.additionalProperties = operand.additionalProperties;
306
324
  }
@@ -518,6 +536,20 @@ function applyPartialOrRequiredToNodeType(baseObject, modifier) {
518
536
  }
519
537
  throw new Error(`Error: Can not apply ${modifier ? "Required" : "Partial"} to type ${baseObject.type}`);
520
538
  }
539
+ function applyExcludeToNodeType(baseObject, filters) {
540
+ const remainingMembers = baseObject.or.filter((type) => {
541
+ if (filters.type === "or") {
542
+ return !filters.or.some((filter) => !computeExtends(type, filter));
543
+ }
544
+ return !computeExtends(type, filters);
545
+ });
546
+ if (remainingMembers.length === 1) {
547
+ return remainingMembers[0];
548
+ }
549
+ return __spreadProps(__spreadValues({}, baseObject), {
550
+ or: remainingMembers
551
+ });
552
+ }
521
553
 
522
554
  function setupTestEnv(sourceCode, mockFileName = "filename.ts") {
523
555
  const fsMap = tsvfs.createDefaultMapFromNodeModules({}, ts);
@@ -724,5 +756,5 @@ function createDocString(node) {
724
756
  return symbolDisplayToString(createTSDocString(node));
725
757
  }
726
758
 
727
- export { applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, computeEffectiveObject, createDocString, createTSDocString, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelDeclaration, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, resolveReferenceNode, setupTestEnv, symbolDisplayToString, tsStripOptionalType };
759
+ export { applyExcludeToNodeType, applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, computeEffectiveObject, computeExtends, createDocString, createTSDocString, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelDeclaration, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, resolveReferenceNode, setupTestEnv, symbolDisplayToString, tsStripOptionalType };
728
760
  //# sourceMappingURL=index.esm.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@player-tools/xlr-utils",
3
- "version": "0.4.1",
3
+ "version": "0.4.2--canary.63.1238",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org"
@@ -10,7 +10,7 @@
10
10
  "jsonc-parser": "^2.3.1"
11
11
  },
12
12
  "dependencies": {
13
- "@player-tools/xlr": "0.4.1",
13
+ "@player-tools/xlr": "0.4.2--canary.63.1238",
14
14
  "@typescript/vfs": "^1.4.0",
15
15
  "@babel/runtime": "7.15.4"
16
16
  },
package/src/ts-helpers.ts CHANGED
@@ -5,8 +5,9 @@ import type {
5
5
  NodeType,
6
6
  ObjectProperty,
7
7
  ObjectType,
8
+ OrType,
8
9
  } from '@player-tools/xlr';
9
- import { resolveConditional } from './validation-helpers';
10
+ import { computeExtends, resolveConditional } from './validation-helpers';
10
11
  import { isGenericNodeType } from './type-checks';
11
12
 
12
13
  /**
@@ -359,3 +360,26 @@ export function applyPartialOrRequiredToNodeType(
359
360
  }`
360
361
  );
361
362
  }
363
+
364
+ /** Applies the TS `Exclude` type to a union */
365
+ export function applyExcludeToNodeType(
366
+ baseObject: OrType,
367
+ filters: NodeType | OrType
368
+ ): NodeType {
369
+ const remainingMembers = baseObject.or.filter((type) => {
370
+ if (filters.type === 'or') {
371
+ return !filters.or.some((filter) => !computeExtends(type, filter));
372
+ }
373
+
374
+ return !computeExtends(type, filters);
375
+ });
376
+
377
+ if (remainingMembers.length === 1) {
378
+ return remainingMembers[0];
379
+ }
380
+
381
+ return {
382
+ ...baseObject,
383
+ or: remainingMembers,
384
+ };
385
+ }
@@ -1,3 +1,5 @@
1
+ /* eslint-disable guard-for-in */
2
+ /* eslint-disable no-restricted-syntax */
1
3
  import type { Node } from 'jsonc-parser';
2
4
  import type {
3
5
  ConditionalType,
@@ -55,34 +57,61 @@ export function isNode(obj: Node | string | number | boolean): obj is Node {
55
57
  }
56
58
 
57
59
  /**
58
- * Attempts to resolve a conditional type
60
+ * Computes if the first arg extends the second arg
59
61
  */
60
- export function resolveConditional(conditional: ConditionalType): NodeType {
61
- const { left, right } = conditional.check;
62
- if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
63
- let conditionalResult = conditional.value.false;
62
+ export function computeExtends(a: NodeType, b: NodeType): boolean {
63
+ // special case for any/unknown being functionally the same
64
+ if (
65
+ (a.type === 'any' || a.type === 'unknown') &&
66
+ (b.type === 'any' || b.type === 'unknown')
67
+ ) {
68
+ return true;
69
+ }
64
70
 
65
- if (
66
- (left.type === 'any' || left.type === 'unknown') &&
67
- (right.type === 'any' || right.type === 'unknown')
68
- ) {
69
- // special case for any/unknown being functionally the same
70
- conditionalResult = conditional.value.true;
71
- } else if (
72
- (left.type === 'null' || left.type === 'undefined') &&
73
- (right.type === 'null' || right.type === 'undefined')
74
- ) {
75
- // special case for null/undefined being functionally the same
76
- conditionalResult = conditional.value.true;
77
- } else if (left.type === right.type) {
78
- if (left.const && right.const) {
79
- if (left.const === right.const) {
80
- conditionalResult = conditional.value.true;
71
+ // special case for null/undefined being functionally the same
72
+ if (
73
+ (a.type === 'null' || a.type === 'undefined') &&
74
+ (b.type === 'null' || b.type === 'undefined')
75
+ ) {
76
+ return true;
77
+ }
78
+
79
+ if (a.type === b.type) {
80
+ if (isPrimitiveTypeNode(a) && isPrimitiveTypeNode(b)) {
81
+ if (a.const && b.const) {
82
+ if (a.const === b.const) {
83
+ return true;
81
84
  }
82
85
  } else {
83
- conditionalResult = conditional.value.true;
86
+ return true;
87
+ }
88
+ }
89
+
90
+ if (a.type === 'object' && b.type === 'object') {
91
+ for (const property in b.properties) {
92
+ const propertyNode = b.properties[property];
93
+ if (
94
+ !a.properties[property] ||
95
+ !computeExtends(a.properties[property].node, propertyNode.node)
96
+ ) {
97
+ return false;
98
+ }
84
99
  }
100
+
101
+ return true;
85
102
  }
103
+ }
104
+
105
+ return false;
106
+ }
107
+
108
+ /**
109
+ * Attempts to resolve a conditional type
110
+ */
111
+ export function resolveConditional(conditional: ConditionalType): NodeType {
112
+ const { left, right } = conditional.check;
113
+ if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
114
+ const conditionalResult = conditional.value.false;
86
115
 
87
116
  // Compose first level generics here since `conditionalResult` won't have them
88
117
  if (isGenericNodeType(conditional)) {
@@ -190,10 +219,16 @@ export function computeEffectiveObject(
190
219
  }
191
220
 
192
221
  if (newObject.additionalProperties && operand.additionalProperties) {
193
- newObject.additionalProperties = {
194
- type: 'and',
195
- and: [newObject.additionalProperties, operand.additionalProperties],
196
- };
222
+ if (
223
+ !isPrimitiveTypeNode(newObject.additionalProperties) ||
224
+ !isPrimitiveTypeNode(operand.additionalProperties) ||
225
+ newObject.additionalProperties.type !== operand.additionalProperties.type
226
+ ) {
227
+ newObject.additionalProperties = {
228
+ type: 'and',
229
+ and: [newObject.additionalProperties, operand.additionalProperties],
230
+ };
231
+ }
197
232
  } else if (operand.additionalProperties) {
198
233
  newObject.additionalProperties = operand.additionalProperties;
199
234
  }