@sdk-it/spec 0.46.3 → 0.46.5

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.
Files changed (77) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/find-unique-schema-name.d.ts +2 -2
  6. package/dist/lib/find-unique-schema-name.d.ts.map +1 -1
  7. package/dist/lib/find-unique-schema-name.js.map +2 -2
  8. package/dist/lib/loaders/load-spec.d.ts.map +1 -1
  9. package/dist/lib/loaders/load-spec.js +13 -3
  10. package/dist/lib/loaders/load-spec.js.map +2 -2
  11. package/dist/lib/options.d.ts +7 -2
  12. package/dist/lib/options.d.ts.map +1 -1
  13. package/dist/lib/options.js +11 -1
  14. package/dist/lib/options.js.map +2 -2
  15. package/dist/lib/overview-docs/doc-text-utils.d.ts +0 -20
  16. package/dist/lib/overview-docs/doc-text-utils.d.ts.map +1 -1
  17. package/dist/lib/overview-docs/doc-text-utils.js +0 -37
  18. package/dist/lib/overview-docs/doc-text-utils.js.map +2 -2
  19. package/dist/lib/overview-docs/overview-docs.d.ts +8 -1
  20. package/dist/lib/overview-docs/overview-docs.d.ts.map +1 -1
  21. package/dist/lib/overview-docs/overview-docs.js +37 -12
  22. package/dist/lib/overview-docs/overview-docs.js.map +2 -2
  23. package/dist/lib/overview-docs/overview-page.d.ts +5 -0
  24. package/dist/lib/overview-docs/overview-page.d.ts.map +1 -0
  25. package/dist/lib/overview-docs/overview-page.js +60 -0
  26. package/dist/lib/overview-docs/overview-page.js.map +7 -0
  27. package/dist/lib/overview-docs/overview-sdks.d.ts +3 -0
  28. package/dist/lib/overview-docs/overview-sdks.d.ts.map +1 -0
  29. package/dist/lib/overview-docs/overview-sdks.js +42 -0
  30. package/dist/lib/overview-docs/overview-sdks.js.map +7 -0
  31. package/dist/lib/overview-docs/types.d.ts +23 -0
  32. package/dist/lib/overview-docs/types.d.ts.map +1 -0
  33. package/dist/lib/overview-docs/types.js +29 -0
  34. package/dist/lib/overview-docs/types.js.map +7 -0
  35. package/dist/lib/processing-plugins/create-default-processing-plugins.d.ts.map +1 -1
  36. package/dist/lib/processing-plugins/create-default-processing-plugins.js +4 -0
  37. package/dist/lib/processing-plugins/create-default-processing-plugins.js.map +2 -2
  38. package/dist/lib/processing-plugins/extract-overview-docs.d.ts.map +1 -1
  39. package/dist/lib/processing-plugins/extract-overview-docs.js +96 -3
  40. package/dist/lib/processing-plugins/extract-overview-docs.js.map +2 -2
  41. package/dist/lib/processing-plugins/index.d.ts +2 -0
  42. package/dist/lib/processing-plugins/index.d.ts.map +1 -1
  43. package/dist/lib/processing-plugins/index.js +2 -0
  44. package/dist/lib/processing-plugins/index.js.map +2 -2
  45. package/dist/lib/processing-plugins/normalize-request-bodies.d.ts +2 -2
  46. package/dist/lib/processing-plugins/normalize-request-bodies.d.ts.map +1 -1
  47. package/dist/lib/processing-plugins/normalize-request-bodies.js +6 -21
  48. package/dist/lib/processing-plugins/normalize-request-bodies.js.map +2 -2
  49. package/dist/lib/processing-plugins/normalize-schemas.d.ts.map +1 -1
  50. package/dist/lib/processing-plugins/normalize-schemas.js +10 -1
  51. package/dist/lib/processing-plugins/normalize-schemas.js.map +2 -2
  52. package/dist/lib/processing-plugins/normalize-security.d.ts +3 -0
  53. package/dist/lib/processing-plugins/normalize-security.d.ts.map +1 -0
  54. package/dist/lib/processing-plugins/normalize-security.js +142 -0
  55. package/dist/lib/processing-plugins/normalize-security.js.map +7 -0
  56. package/dist/lib/processing-plugins/resolve-security-scheme-uris.d.ts +9 -0
  57. package/dist/lib/processing-plugins/resolve-security-scheme-uris.d.ts.map +1 -0
  58. package/dist/lib/processing-plugins/resolve-security-scheme-uris.js +139 -0
  59. package/dist/lib/processing-plugins/resolve-security-scheme-uris.js.map +7 -0
  60. package/dist/lib/processing.js.map +1 -1
  61. package/dist/lib/sidebar.js +1 -1
  62. package/dist/lib/sidebar.js.map +2 -2
  63. package/dist/lib/types.d.ts +8 -5
  64. package/dist/lib/types.d.ts.map +1 -1
  65. package/package.json +2 -2
  66. package/dist/lib/overview-docs/doc-templates.d.ts +0 -51
  67. package/dist/lib/overview-docs/doc-templates.d.ts.map +0 -1
  68. package/dist/lib/overview-docs/doc-templates.js +0 -123
  69. package/dist/lib/overview-docs/doc-templates.js.map +0 -7
  70. package/dist/lib/overview-docs/overview-intro.d.ts +0 -4
  71. package/dist/lib/overview-docs/overview-intro.d.ts.map +0 -1
  72. package/dist/lib/overview-docs/overview-intro.js +0 -82
  73. package/dist/lib/overview-docs/overview-intro.js.map +0 -7
  74. package/dist/lib/security.d.ts +0 -12
  75. package/dist/lib/security.d.ts.map +0 -1
  76. package/dist/lib/security.js +0 -78
  77. package/dist/lib/security.js.map +0 -7
