@aws/nx-plugin 0.104.1 → 0.106.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.
Files changed (51) hide show
  1. package/LICENSE-THIRD-PARTY +406 -436
  2. package/package.json +12 -12
  3. package/src/infra/app/__snapshots__/generator.spec.ts.snap +21 -21
  4. package/src/mcp-server/tools/create-workspace-command.js +9 -5
  5. package/src/mcp-server/tools/create-workspace-command.js.map +1 -1
  6. package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +438 -0
  7. package/src/open-api/ts-client/files/client.gen.ts.template +20 -0
  8. package/src/open-api/utils/codegen-data/languages.js +7 -3
  9. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  10. package/src/open-api/utils/normalise.js +17 -0
  11. package/src/open-api/utils/normalise.js.map +1 -1
  12. package/src/preset/__snapshots__/generator.spec.ts.snap +4 -4
  13. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +4 -4
  14. package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +9 -9
  15. package/src/py/strands-agent/react-connection/__snapshots__/generator.spec.ts.snap +129 -4
  16. package/src/py/strands-agent/react-connection/serve-local.js +1 -1
  17. package/src/py/strands-agent/react-connection/serve-local.js.map +1 -1
  18. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +4 -1
  19. package/src/ts/lib/__snapshots__/generator.spec.ts.snap +3 -1
  20. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +3 -3
  21. package/src/ts/mcp-server/generator.js +1 -0
  22. package/src/ts/mcp-server/generator.js.map +1 -1
  23. package/src/ts/react-website/agui/files/cloudscape/src/components/copilot/CloudscapeAssistantMessage.tsx.template +71 -0
  24. package/src/ts/react-website/agui/files/cloudscape/src/components/copilot/CloudscapeChatInput.tsx.template +65 -0
  25. package/src/ts/react-website/agui/files/cloudscape/src/components/copilot/CloudscapeCursor.tsx.template +10 -0
  26. package/src/ts/react-website/agui/files/cloudscape/src/components/copilot/CloudscapeUserMessage.tsx.template +42 -0
  27. package/src/ts/react-website/agui/files/cloudscape/src/components/copilot/copilot.css.template +128 -0
  28. package/src/ts/react-website/agui/files/cloudscape/src/components/copilot/index.tsx.template +46 -0
  29. package/src/ts/react-website/agui/files/{src → common/src}/components/AguiProvider.tsx.template +10 -2
  30. package/src/ts/react-website/agui/files/default/src/components/copilot/index.tsx.template +5 -0
  31. package/src/ts/react-website/agui/files/shadcn/src/components/copilot/ShadcnAssistantMessage.tsx.template +71 -0
  32. package/src/ts/react-website/agui/files/shadcn/src/components/copilot/ShadcnChatInput.tsx.template +117 -0
  33. package/src/ts/react-website/agui/files/shadcn/src/components/copilot/ShadcnCursor.tsx.template +23 -0
  34. package/src/ts/react-website/agui/files/shadcn/src/components/copilot/ShadcnUserMessage.tsx.template +49 -0
  35. package/src/ts/react-website/agui/files/shadcn/src/components/copilot/copilot.css.template +116 -0
  36. package/src/ts/react-website/agui/files/shadcn/src/components/copilot/index.tsx.template +46 -0
  37. package/src/ts/react-website/agui/generator.d.ts +3 -0
  38. package/src/ts/react-website/agui/generator.js +28 -1
  39. package/src/ts/react-website/agui/generator.js.map +1 -1
  40. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +42 -38
  41. package/src/ts/strands-agent/__snapshots__/generator.spec.ts.snap +1 -1
  42. package/src/ts/strands-agent/generator.js +1 -0
  43. package/src/ts/strands-agent/generator.js.map +1 -1
  44. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +1 -1
  45. package/src/utils/files/common/shadcn/src/components/ui/avatar.tsx.template +53 -0
  46. package/src/utils/files/common/shadcn/src/components/ui/textarea.tsx.template +18 -0
  47. package/src/utils/files/website/hooks/sigv4/useSigV4.tsx.template +4 -1
  48. package/src/utils/versions.d.ts +59 -58
  49. package/src/utils/versions.js +58 -57
  50. package/src/utils/versions.js.map +1 -1
  51. /package/src/ts/react-website/agui/files/{src → common/src}/hooks/useAgui__agentNameClassName__.tsx.template +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin",
