@map-colonies/openapi-helpers 3.0.0 → 4.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/README.md CHANGED
@@ -9,22 +9,132 @@ Run the following commands:
9
9
  npm install --save-dev @map-colonies/openapi-helpers supertest prettier openapi-typescript @types/express
10
10
  ```
11
11
 
12
- ## types-generator
13
- The package contains a script that wraps the `openapi-typescript` package and generates types for the OpenAPI schema. The script also formats the generated types using `prettier`.
14
12
 
15
- The command structure is as follows:
13
+ ## CLI Usage
14
+
15
+ The package provides a unified CLI for generating TypeScript types and error classes from OpenAPI specifications. All code generation is now performed using the `generate` command, which supports subcommands for types and errors.
16
+
17
+ #### CLI Arguments Reference
18
+
19
+ **Positional Arguments:**
20
+ For both `generate types` and `generate errors` commands, the positional arguments are:
21
+
22
+ - `<openapi-file>`: Path to the OpenAPI YAML or JSON file to use as the source schema.
23
+ - `<output-file>`: Path to the file where the generated code will be written.
24
+
25
+ These arguments are required and must be provided in the order shown.
26
+
27
+ **Optional Arguments:**
28
+
29
+ For `generate types`:
30
+ - `-f, --format`: Format the generated types using Prettier
31
+ - `-t, --add-typed-request-handler`: Add the TypedRequestHandler type to the generated types
32
+
33
+ For `generate errors`:
34
+ - `-f, --format`: Format the generated code using Prettier
35
+ - `-e, --errors-output <all|map|classes>`: Specify what to generate (default: all)
36
+ - `all`: generate both error classes and error code mapping
37
+ - `map`: generate only the error code mapping
38
+ - `classes`: generate only the error classes
39
+
40
+ ### Generate Types
41
+
42
+ Generate TypeScript types from an OpenAPI schema:
16
43
  ```bash
17
- npx @map-colonies/openapi-helpers <input-file> <output-file> --format --add-typed-request-handler
44
+ npx @map-colonies/openapi-helpers generate types <openapi-file> <output-file> [options]
18
45
  ```
19
46
 
20
47
  For example:
21
48
  ```bash
