@distilled.cloud/core 1.0.0-rc.1 → 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.
Files changed (148) hide show
  1. package/LICENSE +201 -0
  2. package/lib/api.d.ts.map +1 -1
  3. package/lib/api.js +16 -4
  4. package/lib/api.js.map +1 -1
  5. package/lib/category.d.ts +4 -4
  6. package/lib/category.js +4 -4
  7. package/lib/codegen/boolean-string-enums.d.ts +36 -0
  8. package/lib/codegen/boolean-string-enums.d.ts.map +1 -0
  9. package/lib/codegen/boolean-string-enums.js +94 -0
  10. package/lib/codegen/boolean-string-enums.js.map +1 -0
  11. package/lib/codegen/boolean-string-enums.test.d.ts +2 -0
  12. package/lib/codegen/boolean-string-enums.test.d.ts.map +1 -0
  13. package/lib/codegen/boolean-string-enums.test.js +147 -0
  14. package/lib/codegen/boolean-string-enums.test.js.map +1 -0
  15. package/lib/codegen/cli.d.ts +56 -6
  16. package/lib/codegen/cli.d.ts.map +1 -1
  17. package/lib/codegen/cli.js +59 -75
  18. package/lib/codegen/cli.js.map +1 -1
  19. package/lib/codegen/emit.d.ts +3 -7
  20. package/lib/codegen/emit.d.ts.map +1 -1
  21. package/lib/codegen/emit.js +6 -10
  22. package/lib/codegen/emit.js.map +1 -1
  23. package/lib/codegen/generator.d.ts.map +1 -1
  24. package/lib/codegen/generator.js +142 -20
  25. package/lib/codegen/generator.js.map +1 -1
  26. package/lib/codegen/graphql-client.d.ts +62 -0
  27. package/lib/codegen/graphql-client.d.ts.map +1 -0
  28. package/lib/codegen/graphql-client.js +294 -0
  29. package/lib/codegen/graphql-client.js.map +1 -0
  30. package/lib/codegen/graphql-client.test.d.ts +2 -0
  31. package/lib/codegen/graphql-client.test.d.ts.map +1 -0
  32. package/lib/codegen/graphql-client.test.js +311 -0
  33. package/lib/codegen/graphql-client.test.js.map +1 -0
  34. package/lib/codegen/graphql.d.ts +207 -0
  35. package/lib/codegen/graphql.d.ts.map +1 -0
  36. package/lib/codegen/graphql.js +799 -0
  37. package/lib/codegen/graphql.js.map +1 -0
  38. package/lib/codegen/openapi-cli.d.ts +17 -3
  39. package/lib/codegen/openapi-cli.d.ts.map +1 -1
  40. package/lib/codegen/openapi-cli.js +50 -48
  41. package/lib/codegen/openapi-cli.js.map +1 -1
  42. package/lib/codegen/openapi.d.ts +69 -6
  43. package/lib/codegen/openapi.d.ts.map +1 -1
  44. package/lib/codegen/openapi.js +173 -16
  45. package/lib/codegen/openapi.js.map +1 -1
  46. package/lib/codegen/patches.d.ts +65 -0
  47. package/lib/codegen/patches.d.ts.map +1 -0
  48. package/lib/codegen/patches.js +236 -0
  49. package/lib/codegen/patches.js.map +1 -0
  50. package/lib/codegen/patches.test.d.ts +2 -0
  51. package/lib/codegen/patches.test.d.ts.map +1 -0
  52. package/lib/codegen/patches.test.js +105 -0
  53. package/lib/codegen/patches.test.js.map +1 -0
  54. package/lib/codegen/proto.d.ts +121 -0
  55. package/lib/codegen/proto.d.ts.map +1 -0
  56. package/lib/codegen/proto.js +962 -0
  57. package/lib/codegen/proto.js.map +1 -0
  58. package/lib/codegen/rewrite-operation-ids.d.ts +131 -0
  59. package/lib/codegen/rewrite-operation-ids.d.ts.map +1 -0
  60. package/lib/codegen/rewrite-operation-ids.js +1079 -0
  61. package/lib/codegen/rewrite-operation-ids.js.map +1 -0
  62. package/lib/codegen/rewrite-operation-ids.test.d.ts +2 -0
  63. package/lib/codegen/rewrite-operation-ids.test.d.ts.map +1 -0
  64. package/lib/codegen/rewrite-operation-ids.test.js +533 -0
  65. package/lib/codegen/rewrite-operation-ids.test.js.map +1 -0
  66. package/lib/codegen/spec-path.d.ts +16 -0
  67. package/lib/codegen/spec-path.d.ts.map +1 -0
  68. package/lib/codegen/spec-path.js +101 -0
  69. package/lib/codegen/spec-path.js.map +1 -0
  70. package/lib/errors.d.ts.map +1 -1
  71. package/lib/errors.js +17 -13
  72. package/lib/errors.js.map +1 -1
  73. package/lib/graphql.d.ts +284 -0
  74. package/lib/graphql.d.ts.map +1 -0
  75. package/lib/graphql.fixture.d.ts +249 -0
  76. package/lib/graphql.fixture.d.ts.map +1 -0
  77. package/lib/graphql.fixture.js +240 -0
  78. package/lib/graphql.fixture.js.map +1 -0
  79. package/lib/graphql.js +718 -0
  80. package/lib/graphql.js.map +1 -0
  81. package/lib/graphql.test.d.ts +2 -0
  82. package/lib/graphql.test.d.ts.map +1 -0
  83. package/lib/graphql.test.js +780 -0
  84. package/lib/graphql.test.js.map +1 -0
  85. package/lib/graphql.types.d.ts +2 -0
  86. package/lib/graphql.types.d.ts.map +1 -0
  87. package/lib/graphql.types.js +45 -0
  88. package/lib/graphql.types.js.map +1 -0
  89. package/lib/json-patch.d.ts +18 -11
  90. package/lib/json-patch.d.ts.map +1 -1
  91. package/lib/json-patch.js +63 -25
  92. package/lib/json-patch.js.map +1 -1
  93. package/lib/pagination.d.ts +43 -3
  94. package/lib/pagination.d.ts.map +1 -1
  95. package/lib/pagination.js +91 -5
  96. package/lib/pagination.js.map +1 -1
  97. package/lib/protocol-http.d.ts.map +1 -1
  98. package/lib/protocol-http.js +62 -26
  99. package/lib/protocol-http.js.map +1 -1
  100. package/lib/protocol-http.test.d.ts +2 -0
  101. package/lib/protocol-http.test.d.ts.map +1 -0
  102. package/lib/protocol-http.test.js +88 -0
  103. package/lib/protocol-http.test.js.map +1 -0
  104. package/lib/protocol-rest.d.ts +12 -2
  105. package/lib/protocol-rest.d.ts.map +1 -1
  106. package/lib/protocol-rest.js +17 -3
  107. package/lib/protocol-rest.js.map +1 -1
  108. package/lib/retry.js +1 -1
  109. package/lib/schema.d.ts +1 -1
  110. package/lib/schema.d.ts.map +1 -1
  111. package/lib/schema.js +1 -1
  112. package/lib/schema.js.map +1 -1
  113. package/lib/trait.d.ts +27 -3
  114. package/lib/trait.d.ts.map +1 -1
  115. package/lib/trait.js +17 -1
  116. package/lib/trait.js.map +1 -1
  117. package/package.json +13 -10
  118. package/src/api.ts +18 -4
  119. package/src/category.ts +4 -4
  120. package/src/codegen/boolean-string-enums.test.ts +168 -0
  121. package/src/codegen/boolean-string-enums.ts +106 -0
  122. package/src/codegen/cli.ts +127 -110
  123. package/src/codegen/emit.ts +6 -10
  124. package/src/codegen/generator.ts +151 -21
  125. package/src/codegen/graphql-client.test.ts +386 -0
  126. package/src/codegen/graphql-client.ts +419 -0
  127. package/src/codegen/graphql.ts +1217 -0
  128. package/src/codegen/openapi-cli.ts +75 -59
  129. package/src/codegen/openapi.ts +255 -16
  130. package/src/codegen/patches.test.ts +130 -0
  131. package/src/codegen/patches.ts +291 -0
  132. package/src/codegen/proto.ts +1128 -0
  133. package/src/codegen/rewrite-operation-ids.test.ts +563 -0
  134. package/src/codegen/rewrite-operation-ids.ts +1206 -0
  135. package/src/codegen/spec-path.ts +115 -0
  136. package/src/errors.ts +20 -25
  137. package/src/graphql.fixture.ts +371 -0
  138. package/src/graphql.test.ts +974 -0
  139. package/src/graphql.ts +1321 -0
  140. package/src/graphql.types.ts +185 -0
  141. package/src/json-patch.ts +82 -25
  142. package/src/pagination.ts +134 -7
  143. package/src/protocol-http.test.ts +107 -0
  144. package/src/protocol-http.ts +67 -31
  145. package/src/protocol-rest.ts +28 -4
  146. package/src/retry.ts +1 -1
  147. package/src/schema.ts +2 -2
  148. package/src/trait.ts +39 -3