3
- "version": "0.104.1",
3
+ "version": "0.106.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -19,8 +19,8 @@
19
19
  },
20
20
  "generators": "./generators.json",
21
21
  "peerDependencies": {
22
- "nx": "22.6.5",
23
- "prettier": "3.8.2"
22
+ "nx": "22.7.0",
23
+ "prettier": "3.8.3"
24
24
  },
25
25
  "dependencies": {
26
26
  "@apidevtools/swagger-parser": "12.1.0",
@@ -28,12 +28,12 @@
28
28
  "@hey-api/openapi-ts": "0.64.13",
29
29
  "@iarna/toml": "2.2.5",
30
30
  "@modelcontextprotocol/sdk": "1.29.0",
31
- "@nx/devkit": "22.6.5",
32
- "@nx/eslint": "22.6.5",
33
- "@nx/js": "22.6.5",
34
- "@nx/react": "22.6.5",
35
- "@nx/vite": "22.6.5",
36
- "@nxlv/python": "22.1.1",
31
+ "@nx/devkit": "22.7.0",
32
+ "@nx/eslint": "22.7.0",
33
+ "@nx/js": "22.7.0",
34
+ "@nx/react": "22.7.0",
35
+ "@nx/vite": "22.7.0",
36
+ "@nxlv/python": "22.1.3",
37
37
  "@phenomnomnominal/tsquery": "6.2.0",
38
38
  "enquirer": "2.4.1",
39
39
  "fast-glob": "3.3.3",
@@ -46,9 +46,9 @@
46
46
  "minimatch": "10.2.5",
47
47
  "openapi-types": "12.1.3",
48
48
  "pip-requirements-js": "1.0.3",
49
- "typescript": "6.0.2",
50
- "vite": "8.0.8",
51
- "vitest": "4.1.4",
49
+ "typescript": "6.0.3",
50
+ "vite": "8.0.10",
51
+ "vitest": "4.1.5",
52
52
  "zod": "4.3.6"
53
53
  },
54
54
  "types": "./src/index.d.ts"
@@ -2,8 +2,8 @@
2
2
 
3
3
  exports[`infra generator > should add required dependencies to package.json > dependencies 1`] = `
4
4
  {
5
- "aws-cdk": "2.1118.0",
6
- "aws-cdk-lib": "2.248.0",
5
+ "aws-cdk": "2.1119.0",
6
+ "aws-cdk-lib": "2.251.0",
7
7
  "constructs": "10.6.0",
8
8
  "esbuild": "0.28.0",
9
9
  "source-map-support": "0.5.21",
@@ -13,60 +13,60 @@ exports[`infra generator > should add required dependencies to package.json > de
13
13
  exports[`infra generator > should add required dependencies to package.json > dev-dependencies 1`] = `
14
14
  {
15
15
  "@eslint/js": "^9.8.0",
16
- "@nx/eslint": "22.6.5",
17
- "@nx/eslint-plugin": "22.6.5",
18
- "@nx/js": "22.6.5",
19
- "@nx/vitest": "22.6.5",
16
+ "@nx/eslint": "22.7.0",
17
+ "@nx/eslint-plugin": "22.7.0",
18
+ "@nx/js": "22.7.0",
19
+ "@nx/vitest": "22.7.0",
20
20
  "@swc-node/register": "~1.11.1",
21
21
  "@swc/core": "~1.15.5",
22
22
  "@swc/helpers": "~0.5.18",
23
23
  "@types/node": "25.6.0",
24
- "@vitest/coverage-v8": "4.1.4",
24
+ "@vitest/coverage-v8": "4.1.5",
25
25
  "eslint": "^9.8.0",
26
26
  "eslint-config-prettier": "^10.0.0",
27
27
  "eslint-plugin-prettier": "5.5.5",
28
28
  "jsdom": "^27.1.0",
29
29
  "jsonc-eslint-parser": "3.1.0",
30
- "prettier": "3.8.2",
30
+ "prettier": "3.8.3",
31
31
  "tsx": "4.21.0",
32
32
  "typescript": "~5.9.2",
33
33
  "typescript-eslint": "^8.40.0",
34
34
  "vite": "8.0.8",
35
- "vitest": "4.1.4",
35
+ "vitest": "4.1.5",
36
36
  }
37
37
  `;
