@aws/nx-plugin 0.20.0 → 0.22.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 +531 -21
- package/README.md +3 -9
- package/generators.json +14 -0
- package/package.json +7 -7
- package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/core/user-identity.ts.template +1 -0
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +54 -12
- package/src/infra/app/generator.js +14 -0
- package/src/infra/app/generator.js.map +1 -1
- package/src/open-api/ts-metadata/__snapshots__/generator.spec.ts.snap +49 -0
- package/src/open-api/ts-metadata/files/metadata.gen.ts.template +17 -0
- package/src/open-api/ts-metadata/generator.d.ts +16 -0
- package/src/open-api/ts-metadata/generator.js +32 -0
- package/src/open-api/ts-metadata/generator.js.map +1 -0
- package/src/{utils/http-api.d.ts → open-api/ts-metadata/schema.d.ts} +5 -2
- package/src/open-api/ts-metadata/schema.json +20 -0
- package/src/open-api/utils/codegen-data.js +3 -0
- package/src/open-api/utils/codegen-data.js.map +1 -1
- package/src/open-api/utils/normalise.js +6 -0
- package/src/open-api/utils/normalise.js.map +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +199 -0
- package/src/preset/files/README.md +107 -0
- package/src/preset/generator.d.ts +10 -0
- package/src/preset/generator.js +63 -0
- package/src/preset/generator.js.map +1 -0
- package/src/preset/schema.d.ts +7 -0
- package/src/preset/schema.json +14 -0
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +972 -0
- package/src/py/fast-api/files/app/__name__/init.py.template +8 -0
- package/src/py/fast-api/generator.js +53 -15
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/fast-api/react/files/website/components/__apiNameClassName__Provider.tsx.template +1 -1
- package/src/py/fast-api/react/generator.js +6 -23
- package/src/py/fast-api/react/generator.js.map +1 -1
- package/src/py/fast-api/react/open-api.d.ts +14 -0
- package/src/py/fast-api/react/open-api.js +53 -0
- package/src/py/fast-api/react/open-api.js.map +1 -0
- package/src/py/fast-api/schema.d.ts +3 -0
- package/src/py/fast-api/schema.json +8 -0
- package/src/setup-tests.d.ts +2 -0
- package/src/setup-tests.js +14 -0
- package/src/setup-tests.js.map +1 -0
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +1061 -88
- package/src/trpc/backend/files/backend/src/client/index.ts.template +2 -13
- package/src/trpc/backend/files/backend/src/index.ts.template +1 -0
- package/src/trpc/backend/files/backend/src/init.ts.template +4 -4
- package/src/trpc/backend/files/backend/src/middleware/index.ts.template +3 -2
- package/src/trpc/backend/files/backend/src/router.ts.template +11 -2
- package/src/trpc/backend/generator.js +12 -10
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.d.ts +1 -1
- package/src/trpc/backend/schema.json +8 -0
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +4 -19
- package/src/trpc/react/files/src/components/TrpcClients/TrpcProvider.tsx.template +2 -13
- package/src/trpc/react/generator.js +1 -1
- package/src/trpc/react/generator.js.map +1 -1
- package/src/ts/lib/__snapshots__/generator.spec.ts.snap +26 -9
- package/src/ts/lib/generator.js +9 -0
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +1 -4
- package/src/ts/nx-generator/generator.js +4 -3
- package/src/ts/nx-generator/generator.js.map +1 -1
- package/src/utils/api-constructs/api-constructs.d.ts +29 -0
- package/src/utils/api-constructs/api-constructs.js +65 -0
- package/src/utils/api-constructs/api-constructs.js.map +1 -0
- package/src/utils/api-constructs/files/app/apis/http/__apiNameKebabCase__.ts.template +135 -0
- package/src/utils/api-constructs/files/app/apis/rest/__apiNameKebabCase__.ts.template +156 -0
- package/src/utils/api-constructs/files/core/api/http/http-api.ts.template +112 -0
- package/src/utils/api-constructs/files/core/api/rest/rest-api.ts.template +137 -0
- package/src/utils/api-constructs/files/core/api/trpc/trpc-utils.ts.template +67 -0
- package/src/utils/api-constructs/files/core/api/utils/utils.ts.template +223 -0
- package/src/utils/versions.d.ts +3 -3
- package/src/utils/versions.js +2 -2
- package/src/py/fast-api/files/common/constructs/src/app/http-apis/__apiNameKebabCase__.ts.template +0 -22
- package/src/trpc/backend/files/common/constructs/src/app/http-apis/__apiNameKebabCase__.ts.template +0 -22
- package/src/utils/files/http-api/common/constructs/src/core/http-api.ts.template +0 -87
- package/src/utils/http-api.js +0 -51
- package/src/utils/http-api.js.map +0 -1
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`fastapi project generator > should match snapshot > main-snapshot 1`] = `
|
|
4
4
|
{
|
|
5
|
+
"apps/test_api/scripts/generate_open_api.py": "from test_api.main import app
|
|
6
|
+
import json, os, sys
|
|
7
|
+
|
|
8
|
+
os.makedirs(os.path.dirname(sys.argv[1]), exist_ok=True)
|
|
9
|
+
with open(sys.argv[1], 'w') as f:
|
|
10
|
+
json.dump(app.openapi(), f)
|
|
11
|
+
",
|
|
5
12
|
"apps/test_api/test_api/__init__.py": """"Automatically generated by Nx."""
|
|
6
13
|
",
|
|
7
14
|
"apps/test_api/test_api/init.py": "import os
|
|
@@ -156,3 +163,968 @@ def test_main():
|
|
|
156
163
|
",
|
|
157
164
|
}
|
|
158
165
|
`;
|
|
166
|
+
|
|
167
|
+
exports[`fastapi project generator > should set up shared constructs for http > http-api.ts 1`] = `
|
|
168
|
+
"import { Construct } from 'constructs';
|
|
169
|
+
import { RuntimeConfig } from '../runtime-config.js';
|
|
170
|
+
import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam';
|
|
171
|
+
import { HttpApiIntegration, OperationDetails } from './utils.js';
|
|
172
|
+
import { CfnOutput } from 'aws-cdk-lib';
|
|
173
|
+
import {
|
|
174
|
+
HttpApi as _HttpApi,
|
|
175
|
+
HttpApiProps as _HttpApiProps,
|
|
176
|
+
HttpMethod,
|
|
177
|
+
} from 'aws-cdk-lib/aws-apigatewayv2';
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Properties for creating an HttpApi construct.
|
|
181
|
+
*
|
|
182
|
+
* @template TIntegrations - Record mapping operation names to their integrations
|
|
183
|
+
* @template TOperation - String literal type representing operation names
|
|
184
|
+
*/
|
|
185
|
+
export interface HttpApiProps<
|
|
186
|
+
TIntegrations extends Record<TOperation, HttpApiIntegration>,
|
|
187
|
+
TOperation extends string,
|
|
188
|
+
> extends _HttpApiProps {
|
|
189
|
+
/**
|
|
190
|
+
* Unique name for the API, used in runtime configuration
|
|
191
|
+
*/
|
|
192
|
+
readonly apiName: string;
|
|
193
|
+
/**
|
|
194
|
+
* Map of operation names to their API path and HTTP method details
|
|
195
|
+
*/
|
|
196
|
+
readonly operations: Record<TOperation, OperationDetails>;
|
|
197
|
+
/**
|
|
198
|
+
* Map of operation names to their API Gateway integrations
|
|
199
|
+
*/
|
|
200
|
+
readonly integrations: TIntegrations;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* A CDK construct that creates and configures an AWS API Gateway HTTP API.
|
|
205
|
+
*
|
|
206
|
+
* This class extends the base CDK HttpApi with additional functionality:
|
|
207
|
+
* - Type-safe operation and integration management
|
|
208
|
+
* - Automatic resource creation based on path patterns
|
|
209
|
+
* - Integration with runtime configuration for client discovery
|
|
210
|
+
*
|
|
211
|
+
* @template TOperation - String literal type representing operation names
|
|
212
|
+
* @template TIntegrations - Record mapping operation names to their integrations
|
|
213
|
+
*/
|
|
214
|
+
export class HttpApi<
|
|
215
|
+
TOperation extends string,
|
|
216
|
+
TIntegrations extends Record<TOperation, HttpApiIntegration>,
|
|
217
|
+
> extends Construct {
|
|
218
|
+
/** The underlying CDK HttpApi instance */
|
|
219
|
+
public readonly api: _HttpApi;
|
|
220
|
+
|
|
221
|
+
/** Map of operation names to their API Gateway integrations */
|
|
222
|
+
public readonly integrations: TIntegrations;
|
|
223
|
+
|
|
224
|
+
constructor(
|
|
225
|
+
scope: Construct,
|
|
226
|
+
id: string,
|
|
227
|
+
{
|
|
228
|
+
apiName,
|
|
229
|
+
operations,
|
|
230
|
+
integrations,
|
|
231
|
+
...props
|
|
232
|
+
}: HttpApiProps<TIntegrations, TOperation>,
|
|
233
|
+
) {
|
|
234
|
+
super(scope, id);
|
|
235
|
+
this.integrations = integrations;
|
|
236
|
+
|
|
237
|
+
// Create the API Gateway REST API with logging enabled
|
|
238
|
+
this.api = new _HttpApi(this, 'Api', {
|
|
239
|
+
...props,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Create API resources and methods for each operation
|
|
243
|
+
(Object.entries(operations) as [TOperation, OperationDetails][]).map(
|
|
244
|
+
([op, details]) => {
|
|
245
|
+
this.api.addRoutes({
|
|
246
|
+
path: details.path.startsWith('/')
|
|
247
|
+
? details.path
|
|
248
|
+
: \`/\${details.path}\`,
|
|
249
|
+
methods: [details.method as HttpMethod],
|
|
250
|
+
integration: integrations[op].integration,
|
|
251
|
+
...integrations[op].options,
|
|
252
|
+
});
|
|
253
|
+
},
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
new CfnOutput(this, \`\${apiName}Url\`, {
|
|
257
|
+
value: this.api.url!,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Register the API URL in runtime configuration for client discovery
|
|
261
|
+
RuntimeConfig.ensure(this).config.apis = {
|
|
262
|
+
...RuntimeConfig.ensure(this).config.apis!,
|
|
263
|
+
[apiName]: this.api.url!,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Grants IAM permissions to invoke any method on this API.
|
|
269
|
+
*
|
|
270
|
+
* @param grantee - The IAM principal to grant permissions to
|
|
271
|
+
*/
|
|
272
|
+
public grantInvokeAccess(grantee: IGrantable) {
|
|
273
|
+
Grant.addToPrincipal({
|
|
274
|
+
grantee,
|
|
275
|
+
actions: ['execute-api:Invoke'],
|
|
276
|
+
resourceArns: [this.api.arnForExecuteApi('*', '/*', '*')],
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
"
|
|
281
|
+
`;
|
|
282
|
+
|
|
283
|
+
exports[`fastapi project generator > should set up shared constructs for http > test-api.ts 1`] = `
|
|
284
|
+
"import { Construct } from 'constructs';
|
|
285
|
+
import * as url from 'url';
|
|
286
|
+
import {
|
|
287
|
+
Code,
|
|
288
|
+
Runtime,
|
|
289
|
+
Function,
|
|
290
|
+
FunctionProps,
|
|
291
|
+
Tracing,
|
|
292
|
+
} from 'aws-cdk-lib/aws-lambda';
|
|
293
|
+
import { Duration } from 'aws-cdk-lib';
|
|
294
|
+
import { CorsHttpMethod } from 'aws-cdk-lib/aws-apigatewayv2';
|
|
295
|
+
import { HttpIamAuthorizer } from 'aws-cdk-lib/aws-apigatewayv2-authorizers';
|
|
296
|
+
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
|
297
|
+
import {
|
|
298
|
+
HttpApiIntegration,
|
|
299
|
+
IntegrationBuilder,
|
|
300
|
+
} from '../../core/api/utils.js';
|
|
301
|
+
import { HttpApi } from '../../core/api/http-api.js';
|
|
302
|
+
import {
|
|
303
|
+
OPERATION_DETAILS,
|
|
304
|
+
Operations,
|
|
305
|
+
} from '../../generated/test-api/metadata.gen.js';
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Properties for creating a TestApi construct
|
|
309
|
+
*
|
|
310
|
+
* @template TIntegrations - Map of operation names to their integrations
|
|
311
|
+
*/
|
|
312
|
+
export interface TestApiProps<
|
|
313
|
+
TIntegrations extends Record<Operations, HttpApiIntegration>,
|
|
314
|
+
> {
|
|
315
|
+
/**
|
|
316
|
+
* Map of operation names to their API Gateway integrations
|
|
317
|
+
*/
|
|
318
|
+
integrations: TIntegrations;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* A CDK construct that creates and configures an AWS API Gateway HTTP API
|
|
323
|
+
* specifically for TestApi.
|
|
324
|
+
* @template TIntegrations - Map of operation names to their integrations
|
|
325
|
+
*/
|
|
326
|
+
export class TestApi<
|
|
327
|
+
TIntegrations extends Record<Operations, HttpApiIntegration>,
|
|
328
|
+
> extends HttpApi<Operations, TIntegrations> {
|
|
329
|
+
/**
|
|
330
|
+
* Creates default integrations for all operations, which implement each operation as
|
|
331
|
+
* its own individual lambda function.
|
|
332
|
+
*
|
|
333
|
+
* @param scope - The CDK construct scope
|
|
334
|
+
* @returns An IntegrationBuilder with default lambda integrations
|
|
335
|
+
*/
|
|
336
|
+
public static defaultIntegrations = (scope: Construct) => {
|
|
337
|
+
return IntegrationBuilder.http({
|
|
338
|
+
operations: OPERATION_DETAILS,
|
|
339
|
+
defaultIntegrationOptions: {
|
|
340
|
+
runtime: Runtime.PYTHON_3_12,
|
|
341
|
+
handler: 'test_api.main.handler',
|
|
342
|
+
code: Code.fromAsset(
|
|
343
|
+
url.fileURLToPath(
|
|
344
|
+
new URL(
|
|
345
|
+
'../../../../../../dist/apps/nested/path/test_api/bundle',
|
|
346
|
+
import.meta.url,
|
|
347
|
+
),
|
|
348
|
+
),
|
|
349
|
+
),
|
|
350
|
+
timeout: Duration.seconds(30),
|
|
351
|
+
tracing: Tracing.ACTIVE,
|
|
352
|
+
environment: {
|
|
353
|
+
AWS_CONNECTION_REUSE_ENABLED: '1',
|
|
354
|
+
},
|
|
355
|
+
} satisfies FunctionProps,
|
|
356
|
+
buildDefaultIntegration: (op, props: FunctionProps) => {
|
|
357
|
+
const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
|
|
358
|
+
return {
|
|
359
|
+
handler,
|
|
360
|
+
integration: new HttpLambdaIntegration(
|
|
361
|
+
\`TestApi\${op}Integration\`,
|
|
362
|
+
handler,
|
|
363
|
+
),
|
|
364
|
+
};
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
constructor(
|
|
370
|
+
scope: Construct,
|
|
371
|
+
id: string,
|
|
372
|
+
props: TestApiProps<TIntegrations>,
|
|
373
|
+
) {
|
|
374
|
+
super(scope, id, {
|
|
375
|
+
apiName: 'TestApi',
|
|
376
|
+
corsPreflight: {
|
|
377
|
+
allowOrigins: ['*'],
|
|
378
|
+
allowMethods: [CorsHttpMethod.ANY],
|
|
379
|
+
allowHeaders: [
|
|
380
|
+
'authorization',
|
|
381
|
+
'content-type',
|
|
382
|
+
'x-amz-content-sha256',
|
|
383
|
+
'x-amz-date',
|
|
384
|
+
'x-amz-security-token',
|
|
385
|
+
],
|
|
386
|
+
},
|
|
387
|
+
defaultAuthorizer: new HttpIamAuthorizer(),
|
|
388
|
+
operations: OPERATION_DETAILS,
|
|
389
|
+
...props,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
"
|
|
394
|
+
`;
|
|
395
|
+
|
|
396
|
+
exports[`fastapi project generator > should set up shared constructs for http > utils.ts 1`] = `
|
|
397
|
+
"import { Integration, MethodOptions } from 'aws-cdk-lib/aws-apigateway';
|
|
398
|
+
import {
|
|
399
|
+
HttpRouteIntegration,
|
|
400
|
+
AddRoutesOptions,
|
|
401
|
+
} from 'aws-cdk-lib/aws-apigatewayv2';
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Type representing applicable HTTP Methods in API Gateway
|
|
405
|
+
*/
|
|
406
|
+
export type HttpMethod =
|
|
407
|
+
| 'ANY'
|
|
408
|
+
| 'DELETE'
|
|
409
|
+
| 'GET'
|
|
410
|
+
| 'HEAD'
|
|
411
|
+
| 'OPTIONS'
|
|
412
|
+
| 'PATCH'
|
|
413
|
+
| 'POST'
|
|
414
|
+
| 'PUT';
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Defines the details of an API operation.
|
|
418
|
+
*/
|
|
419
|
+
export interface OperationDetails {
|
|
420
|
+
/**
|
|
421
|
+
* The URL path for the operation
|
|
422
|
+
*/
|
|
423
|
+
path: string;
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* The HTTP method for the operation
|
|
427
|
+
*/
|
|
428
|
+
method: HttpMethod;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Represents an API Gateway REST API integration that can be attached to API methods.
|
|
433
|
+
*/
|
|
434
|
+
export interface RestApiIntegration {
|
|
435
|
+
integration: Integration;
|
|
436
|
+
options?: MethodOptions;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Represents an API Gateway HTTP API that can be attached to API methods.
|
|
441
|
+
*/
|
|
442
|
+
export interface HttpApiIntegration {
|
|
443
|
+
integration: HttpRouteIntegration;
|
|
444
|
+
options?: Omit<AddRoutesOptions, 'path' | 'methods' | 'integration'>;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Options for constructing an IntegrationBuilder
|
|
449
|
+
*/
|
|
450
|
+
export interface IntegrationBuilderProps<
|
|
451
|
+
TOperation extends string,
|
|
452
|
+
TBaseIntegration,
|
|
453
|
+
TDefaultIntegrationProps extends object,
|
|
454
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
455
|
+
> {
|
|
456
|
+
/** Map of operation names to their API path and HTTP method details */
|
|
457
|
+
operations: Record<TOperation, OperationDetails>;
|
|
458
|
+
|
|
459
|
+
/** Default configuration options for integrations */
|
|
460
|
+
defaultIntegrationOptions: TDefaultIntegrationProps;
|
|
461
|
+
|
|
462
|
+
/** Function to create a default integration for an operation */
|
|
463
|
+
buildDefaultIntegration: (
|
|
464
|
+
op: TOperation,
|
|
465
|
+
props: TDefaultIntegrationProps,
|
|
466
|
+
) => TDefaultIntegration;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* A builder class for creating API integrations with flexible configuration options.
|
|
471
|
+
*
|
|
472
|
+
* This class implements the builder pattern to create a set of API integrations
|
|
473
|
+
* with support for default configurations and selective overrides.
|
|
474
|
+
*
|
|
475
|
+
* @template TOperation - String literal type representing operation names
|
|
476
|
+
* @template TBaseIntegration - Base type for all integrations
|
|
477
|
+
* @template TIntegrations - Record mapping operation names to their integrations
|
|
478
|
+
* @template TDefaultIntegrationProps - Type for default integration properties
|
|
479
|
+
* @template TDefaultIntegration - Type for default integration implementation
|
|
480
|
+
*/
|
|
481
|
+
export class IntegrationBuilder<
|
|
482
|
+
TOperation extends string,
|
|
483
|
+
TBaseIntegration,
|
|
484
|
+
TIntegrations extends Record<TOperation, TBaseIntegration>,
|
|
485
|
+
TDefaultIntegrationProps extends object,
|
|
486
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
487
|
+
> {
|
|
488
|
+
/** Options for the integration builder */
|
|
489
|
+
private options: IntegrationBuilderProps<
|
|
490
|
+
TOperation,
|
|
491
|
+
TBaseIntegration,
|
|
492
|
+
TDefaultIntegrationProps,
|
|
493
|
+
TDefaultIntegration
|
|
494
|
+
>;
|
|
495
|
+
|
|
496
|
+
/** Map of operation names to their custom integrations */
|
|
497
|
+
private integrations: Partial<TIntegrations> = {};
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Create an Integration Builder for an HTTP API
|
|
501
|
+
*/
|
|
502
|
+
public static http = <
|
|
503
|
+
TOperation extends string,
|
|
504
|
+
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
505
|
+
TDefaultIntegrationProps extends object,
|
|
506
|
+
TDefaultIntegration extends HttpApiIntegration,
|
|
507
|
+
>(
|
|
508
|
+
options: IntegrationBuilderProps<
|
|
509
|
+
TOperation,
|
|
510
|
+
HttpApiIntegration,
|
|
511
|
+
TDefaultIntegrationProps,
|
|
512
|
+
TDefaultIntegration
|
|
513
|
+
>,
|
|
514
|
+
) => {
|
|
515
|
+
return new IntegrationBuilder<
|
|
516
|
+
TOperation,
|
|
517
|
+
HttpApiIntegration,
|
|
518
|
+
TIntegrations,
|
|
519
|
+
TDefaultIntegrationProps,
|
|
520
|
+
TDefaultIntegration
|
|
521
|
+
>(options);
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Create an Integration Builder for a REST API
|
|
526
|
+
*/
|
|
527
|
+
public static rest = <
|
|
528
|
+
TOperation extends string,
|
|
529
|
+
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
530
|
+
TDefaultIntegrationProps extends object,
|
|
531
|
+
TDefaultIntegration extends RestApiIntegration,
|
|
532
|
+
>(
|
|
533
|
+
options: IntegrationBuilderProps<
|
|
534
|
+
TOperation,
|
|
535
|
+
RestApiIntegration,
|
|
536
|
+
TDefaultIntegrationProps,
|
|
537
|
+
TDefaultIntegration
|
|
538
|
+
>,
|
|
539
|
+
) => {
|
|
540
|
+
return new IntegrationBuilder<
|
|
541
|
+
TOperation,
|
|
542
|
+
RestApiIntegration,
|
|
543
|
+
TIntegrations,
|
|
544
|
+
TDefaultIntegrationProps,
|
|
545
|
+
TDefaultIntegration
|
|
546
|
+
>(options);
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
private constructor(
|
|
550
|
+
options: IntegrationBuilderProps<
|
|
551
|
+
TOperation,
|
|
552
|
+
TBaseIntegration,
|
|
553
|
+
TDefaultIntegrationProps,
|
|
554
|
+
TDefaultIntegration
|
|
555
|
+
>,
|
|
556
|
+
) {
|
|
557
|
+
this.options = options;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Overrides default integrations with custom implementations for specific operations.
|
|
562
|
+
*
|
|
563
|
+
* @param overrides - Map of operation names to their custom integration implementations
|
|
564
|
+
* @returns The builder instance with updated type information reflecting the overrides
|
|
565
|
+
*/
|
|
566
|
+
public withOverrides<
|
|
567
|
+
TOverrideIntegrations extends Partial<Record<TOperation, TBaseIntegration>>,
|
|
568
|
+
>(overrides: TOverrideIntegrations) {
|
|
569
|
+
this.integrations = { ...this.integrations, ...overrides };
|
|
570
|
+
// Re-type to include the overridden integration types
|
|
571
|
+
return this as unknown as IntegrationBuilder<
|
|
572
|
+
TOperation,
|
|
573
|
+
TBaseIntegration,
|
|
574
|
+
Omit<TIntegrations, keyof TOverrideIntegrations> & TOverrideIntegrations,
|
|
575
|
+
TDefaultIntegrationProps,
|
|
576
|
+
TDefaultIntegration
|
|
577
|
+
>;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Updates the default integration options that will be used for operations
|
|
582
|
+
* without custom overrides.
|
|
583
|
+
*
|
|
584
|
+
* @param options - Partial default integration options to merge with existing defaults
|
|
585
|
+
* @returns The builder instance
|
|
586
|
+
*/
|
|
587
|
+
public withDefaultOptions(options: Partial<TDefaultIntegrationProps>) {
|
|
588
|
+
this.options.defaultIntegrationOptions = {
|
|
589
|
+
...this.options.defaultIntegrationOptions,
|
|
590
|
+
...options,
|
|
591
|
+
};
|
|
592
|
+
return this;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Builds and returns the complete set of integrations.
|
|
597
|
+
*
|
|
598
|
+
* This method creates the final integration map by:
|
|
599
|
+
* 1. Including all custom overrides provided via withOverrides()
|
|
600
|
+
* 2. Creating default integrations for any operations without custom overrides
|
|
601
|
+
*
|
|
602
|
+
* @returns A complete map of operation names to their integrations
|
|
603
|
+
*/
|
|
604
|
+
public build(): TIntegrations {
|
|
605
|
+
return {
|
|
606
|
+
...this.integrations,
|
|
607
|
+
...Object.fromEntries(
|
|
608
|
+
(Object.keys(this.options.operations) as TOperation[])
|
|
609
|
+
.filter(
|
|
610
|
+
(op) => !this.integrations[op as keyof typeof this.integrations],
|
|
611
|
+
)
|
|
612
|
+
.map((op) => [
|
|
613
|
+
op,
|
|
614
|
+
this.options.buildDefaultIntegration(
|
|
615
|
+
op,
|
|
616
|
+
this.options.defaultIntegrationOptions,
|
|
617
|
+
),
|
|
618
|
+
]),
|
|
619
|
+
),
|
|
620
|
+
} as unknown as TIntegrations;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
"
|
|
624
|
+
`;
|
|
625
|
+
|
|
626
|
+
exports[`fastapi project generator > should set up shared constructs for rest > rest-api.ts 1`] = `
|
|
627
|
+
"import { Construct } from 'constructs';
|
|
628
|
+
import {
|
|
629
|
+
RestApi as _RestApi,
|
|
630
|
+
RestApiProps as _RestApiProps,
|
|
631
|
+
AccessLogFormat,
|
|
632
|
+
IResource,
|
|
633
|
+
LogGroupLogDestination,
|
|
634
|
+
MethodLoggingLevel,
|
|
635
|
+
} from 'aws-cdk-lib/aws-apigateway';
|
|
636
|
+
import { LogGroup } from 'aws-cdk-lib/aws-logs';
|
|
637
|
+
import { RuntimeConfig } from '../runtime-config.js';
|
|
638
|
+
import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam';
|
|
639
|
+
import { OperationDetails, RestApiIntegration } from './utils.js';
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Properties for creating a RestApi construct.
|
|
643
|
+
*
|
|
644
|
+
* @template TIntegrations - Record mapping operation names to their integrations
|
|
645
|
+
* @template TOperation - String literal type representing operation names
|
|
646
|
+
*/
|
|
647
|
+
export interface RestApiProps<
|
|
648
|
+
TIntegrations extends Record<TOperation, RestApiIntegration>,
|
|
649
|
+
TOperation extends string,
|
|
650
|
+
> extends _RestApiProps {
|
|
651
|
+
/**
|
|
652
|
+
* Unique name for the API, used in runtime configuration
|
|
653
|
+
*/
|
|
654
|
+
readonly apiName: string;
|
|
655
|
+
/**
|
|
656
|
+
* Map of operation names to their API path and HTTP method details
|
|
657
|
+
*/
|
|
658
|
+
readonly operations: Record<TOperation, OperationDetails>;
|
|
659
|
+
/**
|
|
660
|
+
* Map of operation names to their API Gateway integrations
|
|
661
|
+
*/
|
|
662
|
+
readonly integrations: TIntegrations;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* A CDK construct that creates and configures an AWS API Gateway REST API.
|
|
667
|
+
*
|
|
668
|
+
* This class extends the base CDK RestApi with additional functionality:
|
|
669
|
+
* - Type-safe operation and integration management
|
|
670
|
+
* - Automatic resource creation based on path patterns
|
|
671
|
+
* - Integration with runtime configuration for client discovery
|
|
672
|
+
*
|
|
673
|
+
* @template TOperation - String literal type representing operation names
|
|
674
|
+
* @template TIntegrations - Record mapping operation names to their integrations
|
|
675
|
+
*/
|
|
676
|
+
export class RestApi<
|
|
677
|
+
TOperation extends string,
|
|
678
|
+
TIntegrations extends Record<TOperation, RestApiIntegration>,
|
|
679
|
+
> extends Construct {
|
|
680
|
+
/** The underlying CDK RestApi instance */
|
|
681
|
+
public readonly api: _RestApi;
|
|
682
|
+
|
|
683
|
+
/** Map of operation names to their API Gateway integrations */
|
|
684
|
+
public readonly integrations: TIntegrations;
|
|
685
|
+
|
|
686
|
+
constructor(
|
|
687
|
+
scope: Construct,
|
|
688
|
+
id: string,
|
|
689
|
+
{
|
|
690
|
+
apiName,
|
|
691
|
+
operations,
|
|
692
|
+
integrations,
|
|
693
|
+
...props
|
|
694
|
+
}: RestApiProps<TIntegrations, TOperation>,
|
|
695
|
+
) {
|
|
696
|
+
super(scope, id);
|
|
697
|
+
this.integrations = integrations;
|
|
698
|
+
|
|
699
|
+
// Create the API Gateway REST API with logging enabled
|
|
700
|
+
this.api = new _RestApi(this, 'Api', {
|
|
701
|
+
deployOptions: {
|
|
702
|
+
accessLogDestination: new LogGroupLogDestination(
|
|
703
|
+
new LogGroup(this, 'AccessLogs'),
|
|
704
|
+
),
|
|
705
|
+
accessLogFormat: AccessLogFormat.clf(),
|
|
706
|
+
loggingLevel: MethodLoggingLevel.INFO,
|
|
707
|
+
},
|
|
708
|
+
...props,
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
// Create API resources and methods for each operation
|
|
712
|
+
(Object.entries(operations) as [TOperation, OperationDetails][]).map(
|
|
713
|
+
([op, details]) => {
|
|
714
|
+
const resource = this.getOrCreateResource(
|
|
715
|
+
this.api.root,
|
|
716
|
+
(details.path.startsWith('/')
|
|
717
|
+
? details.path.slice(1)
|
|
718
|
+
: details.path
|
|
719
|
+
).split('/'),
|
|
720
|
+
);
|
|
721
|
+
resource.addMethod(
|
|
722
|
+
details.method,
|
|
723
|
+
integrations[op].integration,
|
|
724
|
+
integrations[op].options,
|
|
725
|
+
);
|
|
726
|
+
},
|
|
727
|
+
);
|
|
728
|
+
|
|
729
|
+
// Register the API URL in runtime configuration for client discovery
|
|
730
|
+
RuntimeConfig.ensure(this).config.apis = {
|
|
731
|
+
...RuntimeConfig.ensure(this).config.apis!,
|
|
732
|
+
[apiName]: this.api.url!,
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Recursively creates or retrieves API Gateway resources based on a path pattern.
|
|
738
|
+
*
|
|
739
|
+
* @param resource - The parent API Gateway resource
|
|
740
|
+
* @param pathParts - Array of path segments to create or retrieve
|
|
741
|
+
* @returns The API Gateway resource at the end of the path
|
|
742
|
+
*/
|
|
743
|
+
private getOrCreateResource(
|
|
744
|
+
resource: IResource,
|
|
745
|
+
[nextPathPart, ...pathParts]: string[],
|
|
746
|
+
): IResource {
|
|
747
|
+
if (!nextPathPart) {
|
|
748
|
+
return resource;
|
|
749
|
+
}
|
|
750
|
+
const childResource =
|
|
751
|
+
resource.getResource(nextPathPart) ?? resource.addResource(nextPathPart);
|
|
752
|
+
return this.getOrCreateResource(childResource, pathParts);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* Grants IAM permissions to invoke any method on this API.
|
|
757
|
+
*
|
|
758
|
+
* @param grantee - The IAM principal to grant permissions to
|
|
759
|
+
*/
|
|
760
|
+
public grantInvokeAccess(grantee: IGrantable) {
|
|
761
|
+
Grant.addToPrincipal({
|
|
762
|
+
grantee,
|
|
763
|
+
actions: ['execute-api:Invoke'],
|
|
764
|
+
resourceArns: [this.api.arnForExecuteApi('*', '/*', '*')],
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
"
|
|
769
|
+
`;
|
|
770
|
+
|
|
771
|
+
exports[`fastapi project generator > should set up shared constructs for rest > test-api.ts 1`] = `
|
|
772
|
+
"import { Construct } from 'constructs';
|
|
773
|
+
import * as url from 'url';
|
|
774
|
+
import {
|
|
775
|
+
Code,
|
|
776
|
+
Runtime,
|
|
777
|
+
Function,
|
|
778
|
+
FunctionProps,
|
|
779
|
+
Tracing,
|
|
780
|
+
} from 'aws-cdk-lib/aws-lambda';
|
|
781
|
+
import {
|
|
782
|
+
AuthorizationType,
|
|
783
|
+
Cors,
|
|
784
|
+
LambdaIntegration,
|
|
785
|
+
} from 'aws-cdk-lib/aws-apigateway';
|
|
786
|
+
import { Duration, Stack } from 'aws-cdk-lib';
|
|
787
|
+
import {
|
|
788
|
+
PolicyDocument,
|
|
789
|
+
PolicyStatement,
|
|
790
|
+
Effect,
|
|
791
|
+
AccountPrincipal,
|
|
792
|
+
AnyPrincipal,
|
|
793
|
+
} from 'aws-cdk-lib/aws-iam';
|
|
794
|
+
import {
|
|
795
|
+
IntegrationBuilder,
|
|
796
|
+
RestApiIntegration,
|
|
797
|
+
} from '../../core/api/utils.js';
|
|
798
|
+
import { RestApi } from '../../core/api/rest-api.js';
|
|
799
|
+
import {
|
|
800
|
+
OPERATION_DETAILS,
|
|
801
|
+
Operations,
|
|
802
|
+
} from '../../generated/test-api/metadata.gen.js';
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Properties for creating a TestApi construct
|
|
806
|
+
*
|
|
807
|
+
* @template TIntegrations - Map of operation names to their integrations
|
|
808
|
+
*/
|
|
809
|
+
export interface TestApiProps<
|
|
810
|
+
TIntegrations extends Record<Operations, RestApiIntegration>,
|
|
811
|
+
> {
|
|
812
|
+
/**
|
|
813
|
+
* Map of operation names to their API Gateway integrations
|
|
814
|
+
*/
|
|
815
|
+
integrations: TIntegrations;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* A CDK construct that creates and configures an AWS API Gateway REST API
|
|
820
|
+
* specifically for TestApi.
|
|
821
|
+
* @template TIntegrations - Map of operation names to their integrations
|
|
822
|
+
*/
|
|
823
|
+
export class TestApi<
|
|
824
|
+
TIntegrations extends Record<Operations, RestApiIntegration>,
|
|
825
|
+
> extends RestApi<Operations, TIntegrations> {
|
|
826
|
+
/**
|
|
827
|
+
* Creates default integrations for all operations, which implement each operation as
|
|
828
|
+
* its own individual lambda function.
|
|
829
|
+
*
|
|
830
|
+
* @param scope - The CDK construct scope
|
|
831
|
+
* @returns An IntegrationBuilder with default lambda integrations
|
|
832
|
+
*/
|
|
833
|
+
public static defaultIntegrations = (scope: Construct) => {
|
|
834
|
+
return IntegrationBuilder.rest({
|
|
835
|
+
operations: OPERATION_DETAILS,
|
|
836
|
+
defaultIntegrationOptions: {
|
|
837
|
+
runtime: Runtime.PYTHON_3_12,
|
|
838
|
+
handler: 'test_api.main.handler',
|
|
839
|
+
code: Code.fromAsset(
|
|
840
|
+
url.fileURLToPath(
|
|
841
|
+
new URL(
|
|
842
|
+
'../../../../../../dist/apps/nested/path/test_api/bundle',
|
|
843
|
+
import.meta.url,
|
|
844
|
+
),
|
|
845
|
+
),
|
|
846
|
+
),
|
|
847
|
+
timeout: Duration.seconds(30),
|
|
848
|
+
tracing: Tracing.ACTIVE,
|
|
849
|
+
environment: {
|
|
850
|
+
AWS_CONNECTION_REUSE_ENABLED: '1',
|
|
851
|
+
},
|
|
852
|
+
} satisfies FunctionProps,
|
|
853
|
+
buildDefaultIntegration: (op, props: FunctionProps) => {
|
|
854
|
+
const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
|
|
855
|
+
return { handler, integration: new LambdaIntegration(handler) };
|
|
856
|
+
},
|
|
857
|
+
});
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
constructor(
|
|
861
|
+
scope: Construct,
|
|
862
|
+
id: string,
|
|
863
|
+
props: TestApiProps<TIntegrations>,
|
|
864
|
+
) {
|
|
865
|
+
super(scope, id, {
|
|
866
|
+
apiName: 'TestApi',
|
|
867
|
+
defaultMethodOptions: {
|
|
868
|
+
authorizationType: AuthorizationType.IAM,
|
|
869
|
+
},
|
|
870
|
+
defaultCorsPreflightOptions: {
|
|
871
|
+
allowOrigins: Cors.ALL_ORIGINS,
|
|
872
|
+
allowMethods: Cors.ALL_METHODS,
|
|
873
|
+
},
|
|
874
|
+
policy: new PolicyDocument({
|
|
875
|
+
statements: [
|
|
876
|
+
// Here we grant any AWS credentials from the account that the project is deployed in to call the api.
|
|
877
|
+
// Machine to machine fine-grained access can be defined here using more specific principals (eg roles or
|
|
878
|
+
// users) and resources (eg which api paths may be invoked by which principal) if required.
|
|
879
|
+
new PolicyStatement({
|
|
880
|
+
effect: Effect.ALLOW,
|
|
881
|
+
principals: [new AccountPrincipal(Stack.of(scope).account)],
|
|
882
|
+
actions: ['execute-api:Invoke'],
|
|
883
|
+
resources: ['execute-api:/*'],
|
|
884
|
+
}),
|
|
885
|
+
// Open up OPTIONS to allow browsers to make unauthenticated preflight requests
|
|
886
|
+
new PolicyStatement({
|
|
887
|
+
effect: Effect.ALLOW,
|
|
888
|
+
principals: [new AnyPrincipal()],
|
|
889
|
+
actions: ['execute-api:Invoke'],
|
|
890
|
+
resources: ['execute-api:/*/OPTIONS/*'],
|
|
891
|
+
}),
|
|
892
|
+
],
|
|
893
|
+
}),
|
|
894
|
+
operations: OPERATION_DETAILS,
|
|
895
|
+
...props,
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
"
|
|
900
|
+
`;
|
|
901
|
+
|
|
902
|
+
exports[`fastapi project generator > should set up shared constructs for rest > utils.ts 1`] = `
|
|
903
|
+
"import { Integration, MethodOptions } from 'aws-cdk-lib/aws-apigateway';
|
|
904
|
+
import {
|
|
905
|
+
HttpRouteIntegration,
|
|
906
|
+
AddRoutesOptions,
|
|
907
|
+
} from 'aws-cdk-lib/aws-apigatewayv2';
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* Type representing applicable HTTP Methods in API Gateway
|
|
911
|
+
*/
|
|
912
|
+
export type HttpMethod =
|
|
913
|
+
| 'ANY'
|
|
914
|
+
| 'DELETE'
|
|
915
|
+
| 'GET'
|
|
916
|
+
| 'HEAD'
|
|
917
|
+
| 'OPTIONS'
|
|
918
|
+
| 'PATCH'
|
|
919
|
+
| 'POST'
|
|
920
|
+
| 'PUT';
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* Defines the details of an API operation.
|
|
924
|
+
*/
|
|
925
|
+
export interface OperationDetails {
|
|
926
|
+
/**
|
|
927
|
+
* The URL path for the operation
|
|
928
|
+
*/
|
|
929
|
+
path: string;
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* The HTTP method for the operation
|
|
933
|
+
*/
|
|
934
|
+
method: HttpMethod;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Represents an API Gateway REST API integration that can be attached to API methods.
|
|
939
|
+
*/
|
|
940
|
+
export interface RestApiIntegration {
|
|
941
|
+
integration: Integration;
|
|
942
|
+
options?: MethodOptions;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* Represents an API Gateway HTTP API that can be attached to API methods.
|
|
947
|
+
*/
|
|
948
|
+
export interface HttpApiIntegration {
|
|
949
|
+
integration: HttpRouteIntegration;
|
|
950
|
+
options?: Omit<AddRoutesOptions, 'path' | 'methods' | 'integration'>;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Options for constructing an IntegrationBuilder
|
|
955
|
+
*/
|
|
956
|
+
export interface IntegrationBuilderProps<
|
|
957
|
+
TOperation extends string,
|
|
958
|
+
TBaseIntegration,
|
|
959
|
+
TDefaultIntegrationProps extends object,
|
|
960
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
961
|
+
> {
|
|
962
|
+
/** Map of operation names to their API path and HTTP method details */
|
|
963
|
+
operations: Record<TOperation, OperationDetails>;
|
|
964
|
+
|
|
965
|
+
/** Default configuration options for integrations */
|
|
966
|
+
defaultIntegrationOptions: TDefaultIntegrationProps;
|
|
967
|
+
|
|
968
|
+
/** Function to create a default integration for an operation */
|
|
969
|
+
buildDefaultIntegration: (
|
|
970
|
+
op: TOperation,
|
|
971
|
+
props: TDefaultIntegrationProps,
|
|
972
|
+
) => TDefaultIntegration;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* A builder class for creating API integrations with flexible configuration options.
|
|
977
|
+
*
|
|
978
|
+
* This class implements the builder pattern to create a set of API integrations
|
|
979
|
+
* with support for default configurations and selective overrides.
|
|
980
|
+
*
|
|
981
|
+
* @template TOperation - String literal type representing operation names
|
|
982
|
+
* @template TBaseIntegration - Base type for all integrations
|
|
983
|
+
* @template TIntegrations - Record mapping operation names to their integrations
|
|
984
|
+
* @template TDefaultIntegrationProps - Type for default integration properties
|
|
985
|
+
* @template TDefaultIntegration - Type for default integration implementation
|
|
986
|
+
*/
|
|
987
|
+
export class IntegrationBuilder<
|
|
988
|
+
TOperation extends string,
|
|
989
|
+
TBaseIntegration,
|
|
990
|
+
TIntegrations extends Record<TOperation, TBaseIntegration>,
|
|
991
|
+
TDefaultIntegrationProps extends object,
|
|
992
|
+
TDefaultIntegration extends TBaseIntegration,
|
|
993
|
+
> {
|
|
994
|
+
/** Options for the integration builder */
|
|
995
|
+
private options: IntegrationBuilderProps<
|
|
996
|
+
TOperation,
|
|
997
|
+
TBaseIntegration,
|
|
998
|
+
TDefaultIntegrationProps,
|
|
999
|
+
TDefaultIntegration
|
|
1000
|
+
>;
|
|
1001
|
+
|
|
1002
|
+
/** Map of operation names to their custom integrations */
|
|
1003
|
+
private integrations: Partial<TIntegrations> = {};
|
|
1004
|
+
|
|
1005
|
+
/**
|
|
1006
|
+
* Create an Integration Builder for an HTTP API
|
|
1007
|
+
*/
|
|
1008
|
+
public static http = <
|
|
1009
|
+
TOperation extends string,
|
|
1010
|
+
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
1011
|
+
TDefaultIntegrationProps extends object,
|
|
1012
|
+
TDefaultIntegration extends HttpApiIntegration,
|
|
1013
|
+
>(
|
|
1014
|
+
options: IntegrationBuilderProps<
|
|
1015
|
+
TOperation,
|
|
1016
|
+
HttpApiIntegration,
|
|
1017
|
+
TDefaultIntegrationProps,
|
|
1018
|
+
TDefaultIntegration
|
|
1019
|
+
>,
|
|
1020
|
+
) => {
|
|
1021
|
+
return new IntegrationBuilder<
|
|
1022
|
+
TOperation,
|
|
1023
|
+
HttpApiIntegration,
|
|
1024
|
+
TIntegrations,
|
|
1025
|
+
TDefaultIntegrationProps,
|
|
1026
|
+
TDefaultIntegration
|
|
1027
|
+
>(options);
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* Create an Integration Builder for a REST API
|
|
1032
|
+
*/
|
|
1033
|
+
public static rest = <
|
|
1034
|
+
TOperation extends string,
|
|
1035
|
+
TIntegrations extends Record<TOperation, TDefaultIntegration>,
|
|
1036
|
+
TDefaultIntegrationProps extends object,
|
|
1037
|
+
TDefaultIntegration extends RestApiIntegration,
|
|
1038
|
+
>(
|
|
1039
|
+
options: IntegrationBuilderProps<
|
|
1040
|
+
TOperation,
|
|
1041
|
+
RestApiIntegration,
|
|
1042
|
+
TDefaultIntegrationProps,
|
|
1043
|
+
TDefaultIntegration
|
|
1044
|
+
>,
|
|
1045
|
+
) => {
|
|
1046
|
+
return new IntegrationBuilder<
|
|
1047
|
+
TOperation,
|
|
1048
|
+
RestApiIntegration,
|
|
1049
|
+
TIntegrations,
|
|
1050
|
+
TDefaultIntegrationProps,
|
|
1051
|
+
TDefaultIntegration
|
|
1052
|
+
>(options);
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
private constructor(
|
|
1056
|
+
options: IntegrationBuilderProps<
|
|
1057
|
+
TOperation,
|
|
1058
|
+
TBaseIntegration,
|
|
1059
|
+
TDefaultIntegrationProps,
|
|
1060
|
+
TDefaultIntegration
|
|
1061
|
+
>,
|
|
1062
|
+
) {
|
|
1063
|
+
this.options = options;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* Overrides default integrations with custom implementations for specific operations.
|
|
1068
|
+
*
|
|
1069
|
+
* @param overrides - Map of operation names to their custom integration implementations
|
|
1070
|
+
* @returns The builder instance with updated type information reflecting the overrides
|
|
1071
|
+
*/
|
|
1072
|
+
public withOverrides<
|
|
1073
|
+
TOverrideIntegrations extends Partial<Record<TOperation, TBaseIntegration>>,
|
|
1074
|
+
>(overrides: TOverrideIntegrations) {
|
|
1075
|
+
this.integrations = { ...this.integrations, ...overrides };
|
|
1076
|
+
// Re-type to include the overridden integration types
|
|
1077
|
+
return this as unknown as IntegrationBuilder<
|
|
1078
|
+
TOperation,
|
|
1079
|
+
TBaseIntegration,
|
|
1080
|
+
Omit<TIntegrations, keyof TOverrideIntegrations> & TOverrideIntegrations,
|
|
1081
|
+
TDefaultIntegrationProps,
|
|
1082
|
+
TDefaultIntegration
|
|
1083
|
+
>;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* Updates the default integration options that will be used for operations
|
|
1088
|
+
* without custom overrides.
|
|
1089
|
+
*
|
|
1090
|
+
* @param options - Partial default integration options to merge with existing defaults
|
|
1091
|
+
* @returns The builder instance
|
|
1092
|
+
*/
|
|
1093
|
+
public withDefaultOptions(options: Partial<TDefaultIntegrationProps>) {
|
|
1094
|
+
this.options.defaultIntegrationOptions = {
|
|
1095
|
+
...this.options.defaultIntegrationOptions,
|
|
1096
|
+
...options,
|
|
1097
|
+
};
|
|
1098
|
+
return this;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Builds and returns the complete set of integrations.
|
|
1103
|
+
*
|
|
1104
|
+
* This method creates the final integration map by:
|
|
1105
|
+
* 1. Including all custom overrides provided via withOverrides()
|
|
1106
|
+
* 2. Creating default integrations for any operations without custom overrides
|
|
1107
|
+
*
|
|
1108
|
+
* @returns A complete map of operation names to their integrations
|
|
1109
|
+
*/
|
|
1110
|
+
public build(): TIntegrations {
|
|
1111
|
+
return {
|
|
1112
|
+
...this.integrations,
|
|
1113
|
+
...Object.fromEntries(
|
|
1114
|
+
(Object.keys(this.options.operations) as TOperation[])
|
|
1115
|
+
.filter(
|
|
1116
|
+
(op) => !this.integrations[op as keyof typeof this.integrations],
|
|
1117
|
+
)
|
|
1118
|
+
.map((op) => [
|
|
1119
|
+
op,
|
|
1120
|
+
this.options.buildDefaultIntegration(
|
|
1121
|
+
op,
|
|
1122
|
+
this.options.defaultIntegrationOptions,
|
|
1123
|
+
),
|
|
1124
|
+
]),
|
|
1125
|
+
),
|
|
1126
|
+
} as unknown as TIntegrations;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
"
|
|
1130
|
+
`;
|