toolcraft-openapi 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +64 -0
  2. package/dist/api-command.d.ts +7 -0
  3. package/dist/api-command.js +4 -0
  4. package/dist/auth/bearer-token-auth.d.ts +8 -0
  5. package/dist/auth/bearer-token-auth.js +216 -0
  6. package/dist/auth/types.d.ts +9 -0
  7. package/dist/auth/types.js +1 -0
  8. package/dist/bin/generate.d.ts +40 -0
  9. package/dist/bin/generate.js +248 -0
  10. package/dist/define-client.d.ts +20 -0
  11. package/dist/define-client.js +148 -0
  12. package/dist/generate.d.ts +210 -0
  13. package/dist/generate.js +1131 -0
  14. package/dist/group-by-noun.d.ts +6 -0
  15. package/dist/group-by-noun.js +17 -0
  16. package/dist/http.d.ts +26 -0
  17. package/dist/http.js +123 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.js +6 -0
  20. package/dist/interpreter.d.ts +6 -0
  21. package/dist/interpreter.js +289 -0
  22. package/dist/lock.d.ts +14 -0
  23. package/dist/lock.js +48 -0
  24. package/dist/naming.d.ts +24 -0
  25. package/dist/naming.js +218 -0
  26. package/dist/request-shape.d.ts +15 -0
  27. package/dist/request-shape.js +5 -0
  28. package/dist/runtime.d.ts +13 -0
  29. package/dist/runtime.js +94 -0
  30. package/dist/spec-source.d.ts +11 -0
  31. package/dist/spec-source.js +63 -0
  32. package/node_modules/@poe-code/design-system/dist/acp/components.d.ts +11 -0
  33. package/node_modules/@poe-code/design-system/dist/acp/components.js +121 -0
  34. package/node_modules/@poe-code/design-system/dist/acp/index.d.ts +3 -0
  35. package/node_modules/@poe-code/design-system/dist/acp/index.js +2 -0
  36. package/node_modules/@poe-code/design-system/dist/acp/writer.d.ts +13 -0
  37. package/node_modules/@poe-code/design-system/dist/acp/writer.js +21 -0
  38. package/node_modules/@poe-code/design-system/dist/components/command-errors.d.ts +16 -0
  39. package/node_modules/@poe-code/design-system/dist/components/command-errors.js +22 -0
  40. package/node_modules/@poe-code/design-system/dist/components/help-formatter.d.ts +20 -0
  41. package/node_modules/@poe-code/design-system/dist/components/help-formatter.js +27 -0
  42. package/node_modules/@poe-code/design-system/dist/components/index.d.ts +10 -0
  43. package/node_modules/@poe-code/design-system/dist/components/index.js +7 -0
  44. package/node_modules/@poe-code/design-system/dist/components/logger.d.ts +11 -0
  45. package/node_modules/@poe-code/design-system/dist/components/logger.js +60 -0
  46. package/node_modules/@poe-code/design-system/dist/components/symbols.d.ts +12 -0
  47. package/node_modules/@poe-code/design-system/dist/components/symbols.js +71 -0
  48. package/node_modules/@poe-code/design-system/dist/components/table.d.ts +13 -0
  49. package/node_modules/@poe-code/design-system/dist/components/table.js +74 -0
  50. package/node_modules/@poe-code/design-system/dist/components/text.d.ts +14 -0
  51. package/node_modules/@poe-code/design-system/dist/components/text.js +104 -0
  52. package/node_modules/@poe-code/design-system/dist/dashboard/ansi.d.ts +18 -0
  53. package/node_modules/@poe-code/design-system/dist/dashboard/ansi.js +298 -0
  54. package/node_modules/@poe-code/design-system/dist/dashboard/buffer.d.ts +25 -0
  55. package/node_modules/@poe-code/design-system/dist/dashboard/buffer.js +189 -0
  56. package/node_modules/@poe-code/design-system/dist/dashboard/components/border.d.ts +9 -0
  57. package/node_modules/@poe-code/design-system/dist/dashboard/components/border.js +123 -0
  58. package/node_modules/@poe-code/design-system/dist/dashboard/components/footer.d.ts +8 -0
  59. package/node_modules/@poe-code/design-system/dist/dashboard/components/footer.js +57 -0
  60. package/node_modules/@poe-code/design-system/dist/dashboard/components/output-pane.d.ts +12 -0
  61. package/node_modules/@poe-code/design-system/dist/dashboard/components/output-pane.js +254 -0
  62. package/node_modules/@poe-code/design-system/dist/dashboard/components/stats-pane.d.ts +7 -0
  63. package/node_modules/@poe-code/design-system/dist/dashboard/components/stats-pane.js +121 -0
  64. package/node_modules/@poe-code/design-system/dist/dashboard/dashboard.d.ts +20 -0
  65. package/node_modules/@poe-code/design-system/dist/dashboard/dashboard.js +167 -0
  66. package/node_modules/@poe-code/design-system/dist/dashboard/demo.d.ts +13 -0
  67. package/node_modules/@poe-code/design-system/dist/dashboard/demo.js +145 -0
  68. package/node_modules/@poe-code/design-system/dist/dashboard/index.d.ts +8 -0
  69. package/node_modules/@poe-code/design-system/dist/dashboard/index.js +4 -0
  70. package/node_modules/@poe-code/design-system/dist/dashboard/keymap.d.ts +3 -0
  71. package/node_modules/@poe-code/design-system/dist/dashboard/keymap.js +99 -0
  72. package/node_modules/@poe-code/design-system/dist/dashboard/layout.d.ts +25 -0
  73. package/node_modules/@poe-code/design-system/dist/dashboard/layout.js +79 -0
  74. package/node_modules/@poe-code/design-system/dist/dashboard/should-use-dashboard.d.ts +10 -0
  75. package/node_modules/@poe-code/design-system/dist/dashboard/should-use-dashboard.js +7 -0
  76. package/node_modules/@poe-code/design-system/dist/dashboard/snapshot.d.ts +10 -0
  77. package/node_modules/@poe-code/design-system/dist/dashboard/snapshot.js +68 -0
  78. package/node_modules/@poe-code/design-system/dist/dashboard/store.d.ts +8 -0
  79. package/node_modules/@poe-code/design-system/dist/dashboard/store.js +51 -0
  80. package/node_modules/@poe-code/design-system/dist/dashboard/terminal.d.ts +37 -0
  81. package/node_modules/@poe-code/design-system/dist/dashboard/terminal.js +233 -0
  82. package/node_modules/@poe-code/design-system/dist/dashboard/types.d.ts +36 -0
  83. package/node_modules/@poe-code/design-system/dist/dashboard/types.js +1 -0
  84. package/node_modules/@poe-code/design-system/dist/index.d.ts +33 -0
  85. package/node_modules/@poe-code/design-system/dist/index.js +31 -0
  86. package/node_modules/@poe-code/design-system/dist/internal/output-format.d.ts +6 -0
  87. package/node_modules/@poe-code/design-system/dist/internal/output-format.js +22 -0
  88. package/node_modules/@poe-code/design-system/dist/internal/strip-ansi.d.ts +1 -0
  89. package/node_modules/@poe-code/design-system/dist/internal/strip-ansi.js +3 -0
  90. package/node_modules/@poe-code/design-system/dist/internal/theme-detect.d.ts +11 -0
  91. package/node_modules/@poe-code/design-system/dist/internal/theme-detect.js +49 -0
  92. package/node_modules/@poe-code/design-system/dist/prompts/index.d.ts +66 -0
  93. package/node_modules/@poe-code/design-system/dist/prompts/index.js +132 -0
  94. package/node_modules/@poe-code/design-system/dist/prompts/primitives/cancel.d.ts +2 -0
  95. package/node_modules/@poe-code/design-system/dist/prompts/primitives/cancel.js +9 -0
  96. package/node_modules/@poe-code/design-system/dist/prompts/primitives/intro.d.ts +1 -0
  97. package/node_modules/@poe-code/design-system/dist/prompts/primitives/intro.js +15 -0
  98. package/node_modules/@poe-code/design-system/dist/prompts/primitives/log.d.ts +18 -0
  99. package/node_modules/@poe-code/design-system/dist/prompts/primitives/log.js +101 -0
  100. package/node_modules/@poe-code/design-system/dist/prompts/primitives/note.d.ts +1 -0
  101. package/node_modules/@poe-code/design-system/dist/prompts/primitives/note.js +39 -0
  102. package/node_modules/@poe-code/design-system/dist/prompts/primitives/outro.d.ts +1 -0
  103. package/node_modules/@poe-code/design-system/dist/prompts/primitives/outro.js +16 -0
  104. package/node_modules/@poe-code/design-system/dist/prompts/primitives/spinner.d.ts +6 -0
  105. package/node_modules/@poe-code/design-system/dist/prompts/primitives/spinner.js +74 -0
  106. package/node_modules/@poe-code/design-system/dist/prompts/theme.d.ts +11 -0
  107. package/node_modules/@poe-code/design-system/dist/prompts/theme.js +12 -0
  108. package/node_modules/@poe-code/design-system/dist/static/index.d.ts +4 -0
  109. package/node_modules/@poe-code/design-system/dist/static/index.js +2 -0
  110. package/node_modules/@poe-code/design-system/dist/static/menu.d.ts +11 -0
  111. package/node_modules/@poe-code/design-system/dist/static/menu.js +36 -0
  112. package/node_modules/@poe-code/design-system/dist/static/spinner.d.ts +14 -0
  113. package/node_modules/@poe-code/design-system/dist/static/spinner.js +46 -0
  114. package/node_modules/@poe-code/design-system/dist/terminal-markdown/ast.d.ts +92 -0
  115. package/node_modules/@poe-code/design-system/dist/terminal-markdown/ast.js +1 -0
  116. package/node_modules/@poe-code/design-system/dist/terminal-markdown/demo-content.d.ts +2 -0
  117. package/node_modules/@poe-code/design-system/dist/terminal-markdown/demo-content.js +139 -0
  118. package/node_modules/@poe-code/design-system/dist/terminal-markdown/index.d.ts +6 -0
  119. package/node_modules/@poe-code/design-system/dist/terminal-markdown/index.js +8 -0
  120. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/block.d.ts +7 -0
  121. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/block.js +1495 -0
  122. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/frontmatter.d.ts +8 -0
  123. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/frontmatter.js +412 -0
  124. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/inline.d.ts +10 -0
  125. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser/inline.js +1166 -0
  126. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser.d.ts +5 -0
  127. package/node_modules/@poe-code/design-system/dist/terminal-markdown/parser.js +42 -0
  128. package/node_modules/@poe-code/design-system/dist/terminal-markdown/renderer.d.ts +6 -0
  129. package/node_modules/@poe-code/design-system/dist/terminal-markdown/renderer.js +572 -0
  130. package/node_modules/@poe-code/design-system/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
  131. package/node_modules/@poe-code/design-system/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
  132. package/node_modules/@poe-code/design-system/dist/tokens/colors.d.ts +35 -0
  133. package/node_modules/@poe-code/design-system/dist/tokens/colors.js +34 -0
  134. package/node_modules/@poe-code/design-system/dist/tokens/index.d.ts +4 -0
  135. package/node_modules/@poe-code/design-system/dist/tokens/index.js +4 -0
  136. package/node_modules/@poe-code/design-system/dist/tokens/spacing.d.ts +6 -0
  137. package/node_modules/@poe-code/design-system/dist/tokens/spacing.js +6 -0
  138. package/node_modules/@poe-code/design-system/dist/tokens/typography.d.ts +7 -0
  139. package/node_modules/@poe-code/design-system/dist/tokens/typography.js +8 -0
  140. package/node_modules/@poe-code/design-system/dist/tokens/widths.d.ts +5 -0
  141. package/node_modules/@poe-code/design-system/dist/tokens/widths.js +5 -0
  142. package/node_modules/@poe-code/design-system/package.json +25 -0
  143. package/node_modules/auth-store/README.md +47 -0
  144. package/node_modules/auth-store/dist/create-secret-store.d.ts +2 -0
  145. package/node_modules/auth-store/dist/create-secret-store.js +35 -0
  146. package/node_modules/auth-store/dist/encrypted-file-store.d.ts +39 -0
  147. package/node_modules/auth-store/dist/encrypted-file-store.js +156 -0
  148. package/node_modules/auth-store/dist/index.d.ts +7 -0
  149. package/node_modules/auth-store/dist/index.js +4 -0
  150. package/node_modules/auth-store/dist/keychain-store.d.ts +22 -0
  151. package/node_modules/auth-store/dist/keychain-store.js +111 -0
  152. package/node_modules/auth-store/dist/provider-store.d.ts +10 -0
  153. package/node_modules/auth-store/dist/provider-store.js +28 -0
  154. package/node_modules/auth-store/dist/types.d.ts +20 -0
  155. package/node_modules/auth-store/dist/types.js +1 -0
  156. package/node_modules/auth-store/package.json +25 -0
  157. package/package.json +48 -0
