@sdk-it/spec 0.20.0 → 0.21.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/dist/lib/loaders/load-spec.d.ts.map +1 -1
- package/dist/lib/loaders/load-spec.js +5 -3
- package/dist/lib/loaders/load-spec.js.map +2 -2
- package/dist/lib/loaders/remote-loader.d.ts.map +1 -1
- package/dist/lib/loaders/remote-loader.js +3 -0
- package/dist/lib/loaders/remote-loader.js.map +2 -2
- package/dist/lib/operation.d.ts +20 -2
- package/dist/lib/operation.d.ts.map +1 -1
- package/dist/lib/operation.js +153 -14
- package/dist/lib/operation.js.map +2 -2
- package/dist/lib/pagination/pagination-result.d.ts +20 -0
- package/dist/lib/pagination/pagination-result.d.ts.map +1 -0
- package/dist/lib/pagination/pagination-result.js +237 -0
- package/dist/lib/pagination/pagination-result.js.map +7 -0
- package/dist/lib/pagination/pagination-result.test.d.ts +2 -0
- package/dist/lib/pagination/pagination-result.test.d.ts.map +1 -0
- package/dist/lib/pagination/pagination-result.test.js +548 -0
- package/dist/lib/pagination/pagination-result.test.js.map +7 -0
- package/dist/lib/pagination/pagination.d.ts +50 -0
- package/dist/lib/pagination/pagination.d.ts.map +1 -0
- package/dist/lib/pagination/pagination.js +199 -0
- package/dist/lib/pagination/pagination.js.map +7 -0
- package/dist/lib/pagination/pagination.test.d.ts +2 -0
- package/dist/lib/pagination/pagination.test.d.ts.map +1 -0
- package/dist/lib/pagination/pagination.test.js +380 -0
- package/dist/lib/pagination/pagination.test.js.map +7 -0
- package/dist/lib/sidebar.d.ts +3 -6
- package/dist/lib/sidebar.d.ts.map +1 -1
- package/dist/lib/sidebar.js +64 -16
- package/dist/lib/sidebar.js.map +2 -2
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-spec.d.ts","sourceRoot":"","sources":["../../../src/lib/loaders/load-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"load-spec.d.ts","sourceRoot":"","sources":["../../../src/lib/loaders/load-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAsBvD,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAOvE;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { augmentSpec } from "../operation.js";
|
|
1
2
|
import { loadLocal } from "./local-loader.js";
|
|
2
3
|
import { convertPostmanToOpenAPI } from "./postman/postman-converter.js";
|
|
3
4
|
import { loadRemote } from "./remote-loader.js";
|
|
@@ -5,11 +6,12 @@ function isPostman(content) {
|
|
|
5
6
|
return typeof content === "object" && content !== null && "info" in content && typeof content.info === "object" && content.info !== null && "item" in content && Array.isArray(content.item) && "schema" in content.info && typeof content.info.schema === "string" && content.info.schema.includes("//schema.getpostman.com/");
|
|
6
7
|
}
|
|
7
8
|
async function loadSpec(location) {
|
|
8
|
-
|
|
9
|
+
let content = await loadFile(location);
|
|
9
10
|
if (isPostman(content)) {
|
|
10
|
-
|
|
11
|
+
content = convertPostmanToOpenAPI(content);
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
const spec = content;
|
|
14
|
+
return "x-sdk-augmented" in spec ? spec : augmentSpec({ spec });
|
|
13
15
|
}
|
|
14
16
|
function loadFile(location) {
|
|
15
17
|
const [protocol] = location.split(":");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/loaders/load-spec.ts"],
|
|
4
|
-
"sourcesContent": ["import type { OpenAPIObject } from 'openapi3-ts/oas31';\n\nimport { loadLocal } from './local-loader.js';\nimport { convertPostmanToOpenAPI } from './postman/postman-converter.js';\nimport type { PostmanCollection } from './postman/spec-types.js';\nimport { loadRemote } from './remote-loader.js';\n\nfunction isPostman(content: unknown): content is PostmanCollection {\n return (\n typeof content === 'object' &&\n content !== null &&\n 'info' in content &&\n typeof content.info === 'object' &&\n content.info !== null &&\n 'item' in content &&\n Array.isArray(content.item) &&\n 'schema' in content.info &&\n typeof content.info.schema === 'string' &&\n content.info.schema.includes('//schema.getpostman.com/')\n );\n}\nexport async function loadSpec(location: string): Promise<OpenAPIObject> {\n
|
|
5
|
-
"mappings": "AAEA,SAAS,iBAAiB;AAC1B,SAAS,+BAA+B;AAExC,SAAS,kBAAkB;AAE3B,SAAS,UAAU,SAAgD;AACjE,SACE,OAAO,YAAY,YACnB,YAAY,QACZ,UAAU,WACV,OAAO,QAAQ,SAAS,YACxB,QAAQ,SAAS,QACjB,UAAU,WACV,MAAM,QAAQ,QAAQ,IAAI,KAC1B,YAAY,QAAQ,QACpB,OAAO,QAAQ,KAAK,WAAW,YAC/B,QAAQ,KAAK,OAAO,SAAS,0BAA0B;AAE3D;AACA,eAAsB,SAAS,UAA0C;AACvE,
|
|
4
|
+
"sourcesContent": ["import type { OpenAPIObject } from 'openapi3-ts/oas31';\n\nimport { augmentSpec } from '../operation.js';\nimport { loadLocal } from './local-loader.js';\nimport { convertPostmanToOpenAPI } from './postman/postman-converter.js';\nimport type { PostmanCollection } from './postman/spec-types.js';\nimport { loadRemote } from './remote-loader.js';\n\nfunction isPostman(content: unknown): content is PostmanCollection {\n return (\n typeof content === 'object' &&\n content !== null &&\n 'info' in content &&\n typeof content.info === 'object' &&\n content.info !== null &&\n 'item' in content &&\n Array.isArray(content.item) &&\n 'schema' in content.info &&\n typeof content.info.schema === 'string' &&\n content.info.schema.includes('//schema.getpostman.com/')\n );\n}\nexport async function loadSpec(location: string): Promise<OpenAPIObject> {\n let content = await loadFile(location);\n if (isPostman(content)) {\n content = convertPostmanToOpenAPI(content);\n }\n const spec = content as OpenAPIObject;\n return 'x-sdk-augmented' in spec ? spec : augmentSpec({ spec });\n}\n\nexport function loadFile<T>(location: string): Promise<T> {\n const [protocol] = location.split(':');\n if (protocol === 'http' || protocol === 'https') {\n return loadRemote(location);\n }\n return loadLocal(location);\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,+BAA+B;AAExC,SAAS,kBAAkB;AAE3B,SAAS,UAAU,SAAgD;AACjE,SACE,OAAO,YAAY,YACnB,YAAY,QACZ,UAAU,WACV,OAAO,QAAQ,SAAS,YACxB,QAAQ,SAAS,QACjB,UAAU,WACV,MAAM,QAAQ,QAAQ,IAAI,KAC1B,YAAY,QAAQ,QACpB,OAAO,QAAQ,KAAK,WAAW,YAC/B,QAAQ,KAAK,OAAO,SAAS,0BAA0B;AAE3D;AACA,eAAsB,SAAS,UAA0C;AACvE,MAAI,UAAU,MAAM,SAAS,QAAQ;AACrC,MAAI,UAAU,OAAO,GAAG;AACtB,cAAU,wBAAwB,OAAO;AAAA,EAC3C;AACA,QAAM,OAAO;AACb,SAAO,qBAAqB,OAAO,OAAO,YAAY,EAAE,KAAK,CAAC;AAChE;AAEO,SAAS,SAAY,UAA8B;AACxD,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM,GAAG;AACrC,MAAI,aAAa,UAAU,aAAa,SAAS;AAC/C,WAAO,WAAW,QAAQ;AAAA,EAC5B;AACA,SAAO,UAAU,QAAQ;AAC3B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-loader.d.ts","sourceRoot":"","sources":["../../../src/lib/loaders/remote-loader.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"remote-loader.d.ts","sourceRoot":"","sources":["../../../src/lib/loaders/remote-loader.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAwBhE"}
|
|
@@ -3,6 +3,9 @@ import { parse } from "yaml";
|
|
|
3
3
|
async function loadRemote(location) {
|
|
4
4
|
const extName = extname(location);
|
|
5
5
|
const response = await fetch(location);
|
|
6
|
+
if (!response.ok) {
|
|
7
|
+
throw new Error(`Failed to fetch ${location}: ${response.statusText}`);
|
|
8
|
+
}
|
|
6
9
|
switch (extName) {
|
|
7
10
|
case ".json":
|
|
8
11
|
return response.json();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/loaders/remote-loader.ts"],
|
|
4
|
-
"sourcesContent": ["import { extname } from 'node:path';\nimport { parse } from 'yaml';\n\nexport async function loadRemote<T>(location: string): Promise<T> {\n const extName = extname(location);\n const response = await fetch(location);\n switch (extName) {\n case '.json':\n return response.json() as Promise<T>;\n case '.yaml':\n case '.yml': {\n const text = await response.text();\n return parse(text);\n }\n default:\n try {\n // try to parse it as json first\n return response.json() as Promise<T>;\n } catch {\n // parse as yaml\n const text = await response.text();\n return parse(text) as Promise<T>;\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,aAAa;AAEtB,eAAsB,WAAc,UAA8B;AAChE,QAAM,UAAU,QAAQ,QAAQ;AAChC,QAAM,WAAW,MAAM,MAAM,QAAQ;AACrC,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,SAAS,KAAK;AAAA,IACvB,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO,MAAM,IAAI;AAAA,IACnB;AAAA,IACA;AACE,UAAI;AAEF,eAAO,SAAS,KAAK;AAAA,MACvB,QAAQ;AAEN,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,eAAO,MAAM,IAAI;AAAA,MACnB;AAAA,EACJ;AACF;",
|
|
4
|
+
"sourcesContent": ["import { extname } from 'node:path';\nimport { parse } from 'yaml';\n\nexport async function loadRemote<T>(location: string): Promise<T> {\n const extName = extname(location);\n const response = await fetch(location);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${location}: ${response.statusText}`);\n }\n switch (extName) {\n case '.json':\n return response.json() as Promise<T>;\n case '.yaml':\n case '.yml': {\n const text = await response.text();\n return parse(text);\n }\n default:\n try {\n // try to parse it as json first\n return response.json() as Promise<T>;\n } catch {\n // parse as yaml\n const text = await response.text();\n return parse(text) as Promise<T>;\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,aAAa;AAEtB,eAAsB,WAAc,UAA8B;AAChE,QAAM,UAAU,QAAQ,QAAQ;AAChC,QAAM,WAAW,MAAM,MAAM,QAAQ;AACrC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,mBAAmB,QAAQ,KAAK,SAAS,UAAU,EAAE;AAAA,EACvE;AACA,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,SAAS,KAAK;AAAA,IACvB,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO,MAAM,IAAI;AAAA,IACnB;AAAA,IACA;AACE,UAAI;AAEF,eAAO,SAAS,KAAK;AAAA,MACvB,QAAQ;AAEN,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,eAAO,MAAM,IAAI;AAAA,MACnB;AAAA,EACJ;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/lib/operation.d.ts
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
import type { OpenAPIObject, OperationObject, ParameterObject,
|
|
1
|
+
import type { ComponentsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, PathsObject, RequestBodyObject, ResponseObject, SchemaObject, SecurityRequirementObject } from 'openapi3-ts/oas31';
|
|
2
|
+
import { type PaginationGuess } from './pagination/pagination.js';
|
|
3
|
+
export declare function augmentSpec(config: GenerateSdkConfig): {
|
|
4
|
+
paths: PathsObject;
|
|
5
|
+
openapi: string;
|
|
6
|
+
info: import("openapi3-ts/oas31").InfoObject;
|
|
7
|
+
servers?: import("openapi3-ts/oas31").ServerObject[];
|
|
8
|
+
components?: ComponentsObject;
|
|
9
|
+
security?: SecurityRequirementObject[];
|
|
10
|
+
tags?: import("openapi3-ts/oas31").TagObject[];
|
|
11
|
+
externalDocs?: import("openapi3-ts/oas31").ExternalDocumentationObject;
|
|
12
|
+
webhooks?: PathsObject;
|
|
13
|
+
};
|
|
14
|
+
export type OperationPagination = PaginationGuess & {
|
|
15
|
+
items: string;
|
|
16
|
+
};
|
|
2
17
|
export declare const defaults: Partial<GenerateSdkConfig> & Required<Pick<GenerateSdkConfig, 'operationId' | 'tag'>>;
|
|
3
18
|
export type TunedOperationObject = Omit<OperationObject, 'operationId' | 'parameters' | 'responses'> & {
|
|
4
19
|
operationId: string;
|
|
5
|
-
parameters:
|
|
20
|
+
parameters: ParameterObject[];
|
|
6
21
|
responses: Record<string, ResponseObject>;
|
|
22
|
+
requestBody: RequestBodyObject | undefined;
|
|
7
23
|
};
|
|
8
24
|
export interface OperationEntry {
|
|
9
25
|
name?: string;
|
|
@@ -41,4 +57,6 @@ export declare function parseJsonContentType(contentType: string | null | undefi
|
|
|
41
57
|
export declare function isSseContentType(contentType: string | null | undefined): boolean;
|
|
42
58
|
export declare function isStreamingContentType(contentType: string | null | undefined): boolean;
|
|
43
59
|
export declare function isSuccessStatusCode(statusCode: number | string): boolean;
|
|
60
|
+
export declare function patchParameters(spec: OpenAPIObject, objectSchema: SchemaObject, operation: TunedOperationObject): void;
|
|
61
|
+
export declare function securityToOptions(spec: OpenAPIObject, security: SecurityRequirementObject[], securitySchemes: ComponentsObject['securitySchemes'], staticIn?: ParameterLocation): ParameterObject[];
|
|
44
62
|
//# sourceMappingURL=operation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/lib/operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,
|
|
1
|
+
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/lib/operation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,WAAW,EAEX,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,yBAAyB,EAC1B,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,4BAA4B,CAAC;AAEpC,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB;;;;;;;;;;EA6CpD;AAED,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AA6EF,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAC/C,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,KAAK,CAAC,CAqBxD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,eAAe,EACf,aAAa,GAAG,YAAY,GAAG,WAAW,CAC3C,GAAG;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,WAAW,EAAE,iBAAiB,GAAG,SAAS,CAAC;CAC5C,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AACD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,oBAAoB,CAAC;CACjC,CAAC;AAcF,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,oBAAoB,KAAK,CAAC,OA4BxE;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,CAAC,EAAE,CACZ,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,KACX,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5D;AA6ED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,eAAe,GACzB,MAAM,CAoLR;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,iBAuB1E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACrC,OAAO,CAoBT;AAED,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACrC,OAAO,CAET;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAGxE;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,EACnB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,oBAAoB,QA2BhC;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,yBAAyB,EAAE,EACrC,eAAe,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,EACpD,QAAQ,CAAC,EAAE,iBAAiB,qBAsC7B"}
|
package/dist/lib/operation.js
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
import { camelcase } from "stringcase";
|
|
2
|
-
import { followRef, isRef } from "@sdk-it/core";
|
|
2
|
+
import { followRef, isRef } from "@sdk-it/core/ref.js";
|
|
3
|
+
import {
|
|
4
|
+
guessPagination
|
|
5
|
+
} from "./pagination/pagination.js";
|
|
6
|
+
function augmentSpec(config) {
|
|
7
|
+
config.spec.paths ??= {};
|
|
8
|
+
const paths = {};
|
|
9
|
+
for (const [path, pathItem] of Object.entries(config.spec.paths)) {
|
|
10
|
+
const { parameters = [], ...methods } = pathItem;
|
|
11
|
+
const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
|
|
12
|
+
for (const [method, operation] of Object.entries(methods)) {
|
|
13
|
+
const formatOperationId = config.operationId ?? defaults.operationId;
|
|
14
|
+
const formatTag = config.tag ?? defaults.tag;
|
|
15
|
+
const operationId = formatOperationId(operation, fixedPath, method);
|
|
16
|
+
const operationTag = formatTag(operation, fixedPath);
|
|
17
|
+
const requestBody = isRef(operation.requestBody) ? followRef(config.spec, operation.requestBody.$ref) : operation.requestBody;
|
|
18
|
+
const tunedOperation = {
|
|
19
|
+
...operation,
|
|
20
|
+
parameters: [...parameters, ...operation.parameters ?? []].map(
|
|
21
|
+
(it) => isRef(it) ? followRef(config.spec, it.$ref) : it
|
|
22
|
+
),
|
|
23
|
+
tags: [operationTag],
|
|
24
|
+
operationId,
|
|
25
|
+
responses: resolveResponses(config.spec, operation),
|
|
26
|
+
requestBody
|
|
27
|
+
};
|
|
28
|
+
tunedOperation["x-pagination"] = toPagination(
|
|
29
|
+
config.spec,
|
|
30
|
+
tunedOperation
|
|
31
|
+
);
|
|
32
|
+
Object.assign(paths, {
|
|
33
|
+
[fixedPath]: {
|
|
34
|
+
...paths[fixedPath],
|
|
35
|
+
[method]: tunedOperation
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { ...config.spec, paths };
|
|
41
|
+
}
|
|
42
|
+
function toPagination(spec, tunedOperation) {
|
|
43
|
+
if (tunedOperation["x-pagination"]) {
|
|
44
|
+
return tunedOperation["x-pagination"];
|
|
45
|
+
}
|
|
46
|
+
const schema = getResponseContentSchema(
|
|
47
|
+
spec,
|
|
48
|
+
tunedOperation.responses["200"],
|
|
49
|
+
"application/json"
|
|
50
|
+
);
|
|
51
|
+
const pagination = guessPagination(
|
|
52
|
+
tunedOperation,
|
|
53
|
+
tunedOperation.requestBody ? getRequestContentSchema(
|
|
54
|
+
spec,
|
|
55
|
+
tunedOperation.requestBody,
|
|
56
|
+
"application/json"
|
|
57
|
+
) : void 0,
|
|
58
|
+
schema
|
|
59
|
+
);
|
|
60
|
+
if (pagination && pagination.type !== "none" && schema) {
|
|
61
|
+
return pagination;
|
|
62
|
+
}
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
function getResponseContentSchema(spec, response, type) {
|
|
66
|
+
if (!response) {
|
|
67
|
+
return void 0;
|
|
68
|
+
}
|
|
69
|
+
const content = response.content;
|
|
70
|
+
if (!content) {
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
for (const contentType in content) {
|
|
74
|
+
if (contentType.toLowerCase() === type.toLowerCase()) {
|
|
75
|
+
return isRef(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
function getRequestContentSchema(spec, requestBody, type) {
|
|
81
|
+
const content = requestBody.content;
|
|
82
|
+
if (!content) {
|
|
83
|
+
return void 0;
|
|
84
|
+
}
|
|
85
|
+
for (const contentType in content) {
|
|
86
|
+
if (contentType.toLowerCase() === type.toLowerCase()) {
|
|
87
|
+
return isRef(content[contentType].schema) ? followRef(spec, content[contentType].schema.$ref) : content[contentType].schema;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
3
92
|
const defaults = {
|
|
4
93
|
operationId: (operation, path, method) => {
|
|
5
94
|
if (operation.operationId) {
|
|
@@ -30,28 +119,19 @@ function forEachOperation(config, callback) {
|
|
|
30
119
|
const result = [];
|
|
31
120
|
for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {
|
|
32
121
|
const { parameters = [], ...methods } = pathItem;
|
|
33
|
-
const fixedPath = path.replace(/:([^/]+)/g, "{$1}");
|
|
34
122
|
for (const [method, operation] of Object.entries(methods)) {
|
|
35
|
-
const formatOperationId = config.operationId ?? defaults.operationId;
|
|
36
|
-
const formatTag = config.tag ?? defaults.tag;
|
|
37
|
-
const operationName = formatOperationId(operation, fixedPath, method);
|
|
38
|
-
const operationTag = formatTag(operation, fixedPath);
|
|
39
123
|
const metadata = operation["x-oaiMeta"] ?? {};
|
|
124
|
+
const operationTag = operation.tags?.[0];
|
|
40
125
|
result.push(
|
|
41
126
|
callback(
|
|
42
127
|
{
|
|
43
128
|
name: metadata.name,
|
|
44
129
|
method,
|
|
45
|
-
path
|
|
130
|
+
path,
|
|
46
131
|
groupName: operationTag,
|
|
47
132
|
tag: operationTag
|
|
48
133
|
},
|
|
49
|
-
|
|
50
|
-
...operation,
|
|
51
|
-
parameters: [...parameters, ...operation.parameters ?? []],
|
|
52
|
-
operationId: operationName,
|
|
53
|
-
responses: resolveResponses(config.spec, operation)
|
|
54
|
-
}
|
|
134
|
+
operation
|
|
55
135
|
)
|
|
56
136
|
);
|
|
57
137
|
}
|
|
@@ -274,13 +354,72 @@ function isSuccessStatusCode(statusCode) {
|
|
|
274
354
|
statusCode = Number(statusCode);
|
|
275
355
|
return statusCode >= 200 && statusCode < 300;
|
|
276
356
|
}
|
|
357
|
+
function patchParameters(spec, objectSchema, operation) {
|
|
358
|
+
const securitySchemes = spec.components?.securitySchemes ?? {};
|
|
359
|
+
const securityOptions = securityToOptions(
|
|
360
|
+
spec,
|
|
361
|
+
operation.security ?? [],
|
|
362
|
+
securitySchemes
|
|
363
|
+
);
|
|
364
|
+
objectSchema.properties ??= {};
|
|
365
|
+
objectSchema.required ??= [];
|
|
366
|
+
for (const param of operation.parameters) {
|
|
367
|
+
if (param.required) {
|
|
368
|
+
objectSchema.required.push(param.name);
|
|
369
|
+
}
|
|
370
|
+
objectSchema.properties[param.name] = isRef(param.schema) ? followRef(spec, param.schema.$ref) : param.schema ?? { type: "string" };
|
|
371
|
+
}
|
|
372
|
+
for (const param of securityOptions) {
|
|
373
|
+
objectSchema.required = (objectSchema.required ?? []).filter(
|
|
374
|
+
(name) => name !== param.name
|
|
375
|
+
);
|
|
376
|
+
objectSchema.properties[param.name] = isRef(param.schema) ? followRef(spec, param.schema.$ref) : param.schema ?? { type: "string" };
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function securityToOptions(spec, security, securitySchemes, staticIn) {
|
|
380
|
+
securitySchemes ??= {};
|
|
381
|
+
const parameters = [];
|
|
382
|
+
for (const it of security) {
|
|
383
|
+
const [name] = Object.keys(it);
|
|
384
|
+
if (!name) {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
const schema = isRef(securitySchemes[name]) ? followRef(spec, securitySchemes[name].$ref) : securitySchemes[name];
|
|
388
|
+
if (schema.type === "http") {
|
|
389
|
+
parameters.push({
|
|
390
|
+
in: staticIn ?? "header",
|
|
391
|
+
name: "authorization",
|
|
392
|
+
schema: { type: "string" }
|
|
393
|
+
});
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (schema.type === "apiKey") {
|
|
397
|
+
if (!schema.in) {
|
|
398
|
+
throw new Error(`apiKey security schema must have an "in" field`);
|
|
399
|
+
}
|
|
400
|
+
if (!schema.name) {
|
|
401
|
+
throw new Error(`apiKey security schema must have a "name" field`);
|
|
402
|
+
}
|
|
403
|
+
parameters.push({
|
|
404
|
+
in: staticIn ?? schema.in,
|
|
405
|
+
name: schema.name,
|
|
406
|
+
schema: { type: "string" }
|
|
407
|
+
});
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return parameters;
|
|
412
|
+
}
|
|
277
413
|
export {
|
|
414
|
+
augmentSpec,
|
|
278
415
|
defaults,
|
|
279
416
|
determineGenericTag,
|
|
280
417
|
forEachOperation,
|
|
281
418
|
isSseContentType,
|
|
282
419
|
isStreamingContentType,
|
|
283
420
|
isSuccessStatusCode,
|
|
284
|
-
parseJsonContentType
|
|
421
|
+
parseJsonContentType,
|
|
422
|
+
patchParameters,
|
|
423
|
+
securityToOptions
|
|
285
424
|
};
|
|
286
425
|
//# sourceMappingURL=operation.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/operation.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n OpenAPIObject,\n OperationObject,\n ParameterObject,\n ReferenceObject,\n ResponseObject,\n} from 'openapi3-ts/oas31';\nimport { camelcase } from 'stringcase';\n\nimport { followRef, isRef } from '@sdk-it/core';\n\nexport const defaults: Partial<GenerateSdkConfig> &\n Required<Pick<GenerateSdkConfig, 'operationId' | 'tag'>> = {\n operationId: (operation, path, method) => {\n if (operation.operationId) {\n return camelcase(operation.operationId);\n }\n const metadata = operation['x-oaiMeta'];\n if (metadata && metadata.name) {\n return camelcase(metadata.name);\n }\n return camelcase(\n [method, ...path.replace(/[\\\\/\\\\{\\\\}]/g, ' ').split(' ')]\n .filter(Boolean)\n .join(' ')\n .trim(),\n );\n },\n tag: (operation, path) => {\n return operation.tags?.[0]\n ? sanitizeTag(operation.tags?.[0])\n : determineGenericTag(path, operation);\n },\n};\n\nexport type TunedOperationObject = Omit<\n OperationObject,\n 'operationId' | 'parameters' | 'responses'\n> & {\n operationId: string;\n parameters: (ParameterObject | ReferenceObject)[];\n responses: Record<string, ResponseObject>;\n};\n\nexport interface OperationEntry {\n name?: string;\n method: string;\n path: string;\n groupName: string;\n tag: string;\n}\nexport type Operation = {\n entry: OperationEntry;\n operation: TunedOperationObject;\n};\n\nfunction resolveResponses(spec: OpenAPIObject, operation: OperationObject) {\n const responses = operation.responses ?? {};\n const resolved: Record<string, ResponseObject> = {};\n for (const status in responses) {\n const response = isRef(responses[status] as ReferenceObject)\n ? followRef<ResponseObject>(spec, responses[status].$ref)\n : (responses[status] as ResponseObject);\n resolved[status] = response;\n }\n return resolved;\n}\n\nexport function forEachOperation<T>(\n config: GenerateSdkConfig,\n callback: (entry: OperationEntry, operation: TunedOperationObject) => T,\n) {\n const result: T[] = [];\n for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {\n const { parameters = [], ...methods } = pathItem;\n\n // Convert Express-style routes (:param) to OpenAPI-style routes ({param})\n const fixedPath = path.replace(/:([^/]+)/g, '{$1}');\n\n for (const [method, operation] of Object.entries(methods) as [\n string,\n OperationObject,\n ][]) {\n const formatOperationId = config.operationId ?? defaults.operationId;\n const formatTag = config.tag ?? defaults.tag;\n const operationName = formatOperationId(operation, fixedPath, method);\n const operationTag = formatTag(operation, fixedPath);\n const metadata = operation['x-oaiMeta'] ?? {};\n\n result.push(\n callback(\n {\n name: metadata.name,\n method,\n path: fixedPath,\n groupName: operationTag,\n tag: operationTag,\n },\n {\n ...operation,\n parameters: [...parameters, ...(operation.parameters ?? [])],\n operationId: operationName,\n responses: resolveResponses(config.spec, operation),\n },\n ),\n );\n }\n }\n return result;\n}\n\nexport interface GenerateSdkConfig {\n spec: OpenAPIObject;\n operationId?: (\n operation: OperationObject,\n path: string,\n method: string,\n ) => string;\n tag?: (operation: OperationObject, path: string) => string;\n}\n\n/**\n * Set of reserved TypeScript keywords and common verbs potentially used as tags.\n */\n\nconst reservedKeywords = new Set([\n 'await', // Reserved in async functions\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'enum',\n 'export',\n 'extends',\n 'false',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'implements', // Strict mode\n 'import',\n 'in',\n 'instanceof',\n 'interface', // Strict mode\n 'let', // Strict mode\n 'new',\n 'null',\n 'package', // Strict mode\n 'private', // Strict mode\n 'protected', // Strict mode\n 'public', // Strict mode\n 'return',\n 'static', // Strict mode\n 'super',\n 'switch',\n 'this',\n 'throw',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield', // Strict mode / Generator functions\n // 'arguments' is not technically a reserved word, but it's a special identifier within functions\n // and assigning to it or declaring it can cause issues or unexpected behavior.\n 'arguments',\n]);\n\n/**\n * Sanitizes a potential tag name (assumed to be already camelCased)\n * to avoid conflicts with reserved keywords or invalid starting characters (numbers).\n * Appends an underscore if the tag matches a reserved keyword.\n * Prepends an underscore if the tag starts with a number.\n * @param camelCasedTag The potential tag name, already camelCased.\n * @returns The sanitized tag name.\n */\nfunction sanitizeTag(camelCasedTag: string): string {\n // Prepend underscore if starts with a number\n if (/^\\d/.test(camelCasedTag)) {\n return `_${camelCasedTag}`;\n }\n // Append underscore if it's a reserved keyword\n return reservedKeywords.has(camelcase(camelCasedTag))\n ? `${camelCasedTag}_`\n : camelCasedTag;\n}\n\n/**\n * Attempts to determine a generic tag for an OpenAPI operation based on path and operationId.\n * Rules and fallbacks are documented within the code.\n * @param pathString The path string.\n * @param operation The OpenAPI Operation Object.\n * @returns A sanitized, camelCased tag name string.\n */\nexport function determineGenericTag(\n pathString: string,\n operation: OperationObject,\n): string {\n const operationId = operation.operationId || '';\n const VERSION_REGEX = /^[vV]\\d+$/;\n const commonVerbs = new Set([\n // Verbs to potentially strip from operationId prefix\n 'get',\n 'list',\n 'create',\n 'update',\n 'delete',\n 'post',\n 'put',\n 'patch',\n 'do',\n 'send',\n 'add',\n 'remove',\n 'set',\n 'find',\n 'search',\n 'check',\n 'make',\n ]);\n\n const segments = pathString.split('/').filter(Boolean);\n\n const potentialCandidates = segments.filter(\n (segment) =>\n segment &&\n !segment.startsWith('{') &&\n !segment.endsWith('}') &&\n !VERSION_REGEX.test(segment),\n );\n\n // --- Heuristic 1: Last non-'@' path segment ---\n for (let i = potentialCandidates.length - 1; i >= 0; i--) {\n const segment = potentialCandidates[i];\n if (!segment.startsWith('@')) {\n // Sanitize just before returning\n return sanitizeTag(camelcase(segment));\n }\n }\n\n const canFallbackToPathSegment = potentialCandidates.length > 0;\n\n // --- Heuristic 2: OperationId parsing ---\n if (operationId) {\n const lowerOpId = operationId.toLowerCase();\n const parts = operationId\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')\n .replace(/([a-zA-Z])(\\d)/g, '$1_$2')\n .replace(/(\\d)([a-zA-Z])/g, '$1_$2')\n .toLowerCase()\n .split(/[_-\\s]+/);\n\n const validParts = parts.filter(Boolean);\n\n // Quick skip: If opId is just a verb and we can use Heuristic 3, prefer that.\n if (\n commonVerbs.has(lowerOpId) &&\n validParts.length === 1 &&\n canFallbackToPathSegment\n ) {\n // Proceed directly to Heuristic 3\n }\n // Only process if there are valid parts and the quick skip didn't happen\n else if (validParts.length > 0) {\n const firstPart = validParts[0];\n const isFirstPartVerb = commonVerbs.has(firstPart);\n\n // Case 2a: Starts with verb, has following parts\n if (isFirstPartVerb && validParts.length > 1) {\n const verbPrefixLength = firstPart.length;\n let nextPartStartIndex = -1;\n if (operationId.length > verbPrefixLength) {\n // Simplified check for next part start\n const charAfterPrefix = operationId[verbPrefixLength];\n if (charAfterPrefix >= 'A' && charAfterPrefix <= 'Z') {\n nextPartStartIndex = verbPrefixLength;\n } else if (charAfterPrefix >= '0' && charAfterPrefix <= '9') {\n nextPartStartIndex = verbPrefixLength;\n } else if (['_', '-'].includes(charAfterPrefix)) {\n nextPartStartIndex = verbPrefixLength + 1;\n } else {\n const match = operationId\n .substring(verbPrefixLength)\n .match(/[A-Z0-9]/);\n if (match && match.index !== undefined) {\n nextPartStartIndex = verbPrefixLength + match.index;\n }\n if (\n nextPartStartIndex === -1 &&\n operationId.length > verbPrefixLength\n ) {\n nextPartStartIndex = verbPrefixLength; // Default guess\n }\n }\n }\n\n if (\n nextPartStartIndex !== -1 &&\n nextPartStartIndex < operationId.length\n ) {\n const remainingOriginalSubstring =\n operationId.substring(nextPartStartIndex);\n const potentialTag = camelcase(remainingOriginalSubstring);\n if (potentialTag) {\n // Sanitize just before returning\n return sanitizeTag(potentialTag);\n }\n }\n\n // Fallback: join remaining lowercased parts\n const potentialTagJoined = camelcase(validParts.slice(1).join('_'));\n if (potentialTagJoined) {\n // Sanitize just before returning\n return sanitizeTag(potentialTagJoined);\n }\n }\n\n // Case 2b: Doesn't start with verb, or only one part (might be verb)\n const potentialTagFull = camelcase(operationId);\n if (potentialTagFull) {\n const isResultSingleVerb = validParts.length === 1 && isFirstPartVerb;\n\n // Avoid returning only a verb if Heuristic 3 is possible\n if (!(isResultSingleVerb && canFallbackToPathSegment)) {\n if (potentialTagFull.length > 0) {\n // Sanitize just before returning\n return sanitizeTag(potentialTagFull);\n }\n }\n }\n\n // Case 2c: Further fallbacks within OpId if above failed/skipped\n const firstPartCamel = camelcase(firstPart);\n if (firstPartCamel) {\n const isFirstPartCamelVerb = commonVerbs.has(firstPartCamel);\n if (\n !isFirstPartCamelVerb ||\n validParts.length === 1 ||\n !canFallbackToPathSegment\n ) {\n // Sanitize just before returning\n return sanitizeTag(firstPartCamel);\n }\n }\n if (\n isFirstPartVerb &&\n validParts.length > 1 &&\n validParts[1] &&\n canFallbackToPathSegment\n ) {\n const secondPartCamel = camelcase(validParts[1]);\n if (secondPartCamel) {\n // Sanitize just before returning\n return sanitizeTag(secondPartCamel);\n }\n }\n } // End if(validParts.length > 0) after quick skip check\n } // End if(operationId)\n\n // --- Heuristic 3: First path segment (stripping '@') ---\n if (potentialCandidates.length > 0) {\n let firstCandidate = potentialCandidates[0];\n if (firstCandidate.startsWith('@')) {\n firstCandidate = firstCandidate.substring(1);\n }\n if (firstCandidate) {\n // Sanitize just before returning\n return sanitizeTag(camelcase(firstCandidate));\n }\n }\n\n // --- Heuristic 4: Default ---\n console.warn(\n `Could not determine a suitable tag for path: ${pathString}, operationId: ${operationId}. Using 'unknown'.`,\n );\n return 'unknown'; // 'unknown' is safe\n}\n\nexport function parseJsonContentType(contentType: string | null | undefined) {\n if (!contentType) {\n return null;\n }\n\n // 1. Trim whitespace\n let mainType = contentType.trim();\n\n // 2. Remove parameters (anything after the first ';')\n const semicolonIndex = mainType.indexOf(';');\n if (semicolonIndex !== -1) {\n mainType = mainType.substring(0, semicolonIndex).trim(); // Trim potential space before ';'\n }\n\n // 3. Convert to lowercase for case-insensitive comparison\n mainType = mainType.toLowerCase();\n\n if (mainType.endsWith('/json')) {\n return mainType.split('/')[1];\n } else if (mainType.endsWith('+json')) {\n return mainType.split('+')[1];\n }\n return null;\n}\n\n/**\n * Checks if a given content type string represents Server-Sent Events (SSE).\n * Handles case-insensitivity, parameters (like charset), and leading/trailing whitespace.\n *\n * @param contentType The content type string to check (e.g., from a Content-Type header).\n * @returns True if the content type is 'text/event-stream', false otherwise.\n */\nexport function isSseContentType(\n contentType: string | null | undefined,\n): boolean {\n if (!contentType) {\n return false; // Handle null, undefined, or empty string\n }\n\n // 1. Trim whitespace from the input string\n let mainType = contentType.trim();\n\n // 2. Find the position of the first semicolon (if any) to remove parameters\n const semicolonIndex = mainType.indexOf(';');\n if (semicolonIndex !== -1) {\n // Extract the part before the semicolon and trim potential space\n mainType = mainType.substring(0, semicolonIndex).trim();\n }\n\n // 3. Convert the main type part to lowercase for case-insensitive comparison\n mainType = mainType.toLowerCase();\n\n // 4. Compare against the standard SSE MIME type\n return mainType === 'text/event-stream';\n}\n\nexport function isStreamingContentType(\n contentType: string | null | undefined,\n): boolean {\n return contentType === 'application/octet-stream';\n}\n\nexport function isSuccessStatusCode(statusCode: number | string): boolean {\n statusCode = Number(statusCode);\n return statusCode >= 200 && statusCode < 300;\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type {\n ComponentsObject,\n OpenAPIObject,\n OperationObject,\n ParameterLocation,\n ParameterObject,\n PathsObject,\n ReferenceObject,\n RequestBodyObject,\n ResponseObject,\n SchemaObject,\n SecurityRequirementObject,\n} from 'openapi3-ts/oas31';\nimport { camelcase } from 'stringcase';\n\nimport type { Method } from '@sdk-it/core/paths.js';\nimport { followRef, isRef } from '@sdk-it/core/ref.js';\n\nimport {\n type PaginationGuess,\n guessPagination,\n} from './pagination/pagination.js';\n\nexport function augmentSpec(config: GenerateSdkConfig) {\n config.spec.paths ??= {};\n const paths: PathsObject = {};\n for (const [path, pathItem] of Object.entries(config.spec.paths)) {\n const { parameters = [], ...methods } = pathItem;\n\n // Convert Express-style routes (:param) to OpenAPI-style routes ({param})\n const fixedPath = path.replace(/:([^/]+)/g, '{$1}');\n for (const [method, operation] of Object.entries(methods) as [\n Method,\n OperationObject,\n ][]) {\n const formatOperationId = config.operationId ?? defaults.operationId;\n const formatTag = config.tag ?? defaults.tag;\n const operationId = formatOperationId(operation, fixedPath, method);\n const operationTag = formatTag(operation, fixedPath);\n const requestBody = isRef(operation.requestBody)\n ? followRef<RequestBodyObject>(config.spec, operation.requestBody.$ref)\n : operation.requestBody;\n const tunedOperation: TunedOperationObject = {\n ...operation,\n parameters: [...parameters, ...(operation.parameters ?? [])].map(\n (it) =>\n isRef(it) ? followRef<ParameterObject>(config.spec, it.$ref) : it,\n ),\n tags: [operationTag],\n operationId: operationId,\n responses: resolveResponses(config.spec, operation),\n requestBody: requestBody,\n };\n\n tunedOperation['x-pagination'] = toPagination(\n config.spec,\n tunedOperation,\n );\n\n Object.assign(paths, {\n [fixedPath]: {\n ...paths[fixedPath],\n [method]: tunedOperation,\n },\n });\n }\n }\n return { ...config.spec, paths };\n}\n\nexport type OperationPagination = PaginationGuess & {\n items: string;\n};\n\nfunction toPagination(\n spec: OpenAPIObject,\n tunedOperation: TunedOperationObject,\n) {\n if (tunedOperation['x-pagination']) {\n return tunedOperation['x-pagination'];\n }\n const schema = getResponseContentSchema(\n spec,\n tunedOperation.responses['200'],\n 'application/json',\n );\n const pagination = guessPagination(\n tunedOperation,\n tunedOperation.requestBody\n ? getRequestContentSchema(\n spec,\n tunedOperation.requestBody,\n 'application/json',\n )\n : undefined,\n schema,\n );\n if (pagination && pagination.type !== 'none' && schema) {\n // console.dir({\n // [`${method.toUpperCase()} ${fixedPath}`]: {\n // ...pagination,\n // },\n // });\n return pagination;\n }\n return undefined;\n}\n\nfunction getResponseContentSchema(\n spec: OpenAPIObject,\n response: ResponseObject,\n type: string,\n) {\n if (!response) {\n return undefined;\n }\n const content = response.content;\n if (!content) {\n return undefined;\n }\n for (const contentType in content) {\n if (contentType.toLowerCase() === type.toLowerCase()) {\n return isRef(content[contentType].schema)\n ? followRef<SchemaObject>(spec, content[contentType].schema.$ref)\n : content[contentType].schema;\n }\n }\n return undefined;\n}\n\nfunction getRequestContentSchema(\n spec: OpenAPIObject,\n requestBody: RequestBodyObject,\n type: string,\n) {\n const content = requestBody.content;\n if (!content) {\n return undefined;\n }\n for (const contentType in content) {\n if (contentType.toLowerCase() === type.toLowerCase()) {\n return isRef(content[contentType].schema)\n ? followRef<SchemaObject>(spec, content[contentType].schema.$ref)\n : content[contentType].schema;\n }\n }\n return undefined;\n}\n\nexport const defaults: Partial<GenerateSdkConfig> &\n Required<Pick<GenerateSdkConfig, 'operationId' | 'tag'>> = {\n operationId: (operation, path, method) => {\n if (operation.operationId) {\n return camelcase(operation.operationId);\n }\n const metadata = operation['x-oaiMeta'];\n if (metadata && metadata.name) {\n return camelcase(metadata.name);\n }\n return camelcase(\n [method, ...path.replace(/[\\\\/\\\\{\\\\}]/g, ' ').split(' ')]\n .filter(Boolean)\n .join(' ')\n .trim(),\n );\n },\n tag: (operation, path) => {\n return operation.tags?.[0]\n ? sanitizeTag(operation.tags?.[0])\n : determineGenericTag(path, operation);\n },\n};\n\nexport type TunedOperationObject = Omit<\n OperationObject,\n 'operationId' | 'parameters' | 'responses'\n> & {\n operationId: string;\n parameters: ParameterObject[];\n responses: Record<string, ResponseObject>;\n requestBody: RequestBodyObject | undefined;\n};\n\nexport interface OperationEntry {\n name?: string;\n method: string;\n path: string;\n groupName: string;\n tag: string;\n}\nexport type Operation = {\n entry: OperationEntry;\n operation: TunedOperationObject;\n};\n\nfunction resolveResponses(spec: OpenAPIObject, operation: OperationObject) {\n const responses = operation.responses ?? {};\n const resolved: Record<string, ResponseObject> = {};\n for (const status in responses) {\n const response = isRef(responses[status] as ReferenceObject)\n ? followRef<ResponseObject>(spec, responses[status].$ref)\n : (responses[status] as ResponseObject);\n resolved[status] = response;\n }\n return resolved;\n}\n\nexport function forEachOperation<T>(\n config: GenerateSdkConfig,\n callback: (entry: OperationEntry, operation: TunedOperationObject) => T,\n) {\n const result: T[] = [];\n for (const [path, pathItem] of Object.entries(config.spec.paths ?? {})) {\n const { parameters = [], ...methods } = pathItem;\n\n for (const [method, operation] of Object.entries(methods) as [\n string,\n OperationObject,\n ][]) {\n const metadata = operation['x-oaiMeta'] ?? {};\n const operationTag = operation.tags?.[0] as string;\n\n result.push(\n callback(\n {\n name: metadata.name,\n method,\n path: path,\n groupName: operationTag,\n tag: operationTag,\n },\n operation as TunedOperationObject,\n ),\n );\n }\n }\n return result;\n}\n\nexport interface GenerateSdkConfig {\n spec: OpenAPIObject;\n operationId?: (\n operation: OperationObject,\n path: string,\n method: string,\n ) => string;\n tag?: (operation: OperationObject, path: string) => string;\n}\n\n/**\n * Set of reserved TypeScript keywords and common verbs potentially used as tags.\n */\n\nconst reservedKeywords = new Set([\n 'await', // Reserved in async functions\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'enum',\n 'export',\n 'extends',\n 'false',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'implements', // Strict mode\n 'import',\n 'in',\n 'instanceof',\n 'interface', // Strict mode\n 'let', // Strict mode\n 'new',\n 'null',\n 'package', // Strict mode\n 'private', // Strict mode\n 'protected', // Strict mode\n 'public', // Strict mode\n 'return',\n 'static', // Strict mode\n 'super',\n 'switch',\n 'this',\n 'throw',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield', // Strict mode / Generator functions\n // 'arguments' is not technically a reserved word, but it's a special identifier within functions\n // and assigning to it or declaring it can cause issues or unexpected behavior.\n 'arguments',\n]);\n\n/**\n * Sanitizes a potential tag name (assumed to be already camelCased)\n * to avoid conflicts with reserved keywords or invalid starting characters (numbers).\n * Appends an underscore if the tag matches a reserved keyword.\n * Prepends an underscore if the tag starts with a number.\n * @param camelCasedTag The potential tag name, already camelCased.\n * @returns The sanitized tag name.\n */\nfunction sanitizeTag(camelCasedTag: string): string {\n // Prepend underscore if starts with a number\n if (/^\\d/.test(camelCasedTag)) {\n return `_${camelCasedTag}`;\n }\n // Append underscore if it's a reserved keyword\n return reservedKeywords.has(camelcase(camelCasedTag))\n ? `${camelCasedTag}_`\n : camelCasedTag;\n}\n\n/**\n * Attempts to determine a generic tag for an OpenAPI operation based on path and operationId.\n * Rules and fallbacks are documented within the code.\n * @param pathString The path string.\n * @param operation The OpenAPI Operation Object.\n * @returns A sanitized, camelCased tag name string.\n */\nexport function determineGenericTag(\n pathString: string,\n operation: OperationObject,\n): string {\n const operationId = operation.operationId || '';\n const VERSION_REGEX = /^[vV]\\d+$/;\n const commonVerbs = new Set([\n // Verbs to potentially strip from operationId prefix\n 'get',\n 'list',\n 'create',\n 'update',\n 'delete',\n 'post',\n 'put',\n 'patch',\n 'do',\n 'send',\n 'add',\n 'remove',\n 'set',\n 'find',\n 'search',\n 'check',\n 'make',\n ]);\n\n const segments = pathString.split('/').filter(Boolean);\n\n const potentialCandidates = segments.filter(\n (segment) =>\n segment &&\n !segment.startsWith('{') &&\n !segment.endsWith('}') &&\n !VERSION_REGEX.test(segment),\n );\n\n // --- Heuristic 1: Last non-'@' path segment ---\n for (let i = potentialCandidates.length - 1; i >= 0; i--) {\n const segment = potentialCandidates[i];\n if (!segment.startsWith('@')) {\n // Sanitize just before returning\n return sanitizeTag(camelcase(segment));\n }\n }\n\n const canFallbackToPathSegment = potentialCandidates.length > 0;\n\n // --- Heuristic 2: OperationId parsing ---\n if (operationId) {\n const lowerOpId = operationId.toLowerCase();\n const parts = operationId\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/([A-Z])([A-Z][a-z])/g, '$1_$2')\n .replace(/([a-zA-Z])(\\d)/g, '$1_$2')\n .replace(/(\\d)([a-zA-Z])/g, '$1_$2')\n .toLowerCase()\n .split(/[_-\\s]+/);\n\n const validParts = parts.filter(Boolean);\n\n // Quick skip: If opId is just a verb and we can use Heuristic 3, prefer that.\n if (\n commonVerbs.has(lowerOpId) &&\n validParts.length === 1 &&\n canFallbackToPathSegment\n ) {\n // Proceed directly to Heuristic 3\n }\n // Only process if there are valid parts and the quick skip didn't happen\n else if (validParts.length > 0) {\n const firstPart = validParts[0];\n const isFirstPartVerb = commonVerbs.has(firstPart);\n\n // Case 2a: Starts with verb, has following parts\n if (isFirstPartVerb && validParts.length > 1) {\n const verbPrefixLength = firstPart.length;\n let nextPartStartIndex = -1;\n if (operationId.length > verbPrefixLength) {\n // Simplified check for next part start\n const charAfterPrefix = operationId[verbPrefixLength];\n if (charAfterPrefix >= 'A' && charAfterPrefix <= 'Z') {\n nextPartStartIndex = verbPrefixLength;\n } else if (charAfterPrefix >= '0' && charAfterPrefix <= '9') {\n nextPartStartIndex = verbPrefixLength;\n } else if (['_', '-'].includes(charAfterPrefix)) {\n nextPartStartIndex = verbPrefixLength + 1;\n } else {\n const match = operationId\n .substring(verbPrefixLength)\n .match(/[A-Z0-9]/);\n if (match && match.index !== undefined) {\n nextPartStartIndex = verbPrefixLength + match.index;\n }\n if (\n nextPartStartIndex === -1 &&\n operationId.length > verbPrefixLength\n ) {\n nextPartStartIndex = verbPrefixLength; // Default guess\n }\n }\n }\n\n if (\n nextPartStartIndex !== -1 &&\n nextPartStartIndex < operationId.length\n ) {\n const remainingOriginalSubstring =\n operationId.substring(nextPartStartIndex);\n const potentialTag = camelcase(remainingOriginalSubstring);\n if (potentialTag) {\n // Sanitize just before returning\n return sanitizeTag(potentialTag);\n }\n }\n\n // Fallback: join remaining lowercased parts\n const potentialTagJoined = camelcase(validParts.slice(1).join('_'));\n if (potentialTagJoined) {\n // Sanitize just before returning\n return sanitizeTag(potentialTagJoined);\n }\n }\n\n // Case 2b: Doesn't start with verb, or only one part (might be verb)\n const potentialTagFull = camelcase(operationId);\n if (potentialTagFull) {\n const isResultSingleVerb = validParts.length === 1 && isFirstPartVerb;\n\n // Avoid returning only a verb if Heuristic 3 is possible\n if (!(isResultSingleVerb && canFallbackToPathSegment)) {\n if (potentialTagFull.length > 0) {\n // Sanitize just before returning\n return sanitizeTag(potentialTagFull);\n }\n }\n }\n\n // Case 2c: Further fallbacks within OpId if above failed/skipped\n const firstPartCamel = camelcase(firstPart);\n if (firstPartCamel) {\n const isFirstPartCamelVerb = commonVerbs.has(firstPartCamel);\n if (\n !isFirstPartCamelVerb ||\n validParts.length === 1 ||\n !canFallbackToPathSegment\n ) {\n // Sanitize just before returning\n return sanitizeTag(firstPartCamel);\n }\n }\n if (\n isFirstPartVerb &&\n validParts.length > 1 &&\n validParts[1] &&\n canFallbackToPathSegment\n ) {\n const secondPartCamel = camelcase(validParts[1]);\n if (secondPartCamel) {\n // Sanitize just before returning\n return sanitizeTag(secondPartCamel);\n }\n }\n } // End if(validParts.length > 0) after quick skip check\n } // End if(operationId)\n\n // --- Heuristic 3: First path segment (stripping '@') ---\n if (potentialCandidates.length > 0) {\n let firstCandidate = potentialCandidates[0];\n if (firstCandidate.startsWith('@')) {\n firstCandidate = firstCandidate.substring(1);\n }\n if (firstCandidate) {\n // Sanitize just before returning\n return sanitizeTag(camelcase(firstCandidate));\n }\n }\n\n // --- Heuristic 4: Default ---\n console.warn(\n `Could not determine a suitable tag for path: ${pathString}, operationId: ${operationId}. Using 'unknown'.`,\n );\n return 'unknown'; // 'unknown' is safe\n}\n\nexport function parseJsonContentType(contentType: string | null | undefined) {\n if (!contentType) {\n return null;\n }\n\n // 1. Trim whitespace\n let mainType = contentType.trim();\n\n // 2. Remove parameters (anything after the first ';')\n const semicolonIndex = mainType.indexOf(';');\n if (semicolonIndex !== -1) {\n mainType = mainType.substring(0, semicolonIndex).trim(); // Trim potential space before ';'\n }\n\n // 3. Convert to lowercase for case-insensitive comparison\n mainType = mainType.toLowerCase();\n\n if (mainType.endsWith('/json')) {\n return mainType.split('/')[1];\n } else if (mainType.endsWith('+json')) {\n return mainType.split('+')[1];\n }\n return null;\n}\n\n/**\n * Checks if a given content type string represents Server-Sent Events (SSE).\n * Handles case-insensitivity, parameters (like charset), and leading/trailing whitespace.\n *\n * @param contentType The content type string to check (e.g., from a Content-Type header).\n * @returns True if the content type is 'text/event-stream', false otherwise.\n */\nexport function isSseContentType(\n contentType: string | null | undefined,\n): boolean {\n if (!contentType) {\n return false; // Handle null, undefined, or empty string\n }\n\n // 1. Trim whitespace from the input string\n let mainType = contentType.trim();\n\n // 2. Find the position of the first semicolon (if any) to remove parameters\n const semicolonIndex = mainType.indexOf(';');\n if (semicolonIndex !== -1) {\n // Extract the part before the semicolon and trim potential space\n mainType = mainType.substring(0, semicolonIndex).trim();\n }\n\n // 3. Convert the main type part to lowercase for case-insensitive comparison\n mainType = mainType.toLowerCase();\n\n // 4. Compare against the standard SSE MIME type\n return mainType === 'text/event-stream';\n}\n\nexport function isStreamingContentType(\n contentType: string | null | undefined,\n): boolean {\n return contentType === 'application/octet-stream';\n}\n\nexport function isSuccessStatusCode(statusCode: number | string): boolean {\n statusCode = Number(statusCode);\n return statusCode >= 200 && statusCode < 300;\n}\n\nexport function patchParameters(\n spec: OpenAPIObject,\n objectSchema: SchemaObject,\n operation: TunedOperationObject,\n) {\n const securitySchemes = spec.components?.securitySchemes ?? {};\n const securityOptions = securityToOptions(\n spec,\n operation.security ?? [],\n securitySchemes,\n );\n\n objectSchema.properties ??= {};\n objectSchema.required ??= [];\n for (const param of operation.parameters) {\n if (param.required) {\n objectSchema.required.push(param.name);\n }\n objectSchema.properties[param.name] = isRef(param.schema)\n ? followRef<SchemaObject>(spec, param.schema.$ref)\n : (param.schema ?? { type: 'string' });\n }\n for (const param of securityOptions) {\n objectSchema.required = (objectSchema.required ?? []).filter(\n (name) => name !== param.name,\n );\n objectSchema.properties[param.name] = isRef(param.schema)\n ? followRef<SchemaObject>(spec, param.schema.$ref)\n : (param.schema ?? { type: 'string' });\n }\n}\n\nexport function securityToOptions(\n spec: OpenAPIObject,\n security: SecurityRequirementObject[],\n securitySchemes: ComponentsObject['securitySchemes'],\n staticIn?: ParameterLocation,\n) {\n securitySchemes ??= {};\n const parameters: ParameterObject[] = [];\n for (const it of security) {\n const [name] = Object.keys(it);\n if (!name) {\n // this means the operation doesn't necessarily require security\n continue;\n }\n const schema = isRef(securitySchemes[name])\n ? followRef(spec, securitySchemes[name].$ref)\n : securitySchemes[name];\n\n if (schema.type === 'http') {\n parameters.push({\n in: staticIn ?? 'header',\n name: 'authorization',\n schema: { type: 'string' },\n });\n continue;\n }\n if (schema.type === 'apiKey') {\n if (!schema.in) {\n throw new Error(`apiKey security schema must have an \"in\" field`);\n }\n if (!schema.name) {\n throw new Error(`apiKey security schema must have a \"name\" field`);\n }\n parameters.push({\n in: staticIn ?? (schema.in as ParameterLocation),\n name: schema.name,\n schema: { type: 'string' },\n });\n continue;\n }\n }\n return parameters;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SchemaObject, SchemasObject } from 'openapi3-ts/oas31';
|
|
2
|
+
/**
|
|
3
|
+
* Tries to guess the name of the property that holds the main list of items
|
|
4
|
+
* within an object schema using a series of heuristics.
|
|
5
|
+
*
|
|
6
|
+
* @param schema The OpenAPI SchemaObject, expected to be of type 'object'.
|
|
7
|
+
* @returns The name of the most likely property containing the items array,
|
|
8
|
+
* or null if no array properties are found in the schema.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getItemsName(properties: Record<string, SchemaObject>): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Tries to guess the name of a boolean property that indicates if there are more items
|
|
13
|
+
* to fetch (e.g., for pagination).
|
|
14
|
+
*
|
|
15
|
+
* @param schema The OpenAPI SchemaObject, expected to be of type 'object'.
|
|
16
|
+
* @returns The name of the most likely boolean property indicating "has more",
|
|
17
|
+
* or null if no suitable boolean property is found.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getHasMoreName(properties: SchemasObject): string | null;
|
|
20
|
+
//# sourceMappingURL=pagination-result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-result.d.ts","sourceRoot":"","sources":["../../../src/lib/pagination/pagination-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAoHrE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACvC,MAAM,GAAG,IAAI,CAmFf;AAoFD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAevE"}
|