@distilled.cloud/core 0.30.3 → 1.0.0-rc.10
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/LICENSE +201 -0
- package/lib/api.d.ts +165 -0
- package/lib/api.d.ts.map +1 -0
- package/lib/api.js +190 -0
- package/lib/api.js.map +1 -0
- package/lib/category.d.ts +4 -4
- package/lib/category.js +4 -4
- package/lib/codegen/boolean-string-enums.d.ts +36 -0
- package/lib/codegen/boolean-string-enums.d.ts.map +1 -0
- package/lib/codegen/boolean-string-enums.js +94 -0
- package/lib/codegen/boolean-string-enums.js.map +1 -0
- package/lib/codegen/boolean-string-enums.test.d.ts +2 -0
- package/lib/codegen/boolean-string-enums.test.d.ts.map +1 -0
- package/lib/codegen/boolean-string-enums.test.js +147 -0
- package/lib/codegen/boolean-string-enums.test.js.map +1 -0
- package/lib/codegen/cli.d.ts +79 -0
- package/lib/codegen/cli.d.ts.map +1 -0
- package/lib/codegen/cli.js +149 -0
- package/lib/codegen/cli.js.map +1 -0
- package/lib/codegen/emit.d.ts +125 -0
- package/lib/codegen/emit.d.ts.map +1 -0
- package/lib/codegen/emit.js +101 -0
- package/lib/codegen/emit.js.map +1 -0
- package/lib/codegen/format.d.ts +23 -0
- package/lib/codegen/format.d.ts.map +1 -0
- package/lib/codegen/format.js +28 -0
- package/lib/codegen/format.js.map +1 -0
- package/lib/codegen/generator.d.ts +334 -0
- package/lib/codegen/generator.d.ts.map +1 -0
- package/lib/codegen/generator.js +813 -0
- package/lib/codegen/generator.js.map +1 -0
- package/lib/codegen/graph.d.ts +36 -0
- package/lib/codegen/graph.d.ts.map +1 -0
- package/lib/codegen/graph.js +136 -0
- package/lib/codegen/graph.js.map +1 -0
- package/lib/codegen/graphql-client.d.ts +62 -0
- package/lib/codegen/graphql-client.d.ts.map +1 -0
- package/lib/codegen/graphql-client.js +294 -0
- package/lib/codegen/graphql-client.js.map +1 -0
- package/lib/codegen/graphql-client.test.d.ts +2 -0
- package/lib/codegen/graphql-client.test.d.ts.map +1 -0
- package/lib/codegen/graphql-client.test.js +311 -0
- package/lib/codegen/graphql-client.test.js.map +1 -0
- package/lib/codegen/graphql.d.ts +207 -0
- package/lib/codegen/graphql.d.ts.map +1 -0
- package/lib/codegen/graphql.js +799 -0
- package/lib/codegen/graphql.js.map +1 -0
- package/lib/codegen/members.d.ts +25 -0
- package/lib/codegen/members.d.ts.map +1 -0
- package/lib/codegen/members.js +55 -0
- package/lib/codegen/members.js.map +1 -0
- package/lib/codegen/naming.d.ts +29 -0
- package/lib/codegen/naming.d.ts.map +1 -0
- package/lib/codegen/naming.js +74 -0
- package/lib/codegen/naming.js.map +1 -0
- package/lib/codegen/openapi-cli.d.ts +52 -0
- package/lib/codegen/openapi-cli.d.ts.map +1 -0
- package/lib/codegen/openapi-cli.js +109 -0
- package/lib/codegen/openapi-cli.js.map +1 -0
- package/lib/codegen/openapi.d.ts +178 -0
- package/lib/codegen/openapi.d.ts.map +1 -0
- package/lib/codegen/openapi.js +1377 -0
- package/lib/codegen/openapi.js.map +1 -0
- package/lib/codegen/operations.d.ts +24 -0
- package/lib/codegen/operations.d.ts.map +1 -0
- package/lib/codegen/operations.js +56 -0
- package/lib/codegen/operations.js.map +1 -0
- package/lib/codegen/pagination.d.ts +39 -0
- package/lib/codegen/pagination.d.ts.map +1 -0
- package/lib/codegen/pagination.js +33 -0
- package/lib/codegen/pagination.js.map +1 -0
- package/lib/codegen/patches.d.ts +65 -0
- package/lib/codegen/patches.d.ts.map +1 -0
- package/lib/codegen/patches.js +236 -0
- package/lib/codegen/patches.js.map +1 -0
- package/lib/codegen/patches.test.d.ts +2 -0
- package/lib/codegen/patches.test.d.ts.map +1 -0
- package/lib/codegen/patches.test.js +105 -0
- package/lib/codegen/patches.test.js.map +1 -0
- package/lib/codegen/prelude.d.ts +15 -0
- package/lib/codegen/prelude.d.ts.map +1 -0
- package/lib/codegen/prelude.js +60 -0
- package/lib/codegen/prelude.js.map +1 -0
- package/lib/codegen/proto.d.ts +121 -0
- package/lib/codegen/proto.d.ts.map +1 -0
- package/lib/codegen/proto.js +962 -0
- package/lib/codegen/proto.js.map +1 -0
- package/lib/codegen/rewrite-operation-ids.d.ts +131 -0
- package/lib/codegen/rewrite-operation-ids.d.ts.map +1 -0
- package/lib/codegen/rewrite-operation-ids.js +1079 -0
- package/lib/codegen/rewrite-operation-ids.js.map +1 -0
- package/lib/codegen/rewrite-operation-ids.test.d.ts +2 -0
- package/lib/codegen/rewrite-operation-ids.test.d.ts.map +1 -0
- package/lib/codegen/rewrite-operation-ids.test.js +533 -0
- package/lib/codegen/rewrite-operation-ids.test.js.map +1 -0
- package/lib/codegen/spec-path.d.ts +16 -0
- package/lib/codegen/spec-path.d.ts.map +1 -0
- package/lib/codegen/spec-path.js +101 -0
- package/lib/codegen/spec-path.js.map +1 -0
- package/lib/error-category.d.ts +28 -0
- package/lib/error-category.d.ts.map +1 -0
- package/lib/error-category.js +46 -0
- package/lib/error-category.js.map +1 -0
- package/lib/errors.d.ts +1 -0
- package/lib/errors.d.ts.map +1 -1
- package/lib/errors.js +18 -13
- package/lib/errors.js.map +1 -1
- package/lib/graphql.d.ts +284 -0
- package/lib/graphql.d.ts.map +1 -0
- package/lib/graphql.fixture.d.ts +249 -0
- package/lib/graphql.fixture.d.ts.map +1 -0
- package/lib/graphql.fixture.js +240 -0
- package/lib/graphql.fixture.js.map +1 -0
- package/lib/graphql.js +718 -0
- package/lib/graphql.js.map +1 -0
- package/lib/graphql.test.d.ts +2 -0
- package/lib/graphql.test.d.ts.map +1 -0
- package/lib/graphql.test.js +780 -0
- package/lib/graphql.test.js.map +1 -0
- package/lib/graphql.types.d.ts +2 -0
- package/lib/graphql.types.d.ts.map +1 -0
- package/lib/graphql.types.js +45 -0
- package/lib/graphql.types.js.map +1 -0
- package/lib/json-patch.d.ts +30 -30
- package/lib/json-patch.d.ts.map +1 -1
- package/lib/json-patch.js +73 -107
- package/lib/json-patch.js.map +1 -1
- package/lib/pagination.d.ts +77 -51
- package/lib/pagination.d.ts.map +1 -1
- package/lib/pagination.js +162 -94
- package/lib/pagination.js.map +1 -1
- package/lib/protocol-http.d.ts +74 -0
- package/lib/protocol-http.d.ts.map +1 -0
- package/lib/protocol-http.js +590 -0
- package/lib/protocol-http.js.map +1 -0
- package/lib/protocol-http.test.d.ts +2 -0
- package/lib/protocol-http.test.d.ts.map +1 -0
- package/lib/protocol-http.test.js +88 -0
- package/lib/protocol-http.test.js.map +1 -0
- package/lib/protocol-rest.d.ts +134 -0
- package/lib/protocol-rest.d.ts.map +1 -0
- package/lib/protocol-rest.js +256 -0
- package/lib/protocol-rest.js.map +1 -0
- package/lib/retry.d.ts +8 -2
- package/lib/retry.d.ts.map +1 -1
- package/lib/retry.js +22 -16
- package/lib/retry.js.map +1 -1
- package/lib/schema.d.ts +8 -9
- package/lib/schema.d.ts.map +1 -1
- package/lib/schema.js +8 -9
- package/lib/schema.js.map +1 -1
- package/lib/trait.d.ts +174 -0
- package/lib/trait.d.ts.map +1 -0
- package/lib/trait.js +123 -0
- package/lib/trait.js.map +1 -0
- package/package.json +24 -78
- package/src/api.ts +460 -0
- package/src/category.ts +4 -4
- package/src/codegen/boolean-string-enums.test.ts +168 -0
- package/src/codegen/boolean-string-enums.ts +106 -0
- package/src/codegen/cli.ts +285 -0
- package/src/codegen/emit.ts +203 -0
- package/src/codegen/format.ts +47 -0
- package/src/codegen/generator.ts +1283 -0
- package/src/codegen/graph.ts +151 -0
- package/src/codegen/graphql-client.test.ts +386 -0
- package/src/codegen/graphql-client.ts +419 -0
- package/src/codegen/graphql.ts +1217 -0
- package/src/codegen/members.ts +71 -0
- package/src/codegen/naming.ts +86 -0
- package/src/codegen/openapi-cli.ts +182 -0
- package/src/codegen/openapi.ts +1689 -0
- package/src/codegen/operations.ts +76 -0
- package/src/codegen/pagination.ts +71 -0
- package/src/codegen/patches.test.ts +130 -0
- package/src/codegen/patches.ts +291 -0
- package/src/codegen/prelude.ts +70 -0
- package/src/codegen/proto.ts +1128 -0
- package/src/codegen/rewrite-operation-ids.test.ts +563 -0
- package/src/codegen/rewrite-operation-ids.ts +1206 -0
- package/src/codegen/spec-path.ts +115 -0
- package/src/error-category.ts +84 -0
- package/src/errors.ts +22 -25
- package/src/graphql.fixture.ts +371 -0
- package/src/graphql.test.ts +974 -0
- package/src/graphql.ts +1321 -0
- package/src/graphql.types.ts +185 -0
- package/src/json-patch.ts +95 -122
- package/src/pagination.ts +217 -146
- package/src/protocol-http.test.ts +107 -0
- package/src/protocol-http.ts +735 -0
- package/src/protocol-rest.ts +391 -0
- package/src/retry.ts +21 -22
- package/src/schema.ts +9 -10
- package/src/trait.ts +274 -0
- package/README.md +0 -30
- package/lib/client.d.ts +0 -167
- package/lib/client.d.ts.map +0 -1
- package/lib/client.js +0 -659
- package/lib/client.js.map +0 -1
- package/lib/schemas.d.ts +0 -60
- package/lib/schemas.d.ts.map +0 -1
- package/lib/schemas.js +0 -79
- package/lib/schemas.js.map +0 -1
- package/lib/sensitive.d.ts +0 -71
- package/lib/sensitive.d.ts.map +0 -1
- package/lib/sensitive.js +0 -96
- package/lib/sensitive.js.map +0 -1
- package/lib/traits.d.ts +0 -421
- package/lib/traits.d.ts.map +0 -1
- package/lib/traits.js +0 -737
- package/lib/traits.js.map +0 -1
- package/src/client.ts +0 -1177
- package/src/schemas.ts +0 -128
- package/src/sensitive.ts +0 -119
- package/src/traits.ts +0 -996
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structure-member analysis for the SDK generators (dev-time only).
|
|
3
|
+
*
|
|
4
|
+
* The TS-facing name policy is the provider's (cloudflare camelCases wire
|
|
5
|
+
* names, AWS keeps them) — supplied as `nameFn`. Wire-name resolution from
|
|
6
|
+
* the smithy HTTP binding traits is generic smithy semantics.
|
|
7
|
+
*/
|
|
8
|
+
import { oneLine } from "./naming.ts";
|
|
9
|
+
|
|
10
|
+
export interface MemberBase {
|
|
11
|
+
/** Original smithy member name. */
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/** TS-facing name (per `nameFn`, deduplicated within the structure). */
|
|
14
|
+
readonly tsName: string;
|
|
15
|
+
readonly target: string;
|
|
16
|
+
readonly required: boolean;
|
|
17
|
+
readonly doc: string | undefined;
|
|
18
|
+
readonly traits: Record<string, any>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Base analysis of a structure's members: TS naming (with collision
|
|
23
|
+
* dedup — a clashing name falls back to the original, then a numeric
|
|
24
|
+
* suffix), required-ness, and one-line docs. Binding classification and
|
|
25
|
+
* anything provider-specific layer on top via `traits`.
|
|
26
|
+
*/
|
|
27
|
+
export const memberBases = (
|
|
28
|
+
def: any,
|
|
29
|
+
nameFn: (memberName: string) => string = (n) => n,
|
|
30
|
+
): MemberBase[] => {
|
|
31
|
+
const used = new Set<string>();
|
|
32
|
+
return Object.entries(def.members ?? {}).map(([mn, m]: [string, any]) => {
|
|
33
|
+
const traits = m.traits ?? {};
|
|
34
|
+
let tsName = nameFn(mn);
|
|
35
|
+
if (used.has(tsName)) tsName = mn;
|
|
36
|
+
let k = 2;
|
|
37
|
+
while (used.has(tsName)) tsName = `${nameFn(mn)}${k++}`;
|
|
38
|
+
used.add(tsName);
|
|
39
|
+
return {
|
|
40
|
+
name: mn,
|
|
41
|
+
tsName,
|
|
42
|
+
target: m.target,
|
|
43
|
+
required: "smithy.api#required" in traits,
|
|
44
|
+
doc: oneLine(traits["smithy.api#documentation"]),
|
|
45
|
+
traits,
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The wire name a bound member serializes under, per the smithy HTTP
|
|
52
|
+
* binding traits: labels use the member name (URI placeholders), query and
|
|
53
|
+
* header use the trait value when it's a non-empty string, everything else
|
|
54
|
+
* uses `jsonName` when present.
|
|
55
|
+
*/
|
|
56
|
+
export const smithyWireName = (
|
|
57
|
+
traits: Record<string, any>,
|
|
58
|
+
memberName: string,
|
|
59
|
+
binding: "label" | "query" | "header" | "other",
|
|
60
|
+
): string => {
|
|
61
|
+
if (binding === "label") return memberName;
|
|
62
|
+
if (binding === "query") {
|
|
63
|
+
const v = traits["smithy.api#httpQuery"];
|
|
64
|
+
return typeof v === "string" && v ? v : memberName;
|
|
65
|
+
}
|
|
66
|
+
if (binding === "header") {
|
|
67
|
+
const v = traits["smithy.api#httpHeader"];
|
|
68
|
+
return typeof v === "string" && v ? v : memberName;
|
|
69
|
+
}
|
|
70
|
+
return traits["smithy.api#jsonName"] ?? memberName;
|
|
71
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared naming utilities for the SDK generators (dev-time only — imported by
|
|
3
|
+
* `packages/<sdk>/scripts/generate.ts`, never by runtime code).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** JSON-string-quote a value for emission into generated source. */
|
|
7
|
+
export const q = (s: string): string => JSON.stringify(s);
|
|
8
|
+
|
|
9
|
+
/** Smithy shape id → local name (`ns#Shape` → `Shape`). */
|
|
10
|
+
export const local = (id: string): string => id.split("#")[1] ?? id;
|
|
11
|
+
|
|
12
|
+
/** Whether a shape id is a smithy prelude shape (`smithy.api#…`). */
|
|
13
|
+
export const isPrelude = (id: string): boolean => id.startsWith("smithy.api#");
|
|
14
|
+
|
|
15
|
+
const IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
16
|
+
|
|
17
|
+
/** Emit a TS object key: bare when a valid identifier, quoted otherwise. */
|
|
18
|
+
export const tsKey = (s: string): string => (IDENT.test(s) ? s : q(s));
|
|
19
|
+
|
|
20
|
+
/** snake_case / kebab-case wire name → camelCase TS-facing name. */
|
|
21
|
+
export const camel = (s: string): string =>
|
|
22
|
+
s.replace(/[_-]+([A-Za-z0-9])/g, (_, c: string) => c.toUpperCase());
|
|
23
|
+
|
|
24
|
+
/** Reserved words that can't be `const` names. */
|
|
25
|
+
export const RESERVED = new Set([
|
|
26
|
+
"break",
|
|
27
|
+
"case",
|
|
28
|
+
"catch",
|
|
29
|
+
"class",
|
|
30
|
+
"const",
|
|
31
|
+
"continue",
|
|
32
|
+
"debugger",
|
|
33
|
+
"default",
|
|
34
|
+
"delete",
|
|
35
|
+
"do",
|
|
36
|
+
"else",
|
|
37
|
+
"enum",
|
|
38
|
+
"export",
|
|
39
|
+
"extends",
|
|
40
|
+
"false",
|
|
41
|
+
"finally",
|
|
42
|
+
"for",
|
|
43
|
+
"function",
|
|
44
|
+
"if",
|
|
45
|
+
"import",
|
|
46
|
+
"in",
|
|
47
|
+
"instanceof",
|
|
48
|
+
"let",
|
|
49
|
+
"new",
|
|
50
|
+
"null",
|
|
51
|
+
"package",
|
|
52
|
+
"return",
|
|
53
|
+
"static",
|
|
54
|
+
"super",
|
|
55
|
+
"switch",
|
|
56
|
+
"this",
|
|
57
|
+
"throw",
|
|
58
|
+
"true",
|
|
59
|
+
"try",
|
|
60
|
+
"typeof",
|
|
61
|
+
"var",
|
|
62
|
+
"void",
|
|
63
|
+
"while",
|
|
64
|
+
"with",
|
|
65
|
+
"yield",
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Lower-case the first character for an exported operation name — unless the
|
|
70
|
+
* result is a reserved word, in which case the original casing is kept.
|
|
71
|
+
*/
|
|
72
|
+
export const lowerFirst = (s: string): string => {
|
|
73
|
+
const lowered = s.charAt(0).toLowerCase() + s.slice(1);
|
|
74
|
+
return RESERVED.has(lowered) ? s : lowered;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** Upper-case the first character. */
|
|
78
|
+
export const upperFirst = (s: string): string =>
|
|
79
|
+
s.charAt(0).toUpperCase() + s.slice(1);
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Collapse a smithy documentation string to a single safe line for a
|
|
83
|
+
* `/** … */` comment.
|
|
84
|
+
*/
|
|
85
|
+
export const oneLine = (s: string | undefined): string | undefined =>
|
|
86
|
+
s ? s.replace(/\s+/g, " ").replace(/\*\//g, "*\\/").trim() : undefined;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI → Smithy pipeline helper (dev-time only, provider-agnostic).
|
|
3
|
+
*
|
|
4
|
+
* Owns the spec-side pipeline every OpenAPI-sourced provider shares: read the
|
|
5
|
+
* spec file, apply OpenAPI RFC-6902 ops to the document, convert with
|
|
6
|
+
* {@link convertOpenApiToSmithy} (which owns verbNoun naming), apply Smithy
|
|
7
|
+
* RFC-6902 ops (`/shapes`, `/metadata`) to the model, and write
|
|
8
|
+
* `.generated-specs/<name>.json`. Stale targets fail unless
|
|
9
|
+
* `onStalePatch: "warn"`.
|
|
10
|
+
*
|
|
11
|
+
* A provider's `scripts/convert.ts` is: a `runOpenApiConvert` call.
|
|
12
|
+
* `scripts/generate.ts` compiles the already-patched models and does not
|
|
13
|
+
* apply patches.
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from "node:fs/promises";
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
import {
|
|
18
|
+
convertOpenApiToSmithy,
|
|
19
|
+
type OpenApiConvertOptions,
|
|
20
|
+
} from "./openapi.ts";
|
|
21
|
+
import {
|
|
22
|
+
applyRfc6902Files,
|
|
23
|
+
finalizeConvert,
|
|
24
|
+
isSmithyPatchPath,
|
|
25
|
+
listRfc6902PatchFiles,
|
|
26
|
+
} from "./patches.ts";
|
|
27
|
+
import { resolveSpecPath } from "./spec-path.ts";
|
|
28
|
+
|
|
29
|
+
export interface OpenApiSpecEntry {
|
|
30
|
+
/** Output model name — written to `<outDir>/<name>.json`. */
|
|
31
|
+
readonly name: string;
|
|
32
|
+
/** Spec file path, relative to `root` (or absolute). */
|
|
33
|
+
readonly specPath: string;
|
|
34
|
+
/**
|
|
35
|
+
* Hook between patching and conversion (e.g. path prefixing, server
|
|
36
|
+
* rewrites). May mutate the spec in place or return a replacement.
|
|
37
|
+
*/
|
|
38
|
+
readonly preprocess?: (spec: any) => unknown | void | Promise<unknown | void>;
|
|
39
|
+
/** Per-spec converter option overrides (merged over the shared options). */
|
|
40
|
+
readonly options?: Partial<OpenApiConvertOptions>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface RunOpenApiConvertOptions {
|
|
44
|
+
/** Absolute package root (usually `path.resolve(import.meta.dir, "..")`). */
|
|
45
|
+
readonly root: string;
|
|
46
|
+
readonly specs: readonly OpenApiSpecEntry[];
|
|
47
|
+
/**
|
|
48
|
+
* RFC-6902 patch chain root, relative to `root`. Default `"patches"`;
|
|
49
|
+
* `false` disables. Layout: `<patchesDir>/<name>/*.json` when the
|
|
50
|
+
* per-spec directory exists; for single-spec providers a flat
|
|
51
|
+
* `<patchesDir>/*.json` also works. Ops under `/shapes` or `/metadata`
|
|
52
|
+
* apply to the Smithy model after conversion; the rest apply to OpenAPI.
|
|
53
|
+
*/
|
|
54
|
+
readonly patchesDir?: string | false;
|
|
55
|
+
/** Output directory, relative to `root`. Default `".generated-specs"`. */
|
|
56
|
+
readonly outDir?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Spec text parser. Default `JSON.parse` — the seam for YAML specs
|
|
59
|
+
* (`parse: (text) => YAML.parse(text)`).
|
|
60
|
+
*/
|
|
61
|
+
readonly parse?: (text: string, specPath: string) => unknown;
|
|
62
|
+
/** Shared converter options (per-spec `options` merge over these). */
|
|
63
|
+
readonly options: OpenApiConvertOptions;
|
|
64
|
+
/**
|
|
65
|
+
* What to do when a patch JSON pointer does not resolve. Default `"fail"`:
|
|
66
|
+
* silent skip is how a whole patch chain can vanish after an upstream path
|
|
67
|
+
* prefix change. `"warn"` restores the old skip-and-continue behaviour.
|
|
68
|
+
*/
|
|
69
|
+
readonly onStalePatch?: "fail" | "warn";
|
|
70
|
+
/**
|
|
71
|
+
* Run {@link finalizeConvert} on the written models (reference check +
|
|
72
|
+
* finalized marker; naming already happened in the converter). Default
|
|
73
|
+
* true. Pass false when the caller finalizes once after several convert
|
|
74
|
+
* steps (Fly machines + sprites + addons).
|
|
75
|
+
*/
|
|
76
|
+
readonly finalize?: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const exists = async (p: string): Promise<boolean> => {
|
|
80
|
+
try {
|
|
81
|
+
await fs.access(p);
|
|
82
|
+
return true;
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/** Run the OpenAPI→Smithy conversion pipeline (plain async — call from a script). */
|
|
89
|
+
export const runOpenApiConvert = async (
|
|
90
|
+
o: RunOpenApiConvertOptions,
|
|
91
|
+
): Promise<void> => {
|
|
92
|
+
const outDir = path.resolve(o.root, o.outDir ?? ".generated-specs");
|
|
93
|
+
const patchRoot =
|
|
94
|
+
o.patchesDir === false
|
|
95
|
+
? undefined
|
|
96
|
+
: path.resolve(o.root, o.patchesDir ?? "patches");
|
|
97
|
+
const parse = o.parse ?? ((text: string) => JSON.parse(text));
|
|
98
|
+
const onStalePatch = o.onStalePatch ?? "fail";
|
|
99
|
+
|
|
100
|
+
await fs.mkdir(outDir, { recursive: true });
|
|
101
|
+
|
|
102
|
+
console.log("🛠️ openapi → smithy");
|
|
103
|
+
console.log(` Output: ${outDir}`);
|
|
104
|
+
|
|
105
|
+
for (const entry of o.specs) {
|
|
106
|
+
// Production path by default; `specs/.local` under DISTILLED_SPECS_LOCAL.
|
|
107
|
+
const specPath = resolveSpecPath(o.root, entry.specPath);
|
|
108
|
+
let spec: any = parse(await fs.readFile(specPath, "utf8"), specPath);
|
|
109
|
+
|
|
110
|
+
// ---- RFC-6902: OpenAPI ops before convert, Smithy ops after ----
|
|
111
|
+
let patchDir: string | undefined;
|
|
112
|
+
if (patchRoot && (await exists(patchRoot))) {
|
|
113
|
+
const perSpec = path.join(patchRoot, entry.name);
|
|
114
|
+
if (await exists(perSpec)) {
|
|
115
|
+
patchDir = perSpec;
|
|
116
|
+
} else if (o.specs.length === 1) {
|
|
117
|
+
patchDir = patchRoot;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const patchFiles = patchDir ? await listRfc6902PatchFiles(patchDir) : [];
|
|
121
|
+
const patchLabel = (file: string) => `${entry.name}/${path.basename(file)}`;
|
|
122
|
+
const openapiPatches = await applyRfc6902Files(spec, patchFiles, {
|
|
123
|
+
onStalePatch,
|
|
124
|
+
include: (op) => !isSmithyPatchPath(op.path),
|
|
125
|
+
label: patchLabel,
|
|
126
|
+
});
|
|
127
|
+
if (openapiPatches.errors.length) {
|
|
128
|
+
for (const b of openapiPatches.errors)
|
|
129
|
+
console.error(`❌ bad patch: ${b}`);
|
|
130
|
+
throw new Error(
|
|
131
|
+
`${openapiPatches.errors.length} patch operation(s) failed — fix the pointers or delete the patch`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ---- Preprocess hook ----
|
|
136
|
+
if (entry.preprocess) {
|
|
137
|
+
const replaced = await entry.preprocess(spec);
|
|
138
|
+
if (replaced !== undefined) spec = replaced;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ---- Convert, Smithy patches, write ----
|
|
142
|
+
const model = convertOpenApiToSmithy(spec, {
|
|
143
|
+
...o.options,
|
|
144
|
+
...entry.options,
|
|
145
|
+
});
|
|
146
|
+
const smithyPatches = await applyRfc6902Files(model, patchFiles, {
|
|
147
|
+
onStalePatch,
|
|
148
|
+
include: (op) => isSmithyPatchPath(op.path),
|
|
149
|
+
label: patchLabel,
|
|
150
|
+
});
|
|
151
|
+
if (smithyPatches.errors.length) {
|
|
152
|
+
for (const b of smithyPatches.errors) console.error(`❌ bad patch: ${b}`);
|
|
153
|
+
throw new Error(
|
|
154
|
+
`${smithyPatches.errors.length} Smithy patch operation(s) failed — fix the pointers or delete the patch`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const opCount = Object.values(model.shapes).filter(
|
|
158
|
+
(s: any) => s.type === "operation",
|
|
159
|
+
).length;
|
|
160
|
+
const outPath = path.join(outDir, `${entry.name}.json`);
|
|
161
|
+
await fs.writeFile(outPath, JSON.stringify(model, null, 2) + "\n");
|
|
162
|
+
const staleOps = openapiPatches.stale + smithyPatches.stale;
|
|
163
|
+
console.log(
|
|
164
|
+
` ✅ ${entry.name}: ${opCount} operations, ${Object.keys(model.shapes).length} shapes` +
|
|
165
|
+
(patchFiles.length
|
|
166
|
+
? ` (${patchFiles.length} patch file(s) applied${staleOps ? `, ${staleOps} stale op(s) skipped` : ""})`
|
|
167
|
+
: ""),
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (o.finalize !== false) {
|
|
172
|
+
const written = new Set(o.specs.map((s) => s.name));
|
|
173
|
+
await finalizeConvert({
|
|
174
|
+
root: o.root,
|
|
175
|
+
outDir,
|
|
176
|
+
// Patches and naming already ran above.
|
|
177
|
+
patchesDir: false,
|
|
178
|
+
operationNaming: "as-is",
|
|
179
|
+
include: (resource) => written.has(resource),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
};
|