@@ -1 +1 @@
1
- {"version":3,"file":"trait.d.ts","sourceRoot":"","sources":["../src/trait.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trait.d.ts","sourceRoot":"","sources":["../src/trait.ts"],"names":[],"mappings":"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"}
package/lib/trait.js CHANGED
@@ -68,6 +68,17 @@ export const httpBodySymbol = Symbol.for("@distilled.cloud/core/http-body");
68
68
  * `smithy.api#httpPayload`.
69
69
  */
70
70
  export const HttpBody = () => makeAnnotation(httpBodySymbol, true);
71
+ export const stringEncodedSymbol = Symbol.for("@distilled.cloud/core/http/string-encoded");
72
+ /**
73
+ * Marks a member the API only accepts as the STRING spelling of its value —
74
+ * `true` travels as `"true"`, `3` as `"3"` — while the TS surface keeps the
75
+ * natural type (e.g. Cloudflare's multipart `validation_enabled`, which the
76
+ * docs model as the enum `"true" | "false"`). The protocol stringifies body
77
+ * members on encode, element-wise for lists; `null` is left alone. Query and
78
+ * header bindings already serialize their values as strings, so the trait is
79
+ * documentation there.
80
+ */
81
+ export const StringEncoded = () => makeAnnotation(stringEncodedSymbol, true);
71
82
  export const formDataFileSymbol = Symbol.for("@distilled.cloud/core/form-data-file");
72
83
  /**
73
84
  * Marks an input member holding `File`/`Blob` parts for a multipart upload
@@ -86,8 +97,13 @@ export const unionCasesSymbol = Symbol.for("@distilled.cloud/core/union-cases");
86
97
  * case's keys with `null` for the inactive ones, the protocol uses these key
87
98
  * sets to pick the active case and drop the others, so consumers' `"key" in
88
99
  * value` discrimination works.
100
+ *
101
+ * Key sets alone cannot tell apart cases that share them — the 41 resource
102
+ * kinds of `resource_tagging`, the 34 page-rule actions — so when the union
103
+ * has a discriminator the protocol reads the case off it and only falls back
104
+ * to key-set scoring for a value whose tag is missing or unknown.
89
105
  */
90
- export const UnionCases = (cases) => makeAnnotation(unionCasesSymbol, cases);
106
+ export const UnionCases = (cases, discriminator) => makeAnnotation(unionCasesSymbol, discriminator ? { cases, discriminator } : { cases });
91
107
  //#endregion
92
108
  //#region Error matcher traits
93
109
  export const errorMatchersSymbol = Symbol.for("@distilled.cloud/core/error-matchers");
package/lib/trait.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"trait.js","sourceRoot":"","sources":["../src/trait.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trait.js","sourceRoot":"","sources":["../src/trait.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@distilled.cloud/core",
3
- "version": "1.0.0-rc.1",
3
+ "version": "1.0.0-rc.10",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/alchemy-run/distilled",
@@ -27,16 +27,19 @@
27
27
  "import": "./lib/*.js"
28
28
  }
29
29
  },
30
- "scripts": {
31
- "build": "tsc -b"
32
- },
33
30
  "devDependencies": {
34
- "@effect/platform-bun": ">=4.0.0-beta.102 || >=4.0.0",
35
- "@types/bun": "latest",
36
- "@types/node": "latest",
37
- "effect": ">=4.0.0-beta.102 || >=4.0.0"
31
+ "@effect/platform-bun": ">=4.0.0-rc.115 || >=4.0.0",
32
+ "@types/bun": "1.3.14",
33
+ "@types/node": "26.2.0",
34
+ "effect": ">=4.0.0-rc.115 || >=4.0.0"
38
35
  },
39
36
  "peerDependencies": {
40
- "effect": ">=4.0.0-beta.102 || >=4.0.0"
37
+ "effect": ">=4.0.0-rc.115 || >=4.0.0"
38
+ },
39
+ "dependencies": {
40
+ "graphql": "16.11.0"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc -b"
41
44
  }
42
- }
45
+ }
package/src/api.ts CHANGED
@@ -276,7 +276,11 @@ export function make<
276
276
 
