@appweaver/client 1.3.0 → 1.4.0
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/cjs/clients/modules/resource-client.d.ts +12 -11
- package/cjs/clients/modules/resource-client.js +6 -6
- package/cjs/commands/generate-command.js +3 -1
- package/cjs/constants.d.ts +9 -0
- package/cjs/constants.js +28 -1
- package/cjs/generators/generate-types.d.ts +3 -1
- package/cjs/generators/generate-types.js +99 -9
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +1 -0
- package/cjs/types/generator.d.ts +6 -0
- package/cjs/types/generator.js +2 -0
- package/cjs/types/index.d.ts +2 -0
- package/cjs/types/index.js +2 -0
- package/cjs/types/resource.d.ts +2 -0
- package/cjs/types/resource.js +2 -0
- package/cjs/utils/enum-util.d.ts +17 -17
- package/cjs/utils/enum-util.js +50 -170
- package/cjs/utils/hoist-util.d.ts +29 -0
- package/cjs/utils/hoist-util.js +338 -0
- package/cjs/utils/index.d.ts +1 -0
- package/cjs/utils/index.js +1 -0
- package/esm/clients/modules/resource-client.d.ts +12 -11
- package/esm/clients/modules/resource-client.js +6 -6
- package/esm/commands/generate-command.js +3 -1
- package/esm/constants.d.ts +9 -0
- package/esm/constants.js +27 -0
- package/esm/generators/generate-types.d.ts +3 -1
- package/esm/generators/generate-types.js +100 -10
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/types/generator.d.ts +6 -0
- package/esm/types/generator.js +1 -0
- package/esm/types/index.d.ts +2 -0
- package/esm/types/index.js +2 -0
- package/esm/types/resource.d.ts +2 -0
- package/esm/types/resource.js +1 -0
- package/esm/utils/enum-util.d.ts +17 -17
- package/esm/utils/enum-util.js +49 -169
- package/esm/utils/hoist-util.d.ts +29 -0
- package/esm/utils/hoist-util.js +335 -0
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.js +1 -0
- package/package.json +3 -2
|
@@ -2,6 +2,7 @@ import { BaseModule, RequestOptions } from './base-module';
|
|
|
2
2
|
import { BaseClientInterface } from '../base-client-interface';
|
|
3
3
|
import { FileDataResponse } from '../responses';
|
|
4
4
|
import { RESOURCE_OPERATIONS, RESOURCE_TYPES } from '../../constants';
|
|
5
|
+
import { ResourceId } from '../../types';
|
|
5
6
|
export type ResourceType = Record<(typeof RESOURCE_TYPES)[number], unknown>;
|
|
6
7
|
export type ResourceInterface = {
|
|
7
8
|
[K in keyof typeof RESOURCE_OPERATIONS]: (...args: any[]) => Promise<any>;
|
|
@@ -10,13 +11,13 @@ export declare class ResourceClient<Resource extends ResourceType> extends BaseM
|
|
|
10
11
|
readonly basePath: string;
|
|
11
12
|
constructor(client: BaseClientInterface, basePath: string);
|
|
12
13
|
/**
|
|
13
|
-
* Fetches a single resource by its
|
|
14
|
+
* Fetches a single resource by its ID.
|
|
14
15
|
*
|
|
15
|
-
* @param {
|
|
16
|
+
* @param {ResourceId} id - The ID of the resource to retrieve.
|
|
16
17
|
* @param {RequestOptions} options - Additional request options (headers, query params, etc.).
|
|
17
18
|
* @returns The resource record matching the given ID.
|
|
18
19
|
*/
|
|
19
|
-
find(id:
|
|
20
|
+
find(id: ResourceId, options?: RequestOptions): Promise<Resource['single']>;
|
|
20
21
|
/**
|
|
21
22
|
* Executes a query against the resource collection.
|
|
22
23
|
*
|
|
@@ -49,16 +50,16 @@ export declare class ResourceClient<Resource extends ResourceType> extends BaseM
|
|
|
49
50
|
* @returns The updated resource record.
|
|
50
51
|
*/
|
|
51
52
|
update(resource: Resource['update'] & {
|
|
52
|
-
id:
|
|
53
|
+
id: ResourceId;
|
|
53
54
|
}, options?: RequestOptions): Promise<Resource['single']>;
|
|
54
55
|
/**
|
|
55
|
-
* Deletes a resource record by its
|
|
56
|
+
* Deletes a resource record by its ID.
|
|
56
57
|
*
|
|
57
|
-
* @param {
|
|
58
|
+
* @param {ResourceId} id - The ID of the resource to delete.
|
|
58
59
|
* @param {RequestOptions} options - Additional request options.
|
|
59
60
|
* @returns The deleted resource record.
|
|
60
61
|
*/
|
|
61
|
-
delete(id:
|
|
62
|
+
delete(id: ResourceId, options?: RequestOptions): Promise<Resource['single']>;
|
|
62
63
|
/**
|
|
63
64
|
* Exports resource records as a file (e.g., CSV) and returns a streaming response.
|
|
64
65
|
*
|
|
@@ -72,19 +73,19 @@ export declare class ResourceClient<Resource extends ResourceType> extends BaseM
|
|
|
72
73
|
*
|
|
73
74
|
* Each entry in `files` maps a field name to a single `File` or an array of `File` objects.
|
|
74
75
|
*
|
|
75
|
-
* @param {
|
|
76
|
+
* @param {ResourceId} id - The ID of the resource for which to upload files.
|
|
76
77
|
* @param {Object} files - A map of field names to the file(s) to upload.
|
|
77
78
|
* @param {RequestOptions} options - Additional request options.
|
|
78
79
|
* @returns The updated file metadata for the resource.
|
|
79
80
|
*/
|
|
80
|
-
uploadFiles(id:
|
|
81
|
+
uploadFiles(id: ResourceId, files: Resource['fileUpload'], options?: RequestOptions): Promise<Resource['files']>;
|
|
81
82
|
/**
|
|
82
83
|
* Removes specific files from the resource record.
|
|
83
84
|
*
|
|
84
|
-
* @param {
|
|
85
|
+
* @param {ResourceId} id - The ID of the resource for which to delete files.
|
|
85
86
|
* @param {Object} files - The file deletion payload identifying which files to remove.
|
|
86
87
|
* @param {RequestOptions} options - Additional request options.
|
|
87
88
|
* @returns The updated file metadata for the resource after deletion.
|
|
88
89
|
*/
|
|
89
|
-
deleteFiles(id:
|
|
90
|
+
deleteFiles(id: ResourceId, files: Resource['fileDelete'], options?: RequestOptions): Promise<Resource['files']>;
|
|
90
91
|
}
|
|
@@ -9,9 +9,9 @@ class ResourceClient extends base_module_1.BaseModule {
|
|
|
9
9
|
this.basePath = basePath;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* Fetches a single resource by its
|
|
12
|
+
* Fetches a single resource by its ID.
|
|
13
13
|
*
|
|
14
|
-
* @param {
|
|
14
|
+
* @param {ResourceId} id - The ID of the resource to retrieve.
|
|
15
15
|
* @param {RequestOptions} options - Additional request options (headers, query params, etc.).
|
|
16
16
|
* @returns The resource record matching the given ID.
|
|
17
17
|
*/
|
|
@@ -85,9 +85,9 @@ class ResourceClient extends base_module_1.BaseModule {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
|
-
* Deletes a resource record by its
|
|
88
|
+
* Deletes a resource record by its ID.
|
|
89
89
|
*
|
|
90
|
-
* @param {
|
|
90
|
+
* @param {ResourceId} id - The ID of the resource to delete.
|
|
91
91
|
* @param {RequestOptions} options - Additional request options.
|
|
92
92
|
* @returns The deleted resource record.
|
|
93
93
|
*/
|
|
@@ -125,7 +125,7 @@ class ResourceClient extends base_module_1.BaseModule {
|
|
|
125
125
|
*
|
|
126
126
|
* Each entry in `files` maps a field name to a single `File` or an array of `File` objects.
|
|
127
127
|
*
|
|
128
|
-
* @param {
|
|
128
|
+
* @param {ResourceId} id - The ID of the resource for which to upload files.
|
|
129
129
|
* @param {Object} files - A map of field names to the file(s) to upload.
|
|
130
130
|
* @param {RequestOptions} options - Additional request options.
|
|
131
131
|
* @returns The updated file metadata for the resource.
|
|
@@ -156,7 +156,7 @@ class ResourceClient extends base_module_1.BaseModule {
|
|
|
156
156
|
/**
|
|
157
157
|
* Removes specific files from the resource record.
|
|
158
158
|
*
|
|
159
|
-
* @param {
|
|
159
|
+
* @param {ResourceId} id - The ID of the resource for which to delete files.
|
|
160
160
|
* @param {Object} files - The file deletion payload identifying which files to remove.
|
|
161
161
|
* @param {RequestOptions} options - Additional request options.
|
|
162
162
|
* @returns The updated file metadata for the resource after deletion.
|
|
@@ -41,7 +41,9 @@ function generateCommand(program) {
|
|
|
41
41
|
const schemaContent = await (0, utils_1.readSchemaContent)(schemaPath);
|
|
42
42
|
const schemaObject = await (0, utils_1.toSchemaObject)(schemaContent);
|
|
43
43
|
if (!clientOnly && !noTypes) {
|
|
44
|
-
const typesContent = await (0, generators_1.generateTypes)(schemaObject
|
|
44
|
+
const typesContent = await (0, generators_1.generateTypes)(schemaObject, {
|
|
45
|
+
declaration: typesPath.endsWith('.d.ts')
|
|
46
|
+
});
|
|
45
47
|
await formatAndWriteFile(typesPath, typesContent, typesOnly || typesPath !== clientPath);
|
|
46
48
|
console.log(`Generated types to ${node_path_1.default.relative(cwd, typesPath)}`);
|
|
47
49
|
}
|
package/cjs/constants.d.ts
CHANGED
|
@@ -8,6 +8,15 @@ export declare const CONFIG_RESOURCE_FIELD = "x-appweaver-resource";
|
|
|
8
8
|
* The key is the enum values joined by a `|`; the value is the name of the shared type generated
|
|
9
9
|
* for them. Enums that are not listed here are named after the definitions declaring them. */
|
|
10
10
|
export declare const SHARED_ENUM_NAMES: Record<string, string>;
|
|
11
|
+
/** Shapes an Appweaver schema repeats inline across its definitions, and the name of the shared
|
|
12
|
+
* definition each of them is hoisted into. A `$ref` names the title of the definition it points
|
|
13
|
+
* to, since the keys the definitions are generated under vary per document. The shapes are
|
|
14
|
+
* matched in the order they are declared, so an outer shape is hoisted before the shapes nested
|
|
15
|
+
* inside it (i.e. `QueryFilterValue` before the `QueryFilterScalar` it is built from). */
|
|
16
|
+
export declare const SHARED_SCHEMA_SHAPES: {
|
|
17
|
+
name: string;
|
|
18
|
+
schema: unknown;
|
|
19
|
+
}[];
|
|
11
20
|
/** Suffix used when generating the TypeScript module type name for a resource. */
|
|
12
21
|
export declare const RESOURCE_MODULE_TYPE = "ResourceModuleType";
|
|
13
22
|
/** Maps CRUD operation names to HTTP methods used for matching OpenAPI paths to `ResourceClient` methods. */
|
package/cjs/constants.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// They are typically only modified when changes occur in other Appweaver packages
|
|
4
4
|
// (such as core and common) to reflect new route paths or methods.
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.FILE_OPERATIONS = exports.HEALTH_TYPES = exports.HEALTH_OPERATIONS = exports.HEALTH_MODULE_TYPE = exports.ACCOUNT_TYPES = exports.ACCOUNT_OPERATIONS = exports.ACCOUNT_MODULE_TYPE = exports.AUTH_TYPES = exports.AUTH_OPERATIONS = exports.AUTH_MODULE_TYPE = exports.RESOURCE_TYPES = exports.RESOURCE_OPERATIONS = exports.RESOURCE_MODULE_TYPE = exports.SHARED_ENUM_NAMES = exports.CONFIG_RESOURCE_FIELD = exports.CONFIG_FIELD = exports.FRAMEWORKS = void 0;
|
|
6
|
+
exports.FILE_OPERATIONS = exports.HEALTH_TYPES = exports.HEALTH_OPERATIONS = exports.HEALTH_MODULE_TYPE = exports.ACCOUNT_TYPES = exports.ACCOUNT_OPERATIONS = exports.ACCOUNT_MODULE_TYPE = exports.AUTH_TYPES = exports.AUTH_OPERATIONS = exports.AUTH_MODULE_TYPE = exports.RESOURCE_TYPES = exports.RESOURCE_OPERATIONS = exports.RESOURCE_MODULE_TYPE = exports.SHARED_SCHEMA_SHAPES = exports.SHARED_ENUM_NAMES = exports.CONFIG_RESOURCE_FIELD = exports.CONFIG_FIELD = exports.FRAMEWORKS = void 0;
|
|
7
7
|
/** Supported frameworks for generating the client class. */
|
|
8
8
|
exports.FRAMEWORKS = ['fetch', 'angular'];
|
|
9
9
|
/** Custom OpenAPI extension key used for extracting route prefixes and base paths to their resources. */
|
|
@@ -16,6 +16,33 @@ exports.CONFIG_RESOURCE_FIELD = 'x-appweaver-resource';
|
|
|
16
16
|
exports.SHARED_ENUM_NAMES = {
|
|
17
17
|
'asc|desc': 'SortDirection'
|
|
18
18
|
};
|
|
19
|
+
/** The primitive types a plain filter value takes, as an Appweaver schema declares them. */
|
|
20
|
+
const FILTER_SCALAR = {
|
|
21
|
+
anyOf: [
|
|
22
|
+
{ type: 'string' },
|
|
23
|
+
{ type: 'number' },
|
|
24
|
+
{ type: 'boolean' },
|
|
25
|
+
{ type: 'null' }
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
/** Shapes an Appweaver schema repeats inline across its definitions, and the name of the shared
|
|
29
|
+
* definition each of them is hoisted into. A `$ref` names the title of the definition it points
|
|
30
|
+
* to, since the keys the definitions are generated under vary per document. The shapes are
|
|
31
|
+
* matched in the order they are declared, so an outer shape is hoisted before the shapes nested
|
|
32
|
+
* inside it (i.e. `QueryFilterValue` before the `QueryFilterScalar` it is built from). */
|
|
33
|
+
exports.SHARED_SCHEMA_SHAPES = [
|
|
34
|
+
{
|
|
35
|
+
name: 'QueryFilterValue',
|
|
36
|
+
schema: {
|
|
37
|
+
anyOf: [
|
|
38
|
+
FILTER_SCALAR,
|
|
39
|
+
{ type: 'array', items: FILTER_SCALAR },
|
|
40
|
+
{ $ref: 'QueryCondition' }
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{ name: 'QueryFilterScalar', schema: FILTER_SCALAR }
|
|
45
|
+
];
|
|
19
46
|
/** Suffix used when generating the TypeScript module type name for a resource. */
|
|
20
47
|
exports.RESOURCE_MODULE_TYPE = 'ResourceModuleType';
|
|
21
48
|
/** Maps CRUD operation names to HTTP methods used for matching OpenAPI paths to `ResourceClient` methods. */
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { OpenAPI3 } from 'openapi-typescript';
|
|
2
|
+
import { GenerateTypesOptions } from '../types';
|
|
2
3
|
/**
|
|
3
4
|
* Generates TypeScript types based on an OpenAPI V3 schema content.
|
|
4
5
|
*
|
|
5
6
|
* @param {string | OpenAPI3} schema - The OpenAPI V3 schema to generate types from. The value can be a string
|
|
6
7
|
* representing JSON or YAML format, or an already parsed OpenAPI3 object.
|
|
8
|
+
* @param {GenerateTypesOptions} [options] - Options controlling how the types are emitted.
|
|
7
9
|
* @return {Promise<string>} A promise that resolves to a string containing the generated TypeScript types.
|
|
8
10
|
*/
|
|
9
|
-
export declare function generateTypes(schema: string | OpenAPI3): Promise<string>;
|
|
11
|
+
export declare function generateTypes(schema: string | OpenAPI3, options?: GenerateTypesOptions): Promise<string>;
|
|
@@ -46,15 +46,16 @@ const constants_1 = require("../constants");
|
|
|
46
46
|
*
|
|
47
47
|
* @param {string | OpenAPI3} schema - The OpenAPI V3 schema to generate types from. The value can be a string
|
|
48
48
|
* representing JSON or YAML format, or an already parsed OpenAPI3 object.
|
|
49
|
+
* @param {GenerateTypesOptions} [options] - Options controlling how the types are emitted.
|
|
49
50
|
* @return {Promise<string>} A promise that resolves to a string containing the generated TypeScript types.
|
|
50
51
|
*/
|
|
51
|
-
async function generateTypes(schema) {
|
|
52
|
-
// The schema is copied before the shared
|
|
53
|
-
// caller keeps the schema it passed in unchanged
|
|
52
|
+
async function generateTypes(schema, options = {}) {
|
|
53
|
+
// The schema is copied before the shared definitions are hoisted into it, so
|
|
54
|
+
// the caller keeps the schema it passed in unchanged
|
|
54
55
|
const schemaObject = typeof schema === 'string'
|
|
55
56
|
? await (0, utils_1.toSchemaObject)(schema)
|
|
56
57
|
: structuredClone(schema);
|
|
57
|
-
const
|
|
58
|
+
const sharedTypes = (0, utils_1.hoistSharedTypes)(schemaObject);
|
|
58
59
|
const ast = await (0, openapi_typescript_1.default)(schemaObject, {
|
|
59
60
|
exportType: true,
|
|
60
61
|
emptyObjectsUnknown: true,
|
|
@@ -91,10 +92,11 @@ async function generateTypes(schema) {
|
|
|
91
92
|
}
|
|
92
93
|
});
|
|
93
94
|
let typesContent = (0, openapi_typescript_1.astToString)(deduplicateUnionConstituents(ast));
|
|
94
|
-
typesContent = extractSchemaTypes(typesContent,
|
|
95
|
+
typesContent = extractSchemaTypes(typesContent, sharedTypes);
|
|
95
96
|
typesContent = combineModuleTypes(typesContent, schemaObject);
|
|
96
97
|
typesContent = deduplicateExportedTypes(typesContent);
|
|
97
|
-
|
|
98
|
+
typesContent = replaceFileUploadTypes(typesContent);
|
|
99
|
+
return (0, utils_1.rewriteEnumsAsObjects)(typesContent, options.declaration);
|
|
98
100
|
}
|
|
99
101
|
/**
|
|
100
102
|
* Extracts inline schema types from the generated `schemas` block.
|
|
@@ -108,12 +110,16 @@ async function generateTypes(schema) {
|
|
|
108
110
|
*
|
|
109
111
|
* And replaces the inline body in `schemas` with a reference to the new type.
|
|
110
112
|
*
|
|
113
|
+
* The definitions holding the schemas shared between the other definitions are lifted the
|
|
114
|
+
* same way, whether they hold an object or, as the hoisted enums and filter values do, a
|
|
115
|
+
* union of their own.
|
|
116
|
+
*
|
|
111
117
|
* @param {string} typeContent - The generated TypeScript type content as a string.
|
|
112
|
-
* @param {string[]}
|
|
118
|
+
* @param {string[]} sharedTypes - The names of the definitions holding the schemas shared
|
|
113
119
|
* between the other definitions, whose references are replaced by the name alone.
|
|
114
120
|
* @return {string} The transformed types content with extracted schema types.
|
|
115
121
|
*/
|
|
116
|
-
function extractSchemaTypes(typeContent,
|
|
122
|
+
function extractSchemaTypes(typeContent, sharedTypes = []) {
|
|
117
123
|
const extractedTypes = [];
|
|
118
124
|
const typeNames = new Set();
|
|
119
125
|
const entries = [];
|
|
@@ -179,8 +185,11 @@ function extractSchemaTypes(typeContent, sharedEnums = []) {
|
|
|
179
185
|
}
|
|
180
186
|
}
|
|
181
187
|
updatedBaseContent += normalizedTypes.slice(cursor);
|
|
188
|
+
// Lift the shared definitions holding a union rather than an object, which the
|
|
189
|
+
// entries above leave in place (i.e. `QueryFilterValue: QueryFilterScalar | ...;`)
|
|
190
|
+
updatedBaseContent = extractSharedTypes(updatedBaseContent, sharedTypes, extractedTypes, typeNames);
|
|
182
191
|
// Replace all cross-references like components["schemas"]["def-89"] with the type name
|
|
183
|
-
const references = new Map(
|
|
192
|
+
const references = new Map(sharedTypes.map((name) => [`"${name}"`, name]));
|
|
184
193
|
for (const [defKey, typeName] of defToTypeName) {
|
|
185
194
|
references.set(defKey, typeName);
|
|
186
195
|
}
|
|
@@ -215,6 +224,87 @@ function extractSchemaTypes(typeContent, sharedEnums = []) {
|
|
|
215
224
|
const mergedExtractedTypes = stripFormat(joined.replace(doubleCommentsRegex, '$1*'));
|
|
216
225
|
return updatedBaseContent + '\n' + mergedExtractedTypes;
|
|
217
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Lifts the shared definitions holding a type of their own out of the generated `schemas`
|
|
229
|
+
* block, so the type they hold is declared once and referenced by name everywhere else.
|
|
230
|
+
*
|
|
231
|
+
* Finds entries like:
|
|
232
|
+
* QueryFilterValue: QueryFilterScalar | QueryFilterScalar[] | QueryCondition;
|
|
233
|
+
*
|
|
234
|
+
* Lifts each one into:
|
|
235
|
+
* export type QueryFilterValue = QueryFilterScalar | QueryFilterScalar[] | QueryCondition;
|
|
236
|
+
*
|
|
237
|
+
* The definitions holding nothing but a reference to a type declared elsewhere, as the hoisted
|
|
238
|
+
* enums do, are left alone.
|
|
239
|
+
*
|
|
240
|
+
* @param {string} content - The generated types, with the object definitions already extracted.
|
|
241
|
+
* @param {string[]} names - The names of the shared definitions to lift.
|
|
242
|
+
* @param {string[]} extractedTypes - The extracted types, appended to for every lifted entry.
|
|
243
|
+
* @param {Set<string>} typeNames - The names already extracted, added to for every lifted entry.
|
|
244
|
+
* @return {string} The types with the body of every lifted entry replaced by its name.
|
|
245
|
+
*/
|
|
246
|
+
function extractSharedTypes(content, names, extractedTypes, typeNames) {
|
|
247
|
+
// The definitions live in the components block, so a property named after one of them
|
|
248
|
+
// elsewhere in the types is never mistaken for its declaration
|
|
249
|
+
const componentsStart = content.indexOf('export type components');
|
|
250
|
+
if (componentsStart < 0) {
|
|
251
|
+
return content;
|
|
252
|
+
}
|
|
253
|
+
for (const name of names) {
|
|
254
|
+
if (typeNames.has(name)) {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
// The entry starts on a line of its own, optionally preceded by the JSDoc header
|
|
258
|
+
// holding the name of the definition
|
|
259
|
+
const entry = new RegExp(String.raw `\n[ \t]*(?:\/\*\*(?:(?!\*\/)[\s\S])*\*\/\s*)?${name}: `).exec(content.slice(componentsStart));
|
|
260
|
+
if (!entry) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const start = componentsStart + entry.index + entry[0].length;
|
|
264
|
+
const end = findTypeEnd(content, start);
|
|
265
|
+
const body = content.slice(start, end).trim();
|
|
266
|
+
// A definition referencing a type declared elsewhere holds nothing to lift
|
|
267
|
+
if (!body || body === name) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
typeNames.add(name);
|
|
271
|
+
extractedTypes.push(`export type ${name} = ${body};\n`);
|
|
272
|
+
content = content.slice(0, start) + name + content.slice(end);
|
|
273
|
+
}
|
|
274
|
+
return content;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Finds the end of the type starting at the given index, which is the first semicolon that is
|
|
278
|
+
* not nested inside braces, brackets, parentheses or a string literal.
|
|
279
|
+
*
|
|
280
|
+
* @param {string} content - The content holding the type.
|
|
281
|
+
* @param {number} start - The index the type starts at.
|
|
282
|
+
* @return {number} The index of the semicolon terminating the type.
|
|
283
|
+
*/
|
|
284
|
+
function findTypeEnd(content, start) {
|
|
285
|
+
const closing = { '{': '}', '[': ']', '(': ')' };
|
|
286
|
+
const stack = [];
|
|
287
|
+
for (let i = start; i < content.length; i++) {
|
|
288
|
+
const character = content[i];
|
|
289
|
+
if (character === '"' || character === "'") {
|
|
290
|
+
i = content.indexOf(character, i + 1);
|
|
291
|
+
if (i < 0) {
|
|
292
|
+
return content.length;
|
|
293
|
+
}
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (closing[character]) {
|
|
297
|
+
stack.push(closing[character]);
|
|
298
|
+
}
|
|
299
|
+
else if (character === stack[stack.length - 1]) {
|
|
300
|
+
stack.pop();
|
|
301
|
+
}
|
|
302
|
+
else if (character === ';' && stack.length === 0) {
|
|
303
|
+
return i;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return content.length;
|
|
307
|
+
}
|
|
218
308
|
/**
|
|
219
309
|
* Deduplicates and simplifies union type constituents in the provided TypeScript Abstract Syntax Tree (AST).
|
|
220
310
|
* Ensures that duplicate constituents are removed and shared types across parenthesized union branches are hoisted.
|
package/cjs/index.d.ts
CHANGED
package/cjs/index.js
CHANGED
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./clients"), exports);
|
|
18
18
|
__exportStar(require("./errors"), exports);
|
|
19
|
+
__exportStar(require("./types/resource"), exports);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Options controlling how the TypeScript types are generated from an OpenAPI schema. */
|
|
2
|
+
export type GenerateTypesOptions = {
|
|
3
|
+
/** Whether the types are written into a declaration (`.d.ts`) file, which holds no runtime
|
|
4
|
+
* values and so declares the enum constants instead of initializing them. (default: false) */
|
|
5
|
+
declaration?: boolean;
|
|
6
|
+
};
|
package/cjs/types/index.d.ts
CHANGED
package/cjs/types/index.js
CHANGED
|
@@ -14,4 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./generator"), exports);
|
|
18
|
+
__exportStar(require("./resource"), exports);
|
|
17
19
|
__exportStar(require("./routes"), exports);
|
package/cjs/utils/enum-util.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { OpenAPI3 } from 'openapi-typescript';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
* of their
|
|
2
|
+
* Rewrites the TypeScript enums of the generated types into a constant object holding the
|
|
3
|
+
* members and a type alias of their values, so both forms are accepted wherever the enum is
|
|
4
|
+
* used (i.e. `SortDirection.asc` and the plain `'asc'` literal alike).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* A TypeScript `enum` declares a nominal type, which rejects the very literals it is built
|
|
7
|
+
* from, forcing users of the generated client to import the enum for a value the API
|
|
8
|
+
* documents as a string. The rewritten declaration keeps the member access working while
|
|
9
|
+
* typing the property as the union of its values:
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* and `PostSingle` declaring `status` give `PostStatus`). Enums whose name cannot be
|
|
15
|
-
* resolved, or whose name is already taken, are left inline.
|
|
11
|
+
* ```ts
|
|
12
|
+
* export const SortDirection = { asc: 'asc', desc: 'desc' } as const;
|
|
13
|
+
* export type SortDirection = (typeof SortDirection)[keyof typeof SortDirection];
|
|
14
|
+
* ```
|
|
16
15
|
*
|
|
17
|
-
* The
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
16
|
+
* @param {string} content The generated TypeScript types to rewrite the enums of.
|
|
17
|
+
* @param {boolean} [declaration=false] Whether the types are emitted into a declaration
|
|
18
|
+
* (`.d.ts`) file, which holds no runtime values and so declares the constant instead of
|
|
19
|
+
* initializing it.
|
|
20
|
+
* @return {string} The types with every enum declaration rewritten.
|
|
21
21
|
*/
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function rewriteEnumsAsObjects(content: string, declaration?: boolean): string;
|