@player-tools/xlr-utils 0.2.1-next.3 → 0.2.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.
package/dist/index.cjs.js CHANGED
@@ -29,19 +29,19 @@ var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
29
29
  var ts__default = /*#__PURE__*/_interopDefaultLegacy(ts);
30
30
  var tsvfs__default = /*#__PURE__*/_interopDefaultLegacy(tsvfs);
31
31
 
32
- var __defProp$1 = Object.defineProperty;
33
- var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
34
- var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
35
- var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
36
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
37
- var __spreadValues$1 = (a, b) => {
32
+ var __defProp$2 = Object.defineProperty;
33
+ var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
34
+ var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
35
+ var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
36
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
37
+ var __spreadValues$2 = (a, b) => {
38
38
  for (var prop in b || (b = {}))
39
- if (__hasOwnProp$1.call(b, prop))
40
- __defNormalProp$1(a, prop, b[prop]);
41
- if (__getOwnPropSymbols$1)
42
- for (var prop of __getOwnPropSymbols$1(b)) {
43
- if (__propIsEnum$1.call(b, prop))
44
- __defNormalProp$1(a, prop, b[prop]);
39
+ if (__hasOwnProp$2.call(b, prop))
40
+ __defNormalProp$2(a, prop, b[prop]);
41
+ if (__getOwnPropSymbols$2)
42
+ for (var prop of __getOwnPropSymbols$2(b)) {
43
+ if (__propIsEnum$2.call(b, prop))
44
+ __defNormalProp$2(a, prop, b[prop]);
45
45
  }
46
46
  return a;
47
47
  };
@@ -132,7 +132,7 @@ function extractTags(tags) {
132
132
  descriptions.push(`@${tag.tagName.text} ${text}`);
133
133
  }
134
134
  });
135
- return __spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1({}, descriptions.length === 0 ? {} : { description: descriptions.join("\n") }), examples.length === 0 ? {} : { examples }), _default.length === 0 ? {} : { default: _default.join("\n") }), see.length === 0 ? {} : { see });
135
+ return __spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2({}, descriptions.length === 0 ? {} : { description: descriptions.join("\n") }), examples.length === 0 ? {} : { examples }), _default.length === 0 ? {} : { default: _default.join("\n") }), see.length === 0 ? {} : { see });
136
136
  }
137
137
  function join(t, separator = "\n") {
138
138
  const unique = new Set(t).values();
@@ -147,7 +147,7 @@ function mergeAnnotations(nodes) {
147
147
  const comment = join(nodes.map((n) => n.comment));
148
148
  const examples = join(nodes.map((n) => Array.isArray(n.examples) ? join(n.examples) : n.examples));
149
149
  const see = join(nodes.map((n) => Array.isArray(n.see) ? join(n.see) : n.see));
150
- return __spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1({}, name ? { name } : {}), title ? { title } : {}), description ? { description } : {}), examples ? { examples } : {}), _default ? { default: _default } : {}), see ? { see } : {}), comment ? { comment } : {});
150
+ return __spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2({}, name ? { name } : {}), title ? { title } : {}), description ? { description } : {}), examples ? { examples } : {}), _default ? { default: _default } : {}), see ? { see } : {}), comment ? { comment } : {});
151
151
  }
