@appweaver/client 1.0.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/LICENSE +1 -0
- package/README.md +7 -0
- package/clients/angular-client.d.ts +20 -0
- package/clients/angular-client.js +57 -0
- package/clients/base-client-interface.d.ts +71 -0
- package/clients/base-client-interface.js +2 -0
- package/clients/base-client.d.ts +216 -0
- package/clients/base-client.js +249 -0
- package/clients/fetch-client.d.ts +6 -0
- package/clients/fetch-client.js +10 -0
- package/clients/index.d.ts +5 -0
- package/clients/index.js +21 -0
- package/clients/modules/account-client.d.ts +69 -0
- package/clients/modules/account-client.js +111 -0
- package/clients/modules/auth-client.d.ts +56 -0
- package/clients/modules/auth-client.js +78 -0
- package/clients/modules/base-module.d.ts +17 -0
- package/clients/modules/base-module.js +53 -0
- package/clients/modules/files-client.d.ts +27 -0
- package/clients/modules/files-client.js +46 -0
- package/clients/modules/health-client.d.ts +25 -0
- package/clients/modules/health-client.js +34 -0
- package/clients/modules/index.d.ts +6 -0
- package/clients/modules/index.js +22 -0
- package/clients/modules/resource-client.d.ts +90 -0
- package/clients/modules/resource-client.js +177 -0
- package/clients/responses/file-data-response.d.ts +78 -0
- package/clients/responses/file-data-response.js +109 -0
- package/clients/responses/index.d.ts +1 -0
- package/clients/responses/index.js +17 -0
- package/commands/generate-command.d.ts +3 -0
- package/commands/generate-command.js +129 -0
- package/commands/index.d.ts +1 -0
- package/commands/index.js +17 -0
- package/constants.d.ts +67 -0
- package/constants.js +97 -0
- package/errors/client-error.d.ts +6 -0
- package/errors/client-error.js +15 -0
- package/errors/index.d.ts +1 -0
- package/errors/index.js +17 -0
- package/generators/generate-client.d.ts +16 -0
- package/generators/generate-client.js +394 -0
- package/generators/generate-types.d.ts +9 -0
- package/generators/generate-types.js +525 -0
- package/generators/index.d.ts +2 -0
- package/generators/index.js +18 -0
- package/index.d.ts +2 -0
- package/index.js +18 -0
- package/package.json +54 -0
- package/types/index.d.ts +1 -0
- package/types/index.js +17 -0
- package/types/routes.d.ts +15 -0
- package/types/routes.js +2 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +17 -0
- package/utils/schema-util.d.ts +3 -0
- package/utils/schema-util.js +46 -0
- package/weaver-client.d.ts +2 -0
- package/weaver-client.js +20 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResourceClient = void 0;
|
|
4
|
+
const base_module_1 = require("./base-module");
|
|
5
|
+
class ResourceClient extends base_module_1.BaseModule {
|
|
6
|
+
basePath;
|
|
7
|
+
constructor(client, basePath) {
|
|
8
|
+
super(client);
|
|
9
|
+
this.basePath = basePath;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Fetches a single resource by its numeric ID.
|
|
13
|
+
*
|
|
14
|
+
* @param {number} id - The ID of the resource to retrieve.
|
|
15
|
+
* @param {RequestOptions} options - Additional request options (headers, query params, etc.).
|
|
16
|
+
* @returns The resource record matching the given ID.
|
|
17
|
+
*/
|
|
18
|
+
async find(id, options = {}) {
|
|
19
|
+
return this.sendRequest('get', `${this.basePath}/{id}`, {
|
|
20
|
+
...options,
|
|
21
|
+
params: {
|
|
22
|
+
...(options.params ?? {}),
|
|
23
|
+
path: {
|
|
24
|
+
id
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Executes a query against the resource collection.
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} request - The query payload (filters, sorting, pagination, etc.).
|
|
33
|
+
* @param {RequestOptions} options - Additional request options.
|
|
34
|
+
* @returns A paginated or filtered list of matching resource records.
|
|
35
|
+
*/
|
|
36
|
+
async query(request, options = {}) {
|
|
37
|
+
return this.sendRequest('post', `${this.basePath}/query`, {
|
|
38
|
+
...options,
|
|
39
|
+
body: request
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Runs an aggregation query (e.g., count, sum, avg) against the resource collection.
|
|
44
|
+
*
|
|
45
|
+
* @param {Object} request - The aggregation payload describing the desired computation.
|
|
46
|
+
* @param {RequestOptions} options - Additional request options.
|
|
47
|
+
* @returns The aggregated result for the given query.
|
|
48
|
+
*/
|
|
49
|
+
async aggregate(request, options = {}) {
|
|
50
|
+
return this.sendRequest('post', `${this.basePath}/aggregate`, {
|
|
51
|
+
...options,
|
|
52
|
+
body: request
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new resource record.
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} resource - The data for the resource to create.
|
|
59
|
+
* @param {RequestOptions} options - Additional request options.
|
|
60
|
+
* @returns The newly created resource record.
|
|
61
|
+
*/
|
|
62
|
+
async create(resource, options = {}) {
|
|
63
|
+
return this.sendRequest('post', `${this.basePath}`, {
|
|
64
|
+
...options,
|
|
65
|
+
body: resource
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Updates an existing resource record identified by `id`.
|
|
70
|
+
*
|
|
71
|
+
* @param {Object} resource - The updated field values including the mandatory `id`.
|
|
72
|
+
* @param {RequestOptions} options - Additional request options.
|
|
73
|
+
* @returns The updated resource record.
|
|
74
|
+
*/
|
|
75
|
+
async update(resource, options = {}) {
|
|
76
|
+
return this.sendRequest('put', `${this.basePath}/{id}`, {
|
|
77
|
+
...options,
|
|
78
|
+
params: {
|
|
79
|
+
...(options.params ?? {}),
|
|
80
|
+
path: {
|
|
81
|
+
id: resource['id']
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
body: resource
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Deletes a resource record by its numeric ID.
|
|
89
|
+
*
|
|
90
|
+
* @param {number} id - The ID of the resource to delete.
|
|
91
|
+
* @param {RequestOptions} options - Additional request options.
|
|
92
|
+
* @returns The deleted resource record.
|
|
93
|
+
*/
|
|
94
|
+
async delete(id, options = {}) {
|
|
95
|
+
return this.sendRequest('delete', `${this.basePath}/{id}`, {
|
|
96
|
+
...options,
|
|
97
|
+
params: {
|
|
98
|
+
...(options.params ?? {}),
|
|
99
|
+
path: {
|
|
100
|
+
id
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Exports resource records as a file (e.g., CSV) and returns a streaming response.
|
|
107
|
+
*
|
|
108
|
+
* @param {Object} request - The export request payload (filters, format, etc.).
|
|
109
|
+
* @param {RequestOptions} options - Additional request options.
|
|
110
|
+
* @returns {@link FileDataResponse} containing the readable stream and file metadata.
|
|
111
|
+
*/
|
|
112
|
+
async export(request, options = {}) {
|
|
113
|
+
const { error, response } = await this.sendRequestRaw('post', `${this.basePath}/export`, {
|
|
114
|
+
...options,
|
|
115
|
+
parseAs: 'stream',
|
|
116
|
+
body: request
|
|
117
|
+
});
|
|
118
|
+
if (error) {
|
|
119
|
+
this.handleError(error, response);
|
|
120
|
+
}
|
|
121
|
+
return this.toFileResponse(response);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Uploads one or more files to the resource record.
|
|
125
|
+
*
|
|
126
|
+
* Each entry in `files` maps a field name to a single `File` or an array of `File` objects.
|
|
127
|
+
*
|
|
128
|
+
* @param {number} id - The ID of the resource for which to upload files.
|
|
129
|
+
* @param {Object} files - A map of field names to the file(s) to upload.
|
|
130
|
+
* @param {RequestOptions} options - Additional request options.
|
|
131
|
+
* @returns The updated file metadata for the resource.
|
|
132
|
+
*/
|
|
133
|
+
async uploadFiles(id, files, options = {}) {
|
|
134
|
+
const formData = new FormData();
|
|
135
|
+
for (const [fieldName, fileData] of Object.entries(files)) {
|
|
136
|
+
if (Array.isArray(fileData)) {
|
|
137
|
+
for (const file of fileData) {
|
|
138
|
+
formData.append(fieldName, file);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
formData.append(fieldName, fileData);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return this.sendRequest('post', `${this.basePath}/{id}/files`, {
|
|
146
|
+
...options,
|
|
147
|
+
body: formData,
|
|
148
|
+
params: {
|
|
149
|
+
...(options.params ?? {}),
|
|
150
|
+
path: {
|
|
151
|
+
id
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Removes specific files from the resource record.
|
|
158
|
+
*
|
|
159
|
+
* @param {number} id - The ID of the resource for which to delete files.
|
|
160
|
+
* @param {Object} files - The file deletion payload identifying which files to remove.
|
|
161
|
+
* @param {RequestOptions} options - Additional request options.
|
|
162
|
+
* @returns The updated file metadata for the resource after deletion.
|
|
163
|
+
*/
|
|
164
|
+
async deleteFiles(id, files, options = {}) {
|
|
165
|
+
return this.sendRequest('post', `${this.basePath}/{id}/delete-files`, {
|
|
166
|
+
...options,
|
|
167
|
+
body: files,
|
|
168
|
+
params: {
|
|
169
|
+
...(options.params ?? {}),
|
|
170
|
+
path: {
|
|
171
|
+
id
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
exports.ResourceClient = ResourceClient;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response object containing file data and metadata from a file download request.
|
|
3
|
+
* Provides helper methods to consume the stream as text, base64 data URL, or Buffer.
|
|
4
|
+
*/
|
|
5
|
+
export declare class FileDataResponse {
|
|
6
|
+
/** Readable stream of the file content. */
|
|
7
|
+
readonly stream: ReadableStream;
|
|
8
|
+
/** Name of the file extracted from the Content-Disposition header or provided default. */
|
|
9
|
+
readonly fileName: string;
|
|
10
|
+
/** MIME type of the file from the Content-Type header. */
|
|
11
|
+
readonly type: string;
|
|
12
|
+
/** Size of the file in bytes from the Content-Length header. */
|
|
13
|
+
readonly length: number;
|
|
14
|
+
/** Range information if the response is a partial content response (HTTP 206). */
|
|
15
|
+
readonly range?: FileContentRange;
|
|
16
|
+
/** Cache duration in seconds from the Cache-Control max-age directive. */
|
|
17
|
+
readonly maxAge?: number;
|
|
18
|
+
/** Expiration timestamp from Expires header. */
|
|
19
|
+
readonly expiresAt?: string;
|
|
20
|
+
private _buffer;
|
|
21
|
+
constructor(data: {
|
|
22
|
+
stream: ReadableStream;
|
|
23
|
+
fileName: string;
|
|
24
|
+
type: string;
|
|
25
|
+
length: number;
|
|
26
|
+
range?: FileContentRange;
|
|
27
|
+
maxAge?: number;
|
|
28
|
+
expiresAt?: string;
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Reads and returns the content of the buffer as an ArrayBuffer.
|
|
32
|
+
*
|
|
33
|
+
* @return {Promise<ArrayBuffer>} A promise that resolves to an ArrayBuffer containing the data read from the buffer.
|
|
34
|
+
*/
|
|
35
|
+
buffer(): Promise<ArrayBuffer>;
|
|
36
|
+
/**
|
|
37
|
+
* Reads and returns the content of the buffer as a Blob object.
|
|
38
|
+
*
|
|
39
|
+
* The method reads an ArrayBuffer from an internal data source, then constructs,
|
|
40
|
+
* and returns a Blob object using the buffer's content and a specified MIME type.
|
|
41
|
+
*
|
|
42
|
+
* @return {Promise<Blob>} A promise that resolves to a Blob object containing the read data.
|
|
43
|
+
*/
|
|
44
|
+
blob(): Promise<Blob>;
|
|
45
|
+
/**
|
|
46
|
+
* Reads and decodes the content of the buffer into a string using the TextDecoder API.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} encoding - The character encoding to use for decoding. Defaults to 'utf-8'.
|
|
49
|
+
* @return {Promise<string>} A promise that resolves to the decoded string.
|
|
50
|
+
*/
|
|
51
|
+
text(encoding?: string): Promise<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Reads and converts the buffer into a Base64-encoded data URL string.
|
|
54
|
+
*
|
|
55
|
+
* @return {Promise<string>} A promise that resolves to a Base64-encoded string
|
|
56
|
+
* representing the file, prefixed with the appropriate data MIME type.
|
|
57
|
+
*/
|
|
58
|
+
base64(): Promise<string>;
|
|
59
|
+
/**
|
|
60
|
+
* Reads and concatenates data chunks from a readable stream into a single ArrayBuffer.
|
|
61
|
+
* If the buffer has already been read, it returns the cached ArrayBuffer.
|
|
62
|
+
*
|
|
63
|
+
* @return {Promise<ArrayBuffer>} A promise that resolves to the ArrayBuffer containing
|
|
64
|
+
* the concatenated data from the stream.
|
|
65
|
+
*/
|
|
66
|
+
private _readArrayBuffer;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Represents byte range information for partial content responses.
|
|
70
|
+
*/
|
|
71
|
+
export type FileContentRange = {
|
|
72
|
+
/** Starting byte position of the range (inclusive). */
|
|
73
|
+
start: number;
|
|
74
|
+
/** Ending byte position of the range (inclusive). */
|
|
75
|
+
end: number;
|
|
76
|
+
/** Total size of the complete file in bytes. */
|
|
77
|
+
total: number;
|
|
78
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileDataResponse = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Response object containing file data and metadata from a file download request.
|
|
6
|
+
* Provides helper methods to consume the stream as text, base64 data URL, or Buffer.
|
|
7
|
+
*/
|
|
8
|
+
class FileDataResponse {
|
|
9
|
+
/** Readable stream of the file content. */
|
|
10
|
+
stream;
|
|
11
|
+
/** Name of the file extracted from the Content-Disposition header or provided default. */
|
|
12
|
+
fileName;
|
|
13
|
+
/** MIME type of the file from the Content-Type header. */
|
|
14
|
+
type;
|
|
15
|
+
/** Size of the file in bytes from the Content-Length header. */
|
|
16
|
+
length;
|
|
17
|
+
/** Range information if the response is a partial content response (HTTP 206). */
|
|
18
|
+
range;
|
|
19
|
+
/** Cache duration in seconds from the Cache-Control max-age directive. */
|
|
20
|
+
maxAge;
|
|
21
|
+
/** Expiration timestamp from Expires header. */
|
|
22
|
+
expiresAt;
|
|
23
|
+
_buffer;
|
|
24
|
+
constructor(data) {
|
|
25
|
+
this.stream = data.stream;
|
|
26
|
+
this.fileName = data.fileName;
|
|
27
|
+
this.type = data.type;
|
|
28
|
+
this.length = data.length;
|
|
29
|
+
this.range = data.range;
|
|
30
|
+
this.maxAge = data.maxAge;
|
|
31
|
+
this.expiresAt = data.expiresAt;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reads and returns the content of the buffer as an ArrayBuffer.
|
|
35
|
+
*
|
|
36
|
+
* @return {Promise<ArrayBuffer>} A promise that resolves to an ArrayBuffer containing the data read from the buffer.
|
|
37
|
+
*/
|
|
38
|
+
async buffer() {
|
|
39
|
+
return this._readArrayBuffer();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Reads and returns the content of the buffer as a Blob object.
|
|
43
|
+
*
|
|
44
|
+
* The method reads an ArrayBuffer from an internal data source, then constructs,
|
|
45
|
+
* and returns a Blob object using the buffer's content and a specified MIME type.
|
|
46
|
+
*
|
|
47
|
+
* @return {Promise<Blob>} A promise that resolves to a Blob object containing the read data.
|
|
48
|
+
*/
|
|
49
|
+
async blob() {
|
|
50
|
+
const buf = await this._readArrayBuffer();
|
|
51
|
+
return new Blob([buf], { type: this.type });
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Reads and decodes the content of the buffer into a string using the TextDecoder API.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} encoding - The character encoding to use for decoding. Defaults to 'utf-8'.
|
|
57
|
+
* @return {Promise<string>} A promise that resolves to the decoded string.
|
|
58
|
+
*/
|
|
59
|
+
async text(encoding = 'utf-8') {
|
|
60
|
+
const buf = await this._readArrayBuffer();
|
|
61
|
+
return new TextDecoder(encoding).decode(buf);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Reads and converts the buffer into a Base64-encoded data URL string.
|
|
65
|
+
*
|
|
66
|
+
* @return {Promise<string>} A promise that resolves to a Base64-encoded string
|
|
67
|
+
* representing the file, prefixed with the appropriate data MIME type.
|
|
68
|
+
*/
|
|
69
|
+
async base64() {
|
|
70
|
+
const buf = await this._readArrayBuffer();
|
|
71
|
+
const bytes = new Uint8Array(buf);
|
|
72
|
+
let binary = '';
|
|
73
|
+
for (let i = 0; i < bytes.byteLength; i++) {
|
|
74
|
+
binary += String.fromCharCode(bytes[i]);
|
|
75
|
+
}
|
|
76
|
+
const encoded = btoa(binary);
|
|
77
|
+
return `data:${this.type};base64,${encoded}`;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Reads and concatenates data chunks from a readable stream into a single ArrayBuffer.
|
|
81
|
+
* If the buffer has already been read, it returns the cached ArrayBuffer.
|
|
82
|
+
*
|
|
83
|
+
* @return {Promise<ArrayBuffer>} A promise that resolves to the ArrayBuffer containing
|
|
84
|
+
* the concatenated data from the stream.
|
|
85
|
+
*/
|
|
86
|
+
async _readArrayBuffer() {
|
|
87
|
+
if (this._buffer !== undefined) {
|
|
88
|
+
return this._buffer;
|
|
89
|
+
}
|
|
90
|
+
const reader = this.stream.getReader();
|
|
91
|
+
const chunks = [];
|
|
92
|
+
while (true) {
|
|
93
|
+
const { done, value } = await reader.read();
|
|
94
|
+
if (done)
|
|
95
|
+
break;
|
|
96
|
+
chunks.push(value);
|
|
97
|
+
}
|
|
98
|
+
const totalLength = chunks.reduce((sum, c) => sum + c.byteLength, 0);
|
|
99
|
+
const result = new Uint8Array(totalLength);
|
|
100
|
+
let offset = 0;
|
|
101
|
+
for (const chunk of chunks) {
|
|
102
|
+
result.set(chunk, offset);
|
|
103
|
+
offset += chunk.byteLength;
|
|
104
|
+
}
|
|
105
|
+
this._buffer = result.buffer;
|
|
106
|
+
return this._buffer;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.FileDataResponse = FileDataResponse;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './file-data-response';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./file-data-response"), exports);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateCommand = generateCommand;
|
|
7
|
+
exports.relativePathFrom = relativePathFrom;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const prettier_1 = __importDefault(require("prettier"));
|
|
12
|
+
const commander_1 = require("commander");
|
|
13
|
+
const generators_1 = require("../generators");
|
|
14
|
+
const utils_1 = require("../utils");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
16
|
+
function generateCommand(program) {
|
|
17
|
+
program
|
|
18
|
+
.command('generate')
|
|
19
|
+
.alias('g')
|
|
20
|
+
.description('Generates types and client class.')
|
|
21
|
+
.argument('<schemaPath>', 'The path to the OpenAPI schema (file or URL)', parseSchema)
|
|
22
|
+
.option('--outputPath [path]', 'Output path for both generated types and client class.', './generated/client.ts')
|
|
23
|
+
.option('--typesPath [path]', 'Output path for generated types. (default: output path)')
|
|
24
|
+
.option('--clientPath [path]', 'Output path for generated client class. (default: output path)')
|
|
25
|
+
.option('--clientName [name]', 'Name for generated client class. (default: OpenAPI schema title)')
|
|
26
|
+
.option('--framework [name]', `The framework for generated client class (${constants_1.FRAMEWORKS.join(', ')})`, parseFramework, 'fetch')
|
|
27
|
+
.option('--typesOnly', 'Generate TypeScript types only (without client class).')
|
|
28
|
+
.option('--clientOnly', 'Generate only client class (without TypeScript types).')
|
|
29
|
+
.option('--noTypes', 'Generate client class without TypeScript type support.')
|
|
30
|
+
.action(async (schemaPath, _, command) => {
|
|
31
|
+
const outputPath = command.getOptionValue('outputPath');
|
|
32
|
+
const typesPath = command.getOptionValue('typesPath') || outputPath;
|
|
33
|
+
const clientPath = command.getOptionValue('clientPath') || outputPath;
|
|
34
|
+
const clientName = command.getOptionValue('clientName');
|
|
35
|
+
const framework = command.getOptionValue('framework');
|
|
36
|
+
const typesOnly = command.getOptionValue('typesOnly');
|
|
37
|
+
const clientOnly = command.getOptionValue('clientOnly');
|
|
38
|
+
const noTypes = command.getOptionValue('noTypes');
|
|
39
|
+
const cwd = process.cwd();
|
|
40
|
+
const schemaContent = await (0, utils_1.readSchemaContent)(schemaPath);
|
|
41
|
+
const schemaObject = await (0, utils_1.toSchemaObject)(schemaContent);
|
|
42
|
+
if (!clientOnly && !noTypes) {
|
|
43
|
+
const typesContent = await (0, generators_1.generateTypes)(schemaObject);
|
|
44
|
+
await formatAndWriteFile(typesPath, typesContent, typesOnly || typesPath !== clientPath);
|
|
45
|
+
console.log(`Generated types to ${node_path_1.default.relative(cwd, typesPath)}`);
|
|
46
|
+
}
|
|
47
|
+
if (!typesOnly) {
|
|
48
|
+
const typesImportPath = typesPath === clientPath
|
|
49
|
+
? undefined
|
|
50
|
+
: relativePathFrom(clientPath, typesPath);
|
|
51
|
+
const clientContent = await (0, generators_1.generateClient)(schemaObject, clientName, framework, typesImportPath, noTypes);
|
|
52
|
+
await formatAndWriteFile(clientPath, clientContent, true, typesPath === clientPath);
|
|
53
|
+
console.log(`Generated client to ${node_path_1.default.relative(cwd, clientPath)}`);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function formatAndWriteFile(filePath, content, addGeneratedComment = true, appendIfExists = false) {
|
|
58
|
+
const dirPath = node_path_1.default.resolve(node_path_1.default.dirname(filePath));
|
|
59
|
+
const dirExists = await pathExists(dirPath);
|
|
60
|
+
if (!dirExists) {
|
|
61
|
+
await promises_1.default.mkdir(dirPath, { recursive: true });
|
|
62
|
+
}
|
|
63
|
+
const prettierConfig = await prettier_1.default.resolveConfig(filePath);
|
|
64
|
+
let formattedContent = await prettier_1.default.format(content, {
|
|
65
|
+
...(prettierConfig ?? { singleQuote: true, trailingComma: 'none' }),
|
|
66
|
+
filepath: filePath
|
|
67
|
+
});
|
|
68
|
+
const fileExists = await pathExists(filePath);
|
|
69
|
+
if (appendIfExists && fileExists) {
|
|
70
|
+
const existingContent = await promises_1.default.readFile(filePath, 'utf8');
|
|
71
|
+
formattedContent = formattedContent + '\n' + existingContent;
|
|
72
|
+
}
|
|
73
|
+
if (addGeneratedComment) {
|
|
74
|
+
formattedContent =
|
|
75
|
+
'// Generated by Appweaver. Please do not edit this file manually.\n\n' +
|
|
76
|
+
formattedContent;
|
|
77
|
+
}
|
|
78
|
+
await promises_1.default.writeFile(filePath, formattedContent, 'utf8');
|
|
79
|
+
}
|
|
80
|
+
async function pathExists(filePath) {
|
|
81
|
+
try {
|
|
82
|
+
await promises_1.default.access(filePath, promises_1.default.constants.F_OK);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function relativePathFrom(firstPath, otherPath) {
|
|
90
|
+
const firstDir = node_path_1.default.dirname(node_path_1.default.resolve(firstPath));
|
|
91
|
+
const otherAbs = node_path_1.default.resolve(otherPath);
|
|
92
|
+
let rel = node_path_1.default.relative(firstDir, otherAbs);
|
|
93
|
+
if (!rel.startsWith('.') && rel !== '') {
|
|
94
|
+
rel = `.${node_path_1.default.sep}${rel}`;
|
|
95
|
+
}
|
|
96
|
+
else if (rel === '') {
|
|
97
|
+
rel = '.';
|
|
98
|
+
}
|
|
99
|
+
if (rel.endsWith('.ts')) {
|
|
100
|
+
rel = rel.replace('.d.ts', '.ts').replace('.ts', '');
|
|
101
|
+
}
|
|
102
|
+
return rel.replace(/\\/g, '/');
|
|
103
|
+
}
|
|
104
|
+
function parseSchema(value) {
|
|
105
|
+
let schemaUrl;
|
|
106
|
+
try {
|
|
107
|
+
schemaUrl = new URL(value);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Schema path is not in URL format
|
|
111
|
+
}
|
|
112
|
+
if (schemaUrl) {
|
|
113
|
+
if (!['http:', 'https:', 'file:'].includes(schemaUrl.protocol)) {
|
|
114
|
+
throw new commander_1.InvalidArgumentError(`Unsupported schema URL protocol: ${schemaUrl.protocol}`);
|
|
115
|
+
}
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
if (!node_fs_1.default.existsSync(value)) {
|
|
119
|
+
throw new commander_1.InvalidArgumentError(`Schema path "${value}" does not exist or is not a valid URL.`);
|
|
120
|
+
}
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
function parseFramework(value) {
|
|
124
|
+
const lowerFramework = value.toLowerCase();
|
|
125
|
+
if (!constants_1.FRAMEWORKS.includes(lowerFramework)) {
|
|
126
|
+
throw new commander_1.InvalidOptionArgumentError(`Must be one of following: ${constants_1.FRAMEWORKS.join(', ')}.`);
|
|
127
|
+
}
|
|
128
|
+
return lowerFramework;
|
|
129
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './generate-command';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./generate-command"), exports);
|
package/constants.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** Supported frameworks for generating the client class. */
|
|
2
|
+
export declare const FRAMEWORKS: readonly ["fetch", "angular"];
|
|
3
|
+
/** Custom OpenAPI extension key used for extracting route prefixes and base paths to their resources. */
|
|
4
|
+
export declare const CONFIG_FIELD = "x-appweaver-config";
|
|
5
|
+
/** Custom OpenAPI extension key used for extracting resources names from schema CRUD objects. */
|
|
6
|
+
export declare const CONFIG_RESOURCE_FIELD = "x-appweaver-resource";
|
|
7
|
+
/** Suffix used when generating the TypeScript module type name for a resource. */
|
|
8
|
+
export declare const RESOURCE_MODULE_TYPE = "ResourceModuleType";
|
|
9
|
+
/** Maps CRUD operation names to HTTP methods used for matching OpenAPI paths to `ResourceClient` methods. */
|
|
10
|
+
export declare const RESOURCE_OPERATIONS: {
|
|
11
|
+
readonly find: "get";
|
|
12
|
+
readonly query: "post";
|
|
13
|
+
readonly aggregate: "post";
|
|
14
|
+
readonly create: "post";
|
|
15
|
+
readonly update: "put";
|
|
16
|
+
readonly delete: "delete";
|
|
17
|
+
readonly export: "post";
|
|
18
|
+
readonly uploadFiles: "post";
|
|
19
|
+
readonly deleteFiles: "post";
|
|
20
|
+
};
|
|
21
|
+
/** Expected type keys for a resource used for type inference. */
|
|
22
|
+
export declare const RESOURCE_TYPES: readonly ["single", "multiple", "create", "update", "queryRequest", "queryResponse", "aggregateRequest", "aggregateResponse", "exportRequest", "files", "fileUpload", "fileDelete"];
|
|
23
|
+
/** Type name used when generating the TypeScript module type for the auth module. */
|
|
24
|
+
export declare const AUTH_MODULE_TYPE = "AuthModuleType";
|
|
25
|
+
/** Maps auth operation names to HTTP methods used for matchingOpenAPI paths to `AuthClient` methods.
|
|
26
|
+
* The operation names are matching the real API paths (without a prefix and in camelCase format) from the OpenAPI. */
|
|
27
|
+
export declare const AUTH_OPERATIONS: {
|
|
28
|
+
readonly login: "post";
|
|
29
|
+
readonly logout: "post";
|
|
30
|
+
readonly refresh: "post";
|
|
31
|
+
readonly changePassword: "post";
|
|
32
|
+
readonly exchangeToken: "post";
|
|
33
|
+
readonly me: "get";
|
|
34
|
+
};
|
|
35
|
+
/** Expected type keys for the auth module used for type safety. */
|
|
36
|
+
export declare const AUTH_TYPES: readonly ["loginRequest", "authenticationResponse", "logoutResponse", "changePasswordRequest", "exchangeTokenRequest", "identity"];
|
|
37
|
+
/** Type name used when generating the TypeScript module type for the account module. */
|
|
38
|
+
export declare const ACCOUNT_MODULE_TYPE = "AccountModuleType";
|
|
39
|
+
/** Maps account operation names to HTTP methods used for matching OpenAPI paths to `AccountClient` methods.
|
|
40
|
+
* The operation names are matching the real API paths (without a prefix and in camelCase format) from the OpenAPI. */
|
|
41
|
+
export declare const ACCOUNT_OPERATIONS: {
|
|
42
|
+
readonly sendVerifyEmail: "post";
|
|
43
|
+
readonly verifyEmail: "post";
|
|
44
|
+
readonly verifyEmailRedirect: "get";
|
|
45
|
+
readonly sendResetPassword: "post";
|
|
46
|
+
readonly resetPassword: "post";
|
|
47
|
+
readonly send2FACode: "post";
|
|
48
|
+
readonly verify2FACode: "post";
|
|
49
|
+
};
|
|
50
|
+
/** Expected type keys for the account module which covers email verification, password reset, and 2FA req/resp. */
|
|
51
|
+
export declare const ACCOUNT_TYPES: readonly ["sendEmailVerificationRequest", "statusResponse", "emailVerificationRequest", "sendResetPasswordRequest", "resetPasswordRequest", "send2FACodeRequest", "send2FAResponse", "verify2FARequest", "verify2FAResponse"];
|
|
52
|
+
/** Type name used when generating the TypeScript module type for the health module. */
|
|
53
|
+
export declare const HEALTH_MODULE_TYPE = "HealthModuleType";
|
|
54
|
+
/** Maps health check operations to HTTP GET methods used for matching OpenAPI paths to `HealthClient` methods.
|
|
55
|
+
* The operation names are matching the real API paths (without a prefix and in camelCase format) from the OpenAPI. */
|
|
56
|
+
export declare const HEALTH_OPERATIONS: {
|
|
57
|
+
readonly check: "get";
|
|
58
|
+
readonly ready: "get";
|
|
59
|
+
};
|
|
60
|
+
/** Expected type keys for the health module used for `HealthClient` response typing. */
|
|
61
|
+
export declare const HEALTH_TYPES: readonly ["checkResponse", "readyResponse"];
|
|
62
|
+
/** Maps file-serving operations to HTTP GET methods used for identifying public and protected file endpoints.
|
|
63
|
+
* The operation names are matching the real API paths (without a prefix and in camelCase format) from the OpenAPI. */
|
|
64
|
+
export declare const FILE_OPERATIONS: {
|
|
65
|
+
readonly public: "get";
|
|
66
|
+
readonly protected: "get";
|
|
67
|
+
};
|