api-farmer 0.1.3 → 0.1.4
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/README.md +1 -1
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +13 -0
- package/dist/generate-C4lplT2F.mjs +320 -0
- package/dist/index.d.mts +377 -0
- package/dist/index.mjs +4 -0
- package/dist/utils-DachPo4u.mjs +119 -0
- package/package.json +24 -42
- package/dist/chunk-2227C45C.js +0 -131
- package/dist/chunk-RIXLRGPZ.js +0 -338
- package/dist/cli.cjs +0 -471
- package/dist/cli.d.cts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -14
- package/dist/generate-4J5VPBTS.js +0 -15
- package/dist/index.cjs +0 -521
- package/dist/index.d.cts +0 -334
- package/dist/index.d.ts +0 -334
- package/dist/index.js +0 -76
package/README.md
CHANGED
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { r as getCliVersion } from "./utils-DachPo4u.mjs";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
//#region src/cli.ts
|
|
5
|
+
const program = new Command();
|
|
6
|
+
program.version(getCliVersion());
|
|
7
|
+
program.action(async () => {
|
|
8
|
+
const { generate } = await import("./generate-C4lplT2F.mjs").then((n) => n.r);
|
|
9
|
+
return generate();
|
|
10
|
+
});
|
|
11
|
+
program.parse();
|
|
12
|
+
//#endregion
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { a as getResponseMetadataItems, c as isRequiredRequestBody, d as readTemplateFile, f as CWD, i as getRequestBodyContentType, l as readSchema, p as SUPPORTED_HTTP_METHODS } from "./utils-DachPo4u.mjs";
|
|
2
|
+
import pluralize from "pluralize";
|
|
3
|
+
import { camelize, groupBy, isArray, merge, pascalCase } from "rattail";
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
import ejs from "ejs";
|
|
6
|
+
import fse from "fs-extra";
|
|
7
|
+
import openapiTS, { astToString } from "openapi-typescript";
|
|
8
|
+
import prettier from "prettier";
|
|
9
|
+
import { logger } from "rslog";
|
|
10
|
+
import ts from "typescript";
|
|
11
|
+
import { loadConfig } from "unconfig";
|
|
12
|
+
//#region \0rolldown/runtime.js
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __exportAll = (all, no_symbols) => {
|
|
15
|
+
let target = {};
|
|
16
|
+
for (var name in all) __defProp(target, name, {
|
|
17
|
+
get: all[name],
|
|
18
|
+
enumerable: true
|
|
19
|
+
});
|
|
20
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
21
|
+
return target;
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/transformer.ts
|
|
25
|
+
function transformModuleName({ name }) {
|
|
26
|
+
return camelize(name);
|
|
27
|
+
}
|
|
28
|
+
function transformUrl({ path }) {
|
|
29
|
+
return path.replace(/{/g, ":").replace(/}/g, "");
|
|
30
|
+
}
|
|
31
|
+
function transformComment({ summary, description, path, method }) {
|
|
32
|
+
return `
|
|
33
|
+
/**${summary ? `\n* ${summary}` : ""}${description && summary !== description ? `\n* @description ${description}\n*` : ""}
|
|
34
|
+
* @url ${path}
|
|
35
|
+
* @method ${method.toLocaleUpperCase()}
|
|
36
|
+
*/
|
|
37
|
+
`.trim();
|
|
38
|
+
}
|
|
39
|
+
function transformVerb({ method }) {
|
|
40
|
+
switch (method) {
|
|
41
|
+
case "post": return "Create";
|
|
42
|
+
case "put": return "Update";
|
|
43
|
+
default: return pascalCase(method);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function transformEntity({ path, method, uncountableNouns }) {
|
|
47
|
+
const words = path.split("/").filter(Boolean);
|
|
48
|
+
return words.reduce((entity, word, index) => {
|
|
49
|
+
if (word.includes("{")) return entity;
|
|
50
|
+
word = word.replace(/\.([a-z])/g, (_, p) => p.toUpperCase());
|
|
51
|
+
const isUncountableNoun = uncountableNouns.includes(word);
|
|
52
|
+
word = pascalCase(word);
|
|
53
|
+
word = isUncountableNoun ? word : pluralize.singular(word);
|
|
54
|
+
if (method === "get" && index === words.length - 1) word = isUncountableNoun ? `${word}List` : pluralize.plural(word);
|
|
55
|
+
return `${entity}${word}`;
|
|
56
|
+
}, "");
|
|
57
|
+
}
|
|
58
|
+
function transformFn({ verb, entity }) {
|
|
59
|
+
return `api${verb}${entity}`;
|
|
60
|
+
}
|
|
61
|
+
function transformType({ verb, entity }) {
|
|
62
|
+
return `Api${verb}${entity}`;
|
|
63
|
+
}
|
|
64
|
+
function transformTypeValue({ fullPath, method }) {
|
|
65
|
+
return `paths['${fullPath}']['${method}']`;
|
|
66
|
+
}
|
|
67
|
+
function transformTypeQuery({ type }) {
|
|
68
|
+
return `${type}Query`;
|
|
69
|
+
}
|
|
70
|
+
function transformTypeQueryValue({ type }) {
|
|
71
|
+
return `${type}['parameters']['query']`;
|
|
72
|
+
}
|
|
73
|
+
function transformTypeRequestBody({ type }) {
|
|
74
|
+
return `${type}RequestBody`;
|
|
75
|
+
}
|
|
76
|
+
function transformTypeRequestBodyValue({ type, required, requestContentType }) {
|
|
77
|
+
return required ? `${type}['requestBody']['content']['${requestContentType}']` : `NonNullable<${type}['requestBody']>['content']['${requestContentType}'] | undefined`;
|
|
78
|
+
}
|
|
79
|
+
function transformTypeResponseBody({ type }) {
|
|
80
|
+
return `${type}ResponseBody`;
|
|
81
|
+
}
|
|
82
|
+
function transformTypeResponseBodyValue({ type, responseMetadataItems }) {
|
|
83
|
+
return responseMetadataItems.map(({ status, responseContentType }) => `${type}['responses']['${status}']['content']['${responseContentType}']`).join(" | ");
|
|
84
|
+
}
|
|
85
|
+
function createTransformer() {
|
|
86
|
+
return {
|
|
87
|
+
moduleName: transformModuleName,
|
|
88
|
+
verb: transformVerb,
|
|
89
|
+
url: transformUrl,
|
|
90
|
+
comment: transformComment,
|
|
91
|
+
entity: transformEntity,
|
|
92
|
+
fn: transformFn,
|
|
93
|
+
type: transformType,
|
|
94
|
+
typeValue: transformTypeValue,
|
|
95
|
+
typeQuery: transformTypeQuery,
|
|
96
|
+
typeQueryValue: transformTypeQueryValue,
|
|
97
|
+
typeRequestBody: transformTypeRequestBody,
|
|
98
|
+
typeRequestBodyValue: transformTypeRequestBodyValue,
|
|
99
|
+
typeResponseBody: transformTypeResponseBody,
|
|
100
|
+
typeResponseBodyValue: transformTypeResponseBodyValue
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/config.ts
|
|
105
|
+
function defineConfig(config) {
|
|
106
|
+
return config;
|
|
107
|
+
}
|
|
108
|
+
async function getConfig() {
|
|
109
|
+
const { config } = await loadConfig({ sources: [{ files: "api-farmer.config" }] });
|
|
110
|
+
return config ?? {};
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/generate.ts
|
|
114
|
+
var generate_exports = /* @__PURE__ */ __exportAll({
|
|
115
|
+
generate: () => generate,
|
|
116
|
+
generateTypes: () => generateTypes,
|
|
117
|
+
partitionApiModules: () => partitionApiModules,
|
|
118
|
+
renderApiModules: () => renderApiModules,
|
|
119
|
+
transformPayloads: () => transformPayloads
|
|
120
|
+
});
|
|
121
|
+
function transformPayloads(pathItems, options) {
|
|
122
|
+
const { transformer, path, fullPath, base, uncountableNouns, validateStatus, excludeDeprecated } = options;
|
|
123
|
+
return Object.entries(pathItems).filter(([key]) => SUPPORTED_HTTP_METHODS.includes(key)).filter(([, operation]) => !(excludeDeprecated && operation.deprecated)).reduce((payloads, [method, operation]) => {
|
|
124
|
+
const url = transformer.url({
|
|
125
|
+
path,
|
|
126
|
+
base,
|
|
127
|
+
fullPath
|
|
128
|
+
});
|
|
129
|
+
const args = {
|
|
130
|
+
path,
|
|
131
|
+
base,
|
|
132
|
+
fullPath,
|
|
133
|
+
url,
|
|
134
|
+
method,
|
|
135
|
+
uncountableNouns,
|
|
136
|
+
operation
|
|
137
|
+
};
|
|
138
|
+
const entity = transformer.entity(args);
|
|
139
|
+
const verb = transformer.verb(args);
|
|
140
|
+
const comment = transformer.comment({
|
|
141
|
+
...args,
|
|
142
|
+
...operation
|
|
143
|
+
});
|
|
144
|
+
const requestContentType = operation.requestBody ? getRequestBodyContentType(operation.requestBody) : void 0;
|
|
145
|
+
const responseMetadataItems = getResponseMetadataItems(operation, validateStatus);
|
|
146
|
+
const fn = transformer.fn({
|
|
147
|
+
...args,
|
|
148
|
+
verb,
|
|
149
|
+
entity
|
|
150
|
+
});
|
|
151
|
+
const type = transformer.type({
|
|
152
|
+
...args,
|
|
153
|
+
verb,
|
|
154
|
+
entity
|
|
155
|
+
});
|
|
156
|
+
const typeValue = transformer.typeValue({
|
|
157
|
+
...args,
|
|
158
|
+
verb,
|
|
159
|
+
entity
|
|
160
|
+
});
|
|
161
|
+
const typeQuery = transformer.typeQuery({
|
|
162
|
+
...args,
|
|
163
|
+
type,
|
|
164
|
+
verb,
|
|
165
|
+
entity
|
|
166
|
+
});
|
|
167
|
+
const typeQueryValue = transformer.typeQueryValue({
|
|
168
|
+
...args,
|
|
169
|
+
type,
|
|
170
|
+
verb,
|
|
171
|
+
entity
|
|
172
|
+
});
|
|
173
|
+
const typeRequestBody = transformer.typeRequestBody({
|
|
174
|
+
...args,
|
|
175
|
+
type,
|
|
176
|
+
verb,
|
|
177
|
+
entity
|
|
178
|
+
});
|
|
179
|
+
const typeRequestBodyValue = operation.requestBody && requestContentType ? transformer.typeRequestBodyValue({
|
|
180
|
+
...args,
|
|
181
|
+
type,
|
|
182
|
+
verb,
|
|
183
|
+
entity,
|
|
184
|
+
required: isRequiredRequestBody(operation.requestBody),
|
|
185
|
+
requestContentType
|
|
186
|
+
}) : "undefined";
|
|
187
|
+
const typeResponseBody = transformer.typeResponseBody({
|
|
188
|
+
...args,
|
|
189
|
+
type,
|
|
190
|
+
verb,
|
|
191
|
+
entity
|
|
192
|
+
});
|
|
193
|
+
const typeResponseBodyValue = responseMetadataItems.length > 0 ? transformer.typeResponseBodyValue({
|
|
194
|
+
...args,
|
|
195
|
+
type,
|
|
196
|
+
verb,
|
|
197
|
+
entity,
|
|
198
|
+
responseMetadataItems
|
|
199
|
+
}) : "undefined";
|
|
200
|
+
payloads.push({
|
|
201
|
+
comment,
|
|
202
|
+
fn,
|
|
203
|
+
url,
|
|
204
|
+
method,
|
|
205
|
+
verb,
|
|
206
|
+
entity,
|
|
207
|
+
requestContentType,
|
|
208
|
+
type,
|
|
209
|
+
typeValue,
|
|
210
|
+
typeQuery,
|
|
211
|
+
typeQueryValue,
|
|
212
|
+
typeRequestBody,
|
|
213
|
+
typeRequestBodyValue,
|
|
214
|
+
typeResponseBody,
|
|
215
|
+
typeResponseBodyValue
|
|
216
|
+
});
|
|
217
|
+
return payloads;
|
|
218
|
+
}, []);
|
|
219
|
+
}
|
|
220
|
+
function partitionApiModules(schema, options) {
|
|
221
|
+
const { base, transformer, uncountableNouns, validateStatus, excludeDeprecated } = options;
|
|
222
|
+
const schemaPaths = schema.paths ?? {};
|
|
223
|
+
const keyToPaths = groupBy(base ? Object.keys(schemaPaths).map((key) => key.replace(base, "")) : Object.keys(schemaPaths), (key) => key.split("/")[1]);
|
|
224
|
+
return Object.entries(keyToPaths).reduce((apiModules, [name, paths]) => {
|
|
225
|
+
const payloads = paths.reduce((payloads, path) => {
|
|
226
|
+
const fullPath = base ? base + path : path;
|
|
227
|
+
const pathItems = schemaPaths[fullPath];
|
|
228
|
+
payloads.push(...transformPayloads(pathItems, {
|
|
229
|
+
...options,
|
|
230
|
+
path,
|
|
231
|
+
fullPath,
|
|
232
|
+
transformer,
|
|
233
|
+
uncountableNouns,
|
|
234
|
+
validateStatus,
|
|
235
|
+
excludeDeprecated
|
|
236
|
+
}));
|
|
237
|
+
return payloads;
|
|
238
|
+
}, []);
|
|
239
|
+
apiModules.push({
|
|
240
|
+
name: transformer.moduleName({ name }),
|
|
241
|
+
payloads
|
|
242
|
+
});
|
|
243
|
+
return apiModules;
|
|
244
|
+
}, []);
|
|
245
|
+
}
|
|
246
|
+
function renderApiModules(apiModules, options) {
|
|
247
|
+
const { output, ts, typesOnly, overrides, preset } = options;
|
|
248
|
+
const templateFile = readTemplateFile(preset);
|
|
249
|
+
const typesFilename = options.typesFilename.replace(".ts", "");
|
|
250
|
+
return Promise.all(apiModules.map((apiModule) => new Promise((promiseResolve) => {
|
|
251
|
+
const data = {
|
|
252
|
+
apiModule,
|
|
253
|
+
typesFilename,
|
|
254
|
+
ts,
|
|
255
|
+
typesOnly
|
|
256
|
+
};
|
|
257
|
+
prettier.format(ejs.render(templateFile, data), {
|
|
258
|
+
parser: "typescript",
|
|
259
|
+
semi: false,
|
|
260
|
+
singleQuote: true,
|
|
261
|
+
printWidth: 120
|
|
262
|
+
}).then((content) => {
|
|
263
|
+
const path = resolve(output, `${apiModule.name}.${ts ? "ts" : "js"}`);
|
|
264
|
+
if ((!overrides || isArray(overrides) && !overrides.includes(apiModule.name)) && fse.existsSync(path)) {
|
|
265
|
+
logger.warn(`File already exists, skip: ${path}`);
|
|
266
|
+
promiseResolve(content);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
fse.outputFileSync(path, content);
|
|
270
|
+
logger.success(`Generated ${path}`);
|
|
271
|
+
promiseResolve(content);
|
|
272
|
+
});
|
|
273
|
+
})));
|
|
274
|
+
}
|
|
275
|
+
async function generateTypes(schema, output, typesFilename, openapiTsOptions) {
|
|
276
|
+
const BLOB = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Blob"));
|
|
277
|
+
const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull());
|
|
278
|
+
const contents = astToString(await openapiTS(schema, {
|
|
279
|
+
defaultNonNullable: false,
|
|
280
|
+
transform(schemaObject) {
|
|
281
|
+
if (schemaObject.format === "binary") return schemaObject.nullable ? ts.factory.createUnionTypeNode([BLOB, NULL]) : BLOB;
|
|
282
|
+
},
|
|
283
|
+
...openapiTsOptions
|
|
284
|
+
}));
|
|
285
|
+
const typesFilepath = resolve(CWD, output, typesFilename);
|
|
286
|
+
fse.outputFileSync(typesFilepath, contents);
|
|
287
|
+
logger.success(`Generated ${typesFilepath}`);
|
|
288
|
+
}
|
|
289
|
+
async function generate(userOptions = {}) {
|
|
290
|
+
const { base, ts = true, typesOnly = false, overrides = true, preset = "axle", input = "./schema.json", output = "./src/apis/generated", typesFilename = "_types.ts", clean = true, validateStatus = (status) => status >= 200 && status < 300, transformer = {}, uncountableNouns = [], openapiTsOptions = {}, excludeDeprecated = false } = merge(await getConfig(), userOptions);
|
|
291
|
+
const mergedTransformer = {
|
|
292
|
+
...createTransformer(),
|
|
293
|
+
...transformer
|
|
294
|
+
};
|
|
295
|
+
const schema = await readSchema(input);
|
|
296
|
+
if (clean) {
|
|
297
|
+
fse.removeSync(resolve(CWD, output));
|
|
298
|
+
logger.info(`Cleaned output directory: ${resolve(CWD, output)}`);
|
|
299
|
+
}
|
|
300
|
+
logger.info("Generating API modules...");
|
|
301
|
+
if (openapiTsOptions.excludeDeprecated === void 0) openapiTsOptions.excludeDeprecated = excludeDeprecated;
|
|
302
|
+
if (ts) await generateTypes(schema, output, typesFilename, openapiTsOptions);
|
|
303
|
+
await renderApiModules(partitionApiModules(schema, {
|
|
304
|
+
base,
|
|
305
|
+
uncountableNouns,
|
|
306
|
+
transformer: mergedTransformer,
|
|
307
|
+
validateStatus,
|
|
308
|
+
excludeDeprecated
|
|
309
|
+
}), {
|
|
310
|
+
output,
|
|
311
|
+
typesFilename,
|
|
312
|
+
ts,
|
|
313
|
+
typesOnly,
|
|
314
|
+
overrides,
|
|
315
|
+
preset
|
|
316
|
+
});
|
|
317
|
+
logger.success("Done");
|
|
318
|
+
}
|
|
319
|
+
//#endregion
|
|
320
|
+
export { transformVerb as C, transformUrl as S, transformTypeRequestBody as _, renderApiModules as a, transformTypeResponseBodyValue as b, getConfig as c, transformEntity as d, transformFn as f, transformTypeQueryValue as g, transformTypeQuery as h, partitionApiModules as i, createTransformer as l, transformType as m, generateTypes as n, transformPayloads as o, transformModuleName as p, generate_exports as r, defineConfig as s, generate as t, transformComment as u, transformTypeRequestBodyValue as v, transformTypeValue as x, transformTypeResponseBody as y };
|