api-farmer 0.1.0 → 0.1.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/README.md CHANGED
@@ -153,6 +153,11 @@ export interface Config {
153
153
  * Certain uncountable nouns that do not change from singular to plural
154
154
  */
155
155
  uncountableNouns?: string[]
156
+ /**
157
+ * The options for the openapiTS library.
158
+ * @see https://openapi-ts.dev/node
159
+ */
160
+ openapiTsOptions?: OpenAPITSOptions
156
161
  }
157
162
  ```
158
163
 
@@ -105,7 +105,7 @@ function getResponseMetadataItems(operation, validateStatus) {
105
105
  const validStatusResults = Object.keys(responses).sort((a, b) => Number(a) - Number(b)).filter((key) => validateStatus(Number(key))).map(Number);
106
106
  const metadataItems = validStatusResults.map((status) => {
107
107
  const content = operation.responses?.[status]?.content ?? {};
108
- const responseContentType = findObjectKey(content, ["application/json", "*/*"]);
108
+ const responseContentType = findObjectKey(content, ["application/json", "application/octet-stream", "*/*"]);
109
109
  return {
110
110
  status,
111
111
  responseContentType
@@ -6,7 +6,7 @@ import {
6
6
  isRequiredRequestBody,
7
7
  readSchema,
8
8
  readTemplateFile
9
- } from "./chunk-56NOW5DM.js";
9
+ } from "./chunk-2227C45C.js";
10
10
 
11
11
  // src/generate.ts
12
12
  import { resolve } from "path";
@@ -16,6 +16,7 @@ import openapiTS, { astToString } from "openapi-typescript";
16
16
  import prettier from "prettier";
17
17
  import { groupBy, isArray, merge } from "rattail";
18
18
  import { logger } from "rslog";
19
+ import ts from "typescript";
19
20
 
20
21
  // src/config.ts
21
22
  import { loadConfig } from "unconfig";
@@ -217,7 +218,7 @@ function partitionApiModules(schema, options) {
217
218
  return apiModules;
218
219
  }
219
220
  function renderApiModules(apiModules, options) {
220
- const { output, ts, typesOnly, overrides, preset } = options;
221
+ const { output, ts: ts2, typesOnly, overrides, preset } = options;
221
222
  const templateFile = readTemplateFile(preset);
222
223
  const typesFilename = options.typesFilename.replace(".ts", "");
223
224
  return Promise.all(
@@ -226,7 +227,7 @@ function renderApiModules(apiModules, options) {
226
227
  const data = {
227
228
  apiModule,
228
229
  typesFilename,
229
- ts,
230
+ ts: ts2,
230
231
  typesOnly
231
232
  };
232
233
  prettier.format(ejs.render(templateFile, data), {
@@ -235,7 +236,7 @@ function renderApiModules(apiModules, options) {
235
236
  singleQuote: true,
236
237
  printWidth: 120
237
238
  }).then((content) => {
238
- const path = resolve(output, `${apiModule.name}.${ts ? "ts" : "js"}`);
239
+ const path = resolve(output, `${apiModule.name}.${ts2 ? "ts" : "js"}`);
239
240
  const shouldSkip = (!overrides || isArray(overrides) && !overrides.includes(apiModule.name)) && fse.existsSync(path);
240
241
  if (shouldSkip) {
241
242
  logger.warn(`File already exists, skip: ${path}`);
@@ -250,9 +251,17 @@ function renderApiModules(apiModules, options) {
250
251
  )
251
252
  );
252
253
  }
253
- async function generateTypes(schema, output, typesFilename) {
254
+ async function generateTypes(schema, output, typesFilename, openapiTsOptions) {
255
+ const BLOB = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Blob"));
256
+ const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull());
254
257
  const ast = await openapiTS(schema, {
255
- defaultNonNullable: false
258
+ defaultNonNullable: false,
259
+ transform(schemaObject) {
260
+ if (schemaObject.format === "binary") {
261
+ return schemaObject.nullable ? ts.factory.createUnionTypeNode([BLOB, NULL]) : BLOB;
262
+ }
263
+ },
264
+ ...openapiTsOptions
256
265
  });
257
266
  const contents = astToString(ast);
258
267
  const typesFilepath = resolve(CWD, output, typesFilename);
@@ -264,7 +273,7 @@ async function generate(userOptions = {}) {
264
273
  const options = merge(config, userOptions);
265
274
  const {
266
275
  base,
267
- ts = true,
276
+ ts: ts2 = true,
268
277
  typesOnly = false,
269
278
  overrides = true,
270
279
  preset = "axle",
@@ -273,13 +282,14 @@ async function generate(userOptions = {}) {
273
282
  typesFilename = "_types.ts",
274
283
  validateStatus = (status) => status >= 200 && status < 300,
275
284
  transformer = {},
276
- uncountableNouns = []
285
+ uncountableNouns = [],
286
+ openapiTsOptions = {}
277
287
  } = options;
278
288
  const mergedTransformer = { ...createTransformer(), ...transformer };
279
289
  const schema = await readSchema(input);
280
290
  logger.info("Generating API modules...");
281
- if (ts) {
282
- await generateTypes(schema, output, typesFilename);
291
+ if (ts2) {
292
+ await generateTypes(schema, output, typesFilename, openapiTsOptions);
283
293
  }
284
294
  const apiModules = partitionApiModules(schema, {
285
295
  base,
@@ -287,7 +297,7 @@ async function generate(userOptions = {}) {
287
297
  transformer: mergedTransformer,
288
298
  validateStatus
289
299
  });
290
- await renderApiModules(apiModules, { output, typesFilename, ts, typesOnly, overrides, preset });
300
+ await renderApiModules(apiModules, { output, typesFilename, ts: ts2, typesOnly, overrides, preset });
291
301
  logger.success("Done");
292
302
  }
293
303
 
package/dist/cli.cjs CHANGED
@@ -102,7 +102,7 @@ function getResponseMetadataItems(operation, validateStatus) {
102
102
  const validStatusResults = Object.keys(responses).sort((a, b) => Number(a) - Number(b)).filter((key) => validateStatus(Number(key))).map(Number);
103
103
  const metadataItems = validStatusResults.map((status) => {
104
104
  const content = operation.responses?.[status]?.content ?? {};
105
- const responseContentType = findObjectKey(content, ["application/json", "*/*"]);
105
+ const responseContentType = findObjectKey(content, ["application/json", "application/octet-stream", "*/*"]);
106
106
  return {
107
107
  status,
108
108
  responseContentType
@@ -345,7 +345,7 @@ function partitionApiModules(schema, options) {
345
345
  return apiModules;
346
346
  }
347
347
  function renderApiModules(apiModules, options) {
348
- const { output, ts, typesOnly, overrides, preset } = options;
348
+ const { output, ts: ts2, typesOnly, overrides, preset } = options;
349
349
  const templateFile = readTemplateFile(preset);
350
350
  const typesFilename = options.typesFilename.replace(".ts", "");
351
351
  return Promise.all(
@@ -354,7 +354,7 @@ function renderApiModules(apiModules, options) {
354
354
  const data = {
355
355
  apiModule,
356
356
  typesFilename,
357
- ts,
357
+ ts: ts2,
358
358
  typesOnly
359
359
  };
360
360
  import_prettier.default.format(import_ejs.default.render(templateFile, data), {
@@ -363,7 +363,7 @@ function renderApiModules(apiModules, options) {
363
363
  singleQuote: true,
364
364
  printWidth: 120
365
365
  }).then((content) => {
366
- const path = (0, import_path3.resolve)(output, `${apiModule.name}.${ts ? "ts" : "js"}`);
366
+ const path = (0, import_path3.resolve)(output, `${apiModule.name}.${ts2 ? "ts" : "js"}`);
367
367
  const shouldSkip = (!overrides || (0, import_rattail3.isArray)(overrides) && !overrides.includes(apiModule.name)) && import_fs_extra2.default.existsSync(path);
368
368
  if (shouldSkip) {
369
369
  import_rslog2.logger.warn(`File already exists, skip: ${path}`);
@@ -378,9 +378,17 @@ function renderApiModules(apiModules, options) {
378
378
  )
379
379
  );
380
380
  }
381
- async function generateTypes(schema, output, typesFilename) {
381
+ async function generateTypes(schema, output, typesFilename, openapiTsOptions) {
382
+ const BLOB = import_typescript.default.factory.createTypeReferenceNode(import_typescript.default.factory.createIdentifier("Blob"));
383
+ const NULL = import_typescript.default.factory.createLiteralTypeNode(import_typescript.default.factory.createNull());
382
384
  const ast = await (0, import_openapi_typescript.default)(schema, {
383
- defaultNonNullable: false
385
+ defaultNonNullable: false,
386
+ transform(schemaObject) {
387
+ if (schemaObject.format === "binary") {
388
+ return schemaObject.nullable ? import_typescript.default.factory.createUnionTypeNode([BLOB, NULL]) : BLOB;
389
+ }
390
+ },
391
+ ...openapiTsOptions
384
392
  });
385
393
  const contents = (0, import_openapi_typescript.astToString)(ast);
386
394
  const typesFilepath = (0, import_path3.resolve)(CWD, output, typesFilename);
@@ -392,7 +400,7 @@ async function generate(userOptions = {}) {
392
400
  const options = (0, import_rattail3.merge)(config, userOptions);
393
401
  const {
394
402
  base,
395
- ts = true,
403
+ ts: ts2 = true,
396
404
  typesOnly = false,
397
405
  overrides = true,
398
406
  preset = "axle",
@@ -401,13 +409,14 @@ async function generate(userOptions = {}) {
401
409
  typesFilename = "_types.ts",
402
410
  validateStatus = (status) => status >= 200 && status < 300,
403
411
  transformer = {},
404
- uncountableNouns = []
412
+ uncountableNouns = [],
413
+ openapiTsOptions = {}
405
414
  } = options;
406
415
  const mergedTransformer = { ...createTransformer(), ...transformer };
407
416
  const schema = await readSchema(input);
408
417
  import_rslog2.logger.info("Generating API modules...");
409
- if (ts) {
410
- await generateTypes(schema, output, typesFilename);
418
+ if (ts2) {
419
+ await generateTypes(schema, output, typesFilename, openapiTsOptions);
411
420
  }
412
421
  const apiModules = partitionApiModules(schema, {
413
422
  base,
@@ -415,10 +424,10 @@ async function generate(userOptions = {}) {
415
424
  transformer: mergedTransformer,
416
425
  validateStatus
417
426
  });
418
- await renderApiModules(apiModules, { output, typesFilename, ts, typesOnly, overrides, preset });
427
+ await renderApiModules(apiModules, { output, typesFilename, ts: ts2, typesOnly, overrides, preset });
419
428
  import_rslog2.logger.success("Done");
420
429
  }
421
- var import_path3, import_ejs, import_fs_extra2, import_openapi_typescript, import_prettier, import_rattail3, import_rslog2;
430
+ var import_path3, import_ejs, import_fs_extra2, import_openapi_typescript, import_prettier, import_rattail3, import_rslog2, import_typescript;
422
431
  var init_generate = __esm({
423
432
  "src/generate.ts"() {
424
433
  "use strict";
@@ -430,6 +439,7 @@ var init_generate = __esm({
430
439
  import_prettier = __toESM(require("prettier"), 1);
431
440
  import_rattail3 = require("rattail");
432
441
  import_rslog2 = require("rslog");
442
+ import_typescript = __toESM(require("typescript"), 1);
433
443
  init_config();
434
444
  init_constants();
435
445
  init_transformer();
package/dist/cli.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getCliVersion
4
- } from "./chunk-56NOW5DM.js";
4
+ } from "./chunk-2227C45C.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
8
8
  var program = new Command();
9
9
  program.version(getCliVersion());
10
10
  program.action(async () => {
11
- const { generate } = await import("./generate-BJMNBKQH.js");
11
+ const { generate } = await import("./generate-WIU5E7EL.js");
12
12
  return generate();
13
13
  });
14
14
  program.parse();
@@ -4,8 +4,8 @@ import {
4
4
  partitionApiModules,
5
5
  renderApiModules,
6
6
  transformPayloads
7
- } from "./chunk-XM4XA35S.js";
8
- import "./chunk-56NOW5DM.js";
7
+ } from "./chunk-P3SVS555.js";
8
+ import "./chunk-2227C45C.js";
9
9
  export {
10
10
  generate,
11
11
  generateTypes,
package/dist/index.cjs CHANGED
@@ -185,6 +185,7 @@ var import_openapi_typescript = __toESM(require("openapi-typescript"), 1);
185
185
  var import_prettier = __toESM(require("prettier"), 1);
186
186
  var import_rattail3 = require("rattail");
187
187
  var import_rslog2 = require("rslog");
188
+ var import_typescript = __toESM(require("typescript"), 1);
188
189
 
189
190
  // src/config.ts
190
191
  var import_unconfig = require("unconfig");
@@ -302,7 +303,7 @@ function getResponseMetadataItems(operation, validateStatus) {
302
303
  const validStatusResults = Object.keys(responses).sort((a, b) => Number(a) - Number(b)).filter((key) => validateStatus(Number(key))).map(Number);
303
304
  const metadataItems = validStatusResults.map((status) => {
304
305
  const content = operation.responses?.[status]?.content ?? {};
305
- const responseContentType = findObjectKey(content, ["application/json", "*/*"]);
306
+ const responseContentType = findObjectKey(content, ["application/json", "application/octet-stream", "*/*"]);
306
307
  return {
307
308
  status,
308
309
  responseContentType
@@ -385,7 +386,7 @@ function partitionApiModules(schema, options) {
385
386
  return apiModules;
386
387
  }
387
388
  function renderApiModules(apiModules, options) {
388
- const { output, ts, typesOnly, overrides, preset } = options;
389
+ const { output, ts: ts2, typesOnly, overrides, preset } = options;
389
390
  const templateFile = readTemplateFile(preset);
390
391
  const typesFilename = options.typesFilename.replace(".ts", "");
391
392
  return Promise.all(
@@ -394,7 +395,7 @@ function renderApiModules(apiModules, options) {
394
395
  const data = {
395
396
  apiModule,
396
397
  typesFilename,
397
- ts,
398
+ ts: ts2,
398
399
  typesOnly
399
400
  };
400
401
  import_prettier.default.format(import_ejs.default.render(templateFile, data), {
@@ -403,7 +404,7 @@ function renderApiModules(apiModules, options) {
403
404
  singleQuote: true,
404
405
  printWidth: 120
405
406
  }).then((content) => {
406
- const path = (0, import_path3.resolve)(output, `${apiModule.name}.${ts ? "ts" : "js"}`);
407
+ const path = (0, import_path3.resolve)(output, `${apiModule.name}.${ts2 ? "ts" : "js"}`);
407
408
  const shouldSkip = (!overrides || (0, import_rattail3.isArray)(overrides) && !overrides.includes(apiModule.name)) && import_fs_extra2.default.existsSync(path);
408
409
  if (shouldSkip) {
409
410
  import_rslog2.logger.warn(`File already exists, skip: ${path}`);
@@ -418,9 +419,17 @@ function renderApiModules(apiModules, options) {
418
419
  )
419
420
  );
420
421
  }
421
- async function generateTypes(schema, output, typesFilename) {
422
+ async function generateTypes(schema, output, typesFilename, openapiTsOptions) {
423
+ const BLOB = import_typescript.default.factory.createTypeReferenceNode(import_typescript.default.factory.createIdentifier("Blob"));
424
+ const NULL = import_typescript.default.factory.createLiteralTypeNode(import_typescript.default.factory.createNull());
422
425
  const ast = await (0, import_openapi_typescript.default)(schema, {
423
- defaultNonNullable: false
426
+ defaultNonNullable: false,
427
+ transform(schemaObject) {
428
+ if (schemaObject.format === "binary") {
429
+ return schemaObject.nullable ? import_typescript.default.factory.createUnionTypeNode([BLOB, NULL]) : BLOB;
430
+ }
431
+ },
432
+ ...openapiTsOptions
424
433
  });
425
434
  const contents = (0, import_openapi_typescript.astToString)(ast);
426
435
  const typesFilepath = (0, import_path3.resolve)(CWD, output, typesFilename);
@@ -432,7 +441,7 @@ async function generate(userOptions = {}) {
432
441
  const options = (0, import_rattail3.merge)(config, userOptions);
433
442
  const {
434
443
  base,
435
- ts = true,
444
+ ts: ts2 = true,
436
445
  typesOnly = false,
437
446
  overrides = true,
438
447
  preset = "axle",
@@ -441,13 +450,14 @@ async function generate(userOptions = {}) {
441
450
  typesFilename = "_types.ts",
442
451
  validateStatus = (status) => status >= 200 && status < 300,
443
452
  transformer = {},
444
- uncountableNouns = []
453
+ uncountableNouns = [],
454
+ openapiTsOptions = {}
445
455
  } = options;
446
456
  const mergedTransformer = { ...createTransformer(), ...transformer };
447
457
  const schema = await readSchema(input);
448
458
  import_rslog2.logger.info("Generating API modules...");
449
- if (ts) {
450
- await generateTypes(schema, output, typesFilename);
459
+ if (ts2) {
460
+ await generateTypes(schema, output, typesFilename, openapiTsOptions);
451
461
  }
452
462
  const apiModules = partitionApiModules(schema, {
453
463
  base,
@@ -455,7 +465,7 @@ async function generate(userOptions = {}) {
455
465
  transformer: mergedTransformer,
456
466
  validateStatus
457
467
  });
458
- await renderApiModules(apiModules, { output, typesFilename, ts, typesOnly, overrides, preset });
468
+ await renderApiModules(apiModules, { output, typesFilename, ts: ts2, typesOnly, overrides, preset });
459
469
  import_rslog2.logger.success("Done");
460
470
  }
461
471
 
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { OpenAPI3, RequestBodyObject, ReferenceObject, OperationObject } from 'openapi-typescript';
1
+ import { OpenAPI3, RequestBodyObject, ReferenceObject, OperationObject, OpenAPITSOptions } from 'openapi-typescript';
2
2
  export { default as pluralize } from 'pluralize';
3
3
 
4
4
  type Preset = 'axle' | 'axios';
@@ -285,6 +285,10 @@ interface GenerateOptions {
285
285
  * Certain uncountable nouns that do not change from singular to plural
286
286
  */
287
287
  uncountableNouns?: string[];
288
+ /**
289
+ * A function to transform the generated types AST before printing to string.
290
+ */
291
+ openapiTsOptions?: OpenAPITSOptions;
288
292
  }
289
293
  declare function transformPayloads(pathItems: Record<string, OperationObject>, options: {
290
294
  path: string;
@@ -308,7 +312,7 @@ declare function renderApiModules(apiModules: ApiModule[], options: {
308
312
  overrides: boolean | string[];
309
313
  preset: Preset;
310
314
  }): Promise<unknown[]>;
311
- declare function generateTypes(schema: OpenAPI3, output: string, typesFilename: string): Promise<void>;
315
+ declare function generateTypes(schema: OpenAPI3, output: string, typesFilename: string, openapiTsOptions: OpenAPITSOptions): Promise<void>;
312
316
  declare function generate(userOptions?: GenerateOptions): Promise<void>;
313
317
 
314
318
  type Config = GenerateOptions;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { OpenAPI3, RequestBodyObject, ReferenceObject, OperationObject } from 'openapi-typescript';
1
+ import { OpenAPI3, RequestBodyObject, ReferenceObject, OperationObject, OpenAPITSOptions } from 'openapi-typescript';
2
2
  export { default as pluralize } from 'pluralize';
3
3
 
4
4
  type Preset = 'axle' | 'axios';
@@ -285,6 +285,10 @@ interface GenerateOptions {
285
285
  * Certain uncountable nouns that do not change from singular to plural
286
286
  */
287
287
  uncountableNouns?: string[];
288
+ /**
289
+ * A function to transform the generated types AST before printing to string.
290
+ */
291
+ openapiTsOptions?: OpenAPITSOptions;
288
292
  }
289
293
  declare function transformPayloads(pathItems: Record<string, OperationObject>, options: {
290
294
  path: string;
@@ -308,7 +312,7 @@ declare function renderApiModules(apiModules: ApiModule[], options: {
308
312
  overrides: boolean | string[];
309
313
  preset: Preset;
310
314
  }): Promise<unknown[]>;
311
- declare function generateTypes(schema: OpenAPI3, output: string, typesFilename: string): Promise<void>;
315
+ declare function generateTypes(schema: OpenAPI3, output: string, typesFilename: string, openapiTsOptions: OpenAPITSOptions): Promise<void>;
312
316
  declare function generate(userOptions?: GenerateOptions): Promise<void>;
313
317
 
314
318
  type Config = GenerateOptions;
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  transformTypeValue,
22
22
  transformUrl,
23
23
  transformVerb
24
- } from "./chunk-XM4XA35S.js";
24
+ } from "./chunk-P3SVS555.js";
25
25
  import {
26
26
  createStatusCodesByStrategy,
27
27
  findObjectKey,
@@ -34,7 +34,7 @@ import {
34
34
  readSchema,
35
35
  readSchemaContent,
36
36
  readTemplateFile
37
- } from "./chunk-56NOW5DM.js";
37
+ } from "./chunk-2227C45C.js";
38
38
 
39
39
  // src/index.ts
40
40
  import { default as default2 } from "pluralize";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-farmer",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "API module generation tool based on Openapi3/Swagger2.",
5
5
  "keywords": [
6
6
  "cli",
@@ -78,7 +78,7 @@
78
78
  "typescript": "5.3.3"
79
79
  },
80
80
  "peerDependencies": {
81
- "eslint": "^9.17.0"
81
+ "typescript": "^5.3.3"
82
82
  },
83
83
  "engines": {
84
84
  "pnpm": ">=9.0"