152
152
  function decorateNode(node) {
153
153
  var _a;
@@ -197,12 +197,31 @@ function isGenericNamedType(nt) {
197
197
  return ((_a = nt.genericTokens) == null ? void 0 : _a.length) > 0;
198
198
  }
199
199
  function isPrimitiveTypeNode(node) {
200
- return node.type === "string" || node.type === "number" || node.type === "boolean" || node.type === "null" || node.type === "template" || node.type === "any" || node.type === "never" || node.type === "undefined" || node.type === "unknown";
200
+ return node.type === "string" || node.type === "number" || node.type === "boolean" || node.type === "null" || node.type === "any" || node.type === "never" || node.type === "undefined" || node.type === "unknown";
201
201
  }
202
202
  function isNonNullable(a) {
203
203
  return a !== null || a !== void 0;
204
204
  }
205
205
 
206
+ var __defProp$1 = Object.defineProperty;
207
+ var __defProps$1 = Object.defineProperties;
208
+ var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
209
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
210
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
211
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
212
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
213
+ var __spreadValues$1 = (a, b) => {
214
+ for (var prop in b || (b = {}))
215
+ if (__hasOwnProp$1.call(b, prop))
216
+ __defNormalProp$1(a, prop, b[prop]);
217
+ if (__getOwnPropSymbols$1)
218
+ for (var prop of __getOwnPropSymbols$1(b)) {
219
+ if (__propIsEnum$1.call(b, prop))
220
+ __defNormalProp$1(a, prop, b[prop]);
221
+ }
222
+ return a;
223
+ };
224
+ var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
206
225
  function propertyToTuple(node) {
207
226
  var _a, _b;
208
227
  let key = (_a = node.children) == null ? void 0 : _a[0].value;
@@ -229,22 +248,83 @@ function isNode(obj) {
229
248
  function resolveConditional(conditional) {
230
249
  const { left, right } = conditional.check;
231
250
  if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
232
- if (left.const && right.const) {
233
- return left.const === right.const ? conditional.value.true : conditional.value.false;
234
- }
251
+ let conditionalResult = conditional.value.false;
235
252
  if ((left.type === "any" || left.type === "unknown") && (right.type === "any" || right.type === "unknown")) {
236
- return conditional.value.true;
237
- }
238
- if ((left.type === "null" || left.type === "undefined") && (right.type === "null" || right.type === "undefined")) {
239
- return conditional.value.true;
253
+ conditionalResult = conditional.value.true;
254
+ } else if ((left.type === "null" || left.type === "undefined") && (right.type === "null" || right.type === "undefined")) {
255
+ conditionalResult = conditional.value.true;
256
+ } else if (left.type === right.type) {
257
+ if (left.const && right.const) {
258
+ if (left.const === right.const) {
259
+ conditionalResult = conditional.value.true;
260
+ }
261
+ } else {
262
+ conditionalResult = conditional.value.true;
263
+ }
240
264
  }
241
- if (left.type === right.type) {
242
- return conditional.value.true;
265
+ if (isGenericNodeType(conditional)) {
266
+ const genericMap = new Map();
267
+ conditional.genericTokens.forEach((token) => {
268
+ var _a, _b;
269
+ genericMap.set(token.symbol, (_b = (_a = token.default) != null ? _a : token.constraints) != null ? _b : { type: "any" });
270
+ });
271
+ return fillInGenerics(conditionalResult, genericMap);
243
272
  }
244
- return conditional.value.false;
273
+ return conditionalResult;
245
274
  }
246
275
  return conditional;
247
276
  }
277
+ function resolveReferenceNode(genericReference, typeToFill) {
278
+ var _a, _b, _c;
279
+ const genericArgs = genericReference.genericArguments;
280
+ const genericMap = new Map();
281
+ if (genericArgs && isGenericNodeType(typeToFill)) {
282
+ typeToFill.genericTokens.forEach((token, index) => {
283
+ var _a2, _b2;
284
+ genericMap.set(token.symbol, (_b2 = (_a2 = genericArgs[index]) != null ? _a2 : token.default) != null ? _b2 : token.constraints);
285
+ });
286
+ }
287
+ const filledInNode = fillInGenerics(typeToFill, genericMap);
288
+ if (isGenericNodeType(filledInNode) && (genericArgs == null ? void 0 : genericArgs.length)) {
289
+ if (genericArgs.length < filledInNode.genericTokens.length) {
290
+ filledInNode.genericTokens = filledInNode.genericTokens.slice(genericArgs == null ? void 0 : genericArgs.length);
291
+ } else if (genericArgs.length === filledInNode.genericTokens.length) {
292
+ filledInNode.genericTokens = [];
293
+ }
294
+ }
295
+ if (genericReference.property && filledInNode.type === "object") {
296
+ return (_c = (_b = (_a = filledInNode.properties[genericReference.property]) == null ? void 0 : _a.node) != null ? _b : filledInNode.additionalProperties) != null ? _c : { type: "undefined" };
297
+ }
298
+ return filledInNode;
299
+ }
300
+ function computeEffectiveObject(base, operand, errorOnOverlap = true) {
301
+ var _a, _b;
302
+ const baseObjectName = (_a = base.name) != null ? _a : "object literal";
303
+ const operandObjectName = (_b = operand.name) != null ? _b : "object literal";
304
+ const newObject = __spreadProps$1(__spreadValues$1({}, base), {
305
+ name: `${baseObjectName} & ${operandObjectName}`,
306
+ description: `Effective type combining ${baseObjectName} and ${operandObjectName}`,
307
+ genericTokens: [
308
+ ...isGenericNodeType(base) ? base.genericTokens : [],
309
+ ...isGenericNodeType(operand) ? operand.genericTokens : []
310
+ ]
311
+ });
312
+ for (const property in operand.properties) {
313
+ if (newObject.properties[property] !== void 0 && newObject.properties[property].node.type !== operand.properties[property].node.type && errorOnOverlap) {
314
+ throw new Error(`Can't compute effective type for ${baseObjectName} and ${operandObjectName} because of conflicting properties ${property}`);
315
+ }
316
+ newObject.properties[property] = operand.properties[property];
317
+ }
318
+ if (newObject.additionalProperties && operand.additionalProperties) {
319
+ newObject.additionalProperties = {
320
+ type: "and",
321
+ and: [newObject.additionalProperties, operand.additionalProperties]
322
+ };
323
+ } else if (operand.additionalProperties) {
324
+ newObject.additionalProperties = operand.additionalProperties;
325
+ }
326
+ return newObject;
327
+ }
248
328
 
249
329
  var __defProp = Object.defineProperty;
250
330
  var __defProps = Object.defineProperties;
@@ -269,8 +349,8 @@ function tsStripOptionalType(node) {
269
349
  return ts__namespace.isOptionalTypeNode(node) ? node.type : node;
270
350
  }
271
351
  function isExportedDeclaration(node) {
272
- var _a;
273
- return !!((_a = node.modifiers) == null ? void 0 : _a.some((modifier) => modifier.kind === ts__namespace.SyntaxKind.ExportKeyword));
352
+ const modifiers = ts__namespace.canHaveModifiers(node) ? ts__namespace.getModifiers(node) : void 0;
353
+ return modifiers && modifiers.some((modifier) => modifier.kind === ts__namespace.SyntaxKind.ExportKeyword);
274
354
  }
275
355
  function isNodeExported(node) {
276
356
  return (ts__namespace.getCombinedModifierFlags(node) & ts__namespace.ModifierFlags.Export) !== 0 || !!node.parent && node.parent.kind === ts__namespace.SyntaxKind.SourceFile;
@@ -458,47 +538,26 @@ function applyPartialOrRequiredToNodeType(baseObject, modifier) {
458
538
  throw new Error(`Error: Can not apply ${modifier ? "Required" : "Partial"} to type ${baseObject.type}`);
459
539
  }
460
540
 
461
- var __async = (__this, __arguments, generator) => {
462
- return new Promise((resolve, reject) => {
463
- var fulfilled = (value) => {
464
- try {
465
- step(generator.next(value));
466
- } catch (e) {
467
- reject(e);
468
- }
469
- };
470
- var rejected = (value) => {
471
- try {
472
- step(generator.throw(value));
473
- } catch (e) {
474
- reject(e);
475
- }
476
- };
477
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
478
- step((generator = generator.apply(__this, __arguments)).next());
479
- });
480
- };
481
541
  function setupTestEnv(sourceCode, mockFileName = "filename.ts") {
482
- return __async(this, null, function* () {
483
- const fsMap = yield tsvfs__default["default"].createDefaultMapFromNodeModules({}, ts__default["default"]);
484
- fsMap.set(mockFileName, sourceCode);
485
- const system = tsvfs__default["default"].createSystem(fsMap);
486
- const host = tsvfs__default["default"].createVirtualCompilerHost(system, {}, ts__default["default"]);
487
- const program = ts__default["default"].createProgram({
488
- rootNames: [...fsMap.keys()],
489
- options: {},
490
- host: host.compilerHost
491
- });
492
- return {
493
- sf: host.compilerHost.getSourceFile(mockFileName, ts__default["default"].ScriptTarget.ES5),
494
- tc: program.getTypeChecker()
495
- };
542
+ const fsMap = tsvfs__default["default"].createDefaultMapFromNodeModules({}, ts__default["default"]);
543
+ fsMap.set(mockFileName, sourceCode);
544
+ const system = tsvfs__default["default"].createSystem(fsMap);
545
+ const host = tsvfs__default["default"].createVirtualCompilerHost(system, {}, ts__default["default"]);
546
+ const program = ts__default["default"].createProgram({
547
+ rootNames: [...fsMap.keys()],
548
+ options: {},
549
+ host: host.compilerHost
496
550
  });
551
+ return {
552
+ sf: host.compilerHost.getSourceFile(mockFileName, ts__default["default"].ScriptTarget.ES5),
553
+ tc: program.getTypeChecker()
554
+ };
497
555
  }
498
556
 
499
557
  exports.applyPartialOrRequiredToNodeType = applyPartialOrRequiredToNodeType;
500
558
  exports.applyPickOrOmitToNodeType = applyPickOrOmitToNodeType;
501
559
  exports.buildTemplateRegex = buildTemplateRegex;
560
+ exports.computeEffectiveObject = computeEffectiveObject;
502
561
  exports.decorateNode = decorateNode;
503
562
  exports.fillInGenerics = fillInGenerics;
504
563
  exports.getReferencedType = getReferencedType;
@@ -518,6 +577,7 @@ exports.isTypeReferenceGeneric = isTypeReferenceGeneric;
518
577
  exports.makePropertyMap = makePropertyMap;
519
578
  exports.propertyToTuple = propertyToTuple;
520
579
  exports.resolveConditional = resolveConditional;
580
+ exports.resolveReferenceNode = resolveReferenceNode;
521
581
  exports.setupTestEnv = setupTestEnv;
522
582
  exports.tsStripOptionalType = tsStripOptionalType;
523
583
  //# sourceMappingURL=index.cjs.js.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as ts from 'typescript';
2
2
  import ts__default from 'typescript';
3
- import { Annotations, NodeType, NodeTypeWithGenerics, NamedType, NamedTypeWithGenerics, PrimitiveTypes, ConditionalType } from '@player-tools/xlr';
3
+ import { Annotations, NodeType, NodeTypeWithGenerics, NamedType, NamedTypeWithGenerics, PrimitiveTypes, ConditionalType, RefNode, ObjectType } from '@player-tools/xlr';
4
4
  import { Node } from 'jsonc-parser';
5
5
 
6
6
  /**
@@ -15,7 +15,7 @@ declare function tsStripOptionalType(node: ts.TypeNode): ts.TypeNode;
15
15
  /**
16
16
  * Returns if the top level declaration is exported
17
17
  */
18
- declare function isExportedDeclaration(node: ts.Statement): boolean;
18
+ declare function isExportedDeclaration(node: ts.Statement): boolean | undefined;
19
19
  /**
20
20
  * Returns if the node is exported from the source file
21
21
  */
@@ -37,6 +37,7 @@ declare function getStringLiteralsFromUnion(node: ts.Node): Set<string>;
37
37
  declare function buildTemplateRegex(node: ts.TemplateLiteralTypeNode, typeChecker: ts.TypeChecker): string;
38
38
  /**
39
39
  * Walks generics to fill in values from a combination of the default, constraint, and passed in map values
40
+ * TODO convert this to use simpleTransformGenerator
40
41
  */
41
42
  declare function fillInGenerics(xlrNode: NodeType, generics?: Map<string, NodeType>): NodeType;
42
43
  /** Applies the TS `Pick` type to an interface/union/intersection */
@@ -104,6 +105,18 @@ declare function isNode(obj: Node | string | number | boolean): obj is Node;
104
105
  * Attempts to resolve a conditional type
105
106
  */
106
107
  declare function resolveConditional(conditional: ConditionalType): NodeType;
108
+ /**
109
+ *
110
+ */
111
+ declare function resolveReferenceNode(genericReference: RefNode, typeToFill: NodeType): NodeType;
112
+ /**
113
+ * Combines two ObjectType objects to get a representation of the effective TypeScript interface of `base` extending `operand`
114
+ - * @param base The base interface
115
+ - * @param operand The interface that is extended
116
+ - * @param errorOnOverlap whether or not conflicting properties should throw an error or use the property from operand
117
+ - * @returns `ObjectType`
118
+ */
119
+ declare function computeEffectiveObject(base: ObjectType, operand: ObjectType, errorOnOverlap?: boolean): ObjectType;
107
120
 
108
121
  interface SetupReturnType {
109
122
  /**
@@ -118,9 +131,9 @@ interface SetupReturnType {
118
131
  /**
119
132
  * Setups a virtual TS environment for tests
120
133
  */
121
- declare function setupTestEnv(sourceCode: string, mockFileName?: string): Promise<{
134
+ declare function setupTestEnv(sourceCode: string, mockFileName?: string): {
122
135
  sf: ts__default.SourceFile;
123
136
  tc: ts__default.TypeChecker;
124
- }>;
137
+ };
125
138
 
126
- export { PropertyNode, SetupReturnType, TopLevelDeclaration, applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, setupTestEnv, tsStripOptionalType };
139
+ export { PropertyNode, SetupReturnType, TopLevelDeclaration, applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, computeEffectiveObject, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, resolveReferenceNode, setupTestEnv, tsStripOptionalType };
package/dist/index.esm.js CHANGED
@@ -2,19 +2,19 @@ import * as ts from 'typescript';
2
2
  import ts__default from 'typescript';
3
3
  import tsvfs from '@typescript/vfs';
4
4
 
5
- var __defProp$1 = Object.defineProperty;
6
- var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
7
- var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
8
- var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
9
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
- var __spreadValues$1 = (a, b) => {
5
+ var __defProp$2 = Object.defineProperty;
6
+ var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
7
+ var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
8
+ var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
9
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __spreadValues$2 = (a, b) => {
11
11
  for (var prop in b || (b = {}))
12
- if (__hasOwnProp$1.call(b, prop))
13
- __defNormalProp$1(a, prop, b[prop]);
14
- if (__getOwnPropSymbols$1)
15
- for (var prop of __getOwnPropSymbols$1(b)) {
16
- if (__propIsEnum$1.call(b, prop))
17
- __defNormalProp$1(a, prop, b[prop]);
12
+ if (__hasOwnProp$2.call(b, prop))
13
+ __defNormalProp$2(a, prop, b[prop]);
14
+ if (__getOwnPropSymbols$2)
15
+ for (var prop of __getOwnPropSymbols$2(b)) {
16
+ if (__propIsEnum$2.call(b, prop))
17
+ __defNormalProp$2(a, prop, b[prop]);
18
18
  }
19
19
  return a;
20
20
  };
@@ -105,7 +105,7 @@ function extractTags(tags) {
105
105
  descriptions.push(`@${tag.tagName.text} ${text}`);
106
106
  }
107
107
  });
108
- return __spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1({}, descriptions.length === 0 ? {} : { description: descriptions.join("\n") }), examples.length === 0 ? {} : { examples }), _default.length === 0 ? {} : { default: _default.join("\n") }), see.length === 0 ? {} : { see });
108
+ return __spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2({}, descriptions.length === 0 ? {} : { description: descriptions.join("\n") }), examples.length === 0 ? {} : { examples }), _default.length === 0 ? {} : { default: _default.join("\n") }), see.length === 0 ? {} : { see });
109
109
  }
