@let-aurn/swagger-client 0.3.2 → 0.3.3
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 +17 -0
- package/dist/core/generate.js +1 -1
- package/dist/core/load-config.js +2 -0
- package/dist/core/read-openapi.d.ts +2 -1
- package/dist/core/read-openapi.js +8 -4
- package/dist/core/server-url.d.ts +3 -0
- package/dist/core/server-url.js +15 -0
- package/dist/core/types.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,23 @@ npx swagger-client generate --config=swagger-client.json
|
|
|
24
24
|
|
|
25
25
|
`client` can be `angular` or `react`.
|
|
26
26
|
|
|
27
|
+
`serverUrlIndex` is optional and selects a zero-based index from each document's
|
|
28
|
+
top-level `servers` array to prefix generated endpoint paths:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"serverUrlIndex": 0
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For `servers: [{ "url": "/some-api/V01/xxx" }]`, the endpoint `/posts/{id}`
|
|
37
|
+
gets the path `/some-api/V01/xxx/posts/{id}` in `api-endpoints.ts`. Relative
|
|
38
|
+
server prefixes are appended to the client's configured `baseUrl` when making
|
|
39
|
+
requests. Slashes at the join are normalized; an empty operation path uses the
|
|
40
|
+
selected server URL exactly, without adding a trailing slash. Omitting this option keeps the
|
|
41
|
+
original endpoint paths. Invalid indexes or missing, empty, or non-string
|
|
42
|
+
selected URLs fail generation; URL errors identify the source file.
|
|
43
|
+
|
|
27
44
|
`endpoint-name-strategy` is optional:
|
|
28
45
|
|
|
29
46
|
- `operationId` uses the OpenAPI `operationId` as-is. This is the default.
|
package/dist/core/generate.js
CHANGED
|
@@ -13,7 +13,7 @@ import { emitReactClient } from "../generators/react-client.js";
|
|
|
13
13
|
* @throws Error when OpenAPI files cannot be read or generated files cannot be written.
|
|
14
14
|
*/
|
|
15
15
|
export async function generate(config) {
|
|
16
|
-
const project = await readOpenApiProject(config["swaggers-directory"], config["endpoint-name-strategy"], config["endpoint-namespace"]);
|
|
16
|
+
const project = await readOpenApiProject(config["swaggers-directory"], config["endpoint-name-strategy"], config["endpoint-namespace"], config.serverUrlIndex);
|
|
17
17
|
const modelsPath = config.output["api-models.ts"];
|
|
18
18
|
const endpointsPath = config.output["api-endpoints.ts"];
|
|
19
19
|
const clientPath = config.output["client.ts"];
|
package/dist/core/load-config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { validateEndpointNamespace } from "./endpoint-namespace.js";
|
|
4
|
+
import { validateServerUrlIndex } from "./server-url.js";
|
|
4
5
|
/**
|
|
5
6
|
* Loads and validates a swagger-client configuration file.
|
|
6
7
|
*
|
|
@@ -24,6 +25,7 @@ export async function loadConfig(configPath) {
|
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
function validateConfig(config, configPath) {
|
|
28
|
+
validateServerUrlIndex(config.serverUrlIndex, configPath);
|
|
27
29
|
if (config.client !== "angular" && config.client !== "react") {
|
|
28
30
|
throw new Error(`${configPath}: "client" must be "angular" or "react".`);
|
|
29
31
|
}
|
|
@@ -5,7 +5,8 @@ import type { EndpointNameStrategy, EndpointNamespaceConfig, ProjectModel } from
|
|
|
5
5
|
* @param swaggerDirectory The directory containing one or more OpenAPI JSON files.
|
|
6
6
|
* @param endpointNameStrategy The strategy used to name generated endpoint constants.
|
|
7
7
|
* @param endpointNamespace Configurable document field and optional namespace extraction regex.
|
|
8
|
+
* @param serverUrlIndex Optional document server URL index to prefix endpoint paths with.
|
|
8
9
|
* @returns The normalized schemas and endpoints discovered in the OpenAPI files.
|
|
9
10
|
* @throws Error when a JSON file cannot be read or parsed.
|
|
10
11
|
*/
|
|
11
|
-
export declare function readOpenApiProject(swaggerDirectory: string, endpointNameStrategy?: EndpointNameStrategy, endpointNamespace?: EndpointNamespaceConfig): Promise<ProjectModel>;
|
|
12
|
+
export declare function readOpenApiProject(swaggerDirectory: string, endpointNameStrategy?: EndpointNameStrategy, endpointNamespace?: EndpointNamespaceConfig, serverUrlIndex?: number): Promise<ProjectModel>;
|
|
@@ -3,6 +3,7 @@ import { join, relative } from "node:path";
|
|
|
3
3
|
import { schemaToType } from "./schema-to-typescript.js";
|
|
4
4
|
import { ensureIdentifier, toPascalCase, uniqueName } from "./names.js";
|
|
5
5
|
import { extractEndpointNamespace, validateEndpointNamespace } from "./endpoint-namespace.js";
|
|
6
|
+
import { selectServerUrl, validateServerUrlIndex } from "./server-url.js";
|
|
6
7
|
const HTTP_METHODS = new Set(["get", "post", "put", "patch", "delete", "head", "options"]);
|
|
7
8
|
/**
|
|
8
9
|
* Reads OpenAPI JSON files from a directory and converts them to the generator project model.
|
|
@@ -10,10 +11,12 @@ const HTTP_METHODS = new Set(["get", "post", "put", "patch", "delete", "head", "
|
|
|
10
11
|
* @param swaggerDirectory The directory containing one or more OpenAPI JSON files.
|
|
11
12
|
* @param endpointNameStrategy The strategy used to name generated endpoint constants.
|
|
12
13
|
* @param endpointNamespace Configurable document field and optional namespace extraction regex.
|
|
14
|
+
* @param serverUrlIndex Optional document server URL index to prefix endpoint paths with.
|
|
13
15
|
* @returns The normalized schemas and endpoints discovered in the OpenAPI files.
|
|
14
16
|
* @throws Error when a JSON file cannot be read or parsed.
|
|
15
17
|
*/
|
|
16
|
-
export async function readOpenApiProject(swaggerDirectory, endpointNameStrategy = "operationId", endpointNamespace) {
|
|
18
|
+
export async function readOpenApiProject(swaggerDirectory, endpointNameStrategy = "operationId", endpointNamespace, serverUrlIndex) {
|
|
19
|
+
validateServerUrlIndex(serverUrlIndex, swaggerDirectory);
|
|
17
20
|
if (endpointNameStrategy === "namespaceTagAndOperationId") {
|
|
18
21
|
validateEndpointNamespace(endpointNamespace, swaggerDirectory);
|
|
19
22
|
}
|
|
@@ -25,11 +28,12 @@ export async function readOpenApiProject(swaggerDirectory, endpointNameStrategy
|
|
|
25
28
|
for (const file of files) {
|
|
26
29
|
const document = JSON.parse(await readFile(file, "utf8"));
|
|
27
30
|
const sourceFile = relative(swaggerDirectory, file);
|
|
31
|
+
const serverUrl = selectServerUrl(document, serverUrlIndex, sourceFile);
|
|
28
32
|
const schemaNameMap = collectSchemas(document, schemas, usedSchemaNames);
|
|
29
33
|
const namespace = endpointNameStrategy === "namespaceTagAndOperationId"
|
|
30
34
|
? extractEndpointNamespace(document, endpointNamespace, sourceFile)
|
|
31
35
|
: undefined;
|
|
32
|
-
endpoints.push(...collectEndpoints(document, sourceFile, schemaNameMap, usedEndpointNames, endpointNameStrategy, namespace));
|
|
36
|
+
endpoints.push(...collectEndpoints(document, sourceFile, schemaNameMap, usedEndpointNames, endpointNameStrategy, namespace, serverUrl));
|
|
33
37
|
}
|
|
34
38
|
return { schemas, endpoints };
|
|
35
39
|
}
|
|
@@ -66,7 +70,7 @@ function collectSchemas(document, schemas, usedSchemaNames) {
|
|
|
66
70
|
}
|
|
67
71
|
return schemaNameMap;
|
|
68
72
|
}
|
|
69
|
-
function collectEndpoints(document, sourceFile, schemaNameMap, usedEndpointNames, endpointNameStrategy, namespace) {
|
|
73
|
+
function collectEndpoints(document, sourceFile, schemaNameMap, usedEndpointNames, endpointNameStrategy, namespace, serverUrl = "") {
|
|
70
74
|
const endpoints = [];
|
|
71
75
|
for (const [path, pathItem] of Object.entries(document.paths ?? {})) {
|
|
72
76
|
if (!isRecord(pathItem)) {
|
|
@@ -82,7 +86,7 @@ function collectEndpoints(document, sourceFile, schemaNameMap, usedEndpointNames
|
|
|
82
86
|
endpoints.push({
|
|
83
87
|
name: endpointName,
|
|
84
88
|
method: method.toUpperCase(),
|
|
85
|
-
path,
|
|
89
|
+
path: serverUrl && path ? `${serverUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}` : serverUrl || path,
|
|
86
90
|
operationId,
|
|
87
91
|
sourceFile,
|
|
88
92
|
pathVariables: variablesFor(parameters, "path", schemaNameMap),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function validateServerUrlIndex(index, source) {
|
|
2
|
+
if (index !== undefined && (!Number.isSafeInteger(index) || index < 0)) {
|
|
3
|
+
throw new Error(`${source}: "serverUrlIndex" must be a non-negative safe integer.`);
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
export function selectServerUrl(document, index, sourceFile) {
|
|
7
|
+
if (index === undefined) {
|
|
8
|
+
return "";
|
|
9
|
+
}
|
|
10
|
+
const url = Array.isArray(document.servers) ? document.servers[index]?.url : undefined;
|
|
11
|
+
if (typeof url !== "string" || url.trim() === "") {
|
|
12
|
+
throw new Error(`${sourceFile}: servers[${index}].url must be a non-empty string when "serverUrlIndex" is provided.`);
|
|
13
|
+
}
|
|
14
|
+
return url;
|
|
15
|
+
}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export interface SwaggerClientConfig {
|
|
|
11
11
|
"swaggers-directory": string;
|
|
12
12
|
"endpoint-name-strategy"?: EndpointNameStrategy;
|
|
13
13
|
"endpoint-namespace"?: EndpointNamespaceConfig;
|
|
14
|
+
/** Index of the document server URL to prefix endpoint paths with. */
|
|
15
|
+
serverUrlIndex?: number;
|
|
14
16
|
output: {
|
|
15
17
|
"api-models.ts": string;
|
|
16
18
|
"api-endpoints.ts": string;
|
|
@@ -46,6 +48,9 @@ export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" |
|
|
|
46
48
|
export interface OpenApiDocument {
|
|
47
49
|
openapi?: string;
|
|
48
50
|
swagger?: string;
|
|
51
|
+
servers?: {
|
|
52
|
+
url: string;
|
|
53
|
+
}[];
|
|
49
54
|
info?: {
|
|
50
55
|
title?: string;
|
|
51
56
|
version?: string;
|