toolcraft-openapi 0.0.27 → 0.0.34
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/auth/bearer-token-auth.js +1 -1
- package/dist/bin/generate.d.ts +9 -1
- package/dist/bin/generate.js +65 -9
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +6 -0
- package/dist/generate.d.ts +20 -3
- package/dist/generate.js +604 -144
- package/dist/http.d.ts +17 -1
- package/dist/http.js +113 -7
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -0
- package/dist/inspect-source.d.ts +10 -0
- package/dist/inspect-source.js +14 -0
- package/dist/inspect.d.ts +22 -0
- package/dist/inspect.js +171 -0
- package/dist/interpreter.js +6 -2
- package/dist/mock/fetch.js +28 -12
- package/dist/mock/forgeyard.d.ts +4 -0
- package/dist/mock/forgeyard.js +452 -0
- package/dist/mock.d.ts +1 -0
- package/dist/mock.js +1 -0
- package/dist/naming.d.ts +4 -1
- package/dist/naming.js +93 -7
- package/dist/network-error.js +29 -12
- package/dist/normalize-swagger.d.ts +2 -0
- package/dist/normalize-swagger.js +201 -0
- package/dist/render-inspection.d.ts +2 -0
- package/dist/render-inspection.js +130 -0
- package/dist/request-shape.d.ts +4 -0
- package/dist/request-shape.js +1 -0
- package/dist/runtime.js +7 -1
- package/dist/spec-source.js +7 -4
- package/node_modules/auth-store/dist/create-secret-store.js +6 -1
- package/node_modules/auth-store/dist/encrypted-file-store.d.ts +1 -1
- package/node_modules/auth-store/dist/encrypted-file-store.js +32 -28
- package/node_modules/auth-store/dist/error-codes.d.ts +1 -0
- package/node_modules/auth-store/dist/error-codes.js +5 -0
- package/node_modules/auth-store/dist/keychain-store.js +23 -8
- package/node_modules/toolcraft-design/README.md +148 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/components.d.ts +1 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/components.js +12 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/index.d.ts +1 -1
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/index.js +1 -1
- package/node_modules/toolcraft-design/dist/components/catalog.d.ts +26 -0
- package/node_modules/toolcraft-design/dist/components/catalog.js +94 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/index.d.ts +2 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/index.js +1 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/footer.js +1 -2
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/output-pane.js +16 -19
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/stats-pane.js +1 -15
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/demo.js +2 -2
- package/node_modules/toolcraft-design/dist/explorer/theme.js +29 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/index.d.ts +7 -1
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/index.js +4 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/theme-detect.d.ts +1 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/theme-detect.js +28 -6
- package/node_modules/toolcraft-design/dist/internal/theme-state.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/internal/theme-state.js +35 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/theme.d.ts +1 -1
- package/node_modules/toolcraft-design/dist/prompts/theme.js +15 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/frontmatter.js +50 -0
- package/node_modules/toolcraft-design/dist/tokens/brand.d.ts +5 -0
- package/node_modules/toolcraft-design/dist/tokens/brand.js +5 -0
- package/node_modules/toolcraft-design/dist/tokens/colors.d.ts +37 -0
- package/node_modules/toolcraft-design/dist/tokens/colors.js +85 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/index.d.ts +2 -0
- package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/index.js +1 -0
- package/node_modules/toolcraft-design/package.json +42 -0
- package/package.json +8 -6
- package/node_modules/@poe-code/design-system/dist/explorer/theme.js +0 -97
- package/node_modules/@poe-code/design-system/dist/prompts/theme.js +0 -12
- package/node_modules/@poe-code/design-system/dist/tokens/colors.d.ts +0 -35
- package/node_modules/@poe-code/design-system/dist/tokens/colors.js +0 -34
- package/node_modules/@poe-code/design-system/package.json +0 -29
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/writer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/acp/writer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/browser.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/browser.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/color.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/color.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/command-errors.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/command-errors.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/detail-card.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/detail-card.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter-plain.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter-plain.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/help-formatter.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/logger.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/logger.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/symbols.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/symbols.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/table.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/table.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/template.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/template.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/text.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/components/text.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/ansi.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/ansi.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/buffer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/buffer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/border.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/border.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/footer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/output-pane.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/components/stats-pane.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/dashboard.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/dashboard.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/demo.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/demo.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/keymap.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/keymap.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/layout.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/layout.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/should-use-dashboard.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/should-use-dashboard.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/snapshot.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/snapshot.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/store.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/store.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal-width.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal-width.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/terminal.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/types.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/dashboard/types.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/actions.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/actions.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/demo.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/events.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/events.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/filter.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/filter.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/jobs.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/jobs.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/keymap.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/keymap.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/layout.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/layout.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/reducer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/reducer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/detail.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/detail.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/footer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/footer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/header.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/header.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/list.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/list.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/modal.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/modal.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/test-fixtures.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/test-fixtures.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/text.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/render/text.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.test-helpers.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/runtime.test-helpers.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/state.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/state.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/explorer/theme.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/color-support.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/color-support.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/output-format.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/output-format.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/strip-ansi.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/internal/strip-ansi.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/cancel.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/cancel.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/intro.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/intro.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/log.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/log.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/note.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/note.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/outro.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/outro.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/spinner.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/prompts/primitives/spinner.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/menu.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/menu.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/spinner.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/static/spinner.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/ast.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/ast.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/demo-content.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/demo-content.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/index.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/index.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/block.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/block.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/frontmatter.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/inline.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser/inline.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/parser.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/renderer.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/renderer.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/testing/theme-render-fixture.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/terminal-markdown/testing/theme-render-fixture.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/spacing.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/spacing.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/typography.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/typography.js +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/widths.d.ts +0 -0
- /package/node_modules/{@poe-code/design-system → toolcraft-design}/dist/tokens/widths.js +0 -0
package/dist/http.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { TokenSource } from "./auth/types.js";
|
|
2
2
|
type QueryScalar = string | number | boolean | null | undefined;
|
|
3
|
-
|
|
3
|
+
type QueryObject = {
|
|
4
|
+
readonly [key: string]: QueryValue;
|
|
5
|
+
};
|
|
6
|
+
type HeaderScalar = string | number | boolean | undefined;
|
|
7
|
+
export type QueryValue = QueryScalar | QueryValue[] | QueryObject;
|
|
4
8
|
export interface HttpRequestOptions {
|
|
5
9
|
baseUrl: string;
|
|
6
10
|
path: string;
|
|
@@ -10,7 +14,13 @@ export interface HttpRequestOptions {
|
|
|
10
14
|
fetch?: typeof globalThis.fetch;
|
|
11
15
|
pathParams?: Record<string, string | number | boolean>;
|
|
12
16
|
query?: Record<string, QueryValue>;
|
|
17
|
+
headers?: Record<string, HeaderScalar>;
|
|
13
18
|
body?: unknown;
|
|
19
|
+
bodyMode?: "json" | "form" | "raw" | "base64" | "multipart";
|
|
20
|
+
contentType?: string;
|
|
21
|
+
multipartBinaryFields?: readonly string[];
|
|
22
|
+
responseMode?: "json" | "text" | "binary";
|
|
23
|
+
accept?: string;
|
|
14
24
|
dryRun?: boolean;
|
|
15
25
|
verbose?: boolean;
|
|
16
26
|
signal?: AbortSignal;
|
|
@@ -29,6 +39,12 @@ export interface HttpErrorResponse {
|
|
|
29
39
|
headers: Record<string, string>;
|
|
30
40
|
body: unknown;
|
|
31
41
|
}
|
|
42
|
+
export interface BinaryHttpResponse {
|
|
43
|
+
contentType: string;
|
|
44
|
+
encoding: "base64";
|
|
45
|
+
byteLength: number;
|
|
46
|
+
data: string;
|
|
47
|
+
}
|
|
32
48
|
export declare class HttpError extends Error {
|
|
33
49
|
readonly status: number;
|
|
34
50
|
readonly statusText: string;
|
package/dist/http.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { text as designText } from "
|
|
1
|
+
import { text as designText } from "toolcraft-design";
|
|
2
2
|
import { UserError } from "toolcraft";
|
|
3
3
|
import { classifyNetworkError } from "./network-error.js";
|
|
4
4
|
import { redactHeaders, redactHeaderValue, redactSensitiveQueryValues } from "./redaction.js";
|
|
@@ -25,9 +25,19 @@ export async function requestJson(options) {
|
|
|
25
25
|
const token = options.auth === "none" ? undefined : await options.tokenSource.getToken();
|
|
26
26
|
const method = options.method.toUpperCase();
|
|
27
27
|
const hasBody = options.body !== undefined;
|
|
28
|
-
const serializedBody = hasBody
|
|
28
|
+
const serializedBody = hasBody
|
|
29
|
+
? options.bodyMode === "form"
|
|
30
|
+
? serializeFormBody(options.body)
|
|
31
|
+
: options.bodyMode === "raw"
|
|
32
|
+
? serializeRawBody(options.body)
|
|
33
|
+
: options.bodyMode === "base64"
|
|
34
|
+
? decodeBase64Body(options.body)
|
|
35
|
+
: options.bodyMode === "multipart"
|
|
36
|
+
? serializeMultipartBody(options.body, options.multipartBinaryFields)
|
|
37
|
+
: JSON.stringify(options.body)
|
|
38
|
+
: undefined;
|
|
29
39
|
const url = buildRequestUrl(options);
|
|
30
|
-
const headers = createHeaders(token, hasBody);
|
|
40
|
+
const headers = createHeaders(token, hasBody, options.headers, options.accept, options.bodyMode, options.contentType);
|
|
31
41
|
const writeStdout = options.writeStdout ?? process.stdout.write.bind(process.stdout);
|
|
32
42
|
const writeStderr = options.writeStderr ?? process.stderr.write.bind(process.stderr);
|
|
33
43
|
const requestLine = `${method} ${redactSensitiveQueryValues(url)}`;
|
|
@@ -50,10 +60,29 @@ export async function requestJson(options) {
|
|
|
50
60
|
catch (error) {
|
|
51
61
|
throw classifyNetworkError(error, url) ?? error;
|
|
52
62
|
}
|
|
53
|
-
const text = await response.text();
|
|
54
63
|
const contentType = response.headers.get("content-type");
|
|
55
64
|
const request = createHttpErrorRequest(method, url, headers, options.body);
|
|
56
65
|
const responseHeaders = redactHeaders(serializeHeaders(response.headers));
|
|
66
|
+
if (response.ok && options.responseMode === "binary") {
|
|
67
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
68
|
+
if (bytes.byteLength === 0) {
|
|
69
|
+
if (options.verbose) {
|
|
70
|
+
writeStderr(formatTranscriptLines(formatVerboseResponseTranscript(response, responseHeaders)));
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const body = {
|
|
75
|
+
contentType: contentType ?? options.accept ?? "application/octet-stream",
|
|
76
|
+
encoding: "base64",
|
|
77
|
+
byteLength: bytes.byteLength,
|
|
78
|
+
data: Buffer.from(bytes).toString("base64")
|
|
79
|
+
};
|
|
80
|
+
if (options.verbose) {
|
|
81
|
+
writeStderr(formatTranscriptLines(formatVerboseResponseTranscript(response, responseHeaders, body)));
|
|
82
|
+
}
|
|
83
|
+
return body;
|
|
84
|
+
}
|
|
85
|
+
const text = await response.text();
|
|
57
86
|
if (response.ok) {
|
|
58
87
|
if (text.length === 0) {
|
|
59
88
|
if (options.verbose) {
|
|
@@ -61,6 +90,12 @@ export async function requestJson(options) {
|
|
|
61
90
|
}
|
|
62
91
|
return undefined;
|
|
63
92
|
}
|
|
93
|
+
if (options.responseMode === "text") {
|
|
94
|
+
if (options.verbose) {
|
|
95
|
+
writeStderr(formatTranscriptLines(formatVerboseResponseTranscript(response, responseHeaders, text)));
|
|
96
|
+
}
|
|
97
|
+
return text;
|
|
98
|
+
}
|
|
64
99
|
if (!isJsonContentType(contentType)) {
|
|
65
100
|
if (options.verbose) {
|
|
66
101
|
writeStderr(formatTranscriptLines(formatVerboseResponseTranscript(response, responseHeaders, text)));
|
|
@@ -146,18 +181,89 @@ function substitutePathParams(path, pathParams) {
|
|
|
146
181
|
return resolvedPath;
|
|
147
182
|
}
|
|
148
183
|
function appendQueryValue(searchParams, key, value) {
|
|
184
|
+
if (isQueryObject(value)) {
|
|
185
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
186
|
+
appendQueryValue(searchParams, `${key}[${childKey}]`, childValue);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
149
190
|
const values = Array.isArray(value) ? value : [value];
|
|
150
|
-
for (const entry of values) {
|
|
191
|
+
for (const [index, entry] of values.entries()) {
|
|
151
192
|
if (entry === undefined) {
|
|
152
193
|
continue;
|
|
153
194
|
}
|
|
195
|
+
if (isQueryObject(entry)) {
|
|
196
|
+
for (const [childKey, childValue] of Object.entries(entry)) {
|
|
197
|
+
appendQueryValue(searchParams, `${key}[${Array.isArray(value) ? `${index}][` : ""}${childKey}]`, childValue);
|
|
198
|
+
}
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
154
201
|
searchParams.append(key, entry === null ? "" : String(entry));
|
|
155
202
|
}
|
|
156
203
|
}
|
|
157
|
-
function
|
|
204
|
+
function serializeFormBody(body) {
|
|
205
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
|
206
|
+
throw new UserError("URL-encoded form bodies must be objects.");
|
|
207
|
+
}
|
|
208
|
+
const searchParams = new URLSearchParams();
|
|
209
|
+
for (const [key, value] of Object.entries(body)) {
|
|
210
|
+
appendQueryValue(searchParams, key, value);
|
|
211
|
+
}
|
|
212
|
+
return searchParams.toString();
|
|
213
|
+
}
|
|
214
|
+
function serializeRawBody(body) {
|
|
215
|
+
if (typeof body !== "string") {
|
|
216
|
+
throw new UserError("Raw request bodies must be strings.");
|
|
217
|
+
}
|
|
218
|
+
return body;
|
|
219
|
+
}
|
|
220
|
+
function decodeBase64Body(body) {
|
|
221
|
+
if (typeof body !== "string") {
|
|
222
|
+
throw new UserError("Base64 request bodies must be strings.");
|
|
223
|
+
}
|
|
224
|
+
return Uint8Array.from(Buffer.from(body, "base64")).buffer;
|
|
225
|
+
}
|
|
226
|
+
function serializeMultipartBody(body, binaryFields = []) {
|
|
227
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) {
|
|
228
|
+
throw new UserError("Multipart request bodies must be objects.");
|
|
229
|
+
}
|
|
230
|
+
const binary = new Set(binaryFields);
|
|
231
|
+
const form = new FormData();
|
|
232
|
+
for (const [key, value] of Object.entries(body)) {
|
|
233
|
+
if (value === undefined)
|
|
234
|
+
continue;
|
|
235
|
+
if (binary.has(key)) {
|
|
236
|
+
form.append(key, new Blob([decodeBase64Body(value)]), key);
|
|
237
|
+
}
|
|
238
|
+
else if (Array.isArray(value)) {
|
|
239
|
+
for (const item of value)
|
|
240
|
+
form.append(key, String(item));
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
form.append(key, String(value));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return form;
|
|
247
|
+
}
|
|
248
|
+
function isQueryObject(value) {
|
|
249
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
250
|
+
}
|
|
251
|
+
function createHeaders(token, hasBody, customHeaders, accept = "application/json", bodyMode = "json", contentType) {
|
|
252
|
+
const headers = Object.fromEntries(Object.entries(customHeaders ?? {})
|
|
253
|
+
.filter(([name, value]) => value !== undefined &&
|
|
254
|
+
!["accept", "content-type"].includes(name.toLowerCase()) &&
|
|
255
|
+
!(token !== undefined && name.toLowerCase() === "authorization"))
|
|
256
|
+
.map(([name, value]) => [name, String(value)]));
|
|
158
257
|
return {
|
|
258
|
+
...headers,
|
|
259
|
+
Accept: accept,
|
|
159
260
|
...(token === undefined ? {} : { Authorization: `Bearer ${token}` }),
|
|
160
|
-
...(hasBody
|
|
261
|
+
...(hasBody && bodyMode !== "multipart"
|
|
262
|
+
? {
|
|
263
|
+
"Content-Type": contentType ??
|
|
264
|
+
(bodyMode === "form" ? "application/x-www-form-urlencoded" : "application/json")
|
|
265
|
+
}
|
|
266
|
+
: {})
|
|
161
267
|
};
|
|
162
268
|
}
|
|
163
269
|
function createHttpErrorRequest(method, url, headers, body) {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,11 @@ export { defineApiCommand } from "./api-command.js";
|
|
|
2
2
|
export { defineClient } from "./define-client.js";
|
|
3
3
|
export { generate } from "./generate.js";
|
|
4
4
|
export type { GenerateOptions, GeneratedFile, OpenApiDocument } from "./generate.js";
|
|
5
|
+
export { inspectOpenApiDocument } from "./inspect.js";
|
|
6
|
+
export type { OpenApiInspectionOperation, OpenApiInspectionReport } from "./inspect.js";
|
|
7
|
+
export { inspectOpenApiSource } from "./inspect-source.js";
|
|
8
|
+
export type { InspectOpenApiSourceOptions, OpenApiInspectionSource } from "./inspect-source.js";
|
|
9
|
+
export { renderOpenApiInspection } from "./render-inspection.js";
|
|
5
10
|
export { commandsFromSpec, defineClientFromSpec } from "./runtime.js";
|
|
6
11
|
export type { CommandsFromSpecOptions, DefineClientFromSpecOptions, OpenApiDocumentSource } from "./runtime.js";
|
|
7
12
|
export type { DefineClientOptions, DefinedClient, OpenApiClientServices } from "./define-client.js";
|
|
@@ -9,4 +14,4 @@ export type { AuthProvider, CommandContributor, TokenSource } from "./auth/types
|
|
|
9
14
|
export { bearerTokenAuth } from "./auth/bearer-token-auth.js";
|
|
10
15
|
export type { BearerTokenAuthOptions } from "./auth/bearer-token-auth.js";
|
|
11
16
|
export { HttpError, requestJson } from "./http.js";
|
|
12
|
-
export type { HttpErrorRequest, HttpErrorResponse, HttpRequestOptions, QueryValue } from "./http.js";
|
|
17
|
+
export type { BinaryHttpResponse, HttpErrorRequest, HttpErrorResponse, HttpRequestOptions, QueryValue } from "./http.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { defineApiCommand } from "./api-command.js";
|
|
2
2
|
export { defineClient } from "./define-client.js";
|
|
3
3
|
export { generate } from "./generate.js";
|
|
4
|
+
export { inspectOpenApiDocument } from "./inspect.js";
|
|
5
|
+
export { inspectOpenApiSource } from "./inspect-source.js";
|
|
6
|
+
export { renderOpenApiInspection } from "./render-inspection.js";
|
|
4
7
|
export { commandsFromSpec, defineClientFromSpec } from "./runtime.js";
|
|
5
8
|
export { bearerTokenAuth } from "./auth/bearer-token-auth.js";
|
|
6
9
|
export { HttpError, requestJson } from "./http.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type OpenApiInspectionReport } from "./inspect.js";
|
|
2
|
+
import type { OpenApiDocument } from "./generate.js";
|
|
3
|
+
import { type OpenApiSourceFileSystem } from "./spec-source.js";
|
|
4
|
+
export type OpenApiInspectionSource = OpenApiDocument | string | URL;
|
|
5
|
+
export interface InspectOpenApiSourceOptions {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
fetch?: typeof globalThis.fetch;
|
|
8
|
+
fs?: OpenApiSourceFileSystem;
|
|
9
|
+
}
|
|
10
|
+
export declare function inspectOpenApiSource(source: OpenApiInspectionSource, options?: InspectOpenApiSourceOptions): Promise<OpenApiInspectionReport>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { inspectOpenApiDocument } from "./inspect.js";
|
|
3
|
+
import { parseOpenApiDocument, readOpenApiSourceText } from "./spec-source.js";
|
|
4
|
+
export async function inspectOpenApiSource(source, options = {}) {
|
|
5
|
+
if (typeof source !== "string" && !(source instanceof URL)) {
|
|
6
|
+
return inspectOpenApiDocument(source);
|
|
7
|
+
}
|
|
8
|
+
const sourceText = await readOpenApiSourceText(source, {
|
|
9
|
+
cwd: options.cwd ?? process.cwd(),
|
|
10
|
+
fetch: options.fetch ?? globalThis.fetch,
|
|
11
|
+
fs: options.fs ?? fs
|
|
12
|
+
});
|
|
13
|
+
return inspectOpenApiDocument(parseOpenApiDocument(sourceText, source));
|
|
14
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type OpenApiDocument } from "./generate.js";
|
|
2
|
+
declare const HTTP_METHOD_ORDER: readonly ["get", "post", "put", "patch", "delete", "head", "options", "trace"];
|
|
3
|
+
type InspectedHttpMethod = (typeof HTTP_METHOD_ORDER)[number];
|
|
4
|
+
export interface OpenApiInspectionOperation {
|
|
5
|
+
method: Uppercase<InspectedHttpMethod>;
|
|
6
|
+
path: string;
|
|
7
|
+
operationId: string;
|
|
8
|
+
summary?: string;
|
|
9
|
+
status: "supported" | "unsupported";
|
|
10
|
+
commandPath?: string;
|
|
11
|
+
reason?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface OpenApiInspectionReport {
|
|
14
|
+
title?: string;
|
|
15
|
+
version?: string;
|
|
16
|
+
operationCount: number;
|
|
17
|
+
supportedCount: number;
|
|
18
|
+
unsupportedCount: number;
|
|
19
|
+
operations: OpenApiInspectionOperation[];
|
|
20
|
+
}
|
|
21
|
+
export declare function inspectOpenApiDocument(document: OpenApiDocument): OpenApiInspectionReport;
|
|
22
|
+
export {};
|
package/dist/inspect.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { UserError } from "toolcraft";
|
|
2
|
+
import { collectGeneratedCommand } from "./generate.js";
|
|
3
|
+
import { normalizeOpenApiDocument } from "./normalize-swagger.js";
|
|
4
|
+
import { deriveDisambiguatedVerb, derivePathDisambiguatedVerb } from "./naming.js";
|
|
5
|
+
const HTTP_METHOD_ORDER = [
|
|
6
|
+
"get",
|
|
7
|
+
"post",
|
|
8
|
+
"put",
|
|
9
|
+
"patch",
|
|
10
|
+
"delete",
|
|
11
|
+
"head",
|
|
12
|
+
"options",
|
|
13
|
+
"trace"
|
|
14
|
+
];
|
|
15
|
+
export function inspectOpenApiDocument(document) {
|
|
16
|
+
const normalizedDocument = normalizeOpenApiDocument(document);
|
|
17
|
+
if (normalizedDocument.paths === undefined) {
|
|
18
|
+
throw new UserError('OpenAPI document must define a top-level "paths" object.');
|
|
19
|
+
}
|
|
20
|
+
const operations = collectInspectionOperations(normalizedDocument);
|
|
21
|
+
markCommandPathCollisions(operations);
|
|
22
|
+
const supportedCount = operations.filter((operation) => operation.status === "supported").length;
|
|
23
|
+
return {
|
|
24
|
+
...(normalizedDocument.info?.title === undefined ? {} : { title: normalizedDocument.info.title }),
|
|
25
|
+
...(normalizedDocument.info?.version === undefined ? {} : { version: normalizedDocument.info.version }),
|
|
26
|
+
operationCount: operations.length,
|
|
27
|
+
supportedCount,
|
|
28
|
+
unsupportedCount: operations.length - supportedCount,
|
|
29
|
+
operations
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function collectInspectionOperations(document) {
|
|
33
|
+
return Object.entries(document.paths ?? {})
|
|
34
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
35
|
+
.flatMap(([path, pathItem]) => {
|
|
36
|
+
if (pathItem === undefined) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
return HTTP_METHOD_ORDER.flatMap((method) => {
|
|
40
|
+
const operation = pathItem[method];
|
|
41
|
+
if (operation === undefined) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return [inspectOperation(document, path, pathItem, method, operation)];
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function inspectOperation(document, path, pathItem, method, operation) {
|
|
49
|
+
const metadata = readOperationMetadata(path, method, operation);
|
|
50
|
+
try {
|
|
51
|
+
const command = method === "trace"
|
|
52
|
+
? undefined
|
|
53
|
+
: collectGeneratedCommand(document, path, method);
|
|
54
|
+
if (command === undefined) {
|
|
55
|
+
throw new UserError(`Operation ${JSON.stringify(metadata.operationId)} uses unsupported HTTP method ${JSON.stringify(method.toUpperCase())}. Supported in v1: GET, POST, PUT, PATCH, DELETE.`);
|
|
56
|
+
}
|
|
57
|
+
return createSupportedOperation(metadata, command);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
return {
|
|
61
|
+
...metadata,
|
|
62
|
+
status: "unsupported",
|
|
63
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function createSupportedOperation(metadata, command) {
|
|
68
|
+
return {
|
|
69
|
+
...metadata,
|
|
70
|
+
status: "supported",
|
|
71
|
+
commandPath: `${command.noun} ${command.verb}`
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function readOperationMetadata(path, method, operation) {
|
|
75
|
+
const operationObject = isObject(operation) ? operation : {};
|
|
76
|
+
const operationId = typeof operationObject.operationId === "string"
|
|
77
|
+
? operationObject.operationId
|
|
78
|
+
: `${method.toUpperCase()} ${path}`;
|
|
79
|
+
const summary = typeof operationObject.summary === "string"
|
|
80
|
+
? operationObject.summary
|
|
81
|
+
: typeof operationObject.description === "string"
|
|
82
|
+
? operationObject.description
|
|
83
|
+
: undefined;
|
|
84
|
+
return {
|
|
85
|
+
method: method.toUpperCase(),
|
|
86
|
+
path,
|
|
87
|
+
operationId,
|
|
88
|
+
...(summary === undefined ? {} : { summary })
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function markCommandPathCollisions(operations) {
|
|
92
|
+
const byCommandPath = new Map();
|
|
93
|
+
for (const operation of operations) {
|
|
94
|
+
if (operation.status !== "supported" || operation.commandPath === undefined) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const collisions = byCommandPath.get(operation.commandPath) ?? [];
|
|
98
|
+
collisions.push(operation);
|
|
99
|
+
byCommandPath.set(operation.commandPath, collisions);
|
|
100
|
+
}
|
|
101
|
+
for (const collisions of byCommandPath.values()) {
|
|
102
|
+
if (collisions.length < 2) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const existingPaths = new Set(operations
|
|
106
|
+
.filter((operation) => !collisions.includes(operation) && operation.commandPath !== undefined)
|
|
107
|
+
.map((operation) => operation.commandPath));
|
|
108
|
+
const operationIdCandidates = collisions.map((operation) => {
|
|
109
|
+
const noun = operation.commandPath?.split(" ")[0] ?? "";
|
|
110
|
+
return { operation, commandPath: `${noun} ${deriveDisambiguatedVerb(operation.operationId, noun)}` };
|
|
111
|
+
});
|
|
112
|
+
if (applyInspectionCommandPaths(operationIdCandidates, existingPaths)) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const pathCandidates = collisions.map((operation) => {
|
|
116
|
+
const [noun = "", verb = ""] = operation.commandPath?.split(" ") ?? [];
|
|
117
|
+
const pathVerb = derivePathDisambiguatedVerb(operation.method.toLowerCase(), operation.path, noun, verb);
|
|
118
|
+
return { operation, commandPath: `${noun} ${pathVerb}` };
|
|
119
|
+
});
|
|
120
|
+
if (applyInspectionCommandPaths(pathCandidates, existingPaths)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (applyInspectionCommandPaths(collisions.map((operation) => {
|
|
124
|
+
const [noun = "", verb = ""] = operation.commandPath?.split(" ") ?? [];
|
|
125
|
+
const pathVerb = derivePathDisambiguatedVerb(operation.method.toLowerCase(), operation.path, noun, verb, true);
|
|
126
|
+
return { operation, commandPath: `${noun} ${pathVerb}` };
|
|
127
|
+
}), existingPaths)) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
applyInspectionCommandPaths(collisions.map((operation) => {
|
|
131
|
+
const [noun = "", verb = ""] = operation.commandPath?.split(" ") ?? [];
|
|
132
|
+
const pathVerb = derivePathDisambiguatedVerb(operation.method.toLowerCase(), operation.path, noun, verb, true, true);
|
|
133
|
+
return { operation, commandPath: `${noun} ${pathVerb}` };
|
|
134
|
+
}), existingPaths);
|
|
135
|
+
}
|
|
136
|
+
const remainingByCommandPath = new Map();
|
|
137
|
+
for (const operation of operations) {
|
|
138
|
+
if (operation.status !== "supported" || operation.commandPath === undefined) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
remainingByCommandPath.set(operation.commandPath, [
|
|
142
|
+
...(remainingByCommandPath.get(operation.commandPath) ?? []),
|
|
143
|
+
operation
|
|
144
|
+
]);
|
|
145
|
+
}
|
|
146
|
+
for (const [commandPath, collisions] of remainingByCommandPath) {
|
|
147
|
+
if (collisions.length < 2) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const reason = `Generated command path ${JSON.stringify(commandPath)} is defined more than once (${collisions.map((operation) => JSON.stringify(operation.operationId)).join(" and ")}).`;
|
|
151
|
+
for (const operation of collisions) {
|
|
152
|
+
operation.status = "unsupported";
|
|
153
|
+
operation.reason = reason;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function applyInspectionCommandPaths(candidates, existingPaths) {
|
|
158
|
+
const candidatePaths = candidates.map(({ commandPath }) => commandPath);
|
|
159
|
+
if (candidates.some(({ commandPath }) => commandPath.endsWith(" ")) ||
|
|
160
|
+
new Set(candidatePaths).size !== candidates.length ||
|
|
161
|
+
candidatePaths.some((commandPath) => existingPaths.has(commandPath))) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
for (const { operation, commandPath } of candidates) {
|
|
165
|
+
operation.commandPath = commandPath;
|
|
166
|
+
}
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
function isObject(value) {
|
|
170
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
171
|
+
}
|
package/dist/interpreter.js
CHANGED
|
@@ -16,6 +16,10 @@ const VALUE_REFERENCE_OPERATIONS = {
|
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
const VALUE_EXPRESSION_OPERATIONS = {
|
|
19
|
+
emptyObject: {
|
|
20
|
+
render: (_value) => "{}",
|
|
21
|
+
evaluate: (_value) => ({})
|
|
22
|
+
},
|
|
19
23
|
reference: {
|
|
20
24
|
render: (value) => renderValueReference(value.reference),
|
|
21
25
|
evaluate: (value, context) => evaluateValueReference(value.reference, context)
|
|
@@ -270,13 +274,13 @@ function evaluateValueExpression(value, context) {
|
|
|
270
274
|
return VALUE_EXPRESSION_OPERATIONS[value.kind].evaluate(value, context);
|
|
271
275
|
}
|
|
272
276
|
function renderSerializedQueryArray(reference, serialization) {
|
|
273
|
-
if (serialization === "repeat") {
|
|
277
|
+
if (serialization === "repeat" || serialization === "brackets") {
|
|
274
278
|
return reference;
|
|
275
279
|
}
|
|
276
280
|
return `${reference} === undefined || ${reference} === null ? ${reference} : ${reference}.join(${JSON.stringify(QUERY_ARRAY_SERIALIZATION_SEPARATORS[serialization])})`;
|
|
277
281
|
}
|
|
278
282
|
function serializeQueryArrayValue(value, serialization) {
|
|
279
|
-
if (serialization === "repeat" || value === undefined || value === null) {
|
|
283
|
+
if (serialization === "repeat" || serialization === "brackets" || value === undefined || value === null) {
|
|
280
284
|
return value;
|
|
281
285
|
}
|
|
282
286
|
return Array.isArray(value) ? value.join(QUERY_ARRAY_SERIALIZATION_SEPARATORS[serialization]) : value;
|
package/dist/mock/fetch.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { UserError } from "toolcraft";
|
|
4
|
+
import { hasOwnErrorCode } from "../error-codes.js";
|
|
4
5
|
import { parseOpenApiDocument, readOpenApiSourceText } from "../spec-source.js";
|
|
5
|
-
const HTTP_METHOD_NAMES = ["get", "post", "put", "patch", "delete"];
|
|
6
|
+
const HTTP_METHOD_NAMES = ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
6
7
|
export async function mockFetch(options) {
|
|
7
8
|
const document = await resolveSpec(options);
|
|
8
9
|
const operations = compileOperations(document);
|
|
@@ -15,7 +16,7 @@ export async function mockFetch(options) {
|
|
|
15
16
|
const method = (init?.method ?? getRequestMethod(input) ?? "GET").toUpperCase();
|
|
16
17
|
const headers = collectHeaders(input, init);
|
|
17
18
|
const bodyText = await readRequestBody(input, init);
|
|
18
|
-
const parsedBody =
|
|
19
|
+
const parsedBody = parseRequestBody(bodyText, headers["content-type"]);
|
|
19
20
|
const matchingPath = operations.filter((op) => op.pathRegex.test(requestUrl.pathname));
|
|
20
21
|
if (matchingPath.length === 0) {
|
|
21
22
|
throw new MockFetchError(`mockFetch: no operation in the spec matches ${method} ${requestUrl.pathname}.`);
|
|
@@ -223,7 +224,7 @@ function extractExample(response, document) {
|
|
|
223
224
|
}
|
|
224
225
|
if (media.examples !== undefined) {
|
|
225
226
|
for (const value of Object.values(media.examples)) {
|
|
226
|
-
if (value !== undefined && "value"
|
|
227
|
+
if (value !== undefined && Object.prototype.hasOwnProperty.call(value, "value")) {
|
|
227
228
|
return value.value;
|
|
228
229
|
}
|
|
229
230
|
}
|
|
@@ -244,7 +245,7 @@ function pickJsonMediaType(content) {
|
|
|
244
245
|
return undefined;
|
|
245
246
|
}
|
|
246
247
|
for (const [type, media] of Object.entries(content)) {
|
|
247
|
-
if (media !== undefined && /application\/json|\+json/i.test(type)) {
|
|
248
|
+
if (media !== undefined && (type === "*/*" || /application\/json|\+json/i.test(type))) {
|
|
248
249
|
return media;
|
|
249
250
|
}
|
|
250
251
|
}
|
|
@@ -253,7 +254,7 @@ function pickJsonMediaType(content) {
|
|
|
253
254
|
function isReference(value) {
|
|
254
255
|
return (typeof value === "object" &&
|
|
255
256
|
value !== null &&
|
|
256
|
-
"$ref"
|
|
257
|
+
Object.prototype.hasOwnProperty.call(value, "$ref") &&
|
|
257
258
|
typeof value.$ref === "string");
|
|
258
259
|
}
|
|
259
260
|
function resolveReference(reference, document) {
|
|
@@ -270,6 +271,9 @@ function resolveReference(reference, document) {
|
|
|
270
271
|
if (current === null || typeof current !== "object") {
|
|
271
272
|
throw new UserError(`mockFetch: failed to resolve $ref ${JSON.stringify(ref)}.`);
|
|
272
273
|
}
|
|
274
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment)) {
|
|
275
|
+
throw new UserError(`mockFetch: failed to resolve $ref ${JSON.stringify(ref)}.`);
|
|
276
|
+
}
|
|
273
277
|
current = current[segment];
|
|
274
278
|
}
|
|
275
279
|
if (current === undefined) {
|
|
@@ -394,6 +398,9 @@ function collectHeaders(input, init) {
|
|
|
394
398
|
const requestHeaders = typeof input !== "string" && !(input instanceof URL) ? input.headers : undefined;
|
|
395
399
|
appendHeaders(headers, requestHeaders);
|
|
396
400
|
appendHeaders(headers, initHeaders);
|
|
401
|
+
if (init?.body instanceof FormData && headers["content-type"] === undefined) {
|
|
402
|
+
appendHeaders(headers, new Request("https://mock.invalid", { method: "POST", body: init.body }).headers);
|
|
403
|
+
}
|
|
397
404
|
return headers;
|
|
398
405
|
}
|
|
399
406
|
function appendHeaders(target, source) {
|
|
@@ -433,10 +440,18 @@ async function readRequestBody(input, init) {
|
|
|
433
440
|
}
|
|
434
441
|
return undefined;
|
|
435
442
|
}
|
|
436
|
-
function
|
|
443
|
+
function parseRequestBody(text, contentType) {
|
|
437
444
|
if (text === undefined || text.length === 0) {
|
|
438
445
|
return undefined;
|
|
439
446
|
}
|
|
447
|
+
if (contentType?.toLowerCase().includes("application/x-www-form-urlencoded") === true) {
|
|
448
|
+
const body = {};
|
|
449
|
+
for (const [key, value] of new URLSearchParams(text)) {
|
|
450
|
+
const existing = body[key];
|
|
451
|
+
body[key] = existing === undefined ? value : Array.isArray(existing) ? [...existing, value] : [existing, value];
|
|
452
|
+
}
|
|
453
|
+
return body;
|
|
454
|
+
}
|
|
440
455
|
try {
|
|
441
456
|
return JSON.parse(text);
|
|
442
457
|
}
|
|
@@ -447,7 +462,12 @@ function parseJsonOrUndefined(text) {
|
|
|
447
462
|
function buildResponse(fixture, defaultStatus) {
|
|
448
463
|
const status = fixture.status ?? defaultStatus;
|
|
449
464
|
const headers = new Headers(fixture.headers ?? { "content-type": "application/json" });
|
|
450
|
-
const
|
|
465
|
+
const contentType = headers.get("content-type")?.toLowerCase();
|
|
466
|
+
const body = fixture.body === undefined || fixture.body === null
|
|
467
|
+
? null
|
|
468
|
+
: contentType?.includes("json") === true
|
|
469
|
+
? JSON.stringify(fixture.body)
|
|
470
|
+
: String(fixture.body);
|
|
451
471
|
return new Response(body, { status, headers });
|
|
452
472
|
}
|
|
453
473
|
function jsonResponse(status, body) {
|
|
@@ -507,9 +527,5 @@ function formatList(values) {
|
|
|
507
527
|
return values.map((value) => JSON.stringify(value)).join(", ");
|
|
508
528
|
}
|
|
509
529
|
function isNotFoundError(error) {
|
|
510
|
-
|
|
511
|
-
return false;
|
|
512
|
-
}
|
|
513
|
-
const code = error.code;
|
|
514
|
-
return code === "ENOENT" || code === "ENOTDIR";
|
|
530
|
+
return hasOwnErrorCode(error, "ENOENT") || hasOwnErrorCode(error, "ENOTDIR");
|
|
515
531
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { OpenApiDocument } from "../generate.js";
|
|
2
|
+
export declare const FORGEYARD_BASE_URL = "https://api.forgeyard.invalid";
|
|
3
|
+
export declare const FORGEYARD_RESOURCES: readonly ["artifacts", "audits", "automations", "branches", "builds", "checks", "changes", "comments", "commits", "deployments", "discussions", "environments", "events", "files", "hooks", "identities", "integrations", "invitations", "jobs", "keys", "labels", "licenses", "members", "milestones", "notifications", "organizations", "packages", "pages", "permissions", "pipelines", "policies", "projects", "releases", "repositories", "reviews", "runners", "secrets", "sessions", "settings", "snapshots", "statuses", "tags", "teams", "templates", "tokens", "topics", "variables", "webhooks", "workflows", "workspaces", "approvals", "archives", "attestations", "billing-accounts", "codespaces", "dependencies", "exports", "imports", "mirrors", "rulesets", "security-alerts", "service-accounts", "signatures", "sponsors"];
|
|
4
|
+
export declare function createForgeyardSpec(): OpenApiDocument;
|