22
- npx @map-colonies/openapi-helpers ./openapi3.yaml ./src/openapi.d.ts --format --add-typed-request-handler
49
+ npx @map-colonies/openapi-helpers generate types ./openapi3.yaml ./src/openapi.d.ts --format --add-typed-request-handler
50
+ ```
51
+
52
+ Options:
53
+ - `-f, --format` - Format the generated types using `prettier`.
54
+ - `-t, --add-typed-request-handler` - Add the `TypedRequestHandler` type to the generated types.
55
+
56
+ ### Generate Errors
57
+
58
+ Generate error classes and error code mappings from an OpenAPI schema:
59
+ ```bash
60
+ npx @map-colonies/openapi-helpers generate errors <openapi-file> <output-file> [options]
61
+ ```
62
+
63
+ For example:
64
+ ```bash
65
+ npx @map-colonies/openapi-helpers generate errors ./openapi3.yaml ./src/errors.ts --format
66
+ ```
67
+
68
+
69
+ Options:
70
+ - `-f, --format` - Format the generated code using `prettier`.
71
+ - `-e, --errors-output <all|map|classes>` - Specify what to generate:
72
+ - `all` (default): generate both error classes and error code mapping
73
+ - `map`: generate only the error code mapping
74
+ - `classes`: generate only the error classes
75
+
76
+ ### Help and Examples
77
+
78
+ To see all available commands and options:
79
+ ```bash
80
+ npx @map-colonies/openapi-helpers --help
81
+ npx @map-colonies/openapi-helpers generate --help
82
+ npx @map-colonies/openapi-helpers generate types --help
83
+ npx @map-colonies/openapi-helpers generate errors --help
84
+ ```
85
+
86
+
87
+ #### Example: Run all generations
88
+
89
+ You can run both types and errors generation in sequence:
90
+ ```bash
91
+ npx @map-colonies/openapi-helpers generate types ./openapi3.yaml ./src/openapi.d.ts --format --add-typed-request-handler
92
+ npx @map-colonies/openapi-helpers generate errors ./openapi3.yaml ./src/errors.ts --format --errors-output all
93
+ ```
94
+
95
+
96
+
97
+ ## Programmatic Support
98
+
99
+
100
+ > [!NOTE]
101
+ > **Programmatic usage of the CLI (importing and using the generators directly) is only supported in ECMAScript modules (ESM).** CommonJS is not supported for direct imports.
102
+
103
+ The code generators (`generateTypes.mts` and `generateErrors.mts`) now support functional programming patterns. You can inject custom transformation logic or AST manipulation by providing functional arguments, making the generators more flexible and composable for advanced use cases.
104
+
105
+
106
+ ### API Usage
107
+
108
+ You can import and use the generators directly in your own scripts for full functional programming flexibility:
109
+
110
+ ```typescript
111
+ import { generateTypes, generateErrors } from '@map-colonies/openapi-helpers/generators';
112
+
113
+ // Generate types
114
+ await generateTypes(
115
+ 'openapi3.yaml',
116
+ 'src/openapi.d.ts',
117
+ {
118
+ shouldFormat: true,
119
+ addTypedRequestHandler: true,
120
+ // inject?: string,
121
+ // transform?: (schemaObject, metadata) => ...
122
+ }
123
+ );
124
+
125
+ // Generate errors
126
+ await generateErrors(
127
+ 'openapi3.yaml',
128
+ 'src/errors.ts',
129
+ {
130
+ shouldFormat: true,
131
+ includeMapping: true,
132
+ includeErrorClasses: true
133
+ }
134
+ );
23
135
  ```
24
136
 
25
- ### options
26
- - `--format` - format the generated types using `prettier`.
27
- - `--add-typed-request-handler` - add the `TypedRequestHandler` type to the generated types.
137
+ You can pass custom `inject` or `transform` functions to `generateTypes` for advanced AST/code manipulation, enabling highly composable and functional workflows.
28
138
 
29
139
  ## TypedRequestHandler
30
140
  The package contains a wrapper for the `express` types package that provides autocomplete for all the request handlers to the API based on the OpenAPI schema. The TypedRequestHandler is initialized with the types generated by `openapi-typescript`, and is configured based on operation name or method and path.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import { setTimeout as sleep } from 'node:timers/promises';
3
+ import { program } from '@commander-js/extra-typings';
4
+ import { generateTypes } from '../generator/generateTypes.mjs';
5
+ import { generateErrors } from '../generator/generateErrors.mjs';
6
+ import ora from 'ora';
7
+ import { PACKAGE_VERSION } from '../common/constants.js';
8
+ const errorOutput = ['all', 'map', 'classes'];
9
+ function isErrorsOutput(value) {
10
+ return errorOutput.includes(value);
11
+ }
12
+ const SECOND = 1000;
13
+ program.name('openapi-helpers').description('Generate TypeScript types and error classes from OpenAPI specifications').version(PACKAGE_VERSION);
14
+ const command = program.command('generate').description('Generate code artifacts (types, error classes) from OpenAPI specifications');
15
+ command
16
+ .command('types')
17
+ .description('Generate TypeScript types from OpenAPI spec')
18
+ .argument('<openapiPath>', 'Path to the OpenAPI specification file')
19
+ .argument('<destinationPath>', 'Path where the generated types will be saved')
20
+ .option('-f, --format', 'Format the generated code using Prettier')
21
+ .option('-t, --add-typed-request-handler', 'Add typed request handler types to the generated output')
22
+ .action(async (openapiPath, destinationPath, options) => {
23
+ try {
24
+ const spinner = ora('Generating types').start();
25
+ await generateTypes(openapiPath, destinationPath, { shouldFormat: options.format, addTypedRequestHandler: options.addTypedRequestHandler });
26
+ await sleep(SECOND);
27
+ spinner.stop();
28
+ console.log('Types generated successfully');
29
+ }
30
+ catch (error) {
31
+ console.error('Error generating types:', error);
32
+ process.exit(1);
33
+ }
34
+ });
35
+ command
36
+ .command('errors')
37
+ .description('Generate error classes from OpenAPI spec')
38
+ .argument('<openapiPath>', 'Path to the OpenAPI specification file')
39
+ .argument('<destinationPath>', 'Path where the generated error classes will be saved')
40
+ .option('-f, --format', 'Format the generated code using Prettier')
41
+ .option('-e, --errors-output <all|map|classes>', 'Specify the errors output type', 'all')
42
+ .action(async (openapiPath, destinationPath, options) => {
43
+ try {
44
+ if (!isErrorsOutput(options.errorsOutput)) {
45
+ console.error(`Invalid errors output type: ${options.errorsOutput}`);
46
+ process.exit(1);
47
+ }
48
+ const includeMapping = options.errorsOutput === 'map' || options.errorsOutput === 'all';
49
+ const includeErrorClasses = options.errorsOutput === 'classes' || options.errorsOutput === 'all';
50
+ const spinner = ora('Generating errors').start();
51
+ await generateErrors(openapiPath, destinationPath, {
52
+ shouldFormat: options.format,
53
+ includeMapping,
54
+ includeErrorClasses,
55
+ });
56
+ await sleep(SECOND);
57
+ spinner.stop();
58
+ console.log('Errors generated successfully');
59
+ }
60
+ catch (error) {
61
+ console.error('Error generating errors:', error);
62
+ process.exit(1);
63
+ }
64
+ });
65
+ // Add examples to the help
66
+ program.addHelpText('after', `
67
+ Examples:
68
+ $ openapi-helpers generate types api.yaml types.ts
69
+ $ openapi-helpers generate types api.yaml types.ts --format
70
+ $ openapi-helpers generate types api.yaml types.ts --add-typed-request-handler
71
+ $ openapi-helpers generate types api.yaml types.ts --add-typed-request-handler --format
72
+ $ openapi-helpers generate errors api.yaml errors.ts
73
+ $ openapi-helpers generate errors api.yaml errors.ts --format
74
+ $ openapi-helpers generate errors api.yaml errors.ts --no-mapping
75
+ $ openapi-helpers generate errors api.yaml errors.ts --no-error-classes
76
+ $ openapi-helpers generate errors api.yaml errors.ts --no-mapping --no-error-classes
77
+ $ openapi-helpers --help
78
+ $ openapi-helpers generate --help
79
+ $ openapi-helpers generate types --help
80
+ $ openapi-helpers generate errors --help
81
+ `);
82
+ program.parse();
83
+ //# sourceMappingURL=entrypoint.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entrypoint.mjs","sourceRoot":"","sources":["../../src/cli/entrypoint.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ declare const PACKAGE_VERSION: string;
2
+ export { PACKAGE_VERSION };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PACKAGE_VERSION = void 0;
4
+ const read_pkg_1 = require("@map-colonies/read-pkg");
5
+ const packageJson = (0, read_pkg_1.readPackageJsonSync)();
6
+ const PACKAGE_VERSION = packageJson.version ?? 'unknown';
7
+ exports.PACKAGE_VERSION = PACKAGE_VERSION;
8
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":";;;AAAA,qDAA6D;AAE7D,MAAM,WAAW,GAAG,IAAA,8BAAmB,GAAE,CAAC;AAC1C,MAAM,eAAe,GAAG,WAAW,CAAC,OAAO,IAAI,SAAS,CAAC;AAChD,0CAAe"}
@@ -0,0 +1,5 @@
1
+ export declare function generateErrors(openapiPath: string, destinationPath: string, options: {
2
+ shouldFormat?: boolean;
3
+ includeMapping?: boolean;
4
+ includeErrorClasses?: boolean;
5
+ }): Promise<void>;
@@ -0,0 +1,104 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { dereference } from '@apidevtools/json-schema-ref-parser';
4
+ import { format, resolveConfig } from 'prettier';
5
+ import * as changeCase from 'change-case';
6
+ const ESLINT_DISABLE = '/* eslint-disable */\n';
7
+ const FILE_HEADER = `${ESLINT_DISABLE}// This file was auto-generated. Do not edit manually.
8
+ // To update, run the error generation script again.\n\n`;
9
+ function createError(code) {
10
+ let className = changeCase.pascalCase(code);
11
+ if (!className.endsWith('Error')) {
12
+ className += 'Error';
13
+ }
14
+ return `export class ${className} extends Error {
15
+ public readonly code = '${code}';
16
+ /**
17
+ * Creates an instance of ${className}.
18
+ * @param message - The error message.
19
+ * @param cause - Optional original error or server response data.
20
+ */
21
+ public constructor(message: string, cause?: unknown) {
22
+ super(message, { cause });
23
+ Object.setPrototypeOf(this, new.target.prototype);
24
+ }
25
+ };\n`;
26
+ }
27
+ function buildErrorMapping(errorCodes) {
28
+ return Array.from(errorCodes)
29
+ .map((code) => `'${code}': '${code}'`)
30
+ .join(', ');
31
+ }
32
+ export async function generateErrors(openapiPath, destinationPath, options) {
33
+ const openapi = await dereference(openapiPath);
34
+ if (openapi.paths === undefined) {
35
+ console.error('No paths found in the OpenAPI document.');
36
+ process.exit(1);
37
+ }
38
+ const errorCodes = new Set();
39
+ function extractCodeFromSchema(schema) {
40
+ // Handle direct code property
41
+ if (schema.type === 'object' && schema.properties?.code) {
42
+ const codeProperty = schema.properties.code;
43
+ // Handle enum values
44
+ if (codeProperty.enum) {
45
+ codeProperty.enum.map(String).forEach((code) => {
46
+ errorCodes.add(code);
47
+ });
48
+ }
49
+ }
50
+ // Handle allOf combinations
51
+ if (schema.allOf) {
52
+ for (const subSchema of schema.allOf) {
53
+ extractCodeFromSchema(subSchema);
54
+ }
55
+ }
56
+ // Handle oneOf combinations
57
+ if (schema.oneOf) {
58
+ for (const subSchema of schema.oneOf) {
59
+ extractCodeFromSchema(subSchema);
60
+ }
61
+ }
62
+ // Handle anyOf combinations
63
+ if (schema.anyOf) {
64
+ for (const subSchema of schema.anyOf) {
65
+ extractCodeFromSchema(subSchema);
66
+ }
67
+ }
68
+ }
69
+ for (const [, methods] of Object.entries(openapi.paths)) {
70
+ for (const [key, operation] of Object.entries(methods)) {
71
+ if (['servers', 'parameters'].includes(key)) {
72
+ continue;
73
+ }
74
+ for (const [statusCode, response] of Object.entries(operation.responses ?? {})) {
75
+ if (statusCode.startsWith('2') || statusCode.startsWith('3')) {
76
+ continue; // Skip successful and redirection responses
77
+ }
78
+ const schema = response.content?.['application/json']?.schema;
79
+ if (schema) {
80
+ extractCodeFromSchema(schema);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ if (errorCodes.size === 0) {
86
+ console.warn('No error codes found in the OpenAPI document.');
87
+ process.exit(0);
88
+ }
89
+ let errorFile = FILE_HEADER;
90
+ if (options.includeErrorClasses === true) {
91
+ errorFile += errorCodes.values().map(createError).toArray().join('\n');
92
+ }
93
+ if (options.includeMapping === true) {
94
+ errorFile += ` export const API_ERRORS_MAP = { ${buildErrorMapping(errorCodes)} } as const;\n`;
95
+ }
96
+ if (options.shouldFormat === true) {
97
+ const prettierOptions = await resolveConfig('./src/index.ts');
98
+ errorFile = await format(errorFile, { ...prettierOptions, parser: 'typescript' });
99
+ }
100
+ const directory = path.dirname(destinationPath);
101
+ await fs.mkdir(directory, { recursive: true });
102
+ await fs.writeFile(destinationPath, errorFile);
103
+ }
104
+ //# sourceMappingURL=generateErrors.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateErrors.mjs","sourceRoot":"","sources":["../../src/generator/generateErrors.mts"],"names":[],"mappings":"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"}
@@ -1,2 +1,9 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ import { SchemaObject, TransformNodeOptions, TransformObject } from 'openapi-typescript';
3
+ import { TypeNode } from 'typescript';
4
+ export declare function generateTypes(openapiPath: string, destinationPath: string, options: {
5
+ shouldFormat?: boolean;
6
+ addTypedRequestHandler?: boolean;
7
+ inject?: string;
8
+ transform?: (schemaObject: SchemaObject, metadata: TransformNodeOptions) => TypeNode | TransformObject | undefined;
9
+ }): Promise<void>;
@@ -1,35 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs/promises';
3
- import { parseArgs } from 'node:util';
4
3
  import { format, resolveConfig } from 'prettier';
5
4
  import openapiTS, { astToString } from 'openapi-typescript';
6
- const ARGS_SLICE = 2;
7
- const { values: { format: shouldFormat, 'add-typed-request-handler': addTypedRequestHandler }, positionals, } = parseArgs({
8
- args: process.argv.slice(ARGS_SLICE),
9
- options: {
10
- format: { type: 'boolean', alias: 'f' },
11
- 'add-typed-request-handler': { type: 'boolean', alias: 't' },
12
- },
13
- allowPositionals: true,
14
- });
15
- const [openapiPath, destinationPath] = positionals;
16
- if (openapiPath === undefined || destinationPath === undefined) {
17
- console.error('Usage: generateTypes <openapiPath> <destinationPath>');
18
- process.exit(1);
19
- }
20
5
  const ESLINT_DISABLE = '/* eslint-disable */\n';
6
+ const FILE_HEADER = `${ESLINT_DISABLE}// This file was auto-generated. Do not edit manually.
7
+ // To update, run the error generation script again.\n\n`;
21
8
  const typedRequestHandlerImport = "import type { TypedRequestHandlers as ImportedTypedRequestHandlers } from '@map-colonies/openapi-helpers/typedRequestHandler';\n";
22
9
  const exportTypedRequestHandlers = 'export type TypedRequestHandlers = ImportedTypedRequestHandlers<paths, operations>;\n';
23
- const ast = await openapiTS(await fs.readFile(openapiPath, 'utf-8'), { exportType: true });
24
- let content = astToString(ast);
25
- if (addTypedRequestHandler === true) {
26
- content = typedRequestHandlerImport + content + exportTypedRequestHandlers;
27
- }
28
- content = ESLINT_DISABLE + content;
29
- if (shouldFormat === true) {
30
- const prettierOptions = await resolveConfig('./src/index.ts');
31
- content = await format(content, { ...prettierOptions, parser: 'typescript' });
10
+ export async function generateTypes(openapiPath, destinationPath, options) {
11
+ const ast = await openapiTS(await fs.readFile(openapiPath, 'utf-8'), { exportType: true, inject: options.inject, transform: options.transform });
12
+ let content = astToString(ast);
13
+ if (options.addTypedRequestHandler === true) {
14
+ content = typedRequestHandlerImport + content + exportTypedRequestHandlers;
15
+ }
16
+ content = FILE_HEADER + content;
17
+ if (options.shouldFormat === true) {
18
+ const prettierOptions = await resolveConfig('./src/index.ts');
19
+ content = await format(content, { ...prettierOptions, parser: 'typescript' });
20
+ }
21
+ await fs.writeFile(destinationPath, content);
32
22
  }
33
- await fs.writeFile(destinationPath, content);
34
- console.log('Types generated successfully');
35
23
  //# sourceMappingURL=generateTypes.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateTypes.mjs","sourceRoot":"","sources":["../../src/generator/generateTypes.mts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,UAAU,GAAG,CAAC,CAAC;AAErB,MAAM,EACJ,MAAM,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,EACrF,WAAW,GACZ,GAAG,SAAS,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;IACpC,OAAO,EAAE;QACP,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;QACvC,2BAA2B,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;KAC7D;IACD,gBAAgB,EAAE,IAAI;CACvB,CAAC,CAAC;AAEH,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,GAAG,WAAW,CAAC;AAEnD,IAAI,WAAW,KAAK,SAAS,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;IAC/D,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;IACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,cAAc,GAAG,wBAAwB,CAAC;AAEhD,MAAM,yBAAyB,GAC7B,kIAAkI,CAAC;AACrI,MAAM,0BAA0B,GAAG,uFAAuF,CAAC;AAE3H,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;AAE3F,IAAI,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;AAE/B,IAAI,sBAAsB,KAAK,IAAI,EAAE,CAAC;IACpC,OAAO,GAAG,yBAAyB,GAAG,OAAO,GAAG,0BAA0B,CAAC;AAC7E,CAAC;AAED,OAAO,GAAG,cAAc,GAAG,OAAO,CAAC;AAEnC,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;IAC1B,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAE9D,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AAE7C,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC"}
1
+ {"version":3,"file":"generateTypes.mjs","sourceRoot":"","sources":["../../src/generator/generateTypes.mts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,SAAS,EAAE,EAAE,WAAW,EAAuD,MAAM,oBAAoB,CAAC;AAGjH,MAAM,cAAc,GAAG,wBAAwB,CAAC;AAChD,MAAM,WAAW,GAAG,GAAG,cAAc;yDACoB,CAAC;AAE1D,MAAM,yBAAyB,GAC7B,kIAAkI,CAAC;AACrI,MAAM,0BAA0B,GAAG,uFAAuF,CAAC;AAE3H,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB,EACnB,eAAuB,EACvB,OAKC;IAED,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAEjJ,IAAI,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,OAAO,CAAC,sBAAsB,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,GAAG,yBAAyB,GAAG,OAAO,GAAG,0BAA0B,CAAC;IAC7E,CAAC;IAED,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC;IAEhC,IAAI,OAAO,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QAClC,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAE9D,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './generateTypes.mjs';
2
+ export * from './generateErrors.mjs';
@@ -0,0 +1,3 @@
1
+ export * from './generateTypes.mjs';
2
+ export * from './generateErrors.mjs';
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/generator/index.mts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@map-colonies/openapi-helpers",
3
- "version": "3.0.0",
3
+ "version": "4.0.0",
4
4
  "description": "A package that provides utilities for working with openapi files",
5
5
  "exports": {
6
6
  "./requestSender": {
@@ -10,9 +10,13 @@
10
10
  "./typedRequestHandler": {
11
11
  "default": "./dist/typedRequestHandler/typedRequestHandler.js",
12
12
  "types": "./dist/typedRequestHandler/typedRequestHandler.d.ts"
13
+ },
14
+ "./generators": {
15
+ "import": "./dist/generator/index.mjs",
16
+ "types": "./dist/generator/index.d.mts"
13
17
  }
14
18
  },
15
- "bin": "./dist/generator/generateTypes.mjs",
19
+ "bin": "./dist/cli/entrypoint.mjs",
16
20
  "scripts": {
17
21
  "format": "prettier --check .",
18
22
  "format:fix": "prettier --write .",
@@ -26,6 +30,7 @@
26
30
  "generate:test:types": "npm run build && node dist/generator/generateTypes.mjs tests/openapi3.yaml tests/types.d.ts",
27
31
  "clean": "rimraf dist",
28
32
  "prepublish": "npm run build",
33
+ "prepack": "npm run build",
29
34
  "prepare": "husky",
30
35
  "docs": "typedoc"
31
36
  },
@@ -49,7 +54,13 @@
49
54
  },
50
55
  "homepage": "https://github.com/MapColonies/openapi-helpers#readme",
51
56
  "dependencies": {
57
+ "@apidevtools/json-schema-ref-parser": "^14.1.1",
58
+ "@commander-js/extra-typings": "^14.0.0",
59
+ "@map-colonies/read-pkg": "^1.0.0",
60
+ "change-case": "^5.4.4",
61
+ "commander": "^14.0.0",
52
62
  "oas-normalize": "^14.1.2",
63
+ "ora": "^8.2.0",
53
64
  "ts-essentials": "^10.1.1",
54
65
  "yaml": "^2.8.0"
55
66
  },