38
38
 
39
39
  exports[`infra generator > should add required dependencies to package.json > package-json 1`] = `
40
40
  {
41
41
  "dependencies": {
42
- "aws-cdk": "2.1118.0",
43
- "aws-cdk-lib": "2.248.0",
42
+ "aws-cdk": "2.1119.0",
43
+ "aws-cdk-lib": "2.251.0",
44
44
  "constructs": "10.6.0",
45
45
  "esbuild": "0.28.0",
46
46
  "source-map-support": "0.5.21",
47
47
  },
48
48
  "devDependencies": {
49
49
  "@eslint/js": "^9.8.0",
50
- "@nx/eslint": "22.6.5",
51
- "@nx/eslint-plugin": "22.6.5",
52
- "@nx/js": "22.6.5",
53
- "@nx/vitest": "22.6.5",
50
+ "@nx/eslint": "22.7.0",
51
+ "@nx/eslint-plugin": "22.7.0",
52
+ "@nx/js": "22.7.0",
53
+ "@nx/vitest": "22.7.0",
54
54
  "@swc-node/register": "~1.11.1",
55
55
  "@swc/core": "~1.15.5",
56
56
  "@swc/helpers": "~0.5.18",
57
57
  "@types/node": "25.6.0",
58
- "@vitest/coverage-v8": "4.1.4",
58
+ "@vitest/coverage-v8": "4.1.5",
59
59
  "eslint": "^9.8.0",
60
60
  "eslint-config-prettier": "^10.0.0",
61
61
  "eslint-plugin-prettier": "5.5.5",
62
62
  "jsdom": "^27.1.0",
63
63
  "jsonc-eslint-parser": "3.1.0",
64
- "prettier": "3.8.2",
64
+ "prettier": "3.8.3",
65
65
  "tsx": "4.21.0",
66
66
  "typescript": "~5.9.2",
67
67
  "typescript-eslint": "^8.40.0",
68
68
  "vite": "8.0.8",
69
- "vitest": "4.1.4",
69
+ "vitest": "4.1.5",
70
70
  },
71
71
  "name": "@proj/source",
72
72
  "type": "module",
@@ -84,7 +84,7 @@ exports[`infra generator > should configure Checkov target correctly > checkov-t
84
84
  "{workspaceRoot}/dist/{projectRoot}/cdk.out",
85
85
  ],
86
86
  "options": {
87
- "command": "uvx --from checkov==3.2.519 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
87
+ "command": "uvx --from checkov==3.2.525 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
88
88
  },