@@ -0,0 +1,6 @@
1
+ import type { GeneratedCommand } from "./generate.js";
2
+ export interface GeneratedCommandGroup {
3
+ noun: string;
4
+ commands: GeneratedCommand[];
5
+ }
6
+ export declare function groupByNoun(commands: ReadonlyArray<GeneratedCommand>): GeneratedCommandGroup[];
@@ -0,0 +1,17 @@
1
+ export function groupByNoun(commands) {
2
+ const groups = new Map();
3
+ for (const command of commands) {
4
+ const current = groups.get(command.noun);
5
+ if (current === undefined) {
6
+ groups.set(command.noun, [command]);
7
+ continue;
8
+ }
9
+ current.push(command);
10
+ }
11
+ return [...groups.entries()]
12
+ .sort(([left], [right]) => left.localeCompare(right))
13
+ .map(([noun, nounCommands]) => ({
14
+ noun,
15
+ commands: nounCommands.slice().sort((left, right) => left.verb.localeCompare(right.verb))
16
+ }));
17
+ }
package/dist/http.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { TokenSource } from "./auth/types.js";
2
+ type QueryScalar = string | number | boolean | null | undefined;
3
+ export type QueryValue = QueryScalar | QueryScalar[];
4
+ export interface HttpRequestOptions {
5
+ baseUrl: string;
6
+ path: string;
7
+ method: string;
8
+ tokenSource: TokenSource;
9
+ auth: "required" | "none";
10
+ fetch?: typeof globalThis.fetch;
11
+ pathParams?: Record<string, string | number | boolean>;
12
+ query?: Record<string, QueryValue>;
13
+ body?: unknown;
14
+ dryRun?: boolean;
15
+ verbose?: boolean;
16
+ signal?: AbortSignal;
17
+ writeStdout?: (chunk: string) => void;
18
+ writeStderr?: (chunk: string) => void;
19
+ }
20
+ export declare class HttpError extends Error {
21
+ readonly status: number;
22
+ readonly body: unknown;
23
+ constructor(status: number, body: unknown, message?: string);
24
+ }
25
+ export declare function requestJson<TResult = unknown>(options: HttpRequestOptions): Promise<TResult | undefined>;
26
+ export {};
package/dist/http.js ADDED
@@ -0,0 +1,123 @@
1
+ import { UserError } from "agent-kit";
2
+ export class HttpError extends Error {
3
+ status;
4
+ body;
5
+ constructor(status, body, message = `HTTP ${status}`) {
6
+ super(message);
7
+ this.name = "HttpError";
8
+ this.status = status;
9
+ this.body = body;
10
+ }
11
+ }
12
+ export async function requestJson(options) {
13
+ const token = options.auth === "none" ? undefined : await options.tokenSource.getToken();
14
+ const method = options.method.toUpperCase();
15
+ const hasBody = options.body !== undefined;
16
+ const serializedBody = hasBody ? JSON.stringify(options.body) : undefined;
17
+ const url = buildRequestUrl(options);
18
+ const headers = createHeaders(token, hasBody);
19
+ const writeStdout = options.writeStdout ?? process.stdout.write.bind(process.stdout);
20
+ const writeStderr = options.writeStderr ?? process.stderr.write.bind(process.stderr);
21
+ const requestLine = `${method} ${url}`;
22
+ if (options.verbose) {
23
+ writeStderr(`${requestLine}\n`);
24
+ }
25
+ if (options.dryRun) {
26
+ writeStdout(formatDryRunOutput(requestLine, headers, options.body));
27
+ return undefined;
28
+ }
29
+ const response = await (options.fetch ?? globalThis.fetch)(url, {
30
+ method,
31
+ headers,
32
+ body: serializedBody,
33
+ signal: options.signal,
34
+ });
35
+ const text = await response.text();
36
+ const contentType = response.headers.get("content-type");
37
+ if (response.ok) {
38
+ if (text.length === 0) {
39
+ return undefined;
40
+ }
41
+ if (!isJsonContentType(contentType)) {
42
+ throw new HttpError(response.status, text, `Expected a JSON response body but received content-type ${JSON.stringify(contentType ?? "<missing>")}.`);
43
+ }
44
+ return JSON.parse(text);
45
+ }
46
+ if (response.status === 401) {
47
+ await options.tokenSource.invalidate?.();
48
+ }
49
+ throw new HttpError(response.status, parseResponseBody(text, contentType));
50
+ }
51
+ function buildRequestUrl(options) {
52
+ const resolvedPath = substitutePathParams(options.path, options.pathParams);
53
+ const baseUrl = new URL(options.baseUrl);
54
+ const normalizedBasePath = baseUrl.pathname.endsWith("/")
55
+ ? baseUrl.pathname.slice(0, -1)
56
+ : baseUrl.pathname;
57
+ const normalizedPath = resolvedPath.startsWith("/") ? resolvedPath : `/${resolvedPath}`;
58
+ baseUrl.pathname = `${normalizedBasePath}${normalizedPath}`;
59
+ for (const [key, value] of Object.entries(options.query ?? {})) {
60
+ appendQueryValue(baseUrl.searchParams, key, value);
61
+ }
62
+ return baseUrl.toString();
63
+ }
64
+ function substitutePathParams(path, pathParams) {
65
+ const resolvedPath = path.replace(/\{([^}]+)\}/g, (_match, key) => {
66
+ const value = pathParams?.[key];
67
+ if (value === undefined) {
68
+ throw new UserError(`Missing path parameter "${key}".`);
69
+ }
70
+ return encodeURIComponent(String(value));
71
+ });
72
+ if (resolvedPath.includes("{") || resolvedPath.includes("}")) {
73
+ throw new UserError(`Invalid path template "${path}".`);
74
+ }
75
+ return resolvedPath;
76
+ }
77
+ function appendQueryValue(searchParams, key, value) {
78
+ const values = Array.isArray(value) ? value : [value];
79
+ for (const entry of values) {
80
+ if (entry === undefined) {
81
+ continue;
82
+ }
83
+ searchParams.append(key, entry === null ? "" : String(entry));
84
+ }
85
+ }
86
+ function createHeaders(token, hasBody) {
87
+ return {
88
+ ...(token === undefined ? {} : { Authorization: `Bearer ${token}` }),
89
+ ...(hasBody ? { "Content-Type": "application/json" } : {}),
90
+ };
91
+ }
92
+ function formatDryRunOutput(requestLine, headers, body) {
93
+ const lines = [
94
+ requestLine,
95
+ ...Object.entries(headers).map(([key, value]) => {
96
+ const headerValue = key.toLowerCase() === "authorization" && value.startsWith("Bearer ")
97
+ ? "Bearer ****"
98
+ : value;
99
+ return `${key}: ${headerValue}`;
100
+ }),
101
+ "",
102
+ ];
103
+ if (body !== undefined) {
104
+ lines.push(JSON.stringify(body));
105
+ }
106
+ return `${lines.join("\n")}\n`;
107
+ }
108
+ function parseResponseBody(text, contentType) {
109
+ if (text.length === 0) {
110
+ return undefined;
111
+ }
112
+ if (!isJsonContentType(contentType)) {
113
+ return text;
114
+ }
115
+ return JSON.parse(text);
116
+ }
117
+ function isJsonContentType(contentType) {
118
+ if (contentType === null) {
119
+ return false;
120
+ }
121
+ const normalized = contentType.toLowerCase();
122
+ return normalized.includes("application/json") || normalized.includes("+json");
123
+ }
@@ -0,0 +1,12 @@
1
+ export { defineApiCommand } from "./api-command.js";
2
+ export { defineClient } from "./define-client.js";
3
+ export { generate } from "./generate.js";
4
+ export type { GenerateOptions, GeneratedFile, OpenApiDocument } from "./generate.js";
5
+ export { commandsFromSpec, defineClientFromSpec } from "./runtime.js";
6
+ export type { CommandsFromSpecOptions, DefineClientFromSpecOptions, OpenApiDocumentSource } from "./runtime.js";
7
+ export type { DefineClientOptions, DefinedClient, OpenApiClientServices } from "./define-client.js";
8
+ export type { AuthProvider, CommandContributor, TokenSource } from "./auth/types.js";
9
+ export { bearerTokenAuth } from "./auth/bearer-token-auth.js";
10
+ export type { BearerTokenAuthOptions } from "./auth/bearer-token-auth.js";
11
+ export { HttpError, requestJson } from "./http.js";
12
+ export type { HttpRequestOptions, QueryValue } from "./http.js";
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { defineApiCommand } from "./api-command.js";
2
+ export { defineClient } from "./define-client.js";
3
+ export { generate } from "./generate.js";
4
+ export { commandsFromSpec, defineClientFromSpec } from "./runtime.js";
5
+ export { bearerTokenAuth } from "./auth/bearer-token-auth.js";
6
+ export { HttpError, requestJson } from "./http.js";
@@ -0,0 +1,6 @@
1
+ import { type RequestSectionKey } from "./request-shape.js";
2
+ import type { GeneratedPreflightBlock, GeneratedRequestField, GeneratedRequestLocation, GeneratedRequestSectionRenders } from "./generate.js";
3
+ export declare function renderPreflightBlock(block: GeneratedPreflightBlock): string[];
4
+ export declare function executePreflightBlocks(blocks: ReadonlyArray<GeneratedPreflightBlock>, params: Readonly<Record<string, unknown>>): Record<string, unknown>;
5
+ export declare function renderRequestShape(requestFields: ReadonlyArray<GeneratedRequestField>, sectionRenders: GeneratedRequestSectionRenders, optionalSections: ReadonlySet<GeneratedRequestLocation>): string[];
6
+ export declare function buildRequestShape(requestFields: ReadonlyArray<GeneratedRequestField>, sectionRenders: GeneratedRequestSectionRenders, optionalSections: ReadonlySet<GeneratedRequestLocation>, params: Readonly<Record<string, unknown>>, resolvedValues: Readonly<Record<string, unknown>>): Partial<Record<RequestSectionKey, unknown>>;
@@ -0,0 +1,289 @@
1
+ import { UserError } from "agent-kit";
2
+ import { isIdentifierName, toCliFlag } from "./naming.js";
3
+ import { REQUEST_PARAM_SECTIONS } from "./request-shape.js";
4
+ const QUERY_ARRAY_SERIALIZATION_SEPARATORS = {
5
+ comma: ",",
6
+ pipe: "|"
7
+ };
8
+ const VALUE_REFERENCE_OPERATIONS = {
9
+ param: {
10
+ render: (reference) => renderParamAccess(reference.paramName),
11
+ evaluate: (reference, context) => context.params[reference.paramName]
12
+ },
13
+ resolved: {
14
+ render: (reference) => reference.resolvedName,
15
+ evaluate: (reference, context) => context.resolvedValues[reference.resolvedName]
16
+ }
17
+ };
18
+ const VALUE_EXPRESSION_OPERATIONS = {
19
+ reference: {
20
+ render: (value) => renderValueReference(value.reference),
21
+ evaluate: (value, context) => evaluateValueReference(value.reference, context)
22
+ },
23
+ queryArray: {
24
+ render: (value) => renderSerializedQueryArray(renderValueReference(value.reference), value.serialization),
25
+ evaluate: (value, context) => serializeQueryArrayValue(evaluateValueReference(value.reference, context), value.serialization)
26
+ }
27
+ };
28
+ const PREFLIGHT_BLOCK_OPERATIONS = {
29
+ "scalar-null": {
30
+ render: (block) => {
31
+ const paramAccess = renderParamAccess(block.paramName);
32
+ const nullAccess = renderParamAccess(block.nullParamName);
33
+ return [
34
+ ` if (${paramAccess} !== undefined && ${paramAccess} !== null && ${nullAccess}) {`,
35
+ ` throw new UserError(${JSON.stringify(getScalarNullConflictMessage(block))});`,
36
+ " }",
37
+ ` const ${block.resolvedName} = ${nullAccess} ? null : ${paramAccess};`,
38
+ ...(block.required
39
+ ? [
40
+ ` if (${block.resolvedName} === undefined) {`,
41
+ ` throw new UserError(${JSON.stringify(getMissingRequiredParameterMessage(block.paramName))});`,
42
+ " }"
43
+ ]
44
+ : [])
45
+ ];
46
+ },
47
+ execute: (block, context) => {
48
+ const value = context.params[block.paramName];
49
+ const nullRequested = context.params[block.nullParamName] === true;
50
+ if (value !== undefined && value !== null && nullRequested) {
51
+ throw new UserError(getScalarNullConflictMessage(block));
52
+ }
53
+ context.resolvedValues[block.resolvedName] = nullRequested ? null : value;
54
+ if (block.required && context.resolvedValues[block.resolvedName] === undefined) {
55
+ throw new UserError(getMissingRequiredParameterMessage(block.paramName));
56
+ }
57
+ }
58
+ },
59
+ array: {
60
+ render: (block) => {
61
+ const paramAccess = renderParamAccess(block.paramName);
62
+ const jsonAccess = renderParamAccess(block.jsonParamName);
63
+ return [
64
+ ...(block.nullParamName === undefined
65
+ ? []
66
+ : [
67
+ ` if (${renderParamAccess(block.nullParamName)} && (${paramAccess} !== undefined || ${jsonAccess} !== undefined)) {`,
68
+ ` throw new UserError(${JSON.stringify(getArrayNullConflictMessage(block))});`,
69
+ " }"
70
+ ]),
71
+ ` if (${paramAccess} !== undefined && ${jsonAccess} !== undefined) {`,
72
+ ` throw new UserError(${JSON.stringify(getArrayJsonConflictMessage(block))});`,
73
+ " }",
74
+ ` let ${block.resolvedName} = ${paramAccess};`,
75
+ ` if (${jsonAccess} !== undefined) {`,
76
+ " let parsedJson: unknown;",
77
+ " try {",
78
+ ` parsedJson = JSON.parse(${jsonAccess});`,
79
+ " } catch (error) {",
80
+ ` throw new UserError(${JSON.stringify(getInvalidArrayJsonMessage(block.jsonParamName, "Expected valid JSON."))});`,
81
+ " }",
82
+ " if (!Array.isArray(parsedJson)) {",
83
+ ` throw new UserError(${JSON.stringify(getInvalidArrayJsonMessage(block.jsonParamName, "Expected a JSON array."))});`,
84
+ " }",
85
+ ` ${block.resolvedName} = parsedJson;`,
86
+ " }",
87
+ ...(block.nullParamName === undefined
88
+ ? []
89
+ : [
90
+ ` if (${renderParamAccess(block.nullParamName)}) {`,
91
+ ` ${block.resolvedName} = null;`,
92
+ " }"
93
+ ]),
94
+ ...(block.required
95
+ ? [
96
+ ` if (${block.resolvedName} === undefined) {`,
97
+ ` throw new UserError(${JSON.stringify(getMissingRequiredParameterMessage(block.paramName))});`,
98
+ " }"
99
+ ]
100
+ : [])
101
+ ];
102
+ },
103
+ execute: (block, context) => {
104
+ const directValue = context.params[block.paramName];
105
+ const jsonValue = context.params[block.jsonParamName];
106
+ const nullRequested = block.nullParamName !== undefined && context.params[block.nullParamName] === true;
107
+ if (block.nullParamName !== undefined && nullRequested && (directValue !== undefined || jsonValue !== undefined)) {
108
+ throw new UserError(getArrayNullConflictMessage(block));
109
+ }
110
+ if (directValue !== undefined && jsonValue !== undefined) {
111
+ throw new UserError(getArrayJsonConflictMessage(block));
112
+ }
113
+ let resolved = directValue;
114
+ if (jsonValue !== undefined) {
115
+ let parsedJson;
116
+ try {
117
+ parsedJson = JSON.parse(String(jsonValue));
118
+ }
119
+ catch {
120
+ throw new UserError(getInvalidArrayJsonMessage(block.jsonParamName, "Expected valid JSON."));
121
+ }
122
+ if (!Array.isArray(parsedJson)) {
123
+ throw new UserError(getInvalidArrayJsonMessage(block.jsonParamName, "Expected a JSON array."));
124
+ }
125
+ resolved = parsedJson;
126
+ }
127
+ if (nullRequested) {
128
+ resolved = null;
129
+ }
130
+ if (block.required && resolved === undefined) {
131
+ throw new UserError(getMissingRequiredParameterMessage(block.paramName));
132
+ }
133
+ context.resolvedValues[block.resolvedName] = resolved;
134
+ }
135
+ }
136
+ };
137
+ const REQUEST_SECTION_OPERATIONS = {
138
+ inline: {
139
+ render: (section, sectionFields, optional) => {
140
+ const [field] = sectionFields;
141
+ if (field === undefined) {
142
+ return [];
143
+ }
144
+ if (!optional) {
145
+ return [` ${section.key}: ${renderValueExpression(field.value)},`];
146
+ }
147
+ return [
148
+ ` ...(${renderOmitWhenUndefinedExpression(field.omitWhenUndefinedReference)}`,
149
+ " ? {}",
150
+ " : {",
151
+ ` ${section.key}: ${renderValueExpression(field.value)},`,
152
+ " }),"
153
+ ];
154
+ },
155
+ build: (_section, sectionFields, optional, context) => {
156
+ const [field] = sectionFields;
157
+ if (field === undefined) {
158
+ return undefined;
159
+ }
160
+ if (optional && evaluateValueReference(field.omitWhenUndefinedReference, context) === undefined) {
161
+ return undefined;
162
+ }
163
+ return evaluateValueExpression(field.value, context);
164
+ }
165
+ },
166
+ wrapped: {
167
+ render: (section, sectionFields, optional) => {
168
+ if (!optional) {
169
+ return [
170
+ ` ${section.key}: {`,
171
+ ...sectionFields.map((field) => ` ${JSON.stringify(field.wireName)}: ${renderValueExpression(field.value)},`),
172
+ " },"
173
+ ];
174
+ }
175
+ return [
176
+ ` ...(${sectionFields.map((field) => renderOmitWhenUndefinedExpression(field.omitWhenUndefinedReference)).join(" && ")}`,
177
+ " ? {}",
178
+ " : {",
179
+ ` ${section.key}: {`,
180
+ ...sectionFields.map((field) => ` ${JSON.stringify(field.wireName)}: ${renderValueExpression(field.value)},`),
181
+ " },",
182
+ " }),"
183
+ ];
184
+ },
185
+ build: (_section, sectionFields, optional, context) => {
186
+ if (optional &&
187
+ sectionFields.every((field) => evaluateValueReference(field.omitWhenUndefinedReference, context) === undefined)) {
188
+ return undefined;
189
+ }
190
+ return Object.fromEntries(sectionFields.map((field) => [field.wireName, evaluateValueExpression(field.value, context)]));
191
+ }
192
+ }
193
+ };
194
+ export function renderPreflightBlock(block) {
195
+ return PREFLIGHT_BLOCK_OPERATIONS[block.kind].render(block);
196
+ }
197
+ export function executePreflightBlocks(blocks, params) {
198
+ const resolvedValues = {};
199
+ for (const block of blocks) {
200
+ PREFLIGHT_BLOCK_OPERATIONS[block.kind].execute(block, {
201
+ params,
202
+ resolvedValues
203
+ });
204
+ }
205
+ return resolvedValues;
206
+ }
207
+ export function renderRequestShape(requestFields, sectionRenders, optionalSections) {
208
+ const lines = [];
209
+ for (const section of REQUEST_PARAM_SECTIONS) {
210
+ const sectionFields = requestFields.filter((field) => field.location === section.location);
211
+ if (sectionFields.length === 0) {
212
+ continue;
213
+ }
214
+ const renderKind = sectionRenders[section.location];
215
+ if (renderKind === undefined) {
216
+ continue;
217
+ }
218
+ lines.push(...REQUEST_SECTION_OPERATIONS[renderKind].render(section, sectionFields, optionalSections.has(section.location)));
219
+ }
220
+ return lines;
221
+ }
222
+ export function buildRequestShape(requestFields, sectionRenders, optionalSections, params, resolvedValues) {
223
+ const requestShape = {};
224
+ const context = { params, resolvedValues };
225
+ for (const section of REQUEST_PARAM_SECTIONS) {
226
+ const sectionFields = requestFields.filter((field) => field.location === section.location);
227
+ if (sectionFields.length === 0) {
228
+ continue;
229
+ }
230
+ const renderKind = sectionRenders[section.location];
231
+ if (renderKind === undefined) {
232
+ continue;
233
+ }
234
+ const builtSection = REQUEST_SECTION_OPERATIONS[renderKind].build(section, sectionFields, optionalSections.has(section.location), context);
235
+ if (builtSection !== undefined) {
236
+ requestShape[section.key] = builtSection;
237
+ }
238
+ }
239
+ return requestShape;
240
+ }
241
+ function getScalarNullConflictMessage(block) {
242
+ return `Options "--${toCliFlag(block.paramName)}" and "--${toCliFlag(block.nullParamName)}" are mutually exclusive.`;
243
+ }
244
+ function getArrayNullConflictMessage(block) {
245
+ const nullParamName = block.nullParamName;
246
+ if (nullParamName === undefined) {
247
+ throw new Error("Missing null helper for nullable array preflight block.");
248
+ }
249
+ return `Options "--${toCliFlag(nullParamName)}", "--${toCliFlag(block.paramName)}", and "--${toCliFlag(block.jsonParamName)}" cannot be combined.`;
250
+ }
251
+ function getArrayJsonConflictMessage(block) {
252
+ return `Options "--${toCliFlag(block.paramName)}" and "--${toCliFlag(block.jsonParamName)}" are mutually exclusive.`;
253
+ }
254
+ function getInvalidArrayJsonMessage(paramName, expectation) {
255
+ return `Invalid value for "--${toCliFlag(paramName)}". ${expectation}`;
256
+ }
257
+ function getMissingRequiredParameterMessage(paramName) {
258
+ return `Missing required parameter "${toCliFlag(paramName)}".`;
259
+ }
260
+ function renderValueReference(reference) {
261
+ return VALUE_REFERENCE_OPERATIONS[reference.kind].render(reference);
262
+ }
263
+ function evaluateValueReference(reference, context) {
264
+ return VALUE_REFERENCE_OPERATIONS[reference.kind].evaluate(reference, context);
265
+ }
266
+ function renderValueExpression(value) {
267
+ return VALUE_EXPRESSION_OPERATIONS[value.kind].render(value);
268
+ }
269
+ function evaluateValueExpression(value, context) {
270
+ return VALUE_EXPRESSION_OPERATIONS[value.kind].evaluate(value, context);
271
+ }
272
+ function renderSerializedQueryArray(reference, serialization) {
273
+ if (serialization === "repeat") {
274
+ return reference;
275
+ }
276
+ return `${reference} === undefined || ${reference} === null ? ${reference} : ${reference}.join(${JSON.stringify(QUERY_ARRAY_SERIALIZATION_SEPARATORS[serialization])})`;
277
+ }
278
+ function serializeQueryArrayValue(value, serialization) {
279
+ if (serialization === "repeat" || value === undefined || value === null) {
280
+ return value;
281
+ }
282
+ return Array.isArray(value) ? value.join(QUERY_ARRAY_SERIALIZATION_SEPARATORS[serialization]) : value;
283
+ }
284
+ function renderOmitWhenUndefinedExpression(reference) {
285
+ return `${renderValueReference(reference)} === undefined`;
286
+ }
287
+ function renderParamAccess(name) {
288
+ return isIdentifierName(name) ? `params.${name}` : `params[${JSON.stringify(name)}]`;
289
+ }
package/dist/lock.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ export interface OpenApiLock {
2
+ specSha: string;
3
+ }
4
+ export interface LockFileSystem {
5
+ mkdir(directoryPath: string, options?: {
6
+ recursive?: boolean;
7
+ }): Promise<unknown>;
8
+ readFile(filePath: string, encoding: BufferEncoding): Promise<string>;
9
+ writeFile(filePath: string, contents: string, encoding: BufferEncoding): Promise<void>;
10
+ }
11
+ export declare function parseOpenApiLock(contents: string): OpenApiLock | null;
12
+ export declare function stringifyOpenApiLock(lock: OpenApiLock): string;
13
+ export declare function readOpenApiLock(fs: Pick<LockFileSystem, "readFile">, lockPath: string): Promise<OpenApiLock | null>;
14
+ export declare function writeOpenApiLock(fs: LockFileSystem, lockPath: string, lock: OpenApiLock): Promise<void>;
package/dist/lock.js ADDED
@@ -0,0 +1,48 @@
1
+ import path from "node:path";
2
+ export function parseOpenApiLock(contents) {
3
+ let parsed;
4
+ try {
5
+ parsed = JSON.parse(contents);
6
+ }
7
+ catch {
8
+ return null;
9
+ }
10
+ if (typeof parsed !== "object" ||
11
+ parsed === null ||
12
+ parsed.version !== 1 ||
13
+ typeof parsed.specSha !== "string" ||
14
+ parsed.specSha.length === 0) {
15
+ return null;
16
+ }
17
+ return {
18
+ specSha: parsed.specSha
19
+ };
20
+ }
21
+ export function stringifyOpenApiLock(lock) {
22
+ const document = {
23
+ version: 1,
24
+ specSha: lock.specSha
25
+ };
26
+ return `${JSON.stringify(document, null, 2)}\n`;
27
+ }
28
+ export async function readOpenApiLock(fs, lockPath) {
29
+ try {
30
+ return parseOpenApiLock(await fs.readFile(lockPath, "utf8"));
31
+ }
32
+ catch (error) {
33
+ if (isNotFoundError(error)) {
34
+ return null;
35
+ }
36
+ throw error;
37
+ }
38
+ }
39
+ export async function writeOpenApiLock(fs, lockPath, lock) {
40
+ await fs.mkdir(path.dirname(lockPath), { recursive: true });
41
+ await fs.writeFile(lockPath, stringifyOpenApiLock(lock), "utf8");
42
+ }
43
+ function isNotFoundError(error) {
44
+ return (typeof error === "object" &&
45
+ error !== null &&
46
+ "code" in error &&
47
+ error.code === "ENOENT");
48
+ }
@@ -0,0 +1,24 @@
1
+ export type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
2
+ type MethodDefaults = {
3
+ collection: string;
4
+ resource: string;
5
+ confirm?: true;
6
+ genericVerbs?: readonly string[];
7
+ preferOperationIdWhenPathTailIsGeneric?: true;
8
+ };
9
+ export declare const METHOD_DEFAULTS: Partial<Record<HttpMethod, MethodDefaults>>;
10
+ export declare function deriveNoun(operation: {
11
+ tags?: string[];
12
+ }, path: string, operationId: string): string;
13
+ export declare function deriveVerb(method: HttpMethod, path: string, operation: {
14
+ operationId?: string;
15
+ }, operationId: string, noun: string): string;
16
+ export declare function normalizeParamName(name: string): string;
17
+ export declare function toPascalCase(value: string): string;
18
+ export declare function toCamelCase(value: string): string;
19
+ export declare function toKebabCase(value: string): string;
20
+ export declare function toCliFlag(value: string): string;
21
+ export declare function splitWords(value: string): string[];
22
+ export declare function toMcpPrefix(name: string): string;
23
+ export declare function isIdentifierName(value: string): boolean;
24
+ export {};