@aws/nx-plugin 1.0.0 → 1.0.2

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 (124) hide show
  1. package/LICENSE-THIRD-PARTY +11686 -23398
  2. package/README.md +18 -0
  3. package/generators.json +7 -0
  4. package/migrations.json +39 -1
  5. package/package.json +6 -6
  6. package/src/agentcore-gateway/agent-connection/generator.js +6 -0
  7. package/src/agentcore-gateway/agent-connection/generator.js.map +1 -1
  8. package/src/agentcore-gateway/schema.json +1 -0
  9. package/src/agentcore-harness/generator.d.ts +1 -1
  10. package/src/connection/scaffold-catalog.d.ts +21 -0
  11. package/src/connection/scaffold-catalog.js +14 -6
  12. package/src/connection/scaffold-catalog.js.map +1 -1
  13. package/src/infra/app/generator.d.ts +1 -1
  14. package/src/init/generator.d.ts +1 -1
  15. package/src/mcp-server/guide-pipeline.d.ts +2 -1
  16. package/src/mcp-server/guide-pipeline.js +6 -0
  17. package/src/mcp-server/guide-pipeline.js.map +1 -1
  18. package/src/mcp-server/mdx-ast.d.ts +7 -0
  19. package/src/mcp-server/mdx-ast.js +15 -0
  20. package/src/mcp-server/mdx-ast.js.map +1 -1
  21. package/src/mcp-server/schema-registry.d.ts +2 -2
  22. package/src/mcp-server/schema-registry.js +2 -2
  23. package/src/mcp-server/schema-registry.js.map +1 -1
  24. package/src/migrations/latest/terraform-harness-environment-variables/metadata.json +3 -0
  25. package/src/migrations/latest/terraform-harness-environment-variables/migration.d.ts +6 -0
  26. package/src/migrations/latest/terraform-harness-environment-variables/migration.js +54 -0
  27. package/src/migrations/latest/terraform-harness-environment-variables/migration.js.map +1 -0
  28. package/src/open-api/py-client/__snapshots__/generator.additional-properties.spec.ts.snap +34 -0
  29. package/src/open-api/py-client/__snapshots__/generator.arrays.spec.ts.snap +1750 -0
  30. package/src/open-api/py-client/__snapshots__/generator.complex-types.spec.ts.snap +82 -0
  31. package/src/open-api/py-client/__snapshots__/generator.composite-types.spec.ts.snap +447 -0
  32. package/src/open-api/py-client/__snapshots__/generator.duplicate-types.spec.ts.snap +404 -0
  33. package/src/open-api/py-client/__snapshots__/generator.errors.spec.ts.snap +430 -0
  34. package/src/open-api/py-client/__snapshots__/generator.fast-api.spec.ts.snap +447 -0
  35. package/src/open-api/py-client/__snapshots__/generator.petstore.spec.ts.snap +3488 -0
  36. package/src/open-api/py-client/__snapshots__/generator.primitive-types.spec.ts.snap +1444 -0
  37. package/src/open-api/py-client/__snapshots__/generator.request.spec.ts.snap +390 -0
  38. package/src/open-api/py-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +364 -0
  39. package/src/open-api/py-client/__snapshots__/generator.response.spec.ts.snap +739 -0
  40. package/src/open-api/py-client/__snapshots__/generator.streaming.spec.ts.snap +384 -0
  41. package/src/open-api/py-client/__snapshots__/generator.tags.spec.ts.snap +414 -0
  42. package/src/open-api/py-client/files/client/__clientModuleName__.py.template +1076 -0
  43. package/src/open-api/py-client/files/shared/__init__.py.template +28 -0
  44. package/src/open-api/py-client/files/shared/errors.py.template +37 -0
  45. package/src/open-api/py-client/files/shared/types.py.template +319 -0
  46. package/src/open-api/py-client/generator.d.ts +53 -0
  47. package/src/open-api/py-client/generator.js +119 -0
  48. package/src/open-api/py-client/generator.js.map +1 -0
  49. package/src/open-api/py-client/schema.d.js +6 -0
  50. package/src/open-api/py-client/schema.d.js.map +1 -0
  51. package/src/open-api/py-client/schema.d.ts +12 -0
  52. package/src/open-api/py-client/schema.json +28 -0
  53. package/src/open-api/py-client/vessel-registry-spec.json +2716 -0
  54. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +274 -0
  55. package/src/open-api/ts-client/petstore-spec.d.ts +6 -0
  56. package/src/open-api/ts-client/petstore-spec.js +1275 -0
  57. package/src/open-api/ts-client/petstore-spec.js.map +1 -0
  58. package/src/open-api/ts-hooks/generator.spec.tsx +1 -1
  59. package/src/open-api/utils/codegen-data/languages.d.ts +68 -2
  60. package/src/open-api/utils/codegen-data/languages.js +433 -21
  61. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  62. package/src/open-api/utils/codegen-data/types.d.ts +187 -0
  63. package/src/open-api/utils/codegen-data/types.js +10 -1
  64. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  65. package/src/open-api/utils/codegen-data.d.ts +40 -1
  66. package/src/open-api/utils/codegen-data.js +622 -17
  67. package/src/open-api/utils/codegen-data.js.map +1 -1
  68. package/src/open-api/utils/normalise.js +175 -41
  69. package/src/open-api/utils/normalise.js.map +1 -1
  70. package/src/open-api/utils/parser.js +1 -1
  71. package/src/open-api/utils/parser.js.map +1 -1
  72. package/src/preset/__snapshots__/generator.spec.ts.snap +3 -3
  73. package/src/preset/generator.d.ts +1 -1
  74. package/src/py/agent/gateway-connection/generator.js +0 -3
  75. package/src/py/agent/gateway-connection/generator.js.map +1 -1
  76. package/src/py/agent/react-connection/generator.d.ts +1 -1
  77. package/src/py/agent/schema.json +2 -0
  78. package/src/py/fast-api/react/generator.d.ts +1 -1
  79. package/src/py/mcp-server/schema.json +1 -0
  80. package/src/sdk/open-api.d.ts +2 -0
  81. package/src/sdk/open-api.js +1 -0
  82. package/src/sdk/open-api.js.map +1 -1
  83. package/src/smithy/project/generator.d.ts +1 -1
  84. package/src/smithy/react-connection/generator.d.ts +1 -1
  85. package/src/terraform/project/generator.d.ts +1 -1
  86. package/src/trpc/react/generator.d.ts +1 -1
  87. package/src/ts/agent/a2a-connection/generator.d.ts +1 -1
  88. package/src/ts/agent/gateway-connection/generator.d.ts +1 -1
  89. package/src/ts/agent/gateway-connection/generator.js +0 -3
  90. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  91. package/src/ts/agent/mcp-connection/generator.d.ts +1 -1
  92. package/src/ts/agent/react-connection/generator.d.ts +1 -1
  93. package/src/ts/agent/schema.json +1 -0
  94. package/src/ts/api/schema.json +2 -0
  95. package/src/ts/astro-docs/generator.d.ts +1 -1
  96. package/src/ts/dcr-proxy/generator.d.ts +1 -1
  97. package/src/ts/dynamodb/generator.d.ts +1 -1
  98. package/src/ts/lambda-function/generator.d.ts +1 -1
  99. package/src/ts/lib/generator.d.ts +1 -1
  100. package/src/ts/mcp-server/schema.json +1 -0
  101. package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +1 -1
  102. package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.spec.ts.template +1 -1
  103. package/src/ts/nx-generator/generator.d.ts +1 -1
  104. package/src/ts/nx-migration/generator.d.ts +1 -1
  105. package/src/ts/nx-plugin/generator.d.ts +1 -1
  106. package/src/ts/rdb/generator.d.ts +1 -1
  107. package/src/ts/react-website/agui/generator.d.ts +1 -1
  108. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +10 -10
  109. package/src/ts/react-website/app/schema.json +1 -0
  110. package/src/ts/website/app/schema.json +1 -0
  111. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-harness/__nameKebabCase__/__nameKebabCase__.tf.template +1 -1
  112. package/src/utils/metrics-assertions.d.ts +18 -0
  113. package/src/utils/metrics-assertions.js +42 -0
  114. package/src/utils/metrics-assertions.js.map +1 -0
  115. package/src/utils/test/python-dependencies.d.ts +8 -0
  116. package/src/utils/test/python-dependencies.js +14 -0
  117. package/src/utils/test/python-dependencies.js.map +1 -0
  118. package/src/utils/test/python-worker/worker.py +703 -0
  119. package/src/utils/test/warm-python-cache.d.ts +18 -0
  120. package/src/utils/test/warm-python-cache.js +46 -0
  121. package/src/utils/test/warm-python-cache.js.map +1 -0
  122. package/src/utils/versions.d.ts +10 -9
  123. package/src/utils/versions.js +9 -8
  124. package/src/utils/versions.js.map +1 -1