277
277
  // Make the operation itself yieldable: `yield* operation` captures the
278
278
  // current context and returns a requirement-free call function (mirrors
279
- // the distilled repo's OperationMethod).
279
+ // the distilled repo's OperationMethod). The captured context is a
280
+ // FALLBACK, not a snapshot: entries present on the calling fiber at call
281
+ // time win, so per-call overrides — e.g. providing `Endpoint` with a
282
+ // discovered data-plane address around one invocation — take effect
283
+ // instead of being shadowed by the context captured at yield time.
280
284
  const Proto = {
281
285
  [Symbol.iterator](this: any) {
282
286
  return new SingleShotGen(this.asEffect());
@@ -288,7 +292,12 @@ export function make<
288
292
  return Effect.map(
289
293
  Effect.context(),
290
294
  (context) => (input: unknown) =>
291
- Effect.provideContext(fn(input), context),
295
+ // `Context` is contravariant, so `Context<never>` is not assignable
296
+ // to the `Context<any>` updateContext expects — the widening cast is
297
+ // sound (the merge only ever adds entries).
298
+ Effect.updateContext(fn(input), (current): Context.Context<any> =>
299
+ Context.merge(context, current),
300
+ ),
292
301
  );
293
302
  },
294
303
  };
@@ -432,11 +441,16 @@ export function makePaginated<
432
441
  // `yield* operation` runs through `make`'s Proto.asEffect, which builds a