89
89
  "outputs": [
90
90
  "{workspaceRoot}/dist/{projectRoot}/checkov",
@@ -177,7 +177,7 @@ exports[`infra generator > should configure project.json with correct targets >
177
177
  "{workspaceRoot}/dist/{projectRoot}/cdk.out",
178
178
  ],
179
179
  "options": {
180
- "command": "uvx --from checkov==3.2.519 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
180
+ "command": "uvx --from checkov==3.2.525 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
181
181
  },
182
182
  "outputs": [
183
183
  "{workspaceRoot}/dist/{projectRoot}/checkov",
@@ -739,7 +739,7 @@ exports[`infra generator > should handle custom project names correctly > custom
739
739
  "{workspaceRoot}/dist/{projectRoot}/cdk.out",
740
740
  ],
741
741
  "options": {
742
- "command": "uvx --from checkov==3.2.519 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
742
+ "command": "uvx --from checkov==3.2.525 checkov --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
743
743
  },
744
744
  "outputs": [
745
745
  "{workspaceRoot}/dist/{projectRoot}/checkov",
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addCreateWorkspaceCommandTool = void 0;
4
- const zod_1 = require("zod");
5
4
  const schema_1 = require("../schema");
6
5
  const iac_providers_1 = require("../../utils/iac-providers");
7
6
  const commands_1 = require("../../utils/commands");
@@ -12,20 +11,25 @@ const addCreateWorkspaceCommandTool = (server) => {
12
11
  server.registerTool('create-workspace-command', {
13
12
  description: 'Tool to discover how to create a workspace to start a new project.',
14
13
  inputSchema: {
15
- workspaceName: zod_1.z.string(),
16
14
  packageManager: schema_1.PackageManagerSchema,
17
15
  },
18
- }, ({ workspaceName, packageManager }) => ({
16
+ }, ({ packageManager }) => ({
19
17
  content: [
20
18
  {
21
19
  type: 'text',
22
20
  text: `Run the following command to create a workspace:
23
21
 
24
22
  \`\`\`bash
25
- ${(0, commands_1.buildCreateNxWorkspaceCommand)(packageManager, workspaceName)} --no-interactive
23
+ ${(0, commands_1.buildCreateNxWorkspaceCommand)(packageManager, '<workspace-name>')} --no-interactive
26
24
  \`\`\`
27
25
 
28
- This will create a new workspace within the ${workspaceName} directory.
26
+ This will create a new workspace within the \`<workspace-name>\` directory.
27
+
28
+ If you are already inside an empty directory intended for this project, you can pass \`.\` as the workspace name to create the workspace in the current directory:
29
+
30
+ \`\`\`bash
31
+ ${(0, commands_1.buildCreateNxWorkspaceCommand)(packageManager, '.')} --no-interactive
32
+ \`\`\`
29
33
 
30
34
  Note that this will prompt for an Infrastructure as Code provider (${iac_providers_1.IAC_PROVIDERS.join(', ')}).
31
35
  If you know the preferred option, pass ${iac_providers_1.IAC_PROVIDERS.map((iac) => `\`--iacProvider=${iac}\``).join(' or ')} to the above command to skip the prompt.
@@ -1 +1 @@
1
- {"version":3,"file":"create-workspace-command.js","sourceRoot":"","sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/create-workspace-command.ts"],"names":[],"mappings":";;;AAKA,6BAAwB;AACxB,sCAAiD;AACjD,6DAA0D;AAC1D,mDAAqE;AAErE;;GAEG;AACI,MAAM,6BAA6B,GAAG,CAAC,MAAiB,EAAE,EAAE;IACjE,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,WAAW,EACT,oEAAoE;QACtE,WAAW,EAAE;YACX,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE;YACzB,cAAc,EAAE,6BAAoB;SACrC;KACF,EACD,CAAC,EAAE,aAAa,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC;QACtC,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE;;;EAGd,IAAA,wCAA6B,EAAC,cAAc,EAAE,aAAa,CAAC;;;8CAGhB,aAAa;;qEAEU,6BAAa,CAAC,IAAI,CAAC,IAAI,CAAC;yCACpD,6BAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;GACzG;aACM;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC,CAAC;AA9BW,QAAA,6BAA6B,iCA8BxC"}
1
+ {"version":3,"file":"create-workspace-command.js","sourceRoot":"","sources":["../../../../../../packages/nx-plugin/src/mcp-server/tools/create-workspace-command.ts"],"names":[],"mappings":";;;AAKA,sCAAiD;AACjD,6DAA0D;AAC1D,mDAAqE;AAErE;;GAEG;AACI,MAAM,6BAA6B,GAAG,CAAC,MAAiB,EAAE,EAAE;IACjE,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,WAAW,EACT,oEAAoE;QACtE,WAAW,EAAE;YACX,cAAc,EAAE,6BAAoB;SACrC;KACF,EACD,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC;QACvB,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE;;;EAGd,IAAA,wCAA6B,EAAC,cAAc,EAAE,kBAAkB,CAAC;;;;;;;;EAQjE,IAAA,wCAA6B,EAAC,cAAc,EAAE,GAAG,CAAC;;;qEAGiB,6BAAa,CAAC,IAAI,CAAC,IAAI,CAAC;yCACpD,6BAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;GACzG;aACM;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC,CAAC;AAnCW,QAAA,6BAA6B,iCAmCxC"}
@@ -354,6 +354,254 @@ export class TestApi {
354
354
  "
355
355
  `;
356
356
 
357
+ exports[`openApiTsClientGenerator - composite schemas > should handle FastAPI-style discriminated unions with string const (Literal) 1`] = `
358
+ "export type Circle = {
359
+ kind: string;
360
+ radius: number;
361
+ };
362
+ export type Kind = 'circle';
363
+ export type Kind1 = 'square';
364
+ export type ShapesOut = {
365
+ canonical: ShapesOutCanonical;
366
+ };
367
+ export type ShapesOutCanonical = Circle | Square;
368
+ export type Square = {
369
+ kind: string;
370
+ side: number;
371
+ };
372
+ export type GetShapesError = never;
373
+ "
374
+ `;
375
+
376
+ exports[`openApiTsClientGenerator - composite schemas > should handle FastAPI-style discriminated unions with string const (Literal) 2`] = `
377
+ "import type {
378
+ Circle,
379
+ ShapesOut,
380
+ ShapesOutCanonical,
381
+ Square,
382
+ } from './types.gen.js';
383
+
384
+ /**
385
+ * Utility for serialisation and deserialisation of API types.
386
+ */
387
+ export class $IO {
388
+ protected static $mapValues = (data: any, fn: (item: any) => any) =>
389
+ Object.fromEntries(Object.entries(data).map(([k, v]) => [k, fn(v)]));
390
+
391
+ public static Circle = {
392
+ toJson: (model: Circle): any => {
393
+ if (model === undefined || model === null) {
394
+ return model;
395
+ }
396
+ return {
397
+ ...(model.kind === undefined
398
+ ? {}
399
+ : {
400
+ kind: model.kind,
401
+ }),
402
+ ...(model.radius === undefined
403
+ ? {}
404
+ : {
405
+ radius: model.radius,
406
+ }),
407
+ };
408
+ },
409
+ fromJson: (json: any): Circle => {
410
+ if (json === undefined || json === null) {
411
+ return json;
412
+ }
413
+ return {
414
+ kind: json['kind'],
415
+ radius: json['radius'],
416
+ };
417
+ },
418
+ };
419
+
420
+ public static ShapesOut = {
421
+ toJson: (model: ShapesOut): any => {
422
+ if (model === undefined || model === null) {
423
+ return model;
424
+ }
425
+ return {
426
+ ...(model.canonical === undefined
427
+ ? {}
428
+ : {
429
+ canonical: $IO.ShapesOutCanonical.toJson(model.canonical),
430
+ }),
431
+ };
432
+ },
433
+ fromJson: (json: any): ShapesOut => {
434
+ if (json === undefined || json === null) {
435
+ return json;
436
+ }
437
+ return {
438
+ canonical: $IO.ShapesOutCanonical.fromJson(json['canonical']),
439
+ };
440
+ },
441
+ };
442
+
443
+ public static ShapesOutCanonical = {
444
+ toJson: (model: ShapesOutCanonical): any => {
445
+ if (model === undefined || model === null) {
446
+ return model;
447
+ }
448
+ return {
449
+ ...$IO.Circle.toJson(model as Circle),
450
+ ...$IO.Square.toJson(model as Square),
451
+ };
452
+ },
453
+ fromJson: (json: any): ShapesOutCanonical => {
454
+ if (json === undefined || json === null) {
455
+ return json;
456
+ }
457
+ return {
458
+ ...$IO.Circle.fromJson(json),
459
+ ...$IO.Square.fromJson(json),
460
+ };
461
+ },
462
+ };
463
+
464
+ public static Square = {
465
+ toJson: (model: Square): any => {
466
+ if (model === undefined || model === null) {
467
+ return model;
468
+ }
469
+ return {
470
+ ...(model.kind === undefined
471
+ ? {}
472
+ : {
473
+ kind: model.kind,
474
+ }),
475
+ ...(model.side === undefined
476
+ ? {}
477
+ : {
478
+ side: model.side,
479
+ }),
480
+ };
481
+ },
482
+ fromJson: (json: any): Square => {
483
+ if (json === undefined || json === null) {
484
+ return json;
485
+ }
486
+ return {
487
+ kind: json['kind'],
488
+ side: json['side'],
489
+ };
490
+ },
491
+ };
492
+ }
493
+
494
+ /**
495
+ * Client configuration for TestApi
496
+ */
497
+ export interface TestApiConfig {
498
+ /**
499
+ * Base URL for the API
500
+ */
501
+ url: string;
502
+ /**
503
+ * Custom instance of fetch. By default the global 'fetch' is used.
504
+ * You can override this to add custom middleware for use cases such as adding authentication headers.
505
+ */
506
+ fetch?: typeof fetch;
507
+ /**
508
+ * Additional configuration
509
+ */
510
+ options?: {
511
+ /**
512
+ * By default, the client will add a Content-Type header, set to the media type defined for
513
+ * the request in the OpenAPI specification.
514
+ * Set this to false to omit this header.
515
+ */
516
+ omitContentTypeHeader?: boolean;
517
+ };
518
+ }
519
+
520
+ /**
521
+ * API Client for TestApi
522
+ */
523
+ export class TestApi {
524
+ private $config: TestApiConfig;
525
+
526
+ constructor(config: TestApiConfig) {
527
+ this.$config = config;
528
+
529
+ this.getShapes = this.getShapes.bind(this);
530
+ }
531
+
532
+ private $url = (
533
+ path: string,
534
+ pathParameters: { [key: string]: any },
535
+ queryParameters: { [key: string]: any },
536
+ collectionFormats?: { [key: string]: 'multi' | 'csv' },
537
+ ): string => {
538
+ const baseUrl = this.$config.url.endsWith('/')
539
+ ? this.$config.url.slice(0, -1)
540
+ : this.$config.url;
541
+ const pathWithParameters = Object.entries(pathParameters).reduce(
542
+ (withParams, [key, value]) =>
543
+ withParams.replace(\`{\${key}}\`, encodeURIComponent(\`\${value}\`)),
544
+ path,
545
+ );
546
+ const queryString = Object.entries(queryParameters)
547
+ .map(([key, value]) => {
548
+ if (Array.isArray(value) && collectionFormats?.[key] === 'multi') {
549
+ return value
550
+ .map(
551
+ (v) => \`\${encodeURIComponent(key)}=\${encodeURIComponent(\`\${v}\`)}\`,
552
+ )
553
+ .join('&');
554
+ }
555
+ return \`\${encodeURIComponent(key)}=\${encodeURIComponent(Array.isArray(value) ? value.map(String).join(',') : String(value))}\`;
556
+ })
557
+ .join('&');
558
+ return (
559
+ baseUrl + pathWithParameters + (queryString ? \`?\${queryString}\` : '')
560
+ );
561
+ };
562
+
563
+ private $headers = (
564
+ headerParameters: { [key: string]: any },
565
+ collectionFormats?: { [key: string]: 'multi' | 'csv' },
566
+ ): [string, string][] => {
567
+ return Object.entries(headerParameters).flatMap(([key, value]) => {
568
+ if (Array.isArray(value) && collectionFormats?.[key] === 'multi') {
569
+ return value.map((v) => [key, String(v)]) as [string, string][];
570
+ }
571
+ return [[key, String(value)]];
572
+ });
573
+ };
574
+
575
+ private $fetch: typeof fetch = (...args) =>
576
+ (this.$config.fetch ?? fetch)(...args);
577
+
578
+ public async getShapes(): Promise<ShapesOut> {
579
+ const pathParameters: { [key: string]: any } = {};
580
+ const queryParameters: { [key: string]: any } = {};
581
+ const headerParameters: { [key: string]: any } = {};
582
+
583
+ const body = undefined;
584
+
585
+ const response = await this.$fetch(
586
+ this.$url('/shapes', pathParameters, queryParameters),
587
+ {
588
+ headers: this.$headers(headerParameters),
589
+ method: 'GET',
590
+ body,
591
+ },
592
+ );
593
+
594
+ if (response.status === 200) {
595
+ return $IO.ShapesOut.fromJson(await response.json());
596
+ }
597
+ throw new Error(
598
+ \`Unknown response status \${response.status} returned by API\`,
599
+ );
600
+ }
601
+ }
602
+ "
603
+ `;
604
+
357
605
  exports[`openApiTsClientGenerator - composite schemas > should handle anyOf with any type 1`] = `
358
606
  "export type TestAnyOfAny200Response = {
359
607
  result?: string;
@@ -1920,3 +2168,193 @@ export class TestApi {
1920
2168
  }
1921
2169
  "
1922
2170
  `;
2171
+
2172
+ exports[`openApiTsClientGenerator - composite schemas > should round-trip Date through a composite alias using instanceof checks 1`] = `
2173
+ "export type MaybeDate = Date | MaybeDateOneOf;
2174
+ export type MaybeDateOneOf = {
2175
+ marker: string;
2176
+ };
2177
+
2178
+ export type PostMaybeDateRequest = MaybeDate;
2179
+ export type PostMaybeDateError = never;
2180
+ "
2181
+ `;
2182
+
2183
+ exports[`openApiTsClientGenerator - composite schemas > should round-trip Date through a composite alias using instanceof checks 2`] = `
2184
+ "import type {
2185
+ MaybeDate,
2186
+ MaybeDateOneOf,
2187
+ PostMaybeDateRequest,
2188
+ } from './types.gen.js';
2189
+
2190
+ /**
2191
+ * Utility for serialisation and deserialisation of API types.
2192
+ */
2193
+ export class $IO {
2194
+ protected static $mapValues = (data: any, fn: (item: any) => any) =>
2195
+ Object.fromEntries(Object.entries(data).map(([k, v]) => [k, fn(v)]));
2196
+
2197
+ public static MaybeDate = {
2198
+ toJson: (model: MaybeDate): any => {
2199
+ if (model === undefined || model === null) {
2200
+ return model;
2201
+ }
2202
+ if (model instanceof Date) {
2203
+ return model.toISOString();
2204
+ }
2205
+ return {
2206
+ ...$IO.MaybeDateOneOf.toJson(model as MaybeDateOneOf),
2207
+ };
2208
+ },
2209
+ fromJson: (json: any): MaybeDate => {
2210
+ if (json === undefined || json === null) {
2211
+ return json;
2212
+ }
2213
+ if (typeof json === 'string' || json instanceof Date) {
2214
+ return new Date(json);
2215
+ }
2216
+ return {
2217
+ ...$IO.MaybeDateOneOf.fromJson(json),
2218
+ };
2219
+ },
2220
+ };
2221
+
2222
+ public static MaybeDateOneOf = {
2223
+ toJson: (model: MaybeDateOneOf): any => {
2224
+ if (model === undefined || model === null) {
2225
+ return model;
2226
+ }
2227
+ return {
2228
+ ...(model.marker === undefined
2229
+ ? {}
2230
+ : {
2231
+ marker: model.marker,
2232
+ }),
2233
+ };
2234
+ },
2235
+ fromJson: (json: any): MaybeDateOneOf => {
2236
+ if (json === undefined || json === null) {
2237
+ return json;
2238
+ }
2239
+ return {
2240
+ marker: json['marker'],
2241
+ };
2242
+ },
2243
+ };
2244
+ }
2245
+
2246
+ /**
2247
+ * Client configuration for TestApi
2248
+ */
2249
+ export interface TestApiConfig {
2250
+ /**
2251
+ * Base URL for the API
2252
+ */
2253
+ url: string;
2254
+ /**
2255
+ * Custom instance of fetch. By default the global 'fetch' is used.
2256
+ * You can override this to add custom middleware for use cases such as adding authentication headers.
2257
+ */
2258
+ fetch?: typeof fetch;
2259
+ /**
2260
+ * Additional configuration
2261
+ */
2262
+ options?: {
2263
+ /**
2264
+ * By default, the client will add a Content-Type header, set to the media type defined for
2265
+ * the request in the OpenAPI specification.
2266
+ * Set this to false to omit this header.
2267
+ */
2268
+ omitContentTypeHeader?: boolean;
2269
+ };
2270
+ }
2271
+
2272
+ /**
2273
+ * API Client for TestApi
2274
+ */
2275
+ export class TestApi {
2276
+ private $config: TestApiConfig;
2277
+
2278
+ constructor(config: TestApiConfig) {
2279
+ this.$config = config;
2280
+
2281
+ this.postMaybeDate = this.postMaybeDate.bind(this);
2282
+ }
2283
+
2284
+ private $url = (
2285
+ path: string,
2286
+ pathParameters: { [key: string]: any },
2287
+ queryParameters: { [key: string]: any },
2288
+ collectionFormats?: { [key: string]: 'multi' | 'csv' },
2289
+ ): string => {
2290
+ const baseUrl = this.$config.url.endsWith('/')
2291
+ ? this.$config.url.slice(0, -1)
2292
+ : this.$config.url;
2293
+ const pathWithParameters = Object.entries(pathParameters).reduce(
2294
+ (withParams, [key, value]) =>
2295
+ withParams.replace(\`{\${key}}\`, encodeURIComponent(\`\${value}\`)),
2296
+ path,
2297
+ );
2298
+ const queryString = Object.entries(queryParameters)
2299
+ .map(([key, value]) => {
2300
+ if (Array.isArray(value) && collectionFormats?.[key] === 'multi') {
2301
+ return value
2302
+ .map(
2303
+ (v) => \`\${encodeURIComponent(key)}=\${encodeURIComponent(\`\${v}\`)}\`,
2304
+ )
2305
+ .join('&');
2306
+ }
2307
+ return \`\${encodeURIComponent(key)}=\${encodeURIComponent(Array.isArray(value) ? value.map(String).join(',') : String(value))}\`;
2308
+ })
2309
+ .join('&');
2310
+ return (
2311
+ baseUrl + pathWithParameters + (queryString ? \`?\${queryString}\` : '')
2312
+ );
2313
+ };
2314
+
2315
+ private $headers = (
2316
+ headerParameters: { [key: string]: any },
2317
+ collectionFormats?: { [key: string]: 'multi' | 'csv' },
2318
+ ): [string, string][] => {
2319
+ return Object.entries(headerParameters).flatMap(([key, value]) => {
2320
+ if (Array.isArray(value) && collectionFormats?.[key] === 'multi') {
2321
+ return value.map((v) => [key, String(v)]) as [string, string][];
2322
+ }
2323
+ return [[key, String(value)]];
2324
+ });
2325
+ };
2326
+
2327
+ private $fetch: typeof fetch = (...args) =>
2328
+ (this.$config.fetch ?? fetch)(...args);
2329
+
2330
+ public async postMaybeDate(input: PostMaybeDateRequest): Promise<string> {
2331
+ const pathParameters: { [key: string]: any } = {};
2332
+ const queryParameters: { [key: string]: any } = {};
2333
+ const headerParameters: { [key: string]: any } = {};
2334
+ if (!this.$config.options?.omitContentTypeHeader) {
2335
+ headerParameters['Content-Type'] = 'application/json';
2336
+ }
2337
+ const body =
2338
+ typeof input === 'object'
2339
+ ? JSON.stringify($IO.MaybeDate.toJson(input))
2340
+ : String($IO.MaybeDate.toJson(input));
2341
+
2342
+ const response = await this.$fetch(
2343
+ this.$url('/maybe-date', pathParameters, queryParameters),
2344
+ {
2345
+ headers: this.$headers(headerParameters),
2346
+ method: 'POST',
2347
+ body,
2348
+ },
2349
+ );
2350
+
2351
+ if (response.status === 200) {
2352
+ return await response.text();
2353
+ }
2354
+ throw new Error(
2355
+ \`Unknown response status \${response.status} returned by API\`,
2356
+ );
2357
+ }
2358
+ }
2359
+ "
2360
+ `;