@@ -0,0 +1,28 @@
1
+ """<%- className %> client — AUTO-GENERATED, do not edit."""
2
+
3
+ from . import types as types
4
+ from .errors import ApiError as ApiError
5
+ <%_ if (clientType === 'sync' || clientType === 'both') { _%>
6
+ from .client import <%- className %> as <%- className %>
7
+ from .client import <%- className %>Config as <%- className %>Config
8
+ <%_ } _%>
9
+ <%_ if (clientType === 'async' || clientType === 'both') { _%>
10
+ from .async_client import Async<%- className %> as Async<%- className %>
11
+ from .async_client import Async<%- className %>Config as Async<%- className %>Config
12
+ <%_ } _%>
13
+
14
+ # `ApiError` catches any failure from either client. The per-operation
15
+ # subclasses in `.errors` narrow `.error` to the responses one operation
16
+ # declares — import them from there when you want that.
17
+ __all__ = [
18
+ <%_ if (clientType === 'sync' || clientType === 'both') { _%>
19
+ "<%- className %>",
20
+ "<%- className %>Config",
21
+ <%_ } _%>
22
+ <%_ if (clientType === 'async' || clientType === 'both') { _%>
23
+ "Async<%- className %>",
24
+ "Async<%- className %>Config",
25
+ <%_ } _%>
26
+ "ApiError",
27
+ "types",
28
+ ]
@@ -0,0 +1,37 @@
1
+ <%_ // An operation with no error responses has `Never` as its error type. _%>
2
+ <%_ const hasNeverErrorType = allOperations.some(op => !op.errorShape || op.errorShape.entries.length === 0); _%>
3
+ """Errors raised by <%- className %> — AUTO-GENERATED, do not edit."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any<%- hasNeverErrorType ? ', Never' : '' %>
8
+
9
+ from . import types
10
+
11
+
12
+ class ApiError(Exception):
13
+ """Base class for all API errors.
14
+
15
+ Subclasses are generated per-operation so `error` can be narrowed by the
16
+ type checker via `isinstance` or `match`. Catch `ApiError` to handle any
17
+ status code across operations, from either the sync or the async client.
18
+ """
19
+
20
+ status: int
21
+ error: Any
22
+
23
+ def __init__(self, status: int, error: Any = None) -> None:
24
+ super().__init__(f"API returned status {status}")
25
+ self.status = status
26
+ self.error = error
27
+
28
+ <%_ allOperations.forEach((op) => {
29
+ const shape = op.errorShape;
30
+ _%>
31
+
32
+
33
+ class <%- shape.exceptionClassName %>(ApiError):
34
+ """Raised when `<%- op.operationIdSnakeCase || op.name %>` returns a non-success status."""
35
+
36
+ error: <% if (shape.entries.length === 0) { %>Never<% } else { %>types.<%- shape.unionTypeName %><% } %>
37
+ <%_ }); _%>
@@ -0,0 +1,319 @@
1
+ <%_
2
+ // An operation with no error responses has `Never` as its error type.
3
+ const hasNeverErrorType = allOperations.some(op => !op.errorShape || op.errorShape.entries.length === 0);
4
+ const pyEnumValue = (member) => toPythonLiteral(member.value);
5
+ /**
6
+ * A discriminated subtype's tag property. pydantic dispatches a tagged union
7
+ * on a bare `Literal` field that every member declares, so the tag is emitted
8
+ * as required whether or not the schema lists it in `required`: its value is
9
+ * fixed by union membership, and a missing tag is a request the server always
10
+ * rejects.
11
+ */
12
+ const isDiscriminatorTag = (prop) => !!prop.discriminatorValue;
13
+
14
+ /**
15
+ * Render text from the spec as a Python docstring body. A description is
16
+ * arbitrary text: a backslash would start an escape sequence and a trailing one
17
+ * would escape the closing quotes, so it goes through the same escaping as any
18
+ * other literal, with the surrounding quotes stripped.
19
+ */
20
+ const pyDocstring = (text) =>
21
+ toPythonLiteral(String(text ?? '').replace(/\r?\n/g, ' ')).slice(1, -1);
22
+
23
+ /** A model's docstring text, noting deprecation where the spec declares it. */
24
+ const modelDocstring = (model) =>
25
+ pyDocstring(model.description || '') + (model.deprecated ? ' (deprecated)' : '');
26
+
27
+ /**
28
+ * A docstring, indented and wrapped to the vended line length so a long
29
+ * description doesn't trip the `E501` the generated project lints with. Returns
30
+ * the empty string when there is nothing to say.
31
+ */
32
+ const docstring = (text, indent) => {
33
+ const body = String(text ?? '');
34
+ if (!body) return '';
35
+ const oneLine = `${indent}"""${body}"""`;
36
+ if (oneLine.length <= 120) return `${oneLine}\n`;
37
+ const width = 120 - indent.length;
38
+ const lines = [];
39
+ let current = '';
40
+ for (const word of body.split(' ')) {
41
+ if (current && `${current} ${word}`.length > width) {
42
+ lines.push(current);
43
+ current = word;
44
+ } else {
45
+ current = current ? `${current} ${word}` : word;
46
+ }
47
+ }
48
+ if (current) lines.push(current);
49
+ return `${indent}"""\n${lines.map((l) => `${indent}${l}`).join('\n')}\n${indent}"""\n`;
50
+ };
51
+
52
+ /** A model's docstring, wrapped as above. */
53
+ const docstringBlock = (model, indent) =>
54
+ model.description || model.deprecated
55
+ ? docstring(modelDocstring(model), indent)
56
+ : '';
57
+
58
+ const fieldAnnotation = (prop) => {
59
+ let base;
60
+ if (prop.isEnum && Array.isArray(prop.enum) && prop.enum.length > 0) {
61
+ base = `Literal[${prop.enum.map(pyEnumValue).join(', ')}]`;
62
+ } else {
63
+ base = prop.pythonType || 'Any';
64
+ }
65
+ if (isDiscriminatorTag(prop)) return base;
66
+ if (!prop.isRequired || prop.isNullable) return `${base} | None`;
67
+ return base;
68
+ };
69
+
70
+ /**
71
+ * Render a pydantic `Field(...)` call for a model property — alias, default,
72
+ * description, deprecated, frozen. Returns null when no Field(...) is needed
73
+ * so the template can emit a bare `name: T` or `name: T = None`.
74
+ */
75
+ const fieldCallFor = (property) => {
76
+ const snake = property.pythonName || property.name;
77
+ const aliasNeeded = snake !== property.name;
78
+ const args = [];
79
+ const needsDefault = !isDiscriminatorTag(property) && !property.isRequired;
80
+ if (needsDefault) args.push('default=None');
81
+ if (aliasNeeded) args.push(`alias=${toPythonLiteral(property.name)}`);
82
+ if (property.description) {
83
+ args.push(`description=${toPythonLiteral(property.description.replace(/\r?\n/g, ' '))}`);
84
+ }
85
+ if (property.isReadOnly) args.push('frozen=True');
86
+ if (property.deprecated) args.push('deprecated=True');
87
+ // Only emit Field(...) if something beyond a bare type annotation is needed.
88
+ if (args.length === 0) return null;
89
+ // If the only argument is default=None and there is no alias/desc/frozen/deprecated,
90
+ // prefer the shorter `= None` form.
91
+ if (args.length === 1 && args[0] === 'default=None') return null;
92
+ return `Field(${args.join(', ')})`;
93
+ };
94
+
95
+ const renderProperty = (property) => {
96
+ const snake = property.pythonName || property.name;
97
+ const typeAnnotation = fieldAnnotation(property);
98
+ const fieldCall = fieldCallFor(property);
99
+ const needsDefault = !isDiscriminatorTag(property) && !property.isRequired;
100
+ if (fieldCall) {
101
+ return ` ${snake}: ${typeAnnotation} = ${fieldCall}`;
102
+ }
103
+ if (needsDefault) {
104
+ return ` ${snake}: ${typeAnnotation} = None`;
105
+ }
106
+ return ` ${snake}: ${typeAnnotation}`;
107
+ };
108
+ _%>
109
+ """Types for <%- className %> — AUTO-GENERATED, do not edit."""
110
+
111
+ from __future__ import annotations
112
+
113
+ import datetime
114
+ from typing import Annotated, Any, Literal<%- hasNeverErrorType ? ', Never' : '' %>, TypedDict
115
+
116
+ from pydantic import BaseModel, ConfigDict, Field
117
+
118
+ <%_
119
+ /**
120
+ * Classify a model by how it's rendered in the module.
121
+ *
122
+ * `class` models emit as `class Foo(BaseModel)` and are self-contained — they
123
+ * reference other types only via forward-ref-quoted annotations that pydantic
124
+ * resolves lazily.
125
+ *
126
+ * `alias` models emit as `Foo = A | B / Literal[...] / list[...] / ...`.
127
+ * These are module-level expressions evaluated at import time, so every
128
+ * type they reference must already be defined. Emit them *after* all class
129
+ * definitions so `TypeAdapter(Foo)` can resolve references without relying
130
+ * on forward-ref strings.
131
+ */
132
+ const classifyModel = (model) => {
133
+ if (model.isInlinedByAllOf) return 'skip';
134
+ if (model.export === 'enum') return 'alias';
135
+ if (model.export === 'one-of' || model.export === 'any-of') return 'alias';
136
+ // An object with no properties and no `additionalProperties` parses as a
137
+ // dictionary whose value type is the model itself, which would render as the
138
+ // self-referential `X = dict[str, X]`. It carries no value type at all, so it
139
+ // is emitted as an empty class — which is what the schema describes.
140
+ if (model.export === 'dictionary') {
141
+ const isEmptyObject =
142
+ !model.link &&
143
+ !model.hasAdditionalProperties &&
144
+ !model.hasPatternProperties &&
145
+ model.type === model.name;
146
+ return isEmptyObject ? 'class' : 'alias';
147
+ }
148
+ if (model.export === 'array') return 'alias';
149
+ if (model.export === 'tuple') return 'alias';
150
+ // `all-of` is rendered as a `BaseModel` subclass with flattened fields.
151
+ return 'class';
152
+ };
153
+ _%>
154
+
155
+ <%_ /* ────── Pass 1: all class definitions ────── */ _%>
156
+ <%_ models.forEach((model) => {
157
+ if (classifyModel(model) !== 'class') return;
158
+ _%>
159
+ <%_ if (model.export === 'all-of') {
160
+ // `effectiveProperties` is the shared flattening of the composition,
161
+ // recursing through members that are themselves allOf composites.
162
+ const flattened = model.effectiveProperties || [];
163
+ _%>
164
+
165
+ class <%- model.pythonClassName %>(BaseModel):
166
+ <%- docstringBlock(model, ' ') %> model_config = ConfigDict(populate_by_name=True, extra="allow")
167
+
168
+ <%_ if (flattened.length === 0) { _%>
169
+ pass
170
+ <%_ } _%>
171
+ <%_ flattened.forEach((property) => { _%>
172
+ <%- renderProperty(property) %>
173
+ <%_ }); _%>
174
+ <%_ } else { _%>
175
+
176
+ class <%- model.pythonClassName %>(BaseModel):
177
+ <%- docstringBlock(model, ' ') %> model_config = ConfigDict(populate_by_name=True, extra="allow")
178
+
179
+ <%_ if ((model.properties || []).length === 0 && !model.hasAdditionalProperties) { _%>
180
+ pass
181
+ <%_ } _%>
182
+ <%_ (model.properties || []).forEach((property) => { _%>
183
+ <%- renderProperty(property) %>
184
+ <%_ }); _%>
185
+ <%_ } _%>
186
+ <%_ }); _%>
187
+
188
+ <%_
189
+ /* ────── Pass 2: all non-class aliases ──────
190
+ * An alias is a module-level expression evaluated at import time, so unlike a
191
+ * class-body annotation (which `from __future__ import annotations` defers)
192
+ * every alias it references must already be bound. Emit them in dependency
193
+ * order via a topological sort: an alias that names another alias follows it.
194
+ * Classes are all defined above, so only alias-to-alias edges matter.
195
+ */
196
+ const aliasModels = models.filter((m) => classifyModel(m) === 'alias');
197
+ const aliasByClassName = new Map(aliasModels.map((m) => [m.pythonClassName, m]));
198
+ /** The aliases the given alias's rendered type expression names. */
199
+ const aliasDependencies = (model) => {
200
+ const rendered = model.export === 'enum'
201
+ ? ''
202
+ : [model.pythonType || '', ...(model.properties || []).map((p) => p.pythonType || '')].join(' ');
203
+ const found = new Set();
204
+ for (const identifier of rendered.match(/[A-Za-z_][A-Za-z0-9_]*/g) || []) {
205
+ const dependency = aliasByClassName.get(identifier);
206
+ if (dependency && dependency !== model) found.add(dependency);
207
+ }
208
+ return found;
209
+ };
210
+ const sortedAliasModels = [];
211
+ const aliasState = new Map();
212
+ const visitAlias = (model) => {
213
+ // 'visiting' marks a cycle: emit it where first reached and let the reference
214
+ // that closed the loop resolve against the earlier binding.
215
+ if (aliasState.get(model)) return;
216
+ aliasState.set(model, 'visiting');
217
+ for (const dependency of aliasDependencies(model)) {
218
+ visitAlias(dependency);
219
+ }
220
+ aliasState.set(model, 'done');
221
+ sortedAliasModels.push(model);
222
+ };
223
+ aliasModels
224
+ .slice()
225
+ .sort((a, b) => a.name.localeCompare(b.name))
226
+ .forEach(visitAlias);
227
+ _%>
228
+ <%_ sortedAliasModels.forEach((model) => { _%>
229
+
230
+ <%_ if (model.export === 'enum') { _%>
231
+ <%- model.pythonClassName %> = Literal[<%_ model.enum.forEach((m, i) => { _%><%- i > 0 ? ', ' : '' %><%- pyEnumValue(m) %><%_ }); _%>]
232
+ <%- docstringBlock(model, '') %><%_ } else if (model.export === 'one-of' || model.export === 'any-of') { _%>
233
+ <%_ /* Classes are already defined above, so references can be unquoted —
234
+ which matters here, since pydantic's `TypeAdapter(X)` resolves an alias
235
+ at runtime and cannot see through a string forward-ref. */ _%>
236
+ <%_ /* A discriminated union renders as a pydantic tagged union so parsing
237
+ dispatches directly to the matching branch (never merging branches).
238
+ Requires every member to carry the discriminator as a Literal-typed
239
+ field; otherwise fall back to a plain union. */ _%>
240
+ <%_ /* pydantic requires the tag to be a bare Literal field on every member,
241
+ else TypeAdapter construction fails at import time. `renderProperty`
242
+ emits a tag that way whether or not the schema requires it. */
243
+ const memberModels = (model.composedModels || []);
244
+ const isTagged = model.discriminator && memberModels.length > 0
245
+ && memberModels.length === model.properties.filter(p => !p.isPrimitive).length
246
+ && (model.composedPrimitives || []).length === 0
247
+ && memberModels.every(m => (m.properties || []).some(p =>
248
+ p.name === model.discriminator.propertyName && p.discriminatorValue)); _%>
249
+ <%_ if (isTagged) { _%>
250
+ <%- model.pythonClassName %> = Annotated[<%_ model.properties.forEach((p, i) => { _%><%- i > 0 ? ' | ' : '' %><%- p.pythonType || 'Any' %><%_ }); _%>, Field(discriminator="<%- model.discriminator.pythonPropertyName %>")]
251
+ <%_ } else { _%>
252
+ <%- model.pythonClassName %> = <% model.properties.forEach((p, i) => { %><%- i > 0 ? ' | ' : '' %><%- p.pythonType || 'Any' %><% }); %>
253
+ <%_ } _%>
254
+ <%- docstringBlock(model, '') %><%_ } else if (model.export === 'dictionary' || model.export === 'array' || model.export === 'tuple') { _%>
255
+ <%- model.pythonClassName %> = <%- model.pythonType %>
256
+ <%- docstringBlock(model, '') %><%_ } _%>
257
+ <%_ }); _%>
258
+ <%_ // ────── Per-operation request TypedDicts ────── _%>
259
+ <%_ allOperations.forEach((op) => { _%>
260
+ <%_ if (op.parameters && op.parameters.length > 0) { _%>
261
+ <%_ const required = op.parameters.filter(p => p.isRequired); _%>
262
+ <%_ const optional = op.parameters.filter(p => !p.isRequired); _%>
263
+ <%_ if (required.length > 0 && optional.length === 0) { _%>
264
+
265
+ class <%- op.pythonRequestTypeName %>(TypedDict):
266
+ <%- docstring(pyDocstring(op.description || op.summary), ' ') %><%_ op.parameters.forEach((p) => { _%>
267
+ <%- p.pythonName %>: <%- p.pythonType || 'Any' %>
268
+ <%_ }); _%>
269
+ <%_ } else if (required.length === 0) { _%>
270
+
271
+ class <%- op.pythonRequestTypeName %>(TypedDict, total=False):
272
+ <%- docstring(pyDocstring(op.description || op.summary), ' ') %><%_ op.parameters.forEach((p) => { _%>
273
+ <%- p.pythonName %>: <%- p.pythonType || 'Any' %>
274
+ <%_ }); _%>
275
+ <%_ } else { _%>
276
+
277
+ class <%- op.pythonRequestTypeName %>Required(TypedDict):
278
+ <%_ required.forEach((p) => { _%>
279
+ <%- p.pythonName %>: <%- p.pythonType || 'Any' %>
280
+ <%_ }); _%>
281
+
282
+
283
+ class <%- op.pythonRequestTypeName %>(<%- op.pythonRequestTypeName %>Required, total=False):
284
+ <%- docstring(pyDocstring(op.description || op.summary), ' ') %><%_ optional.forEach((p) => { _%>
285
+ <%- p.pythonName %>: <%- p.pythonType || 'Any' %>
286
+ <%_ }); _%>
287
+ <%_ } _%>
288
+ <%_ } _%>
289
+ <%_ }); _%>
290
+ <%_ // ────── Per-operation error taxonomy ────── _%>
291
+ <%_ allOperations.forEach((op) => {
292
+ const shape = op.errorShape;
293
+ if (!shape || shape.entries.length === 0) {
294
+ _%>
295
+
296
+ <%- shape.unionTypeName %> = Never
297
+ <%_
298
+ } else {
299
+ _%>
300
+ <%_ shape.entries.forEach((entry) => {
301
+ // Inside types.py the error type is defined locally; strip the client
302
+ // module's `types.` prefix the response model's pythonClientType carries.
303
+ const payloadType = entry.responseModel.type === 'void'
304
+ ? 'None'
305
+ : (entry.responseModel.pythonClientType || 'Any').replace(/\btypes\./g, '');
306
+ _%>
307
+
308
+ class <%- entry.className %>(BaseModel):
309
+ """Error wrapper for <%- op.operationIdPascalCase %> status <%- entry.code %>."""
310
+
311
+ model_config = ConfigDict(populate_by_name=True, extra="allow")
312
+
313
+ status: <%- entry.statusAnnotation %>
314
+ error: <%- payloadType %>
315
+ <%_ }); _%>
316
+
317
+ <%- shape.unionTypeName %> = <% shape.entries.forEach((e, i) => { %><%- i > 0 ? ' | ' : '' %><%- e.className %><% }); %>
318
+ <%_ } _%>
319
+ <%_ }); _%>
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { type Tree } from '@nx/devkit';
6
+ import { type NxGeneratorInfo } from '../../utils/nx.js';
7
+ import { type CodeGenData } from '../utils/codegen-data/types.js';
8
+ import type { OpenApiPyClientGeneratorSchema } from './schema.js';
9
+ export declare const OPEN_API_PY_CLIENT_GENERATOR_INFO: NxGeneratorInfo;
10
+ /**
11
+ * Python packages a generated client imports at runtime. A generator that
12
+ * emits a client into a project spreads these into its own declaration and
13
+ * adds them to that project's pyproject.
14
+ */
15
+ export declare const OPEN_API_PY_CLIENT_DEPENDENCIES: import("../../utils/declared-dependencies.js").DependencyDeclaration<readonly import("../../utils/declared-dependencies.js").DeclaredTsDependency<"@ag-ui/client" | "@ag-ui/core" | "@ag-ui/encoder" | "@biomejs/biome" | "@a2a-js/sdk" | "@aws/aws-distro-opentelemetry-node-autoinstrumentation" | "@opentelemetry/propagator-jaeger" | "minimatch" | "deepmerge-ts" | "mysql2" | "@aws-sdk/client-dynamodb" | "@aws-sdk/client-api-gateway" | "@aws-sdk/client-iam" | "@aws-sdk/client-bedrock-agentcore" | "@aws-sdk/client-bedrock-runtime" | "@aws-sdk/client-s3" | "@aws-sdk/client-sts" | "@aws-sdk/client-cognito-identity-provider" | "@aws-sdk/credential-providers" | "@aws-sdk/credential-provider-cognito-identity" | "@aws-sdk/client-secrets-manager" | "@aws-sdk/rds-signer" | "@smithy/server-apigateway" | "@smithy/server-node" | "@aws-lambda-powertools/logger" | "@aws-lambda-powertools/metrics" | "@aws-lambda-powertools/parameters" | "@aws-lambda-powertools/tracer" | "@aws-lambda-powertools/parser" | "@aws-sdk/client-appconfigdata" | "@middy/core" | "@nxlv/python" | "@nx-extend/terraform" | "nx" | "@nx/devkit" | "@nx/js" | "@nx/react" | "@nx/vite" | "@nx/vitest" | "@nx/workspace" | "create-nx-workspace" | "@swc-node/register" | "@swc/core" | "@modelcontextprotocol/sdk" | "@modelcontextprotocol/inspector" | "@ag-ui/a2ui-toolkit" | "@ag-ui/aws-strands" | "agent-chat-cli" | "@copilotkit/react-core" | "rxjs" | "@strands-agents/sdk" | "@tanstack/react-router" | "@tanstack/router-plugin" | "@tanstack/router-generator" | "@tanstack/virtual-file-routes" | "@tanstack/router-utils" | "@cloudscape-design/board-components" | "@cloudscape-design/chat-components" | "@cloudscape-design/components" | "@cloudscape-design/global-styles" | "@tanstack/react-query" | "@tanstack/react-query-devtools" | "@trpc/tanstack-react-query" | "@trpc/client" | "@trpc/server" | "@types/node" | "@types/aws-lambda" | "@types/cors" | "@types/pg" | "@types/ws" | "@types/express" | "@smithy/config-resolver" | "@smithy/node-config-provider" | "@smithy/node-http-handler" | "@smithy/types" | "@vitest/coverage-v8" | "@vitest/ui" | "@astrojs/react" | "@astrojs/starlight" | "astro" | "cookie" | "aws4fetch" | "aws-cdk" | "aws-cdk-lib" | "aws-xray-sdk-core" | "constructs" | "cors" | "chalk" | "class-variance-authority" | "cn" | "commander" | "electrodb" | "esbuild" | "event-source-polyfill" | "@types/event-source-polyfill" | "@prisma/adapter-mariadb" | "@prisma/adapter-pg" | "@prisma/client" | "ejs" | "@types/ejs" | "express" | "fast-glob" | "husky" | "fs-extra" | "@types/fs-extra" | "mariadb" | "mise" | "npm" | "npm-check-updates" | "oidc-client-ts" | "pg" | "prisma" | "react-oidc-context" | "react" | "react-dom" | "rolldown" | "rolldown-plugin-dts" | "shx" | "simple-git" | "source-map-support" | "starlight-blog" | "tailwindcss" | "@tailwindcss/vite" | "tsx" | "lucide-react" | "radix-ui" | "shadcn" | "tw-animate-css" | "vite" | "typescript" | "vitest" | "jsdom" | "zod" | "ws", Record<string, never>>[], readonly [{
16
+ readonly name: "httpx";
17
+ }, {
18
+ readonly name: "pydantic";
19
+ }]>;
20
+ /**
21
+ * Generate a Python httpx-based client from an OpenAPI spec.
22
+ *
23
+ * Emits:
24
+ * - types.py — pydantic v2 models + per-op error classes and TypedDicts
25
+ * - client.py — sync client (httpx.Client) when clientType includes 'sync'
26
+ * - async_client.py — async client (httpx.AsyncClient) when clientType includes 'async'
27
+ *
28
+ * The shape mirrors `open-api#ts-client`, but the two decide a few things
29
+ * separately rather than through shared code: this generator reads the neutral
30
+ * `requestShape` from `codegen-data`, while the TypeScript templates still
31
+ * compute inlining themselves. Where they differ today, for the same spec:
32
+ *
33
+ * - A discriminated object body: TypeScript inlines its fields, Python passes
34
+ * the body whole so marshalling can dispatch on the discriminator.
35
+ * - A body carrying `additionalProperties`, a union, or `patternProperties`, or
36
+ * a body property literally named `body`: TypeScript wraps, Python flattens.
37
+ * - An optional (`required: false`) object body: Python flattens its required
38
+ * fields into required keyword arguments, so the body is always sent.
39
+ * - A primitive `application/json` body: TypeScript sends the raw text, Python
40
+ * sends it JSON-encoded.
41
+ * - The media type chosen for a body offering several: TypeScript prefers any
42
+ * `+json` type, Python only an exact `application/json`.
43
+ *
44
+ * Migrating the TypeScript templates onto `requestShape` would collapse these
45
+ * into one decision; until then they are differences of behaviour, not of
46
+ * correctness, and are covered by this generator's own tests.
47
+ */
48
+ export declare const openApiPyClientGenerator: (tree: Tree, options: OpenApiPyClientGeneratorSchema) => Promise<void>;
49
+ /**
50
+ * Generate an OpenAPI Python client in the target directory
51
+ */
52
+ export declare const generateOpenApiPyClient: (tree: Tree, data: CodeGenData, outputPath: string, clientType?: "sync" | "async" | "both") => void;
53
+ export default openApiPyClientGenerator;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import { generateFiles } from "@nx/devkit";
5
+ import * as path from "path";
6
+ import { declareDependencies } from "../../utils/declared-dependencies.js";
7
+ import { formatFilesInSubtree } from "../../utils/format.js";
8
+ import { updateGitIgnore } from "../../utils/git.js";
9
+ import { addGeneratorMetricsIfApplicable } from "../../utils/metrics.js";
10
+ import { getGeneratorInfo } from "../../utils/nx.js";
11
+ import { buildOpenApiCodeGenerationData } from "../ts-client/generator.js";
12
+ import { toPythonClassName, toPythonLiteral } from "../utils/codegen-data/languages.js";
13
+ import { isPythonCollection, needsPythonTypeAdapter } from "../utils/codegen-data/types.js";
14
+ import { annotatePythonData, assertNoClashingPythonNames } from "../utils/codegen-data.js";
15
+ export const OPEN_API_PY_CLIENT_GENERATOR_INFO = getGeneratorInfo(import.meta.filename);
16
+ /**
17
+ * Python packages a generated client imports at runtime. A generator that
18
+ * emits a client into a project spreads these into its own declaration and
19
+ * adds them to that project's pyproject.
20
+ */ export const OPEN_API_PY_CLIENT_DEPENDENCIES = declareDependencies()({
21
+ py: [
22
+ {
23
+ name: 'httpx'
24
+ },
25
+ {
26
+ name: 'pydantic'
27
+ }
28
+ ]
29
+ });
30
+ /**
31
+ * Generate a Python httpx-based client from an OpenAPI spec.
32
+ *
33
+ * Emits:
34
+ * - types.py — pydantic v2 models + per-op error classes and TypedDicts
35
+ * - client.py — sync client (httpx.Client) when clientType includes 'sync'
36
+ * - async_client.py — async client (httpx.AsyncClient) when clientType includes 'async'
37
+ *
38
+ * The shape mirrors `open-api#ts-client`, but the two decide a few things
39
+ * separately rather than through shared code: this generator reads the neutral
40
+ * `requestShape` from `codegen-data`, while the TypeScript templates still
41
+ * compute inlining themselves. Where they differ today, for the same spec:
42
+ *
43
+ * - A discriminated object body: TypeScript inlines its fields, Python passes
44
+ * the body whole so marshalling can dispatch on the discriminator.
45
+ * - A body carrying `additionalProperties`, a union, or `patternProperties`, or
46
+ * a body property literally named `body`: TypeScript wraps, Python flattens.
47
+ * - An optional (`required: false`) object body: Python flattens its required
48
+ * fields into required keyword arguments, so the body is always sent.
49
+ * - A primitive `application/json` body: TypeScript sends the raw text, Python
50
+ * sends it JSON-encoded.
51
+ * - The media type chosen for a body offering several: TypeScript prefers any
52
+ * `+json` type, Python only an exact `application/json`.
53
+ *
54
+ * Migrating the TypeScript templates onto `requestShape` would collapse these
55
+ * into one decision; until then they are differences of behaviour, not of
56
+ * correctness, and are covered by this generator's own tests.
57
+ */ export const openApiPyClientGenerator = async (tree, options)=>{
58
+ const data = await buildOpenApiCodeGenerationData(tree, options.openApiSpecPath);
59
+ const clientType = options.clientType ?? 'both';
60
+ // Derived here rather than in the shared pipeline, so a TypeScript consumer of
61
+ // the same spec pays for neither these fields nor a Python-specific name clash.
62
+ annotatePythonData(data);
63
+ for (const model of data.models){
64
+ assertNoClashingPythonNames(model);
65
+ }
66
+ generateOpenApiPyClient(tree, data, options.outputPath, clientType);
67
+ // The client is regenerated from the spec, so it is ignored by default.
68
+ // Remove the entry to check it in instead.
69
+ updateGitIgnore(tree, '.', (patterns)=>[
70
+ ...patterns,
71
+ options.outputPath
72
+ ]);
73
+ await addGeneratorMetricsIfApplicable(tree, [
74
+ OPEN_API_PY_CLIENT_GENERATOR_INFO
75
+ ]);
76
+ await formatFilesInSubtree(tree);
77
+ };
78
+ /**
79
+ * Generate an OpenAPI Python client in the target directory
80
+ */ export const generateOpenApiPyClient = (tree, data, outputPath, clientType = 'both')=>{
81
+ // `toPythonLiteral` is shared with the type renderer so a value is escaped
82
+ // the same way wherever a template spells it out. The type predicates let a
83
+ // template ask what a Python type is, rather than matching its spelling.
84
+ const base = {
85
+ ...data,
86
+ // The shared `className` comes from the spec title via `toClassName`, which
87
+ // is a valid TypeScript name but not always a Python one: a title with no
88
+ // alphanumerics renders nothing (`class :`) and one spelt `None` renders a
89
+ // keyword. It also has to clear the names these modules export themselves,
90
+ // so a title of `ApiError` cannot shadow the base exception.
91
+ className: toPythonClassName(data.className),
92
+ clientType,
93
+ toPythonLiteral,
94
+ isPythonCollection,
95
+ needsPythonTypeAdapter
96
+ };
97
+ generateFiles(tree, path.join(import.meta.dirname, 'files', 'shared'), outputPath, base);
98
+ // Both clients render from one template: they differ only in how they await,
99
+ // and keeping two copies is how a fix lands in one and not the other.
100
+ // `clientModuleName` names the emitted file, `isAsync` selects the keywords.
101
+ const clientDir = path.join(import.meta.dirname, 'files', 'client');
102
+ if (clientType === 'sync' || clientType === 'both') {
103
+ generateFiles(tree, clientDir, outputPath, {
104
+ ...base,
105
+ isAsync: false,
106
+ clientModuleName: 'client'
107
+ });
108
+ }
109
+ if (clientType === 'async' || clientType === 'both') {
110
+ generateFiles(tree, clientDir, outputPath, {
111
+ ...base,
112
+ isAsync: true,
113
+ clientModuleName: 'async_client'
114
+ });
115
+ }
116
+ };
117
+ export default openApiPyClientGenerator;
118
+
119
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/py-client/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { generateFiles, type Tree } from '@nx/devkit';\nimport * as path from 'path';\nimport { declareDependencies } from '../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { updateGitIgnore } from '../../utils/git.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { getGeneratorInfo, type NxGeneratorInfo } from '../../utils/nx.js';\nimport { buildOpenApiCodeGenerationData } from '../ts-client/generator.js';\nimport {\n toPythonClassName,\n toPythonLiteral,\n} from '../utils/codegen-data/languages.js';\nimport {\n type CodeGenData,\n isPythonCollection,\n needsPythonTypeAdapter,\n} from '../utils/codegen-data/types.js';\nimport {\n annotatePythonData,\n assertNoClashingPythonNames,\n} from '../utils/codegen-data.js';\nimport type { OpenApiPyClientGeneratorSchema } from './schema.js';\n\nexport const OPEN_API_PY_CLIENT_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\n/**\n * Python packages a generated client imports at runtime. A generator that\n * emits a client into a project spreads these into its own declaration and\n * adds them to that project's pyproject.\n */\nexport const OPEN_API_PY_CLIENT_DEPENDENCIES = declareDependencies()({\n py: [{ name: 'httpx' }, { name: 'pydantic' }],\n});\n\n/**\n * Generate a Python httpx-based client from an OpenAPI spec.\n *\n * Emits:\n * - types.py — pydantic v2 models + per-op error classes and TypedDicts\n * - client.py — sync client (httpx.Client) when clientType includes 'sync'\n * - async_client.py — async client (httpx.AsyncClient) when clientType includes 'async'\n *\n * The shape mirrors `open-api#ts-client`, but the two decide a few things\n * separately rather than through shared code: this generator reads the neutral\n * `requestShape` from `codegen-data`, while the TypeScript templates still\n * compute inlining themselves. Where they differ today, for the same spec:\n *\n * - A discriminated object body: TypeScript inlines its fields, Python passes\n * the body whole so marshalling can dispatch on the discriminator.\n * - A body carrying `additionalProperties`, a union, or `patternProperties`, or\n * a body property literally named `body`: TypeScript wraps, Python flattens.\n * - An optional (`required: false`) object body: Python flattens its required\n * fields into required keyword arguments, so the body is always sent.\n * - A primitive `application/json` body: TypeScript sends the raw text, Python\n * sends it JSON-encoded.\n * - The media type chosen for a body offering several: TypeScript prefers any\n * `+json` type, Python only an exact `application/json`.\n *\n * Migrating the TypeScript templates onto `requestShape` would collapse these\n * into one decision; until then they are differences of behaviour, not of\n * correctness, and are covered by this generator's own tests.\n */\nexport const openApiPyClientGenerator = async (\n tree: Tree,\n options: OpenApiPyClientGeneratorSchema,\n) => {\n const data = await buildOpenApiCodeGenerationData(\n tree,\n options.openApiSpecPath,\n );\n const clientType = options.clientType ?? 'both';\n\n // Derived here rather than in the shared pipeline, so a TypeScript consumer of\n // the same spec pays for neither these fields nor a Python-specific name clash.\n annotatePythonData(data);\n\n for (const model of data.models) {\n assertNoClashingPythonNames(model);\n }\n\n generateOpenApiPyClient(tree, data, options.outputPath, clientType);\n\n // The client is regenerated from the spec, so it is ignored by default.\n // Remove the entry to check it in instead.\n updateGitIgnore(tree, '.', (patterns) => [...patterns, options.outputPath]);\n\n await addGeneratorMetricsIfApplicable(tree, [\n OPEN_API_PY_CLIENT_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n};\n\n/**\n * Generate an OpenAPI Python client in the target directory\n */\nexport const generateOpenApiPyClient = (\n tree: Tree,\n data: CodeGenData,\n outputPath: string,\n clientType: 'sync' | 'async' | 'both' = 'both',\n) => {\n // `toPythonLiteral` is shared with the type renderer so a value is escaped\n // the same way wherever a template spells it out. The type predicates let a\n // template ask what a Python type is, rather than matching its spelling.\n const base = {\n ...data,\n // The shared `className` comes from the spec title via `toClassName`, which\n // is a valid TypeScript name but not always a Python one: a title with no\n // alphanumerics renders nothing (`class :`) and one spelt `None` renders a\n // keyword. It also has to clear the names these modules export themselves,\n // so a title of `ApiError` cannot shadow the base exception.\n className: toPythonClassName(data.className),\n clientType,\n toPythonLiteral,\n isPythonCollection,\n needsPythonTypeAdapter,\n };\n\n generateFiles(\n tree,\n path.join(import.meta.dirname, 'files', 'shared'),\n outputPath,\n base,\n );\n\n // Both clients render from one template: they differ only in how they await,\n // and keeping two copies is how a fix lands in one and not the other.\n // `clientModuleName` names the emitted file, `isAsync` selects the keywords.\n const clientDir = path.join(import.meta.dirname, 'files', 'client');\n\n if (clientType === 'sync' || clientType === 'both') {\n generateFiles(tree, clientDir, outputPath, {\n ...base,\n isAsync: false,\n clientModuleName: 'client',\n });\n }\n if (clientType === 'async' || clientType === 'both') {\n generateFiles(tree, clientDir, outputPath, {\n ...base,\n isAsync: true,\n clientModuleName: 'async_client',\n });\n }\n};\n\nexport default openApiPyClientGenerator;\n"],"names":["generateFiles","path","declareDependencies","formatFilesInSubtree","updateGitIgnore","addGeneratorMetricsIfApplicable","getGeneratorInfo","buildOpenApiCodeGenerationData","toPythonClassName","toPythonLiteral","isPythonCollection","needsPythonTypeAdapter","annotatePythonData","assertNoClashingPythonNames","OPEN_API_PY_CLIENT_GENERATOR_INFO","filename","OPEN_API_PY_CLIENT_DEPENDENCIES","py","name","openApiPyClientGenerator","tree","options","data","openApiSpecPath","clientType","model","models","generateOpenApiPyClient","outputPath","patterns","base","className","join","dirname","clientDir","isAsync","clientModuleName"],"mappings":"AAAA;;;CAGC,GACD,SAASA,aAAa,QAAmB,aAAa;AACtD,YAAYC,UAAU,OAAO;AAC7B,SAASC,mBAAmB,QAAQ,uCAAuC;AAC3E,SAASC,oBAAoB,QAAQ,wBAAwB;AAC7D,SAASC,eAAe,QAAQ,qBAAqB;AACrD,SAASC,+BAA+B,QAAQ,yBAAyB;AACzE,SAASC,gBAAgB,QAA8B,oBAAoB;AAC3E,SAASC,8BAA8B,QAAQ,4BAA4B;AAC3E,SACEC,iBAAiB,EACjBC,eAAe,QACV,qCAAqC;AAC5C,SAEEC,kBAAkB,EAClBC,sBAAsB,QACjB,iCAAiC;AACxC,SACEC,kBAAkB,EAClBC,2BAA2B,QACtB,2BAA2B;AAGlC,OAAO,MAAMC,oCACXR,iBAAiB,YAAYS,QAAQ,EAAE;AAEzC;;;;CAIC,GACD,OAAO,MAAMC,kCAAkCd,sBAAsB;IACnEe,IAAI;QAAC;YAAEC,MAAM;QAAQ;QAAG;YAAEA,MAAM;QAAW;KAAE;AAC/C,GAAG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,GACD,OAAO,MAAMC,2BAA2B,OACtCC,MACAC;IAEA,MAAMC,OAAO,MAAMf,+BACjBa,MACAC,QAAQE,eAAe;IAEzB,MAAMC,aAAaH,QAAQG,UAAU,IAAI;IAEzC,+EAA+E;IAC/E,gFAAgF;IAChFZ,mBAAmBU;IAEnB,KAAK,MAAMG,SAASH,KAAKI,MAAM,CAAE;QAC/Bb,4BAA4BY;IAC9B;IAEAE,wBAAwBP,MAAME,MAAMD,QAAQO,UAAU,EAAEJ;IAExD,wEAAwE;IACxE,2CAA2C;IAC3CpB,gBAAgBgB,MAAM,KAAK,CAACS,WAAa;eAAIA;YAAUR,QAAQO,UAAU;SAAC;IAE1E,MAAMvB,gCAAgCe,MAAM;QAC1CN;KACD;IAED,MAAMX,qBAAqBiB;AAC7B,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMO,0BAA0B,CACrCP,MACAE,MACAM,YACAJ,aAAwC,MAAM;IAE9C,2EAA2E;IAC3E,4EAA4E;IAC5E,yEAAyE;IACzE,MAAMM,OAAO;QACX,GAAGR,IAAI;QACP,4EAA4E;QAC5E,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,6DAA6D;QAC7DS,WAAWvB,kBAAkBc,KAAKS,SAAS;QAC3CP;QACAf;QACAC;QACAC;IACF;IAEAX,cACEoB,MACAnB,KAAK+B,IAAI,CAAC,YAAYC,OAAO,EAAE,SAAS,WACxCL,YACAE;IAGF,6EAA6E;IAC7E,sEAAsE;IACtE,6EAA6E;IAC7E,MAAMI,YAAYjC,KAAK+B,IAAI,CAAC,YAAYC,OAAO,EAAE,SAAS;IAE1D,IAAIT,eAAe,UAAUA,eAAe,QAAQ;QAClDxB,cAAcoB,MAAMc,WAAWN,YAAY;YACzC,GAAGE,IAAI;YACPK,SAAS;YACTC,kBAAkB;QACpB;IACF;IACA,IAAIZ,eAAe,WAAWA,eAAe,QAAQ;QACnDxB,cAAcoB,MAAMc,WAAWN,YAAY;YACzC,GAAGE,IAAI;YACPK,SAAS;YACTC,kBAAkB;QACpB;IACF;AACF,EAAE;AAEF,eAAejB,yBAAyB"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ export { };
5
+
6
+ //# sourceMappingURL=schema.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/open-api/py-client/schema.d.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport type OpenApiPyClientClientType = 'sync' | 'async' | 'both';\n\nexport interface OpenApiPyClientGeneratorSchema {\n openApiSpecPath: string;\n outputPath: string;\n clientType?: OpenApiPyClientClientType;\n}\n"],"names":[],"mappings":"AAAA;;;CAGC,GAID,WAIC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ export type OpenApiPyClientClientType = 'sync' | 'async' | 'both';
7
+
8
+ export interface OpenApiPyClientGeneratorSchema {
9
+ openApiSpecPath: string;
10
+ outputPath: string;
11
+ clientType?: OpenApiPyClientClientType;
12
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "OpenApiPyClient",
4
+ "title": "OpenAPI Python Client",
5
+ "description": "Generate a Python httpx client from an OpenAPI specification",
6
+ "type": "object",
7
+ "properties": {
8
+ "openApiSpecPath": {
9
+ "type": "string",
10
+ "description": "Path to the OpenAPI specification relative to the monorepo root",
11
+ "x-priority": "important"
12
+ },
13
+ "outputPath": {
14
+ "type": "string",
15
+ "description": "Path to the directory in which to generate the client relative to the monorepo root",
16
+ "x-priority": "important"
17
+ },
18
+ "clientType": {
19
+ "type": "string",
20
+ "description": "Which clients to emit. 'sync' emits client.py using httpx.Client, 'async' emits async_client.py using httpx.AsyncClient, 'both' emits both.",
21
+ "enum": ["sync", "async", "both"],
22
+ "x-prompt": "Which clients would you like to emit?",
23
+ "default": "both",
24
+ "x-priority": "important"
25
+ }
26
+ },
27
+ "required": ["openApiSpecPath", "outputPath"]
28
+ }