433
442
  // fresh arrow and would drop `.pages` / `.items` (distilled #145). Override
434
443
  // it here — Proto's `[Symbol.iterator]`/`pipe` dispatch on `this`, so both
435
- // pick this up. Only paginated operations pay for it.
444
+ // pick this up. Only paginated operations pay for it. Same fallback (not
445
+ // snapshot) semantics as Proto.asEffect: call-time fiber entries win over
446
+ // the captured context.
436
447
  fn.asEffect = () =>
437
448
  Effect.map(Effect.context(), (context) =>
438
449
  withStreams((input: unknown) =>
439
- Effect.provideContext(fn(input), context),
450
+ // Same contravariance widening as Proto.asEffect above.
451
+ Effect.updateContext(fn(input), (current): Context.Context<any> =>
452
+ Context.merge(context, current),
453
+ ),
440
454
  ),
441
455
  );
442
456
 
package/src/category.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * ```ts
10
10
  * import * as Category from "@distilled.cloud/core/category";
11
11
  *
12
- * export class Unauthorized extends Schema.TaggedErrorClass<Unauthorized>()(
12
+ * export class Unauthorized extends Schema.TaggedError<Unauthorized>()(
13
13
  * "Unauthorized",
14
14
  * { message: Schema.String },
15
15
  * ).pipe(Category.withAuthError) {}
@@ -92,7 +92,7 @@ export interface RetryableInfo {
92
92
  *
93
93
  * @example
94
94
  * ```ts
