@aws/nx-plugin 0.88.1 → 0.89.0
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-THIRD-PARTY +688 -54
- package/bin/aws-nx-mcp.js +3 -4
- package/bin/aws-nx-mcp.js.map +1 -1
- package/package.json +2 -2
- package/src/connection/generator.js +20 -26
- package/src/connection/generator.js.map +1 -1
- package/src/connection/serve-local.js +7 -9
- package/src/connection/serve-local.js.map +1 -1
- package/src/infra/app/generator.js +152 -143
- package/src/infra/app/generator.js.map +1 -1
- package/src/license/config.js +90 -79
- package/src/license/config.js.map +1 -1
- package/src/license/generator.js +20 -15
- package/src/license/generator.js.map +1 -1
- package/src/license/sync/generator.js +71 -77
- package/src/license/sync/generator.js.map +1 -1
- package/src/license/sync/project-file-sync.js +13 -6
- package/src/license/sync/project-file-sync.js.map +1 -1
- package/src/mcp-server/generator-info.js +28 -34
- package/src/mcp-server/generator-info.js.map +1 -1
- package/src/mcp-server/index.js +3 -4
- package/src/mcp-server/index.js.map +1 -1
- package/src/mcp-server/tools/general-guidance.js +8 -11
- package/src/mcp-server/tools/general-guidance.js.map +1 -1
- package/src/mcp-server/tools/generator-guide.js +3 -4
- package/src/mcp-server/tools/generator-guide.js.map +1 -1
- package/src/open-api/ts-client/generator.js +8 -8
- package/src/open-api/ts-client/generator.js.map +1 -1
- package/src/open-api/ts-hooks/generator.js +4 -4
- package/src/open-api/ts-hooks/generator.js.map +1 -1
- package/src/open-api/ts-metadata/generator.js +4 -4
- package/src/open-api/ts-metadata/generator.js.map +1 -1
- package/src/open-api/utils/codegen-data/languages.js +1 -2
- package/src/open-api/utils/codegen-data/languages.js.map +1 -1
- package/src/open-api/utils/codegen-data.js +90 -92
- package/src/open-api/utils/codegen-data.js.map +1 -1
- package/src/open-api/utils/normalise.js +34 -34
- package/src/open-api/utils/normalise.js.map +1 -1
- package/src/open-api/utils/parse.js +3 -3
- package/src/open-api/utils/parse.js.map +1 -1
- package/src/open-api/utils/refs.js +1 -1
- package/src/open-api/utils/refs.js.map +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +2 -1
- package/src/preset/generator.js +51 -24
- package/src/preset/generator.js.map +1 -1
- package/src/py/fast-api/generator.js +18 -13
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/py/fast-api/react/generator.js +8 -10
- package/src/py/fast-api/react/generator.js.map +1 -1
- package/src/py/fast-api/react/open-api.js +15 -7
- package/src/py/fast-api/react/open-api.js.map +1 -1
- package/src/py/lambda-function/generator.js +18 -16
- package/src/py/lambda-function/generator.js.map +1 -1
- package/src/py/mcp-server/generator.js +36 -24
- package/src/py/mcp-server/generator.js.map +1 -1
- package/src/py/project/generator.js +36 -24
- package/src/py/project/generator.js.map +1 -1
- package/src/py/strands-agent/generator.js +21 -16
- package/src/py/strands-agent/generator.js.map +1 -1
- package/src/py/strands-agent/mcp-connection/generator.js +30 -32
- package/src/py/strands-agent/mcp-connection/generator.js.map +1 -1
- package/src/smithy/project/generator.js +6 -8
- package/src/smithy/project/generator.js.map +1 -1
- package/src/smithy/react-connection/generator.js +14 -17
- package/src/smithy/react-connection/generator.js.map +1 -1
- package/src/smithy/ts/api/generator.js +17 -11
- package/src/smithy/ts/api/generator.js.map +1 -1
- package/src/terraform/project/generator.js +191 -189
- package/src/terraform/project/generator.js.map +1 -1
- package/src/trpc/backend/generator.js +95 -83
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +12 -9
- package/src/trpc/react/files/src/components/__apiNameClassName__ClientProvider.tsx.template +1 -1
- package/src/trpc/react/files/src/hooks/use__apiNameClassName__.tsx.template +3 -3
- package/src/trpc/react/generator.js +75 -76
- package/src/trpc/react/generator.js.map +1 -1
- package/src/ts/lambda-function/generator.js +15 -12
- package/src/ts/lambda-function/generator.js.map +1 -1
- package/src/ts/lib/eslint.js +19 -8
- package/src/ts/lib/eslint.js.map +1 -1
- package/src/ts/lib/generator.js +44 -19
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/lib/ts-project-utils.js +53 -30
- package/src/ts/lib/ts-project-utils.js.map +1 -1
- package/src/ts/lib/vitest.js +13 -3
- package/src/ts/lib/vitest.js.map +1 -1
- package/src/ts/mcp-server/generator.js +22 -17
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/nx-generator/generator.js +40 -22
- package/src/ts/nx-generator/generator.js.map +1 -1
- package/src/ts/nx-plugin/generator.js +14 -11
- package/src/ts/nx-plugin/generator.js.map +1 -1
- package/src/ts/nx-plugin/utils.js +11 -10
- package/src/ts/nx-plugin/utils.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +4 -6
- package/src/ts/react-website/app/generator.js +291 -253
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/ts/react-website/cognito-auth/generator.js +86 -90
- package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
- package/src/ts/react-website/cognito-auth/utils.js +14 -21
- package/src/ts/react-website/cognito-auth/utils.js.map +1 -1
- package/src/ts/react-website/runtime-config/generator.js +35 -34
- package/src/ts/react-website/runtime-config/generator.js.map +1 -1
- package/src/ts/strands-agent/generator.js +18 -13
- package/src/ts/strands-agent/generator.js.map +1 -1
- package/src/ts/strands-agent/mcp-connection/generator.js +15 -17
- package/src/ts/strands-agent/mcp-connection/generator.js.map +1 -1
- package/src/ts/sync/generator.js +36 -14
- package/src/ts/sync/generator.js.map +1 -1
- package/src/utils/agent-connection/agent-connection.js +62 -68
- package/src/utils/agent-connection/agent-connection.js.map +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.js +14 -16
- package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
- package/src/utils/api-constructs/api-constructs.js +8 -10
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/api-constructs/open-api-metadata.js +1 -2
- package/src/utils/api-constructs/open-api-metadata.js.map +1 -1
- package/src/utils/ast/website.js +3 -4
- package/src/utils/ast/website.js.map +1 -1
- package/src/utils/ast.js +20 -23
- package/src/utils/ast.js.map +1 -1
- package/src/utils/bundle/bundle.js +14 -14
- package/src/utils/bundle/bundle.js.map +1 -1
- package/src/utils/config/utils.js +9 -9
- package/src/utils/config/utils.js.map +1 -1
- package/src/utils/connection/open-api/react.js +28 -23
- package/src/utils/connection/open-api/react.js.map +1 -1
- package/src/utils/format.js +50 -47
- package/src/utils/format.js.map +1 -1
- package/src/utils/fs.js +1 -0
- package/src/utils/fs.js.map +1 -1
- package/src/utils/function-constructs/function-constructs.js +16 -12
- package/src/utils/function-constructs/function-constructs.js.map +1 -1
- package/src/utils/git.js +2 -3
- package/src/utils/git.js.map +1 -1
- package/src/utils/iac.js +4 -6
- package/src/utils/iac.js.map +1 -1
- package/src/utils/identity-constructs/identity-constructs.js +6 -7
- package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
- package/src/utils/js.js +7 -8
- package/src/utils/js.js.map +1 -1
- package/src/utils/metrics.js +12 -13
- package/src/utils/metrics.js.map +1 -1
- package/src/utils/mock-project-graph.js +3 -6
- package/src/utils/mock-project-graph.js.map +1 -1
- package/src/utils/names.js +8 -3
- package/src/utils/names.js.map +1 -1
- package/src/utils/npm-scope.js +1 -1
- package/src/utils/npm-scope.js.map +1 -1
- package/src/utils/nx.js +42 -19
- package/src/utils/nx.js.map +1 -1
- package/src/utils/nxlv-python.d.ts +124 -5
- package/src/utils/nxlv-python.js +5 -14
- package/src/utils/nxlv-python.js.map +1 -1
- package/src/utils/pkg-manager.js +1 -1
- package/src/utils/pkg-manager.js.map +1 -1
- package/src/utils/port.js +4 -6
- package/src/utils/port.js.map +1 -1
- package/src/utils/py.js +12 -12
- package/src/utils/py.js.map +1 -1
- package/src/utils/shared-constructs.js +67 -72
- package/src/utils/shared-constructs.js.map +1 -1
- package/src/utils/shared-infra-config.js +24 -26
- package/src/utils/shared-infra-config.js.map +1 -1
- package/src/utils/shared-scripts.js +24 -26
- package/src/utils/shared-scripts.js.map +1 -1
- package/src/utils/shared-shadcn.js +64 -53
- package/src/utils/shared-shadcn.js.map +1 -1
- package/src/utils/versions.d.ts +5 -1
- package/src/utils/versions.js +8 -4
- package/src/utils/versions.js.map +1 -1
- package/src/utils/website-constructs/website-constructs.js +9 -11
- package/src/utils/website-constructs/website-constructs.js.map +1 -1
|
@@ -19,12 +19,11 @@ const types_1 = require("./codegen-data/types");
|
|
|
19
19
|
/**
|
|
20
20
|
* Builds a data structure from an OpenAPI spec which can be used to generate code
|
|
21
21
|
*/
|
|
22
|
-
const buildOpenApiCodeGenData = (inSpec) =>
|
|
23
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
22
|
+
const buildOpenApiCodeGenData = async (inSpec) => {
|
|
24
23
|
// Ensure spec is ready for codegen
|
|
25
24
|
const spec = (0, normalise_1.normaliseOpenApiSpecForCodeGen)(inSpec);
|
|
26
25
|
// Build the initial data, which we will augment with additional information
|
|
27
|
-
const data =
|
|
26
|
+
const data = await buildInitialCodeGenData(spec);
|
|
28
27
|
// Ensure the models have their links set when they are arrays/dictionaries
|
|
29
28
|
ensureModelLinks(spec, data);
|
|
30
29
|
// Mutate the models with enough data to render composite models in the templates
|
|
@@ -37,8 +36,8 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
37
36
|
const responseModelImports = [];
|
|
38
37
|
for (const op of service.operations) {
|
|
39
38
|
// Extract the operation back from the openapi spec
|
|
40
|
-
const specOp =
|
|
41
|
-
op.name =
|
|
39
|
+
const specOp = spec?.paths?.[op.path]?.[op.method.toLowerCase()];
|
|
40
|
+
op.name = op.id ?? op.name;
|
|
42
41
|
op.uniqueName = op.name;
|
|
43
42
|
if (specOp['x-aws-nx-deduplicated-op-id']) {
|
|
44
43
|
op.uniqueName = specOp['x-aws-nx-deduplicated-op-id'];
|
|
@@ -47,8 +46,8 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
47
46
|
op.dotNotationName = specOp['x-aws-nx-deduplicated-dot-op-id'];
|
|
48
47
|
}
|
|
49
48
|
// Add vendor extensions
|
|
50
|
-
op.vendorExtensions =
|
|
51
|
-
copyVendorExtensions(specOp
|
|
49
|
+
op.vendorExtensions = op.vendorExtensions ?? {};
|
|
50
|
+
copyVendorExtensions(specOp ?? {}, op.vendorExtensions);
|
|
52
51
|
if (specOp) {
|
|
53
52
|
// Add all response models to the response model imports
|
|
54
53
|
responseModelImports.push(...op.responses
|
|
@@ -58,7 +57,7 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
58
57
|
// Validate that the response is not a composite schema of primitives since we cannot determine what
|
|
59
58
|
// the type of the response is (it all comes back as text!)
|
|
60
59
|
if (response.export === 'reference' &&
|
|
61
|
-
types_1.COMPOSED_SCHEMA_TYPES.has(
|
|
60
|
+
types_1.COMPOSED_SCHEMA_TYPES.has(modelsByName[response.type]?.export)) {
|
|
62
61
|
const composedPrimitives = modelsByName[response.type].composedPrimitives.filter((p) => !['array', 'dictionary'].includes(p.export));
|
|
63
62
|
if (composedPrimitives.length > 0) {
|
|
64
63
|
throw new Error(`Operation "${op.method} ${op.path}" returns a composite schema of primitives with ${(0, lodash_camelcase_1.default)(modelsByName[response.type].export)}, which cannot be distinguished at runtime`);
|
|
@@ -80,23 +79,24 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
80
79
|
const mediaTypes = Object.keys(specResponse.content);
|
|
81
80
|
response.mediaTypes = mediaTypes;
|
|
82
81
|
for (const mediaType of mediaTypes) {
|
|
83
|
-
const responseContent =
|
|
82
|
+
const responseContent = specResponse.content?.[mediaType] ??
|
|
83
|
+
Object.values(specResponse.content)[0];
|
|
84
84
|
const responseSchema = (0, refs_1.resolveIfRef)(spec, responseContent.schema);
|
|
85
85
|
if (responseSchema) {
|
|
86
|
-
|
|
86
|
+
await mutateWithOpenapiSchemaProperties(spec, response, responseSchema, modelsByName);
|
|
87
87
|
}
|
|
88
88
|
if (types_1.STREAMING_CONTENT_TYPES.has(mediaType) &&
|
|
89
89
|
'itemSchema' in responseContent) {
|
|
90
90
|
response.isJsonlStreaming = true;
|
|
91
91
|
response.itemSchemaModel =
|
|
92
|
-
|
|
92
|
+
await buildOrReferenceModel(spec, modelsByName, responseContent.itemSchema);
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
const specParametersByName = Object.fromEntries((
|
|
99
|
+
const specParametersByName = Object.fromEntries((specOp?.parameters ?? []).map((p) => {
|
|
100
100
|
const param = (0, refs_1.resolveIfRef)(spec, p);
|
|
101
101
|
return [param.name, param];
|
|
102
102
|
}));
|
|
@@ -107,9 +107,9 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
107
107
|
requestModelImports.push(parameter.type);
|
|
108
108
|
}
|
|
109
109
|
const specParameter = specParametersByName[parameter.prop];
|
|
110
|
-
const specParameterSchema = (0, refs_1.resolveIfRef)(spec, specParameter
|
|
110
|
+
const specParameterSchema = (0, refs_1.resolveIfRef)(spec, specParameter?.schema);
|
|
111
111
|
if (specParameterSchema) {
|
|
112
|
-
|
|
112
|
+
await mutateWithOpenapiSchemaProperties(spec, parameter, specParameterSchema, modelsByName);
|
|
113
113
|
}
|
|
114
114
|
if (parameter.in === 'body') {
|
|
115
115
|
// Parameter name for the body is 'body'
|
|
@@ -117,12 +117,12 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
117
117
|
parameter.prop = 'body';
|
|
118
118
|
// The request body is not in the "parameters" section of the openapi spec so we won't have added the schema
|
|
119
119
|
// properties above. Find it here.
|
|
120
|
-
const specBody = (0, refs_1.resolveIfRef)(spec, specOp
|
|
120
|
+
const specBody = (0, refs_1.resolveIfRef)(spec, specOp?.requestBody);
|
|
121
121
|
if (specBody) {
|
|
122
122
|
if (parameter.mediaType) {
|
|
123
|
-
const bodySchema = (0, refs_1.resolveIfRef)(spec,
|
|
123
|
+
const bodySchema = (0, refs_1.resolveIfRef)(spec, specBody.content?.[parameter.mediaType]?.schema);
|
|
124
124
|
if (bodySchema) {
|
|
125
|
-
|
|
125
|
+
await mutateWithOpenapiSchemaProperties(spec, parameter, bodySchema, modelsByName);
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
// Track all the media types that can be accepted in the request body
|
|
@@ -133,17 +133,18 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
133
133
|
specParameter) {
|
|
134
134
|
// Translate style/explode to OpenAPI v2 style collectionFormat
|
|
135
135
|
// https://spec.openapis.org/oas/v3.0.3.html#style-values
|
|
136
|
-
const style =
|
|
137
|
-
|
|
136
|
+
const style = specParameter.style ??
|
|
137
|
+
(parameter.in === 'query' ? 'form' : 'simple');
|
|
138
|
+
const explode = specParameter.explode ?? style === 'form';
|
|
138
139
|
if (parameter.in === 'query') {
|
|
139
140
|
parameter.collectionFormat = explode
|
|
140
141
|
? 'multi'
|
|
141
|
-
: (
|
|
142
|
+
: ({
|
|
142
143
|
spaceDelimited: 'ssv',
|
|
143
144
|
pipeDelimited: 'tsv',
|
|
144
145
|
simple: 'csv',
|
|
145
146
|
form: 'csv',
|
|
146
|
-
}[style]
|
|
147
|
+
}[style] ?? 'multi');
|
|
147
148
|
}
|
|
148
149
|
else {
|
|
149
150
|
// parameter.in === "header"
|
|
@@ -153,13 +154,14 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
153
154
|
mutateModelWithAdditionalTypes(parameter);
|
|
154
155
|
}
|
|
155
156
|
// Add language types to response models
|
|
156
|
-
(
|
|
157
|
+
(op.responses ?? []).forEach(mutateModelWithAdditionalTypes);
|
|
157
158
|
// Sort responses by code
|
|
158
159
|
op.responses = (0, lodash_orderby_1.default)(op.responses, (r) => r.code);
|
|
159
160
|
// Result is the lowest successful response, otherwise is the 2XX or default response
|
|
160
161
|
const result = op.responses.find((r) => typeof r.code === 'number' && r.code >= 200 && r.code < 300);
|
|
161
162
|
op.result =
|
|
162
|
-
result
|
|
163
|
+
result ??
|
|
164
|
+
op.responses.find((r) => r.code === '2XX' || r.code === 'default');
|
|
163
165
|
// Add variants of operation name
|
|
164
166
|
op.operationIdPascalCase = (0, names_1.pascalCase)(op.uniqueName);
|
|
165
167
|
op.operationIdKebabCase = (0, names_1.kebabCase)(op.uniqueName);
|
|
@@ -167,7 +169,7 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
167
169
|
// Add request type name (after operationIdPascalCase is set)
|
|
168
170
|
if (op.parameters && op.parameters.length > 0) {
|
|
169
171
|
const baseRequestTypeName = `${op.operationIdPascalCase}Request`;
|
|
170
|
-
const hasConflict = !!
|
|
172
|
+
const hasConflict = !!spec.components?.schemas?.[baseRequestTypeName];
|
|
171
173
|
if (hasConflict) {
|
|
172
174
|
// Use OperationRequest suffix when there's a conflict
|
|
173
175
|
op.requestTypeName =
|
|
@@ -195,7 +197,6 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
195
197
|
data.models = [
|
|
196
198
|
...data.models,
|
|
197
199
|
...allOperations.flatMap((op) => {
|
|
198
|
-
var _a;
|
|
199
200
|
if (op.parameters && op.parameters.length > 0) {
|
|
200
201
|
// Build a collection of request parameter models to create based on their position (ie 'in' in the openapi spec, eg body, query, path, header, etc)
|
|
201
202
|
const parametersByPosition = {};
|
|
@@ -203,7 +204,6 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
203
204
|
.filter(
|
|
204
205
|
// We filter out (return false for) request bodies which we "inline" - ie we don't create a property which points to the body, the request will only be the body itself
|
|
205
206
|
(p) => {
|
|
206
|
-
var _a, _b, _c;
|
|
207
207
|
// Always create models for non-body parameters
|
|
208
208
|
if (p.in !== 'body') {
|
|
209
209
|
return true;
|
|
@@ -214,9 +214,9 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
214
214
|
}
|
|
215
215
|
// We inline object bodies, so long as they aren't dictionaries (as dictionary keys could clash with other parameters),
|
|
216
216
|
// and so long as they don't have a property name that clashes with another parameter
|
|
217
|
-
const hasClashingPropertyName = (
|
|
217
|
+
const hasClashingPropertyName = (modelsByName?.[p.type]?.properties ?? []).some((prop) => op.parameters.some((param) => param.name === prop.name));
|
|
218
218
|
if (p.export === 'reference' &&
|
|
219
|
-
|
|
219
|
+
modelsByName?.[p.type]?.export !== 'dictionary' &&
|
|
220
220
|
!hasClashingPropertyName) {
|
|
221
221
|
return false;
|
|
222
222
|
}
|
|
@@ -224,14 +224,13 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
224
224
|
return true;
|
|
225
225
|
})
|
|
226
226
|
.forEach((parameter) => {
|
|
227
|
-
var _a;
|
|
228
227
|
parametersByPosition[parameter.in] = [
|
|
229
|
-
...(
|
|
228
|
+
...(parametersByPosition[parameter.in] ?? []),
|
|
230
229
|
parameter,
|
|
231
230
|
];
|
|
232
231
|
});
|
|
233
232
|
// Ensure that if we have an explicit body parameter, it's called "body"
|
|
234
|
-
const requestBodyParameter =
|
|
233
|
+
const requestBodyParameter = parametersByPosition['body']?.[0];
|
|
235
234
|
if (requestBodyParameter) {
|
|
236
235
|
requestBodyParameter.name = 'body';
|
|
237
236
|
requestBodyParameter.prop = 'body';
|
|
@@ -267,10 +266,10 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
267
266
|
for (const model of data.models) {
|
|
268
267
|
// Add a snake_case name
|
|
269
268
|
model.nameSnakeCase = (0, languages_1.toPythonName)('model', model.name);
|
|
270
|
-
const matchingSpecModel =
|
|
269
|
+
const matchingSpecModel = spec?.components?.schemas?.[model.name];
|
|
271
270
|
if (matchingSpecModel) {
|
|
272
271
|
const specModel = (0, refs_1.resolveIfRef)(spec, matchingSpecModel);
|
|
273
|
-
|
|
272
|
+
await mutateWithOpenapiSchemaProperties(spec, model, specModel, modelsByName);
|
|
274
273
|
// Add unique imports
|
|
275
274
|
model.uniqueImports = (0, lodash_orderby_1.default)((0, lodash_uniqby_1.default)([
|
|
276
275
|
...model.imports,
|
|
@@ -283,10 +282,10 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
283
282
|
model.deprecated = specModel.deprecated || false;
|
|
284
283
|
// Augment properties with additional data
|
|
285
284
|
for (const property of model.properties) {
|
|
286
|
-
const matchingSpecProperty =
|
|
285
|
+
const matchingSpecProperty = specModel.properties?.[property.name];
|
|
287
286
|
if (matchingSpecProperty) {
|
|
288
287
|
const specProperty = (0, refs_1.resolveIfRef)(spec, matchingSpecProperty);
|
|
289
|
-
|
|
288
|
+
await mutateWithOpenapiSchemaProperties(spec, property, specProperty, modelsByName);
|
|
290
289
|
}
|
|
291
290
|
}
|
|
292
291
|
}
|
|
@@ -312,8 +311,7 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
312
311
|
const tags = op.tags;
|
|
313
312
|
if (tags && tags.length > 0) {
|
|
314
313
|
tags.map(lodash_camelcase_1.default).forEach((tag) => {
|
|
315
|
-
|
|
316
|
-
operationsByTag[tag] = [...((_a = operationsByTag[tag]) !== null && _a !== void 0 ? _a : []), op];
|
|
314
|
+
operationsByTag[tag] = [...(operationsByTag[tag] ?? []), op];
|
|
317
315
|
});
|
|
318
316
|
}
|
|
319
317
|
else {
|
|
@@ -322,13 +320,19 @@ const buildOpenApiCodeGenData = (inSpec) => tslib_1.__awaiter(void 0, void 0, vo
|
|
|
322
320
|
});
|
|
323
321
|
// Add top level vendor extensions
|
|
324
322
|
const vendorExtensions = {};
|
|
325
|
-
copyVendorExtensions(spec
|
|
326
|
-
return
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
323
|
+
copyVendorExtensions(spec ?? {}, vendorExtensions);
|
|
324
|
+
return {
|
|
325
|
+
...data,
|
|
326
|
+
operationsByTag,
|
|
327
|
+
untaggedOperations,
|
|
328
|
+
info: spec.info,
|
|
329
|
+
allOperations,
|
|
330
|
+
vendorExtensions,
|
|
331
|
+
className: (0, names_1.toClassName)(spec.info.title),
|
|
332
|
+
};
|
|
333
|
+
};
|
|
330
334
|
exports.buildOpenApiCodeGenData = buildOpenApiCodeGenData;
|
|
331
|
-
const buildInitialCodeGenData = (spec) =>
|
|
335
|
+
const buildInitialCodeGenData = async (spec) => {
|
|
332
336
|
let data;
|
|
333
337
|
// We create a plugin which will capture the client data
|
|
334
338
|
const plugin = () => ({
|
|
@@ -340,7 +344,7 @@ const buildInitialCodeGenData = (spec) => tslib_1.__awaiter(void 0, void 0, void
|
|
|
340
344
|
},
|
|
341
345
|
});
|
|
342
346
|
// Use @hey-api/openapi-ts to build the initial data structure that we'll generate clients from
|
|
343
|
-
|
|
347
|
+
await gen.createClient({
|
|
344
348
|
experimentalParser: false,
|
|
345
349
|
input: {
|
|
346
350
|
path: spec,
|
|
@@ -355,53 +359,54 @@ const buildInitialCodeGenData = (spec) => tslib_1.__awaiter(void 0, void 0, void
|
|
|
355
359
|
throw new Error('Failed to build code generation data');
|
|
356
360
|
}
|
|
357
361
|
return data;
|
|
358
|
-
}
|
|
362
|
+
};
|
|
359
363
|
/**
|
|
360
364
|
* Build a model for a particular primitive schema.
|
|
361
365
|
* Only primitives are supported since we only return one model.
|
|
362
366
|
* For non-primitives, it assumes all referenced subschemas are already models
|
|
363
367
|
*/
|
|
364
|
-
const buildModelForPrimitive = (originalSpec, schema) =>
|
|
365
|
-
var _a;
|
|
368
|
+
const buildModelForPrimitive = async (originalSpec, schema) => {
|
|
366
369
|
const targetSchemaName = '___aws_nx_plugin_openapi_tmp_schema___';
|
|
367
370
|
const spec = {
|
|
368
371
|
openapi: '3.1.0',
|
|
369
372
|
info: { title: 'tmp', version: '1.0.0' },
|
|
370
373
|
paths: {},
|
|
371
374
|
components: {
|
|
372
|
-
schemas:
|
|
375
|
+
schemas: {
|
|
376
|
+
...originalSpec.components?.schemas,
|
|
377
|
+
[targetSchemaName]: schema,
|
|
378
|
+
},
|
|
373
379
|
},
|
|
374
380
|
};
|
|
375
|
-
const data =
|
|
381
|
+
const data = await buildInitialCodeGenData(spec);
|
|
376
382
|
const model = data.models.find((m) => m.name === targetSchemaName);
|
|
377
383
|
if (!model) {
|
|
378
384
|
throw new Error(`Failed to construct model for schema ${JSON.stringify(schema)}`);
|
|
379
385
|
}
|
|
380
386
|
ensureModelLinks(spec, data);
|
|
381
|
-
|
|
387
|
+
await mutateWithOpenapiSchemaProperties(spec, model, schema, Object.fromEntries(data.models.map((m) => [m.name, m])));
|
|
382
388
|
return model;
|
|
383
|
-
}
|
|
384
|
-
const buildOrReferenceModel = (spec, modelsByName, schema) =>
|
|
389
|
+
};
|
|
390
|
+
const buildOrReferenceModel = async (spec, modelsByName, schema) => {
|
|
385
391
|
if ((0, refs_1.isRef)(schema)) {
|
|
386
392
|
const name = (0, refs_1.splitRef)(schema.$ref)[2];
|
|
387
393
|
return modelsByName[name];
|
|
388
394
|
}
|
|
389
395
|
// Non referenced schemas won't have a model created as they are primitives and aren't covered by @heyapi
|
|
390
396
|
// So we build the model here
|
|
391
|
-
return
|
|
392
|
-
}
|
|
397
|
+
return await buildModelForPrimitive(spec, schema);
|
|
398
|
+
};
|
|
393
399
|
/**
|
|
394
400
|
* Copy vendor extensions from the first parameter to the second
|
|
395
401
|
*/
|
|
396
402
|
const copyVendorExtensions = (object, vendorExtensions) => {
|
|
397
|
-
Object.entries(object
|
|
403
|
+
Object.entries(object ?? {}).forEach(([key, value]) => {
|
|
398
404
|
if (key.startsWith('x-')) {
|
|
399
405
|
vendorExtensions[key] = value;
|
|
400
406
|
}
|
|
401
407
|
});
|
|
402
408
|
};
|
|
403
|
-
const mutateWithOpenapiSchemaProperties =
|
|
404
|
-
var _a, _b, _c;
|
|
409
|
+
const mutateWithOpenapiSchemaProperties = async (spec, model, schema, modelsByName, visited = new Set()) => {
|
|
405
410
|
model.format = schema.format;
|
|
406
411
|
model.isInteger = schema.type === 'integer';
|
|
407
412
|
model.isShort = schema.format === 'int32';
|
|
@@ -414,10 +419,10 @@ const mutateWithOpenapiSchemaProperties = (spec_1, model_1, schema_1, modelsByNa
|
|
|
414
419
|
model.vendorExtensions = {};
|
|
415
420
|
copyVendorExtensions(schema, model.vendorExtensions);
|
|
416
421
|
// Use our added vendor extension
|
|
417
|
-
model.isHoisted = !!
|
|
422
|
+
model.isHoisted = !!model.vendorExtensions?.['x-aws-nx-hoisted'];
|
|
418
423
|
// Ensure models with additional properties are handled correctly
|
|
419
424
|
if (schema.additionalProperties) {
|
|
420
|
-
const additionalPropertiesModel =
|
|
425
|
+
const additionalPropertiesModel = await buildOrReferenceModel(spec, modelsByName, schema.additionalProperties === true ? {} : schema.additionalProperties);
|
|
421
426
|
// The original models treat _some_ objects with additional properties as a "dictionary", and others as an "interface"
|
|
422
427
|
// For the purposes of our code generation, we define a "dictionary" to be a model with no explicit properties, only
|
|
423
428
|
// additional properties. Interfaces can have a mixture of explicit properties and additional properties.
|
|
@@ -438,7 +443,7 @@ const mutateWithOpenapiSchemaProperties = (spec_1, model_1, schema_1, modelsByNa
|
|
|
438
443
|
model.additionalPropertiesModel = additionalPropertiesModel;
|
|
439
444
|
// There's a special property named [key: string] which is the definition of the additional properties
|
|
440
445
|
// We remove this so we don't render it as a regular property.
|
|
441
|
-
model.properties = (
|
|
446
|
+
model.properties = (model.properties ?? []).filter((p) => p.name !== '[key: string]');
|
|
442
447
|
}
|
|
443
448
|
}
|
|
444
449
|
// Ensure models with pattern properties are handled correctly
|
|
@@ -451,7 +456,7 @@ const mutateWithOpenapiSchemaProperties = (spec_1, model_1, schema_1, modelsByNa
|
|
|
451
456
|
model.export = 'interface';
|
|
452
457
|
}
|
|
453
458
|
for (const [pattern, patternProperty] of Object.entries(patternProperties)) {
|
|
454
|
-
const patternPropertyModel =
|
|
459
|
+
const patternPropertyModel = await buildOrReferenceModel(spec, modelsByName, patternProperty);
|
|
455
460
|
if (patternPropertyModel) {
|
|
456
461
|
patternPropertiesModels.push({
|
|
457
462
|
pattern,
|
|
@@ -472,7 +477,7 @@ const mutateWithOpenapiSchemaProperties = (spec_1, model_1, schema_1, modelsByNa
|
|
|
472
477
|
schema.items &&
|
|
473
478
|
!visited.has(modelLink)) {
|
|
474
479
|
const subSchema = (0, refs_1.resolveIfRef)(spec, schema.items);
|
|
475
|
-
|
|
480
|
+
await mutateWithOpenapiSchemaProperties(spec, modelLink, subSchema, modelsByName, visited);
|
|
476
481
|
}
|
|
477
482
|
// Also apply to object properties recursively
|
|
478
483
|
if (model.export === 'dictionary' &&
|
|
@@ -483,22 +488,22 @@ const mutateWithOpenapiSchemaProperties = (spec_1, model_1, schema_1, modelsByNa
|
|
|
483
488
|
const subSchema = (0, refs_1.resolveIfRef)(spec, schema.additionalProperties);
|
|
484
489
|
// Additional properties can be "true" rather than a type
|
|
485
490
|
if (subSchema !== true) {
|
|
486
|
-
|
|
491
|
+
await mutateWithOpenapiSchemaProperties(spec, modelLink, subSchema, modelsByName, visited);
|
|
487
492
|
}
|
|
488
493
|
}
|
|
489
|
-
for (const property of model.properties.filter((p) =>
|
|
494
|
+
for (const property of model.properties.filter((p) => !visited.has(p) && schema.properties?.[(0, lodash_trim_1.default)(p.name, `"'`)])) {
|
|
490
495
|
const subSchema = (0, refs_1.resolveIfRef)(spec, schema.properties[(0, lodash_trim_1.default)(property.name, `"'`)]);
|
|
491
|
-
|
|
496
|
+
await mutateWithOpenapiSchemaProperties(spec, property, subSchema, modelsByName, visited);
|
|
492
497
|
}
|
|
493
498
|
if (types_1.COMPOSED_SCHEMA_TYPES.has(model.export)) {
|
|
494
499
|
for (let i = 0; i < model.properties.length; i++) {
|
|
495
|
-
const subSchema = (0, refs_1.resolveIfRef)(spec,
|
|
500
|
+
const subSchema = (0, refs_1.resolveIfRef)(spec, schema[(0, lodash_camelcase_1.default)(model.export)]?.[i]);
|
|
496
501
|
if (subSchema) {
|
|
497
|
-
|
|
502
|
+
await mutateWithOpenapiSchemaProperties(spec, model.properties[i], subSchema, modelsByName, visited);
|
|
498
503
|
}
|
|
499
504
|
}
|
|
500
505
|
}
|
|
501
|
-
}
|
|
506
|
+
};
|
|
502
507
|
/**
|
|
503
508
|
* Ensure that the "link" property of all dictionary/array models and properties are set recursively
|
|
504
509
|
*/
|
|
@@ -507,8 +512,7 @@ const ensureModelLinks = (spec, data) => {
|
|
|
507
512
|
const visited = new Set();
|
|
508
513
|
// Ensure set for all models
|
|
509
514
|
data.models.forEach((model) => {
|
|
510
|
-
|
|
511
|
-
const schema = (0, refs_1.resolveIfRef)(spec, (_b = (_a = spec === null || spec === void 0 ? void 0 : spec.components) === null || _a === void 0 ? void 0 : _a.schemas) === null || _b === void 0 ? void 0 : _b[model.name]);
|
|
515
|
+
const schema = (0, refs_1.resolveIfRef)(spec, spec?.components?.schemas?.[model.name]);
|
|
512
516
|
if (schema) {
|
|
513
517
|
// Object schemas should be typed as the model we will create
|
|
514
518
|
if (schema.type === 'object' &&
|
|
@@ -521,35 +525,31 @@ const ensureModelLinks = (spec, data) => {
|
|
|
521
525
|
// Ensure set for all parameters and responses
|
|
522
526
|
data.services.forEach((service) => {
|
|
523
527
|
service.operations.forEach((op) => {
|
|
524
|
-
|
|
525
|
-
const
|
|
526
|
-
const specParametersByName = Object.fromEntries(((_c = specOp === null || specOp === void 0 ? void 0 : specOp.parameters) !== null && _c !== void 0 ? _c : []).map((p) => {
|
|
528
|
+
const specOp = spec?.paths?.[op.path]?.[op.method.toLowerCase()];
|
|
529
|
+
const specParametersByName = Object.fromEntries((specOp?.parameters ?? []).map((p) => {
|
|
527
530
|
const param = (0, refs_1.resolveIfRef)(spec, p);
|
|
528
531
|
return [param.name, param];
|
|
529
532
|
}));
|
|
530
533
|
op.parameters.forEach((parameter) => {
|
|
531
|
-
var _a, _b;
|
|
532
534
|
const specParameter = specParametersByName[parameter.prop];
|
|
533
|
-
const specParameterSchema = (0, refs_1.resolveIfRef)(spec, specParameter
|
|
535
|
+
const specParameterSchema = (0, refs_1.resolveIfRef)(spec, specParameter?.schema);
|
|
534
536
|
if (specParameterSchema) {
|
|
535
537
|
_ensureModelLinks(spec, modelsByName, parameter, specParameterSchema, visited);
|
|
536
538
|
}
|
|
537
539
|
else if (parameter.in === 'body') {
|
|
538
540
|
// Body is not in the "parameters" section of the OpenAPI spec so we handle it in an explicit case here
|
|
539
|
-
const specBody = (0, refs_1.resolveIfRef)(spec, specOp
|
|
540
|
-
const specBodySchema = (0, refs_1.resolveIfRef)(spec,
|
|
541
|
+
const specBody = (0, refs_1.resolveIfRef)(spec, specOp?.requestBody);
|
|
542
|
+
const specBodySchema = (0, refs_1.resolveIfRef)(spec, specBody?.content?.[parameter.mediaType]?.schema);
|
|
541
543
|
if (specBodySchema) {
|
|
542
544
|
_ensureModelLinks(spec, modelsByName, parameter, specBodySchema, visited);
|
|
543
545
|
}
|
|
544
546
|
}
|
|
545
547
|
});
|
|
546
548
|
op.responses.forEach((response) => {
|
|
547
|
-
|
|
548
|
-
const
|
|
549
|
-
const mediaTypes = Object.keys((_b = specResponse === null || specResponse === void 0 ? void 0 : specResponse.content) !== null && _b !== void 0 ? _b : {});
|
|
549
|
+
const specResponse = (0, refs_1.resolveIfRef)(spec, specOp?.responses?.[response.code]);
|
|
550
|
+
const mediaTypes = Object.keys(specResponse?.content ?? {});
|
|
550
551
|
mediaTypes.forEach((mediaType) => {
|
|
551
|
-
|
|
552
|
-
const responseSchema = (0, refs_1.resolveIfRef)(spec, (_b = (_a = specResponse === null || specResponse === void 0 ? void 0 : specResponse.content) === null || _a === void 0 ? void 0 : _a[mediaType]) === null || _b === void 0 ? void 0 : _b.schema);
|
|
552
|
+
const responseSchema = (0, refs_1.resolveIfRef)(spec, specResponse?.content?.[mediaType]?.schema);
|
|
553
553
|
if (responseSchema) {
|
|
554
554
|
_ensureModelLinks(spec, modelsByName, response, responseSchema, visited);
|
|
555
555
|
}
|
|
@@ -588,15 +588,14 @@ const _ensureModelLinks = (spec, modelsByName, model, schema, visited) => {
|
|
|
588
588
|
}
|
|
589
589
|
}
|
|
590
590
|
model.properties
|
|
591
|
-
.filter((p) =>
|
|
591
|
+
.filter((p) => !visited.has(p) && schema.properties?.[(0, lodash_trim_1.default)(p.name, `"'`)])
|
|
592
592
|
.forEach((property) => {
|
|
593
593
|
const subSchema = (0, refs_1.resolveIfRef)(spec, schema.properties[(0, lodash_trim_1.default)(property.name, `"'`)]);
|
|
594
594
|
_ensureModelLinks(spec, modelsByName, property, subSchema, visited);
|
|
595
595
|
});
|
|
596
596
|
if (types_1.COMPOSED_SCHEMA_TYPES.has(model.export)) {
|
|
597
597
|
model.properties.forEach((property, i) => {
|
|
598
|
-
|
|
599
|
-
const subSchema = (0, refs_1.resolveIfRef)(spec, (_a = schema[(0, lodash_camelcase_1.default)(model.export)]) === null || _a === void 0 ? void 0 : _a[i]);
|
|
598
|
+
const subSchema = (0, refs_1.resolveIfRef)(spec, schema[(0, lodash_camelcase_1.default)(model.export)]?.[i]);
|
|
600
599
|
if (subSchema) {
|
|
601
600
|
_ensureModelLinks(spec, modelsByName, property, subSchema, visited);
|
|
602
601
|
}
|
|
@@ -670,10 +669,10 @@ const mutateModelWithAdditionalTypes = (model) => {
|
|
|
670
669
|
const isOperationMutation = (op) => {
|
|
671
670
|
// Let the user override whether an operation is a query or mutation using x-mutation/x-query
|
|
672
671
|
const { vendorExtensions } = op;
|
|
673
|
-
if (vendorExtensions
|
|
672
|
+
if (vendorExtensions?.[types_1.VENDOR_EXTENSIONS.MUTATION]) {
|
|
674
673
|
return true;
|
|
675
674
|
}
|
|
676
|
-
else if (vendorExtensions
|
|
675
|
+
else if (vendorExtensions?.[types_1.VENDOR_EXTENSIONS.QUERY]) {
|
|
677
676
|
return false;
|
|
678
677
|
}
|
|
679
678
|
// Assume a restful API and treat mutative HTTP methods as mutations
|
|
@@ -709,7 +708,7 @@ const mutateOperationWithInfiniteQueryDetails = (op) => {
|
|
|
709
708
|
*/
|
|
710
709
|
const getCursorOptions = (op) => {
|
|
711
710
|
const { vendorExtensions } = op;
|
|
712
|
-
const cursorExtension = vendorExtensions
|
|
711
|
+
const cursorExtension = vendorExtensions?.[types_1.VENDOR_EXTENSIONS.CURSOR];
|
|
713
712
|
// By default pagination isn't explicitly disabled and the cursor property to look for is 'cursor'
|
|
714
713
|
let paginationDisabled = false;
|
|
715
714
|
let cursorPropertyName = 'cursor';
|
|
@@ -720,10 +719,10 @@ const getCursorOptions = (op) => {
|
|
|
720
719
|
cursorPropertyName = cursorExtension;
|
|
721
720
|
}
|
|
722
721
|
else if (typeof cursorExtension === 'object') {
|
|
723
|
-
if (
|
|
722
|
+
if (cursorExtension?.enabled === false) {
|
|
724
723
|
paginationDisabled = true;
|
|
725
724
|
}
|
|
726
|
-
if (
|
|
725
|
+
if (cursorExtension?.inputToken &&
|
|
727
726
|
typeof cursorExtension.inputToken === 'string') {
|
|
728
727
|
cursorPropertyName = cursorExtension.inputToken;
|
|
729
728
|
}
|
|
@@ -738,14 +737,13 @@ const getCursorOptions = (op) => {
|
|
|
738
737
|
* Add additional data to an operation for code generation decisions
|
|
739
738
|
*/
|
|
740
739
|
const mutateOperationWithAdditionalData = (op) => {
|
|
741
|
-
var _a;
|
|
742
740
|
// Add mutation/query details
|
|
743
741
|
const isMutation = isOperationMutation(op);
|
|
744
742
|
op.isMutation = isMutation;
|
|
745
743
|
op.isQuery = !isMutation;
|
|
746
744
|
// Streaming responses
|
|
747
745
|
op.isStreaming =
|
|
748
|
-
!!
|
|
746
|
+
!!op.vendorExtensions?.[types_1.VENDOR_EXTENSIONS.STREAMING] ||
|
|
749
747
|
op.responses.some((res) => res.isJsonlStreaming);
|
|
750
748
|
// Set the result type for the client method to the item schema so that
|
|
751
749
|
// it will resolve to AsyncIterableIterator<{itemSchemaModel.name}>
|