@xlr-lib/xlr-utils 0.1.1-next.3 → 0.1.1-next.5

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.
@@ -1,4 +1,3 @@
1
- import ts from "typescript";
2
1
  import type {
3
2
  NamedType,
4
3
  NamedTypeWithGenerics,
@@ -16,77 +15,6 @@ import type {
16
15
  RecordType,
17
16
  } from "@xlr-lib/xlr";
18
17
 
19
- /**
20
- * Returns if the Object Property is optional
21
- */
22
- export function isOptionalProperty(node: ts.PropertySignature): boolean {
23
- return node.questionToken?.kind === ts.SyntaxKind.QuestionToken;
24
- }
25
-
26
- /**
27
- * Returns if the node is an Interface or Type with Generics
28
- */
29
- export function isGenericInterfaceDeclaration(
30
- node: ts.InterfaceDeclaration,
31
- ): boolean {
32
- const length = node.typeParameters?.length;
33
- return length ? length > 0 : false;
34
- }
35
-
36
- /**
37
- * Returns if the node is an Type Declaration with Generics
38
- */
39
- export function isGenericTypeDeclaration(
40
- node: ts.TypeAliasDeclaration,
41
- ): boolean {
42
- const length = node.typeParameters?.length;
43
- return length ? length > 0 : false;
44
- }
45
-
46
- /**
47
- * Returns if the referenced type is a generic
48
- */
49
- export function isTypeReferenceGeneric(
50
- node: ts.TypeReferenceNode,
51
- typeChecker: ts.TypeChecker,
52
- ): boolean {
53
- const symbol = typeChecker.getSymbolAtLocation(node.typeName);
54
- if (symbol && symbol.declarations) {
55
- return symbol.declarations[0].kind === ts.SyntaxKind.TypeParameter;
56
- }
57
-
58
- return false;
59
- }
60
-
61
- export type TopLevelDeclaration =
62
- | ts.InterfaceDeclaration
63
- | ts.TypeAliasDeclaration;
64
-
65
- /**
66
- * Returns if the node is an interface or a type declaration
67
- */
68
- export function isTopLevelDeclaration(
69
- node: ts.Node,
70
- ): node is TopLevelDeclaration {
71
- return (
72
- node.kind === ts.SyntaxKind.InterfaceDeclaration ||
73
- node.kind === ts.SyntaxKind.TypeAliasDeclaration
74
- );
75
- }
76
-
77
- export type TopLevelNode = TopLevelDeclaration | ts.VariableStatement;
78
-
79
- /**
80
- * Returns if the node is an interface or a type declaration
81
- */
82
- export function isTopLevelNode(node: ts.Node): node is TopLevelNode {
83
- return (
84
- node.kind === ts.SyntaxKind.InterfaceDeclaration ||
85
- node.kind === ts.SyntaxKind.TypeAliasDeclaration ||
86
- node.kind === ts.SyntaxKind.VariableStatement
87
- );
88
- }
89
-
90
18
  /**
91
19
  * Returns if the NodeType has generic tokens
92
20
  */
@@ -6,7 +6,7 @@ import type {
6
6
  RefNode,
7
7
  } from "@xlr-lib/xlr";
8
8
  import { isGenericNodeType, isPrimitiveTypeNode } from "./type-checks";
9
- import { fillInGenerics } from "./ts-helpers";
9
+ import { fillInGenerics } from "./xlr-helpers";
10
10
 
11
11
  export interface PropertyNode {
12
12
  /** Equivalent Property Name */
@@ -1,4 +1,3 @@
1
- import ts from "typescript";
2
1
  import type {
3
2
  NamedType,
4
3
  NodeType,
@@ -10,181 +9,6 @@ import type {
10
9
  import { computeExtends, resolveConditional } from "./validation-helpers";
11
10
  import { isGenericNamedType, isGenericNodeType } from "./type-checks";
12
11
 
13
- /**
14
- * Returns the required type or the optionally required type
15
- */
16
- export function tsStripOptionalType(node: ts.TypeNode): ts.TypeNode {
17
- return ts.isOptionalTypeNode(node) ? node.type : node;
18
- }
19
-
20
- /**
21
- * Returns if the top level declaration is exported
22
- */
23
- export function isExportedDeclaration(node: ts.Statement): boolean {
24
- const modifiers = ts.canHaveModifiers(node)
25
- ? ts.getModifiers(node)
26
- : undefined;
27
-
28
- if (modifiers) {
29
- return modifiers.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
30
- }
31
- return false;
32
- }
33
-
34
- /**
35
- * Returns if the top level declaration is exported
36
- */
37
- export function isExportedModuleDeclaration(
38
- node: ts.Statement,
39
- ): node is ts.ModuleDeclaration {
40
- return isExportedDeclaration(node) && ts.isModuleDeclaration(node);
41
- }
42
-
43
- /**
44
- * Returns if the node is exported from the source file
45
- */
46
- export function isNodeExported(node: ts.Node): boolean {
47
- return (
48
- (ts.getCombinedModifierFlags(node as ts.Declaration) &
49
- ts.ModifierFlags.Export) !==
50
- 0 ||
51
- (!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile)
52
- );
53
- }
54
-
55
- /**
56
- * Returns the actual type and will following import chains if needed
57
- */
58
- export function getReferencedType(
59
- node: ts.TypeReferenceNode,
60
- typeChecker: ts.TypeChecker,
61
- ):
62
- | {
63
- declaration: ts.InterfaceDeclaration | ts.TypeAliasDeclaration;
64
- exported: boolean;
65
- }
66
- | undefined {
67
- let symbol = typeChecker.getSymbolAtLocation(node.typeName);
68
-
69
- if (
70
- symbol &&
71
- (symbol.flags & ts.SymbolFlags.Alias) === ts.SymbolFlags.Alias
72
- ) {
73
- // follow alias if it is a symbol
74
- symbol = typeChecker.getAliasedSymbol(symbol);
75
- }
76
-
77
- const varDecl = symbol?.declarations?.[0];
78
- if (
79
- varDecl &&
80
- (ts.isInterfaceDeclaration(varDecl) || ts.isTypeAliasDeclaration(varDecl))
81
- ) {
82
- return { declaration: varDecl, exported: isNodeExported(varDecl) };
83
- }
84
- }
85
-
86
- /**
87
- * Checks if a type reference points to a TypeScript built-in type
88
- * by examining whether its declaration comes from TypeScript's lib files.
89
- *
90
- * This is more robust than maintaining a hardcoded list of built-in types
91
- * as it automatically handles all TypeScript lib types (Map, Set, WeakMap,
92
- * Promise, Array, Date, Error, RegExp, etc.).
93
- */
94
- export function isTypeScriptLibType(
95
- node: ts.TypeReferenceNode,
96
- typeChecker: ts.TypeChecker,
97
- ): boolean {
98
- let symbol = typeChecker.getSymbolAtLocation(node.typeName);
99
-
100
- if (!symbol) return false;
101
-
102
- // Follow alias if it is a symbol
103
- if ((symbol.flags & ts.SymbolFlags.Alias) === ts.SymbolFlags.Alias) {
104
- symbol = typeChecker.getAliasedSymbol(symbol);
105
- }
106
-
107
- const declarations = symbol.getDeclarations();
108
- if (!declarations || declarations.length === 0) return false;
109
-
110
- // Check if any declaration comes from TypeScript lib files
111
- return declarations.some((decl) => {
112
- const sourceFile = decl.getSourceFile();
113
- if (!sourceFile) return false;
114
-
115
- const filePath = sourceFile.fileName;
116
- return (
117
- filePath.includes("/typescript/lib/") ||
118
- filePath.includes("\\typescript\\lib\\") ||
119
- (filePath.endsWith(".d.ts") && filePath.includes("lib."))
120
- );
121
- });
122
- }
123
-
124
- /**
125
- * Returns list of string literals from potential union of strings
126
- */
127
- export function getStringLiteralsFromUnion(node: ts.Node): Set<string> {
128
- if (ts.isUnionTypeNode(node)) {
129
- return new Set(
130
- node.types.map((type) => {
131
- if (ts.isLiteralTypeNode(type) && ts.isStringLiteral(type.literal)) {
132
- return type.literal.text;
133
- }
134
-
135
- return "";
136
- }),
137
- );
138
- }
139
-
140
- if (ts.isLiteralTypeNode(node) && ts.isStringLiteral(node.literal)) {
141
- return new Set([node.literal.text]);
142
- }
143
-
144
- return new Set();
145
- }
146
-
147
- /**
148
- * Converts a format string into a regex that can be used to validate a given string matches the template
149
- */
150
- export function buildTemplateRegex(
151
- node: ts.TemplateLiteralTypeNode,
152
- typeChecker: ts.TypeChecker,
153
- ): string {
154
- let regex = node.head.text;
155
- node.templateSpans.forEach((span) => {
156
- // process template tag
157
- let type = span.type.kind;
158
- if (ts.isTypeReferenceNode(span.type)) {
159
- let symbol = typeChecker.getSymbolAtLocation(
160
- span.type.typeName,
161
- ) as ts.Symbol;
162
-
163
- if (
164
- symbol &&
165
- (symbol.flags & ts.SymbolFlags.Alias) === ts.SymbolFlags.Alias
166
- ) {
167
- // follow alias if it is a symbol
168
- symbol = typeChecker.getAliasedSymbol(symbol);
169
- }
170
-
171
- type = (symbol?.declarations?.[0] as ts.TypeAliasDeclaration).type.kind;
172
- }
173
-
174
- if (type === ts.SyntaxKind.StringKeyword) {
175
- regex += ".*";
176
- } else if (type === ts.SyntaxKind.NumberKeyword) {
177
- regex += "[0-9]*";
178
- } else if (type === ts.SyntaxKind.BooleanKeyword) {
179
- regex += "true|false";
180
- }
181
-
182
- // add non-tag element
183
- regex += span.literal.text;
184
- });
185
- return regex;
186
- }
187
-
188
12
  /**
189
13
  * Walks generics to fill in values from a combination of the default, constraint, and passed in map values
190
14
  * TODO convert this to use simpleTransformGenerator
package/types/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- export * from "./annotations";
2
- export * from "./ts-helpers";
1
+ export * from "./xlr-helpers";
3
2
  export * from "./type-checks";
4
3
  export * from "./validation-helpers";
5
- export * from "./documentation";
6
4
  //# sourceMappingURL=index.d.ts.map
@@ -1,31 +1,4 @@
1
- import ts from "typescript";
2
1
  import type { NamedType, NamedTypeWithGenerics, NodeType, NodeTypeWithGenerics, PrimitiveTypes, StringType, NumberType, BooleanType, ObjectType, ArrayType, RefType, OrType, AndType, RecordType } from "@xlr-lib/xlr";
3
- /**
4
- * Returns if the Object Property is optional
5
- */
6
- export declare function isOptionalProperty(node: ts.PropertySignature): boolean;
7
- /**
8
- * Returns if the node is an Interface or Type with Generics
9
- */
10
- export declare function isGenericInterfaceDeclaration(node: ts.InterfaceDeclaration): boolean;
11
- /**
12
- * Returns if the node is an Type Declaration with Generics
13
- */
14
- export declare function isGenericTypeDeclaration(node: ts.TypeAliasDeclaration): boolean;
15
- /**
16
- * Returns if the referenced type is a generic
17
- */
18
- export declare function isTypeReferenceGeneric(node: ts.TypeReferenceNode, typeChecker: ts.TypeChecker): boolean;
19
- export type TopLevelDeclaration = ts.InterfaceDeclaration | ts.TypeAliasDeclaration;
20
- /**
21
- * Returns if the node is an interface or a type declaration
22
- */
23
- export declare function isTopLevelDeclaration(node: ts.Node): node is TopLevelDeclaration;
24
- export type TopLevelNode = TopLevelDeclaration | ts.VariableStatement;
25
- /**
26
- * Returns if the node is an interface or a type declaration
27
- */
28
- export declare function isTopLevelNode(node: ts.Node): node is TopLevelNode;
29
2
  /**
30
3
  * Returns if the NodeType has generic tokens
31
4
  */
@@ -0,0 +1,13 @@
1
+ import type { NodeType, OrType } from "@xlr-lib/xlr";
2
+ /**
3
+ * Walks generics to fill in values from a combination of the default, constraint, and passed in map values
4
+ * TODO convert this to use simpleTransformGenerator
5
+ */
6
+ export declare function fillInGenerics(xlrNode: NodeType, generics?: Map<string, NodeType>, preferLocalGenerics?: boolean): NodeType;
7
+ /** Applies the TS `Pick` or `Omit` type to an interface/union/intersection */
8
+ export declare function applyPickOrOmitToNodeType(baseObject: NodeType, operation: "Pick" | "Omit", properties: Set<string>): NodeType | undefined;
9
+ /** Applies the TS `Partial` or `Required` type to an interface/union/intersection */
10
+ export declare function applyPartialOrRequiredToNodeType(baseObject: NodeType, modifier: boolean): NodeType;
11
+ /** Applies the TS `Exclude` type to a union */
12
+ export declare function applyExcludeToNodeType(baseObject: OrType, filters: NodeType | OrType): NodeType;
13
+ //# sourceMappingURL=xlr-helpers.d.ts.map
@@ -1,40 +0,0 @@
1
- import { test, expect, describe } from "vitest";
2
- import { setupTestEnv } from "@xlr-lib/test-utils";
3
- import { decorateNode } from "../annotations";
4
-
5
- describe("Annotations", () => {
6
- test("JSDoc comments to strings", () => {
7
- const sc = `
8
- /**
9
- * An asset is the smallest unit of user interaction in a player view
10
- * @example Example usage of interface Asset
11
- * @see Asset for implementation details
12
- * @default default value
13
- */
14
- export interface Asset<T extends string = string> {
15
- id: string;
16
- [key: string]: unknown;
17
- }
18
- `;
19
-
20
- const { sf } = setupTestEnv(sc);
21
- expect(decorateNode(sf.statements[0])).toMatchSnapshot();
22
- });
23
-
24
- test("JSDoc @meta", () => {
25
- const sc = `
26
- /**
27
- * An asset is the smallest unit of user interaction in a player view
28
- * @meta category:views
29
- * @meta screenshot:/path/image.png
30
- */
31
- export interface Asset<T extends string = string> {
32
- id: string;
33
- [key: string]: unknown;
34
- }
35
- `;
36
-
37
- const { sf } = setupTestEnv(sc);
38
- expect(decorateNode(sf.statements[0])).toMatchSnapshot();
39
- });
40
- });
@@ -1,116 +0,0 @@
1
- import { test, expect, describe } from "vitest";
2
- import type { FunctionType, OrType, TupleType } from "@xlr-lib/xlr";
3
- import { createDocString } from "../documentation";
4
-
5
- describe("docs", () => {
6
- test("or", () => {
7
- const type1: OrType = {
8
- type: "or",
9
- or: [
10
- {
11
- type: "string",
12
- },
13
- {
14
- type: "array",
15
- elementType: {
16
- type: "string",
17
- },
18
- },
19
- ],
20
- };
21
-
22
- expect(createDocString(type1)).toMatchInlineSnapshot(
23
- `"string | Array<string>"`,
24
- );
25
- });
26
-
27
- test("function", () => {
28
- const type1: FunctionType = {
29
- type: "function",
30
- name: "testABC",
31
- parameters: [
32
- {
33
- name: "a",
34
- type: {
35
- type: "string",
36
- },
37
- },
38
- {
39
- name: "b",
40
- type: {
41
- type: "array",
42
- elementType: {
43
- type: "string",
44
- },
45
- },
46
- },
47
- ],
48
- returnType: {
49
- type: "string",
50
- },
51
- };
52
-
53
- expect(createDocString(type1)).toMatchInlineSnapshot(
54
- `"function testABC(a: string, b: Array<string>): string"`,
55
- );
56
- });
57
-
58
- test("tuple", () => {
59
- const type1: TupleType = {
60
- type: "tuple",
61
- name: "testABC",
62
- elementTypes: [
63
- {
64
- name: "a",
65
- type: {
66
- type: "string",
67
- },
68
- },
69
- {
70
- type: {
71
- type: "array",
72
- elementType: {
73
- type: "string",
74
- },
75
- },
76
- },
77
- ],
78
- minItems: 2,
79
- additionalItems: false,
80
- };
81
-
82
- expect(createDocString(type1)).toMatchInlineSnapshot(
83
- `"[a: string, Array<string>]"`,
84
- );
85
- });
86
-
87
- test("const", () => {
88
- const type1: OrType = {
89
- type: "or",
90
- or: [
91
- {
92
- type: "string",
93
- const: "abc",
94
- },
95
- {
96
- type: "number",
97
- const: 123,
98
- },
99
- {
100
- type: "boolean",
101
- const: true,
102
- },
103
- {
104
- type: "array",
105
- elementType: {
106
- type: "string",
107
- },
108
- },
109
- ],
110
- };
111
-
112
- expect(createDocString(type1)).toMatchInlineSnapshot(
113
- `""abc" | 123 | true | Array<string>"`,
114
- );
115
- });
116
- });
@@ -1,39 +0,0 @@
1
- import * as ts from "typescript";
2
- import { isOptionalProperty } from "../type-checks";
3
- import { describe, test, expect } from "vitest";
4
-
5
- describe("isOptionalProperty", () => {
6
- test("should return true for an optional property", () => {
7
- const source = ts.createSourceFile(
8
- "test.ts",
9
- `
10
- interface Test {
11
- prop?: string;
12
- }
13
- `,
14
- ts.ScriptTarget.Latest,
15
- true,
16
- );
17
- const node = source.statements[0] as ts.InterfaceDeclaration;
18
- const prop = node.members[0] as ts.PropertySignature;
19
-
20
- expect(isOptionalProperty(prop)).toBe(true);
21
- });
22
-
23
- test("should return false for a non-optional property", () => {
24
- const source = ts.createSourceFile(
25
- "test.ts",
26
- `
27
- interface Test {
28
- prop: string;
29
- }
30
- `,
31
- ts.ScriptTarget.Latest,
32
- true,
33
- );
34
- const node = source.statements[0] as ts.InterfaceDeclaration;
35
- const prop = node.members[0] as ts.PropertySignature;
36
-
37
- expect(isOptionalProperty(prop)).toBe(false);
38
- });
39
- });