@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 +121 -61
- package/dist/index.d.ts +18 -5
- package/dist/index.esm.js +120 -62
- package/package.json +2 -2
- package/src/test-helpers.ts +2 -5
- package/src/ts-helpers.ts +7 -2
- package/src/type-checks.ts +0 -1
- package/src/validation-helpers.ts +131 -17
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$
|
|
33
|
-
var __getOwnPropSymbols$
|
|
34
|
-
var __hasOwnProp$
|
|
35
|
-
var __propIsEnum$
|
|
36
|
-
var __defNormalProp$
|
|
37
|
-
var __spreadValues$
|
|
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$
|
|
40
|
-
__defNormalProp$
|
|
41
|
-
if (__getOwnPropSymbols$
|
|
42
|
-
for (var prop of __getOwnPropSymbols$
|
|
43
|
-
if (__propIsEnum$
|
|
44
|
-
__defNormalProp$
|
|
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$
|
|
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$
|
|
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 === "
|
|
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
|
-
|
|
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
|
-
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
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 (
|
|
242
|
-
|
|
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
|
|
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
|
-
|
|
273
|
-
return
|
|
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
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
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):
|
|
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$
|
|
6
|
-
var __getOwnPropSymbols$
|
|
7
|
-
var __hasOwnProp$
|
|
8
|
-
var __propIsEnum$
|
|
9
|
-
var __defNormalProp$
|
|
10
|
-
var __spreadValues$
|
|
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$
|
|
13
|
-
__defNormalProp$
|
|
14
|
-
if (__getOwnPropSymbols$
|
|
15
|
-
for (var prop of __getOwnPropSymbols$
|
|
16
|
-
if (__propIsEnum$
|
|
17
|
-
__defNormalProp$
|
|
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$
|
|
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$
|
|
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 === "
|
|
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
|
-
|
|
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
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
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 (
|
|
215
|
-
|
|
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
|
|
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
|
-
|
|
246
|
-
return
|
|
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
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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
|
|
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
|
|
13
|
+
"@player-tools/xlr": "0.2.1",
|
|
14
14
|
"@typescript/vfs": "^1.4.0",
|
|
15
15
|
"@babel/runtime": "7.15.4"
|
|
16
16
|
},
|
package/src/test-helpers.ts
CHANGED
|
@@ -15,11 +15,8 @@ export interface SetupReturnType {
|
|
|
15
15
|
/**
|
|
16
16
|
* Setups a virtual TS environment for tests
|
|
17
17
|
*/
|
|
18
|
-
export
|
|
19
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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,
|
package/src/type-checks.ts
CHANGED
|
@@ -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 {
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
|
|
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
|
|
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
|
+
}
|