95
- * export class MyError extends Schema.TaggedErrorClass<MyError>()(
95
+ * export class MyError extends Schema.TaggedError<MyError>()(
96
96
  * "MyError",
97
97
  * { message: Schema.String },
98
98
  * ).pipe(Category.withCategory(Category.AuthError)) {}
@@ -123,13 +123,13 @@ export const withCategory =
123
123
  * @example
124
124
  * ```ts
125
125
  * // Standard retryable error
126
- * export class TransientError extends Schema.TaggedErrorClass<TransientError>()(
126
+ * export class TransientError extends Schema.TaggedError<TransientError>()(
127
127
  * "TransientError",
128
128
  * { message: Schema.String },
129
129
  * ).pipe(Category.withRetryable()) {}
130
130
  *
131
131
  * // Throttling error (uses longer backoff)
132
- * export class RateLimitError extends Schema.TaggedErrorClass<RateLimitError>()(
132
+ * export class RateLimitError extends Schema.TaggedError<RateLimitError>()(
133
133
  * "RateLimitError",
134
134
  * { message: Schema.String },
135
135
  * ).pipe(Category.withRetryable({ throttling: true })) {}
@@ -0,0 +1,168 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import {
3
+ booleanStringEnums,
4
+ STRING_ENCODED_TRAIT,
5
+ } from "./boolean-string-enums.ts";
6
+ import { generateService } from "./generator.ts";
7
+
8
+ const boolEnum = {
9
+ type: "enum",
10
+ members: {
11
+ TRUE: {
12
+ target: "smithy.api#Unit",
13
+ traits: { "smithy.api#enumValue": "true" },
14
+ },
15
+ FALSE: {
16
+ target: "smithy.api#Unit",
17
+ traits: { "smithy.api#enumValue": "false" },
18
+ },
19
+ },
20
+ };
21
+
22
+ const model = (shapes: Record<string, any>) => ({ smithy: "2.0", shapes });
23
+
24
+ describe("booleanStringEnums", () => {
25
+ test("retargets a request member and stamps the trait", () => {
26
+ const m = model({
27
+ "com.example.x#Flag": boolEnum,
28
+ "com.example.x#Request": {
29
+ type: "structure",
30
+ traits: { "smithy.api#input": {} },
31
+ members: { validation_enabled: { target: "com.example.x#Flag" } },
32
+ },
33
+ });
34
+ expect(booleanStringEnums(m)).toEqual({ members: 1, lists: 0 });
35
+ const member = m.shapes["com.example.x#Request"].members.validation_enabled;
36
+ expect(member.target).toBe("smithy.api#Boolean");
37
+ expect(member.traits[STRING_ENCODED_TRAIT]).toEqual({});
38
+ });
39
+
40
+ test("leaves response members alone", () => {
41
+ const m = model({
42
+ "com.example.x#Flag": boolEnum,
43
+ "com.example.x#Response": {
44
+ type: "structure",
45
+ members: { active: { target: "com.example.x#Flag" } },
46
+ },
47
+ });
48
+ expect(booleanStringEnums(m)).toEqual({ members: 0, lists: 0 });
49
+ expect(m.shapes["com.example.x#Response"].members.active.target).toBe(
50
+ "com.example.x#Flag",
51
+ );
52
+ });
53
+
54
+ test("retargets a request-only list's element type", () => {
55
+ const m = model({
56
+ "com.example.x#Flag": boolEnum,
57
+ "com.example.x#FlagList": {
58
+ type: "list",
59
+ member: { target: "com.example.x#Flag" },
60
+ },
61
+ "com.example.x#Request": {
62
+ type: "structure",
63
+ traits: { "smithy.api#input": {} },
64
+ members: { unique_entries: { target: "com.example.x#FlagList" } },
65
+ },
66
+ });
67
+ expect(booleanStringEnums(m)).toEqual({ members: 1, lists: 1 });
68
+ expect(m.shapes["com.example.x#FlagList"].member.target).toBe(
69
+ "smithy.api#Boolean",
70
+ );
71
+ });
72
+
73
+ test("leaves a list a response also uses", () => {
74
+ const m = model({
75
+ "com.example.x#Flag": boolEnum,
76
+ "com.example.x#FlagList": {
77
+ type: "list",
78
+ member: { target: "com.example.x#Flag" },
79
+ },
80
+ "com.example.x#Request": {
81
+ type: "structure",
82
+ traits: { "smithy.api#input": {} },
83
+ members: { unique_entries: { target: "com.example.x#FlagList" } },
84
+ },
85
+ "com.example.x#Response": {
86
+ type: "structure",
87
+ members: { seen: { target: "com.example.x#FlagList" } },
88
+ },
89
+ });
90
+ expect(booleanStringEnums(m)).toEqual({ members: 0, lists: 0 });
91
+ expect(m.shapes["com.example.x#FlagList"].member.target).toBe(
92
+ "com.example.x#Flag",
93
+ );
94
+ });
95
+
96
+ test("leaves an enum that is not exactly true/false", () => {
97
+ const m = model({
98
+ "com.example.x#Tri": {
99
+ type: "enum",
100
+ members: {
101
+ TRUE: {
102
+ target: "smithy.api#Unit",
103
+ traits: { "smithy.api#enumValue": "true" },
104
+ },
105
+ FALSE: {
106
+ target: "smithy.api#Unit",
107
+ traits: { "smithy.api#enumValue": "false" },
108
+ },
109
+ AUTO: {
110
+ target: "smithy.api#Unit",
111
+ traits: { "smithy.api#enumValue": "auto" },
112
+ },
113
+ },
114
+ },
115
+ "com.example.x#Request": {
116
+ type: "structure",
117
+ traits: { "smithy.api#input": {} },
118
+ members: { mode: { target: "com.example.x#Tri" } },
119
+ },
120
+ });
121
+ expect(booleanStringEnums(m)).toEqual({ members: 0, lists: 0 });
122
+ });
123
+ });
124
+
125
+ describe("generateService", () => {
126
+ test("emits a boolean piped through T.StringEncoded()", () => {
127
+ const { code } = generateService(
128
+ model({
129
+ "com.example.x#Example": {
130
+ type: "service",
131
+ version: "2024-01-01",
132
+ operations: [{ target: "com.example.x#GetThing" }],
133
+ },
134
+ "com.example.x#GetThing": {
135
+ type: "operation",
136
+ input: { target: "com.example.x#GetThingRequest" },
137
+ output: { target: "smithy.api#Unit" },
138
+ traits: { "smithy.api#http": { method: "GET", uri: "/things" } },
139
+ },
140
+ "com.example.x#GetThingRequest": {
141
+ type: "structure",
142
+ traits: { "smithy.api#input": {} },
143
+ members: {
144
+ verbose: {
145
+ target: "com.example.x#Flag",
146
+ traits: { "smithy.api#httpQuery": "verbose" },
147
+ },
148
+ },
149
+ },
150
+ "com.example.x#Flag": boolEnum,
151
+ }),
152
+ {
153
+ operationDecl: {
154
+ contextType: "ExampleOpContext",
155
+ commonErrorType: "ExampleOpError",
156
+ commonErrorClasses: [],
157
+ protocol: "ExampleProtocol",
158
+ retry: "Retry.Retry",
159
+ },
160
+ },
161
+ );
162
+ expect(code).toContain(
163
+ '"verbose": S.optional(S.Boolean.pipe(T.Query(), T.StringEncoded())),',
164
+ );
165
+ expect(code).toContain("verbose?: boolean;");
166
+ expect(code).not.toContain('"true" | "false"');
167
+ });
168
+ });
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Boolean-valued string enums on request members (dev-time only).
3
+ *
4
+ * Plenty of APIs document a flag as the string enum `"true" | "false"`
5
+ * rather than a JSON boolean — Cloudflare's `validation_enabled`, Clerk's
6
+ * `include_invalid`, GrowthBook's `deleteMissing`, and so on. Taken
7
+ * literally that surfaces as `"true" | "false" | (string & {})` and every
8
+ * caller writes the ternary itself.
9
+ *
10
+ * {@link generateService} runs this pass over the loaded model before
11
+ * emitting: REQUEST members of such an enum are retargeted to a real
12
+ * `smithy.api#Boolean` and stamped {@link STRING_ENCODED_TRAIT}, which the
13
+ * generator emits as `T.StringEncoded()` and the protocol's `buildRequest`
14
+ * honors by sending the value's string spelling. The TS surface becomes
15
+ * `boolean` with the wire unchanged. The model on disk keeps the string
16
+ * enum the description documents.
17
+ *
18
+ * Deliberately narrow:
19
+ *
20
+ * • request shapes only (`smithy.api#input`) — a response member would
21
+ * need the mirror-image decode, which the protocol does not do;
22
+ * • a list member is retargeted only when EVERY reference to that list
23
+ * comes from a request shape, so a shared list is never rewritten;
24
+ * • the enum must be exactly `{"true", "false"}` — a three-value enum
25
+ * that happens to include them is left alone.
26
+ */
27
+
28
+ /** Synthetic trait: send this member's value as its string spelling. */
29
+ export const STRING_ENCODED_TRAIT = "distilled.protocols#stringEncoded";
30
+
31
+ const BOOLEAN = "smithy.api#Boolean";
32
+
33
+ export interface BooleanStringEnumResult {
34
+ /** Request members retargeted to a real boolean. */
35
+ members: number;
36
+ /** List shapes whose element type was retargeted. */
37
+ lists: number;
38
+ }
39
+
40
+ /** Enum shapes whose values are exactly `"true"` and `"false"`. */
41
+ const booleanEnumIds = (shapes: Record<string, any>): Set<string> => {
42
+ const out = new Set<string>();
43
+ for (const [id, shape] of Object.entries(shapes)) {
44
+ if (shape?.type !== "enum") continue;
45
+ const values = Object.values(shape.members ?? {}).map(
46
+ (m: any) => m?.traits?.["smithy.api#enumValue"],
47
+ );
48
+ if (
49
+ values.length === 2 &&
50
+ values.includes("true") &&
51
+ values.includes("false")
52
+ ) {
53
+ out.add(id);
54
+ }
55
+ }
56
+ return out;
57
+ };
58
+
59
+ const isRequestShape = (shape: any): boolean =>
60
+ shape?.type === "structure" && "smithy.api#input" in (shape.traits ?? {});
61
+
62
+ export const booleanStringEnums = (model: any): BooleanStringEnumResult => {
63
+ const shapes: Record<string, any> = model?.shapes ?? {};
64
+ const boolEnums = booleanEnumIds(shapes);
65
+ if (boolEnums.size === 0) return { members: 0, lists: 0 };
66
+
67
+ // Lists of a boolean enum, and whether anything outside a request shape
68
+ // refers to them (a shared list keeps its documented string type).
69
+ const boolLists = new Set<string>();
70
+ for (const [id, shape] of Object.entries(shapes)) {
71
+ if (shape?.type === "list" && boolEnums.has(shape.member?.target)) {
72
+ boolLists.add(id);
73
+ }
74
+ }
75
+ const sharedLists = new Set<string>();
76
+ for (const shape of Object.values(shapes)) {
77
+ if (isRequestShape(shape)) continue;
78
+ for (const member of Object.values<any>(shape?.members ?? {})) {
79
+ if (boolLists.has(member?.target)) sharedLists.add(member.target);
80
+ }
81
+ if (boolLists.has(shape?.member?.target)) {
82
+ sharedLists.add(shape.member.target);
83
+ }
84
+ }
85
+
86
+ let members = 0;
87
+ const retargeted = new Set<string>();
88
+ for (const shape of Object.values<any>(shapes)) {
89
+ if (!isRequestShape(shape)) continue;
90
+ for (const member of Object.values<any>(shape.members ?? {})) {
91
+ const isList =
92
+ boolLists.has(member?.target) && !sharedLists.has(member.target);
93
+ if (!boolEnums.has(member?.target) && !isList) continue;
94
+ if (isList) {
95
+ retargeted.add(member.target);
96
+ } else {
97
+ member.target = BOOLEAN;
98
+ }
99
+ member.traits = { ...member.traits, [STRING_ENCODED_TRAIT]: {} };
100
+ members++;
101
+ }
102
+ }
103
+ for (const id of retargeted) shapes[id].member.target = BOOLEAN;
104
+
105
+ return { members, lists: retargeted.size };
106
+ };