@@ -0,0 +1,142 @@
1
+ import { iterateOperations } from "../for-each-operation.js";
2
+ function normalizeSecurity() {
3
+ return {
4
+ name: "normalize-security",
5
+ process({ spec, report }) {
6
+ for (const [name, scheme] of Object.entries(
7
+ spec.components.securitySchemes
8
+ )) {
9
+ const message = invalidSecurityScheme(scheme);
10
+ if (message) {
11
+ report({
12
+ code: "invalid-security-scheme",
13
+ severity: "error",
14
+ path: `components.securitySchemes.${name}`,
15
+ message
16
+ });
17
+ }
18
+ }
19
+ for (const { entry, operation } of iterateOperations(spec)) {
20
+ operation.security = structuredClone(
21
+ operation.security ?? spec.security ?? []
22
+ );
23
+ const path = `${entry.method.toUpperCase()} ${entry.path}`;
24
+ for (const requirement of operation.security) {
25
+ const targets = /* @__PURE__ */ new Map();
26
+ for (const [name, values] of Object.entries(requirement)) {
27
+ const scheme = spec.components.securitySchemes[name];
28
+ if (!scheme) {
29
+ report({
30
+ code: "unresolved-security-scheme",
31
+ severity: "error",
32
+ path,
33
+ message: `Security scheme ${name} must be resolved in components.securitySchemes`
34
+ });
35
+ continue;
36
+ }
37
+ if (scheme.type === "oauth2") {
38
+ const availableScopes = new Set(
39
+ Object.values(scheme.flows ?? {}).flatMap(
40
+ (flow) => Object.keys(flow?.scopes ?? {})
41
+ )
42
+ );
43
+ for (const scope of values) {
44
+ if (!availableScopes.has(scope)) {
45
+ report({
46
+ code: "unknown-oauth-scope",
47
+ severity: "error",
48
+ path,
49
+ message: `OAuth2 scheme ${name} does not declare scope ${scope}`
50
+ });
51
+ }
52
+ }
53
+ }
54
+ const target = credentialTarget(scheme);
55
+ const existing = target ? targets.get(target) : void 0;
56
+ if (target && existing) {
57
+ report({
58
+ code: "conflicting-security-target",
59
+ severity: "error",
60
+ path,
61
+ message: `Security schemes ${existing} and ${name} both use ${target}`
62
+ });
63
+ } else if (target) {
64
+ targets.set(target, name);
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ };
71
+ }
72
+ function invalidSecurityScheme(scheme) {
73
+ const value = scheme;
74
+ switch (value.type) {
75
+ case "apiKey":
76
+ if (typeof value.name !== "string" || value.name.length === 0) {
77
+ return "apiKey security schemes require a name";
78
+ }
79
+ if (!["header", "query", "cookie"].includes(value.in)) {
80
+ return "apiKey security schemes require header, query, or cookie in";
81
+ }
82
+ return void 0;
83
+ case "http":
84
+ return typeof value.scheme === "string" && value.scheme.length > 0 ? void 0 : "HTTP security schemes require a scheme";
85
+ case "mutualTLS":
86
+ return void 0;
87
+ case "openIdConnect":
88
+ return typeof value.openIdConnectUrl === "string" && value.openIdConnectUrl.length > 0 ? void 0 : "OpenID Connect security schemes require openIdConnectUrl";
89
+ case "oauth2": {
90
+ if (!value.flows || typeof value.flows !== "object") {
91
+ return "OAuth2 security schemes require flows";
92
+ }
93
+ const flows = value.flows;
94
+ const requiredUrls = {
95
+ implicit: ["authorizationUrl"],
96
+ password: ["tokenUrl"],
97
+ clientCredentials: ["tokenUrl"],
98
+ authorizationCode: ["authorizationUrl", "tokenUrl"],
99
+ deviceAuthorization: ["deviceAuthorizationUrl", "tokenUrl"]
100
+ };
101
+ const configured = Object.entries(requiredUrls).filter(
102
+ ([flow]) => flows[flow] !== void 0
103
+ );
104
+ if (configured.length === 0) {
105
+ return "OAuth2 security schemes require at least one flow";
106
+ }
107
+ for (const [flowName, fields] of configured) {
108
+ const flow = flows[flowName];
109
+ if (!flow.scopes || typeof flow.scopes !== "object") {
110
+ return `OAuth2 ${flowName} flow requires scopes`;
111
+ }
112
+ for (const field of fields) {
113
+ if (typeof flow[field] !== "string" || flow[field].length === 0) {
114
+ return `OAuth2 ${flowName} flow requires ${field}`;
115
+ }
116
+ }
117
+ }
118
+ return void 0;
119
+ }
120
+ default:
121
+ return `Unsupported security scheme type ${String(value.type)}`;
122
+ }
123
+ }
124
+ function credentialTarget(scheme) {
125
+ switch (scheme.type) {
126
+ case "apiKey": {
127
+ if (!scheme.in || !scheme.name) return void 0;
128
+ const name = scheme.in === "header" ? scheme.name.toLowerCase() : scheme.name;
129
+ return `${scheme.in}:${name}`;
130
+ }
131
+ case "http":
132
+ case "oauth2":
133
+ case "openIdConnect":
134
+ return "header:authorization";
135
+ case "mutualTLS":
136
+ return "transport:client-certificate";
137
+ }
138
+ }
139
+ export {
140
+ normalizeSecurity
141
+ };
142
+ //# sourceMappingURL=normalize-security.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/processing-plugins/normalize-security.ts"],
4
+ "sourcesContent": ["import type { OpenAPISecuritySchemeObject } from '@sdk-it/core';\n\nimport { iterateOperations } from '../for-each-operation.js';\nimport type { ProcessingPlugin } from '../processing.js';\n\nexport function normalizeSecurity(): ProcessingPlugin {\n return {\n name: 'normalize-security',\n process({ spec, report }) {\n for (const [name, scheme] of Object.entries(\n spec.components.securitySchemes,\n )) {\n const message = invalidSecurityScheme(scheme);\n if (message) {\n report({\n code: 'invalid-security-scheme',\n severity: 'error',\n path: `components.securitySchemes.${name}`,\n message,\n });\n }\n }\n for (const { entry, operation } of iterateOperations(spec)) {\n operation.security = structuredClone(\n operation.security ?? spec.security ?? [],\n );\n const path = `${entry.method.toUpperCase()} ${entry.path}`;\n for (const requirement of operation.security) {\n const targets = new Map<string, string>();\n for (const [name, values] of Object.entries(requirement)) {\n const scheme = spec.components.securitySchemes[name];\n if (!scheme) {\n // OpenAPI 3.2 allows external URI references here, but no\n // generator can emit a credential for one.\n report({\n code: 'unresolved-security-scheme',\n severity: 'error',\n path,\n message: `Security scheme ${name} must be resolved in components.securitySchemes`,\n });\n continue;\n }\n if (scheme.type === 'oauth2') {\n const availableScopes = new Set(\n Object.values(scheme.flows ?? {}).flatMap((flow) =>\n Object.keys(flow?.scopes ?? {}),\n ),\n );\n for (const scope of values) {\n if (!availableScopes.has(scope)) {\n report({\n code: 'unknown-oauth-scope',\n severity: 'error',\n path,\n message: `OAuth2 scheme ${name} does not declare scope ${scope}`,\n });\n }\n }\n }\n const target = credentialTarget(scheme);\n const existing = target ? targets.get(target) : undefined;\n if (target && existing) {\n report({\n code: 'conflicting-security-target',\n severity: 'error',\n path,\n message: `Security schemes ${existing} and ${name} both use ${target}`,\n });\n } else if (target) {\n targets.set(target, name);\n }\n }\n }\n }\n },\n };\n}\n\nfunction invalidSecurityScheme(\n scheme: OpenAPISecuritySchemeObject,\n): string | undefined {\n const value = scheme as OpenAPISecuritySchemeObject & Record<string, unknown>;\n switch (value.type as string) {\n case 'apiKey':\n if (typeof value.name !== 'string' || value.name.length === 0) {\n return 'apiKey security schemes require a name';\n }\n if (!['header', 'query', 'cookie'].includes(value.in as string)) {\n return 'apiKey security schemes require header, query, or cookie in';\n }\n return undefined;\n case 'http':\n return typeof value.scheme === 'string' && value.scheme.length > 0\n ? undefined\n : 'HTTP security schemes require a scheme';\n case 'mutualTLS':\n return undefined;\n case 'openIdConnect':\n return typeof value.openIdConnectUrl === 'string' &&\n value.openIdConnectUrl.length > 0\n ? undefined\n : 'OpenID Connect security schemes require openIdConnectUrl';\n case 'oauth2': {\n if (!value.flows || typeof value.flows !== 'object') {\n return 'OAuth2 security schemes require flows';\n }\n const flows = value.flows as Record<\n string,\n Record<string, unknown> | undefined\n >;\n const requiredUrls: Record<string, string[]> = {\n implicit: ['authorizationUrl'],\n password: ['tokenUrl'],\n clientCredentials: ['tokenUrl'],\n authorizationCode: ['authorizationUrl', 'tokenUrl'],\n deviceAuthorization: ['deviceAuthorizationUrl', 'tokenUrl'],\n };\n const configured = Object.entries(requiredUrls).filter(\n ([flow]) => flows[flow] !== undefined,\n );\n if (configured.length === 0) {\n return 'OAuth2 security schemes require at least one flow';\n }\n for (const [flowName, fields] of configured) {\n const flow = flows[flowName]!;\n if (!flow.scopes || typeof flow.scopes !== 'object') {\n return `OAuth2 ${flowName} flow requires scopes`;\n }\n for (const field of fields) {\n if (typeof flow[field] !== 'string' || flow[field].length === 0) {\n return `OAuth2 ${flowName} flow requires ${field}`;\n }\n }\n }\n return undefined;\n }\n default:\n return `Unsupported security scheme type ${String(value.type)}`;\n }\n}\n\nfunction credentialTarget(\n scheme: OpenAPISecuritySchemeObject,\n): string | undefined {\n switch (scheme.type) {\n case 'apiKey': {\n if (!scheme.in || !scheme.name) return undefined;\n const name =\n scheme.in === 'header' ? scheme.name.toLowerCase() : scheme.name;\n return `${scheme.in}:${name}`;\n }\n case 'http':\n case 'oauth2':\n case 'openIdConnect':\n return 'header:authorization';\n case 'mutualTLS':\n return 'transport:client-certificate';\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,9 @@
1
+ import type { ProcessingPlugin } from '../processing.js';
2
+ /**
3
+ * OpenAPI 3.2 lets a security requirement key be a URI of a Security Scheme
4
+ * Object instead of a `components.securitySchemes` name. Generators key
5
+ * credentials by scheme name, so each URI is fetched, registered locally, and
6
+ * the requirement rewritten to point at the registered name.
7
+ */
8
+ export declare function resolveSecuritySchemeUris(): ProcessingPlugin;
9
+ //# sourceMappingURL=resolve-security-scheme-uris.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-security-scheme-uris.d.ts","sourceRoot":"","sources":["../../../src/lib/processing-plugins/resolve-security-scheme-uris.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGzD;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,gBAAgB,CAkD5D"}
@@ -0,0 +1,139 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import {
3
+ followRef,
4
+ isRef
5
+ } from "@sdk-it/core";
6
+ import { iterateOperations } from "../for-each-operation.js";
7
+ import { loadFile } from "../loaders/load-spec.js";
8
+ function resolveSecuritySchemeUris() {
9
+ return {
10
+ name: "resolve-security-scheme-uris",
11
+ async process({ spec, report }) {
12
+ const requirements = collectRequirements(spec);
13
+ const uris = new Set(
14
+ requirements.flatMap((requirement) => Object.keys(requirement)).filter(
15
+ (key) => !spec.components.securitySchemes[key] && isUriKey(key)
16
+ )
17
+ );
18
+ if (!uris.size) {
19
+ return;
20
+ }
21
+ const documents = /* @__PURE__ */ new Map();
22
+ const registered = /* @__PURE__ */ new Map();
23
+ for (const uri of uris) {
24
+ try {
25
+ const scheme = await resolveScheme(uri, spec, documents);
26
+ const [alias] = Object.entries(spec.components.securitySchemes).find(
27
+ ([, registeredScheme]) => registeredScheme === scheme
28
+ ) ?? [];
29
+ const name = alias ?? availableName(spec, schemeName(uri));
30
+ spec.components.securitySchemes[name] = scheme;
31
+ registered.set(uri, name);
32
+ } catch (error) {
33
+ report({
34
+ code: "unresolvable-security-scheme-uri",
35
+ severity: "error",
36
+ path: uri,
37
+ message: `Could not resolve security scheme URI ${uri}: ${error instanceof Error ? error.message : String(error)}`
38
+ });
39
+ }
40
+ }
41
+ for (const requirement of requirements) {
42
+ for (const [uri, name] of registered) {
43
+ if (Object.hasOwn(requirement, uri)) {
44
+ requirement[name] = requirement[uri];
45
+ delete requirement[uri];
46
+ }
47
+ }
48
+ }
49
+ }
50
+ };
51
+ }
52
+ function collectRequirements(spec) {
53
+ const requirements = [...spec.security ?? []];
54
+ for (const { operation } of iterateOperations(spec)) {
55
+ requirements.push(...operation.security ?? []);
56
+ }
57
+ return requirements;
58
+ }
59
+ function isUriKey(key) {
60
+ return !/^[a-zA-Z0-9._-]+$/.test(key);
61
+ }
62
+ async function resolveScheme(uri, spec, documents) {
63
+ const [location, fragment] = splitFragment(uri);
64
+ const document = location ? await loadDocument(location, spec, documents) : spec;
65
+ let scheme = fragment ? readPointer(document, fragment) : document;
66
+ if (isRef(scheme)) {
67
+ scheme = followRef(document, scheme.$ref);
68
+ }
69
+ if (scheme === null || typeof scheme !== "object" || typeof scheme.type !== "string") {
70
+ return Promise.reject(
71
+ new Error("the target is not a Security Scheme Object")
72
+ );
73
+ }
74
+ return scheme;
75
+ }
76
+ function loadDocument(location, spec, documents) {
77
+ const base = spec.$self;
78
+ if (!base && !isAbsolute(location)) {
79
+ return Promise.reject(
80
+ new Error(
81
+ "the document declares no $self, so a relative URI has no base to resolve against"
82
+ )
83
+ );
84
+ }
85
+ const url = new URL(location, base);
86
+ if (url.href === base) {
87
+ return Promise.resolve(spec);
88
+ }
89
+ let pending = documents.get(url.href);
90
+ if (!pending) {
91
+ pending = loadFile(
92
+ url.protocol === "file:" ? fileURLToPath(url) : url.href
93
+ );
94
+ documents.set(url.href, pending);
95
+ }
96
+ return pending;
97
+ }
98
+ function isAbsolute(location) {
99
+ return URL.canParse(location);
100
+ }
101
+ function splitFragment(uri) {
102
+ const index = uri.indexOf("#");
103
+ return index === -1 ? [uri, void 0] : [uri.slice(0, index), uri.slice(index + 1)];
104
+ }
105
+ function readPointer(document, fragment) {
106
+ let current = document;
107
+ for (const segment of fragment.split("/")) {
108
+ if (!segment) {
109
+ continue;
110
+ }
111
+ const key = decodeURIComponent(segment).replaceAll("~1", "/").replaceAll("~0", "~");
112
+ if (current === null || typeof current !== "object" || !(key in current)) {
113
+ throw new Error(`no value at pointer #${fragment}`);
114
+ }
115
+ current = current[key];
116
+ }
117
+ return current;
118
+ }
119
+ function schemeName(uri) {
120
+ const [location, fragment] = splitFragment(uri);
121
+ const candidate = lastSegment(fragment ?? "") ?? lastSegment(location.split("?")[0])?.replace(/\.(json|ya?ml)$/i, "");
122
+ const sanitized = (candidate ?? "").replace(/[^a-zA-Z0-9._-]/g, "");
123
+ return sanitized || "externalSecurityScheme";
124
+ }
125
+ function lastSegment(value) {
126
+ return value.split("/").filter(Boolean).at(-1);
127
+ }
128
+ function availableName(spec, candidate) {
129
+ let name = candidate;
130
+ let suffix = 2;
131
+ while (spec.components.securitySchemes[name]) {
132
+ name = `${candidate}${suffix++}`;
133
+ }
134
+ return name;
135
+ }
136
+ export {
137
+ resolveSecuritySchemeUris
138
+ };
139
+ //# sourceMappingURL=resolve-security-scheme-uris.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/lib/processing-plugins/resolve-security-scheme-uris.ts"],
4
+ "sourcesContent": ["import { fileURLToPath } from 'node:url';\nimport type { SecurityRequirementObject } from 'openapi3-ts/oas31';\n\nimport {\n type OpenAPISecuritySchemeObject,\n followRef,\n isRef,\n} from '@sdk-it/core';\n\nimport { iterateOperations } from '../for-each-operation.js';\nimport { loadFile } from '../loaders/load-spec.js';\nimport type { ProcessingPlugin } from '../processing.js';\nimport type { IR } from '../types.js';\n\n/**\n * OpenAPI 3.2 lets a security requirement key be a URI of a Security Scheme\n * Object instead of a `components.securitySchemes` name. Generators key\n * credentials by scheme name, so each URI is fetched, registered locally, and\n * the requirement rewritten to point at the registered name.\n */\nexport function resolveSecuritySchemeUris(): ProcessingPlugin {\n return {\n name: 'resolve-security-scheme-uris',\n async process({ spec, report }) {\n const requirements = collectRequirements(spec);\n const uris = new Set(\n requirements\n .flatMap((requirement) => Object.keys(requirement))\n .filter(\n (key) => !spec.components.securitySchemes[key] && isUriKey(key),\n ),\n );\n if (!uris.size) {\n return;\n }\n\n const documents = new Map<string, Promise<unknown>>();\n const registered = new Map<string, string>();\n for (const uri of uris) {\n try {\n const scheme = await resolveScheme(uri, spec, documents);\n // A same-document pointer lands on an already registered object;\n // reuse its name instead of registering a second copy.\n const [alias] =\n Object.entries(spec.components.securitySchemes).find(\n ([, registeredScheme]) => registeredScheme === scheme,\n ) ?? [];\n const name = alias ?? availableName(spec, schemeName(uri));\n spec.components.securitySchemes[name] = scheme;\n registered.set(uri, name);\n } catch (error) {\n report({\n code: 'unresolvable-security-scheme-uri',\n severity: 'error',\n path: uri,\n message: `Could not resolve security scheme URI ${uri}: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n }\n\n for (const requirement of requirements) {\n for (const [uri, name] of registered) {\n if (Object.hasOwn(requirement, uri)) {\n requirement[name] = requirement[uri];\n delete requirement[uri];\n }\n }\n }\n },\n };\n}\n\nfunction collectRequirements(spec: IR) {\n const requirements: SecurityRequirementObject[] = [...(spec.security ?? [])];\n for (const { operation } of iterateOperations(spec)) {\n requirements.push(...(operation.security ?? []));\n }\n return requirements;\n}\n\n/**\n * Component keys are limited to `^[a-zA-Z0-9._-]+$`, so anything else can only\n * be a URI. A bare `auth.yaml` stays a name \u2014 treating it as a document would\n * turn a typo into a file read.\n */\nfunction isUriKey(key: string) {\n return !/^[a-zA-Z0-9._-]+$/.test(key);\n}\n\nasync function resolveScheme(\n uri: string,\n spec: IR,\n documents: Map<string, Promise<unknown>>,\n): Promise<OpenAPISecuritySchemeObject> {\n const [location, fragment] = splitFragment(uri);\n const document = location\n ? await loadDocument(location, spec, documents)\n : spec;\n let scheme = fragment ? readPointer(document, fragment) : document;\n if (isRef(scheme)) {\n scheme = followRef(document as never, scheme.$ref);\n }\n if (\n scheme === null ||\n typeof scheme !== 'object' ||\n typeof (scheme as { type?: unknown }).type !== 'string'\n ) {\n return Promise.reject(\n new Error('the target is not a Security Scheme Object'),\n );\n }\n return scheme as OpenAPISecuritySchemeObject;\n}\n\nfunction loadDocument(\n location: string,\n spec: IR,\n documents: Map<string, Promise<unknown>>,\n) {\n const base = spec.$self;\n if (!base && !isAbsolute(location)) {\n return Promise.reject(\n new Error(\n 'the document declares no $self, so a relative URI has no base to resolve against',\n ),\n );\n }\n const url = new URL(location, base);\n if (url.href === base) {\n return Promise.resolve(spec);\n }\n let pending = documents.get(url.href);\n if (!pending) {\n pending = loadFile(\n url.protocol === 'file:' ? fileURLToPath(url) : url.href,\n );\n documents.set(url.href, pending);\n }\n return pending;\n}\n\nfunction isAbsolute(location: string) {\n return URL.canParse(location);\n}\n\nfunction splitFragment(uri: string): [string, string | undefined] {\n const index = uri.indexOf('#');\n return index === -1\n ? [uri, undefined]\n : [uri.slice(0, index), uri.slice(index + 1)];\n}\n\nfunction readPointer(document: unknown, fragment: string) {\n let current: unknown = document;\n for (const segment of fragment.split('/')) {\n if (!segment) {\n continue;\n }\n const key = decodeURIComponent(segment)\n .replaceAll('~1', '/')\n .replaceAll('~0', '~');\n if (\n current === null ||\n typeof current !== 'object' ||\n !(key in (current as object))\n ) {\n throw new Error(`no value at pointer #${fragment}`);\n }\n current = (current as Record<string, unknown>)[key];\n }\n return current;\n}\n\nfunction schemeName(uri: string) {\n const [location, fragment] = splitFragment(uri);\n const candidate =\n lastSegment(fragment ?? '') ??\n lastSegment(location.split('?')[0])?.replace(/\\.(json|ya?ml)$/i, '');\n const sanitized = (candidate ?? '').replace(/[^a-zA-Z0-9._-]/g, '');\n return sanitized || 'externalSecurityScheme';\n}\n\nfunction lastSegment(value: string) {\n return value.split('/').filter(Boolean).at(-1);\n}\n\nfunction availableName(spec: IR, candidate: string) {\n let name = candidate;\n let suffix = 2;\n while (spec.components.securitySchemes[name]) {\n name = `${candidate}${suffix++}`;\n }\n return name;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/processing.ts"],
4
- "sourcesContent": ["import type { OpenAPIObject } from 'openapi3-ts/oas31';\n\nimport {\n type GenerateSdkConfig,\n coeraceConfig as coerceConfig,\n} from './options.js';\nimport type { IR } from './types.js';\n\nexport type ProcessingDiagnosticSeverity = 'info' | 'warning' | 'error';\n\nexport interface ProcessingDiagnostic {\n plugin: string;\n severity: ProcessingDiagnosticSeverity;\n code: string;\n message: string;\n path?: string;\n}\n\nexport type ProcessingOptions = Omit<ReturnType<typeof coerceConfig>, 'spec'>;\n\nexport interface ProcessingContext {\n spec: IR;\n options: ProcessingOptions;\n diagnostics: ProcessingDiagnostic[];\n signal?: AbortSignal;\n report(\n diagnostic: Omit<ProcessingDiagnostic, 'plugin'>,\n ): ProcessingDiagnostic;\n}\n\nexport interface ProcessingPlugin {\n name: string;\n process(context: ProcessingContext): void | Promise<void>;\n}\n\nexport interface ProcessSpecConfig extends GenerateSdkConfig {\n plugins: readonly ProcessingPlugin[];\n signal?: AbortSignal;\n onDiagnostic?: (diagnostic: ProcessingDiagnostic) => void;\n}\n\nexport interface ProcessingResult {\n spec: IR;\n diagnostics: ProcessingDiagnostic[];\n}\n\nexport async function processSpec(\n config: ProcessSpecConfig,\n): Promise<ProcessingResult> {\n const { plugins, signal, onDiagnostic, ...generateConfig } = config;\n signal?.throwIfAborted();\n const coerced = coerceConfig({\n ...generateConfig,\n spec: structuredClone(generateConfig.spec) as OpenAPIObject,\n });\n const { spec, ...options } = coerced;\n const diagnostics: ProcessingDiagnostic[] = [];\n const pluginNames = plugins.map((plugin) => plugin.name);\n const configuration = JSON.stringify({\n pagination: options.pagination,\n responses: options.responses,\n });\n\n for (const plugin of plugins) {\n signal?.throwIfAborted();\n const context: ProcessingContext = {\n spec,\n options,\n diagnostics,\n signal,\n report(diagnostic) {\n const reported = { ...diagnostic, plugin: plugin.name };\n diagnostics.push(reported);\n onDiagnostic?.(reported);\n return reported;\n },\n };\n await plugin.process(context);\n signal?.throwIfAborted();\n }\n\n spec['x-sdk-processing'] = { plugins: pluginNames, configuration };\n\n return { spec, diagnostics };\n}\n"],
4
+ "sourcesContent": ["import type { OpenAPIDocument } from '@sdk-it/core';\n\nimport {\n type GenerateSdkConfig,\n coeraceConfig as coerceConfig,\n} from './options.js';\nimport type { IR } from './types.js';\n\nexport type ProcessingDiagnosticSeverity = 'info' | 'warning' | 'error';\n\nexport interface ProcessingDiagnostic {\n plugin: string;\n severity: ProcessingDiagnosticSeverity;\n code: string;\n message: string;\n path?: string;\n}\n\nexport type ProcessingOptions = Omit<ReturnType<typeof coerceConfig>, 'spec'>;\n\nexport interface ProcessingContext {\n spec: IR;\n options: ProcessingOptions;\n diagnostics: ProcessingDiagnostic[];\n signal?: AbortSignal;\n report(\n diagnostic: Omit<ProcessingDiagnostic, 'plugin'>,\n ): ProcessingDiagnostic;\n}\n\nexport interface ProcessingPlugin {\n name: string;\n process(context: ProcessingContext): void | Promise<void>;\n}\n\nexport interface ProcessSpecConfig extends GenerateSdkConfig {\n plugins: readonly ProcessingPlugin[];\n signal?: AbortSignal;\n onDiagnostic?: (diagnostic: ProcessingDiagnostic) => void;\n}\n\nexport interface ProcessingResult {\n spec: IR;\n diagnostics: ProcessingDiagnostic[];\n}\n\nexport async function processSpec(\n config: ProcessSpecConfig,\n): Promise<ProcessingResult> {\n const { plugins, signal, onDiagnostic, ...generateConfig } = config;\n signal?.throwIfAborted();\n const coerced = coerceConfig({\n ...generateConfig,\n spec: structuredClone(generateConfig.spec) as OpenAPIDocument,\n });\n const { spec, ...options } = coerced;\n const diagnostics: ProcessingDiagnostic[] = [];\n const pluginNames = plugins.map((plugin) => plugin.name);\n const configuration = JSON.stringify({\n pagination: options.pagination,\n responses: options.responses,\n });\n\n for (const plugin of plugins) {\n signal?.throwIfAborted();\n const context: ProcessingContext = {\n spec,\n options,\n diagnostics,\n signal,\n report(diagnostic) {\n const reported = { ...diagnostic, plugin: plugin.name };\n diagnostics.push(reported);\n onDiagnostic?.(reported);\n return reported;\n },\n };\n await plugin.process(context);\n signal?.throwIfAborted();\n }\n\n spec['x-sdk-processing'] = { plugins: pluginNames, configuration };\n\n return { spec, diagnostics };\n}\n"],
5
5
  "mappings": "AAEA;AAAA,EAEE,iBAAiB;AAAA,OACZ;AAyCP,eAAsB,YACpB,QAC2B;AAC3B,QAAM,EAAE,SAAS,QAAQ,cAAc,GAAG,eAAe,IAAI;AAC7D,UAAQ,eAAe;AACvB,QAAM,UAAU,aAAa;AAAA,IAC3B,GAAG;AAAA,IACH,MAAM,gBAAgB,eAAe,IAAI;AAAA,EAC3C,CAAC;AACD,QAAM,EAAE,MAAM,GAAG,QAAQ,IAAI;AAC7B,QAAM,cAAsC,CAAC;AAC7C,QAAM,cAAc,QAAQ,IAAI,CAAC,WAAW,OAAO,IAAI;AACvD,QAAM,gBAAgB,KAAK,UAAU;AAAA,IACnC,YAAY,QAAQ;AAAA,IACpB,WAAW,QAAQ;AAAA,EACrB,CAAC;AAED,aAAW,UAAU,SAAS;AAC5B,YAAQ,eAAe;AACvB,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,YAAY;AACjB,cAAM,WAAW,EAAE,GAAG,YAAY,QAAQ,OAAO,KAAK;AACtD,oBAAY,KAAK,QAAQ;AACzB,uBAAe,QAAQ;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,OAAO,QAAQ,OAAO;AAC5B,YAAQ,eAAe;AAAA,EACzB;AAEA,OAAK,kBAAkB,IAAI,EAAE,SAAS,aAAa,cAAc;AAEjE,SAAO,EAAE,MAAM,YAAY;AAC7B;",
6
6
  "names": []
7
7
  }
@@ -2,7 +2,7 @@ import { camelcase } from "stringcase";
2
2
  import { notNullOrUndefined } from "@sdk-it/core/file-system.js";
3
3
  import { forEachOperation } from "./for-each-operation.js";
4
4
  function toSidebar(spec) {
5
- const sidebar = spec["x-docs"];
5
+ const sidebar = [...spec["x-docs"]];
6
6
  for (const tagGroup of spec["x-tagGroups"]) {
7
7
  sidebar.push({
8
8
  id: camelcase(tagGroup.name),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/sidebar.ts"],
4
- "sourcesContent": ["import { camelcase } from 'stringcase';\n\nimport { notNullOrUndefined } from '@sdk-it/core/file-system.js';\n\nimport { forEachOperation } from './for-each-operation.js';\nimport type { IR } from './types.js';\n\nexport type ChildNavItem = {\n id: string;\n title: string;\n url: string;\n};\n\nexport type NavItem = {\n id: string;\n title: string;\n description?: string;\n url?: string;\n items?: ChildNavItem[];\n content?: string; // Markdown content\n};\n\nexport type CategoryItem = {\n id: string;\n category: string;\n description?: string;\n items: NavItem[];\n};\n\nexport type SidebarData = CategoryItem[];\n\nexport interface TagGroups {\n name: string;\n tags: string[];\n}\n\nexport function toSidebar(spec: IR) {\n const sidebar: SidebarData = spec['x-docs'];\n for (const tagGroup of spec['x-tagGroups']) {\n sidebar.push({\n id: camelcase(tagGroup.name),\n category: tagGroup.name,\n items: tagGroup.tags.map((tag) => {\n const tagSpec = spec.tags?.find((t) => t.name === tag);\n return {\n id: crypto.randomUUID(),\n description: tagSpec?.description,\n title: tagSpec\n ? tagSpec['x-displayName'] || tagSpec.name || tag\n : tag,\n items: forEachOperation(spec, (entry, operation) => {\n if (operation.tags.includes(tag)) {\n const title = operation.summary || operation.operationId;\n return {\n id: operation.operationId,\n title,\n url: `${camelcase(tag)}/${camelcase(operation.operationId)}`,\n };\n }\n return null;\n }).filter(notNullOrUndefined),\n };\n }),\n });\n }\n return sidebar;\n}\n"],
5
- "mappings": "AAAA,SAAS,iBAAiB;AAE1B,SAAS,0BAA0B;AAEnC,SAAS,wBAAwB;AAgC1B,SAAS,UAAU,MAAU;AAClC,QAAM,UAAuB,KAAK,QAAQ;AAC1C,aAAW,YAAY,KAAK,aAAa,GAAG;AAC1C,YAAQ,KAAK;AAAA,MACX,IAAI,UAAU,SAAS,IAAI;AAAA,MAC3B,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS,KAAK,IAAI,CAAC,QAAQ;AAChC,cAAM,UAAU,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG;AACrD,eAAO;AAAA,UACL,IAAI,OAAO,WAAW;AAAA,UACtB,aAAa,SAAS;AAAA,UACtB,OAAO,UACH,QAAQ,eAAe,KAAK,QAAQ,QAAQ,MAC5C;AAAA,UACJ,OAAO,iBAAiB,MAAM,CAAC,OAAO,cAAc;AAClD,gBAAI,UAAU,KAAK,SAAS,GAAG,GAAG;AAChC,oBAAM,QAAQ,UAAU,WAAW,UAAU;AAC7C,qBAAO;AAAA,gBACL,IAAI,UAAU;AAAA,gBACd;AAAA,gBACA,KAAK,GAAG,UAAU,GAAG,CAAC,IAAI,UAAU,UAAU,WAAW,CAAC;AAAA,cAC5D;AAAA,YACF;AACA,mBAAO;AAAA,UACT,CAAC,EAAE,OAAO,kBAAkB;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACA,SAAO;AACT;",
4
+ "sourcesContent": ["import { camelcase } from 'stringcase';\n\nimport { notNullOrUndefined } from '@sdk-it/core/file-system.js';\n\nimport { forEachOperation } from './for-each-operation.js';\nimport type { IR } from './types.js';\n\nexport type ChildNavItem = {\n id: string;\n title: string;\n url: string;\n};\n\nexport type NavItem = {\n id: string;\n title: string;\n description?: string;\n url?: string;\n items?: ChildNavItem[];\n content?: string; // Markdown content\n};\n\nexport type CategoryItem = {\n id: string;\n category: string;\n description?: string;\n items: NavItem[];\n};\n\nexport type SidebarData = CategoryItem[];\n\nexport interface TagGroups {\n name: string;\n tags: string[];\n}\n\nexport function toSidebar(spec: IR) {\n const sidebar: SidebarData = [...spec['x-docs']];\n for (const tagGroup of spec['x-tagGroups']) {\n sidebar.push({\n id: camelcase(tagGroup.name),\n category: tagGroup.name,\n items: tagGroup.tags.map((tag) => {\n const tagSpec = spec.tags?.find((t) => t.name === tag);\n return {\n id: crypto.randomUUID(),\n description: tagSpec?.description,\n title: tagSpec\n ? tagSpec['x-displayName'] || tagSpec.name || tag\n : tag,\n items: forEachOperation(spec, (entry, operation) => {\n if (operation.tags.includes(tag)) {\n const title = operation.summary || operation.operationId;\n return {\n id: operation.operationId,\n title,\n url: `${camelcase(tag)}/${camelcase(operation.operationId)}`,\n };\n }\n return null;\n }).filter(notNullOrUndefined),\n };\n }),\n });\n }\n return sidebar;\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAE1B,SAAS,0BAA0B;AAEnC,SAAS,wBAAwB;AAgC1B,SAAS,UAAU,MAAU;AAClC,QAAM,UAAuB,CAAC,GAAG,KAAK,QAAQ,CAAC;AAC/C,aAAW,YAAY,KAAK,aAAa,GAAG;AAC1C,YAAQ,KAAK;AAAA,MACX,IAAI,UAAU,SAAS,IAAI;AAAA,MAC3B,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS,KAAK,IAAI,CAAC,QAAQ;AAChC,cAAM,UAAU,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG;AACrD,eAAO;AAAA,UACL,IAAI,OAAO,WAAW;AAAA,UACtB,aAAa,SAAS;AAAA,UACtB,OAAO,UACH,QAAQ,eAAe,KAAK,QAAQ,QAAQ,MAC5C;AAAA,UACJ,OAAO,iBAAiB,MAAM,CAAC,OAAO,cAAc;AAClD,gBAAI,UAAU,KAAK,SAAS,GAAG,GAAG;AAChC,oBAAM,QAAQ,UAAU,WAAW,UAAU;AAC7C,qBAAO;AAAA,gBACL,IAAI,UAAU;AAAA,gBACd;AAAA,gBACA,KAAK,GAAG,UAAU,GAAG,CAAC,IAAI,UAAU,UAAU,WAAW,CAAC;AAAA,cAC5D;AAAA,YACF;AACA,mBAAO;AAAA,UACT,CAAC,EAAE,OAAO,kBAAkB;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,21 +1,24 @@
1
- import type { ComponentsObject, MediaTypeObject, OpenAPIObject, OperationObject, ParameterObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, SchemaObject, SecuritySchemeObject, ServerObject, TagObject } from 'openapi3-ts/oas31';
1
+ import type { MediaTypeObject, OperationObject, ParameterObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, SchemaObject, ServerObject, TagObject } from 'openapi3-ts/oas31';
2
+ import type { OpenAPIComponentsObject, OpenAPIDocument, OpenAPISecuritySchemeObject } from '@sdk-it/core';
3
+ import type { SdkDoc } from './overview-docs/types.js';
2
4
  import type { PaginationGuess } from './pagination/guess-pagination.js';
3
5
  import type { SidebarData, TagGroups } from './sidebar.js';
4
- export interface IR extends OpenAPIObject {
6
+ export type IR = Omit<OpenAPIDocument, 'components' | 'paths' | 'servers' | 'tags'> & {
5
7
  servers: ServerObject[];
6
8
  'x-sdk-processing'?: {
7
9
  plugins: string[];
8
10
  configuration: string;
9
11
  };
10
12
  'x-docs': SidebarData;
13
+ 'x-sdks': SdkDoc[];
11
14
  'x-tagGroups': TagGroups[];
12
- components: Omit<ComponentsObject, 'schemas'> & {
15
+ components: Omit<OpenAPIComponentsObject, 'schemas' | 'securitySchemes'> & {
13
16
  schemas: Record<string, SchemaObject | ReferenceObject>;
14
- securitySchemes: Record<string, SecuritySchemeObject>;
17
+ securitySchemes: Record<string, OpenAPISecuritySchemeObject>;
15
18
  };
16
19
  paths: PathsObject;
17
20
  tags: TagObject[];
18
- }
21
+ };
19
22
  export interface OurRequestBodyObject extends RequestBodyObject {
20
23
  content: Record<string, Omit<MediaTypeObject, 'schema'> & {
21
24
  schema: ReferenceObject;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,eAAe,EACf,eAAe,EACf,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,SAAS,EACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,WAAW,EAAG,SAAQ,aAAa;IACvC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,kBAAkB,CAAC,EAAE;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,QAAQ,EAAE,WAAW,CAAC;IACtB,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,UAAU,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,GAAG;QAC9C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAAC,CAAC;QACxD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;KACvD,CAAC;IACF,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,OAAO,EAAE,MAAM,CACb,MAAM,EACN,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG;QAAE,MAAM,EAAE,eAAe,CAAA;KAAE,CAC9D,CAAC;CACH;AAED,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,eAAe,EACf,aAAa,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,MAAM,CAC7E,GAAG;IACF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CACf,MAAM,EACN,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,GAAG;QAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;KAC1C,CACF,CAAC;IACF,WAAW,EAAE,oBAAoB,CAAC;CACnC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AACD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,oBAAoB,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,eAAe,EACf,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,SAAS,EACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EACV,uBAAuB,EACvB,eAAe,EACf,2BAA2B,EAC5B,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,MAAM,EAAE,GAAG,IAAI,CACnB,eAAe,EACf,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAC5C,GAAG;IACF,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,kBAAkB,CAAC,EAAE;QACnB,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,UAAU,EAAE,IAAI,CAAC,uBAAuB,EAAE,SAAS,GAAG,iBAAiB,CAAC,GAAG;QACzE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAAC,CAAC;QACxD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;KAC9D,CAAC;IACF,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,OAAO,EAAE,MAAM,CACb,MAAM,EACN,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG;QAAE,MAAM,EAAE,eAAe,CAAA;KAAE,CAC9D,CAAC;CACH;AAED,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,eAAe,EACf,aAAa,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,MAAM,CAC7E,GAAG;IACF,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CACf,MAAM,EACN,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,GAAG;QAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;KAC1C,CACF,CAAC;IACF,WAAW,EAAE,oBAAoB,CAAC;CACnC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AACD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,oBAAoB,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdk-it/spec",
3
- "version": "0.46.3",
3
+ "version": "0.46.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -27,7 +27,7 @@
27
27
  "!**/*.test.*"
28
28
  ],
29
29
  "dependencies": {
30
- "@sdk-it/core": "0.46.3",
30
+ "@sdk-it/core": "0.46.5",
31
31
  "openapi3-ts": "4.5.0",
32
32
  "pluralize": "^8.0.0",
33
33
  "stringcase": "^4.3.1",
@@ -1,51 +0,0 @@
1
- export declare const docTemplates: {
2
- readonly servers: {
3
- readonly sectionTitle: "API Server";
4
- readonly description: "The following {count} {isAre} available for this API:";
5
- };
6
- readonly authMethods: {
7
- readonly sectionTitle: "Available Authentication Method";
8
- readonly introText: "This API provides secure access through {countText} authentication {method}. Below you'll find details about {articleCount} available authentication {scheme} and how to use {pronoun}.";
9
- readonly noAuthText: "This API does not require authentication.";
10
- };
11
- readonly apiClients: {
12
- readonly sectionTitle: "Official API Client";
13
- readonly description: "{apiTitle} provides official client SDK{sdkPlural} for {languageText}. We recommend using {clientText} to interact with all stable endpoints. You can find {pronoun} here:";
14
- };
15
- readonly needHelp: {
16
- readonly sectionTitle: "Need Help?";
17
- };
18
- };
19
- interface CountTextOptions {
20
- count: number;
21
- word: string;
22
- includeCount?: boolean;
23
- }
24
- export declare function getCountText(options: CountTextOptions): string;
25
- export declare function getPronoun(count: number, type?: 'subject' | 'object'): string;
26
- export declare function getArticle(count: number, word: string): string;
27
- export declare function getIsAre(count: number): string;
28
- export declare function getThisThese(count: number): string;
29
- export declare function processTemplate(template: string, replacements: Record<string, string | number>): string;
30
- export declare function getServerText(count: number): {
31
- title: string;
32
- description: string;
33
- };
34
- export declare function getAuthMethodText(count: number): {
35
- title: string;
36
- intro: string;
37
- };
38
- export declare function getApiClientText(count: number, apiTitle: string): {
39
- title: string;
40
- description: string;
41
- };
42
- export declare function getAuthText(count: number): {
43
- title: string;
44
- intro: string;
45
- };
46
- export declare function getErrorsApiClientText(count: number, apiTitle: string, sdkList: string[]): {
47
- title: string;
48
- description: string;
49
- };
50
- export {};
51
- //# sourceMappingURL=doc-templates.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"doc-templates.d.ts","sourceRoot":"","sources":["../../../src/lib/overview-docs/doc-templates.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;CAmBf,CAAC;AAEX,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAK9D;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,GAAG,QAAmB,GACpC,MAAM,CAKR;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAC5C,MAAM,CAKR;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAQA;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAeA;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAkBA;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAeA;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EAAE,GAChB;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAWA"}
@@ -1,123 +0,0 @@
1
- import pluralize from "pluralize";
2
- const docTemplates = {
3
- servers: {
4
- sectionTitle: "API Server",
5
- description: "The following {count} {isAre} available for this API:"
6
- },
7
- authMethods: {
8
- sectionTitle: "Available Authentication Method",
9
- introText: "This API provides secure access through {countText} authentication {method}. Below you'll find details about {articleCount} available authentication {scheme} and how to use {pronoun}.",
10
- noAuthText: "This API does not require authentication."
11
- },
12
- apiClients: {
13
- sectionTitle: "Official API Client",
14
- description: "{apiTitle} provides official client SDK{sdkPlural} for {languageText}. We recommend using {clientText} to interact with all stable endpoints. You can find {pronoun} here:"
15
- },
16
- needHelp: {
17
- sectionTitle: "Need Help?"
18
- }
19
- };
20
- function getCountText(options) {
21
- const { count, word, includeCount = false } = options;
22
- const pluralizedWord = count === 1 ? pluralize.singular(word) : pluralize.plural(word);
23
- return includeCount ? `${count} ${pluralizedWord}` : pluralizedWord;
24
- }
25
- function getPronoun(count, type = "object") {
26
- if (type === "subject") {
27
- return count === 1 ? "it" : "they";
28
- }
29
- return count === 1 ? "it" : "them";
30
- }
31
- function getArticle(count, word) {
32
- if (count === 1) {
33
- const firstLetter = word.charAt(0).toLowerCase();
34
- return ["a", "e", "i", "o", "u"].includes(firstLetter) ? "an" : "a";
35
- }
36
- return "";
37
- }
38
- function getIsAre(count) {
39
- return count === 1 ? "is" : "are";
40
- }
41
- function getThisThese(count) {
42
- return count === 1 ? "this" : "these";
43
- }
44
- function processTemplate(template, replacements) {
45
- return template.replace(/\{([^}]+)\}/g, (match, key) => {
46
- const value = replacements[key];
47
- return value !== void 0 ? String(value) : match;
48
- });
49
- }
50
- function getServerText(count) {
51
- return {
52
- title: `## ${getCountText({ count, word: "server", includeCount: false })}`,
53
- description: processTemplate(docTemplates.servers.description, {
54
- count: getCountText({ count, word: "server", includeCount: true }),
55
- isAre: getIsAre(count)
56
- })
57
- };
58
- }
59
- function getAuthMethodText(count) {
60
- const countText = count === 1 ? getArticle(count, "authentication method") : "various";
61
- const articleCount = count === 1 ? "the" : "each";
62
- return {
63
- title: `## ${getCountText({ count, word: docTemplates.authMethods.sectionTitle })}`,
64
- intro: processTemplate(docTemplates.authMethods.introText, {
65
- countText,
66
- method: getCountText({ count, word: "method" }),
67
- articleCount,
68
- scheme: getCountText({ count, word: "scheme" }),
69
- pronoun: getPronoun(count)
70
- })
71
- };
72
- }
73
- function getApiClientText(count, apiTitle) {
74
- const languageText = count === 1 ? "a programming language" : "multiple programming languages";
75
- const clientText = count === 1 ? getThisThese(count) + " client" : getThisThese(count) + " clients";
76
- return {
77
- title: `## ${getCountText({ count, word: docTemplates.apiClients.sectionTitle })}`,
78
- description: processTemplate(docTemplates.apiClients.description, {
79
- apiTitle,
80
- sdkPlural: count === 1 ? "" : "s",
81
- languageText,
82
- clientText,
83
- pronoun: getPronoun(count)
84
- })
85
- };
86
- }
87
- function getAuthText(count) {
88
- const countText = count === 1 ? getArticle(count, "authentication method") : "various";
89
- const articleCount = count === 1 ? "the" : "each";
90
- return {
91
- title: `## ${getCountText({ count, word: docTemplates.authMethods.sectionTitle })}`,
92
- intro: processTemplate(docTemplates.authMethods.introText, {
93
- countText,
94
- method: getCountText({ count, word: "method" }),
95
- articleCount,
96
- scheme: getCountText({ count, word: "scheme" }),
97
- pronoun: getPronoun(count)
98
- })
99
- };
100
- }
101
- function getErrorsApiClientText(count, apiTitle, sdkList) {
102
- const languageText = count === 1 ? sdkList[0] : sdkList.join(", ");
103
- const clientText = count === 1 ? getThisThese(count) + " client" : getThisThese(count) + " clients";
104
- return {
105
- title: `## ${getCountText({ count, word: docTemplates.apiClients.sectionTitle })}`,
106
- description: `${apiTitle} maintains official API ${getCountText({ count, word: "client" })}${count > 0 ? ` for ${languageText}` : ""}. We recommend using ${clientText} to interact with all stable endpoints. You can find ${getPronoun(count)} here:`
107
- };
108
- }
109
- export {
110
- docTemplates,
111
- getApiClientText,
112
- getArticle,
113
- getAuthMethodText,
114
- getAuthText,
115
- getCountText,
116
- getErrorsApiClientText,
117
- getIsAre,
118
- getPronoun,
119
- getServerText,
120
- getThisThese,
121
- processTemplate
122
- };
123
- //# sourceMappingURL=doc-templates.js.map