110
110
  function join(t, separator = "\n") {
111
111
  const unique = new Set(t).values();
@@ -120,7 +120,7 @@ function mergeAnnotations(nodes) {
120
120
  const comment = join(nodes.map((n) => n.comment));
121
121
  const examples = join(nodes.map((n) => Array.isArray(n.examples) ? join(n.examples) : n.examples));
122
122
  const see = join(nodes.map((n) => Array.isArray(n.see) ? join(n.see) : n.see));
123
- return __spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1(__spreadValues$1({}, name ? { name } : {}), title ? { title } : {}), description ? { description } : {}), examples ? { examples } : {}), _default ? { default: _default } : {}), see ? { see } : {}), comment ? { comment } : {});
123
+ return __spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2(__spreadValues$2({}, name ? { name } : {}), title ? { title } : {}), description ? { description } : {}), examples ? { examples } : {}), _default ? { default: _default } : {}), see ? { see } : {}), comment ? { comment } : {});
124
124
  }
125
125
  function decorateNode(node) {
126
126
  var _a;
@@ -170,12 +170,31 @@ function isGenericNamedType(nt) {
170
170
  return ((_a = nt.genericTokens) == null ? void 0 : _a.length) > 0;
171
171
  }
172
172
  function isPrimitiveTypeNode(node) {
173
- return node.type === "string" || node.type === "number" || node.type === "boolean" || node.type === "null" || node.type === "template" || node.type === "any" || node.type === "never" || node.type === "undefined" || node.type === "unknown";
173
+ return node.type === "string" || node.type === "number" || node.type === "boolean" || node.type === "null" || node.type === "any" || node.type === "never" || node.type === "undefined" || node.type === "unknown";
174
174
  }
175
175
  function isNonNullable(a) {
176
176
  return a !== null || a !== void 0;
177
177
  }
178
178
 
179
+ var __defProp$1 = Object.defineProperty;
180
+ var __defProps$1 = Object.defineProperties;
181
+ var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
182
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
183
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
184
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
185
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
186
+ var __spreadValues$1 = (a, b) => {
187
+ for (var prop in b || (b = {}))
188
+ if (__hasOwnProp$1.call(b, prop))
189
+ __defNormalProp$1(a, prop, b[prop]);
190
+ if (__getOwnPropSymbols$1)
191
+ for (var prop of __getOwnPropSymbols$1(b)) {
192
+ if (__propIsEnum$1.call(b, prop))
193
+ __defNormalProp$1(a, prop, b[prop]);
194
+ }
195
+ return a;
196
+ };
197
+ var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
179
198
  function propertyToTuple(node) {
180
199
  var _a, _b;
181
200
  let key = (_a = node.children) == null ? void 0 : _a[0].value;
@@ -202,22 +221,83 @@ function isNode(obj) {
202
221
  function resolveConditional(conditional) {
203
222
  const { left, right } = conditional.check;
204
223
  if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
205
- if (left.const && right.const) {
206
- return left.const === right.const ? conditional.value.true : conditional.value.false;
207
- }
224
+ let conditionalResult = conditional.value.false;
208
225
  if ((left.type === "any" || left.type === "unknown") && (right.type === "any" || right.type === "unknown")) {
209
- return conditional.value.true;
210
- }
211
- if ((left.type === "null" || left.type === "undefined") && (right.type === "null" || right.type === "undefined")) {
212
- return conditional.value.true;
226
+ conditionalResult = conditional.value.true;
227
+ } else if ((left.type === "null" || left.type === "undefined") && (right.type === "null" || right.type === "undefined")) {
228
+ conditionalResult = conditional.value.true;
229
+ } else if (left.type === right.type) {
230
+ if (left.const && right.const) {
231
+ if (left.const === right.const) {
232
+ conditionalResult = conditional.value.true;
233
+ }
234
+ } else {
235
+ conditionalResult = conditional.value.true;
236
+ }
213
237
  }
214
- if (left.type === right.type) {
215
- return conditional.value.true;
238
+ if (isGenericNodeType(conditional)) {
239
+ const genericMap = new Map();
240
+ conditional.genericTokens.forEach((token) => {
241
+ var _a, _b;
242
+ genericMap.set(token.symbol, (_b = (_a = token.default) != null ? _a : token.constraints) != null ? _b : { type: "any" });
243
+ });
244
+ return fillInGenerics(conditionalResult, genericMap);
216
245
  }
217
- return conditional.value.false;
246
+ return conditionalResult;
218
247
  }
219
248
  return conditional;
220
249
  }
250
+ function resolveReferenceNode(genericReference, typeToFill) {
251
+ var _a, _b, _c;
252
+ const genericArgs = genericReference.genericArguments;
253
+ const genericMap = new Map();
254
+ if (genericArgs && isGenericNodeType(typeToFill)) {
255
+ typeToFill.genericTokens.forEach((token, index) => {
256
+ var _a2, _b2;
257
+ genericMap.set(token.symbol, (_b2 = (_a2 = genericArgs[index]) != null ? _a2 : token.default) != null ? _b2 : token.constraints);
258
+ });
259
+ }
260
+ const filledInNode = fillInGenerics(typeToFill, genericMap);
261
+ if (isGenericNodeType(filledInNode) && (genericArgs == null ? void 0 : genericArgs.length)) {
262
+ if (genericArgs.length < filledInNode.genericTokens.length) {
263
+ filledInNode.genericTokens = filledInNode.genericTokens.slice(genericArgs == null ? void 0 : genericArgs.length);
264
+ } else if (genericArgs.length === filledInNode.genericTokens.length) {
265
+ filledInNode.genericTokens = [];
266
+ }
267
+ }
268
+ if (genericReference.property && filledInNode.type === "object") {
269
+ return (_c = (_b = (_a = filledInNode.properties[genericReference.property]) == null ? void 0 : _a.node) != null ? _b : filledInNode.additionalProperties) != null ? _c : { type: "undefined" };
270
+ }
271
+ return filledInNode;
272
+ }
273
+ function computeEffectiveObject(base, operand, errorOnOverlap = true) {
274
+ var _a, _b;
275
+ const baseObjectName = (_a = base.name) != null ? _a : "object literal";
276
+ const operandObjectName = (_b = operand.name) != null ? _b : "object literal";
277
+ const newObject = __spreadProps$1(__spreadValues$1({}, base), {
278
+ name: `${baseObjectName} & ${operandObjectName}`,
279
+ description: `Effective type combining ${baseObjectName} and ${operandObjectName}`,
280
+ genericTokens: [
281
+ ...isGenericNodeType(base) ? base.genericTokens : [],
282
+ ...isGenericNodeType(operand) ? operand.genericTokens : []
283
+ ]
284
+ });
285
+ for (const property in operand.properties) {
286
+ if (newObject.properties[property] !== void 0 && newObject.properties[property].node.type !== operand.properties[property].node.type && errorOnOverlap) {
287
+ throw new Error(`Can't compute effective type for ${baseObjectName} and ${operandObjectName} because of conflicting properties ${property}`);
288
+ }
289
+ newObject.properties[property] = operand.properties[property];
290
+ }
291
+ if (newObject.additionalProperties && operand.additionalProperties) {
292
+ newObject.additionalProperties = {
293
+ type: "and",
294
+ and: [newObject.additionalProperties, operand.additionalProperties]
295
+ };
296
+ } else if (operand.additionalProperties) {
297
+ newObject.additionalProperties = operand.additionalProperties;
298
+ }
299
+ return newObject;
300
+ }
221
301
 
222
302
  var __defProp = Object.defineProperty;
223
303
  var __defProps = Object.defineProperties;
@@ -242,8 +322,8 @@ function tsStripOptionalType(node) {
242
322
  return ts.isOptionalTypeNode(node) ? node.type : node;
243
323
  }
244
324
  function isExportedDeclaration(node) {
245
- var _a;
246
- return !!((_a = node.modifiers) == null ? void 0 : _a.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
325
+ const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : void 0;
326
+ return modifiers && modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
247
327
  }
248
328
  function isNodeExported(node) {
249
329
  return (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 || !!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile;
@@ -431,43 +511,21 @@ function applyPartialOrRequiredToNodeType(baseObject, modifier) {
431
511
  throw new Error(`Error: Can not apply ${modifier ? "Required" : "Partial"} to type ${baseObject.type}`);
432
512
  }
433
513
 
434
- var __async = (__this, __arguments, generator) => {
435
- return new Promise((resolve, reject) => {
436
- var fulfilled = (value) => {
437
- try {
438
- step(generator.next(value));
439
- } catch (e) {
440
- reject(e);
441
- }
442
- };
443
- var rejected = (value) => {
444
- try {
445
- step(generator.throw(value));
446
- } catch (e) {
447
- reject(e);
448
- }
449
- };
450
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
451
- step((generator = generator.apply(__this, __arguments)).next());
452
- });
453
- };
454
514
  function setupTestEnv(sourceCode, mockFileName = "filename.ts") {
455
- return __async(this, null, function* () {
456
- const fsMap = yield tsvfs.createDefaultMapFromNodeModules({}, ts__default);
457
- fsMap.set(mockFileName, sourceCode);
458
- const system = tsvfs.createSystem(fsMap);
459
- const host = tsvfs.createVirtualCompilerHost(system, {}, ts__default);
460
- const program = ts__default.createProgram({
461
- rootNames: [...fsMap.keys()],
462
- options: {},
463
- host: host.compilerHost
464
- });
465
- return {
466
- sf: host.compilerHost.getSourceFile(mockFileName, ts__default.ScriptTarget.ES5),
467
- tc: program.getTypeChecker()
468
- };
515
+ const fsMap = tsvfs.createDefaultMapFromNodeModules({}, ts__default);
516
+ fsMap.set(mockFileName, sourceCode);
517
+ const system = tsvfs.createSystem(fsMap);
518
+ const host = tsvfs.createVirtualCompilerHost(system, {}, ts__default);
519
+ const program = ts__default.createProgram({
520
+ rootNames: [...fsMap.keys()],
521
+ options: {},
522
+ host: host.compilerHost
469
523
  });
524
+ return {
525
+ sf: host.compilerHost.getSourceFile(mockFileName, ts__default.ScriptTarget.ES5),
526
+ tc: program.getTypeChecker()
527
+ };
470
528
  }
471
529
 
472
- export { applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, setupTestEnv, tsStripOptionalType };
530
+ export { applyPartialOrRequiredToNodeType, applyPickOrOmitToNodeType, buildTemplateRegex, computeEffectiveObject, decorateNode, fillInGenerics, getReferencedType, getStringLiteralsFromUnion, isExportedDeclaration, isGenericInterfaceDeclaration, isGenericNamedType, isGenericNodeType, isGenericTypeDeclaration, isNode, isNodeExported, isNonNullable, isOptionalProperty, isPrimitiveTypeNode, isTopLevelNode, isTypeReferenceGeneric, makePropertyMap, propertyToTuple, resolveConditional, resolveReferenceNode, setupTestEnv, tsStripOptionalType };
473
531
  //# 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.2.1-next.3",
3
+ "version": "0.2.1",
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.2.1-next.3",
13
+ "@player-tools/xlr": "0.2.1",
14
14
  "@typescript/vfs": "^1.4.0",
15
15
  "@babel/runtime": "7.15.4"
16
16
  },
@@ -15,11 +15,8 @@ export interface SetupReturnType {
15
15
  /**
16
16
  * Setups a virtual TS environment for tests
17
17
  */
18
- export async function setupTestEnv(
19
- sourceCode: string,
20
- mockFileName = 'filename.ts'
21
- ) {
22
- const fsMap = await tsvfs.createDefaultMapFromNodeModules({}, ts);
18
+ export function setupTestEnv(sourceCode: string, mockFileName = 'filename.ts') {
19
+ const fsMap = tsvfs.createDefaultMapFromNodeModules({}, ts);
23
20
  fsMap.set(mockFileName, sourceCode);
24
21
 
25
22
  const system = tsvfs.createSystem(fsMap);
package/src/ts-helpers.ts CHANGED
@@ -20,8 +20,12 @@ export function tsStripOptionalType(node: ts.TypeNode): ts.TypeNode {
20
20
  * Returns if the top level declaration is exported
21
21
  */
22
22
  export function isExportedDeclaration(node: ts.Statement) {
23
- return !!node.modifiers?.some(
24
- (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword
23
+ const modifiers = ts.canHaveModifiers(node)
24
+ ? ts.getModifiers(node)
25
+ : undefined;
26
+ return (
27
+ modifiers &&
28
+ modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)
25
29
  );
26
30
  }
27
31
 
@@ -129,6 +133,7 @@ export function buildTemplateRegex(
129
133
 
130
134
  /**
131
135
  * Walks generics to fill in values from a combination of the default, constraint, and passed in map values
136
+ * TODO convert this to use simpleTransformGenerator
132
137
  */
133
138
  export function fillInGenerics(
134
139
  xlrNode: NodeType,
@@ -90,7 +90,6 @@ export function isPrimitiveTypeNode(node: NodeType): node is PrimitiveTypes {
90
90
  node.type === 'number' ||
91
91
  node.type === 'boolean' ||
92
92
  node.type === 'null' ||
93
- node.type === 'template' ||
94
93
  node.type === 'any' ||
95
94
  node.type === 'never' ||
96
95
  node.type === 'undefined' ||
@@ -1,6 +1,12 @@
1
1
  import type { Node } from 'jsonc-parser';
2
- import type { ConditionalType, NodeType } from '@player-tools/xlr';
3
- import { isPrimitiveTypeNode } from './type-checks';
2
+ import type {
3
+ ConditionalType,
4
+ NodeType,
5
+ ObjectType,
6
+ RefNode,
7
+ } from '@player-tools/xlr';
8
+ import { isGenericNodeType, isPrimitiveTypeNode } from './type-checks';
9
+ import { fillInGenerics } from './ts-helpers';
4
10
 
5
11
  export interface PropertyNode {
6
12
  /** Equivalent Property Name */
@@ -54,35 +60,143 @@ export function isNode(obj: Node | string | number | boolean): obj is Node {
54
60
  export function resolveConditional(conditional: ConditionalType): NodeType {
55
61
  const { left, right } = conditional.check;
56
62
  if (isPrimitiveTypeNode(left) && isPrimitiveTypeNode(right)) {
57
- if (left.const && right.const) {
58
- return left.const === right.const
59
- ? conditional.value.true
60
- : conditional.value.false;
61
- }
63
+ let conditionalResult = conditional.value.false;
62
64
 
63
- // special case for any/unknown being functionally the same
64
65
  if (
65
66
  (left.type === 'any' || left.type === 'unknown') &&
66
67
  (right.type === 'any' || right.type === 'unknown')
67
68
  ) {
68
- return conditional.value.true;
69
- }
70
-
71
- // special case for null/undefined being functionally the same
72
- if (
69
+ // special case for any/unknown being functionally the same
70
+ conditionalResult = conditional.value.true;
71
+ } else if (
73
72
  (left.type === 'null' || left.type === 'undefined') &&
74
73
  (right.type === 'null' || right.type === 'undefined')
75
74
  ) {
76
- return conditional.value.true;
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;
81
+ }
82
+ } else {
83
+ conditionalResult = conditional.value.true;
84
+ }
77
85
  }
78
86
 
79
- if (left.type === right.type) {
80
- return conditional.value.true;
87
+ // Compose first level generics here since `conditionalResult` won't have them
88
+ if (isGenericNodeType(conditional)) {
89
+ const genericMap: Map<string, NodeType> = new Map();
90
+ conditional.genericTokens.forEach((token) => {
91
+ genericMap.set(
92
+ token.symbol,
93
+ token.default ?? token.constraints ?? { type: 'any' }
94
+ );
95
+ });
96
+
97
+ return fillInGenerics(conditionalResult, genericMap);
81
98
  }
82
99
 
83
- return conditional.value.false;
100
+ return conditionalResult;
84
101
  }
85
102
 
86
103
  // unable to process return original
87
104
  return conditional;
88
105
  }
106
+
107
+ /**
108
+ *
109
+ */
110
+ export function resolveReferenceNode(
111
+ genericReference: RefNode,
112
+ typeToFill: NodeType
113
+ ): NodeType {
114
+ const genericArgs = genericReference.genericArguments;
115
+ const genericMap: Map<string, NodeType> = new Map();
116
+
117
+ // Compose first level generics here from `genericReference`
118
+ if (genericArgs && isGenericNodeType(typeToFill)) {
119
+ typeToFill.genericTokens.forEach((token, index) => {
120
+ genericMap.set(
121
+ token.symbol,
122
+ genericArgs[index] ?? token.default ?? token.constraints
123
+ );
124
+ });
125
+ }
126
+
127
+ // Fill in generics
128
+ const filledInNode = fillInGenerics(typeToFill, genericMap);
129
+
130
+ // Remove generic tokens that were resolve
131
+ if (isGenericNodeType(filledInNode) && genericArgs?.length) {
132
+ if (genericArgs.length < filledInNode.genericTokens.length) {
133
+ filledInNode.genericTokens = filledInNode.genericTokens.slice(
134
+ genericArgs?.length
135
+ );
136
+ } else if (genericArgs.length === filledInNode.genericTokens.length) {
137
+ filledInNode.genericTokens = [];
138
+ }
139
+ }
140
+
141
+ // Resolve index access
142
+ if (genericReference.property && filledInNode.type === 'object') {
143
+ return (
144
+ filledInNode.properties[genericReference.property]?.node ??
145
+ filledInNode.additionalProperties ?? { type: 'undefined' }
146
+ );
147
+ }
148
+
149
+ return filledInNode;
150
+ }
151
+
152
+ /**
153
+ * Combines two ObjectType objects to get a representation of the effective TypeScript interface of `base` extending `operand`
154
+ - * @param base The base interface
155
+ - * @param operand The interface that is extended
156
+ - * @param errorOnOverlap whether or not conflicting properties should throw an error or use the property from operand
157
+ - * @returns `ObjectType`
158
+ */
159
+ export function computeEffectiveObject(
160
+ base: ObjectType,
161
+ operand: ObjectType,
162
+ errorOnOverlap = true
163
+ ): ObjectType {
164
+ const baseObjectName = base.name ?? 'object literal';
165
+ const operandObjectName = operand.name ?? 'object literal';
166
+ const newObject = {
167
+ ...base,
168
+ name: `${baseObjectName} & ${operandObjectName}`,
169
+ description: `Effective type combining ${baseObjectName} and ${operandObjectName}`,
170
+ genericTokens: [
171
+ ...(isGenericNodeType(base) ? base.genericTokens : []),
172
+ ...(isGenericNodeType(operand) ? operand.genericTokens : []),
173
+ ],
174
+ };
175
+
176
+ // eslint-disable-next-line no-restricted-syntax, guard-for-in
177
+ for (const property in operand.properties) {
178
+ if (
179
+ newObject.properties[property] !== undefined &&
180
+ newObject.properties[property].node.type !==
181
+ operand.properties[property].node.type &&
182
+ errorOnOverlap
183
+ ) {
184
+ throw new Error(
185
+ `Can't compute effective type for ${baseObjectName} and ${operandObjectName} because of conflicting properties ${property}`
186
+ );
187
+ }
188
+
189
+ newObject.properties[property] = operand.properties[property];
190
+ }
191
+
192
+ if (newObject.additionalProperties && operand.additionalProperties) {
193
+ newObject.additionalProperties = {
194
+ type: 'and',
195
+ and: [newObject.additionalProperties, operand.additionalProperties],
196
+ };
197
+ } else if (operand.additionalProperties) {
198
+ newObject.additionalProperties = operand.additionalProperties;
199
+ }
200
+
201
+ return newObject;
202
+ }