From 31a2f13510af9a901a9f2027501a0ffaea1abce5 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Tue, 25 Nov 2025 21:59:09 +1100 Subject: [PATCH 01/24] MI-250: Added base service generator --- package-lock.json | 70 ++++++----------- packages/nx-cdk/README.md | 11 +++ packages/nx-cdk/eslint.config.mjs | 21 +++++ packages/nx-cdk/generators.json | 15 ++++ packages/nx-cdk/package.json | 18 +++++ packages/nx-cdk/project.json | 41 ++++++++++ .../src/generators/preset/preset.spec.ts | 20 +++++ .../nx-cdk/src/generators/preset/preset.ts | 18 +++++ .../nx-cdk/src/generators/preset/schema.d.ts | 3 + .../nx-cdk/src/generators/preset/schema.json | 18 +++++ .../service/files/README.md.template | 25 ++++++ .../service/files/eslint.config.mjs.template | 3 + .../service/files/package.json.template | 27 +++++++ .../service/files/rsbuild.config.mjs.template | 3 + .../service/files/src/index.ts.template | 66 ++++++++++++++++ .../service/files/src/infra/.gitkeep.template | 0 .../src/runtime/handlers/.gitkeep.template | 0 .../src/runtime/lib/utils/.gitkeep.template | 0 .../files/tests/__data__/.gitkeep.template | 0 .../service/files/vitest.config.mjs.template | 18 +++++ .../src/generators/service/generator.spec.ts | 78 +++++++++++++++++++ .../src/generators/service/generator.ts | 76 ++++++++++++++++++ .../nx-cdk/src/generators/service/schema.d.ts | 4 + .../nx-cdk/src/generators/service/schema.json | 20 +++++ packages/nx-cdk/src/index.ts | 3 + packages/nx-cdk/tsconfig.json | 14 ++++ packages/nx-cdk/tsconfig.lib.json | 8 ++ packages/nx-cdk/tsconfig.spec.json | 7 ++ packages/nx-cdk/vite.config.mjs | 9 +++ 29 files changed, 551 insertions(+), 45 deletions(-) create mode 100644 packages/nx-cdk/README.md create mode 100644 packages/nx-cdk/eslint.config.mjs create mode 100644 packages/nx-cdk/generators.json create mode 100644 packages/nx-cdk/package.json create mode 100644 packages/nx-cdk/project.json create mode 100644 packages/nx-cdk/src/generators/preset/preset.spec.ts create mode 100644 packages/nx-cdk/src/generators/preset/preset.ts create mode 100644 packages/nx-cdk/src/generators/preset/schema.d.ts create mode 100644 packages/nx-cdk/src/generators/preset/schema.json create mode 100644 packages/nx-cdk/src/generators/service/files/README.md.template create mode 100644 packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template create mode 100644 packages/nx-cdk/src/generators/service/files/package.json.template create mode 100644 packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template create mode 100644 packages/nx-cdk/src/generators/service/files/src/index.ts.template create mode 100644 packages/nx-cdk/src/generators/service/files/src/infra/.gitkeep.template create mode 100644 packages/nx-cdk/src/generators/service/files/src/runtime/handlers/.gitkeep.template create mode 100644 packages/nx-cdk/src/generators/service/files/src/runtime/lib/utils/.gitkeep.template create mode 100644 packages/nx-cdk/src/generators/service/files/tests/__data__/.gitkeep.template create mode 100644 packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template create mode 100644 packages/nx-cdk/src/generators/service/generator.spec.ts create mode 100644 packages/nx-cdk/src/generators/service/generator.ts create mode 100644 packages/nx-cdk/src/generators/service/schema.d.ts create mode 100644 packages/nx-cdk/src/generators/service/schema.json create mode 100644 packages/nx-cdk/src/index.ts create mode 100644 packages/nx-cdk/tsconfig.json create mode 100644 packages/nx-cdk/tsconfig.lib.json create mode 100644 packages/nx-cdk/tsconfig.spec.json create mode 100644 packages/nx-cdk/vite.config.mjs diff --git a/package-lock.json b/package-lock.json index 24b43cf..9f2733b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,6 +53,10 @@ "resolved": "packages/microservice-util-lib", "link": true }, + "node_modules/@aligent/nx-cdk": { + "resolved": "packages/nx-cdk", + "link": true + }, "node_modules/@aligent/nx-openapi": { "resolved": "packages/nx-openapi", "link": true @@ -4509,7 +4513,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4523,7 +4526,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4537,7 +4539,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4551,7 +4552,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4565,7 +4565,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4579,7 +4578,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4593,7 +4591,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4607,7 +4604,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4621,7 +4617,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4635,7 +4630,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4649,7 +4643,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4663,7 +4656,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4677,7 +4669,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4691,7 +4682,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4705,7 +4695,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4719,7 +4708,6 @@ "cpu": [ "wasm32" ], - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -4733,7 +4721,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz", "integrity": "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -4746,7 +4733,6 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -4760,7 +4746,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4774,7 +4759,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4788,7 +4772,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6256,7 +6239,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.14.1.tgz", "integrity": "sha512-jrt5GUaZUU6cmMS+WTJEvGvaB6j1YNKPHPzC2PUi2BjaFbtxURHj6641Az6xN7b665hNniAIdvjxWcRml5yCnw==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 10" @@ -6274,7 +6257,7 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.11.1.tgz", "integrity": "sha512-VQ0hJ5jX31TVv/fhZx4xJRzd8pwn6VvzYd2tGOHHr2TfXGCBixZoqdPDXTiEoJLCTS2MmvBf6zyQZZ0M8aGQCQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@swc-node/core": "^1.14.1", @@ -6298,14 +6281,14 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@swc-node/sourcemap-support": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.6.1.tgz", "integrity": "sha512-ovltDVH5QpdHXZkW138vG4+dgcNsxfwxHVoV6BtmTbz2KKl1A8ZSlbdtxzzfNjCjbpayda8Us9eMtcHobm38dA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "source-map-support": "^0.5.21", @@ -6316,7 +6299,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -6327,7 +6310,7 @@ "version": "1.15.2", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.2.tgz", "integrity": "sha512-OQm+yJdXxvSjqGeaWhP6Ia264ogifwAO7Q12uTDVYj/Ks4jBTI4JknlcjDRAXtRhqbWsfbZyK/5RtuIPyptk3w==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -6369,7 +6352,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6386,7 +6368,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6403,7 +6384,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -6420,7 +6400,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6437,7 +6416,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6454,7 +6432,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6471,7 +6448,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6488,7 +6464,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6505,7 +6480,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6522,7 +6496,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -6536,14 +6509,14 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0" }, "node_modules/@swc/helpers": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -6553,7 +6526,7 @@ "version": "0.1.25", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3" @@ -12884,7 +12857,7 @@ "version": "11.13.2", "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.13.2.tgz", "integrity": "sha512-1SXVyYQ9bqMX3uZo8Px81EG7jhZkO9PvvR5X9roY5TLYVm4ZA7pbPDNlYaDBBeF9U+YO3OeMNoHde52hrcCu8w==", - "dev": true, + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" @@ -13127,7 +13100,7 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 6" @@ -14464,9 +14437,9 @@ } }, "node_modules/test-exclude/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -15493,6 +15466,13 @@ "openapi-fetch": "^0.15.0" } }, + "packages/nx-cdk": { + "name": "@aligent/nx-cdk", + "version": "0.0.1", + "dependencies": { + "tslib": "^2.3.0" + } + }, "packages/nx-openapi": { "name": "@aligent/nx-openapi", "version": "1.0.0", diff --git a/packages/nx-cdk/README.md b/packages/nx-cdk/README.md new file mode 100644 index 0000000..bf7f629 --- /dev/null +++ b/packages/nx-cdk/README.md @@ -0,0 +1,11 @@ +# Nx Cloud Development Kit + +The `@aligent/nx-cdk` package provides Nx generators for AWS CDK development. + +## Preset Generator + + + +## Service Generator + + diff --git a/packages/nx-cdk/eslint.config.mjs b/packages/nx-cdk/eslint.config.mjs new file mode 100644 index 0000000..40f2223 --- /dev/null +++ b/packages/nx-cdk/eslint.config.mjs @@ -0,0 +1,21 @@ +import nxEslintPlugin from '@nx/eslint-plugin'; +import jsonParser from 'jsonc-eslint-parser'; +import baseConfig from '../../eslint.config.mjs'; + +export default [ + ...baseConfig, + { + files: ['./package.json'], + plugins: { '@nx': nxEslintPlugin }, + rules: { + '@nx/dependency-checks': ['error', { ignoredFiles: ['{projectRoot}/*.{js,cjs,mjs}'] }], + }, + languageOptions: { parser: jsonParser }, + }, + { + files: ['./package.json', './generators.json'], + plugins: { '@nx': nxEslintPlugin }, + rules: { '@nx/nx-plugin-checks': 'error' }, + languageOptions: { parser: jsonParser }, + }, +]; diff --git a/packages/nx-cdk/generators.json b/packages/nx-cdk/generators.json new file mode 100644 index 0000000..7b9eaf2 --- /dev/null +++ b/packages/nx-cdk/generators.json @@ -0,0 +1,15 @@ +{ + "generators": { + "preset": { + "factory": "./src/generators/preset/preset", + "schema": "./src/generators/preset/schema.json", + "description": "preset generator", + "x-use-standalone-layout": true + }, + "service": { + "factory": "./src/generators/service/generator", + "schema": "./src/generators/service/schema.json", + "description": "Generate a new service" + } + } +} diff --git a/packages/nx-cdk/package.json b/packages/nx-cdk/package.json new file mode 100644 index 0000000..e5a5a00 --- /dev/null +++ b/packages/nx-cdk/package.json @@ -0,0 +1,18 @@ +{ + "name": "@aligent/nx-cdk", + "version": "0.0.1", + "type": "commonjs", + "main": "./src/index.js", + "typings": "./src/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/aligent/microservice-development-utilities.git", + "directory": "packages/nx-cdk" + }, + "dependencies": { + "@nx/devkit": "20.8.1" + }, + "generators": "./generators.json", + "author": "Aligent", + "license": "MIT" +} diff --git a/packages/nx-cdk/project.json b/packages/nx-cdk/project.json new file mode 100644 index 0000000..ddeb1bc --- /dev/null +++ b/packages/nx-cdk/project.json @@ -0,0 +1,41 @@ +{ + "name": "nx-cdk", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/nx-cdk/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/nx-cdk", + "main": "{projectRoot}/src/index.ts", + "tsConfig": "{projectRoot}/tsconfig.lib.json", + "assets": [ + "{projectRoot}/*.md", + { + "input": "./{projectRoot}/src", + "glob": "**/!(*.ts)", + "output": "./src" + }, + { + "input": "./{projectRoot}/src", + "glob": "**/*.d.ts", + "output": "./src" + }, + { + "input": "./{projectRoot}", + "glob": "generators.json", + "output": "." + }, + { + "input": "./{projectRoot}", + "glob": "executors.json", + "output": "." + } + ] + } + } + }, + "tags": ["nx", "plugin", "cdk"] +} diff --git a/packages/nx-cdk/src/generators/preset/preset.spec.ts b/packages/nx-cdk/src/generators/preset/preset.spec.ts new file mode 100644 index 0000000..02b1284 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/preset.spec.ts @@ -0,0 +1,20 @@ +import { Tree, readProjectConfiguration } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; + +import { presetGenerator } from './preset'; +import { PresetGeneratorSchema } from './schema'; + +describe('preset generator', () => { + let tree: Tree; + const options: PresetGeneratorSchema = { name: 'test' }; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + }); + + it('should run successfully', async () => { + await presetGenerator(tree, options); + const config = readProjectConfiguration(tree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/packages/nx-cdk/src/generators/preset/preset.ts b/packages/nx-cdk/src/generators/preset/preset.ts new file mode 100644 index 0000000..8739a11 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/preset.ts @@ -0,0 +1,18 @@ +import { addProjectConfiguration, formatFiles, generateFiles, Tree } from '@nx/devkit'; +import * as path from 'path'; +import { PresetGeneratorSchema } from './schema'; + +export async function presetGenerator(tree: Tree, options: PresetGeneratorSchema) { + // TODO implement the preset generator here + const projectRoot = `libs/${options.name}`; + addProjectConfiguration(tree, options.name, { + root: projectRoot, + projectType: 'library', + sourceRoot: `${projectRoot}/src`, + targets: {}, + }); + generateFiles(tree, path.join(__dirname, 'files'), projectRoot, options); + await formatFiles(tree); +} + +export default presetGenerator; diff --git a/packages/nx-cdk/src/generators/preset/schema.d.ts b/packages/nx-cdk/src/generators/preset/schema.d.ts new file mode 100644 index 0000000..9ddd208 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/schema.d.ts @@ -0,0 +1,3 @@ +export interface PresetGeneratorSchema { + name: string; +} diff --git a/packages/nx-cdk/src/generators/preset/schema.json b/packages/nx-cdk/src/generators/preset/schema.json new file mode 100644 index 0000000..a4b0aed --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/schema.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/schema", + "$id": "Preset", + "title": "", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "What name would you like to use?" + } + }, + "required": ["name"] +} diff --git a/packages/nx-cdk/src/generators/service/files/README.md.template b/packages/nx-cdk/src/generators/service/files/README.md.template new file mode 100644 index 0000000..c6e9533 --- /dev/null +++ b/packages/nx-cdk/src/generators/service/files/README.md.template @@ -0,0 +1,25 @@ +# <%= name %> + +This is a CDK service generated using `@aligent/nx-cdk` for Nx. + +## Architecture + +[Add your architecture documentation here] + +## Development + +### Type Checking + +```bash +npx nx check-types <%= name %> +``` + +### Testing + +```bash +npx nx test <%= name %> +``` + +## Deployment + +This service is deployed as part of the CDK application. See the main README for deployment instructions. diff --git a/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template b/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template new file mode 100644 index 0000000..66a4fbe --- /dev/null +++ b/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template @@ -0,0 +1,3 @@ +import baseConfig from '../../eslint.config.mjs'; + +export default [...baseConfig]; \ No newline at end of file diff --git a/packages/nx-cdk/src/generators/service/files/package.json.template b/packages/nx-cdk/src/generators/service/files/package.json.template new file mode 100644 index 0000000..1a1c5a2 --- /dev/null +++ b/packages/nx-cdk/src/generators/service/files/package.json.template @@ -0,0 +1,27 @@ +{ + "name": "@services/<%= name %>", + "version": "0.0.1", + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "exports": { + ".": { + "types": "./src/index.ts", + "import": "./src/index.ts", + "default": "./src/index.ts" + }, + "./package.json": "./package.json" + }, + "nx": { + "tags": [ + "scope:services" + ], + "targets": { + "pg": { + "options": { + "stack": "dev/<%= name %>" + } + } + } + } +} diff --git a/packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template b/packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template new file mode 100644 index 0000000..0dafb4d --- /dev/null +++ b/packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template @@ -0,0 +1,3 @@ +import { defineLambdaConfig } from '../../rsbuild.config.base.mjs'; + +export default defineLambdaConfig(import.meta.dirname); diff --git a/packages/nx-cdk/src/generators/service/files/src/index.ts.template b/packages/nx-cdk/src/generators/service/files/src/index.ts.template new file mode 100644 index 0000000..5a642d7 --- /dev/null +++ b/packages/nx-cdk/src/generators/service/files/src/index.ts.template @@ -0,0 +1,66 @@ +import { Stack, StackProps, Stage, Tags } from 'aws-cdk-lib'; +import { Code } from 'aws-cdk-lib/aws-lambda'; +import { Construct } from 'constructs'; +import path from 'node:path'; + +const SERVICE_NAME = '<%= name %>' as const; + +export interface <%= name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('') %>StackProps extends StackProps { + description: string; +} + +/** + * Entrypoint for the <%= name %> service + * + * Instantiate in a CDK Application Stage to deploy to AWS. + * + * Use 'resolve' helpers below when referencing lambda handlers, step function files etc. + */ +export class <%= name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('') %>Stack extends Stack { + constructor(scope: Construct, id: typeof SERVICE_NAME | (string & {}), props?: <%= name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('') %>StackProps) { + super(scope, id, props); + + const STAGE = Stage.of(this)?.stageName; + if (!STAGE) { + throw new Error('This construct must be used within a CDK Stage'); + } + + Tags.of(this).add('SERVICE', id); + } +} + +/** + * Resolves a path to infra assets relative to this stack + * + * @param assetPath - The path to the asset. + * @returns The resolved path. + */ +export function resolveAssetPath(assetPath: `${'infra/'}${string}`) { + return path.resolve(import.meta.dirname, assetPath); +} + +/** + * Return an object with the default bundled code asset and + * handler property for use with the NodejsFunction construct. + * + * @example + * ```ts + * new NodejsFunction(this, 'FetchData', { + * ...resolveLambdaHandler('runtime/handlers/fetch-data.ts'), + * }); + * ``` + * + * @param assetPath - The path to the typescript handler file. + * @returns The resolved bundled code path and handler name. + */ +export function resolveLambdaHandler(assetPath: `${'runtime/handlers/'}${string}${'.ts'}`) { + // Replace 'runtime/handlers/' with '..dist/' and remove the file extension + const bundledPath = assetPath.replace( + /^runtime\/handlers\/(?.*)\.ts$/, + '../dist/$' + ); + return { + code: Code.fromAsset(path.resolve(import.meta.dirname, bundledPath)), + handler: 'index.handler', + }; +} diff --git a/packages/nx-cdk/src/generators/service/files/src/infra/.gitkeep.template b/packages/nx-cdk/src/generators/service/files/src/infra/.gitkeep.template new file mode 100644 index 0000000..e69de29 diff --git a/packages/nx-cdk/src/generators/service/files/src/runtime/handlers/.gitkeep.template b/packages/nx-cdk/src/generators/service/files/src/runtime/handlers/.gitkeep.template new file mode 100644 index 0000000..e69de29 diff --git a/packages/nx-cdk/src/generators/service/files/src/runtime/lib/utils/.gitkeep.template b/packages/nx-cdk/src/generators/service/files/src/runtime/lib/utils/.gitkeep.template new file mode 100644 index 0000000..e69de29 diff --git a/packages/nx-cdk/src/generators/service/files/tests/__data__/.gitkeep.template b/packages/nx-cdk/src/generators/service/files/tests/__data__/.gitkeep.template new file mode 100644 index 0000000..e69de29 diff --git a/packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template b/packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template new file mode 100644 index 0000000..d55869b --- /dev/null +++ b/packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template @@ -0,0 +1,18 @@ +import { defineConfig, mergeConfig } from 'vitest/config'; +import { viteBaseConfig } from '../../vitest.config.base.mjs'; + +export default defineConfig(configEnv => { + return mergeConfig( + viteBaseConfig(configEnv), + defineConfig({ + cacheDir: '../../node_modules/.vite/<%= name %>', + test: { + env: { + NODE_ENV: 'test', + YOUR_ENV_VAR: 'environment-variable', + }, + unstubEnvs: true, + }, + }) + ); +}); diff --git a/packages/nx-cdk/src/generators/service/generator.spec.ts b/packages/nx-cdk/src/generators/service/generator.spec.ts new file mode 100644 index 0000000..ba16c77 --- /dev/null +++ b/packages/nx-cdk/src/generators/service/generator.spec.ts @@ -0,0 +1,78 @@ +import { Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; + +import { serviceGenerator } from './generator'; +import { ServiceGeneratorSchema } from './schema'; + +describe('service generator', () => { + let tree: Tree; + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + tree.write( + 'tsconfig.json', + `{ + "extends": "./tsconfig.base.json", + "compileOnSave": false, + "files": [], + "references": [] + }` + ); + }); + + it('should run successfully when type is general', async () => { + const options: ServiceGeneratorSchema = { name: 'test' }; + await expect(serviceGenerator(tree, options)).resolves.not.toThrow(); + }); + + it('should add the project reference to tsconfig.json', async () => { + const options: ServiceGeneratorSchema = { name: 'test' }; + + await serviceGenerator(tree, options); + + const tsconfig = tree.read('tsconfig.json', 'utf-8'); + + assert.isNotNull(tsconfig); + + const references = JSON.parse(tsconfig).references; + + expect(references).toEqual([{ path: './services/test' }]); + }); + + it('should register the services as a no-buildable typecheck target', async () => { + const options: ServiceGeneratorSchema = { name: 'test' }; + + await serviceGenerator(tree, options); + + const nxJson = tree.read('nx.json', 'utf-8'); + + assert.isNotNull(nxJson); + + const plugins = JSON.parse(nxJson).plugins; + + expect(plugins).toEqual([ + { + plugin: '@nx/js/typescript', + options: { + typecheck: { + targetName: 'typecheck', + }, + }, + include: ['services/test/*'], + }, + ]); + }); + + it('should not add paths to the base tsconfig', async () => { + const options: ServiceGeneratorSchema = { name: 'test' }; + + await serviceGenerator(tree, options); + + const tsconfig = tree.read('tsconfig.base.json', 'utf-8'); + + assert.isNotNull(tsconfig); + + const paths = JSON.parse(tsconfig).paths; + + expect(paths).toBe(undefined); + }); +}); diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts new file mode 100644 index 0000000..72a17a3 --- /dev/null +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -0,0 +1,76 @@ +import { formatFiles, generateFiles, Tree, updateJson } from '@nx/devkit'; +import { ServiceGeneratorSchema } from './schema'; + +const SERVICES_FOLDER = 'services'; + +function addTsConfigReference(tree: Tree, referencePath: string) { + updateJson(tree, 'tsconfig.json', json => { + json.references ??= []; + + if (json.references.some((r: { path: string }) => r.path === referencePath)) { + throw new Error( + `You already have a library using the import path "${referencePath}". Make sure to specify a unique one.` + ); + } + + json.references.push({ + path: referencePath, + }); + + return json; + }); +} + +function registerWithTypecheckPlugin(tree: Tree, referencePath: string) { + updateJson(tree, 'nx.json', json => { + json.plugins ??= []; + + // Services should be non-buildable, so we need to register them with the typescript plugin configuration + // that adds typechecking but not a build argument + const plugin = json.plugins.find( + (p: { + plugin: string; + include: string[]; + options?: { typecheck?: unknown; build?: unknown }; + }) => p.plugin === '@nx/js/typescript' && p.options?.typecheck && !p.options?.build + ); + + if (!plugin) { + json.plugins.push({ + plugin: '@nx/js/typescript', + options: { + typecheck: { + targetName: 'typecheck', + }, + }, + include: [referencePath], + }); + } else { + plugin.include.push(referencePath); + } + + return json; + }); +} + +export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSchema) { + const projectRoot = `${SERVICES_FOLDER}/${options.name}`; + + if (!tree.exists(SERVICES_FOLDER)) { + tree.write(`${SERVICES_FOLDER}/.gitkeep`, ''); + } + + generateFiles(tree, 'files', projectRoot, { + ...options, + template: '', + }); + + // Add the service to tsconfig.json references and nx.json plugins + // The root application needs to import stacks from the service + addTsConfigReference(tree, `./${projectRoot}`); + registerWithTypecheckPlugin(tree, `${projectRoot}/*`); + + await formatFiles(tree); +} + +export default serviceGenerator; diff --git a/packages/nx-cdk/src/generators/service/schema.d.ts b/packages/nx-cdk/src/generators/service/schema.d.ts new file mode 100644 index 0000000..f8c9385 --- /dev/null +++ b/packages/nx-cdk/src/generators/service/schema.d.ts @@ -0,0 +1,4 @@ +/* v8 ignore start */ +export interface ServiceGeneratorSchema { + name: string; +} diff --git a/packages/nx-cdk/src/generators/service/schema.json b/packages/nx-cdk/src/generators/service/schema.json new file mode 100644 index 0000000..82e164c --- /dev/null +++ b/packages/nx-cdk/src/generators/service/schema.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "ServiceGenerator", + "title": "Nx Generator for bootstrapping Serverless Framework services", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the service", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "What is the name of the service?", + "pattern": "^(?!.*[Ss]tack|.*[Ss]ervice).*$", + "patternErrorMessage": "Service name cannot contain '[Ss]tack' or '[Ss]ervice'" + } + }, + "required": ["brand", "name"] +} diff --git a/packages/nx-cdk/src/index.ts b/packages/nx-cdk/src/index.ts new file mode 100644 index 0000000..18e56bb --- /dev/null +++ b/packages/nx-cdk/src/index.ts @@ -0,0 +1,3 @@ +/* v8 ignore next 2 */ +export * from './generators/preset/preset'; +export * from './generators/service/generator'; diff --git a/packages/nx-cdk/tsconfig.json b/packages/nx-cdk/tsconfig.json new file mode 100644 index 0000000..9fa1b41 --- /dev/null +++ b/packages/nx-cdk/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": {}, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/nx-cdk/tsconfig.lib.json b/packages/nx-cdk/tsconfig.lib.json new file mode 100644 index 0000000..d7f7e3e --- /dev/null +++ b/packages/nx-cdk/tsconfig.lib.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true + }, + "include": ["src/**/*.ts"], + "exclude": ["vite.config.mjs", "src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/packages/nx-cdk/tsconfig.spec.json b/packages/nx-cdk/tsconfig.spec.json new file mode 100644 index 0000000..bc3aad4 --- /dev/null +++ b/packages/nx-cdk/tsconfig.spec.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc" + }, + "include": ["vite.config.mjs", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"] +} diff --git a/packages/nx-cdk/vite.config.mjs b/packages/nx-cdk/vite.config.mjs new file mode 100644 index 0000000..debc737 --- /dev/null +++ b/packages/nx-cdk/vite.config.mjs @@ -0,0 +1,9 @@ +import { defineConfig, mergeConfig } from 'vitest/config'; +import { viteBaseConfig } from '../../vite.config.base.mjs'; + +export default mergeConfig( + viteBaseConfig, + defineConfig({ + cacheDir: '../../node_modules/.vite/packages/nx-cdk', + }) +); From 6f958dda060182d838c51e7e0abdf5d5182e5567 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Fri, 28 Nov 2025 12:07:38 +1100 Subject: [PATCH 02/24] MI-250: Initial ns-cdk generator --- .../src/generators/helpers/configs/nxJson.ts | 66 +++++++++ .../generators/helpers/configs/packageJson.ts | 61 +++++++++ .../generators/helpers/configs/tsConfigs.ts | 41 ++++++ .../src/generators/helpers/utilities.ts | 61 +++++++++ .../preset/files/.editorconfig.template | 18 +++ .../preset/files/.git-hooks/pre-push.template | 68 ++++++++++ .../preset/files/.github/CODEOWNERS.template | 3 + .../files/.github/dependabot.yml.template | 7 + .../.github/workflows/ci-cd.yml.template | 27 ++++ .../preset/files/.gitignore.template | 46 +++++++ .../generators/preset/files/.nvmrc.template | 1 + .../preset/files/.prettierignore.template | 11 ++ .../preset/files/.yarnrc.yml.template | 6 + .../generators/preset/files/LICENSE.template | 21 +++ .../files/application/README.md.template | 73 ++++++++++ .../log-group-defaults-injector.ts.template | 100 ++++++++++++++ .../_internal/microservice-checks.ts.template | 58 ++++++++ ...ejs-function-defaults-injector.ts.template | 109 +++++++++++++++ ...tep-function-defaults-injector.ts.template | 126 ++++++++++++++++++ .../version-functions-aspect.ts.template | 74 ++++++++++ .../files/application/bin/main.ts.template | 42 ++++++ .../application/cdk.context.json.template | 4 + .../files/application/cdk.json.template | 92 +++++++++++++ .../lib/service-stacks.ts.template | 17 +++ .../files/application/package.json.template | 27 ++++ .../preset/files/cdk-config.yml.template | 16 +++ .../preset/files/eslint.config.mjs.template | 63 +++++++++ .../preset/files/prettier.config.mjs.template | 3 + .../files/rsbuild.config.base.mjs.template | 67 ++++++++++ .../preset/files/tsconfig.json.template | 6 + .../files/vitest.config.base.mjs.template | 39 ++++++ .../files/vitest.global.setup.mjs.template | 109 +++++++++++++++ .../nx-cdk/src/generators/preset/preset.ts | 36 +++-- .../nx-cdk/src/generators/preset/schema.d.ts | 1 + .../nx-cdk/src/generators/preset/schema.json | 18 ++- .../service/files/vitest.config.mjs.template | 4 +- .../src/generators/service/generator.ts | 80 ++++++----- 37 files changed, 1550 insertions(+), 51 deletions(-) create mode 100644 packages/nx-cdk/src/generators/helpers/configs/nxJson.ts create mode 100644 packages/nx-cdk/src/generators/helpers/configs/packageJson.ts create mode 100644 packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts create mode 100644 packages/nx-cdk/src/generators/helpers/utilities.ts create mode 100644 packages/nx-cdk/src/generators/preset/files/.editorconfig.template create mode 100755 packages/nx-cdk/src/generators/preset/files/.git-hooks/pre-push.template create mode 100644 packages/nx-cdk/src/generators/preset/files/.github/CODEOWNERS.template create mode 100644 packages/nx-cdk/src/generators/preset/files/.github/dependabot.yml.template create mode 100644 packages/nx-cdk/src/generators/preset/files/.github/workflows/ci-cd.yml.template create mode 100644 packages/nx-cdk/src/generators/preset/files/.gitignore.template create mode 100644 packages/nx-cdk/src/generators/preset/files/.nvmrc.template create mode 100644 packages/nx-cdk/src/generators/preset/files/.prettierignore.template create mode 100644 packages/nx-cdk/src/generators/preset/files/.yarnrc.yml.template create mode 100644 packages/nx-cdk/src/generators/preset/files/LICENSE.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/README.md.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/_internal/log-group-defaults-injector.ts.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/_internal/microservice-checks.ts.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/_internal/step-function-defaults-injector.ts.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/_internal/version-functions-aspect.ts.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/cdk.context.json.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/cdk.json.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/package.json.template create mode 100644 packages/nx-cdk/src/generators/preset/files/cdk-config.yml.template create mode 100644 packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template create mode 100644 packages/nx-cdk/src/generators/preset/files/prettier.config.mjs.template create mode 100644 packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template create mode 100644 packages/nx-cdk/src/generators/preset/files/tsconfig.json.template create mode 100644 packages/nx-cdk/src/generators/preset/files/vitest.config.base.mjs.template create mode 100644 packages/nx-cdk/src/generators/preset/files/vitest.global.setup.mjs.template diff --git a/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts new file mode 100644 index 0000000..0d24bdd --- /dev/null +++ b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts @@ -0,0 +1,66 @@ +import { NxJsonConfiguration } from '@nx/devkit'; + +export const NX_JSON: NxJsonConfiguration & { $schema: string } = { + $schema: './node_modules/nx/schemas/nx-schema.json', + defaultBase: 'origin/staging', + plugins: [ + { plugin: '@nx/eslint/plugin', options: {} }, + { plugin: '@nx/vite/plugin', options: {} }, + { + plugin: '@nx/rsbuild', + options: { + buildTargetName: 'build:lambda', + devTargetName: 'dev:lambda', + inspectTargetName: 'inspect:lambda', + }, + // This plugin configuration is only for bundling lambda code in services + // The `**` glob is required to include all services + include: ['services/**'], + // Services with no lambda handlers should be excluded from here + exclude: [], + }, + ], + generators: { + '@nx/js:library': { bundler: 'none', linter: 'eslint', unitTestRunner: 'vitest' }, + }, + namedInputs: { + default: ['{projectRoot}/**/*', 'sharedGlobals'], + production: [ + 'default', + '!{projectRoot}/.eslintrc.json', + '!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)', + '!{projectRoot}/tsconfig.spec.json', + '!{projectRoot}/vitest.config.m[jt]s', + '!{projectRoot}/src/test-setup.[jt]s', + ], + sharedGlobals: [], + }, + targetDefaults: { + build: { + cache: true, + dependsOn: ['^build'], + inputs: ['production', '^production'], + outputs: ['{projectRoot}/dist'], + }, + cdk: { dependsOn: ['^build', '^build:lambda'], inputs: ['production', '^production'] }, + lint: { cache: true, inputs: ['default'] }, + test: { + cache: true, + inputs: ['default', '^production'], + outputs: ['{projectRoot}/coverage'], + // Stack tests may require lambda handlers to be built first + dependsOn: ['^build', 'build:lambda'], + configurations: { coverage: { coverage: true } }, + }, + typecheck: { cache: true, dependsOn: ['^build'], inputs: ['production', '^production'] }, + parameters: { + executor: 'nx:run-commands', + options: { color: true, cwd: '{projectRoot}/parameters', file: '.env.csv' }, + defaultConfiguration: 'export', + configurations: { + import: { command: 'store-parameters import {args.file}' }, + export: { command: 'store-parameters export {args.file} --path={args.path}' }, + }, + }, + }, +} as const; diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts new file mode 100644 index 0000000..386cab2 --- /dev/null +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -0,0 +1,61 @@ +export const PACKAGE_JSON = { + author: 'Aligent Consulting', + private: true, + license: 'MIT', + type: 'module', + scripts: { + test: 'nx affected -t test --coverage', + 'test:all': 'nx run-many -t test --coverage', + lint: 'nx affected -t lint', + 'lint:all': 'nx run-many -t lint', + typecheck: 'nx affected -t typecheck', + 'typecheck:all': 'nx run-many -t typecheck', + postinstall: `[ -d .git ] && git config core.hooksPath '.git-hooks' || true`, + 'pg:synth': `nx run application:cdk synth 'dev/**' --exclusively --profile playground`, + 'pg:deploy': `nx run application:cdk deploy --method 'direct' 'dev/**' --exclusively --require-approval never --profile playground`, + 'pg:destroy': "nx run application:cdk destroy 'dev/**' --profile playground", + audit: 'nx run-many -t lint typecheck test --configuration coverage --skip-nx-cache', + }, + dependencies: {}, + devDependencies: { + // '@aligent/cdk-constructs': '^0.0.1', FIXME: this one seems to be a private package + '@aligent/ts-code-standards': '^4.1.0', + '@nx/eslint': '21.5.2', + '@nx/eslint-plugin': '21.5.2', + '@nx/js': '21.5.2', // TODO we may want to remove this package, double check if it's actually needed + '@nx/rsbuild': '21.5.2', + '@nx/vite': '21.5.2', + '@rsbuild/core': '^1.5.6', + '@swc-node/register': '^1.10.10', + '@swc/core': '^1.13.3', + '@swc/helpers': '^0.5.17', + '@types/aws-lambda': '^8.10.152', + '@types/node': '^22.17.0', + '@typescript-eslint/eslint-plugin': '8.44.0', + '@typescript-eslint/parser': '8.44.0', + '@vitest/coverage-v8': '^3.2.4', + '@vitest/ui': '^3.2.4', + 'aws-cdk': '^2.1033.0', + 'aws-cdk-lib': '^2.230.0', + 'cdk-nag': '^2.37.55', + constructs: '^10.4.3', + esbuild: '~0.25.8', // TODO: Do we need this package now that we're using rsbuild instead + 'esbuild-visualizer': '^0.7.0', + eslint: '^9.32.0', + 'eslint-config-prettier': '10.1.8', + 'fast-glob': '^3.3.3', + jiti: '2.5.1', + 'jsonc-eslint-parser': '^2.4.0', + nx: '21.5.2', + // open: '^10.2.0', TODO Double check what is this and why it's here? + prettier: '^3.6.2', + 'store-parameters': '^1.0.6', + tslib: '^2.8.1', + typescript: '~5.9.2', + vite: '7.1.6', + vitest: '^3.2.4', + }, + workspaces: ['libs/*', 'services/*', 'application/*'], + packageManager: + 'yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c', +} as const; diff --git a/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts b/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts new file mode 100644 index 0000000..5ad5ed5 --- /dev/null +++ b/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts @@ -0,0 +1,41 @@ +interface TsConfig { + extends: string; + compilerOptions?: Record; + files?: string[]; + include: string[]; + exclude?: string[]; + references: Record[]; +} + +const BASE_CONFIG = '@aligent/ts-code-standards/tsconfigs-extend'; + +export const TS_CONFIG_JSON: TsConfig = { + extends: BASE_CONFIG, + files: [], + include: [], + references: [], +} as const; + +export const TS_CONFIG_LIB_JSON: TsConfig = { + extends: BASE_CONFIG, + compilerOptions: { + baseUrl: '.', + rootDir: 'src', + outDir: 'dist', + tsBuildInfoFile: 'dist/tsconfig.lib.tsbuildinfo', + types: ['node'], + }, + include: ['src/**/*.ts'], + exclude: ['vite.config.mjs', 'src/**/*.spec.ts', 'src/**/*.test.ts'], + references: [], +} as const; + +export const TS_CONFIG_SPEC_JSON: TsConfig = { + extends: BASE_CONFIG, + compilerOptions: { + outDir: './out-tsc/vitest', + types: ['vitest/globals', 'vitest/importMeta', 'vite/client', 'node', 'vitest'], + }, + include: ['vite.config.mjs', 'src/**/*.test.ts', 'src/**/*.spec.ts', 'src/**/*.d.ts'], + references: [{ path: './tsconfig.lib.json' }], +}; diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts new file mode 100644 index 0000000..75cee60 --- /dev/null +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -0,0 +1,61 @@ +import { readJsonFile } from '@nx/devkit'; +import { join } from 'path'; +import { PACKAGE_JSON } from './configs/packageJson'; +import { TS_CONFIG_JSON, TS_CONFIG_LIB_JSON, TS_CONFIG_SPEC_JSON } from './configs/tsConfigs'; + +export function constructPackageJsonFile(name: string, version: string, nodeVersion: string) { + const [nodeVersionMajor, nodeVersionMinor] = nodeVersion.split('.'); + + const devDependencies = Object.fromEntries( + Object.entries({ + '@aligent/nx-cdk': version, + ...PACKAGE_JSON.devDependencies, + }).sort() + ); + + const packageJson = Object.fromEntries( + Object.entries({ + ...PACKAGE_JSON, + name: `@${name}/integrations`, + description: `${name} integrations mono-repository`, + version, + devDependencies, + engines: { node: `^${nodeVersionMajor}.${nodeVersionMinor}.0` }, + }).sort() + ); + + return packageJson; +} + +export function constructProjectTsConfigFiles(type: 'application' | 'service') { + const tsConfig = { ...TS_CONFIG_JSON }; + if (type === 'service') { + tsConfig.references = [{ path: './tsconfig.lib.json' }, { path: './tsconfig.spec.json' }]; + } + + return { + tsConfig, + tsConfigLib: { ...TS_CONFIG_LIB_JSON }, + tsConfigSpec: { ...TS_CONFIG_SPEC_JSON }, + }; +} + +function isPackageJsonWithVersion(obj: unknown): obj is { version: string } { + return ( + typeof obj === 'object' && + obj !== null && + 'version' in obj && + typeof (obj as any).version === 'string' + ); +} + +export function getGeneratorVersion() { + const packagePath = join(__dirname, '../../../package.json'); + const packageJson = readJsonFile(packagePath); + + if (isPackageJsonWithVersion(packageJson)) { + return packageJson.version; + } + + throw new Error(`Unable to get generator version from ${packagePath}`); +} diff --git a/packages/nx-cdk/src/generators/preset/files/.editorconfig.template b/packages/nx-cdk/src/generators/preset/files/.editorconfig.template new file mode 100644 index 0000000..24b98c1 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.editorconfig.template @@ -0,0 +1,18 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +max_line_length = 100 + +[{package.json,*.yml,*.md}] +indent_size = 2 +indent_style = space + +[*.md] +trim_trailing_whitespace = false diff --git a/packages/nx-cdk/src/generators/preset/files/.git-hooks/pre-push.template b/packages/nx-cdk/src/generators/preset/files/.git-hooks/pre-push.template new file mode 100755 index 0000000..b99870a --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.git-hooks/pre-push.template @@ -0,0 +1,68 @@ +#!/bin/bash +# Script adapted from https://github.com/kaczor6418/git-hooks-example/blob/master/git-hooks/pre-commit + +# Support using VSCode to commit +# This loads nvm.sh and sets the correct PATH before running hook +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + +# Define colours for nicer CLI output +RED="\033[1;31m" +GREEN="\033[1;32m" +NO_COLOUR="\033[0m" + +echo -e "${GREEN}Executing git hook $0 $@${NO_COLOUR}" + +# Use the current Node version explicitly +nvm use + +# Get the list of staged changes +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM) + +# Exclude files that shouldn't trigger pre-commit checks +# This is done here because `nx affected` doesn't look at task inputs +# when determining if a project is affected +EXCLUDED_FILES_REGEX='.*\.md$' # Ignore markdown files +EXCLUDED_FILES_REGEX+='|.*\/step-functions\/.*\.(yml|yaml)$' # Ignore step function yaml files +EXCLUDED_FILES_REGEX+='|^\/?([^\/]*)$' # Ignore all root-level files +AFFECTED_FILES=$(echo "$STAGED_FILES" | \ + grep -vE "$EXCLUDED_FILES_REGEX" | \ + paste -sd,) + +echo -e "${GREEN}\nAffected files: $AFFECTED_FILES\n${NO_COLOUR}" + +# Exit early if there are no affected files +if [ -z "$AFFECTED_FILES" ]; then + echo -e "${GREEN}No affected files found. Exiting pre-commit hook.${NO_COLOUR}" + exit 0 +fi + +# Prepare the affected commands for static analysis targets +AFFECTED_COMMAND="yarn nx affected --files=$AFFECTED_FILES --nxBail --tui=false" +commands=("$AFFECTED_COMMAND -t lint typecheck --parallel=3", "$AFFECTED_COMMAND -t test --configuration coverage") +failures=() + +# Loop over commands, execute and push failure message if we see one +for cmd in "${commands[@]}"; do + $cmd + exit_code=$? + + if [ "$exit_code" -eq 1 ]; then + failures+=("āœ– Command ${RED}'${cmd}'${NO_COLOUR} failed with exit code ${exit_code} - see CLI output for errors") + elif [ "$exit_code" -eq 127 ]; then + failures+=("āœ– Command ${RED}'${cmd}'${NO_COLOUR} failed with exit code ${exit_code} - check that the script exists in package.json") + elif [ "$exit_code" -ne 0 ]; then + failures+=("āœ– Command ${RED}'${cmd}'${NO_COLOUR} failed with unexpected exit code ${exit_code}") + fi +done + +# Report overall success or failure +if [ ${#failures[@]} -ne 0 ]; then + echo -e "\n🚩${RED} Couldn't commit changes dues to the following errors: ${NO_COLOUR}" + + for report in "${failures[@]}"; do + echo -e $report; + done + + exit 1 +fi diff --git a/packages/nx-cdk/src/generators/preset/files/.github/CODEOWNERS.template b/packages/nx-cdk/src/generators/preset/files/.github/CODEOWNERS.template new file mode 100644 index 0000000..261386d --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.github/CODEOWNERS.template @@ -0,0 +1,3 @@ +# Both Microservice and DevOps teams own everything in this repo +# We'll review this in few months time and adjust when needed +* @aligent/microservices @aligent/devops diff --git a/packages/nx-cdk/src/generators/preset/files/.github/dependabot.yml.template b/packages/nx-cdk/src/generators/preset/files/.github/dependabot.yml.template new file mode 100644 index 0000000..439d325 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.github/dependabot.yml.template @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'monthly' + open-pull-requests-limit: 10 diff --git a/packages/nx-cdk/src/generators/preset/files/.github/workflows/ci-cd.yml.template b/packages/nx-cdk/src/generators/preset/files/.github/workflows/ci-cd.yml.template new file mode 100644 index 0000000..bd61d2a --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.github/workflows/ci-cd.yml.template @@ -0,0 +1,27 @@ +name: CI/CD Pipeline + +on: + pull_request: + branches: + - '**' + push: + branches: + - staging + - production + +jobs: + code-quality: + name: šŸ•µļøā€ā™€ļø Code Quality Check + uses: aligent/workflows/.github/workflows/node-pr.yml@main + with: + skip-format: false + + deploy: + name: Deploy to AWS + uses: aligent/workflows/.github/workflows/aws-cdk-deploy.yml@main + with: + cdk-stack-name: ${{ vars.STACK_NAME }} + aws-access-key-id: ${{ vars.AWS_ACCESS_KEY_ID }} + deploy: true + secrets: + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/packages/nx-cdk/src/generators/preset/files/.gitignore.template b/packages/nx-cdk/src/generators/preset/files/.gitignore.template new file mode 100644 index 0000000..6a3d32b --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.gitignore.template @@ -0,0 +1,46 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. +# Ignore everything by default +* + +# Project standard configurations +!**/*.md +!.githooks +!.github +!.editorconfig +!.gitignore +!.nvmrc +!.prettierignore +!cdk-config.yml +!eslint.config.mjs +!nx.json +!package.json +!prettier.config.mjs +!rsbuild.config.base.mjs +!tsconfig.json +!vitest.global.setup.mjs +!vitest.config.base.mjs + +# IDE - VSCode +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Package manager +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions +!.yarnrc.yml +!yarn.lock + +# Application +!applications +!docs +!libs +!services + +# Test and bundle artifacts +# **/cdk.out +# **/dist +# **/coverage diff --git a/packages/nx-cdk/src/generators/preset/files/.nvmrc.template b/packages/nx-cdk/src/generators/preset/files/.nvmrc.template new file mode 100644 index 0000000..1b29d17 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.nvmrc.template @@ -0,0 +1 @@ +v<%= nodeVersion %> diff --git a/packages/nx-cdk/src/generators/preset/files/.prettierignore.template b/packages/nx-cdk/src/generators/preset/files/.prettierignore.template new file mode 100644 index 0000000..89abafc --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.prettierignore.template @@ -0,0 +1,11 @@ +# Add files here to ignore them from prettier formatting + +# Build and test artifacts +**/dist +**/coverage + +# lock file is autogenerated +yarn.lock + +# Tools and misc +.nx diff --git a/packages/nx-cdk/src/generators/preset/files/.yarnrc.yml.template b/packages/nx-cdk/src/generators/preset/files/.yarnrc.yml.template new file mode 100644 index 0000000..f3a90a9 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/.yarnrc.yml.template @@ -0,0 +1,6 @@ +nodeLinker: node-modules + +plugins: + - checksum: e5e6e2885ab0e6521b70b0af7c6d8ca2c75dcae2403706fc4600a783b339a6530a476dafb9450c9436ca4050eb6bdee9b62e6e2cebfecf1e81dd709a2480dc07 + path: .yarn/plugins/@yarnpkg/plugin-engines.cjs + spec: 'https://raw.githubusercontent.com/devoto13/yarn-plugin-engines/main/bundles/%40yarnpkg/plugin-engines.js' diff --git a/packages/nx-cdk/src/generators/preset/files/LICENSE.template b/packages/nx-cdk/src/generators/preset/files/LICENSE.template new file mode 100644 index 0000000..26f3f77 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/LICENSE.template @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Aligent + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/nx-cdk/src/generators/preset/files/application/README.md.template b/packages/nx-cdk/src/generators/preset/files/application/README.md.template new file mode 100644 index 0000000..b32e0f1 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/README.md.template @@ -0,0 +1,73 @@ +# <%= name %> Application + +This application manages the deployment of microservices and their shared infrastructure. + +## Architecture + +This application deploys: + +_add details here_ + +## Configuration + +### Environment Parameters + +Parameters are managed through the `parameters/.env.csv` file by default + +```bash +# Pull down parameters from the playground environment to .env.csv +yarn nx run application:parameters + +# Update parameters from .env.csv +yarn nx run application:parameters:import + +# Custom filename and parameter path can be passed in as arguments +yarn nx run application:parameters --file .env.dev.csv --path /my/dev/path +``` + +## Deployment + +### Using yarn script from workspace root (Recommended) + +```bash +# Synthesize templates +yarn pg:synth + +# Deploy to playground +yarn pg:deploy +``` + +### Direct Nx Commands + +```bash +yarn nx run application:cdk +``` + +## Services + +This application deploys the following services: + +- _list services here_ + +## Testing + +### Mock Services + +The application includes mock services for testing integrations without external dependencies. + +- _list mock services here_ + +Change the value of the `/application/dev/url` SSM Parameter to switch between real and mock endpoints + +### Local Development + +```bash +# Type checking +yarn typecheck + +# Testing +yarn test + +# Linting +yarn lint +``` diff --git a/packages/nx-cdk/src/generators/preset/files/application/_internal/log-group-defaults-injector.ts.template b/packages/nx-cdk/src/generators/preset/files/application/_internal/log-group-defaults-injector.ts.template new file mode 100644 index 0000000..c20552d --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/_internal/log-group-defaults-injector.ts.template @@ -0,0 +1,100 @@ +import { RemovalPolicy, type IPropertyInjector } from 'aws-cdk-lib'; +import { LogGroup, RetentionDays, type LogGroupProps } from 'aws-cdk-lib/aws-logs'; + +interface Config { + duration: 'SHORT' | 'MEDIUM' | 'LONG'; +} + +/** + * Property injector for CloudWatch Log Groups with configuration-aware defaults + * + * Applies configuration-specific retention policies and removal settings to log groups. + * Different configurations balance between cost optimization and data retention needs. + * + * @example + * ```typescript + * // Apply configuration-specific defaults + * PropertyInjectors.of(scope).add( + * new LogGroupDefaultsInjector({ duration: 'SHORT' }).withProps({ + * logGroupName: '/custom/log/group', + * }) + * ); + * + * // Log groups automatically inherit configuration defaults + * new LogGroup(stack, 'MyLogGroup', { + * // retention and removal policy applied automatically + * }); + * ``` + * + * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_logs.LogGroup.html + */ +export class LogGroupDefaultsInjector implements IPropertyInjector { + readonly constructUniqueId = LogGroup.PROPERTY_INJECTION_ID; + private readonly config: Config; + private defaultProps: LogGroupProps; + + /** + * Creates a new LogGroupDefaultsInjector + * + * @param config - Configuration identifier used to select appropriate defaults. + */ + constructor(config: Config) { + const props = retentionProperties(config.duration); + this.config = { ...config }; + this.defaultProps = { ...props }; + } + + /** + * Creates a new injector instance with additional properties + * + * Returns a new injector that inherits the current configuration but includes + * additional properties that override the configuration defaults. + * + * @param props - Additional properties to merge with configuration defaults + * @returns A new injector instance with merged properties + * + * @example + * ```typescript + * const customInjector = new LogGroupDefaultsInjector({ duration: 'SHORT' }) + * .withProps({ + * logGroupName: '/aws/lambda/custom', + * retention: RetentionDays.ONE_MONTH, + * }); + * ``` + */ + public withProps(props: LogGroupProps) { + const modifiedInjector = new LogGroupDefaultsInjector(this.config); + modifiedInjector.defaultProps = { ...this.defaultProps, ...props }; + return modifiedInjector; + } + + /** + * Injects configuration-appropriate defaults into log group properties + * + * Merges configuration-specific retention and removal policies with user-provided properties. + * + * @param originalProps - Properties provided when creating the log group + * @param context - CDK injection context containing construct information + * @returns Merged properties with injected defaults + */ + public inject(originalProps: LogGroupProps) { + return { ...this.defaultProps, ...originalProps }; + } +} + +/** + * Get duration-specific log group properties + * + * @param duration - The duration to get the log group properties for + * @returns The log group properties for the duration + */ +function retentionProperties(duration: 'SHORT' | 'MEDIUM' | 'LONG') { + switch (duration) { + case 'SHORT': + return { retention: RetentionDays.ONE_WEEK, removalPolicy: RemovalPolicy.DESTROY }; + case 'MEDIUM': + return { retention: RetentionDays.SIX_MONTHS, removalPolicy: RemovalPolicy.DESTROY }; + default: + return { retention: RetentionDays.TWO_YEARS, removalPolicy: RemovalPolicy.RETAIN }; + } +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/_internal/microservice-checks.ts.template b/packages/nx-cdk/src/generators/preset/files/application/_internal/microservice-checks.ts.template new file mode 100644 index 0000000..79c7151 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/_internal/microservice-checks.ts.template @@ -0,0 +1,58 @@ +import { CfnResource } from 'aws-cdk-lib'; +import { NagMessageLevel, NagPack, rules, type NagPackProps } from 'cdk-nag'; +import type { IConstruct } from 'constructs'; + +/** + * Microservice Checks are a compilation of rules to validate infrastructure-as-code template + * against recommended practices using the cdk-nag library. + * + * @see https://github.com/cdk-patterns/cdk-nag/ + * + * @example + * const app = new App(); + * const stack = new Stack(app, 'MyStack'); + * Aspects.of(stack).add(new MicroservicesChecks()); + */ +export class MicroserviceChecks extends NagPack { + constructor(props?: NagPackProps) { + super(props); + this.packName = 'Microservices'; + } + + public visit(node: IConstruct) { + if (node instanceof CfnResource) { + this.applyRule({ + info: 'The Lambda function does not have an explicit memory value configured.', + explanation: + "Lambda allocates CPU power in proportion to the amount of memory configured. By default, your functions have 128 MB of memory allocated. You can increase that value up to 10 GB. With more CPU resources, your Lambda function's duration might decrease. You can use tools such as AWS Lambda Power Tuning to test your function at different memory settings to find the one that matches your cost and performance requirements the best.", + level: NagMessageLevel.ERROR, + rule: rules.lambda.LambdaDefaultMemorySize, + node: node, + }); + this.applyRule({ + info: 'The Lambda function does not have an explicitly defined timeout value.', + explanation: + 'Lambda functions have a default timeout of 3 seconds. If your timeout value is too short, Lambda might terminate invocations prematurely. On the other side, setting the timeout much higher than the average execution may cause functions to execute for longer upon code malfunction, resulting in higher costs and possibly reaching concurrency limits depending on how such functions are invoked. You can also use AWS Lambda Power Tuning to test your function at different timeout settings to find the one that matches your cost and performance requirements the best.', + level: NagMessageLevel.ERROR, + rule: rules.lambda.LambdaDefaultTimeout, + node: node, + }); + this.applyRule({ + info: 'The Lambda function does not have tracing set to Tracing.ACTIVE.', + explanation: + 'When a Lambda function has ACTIVE tracing, Lambda automatically samples invocation requests, based on the sampling algorithm specified by X-Ray.', + level: NagMessageLevel.ERROR, + rule: rules.lambda.LambdaTracing, + node: node, + }); + this.applyRule({ + info: 'The CloudWatch Log Group does not have an explicit retention policy defined.', + explanation: + 'By default, logs are kept indefinitely and never expire. You can adjust the retention policy for each log group, keeping the indefinite retention, or choosing a retention period between one day and 10 years. For Lambda functions, this applies to their automatically created CloudWatch Log Groups.', + level: NagMessageLevel.ERROR, + rule: rules.cloudwatch.CloudWatchLogGroupRetentionPeriod, + node: node, + }); + } + } +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template b/packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template new file mode 100644 index 0000000..5e3c3e6 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template @@ -0,0 +1,109 @@ +import { type IPropertyInjector } from 'aws-cdk-lib'; +import { Runtime, Tracing } from 'aws-cdk-lib/aws-lambda'; +import { NodejsFunction, type NodejsFunctionProps } from 'aws-cdk-lib/aws-lambda-nodejs'; + +interface Config { + sourceMap: boolean; +} + +/** + * Property injector for Node.js Lambda functions with configuration-aware defaults + * + * Applies configuration-specific bundling and runtime settings to Lambda functions. + * Different configurations can optimize for different priorities such as build speed, + * bundle size, or debugging capabilities. + * + * @example + * ```typescript + * // Apply configuration-specific defaults + * PropertyInjectors.of(scope).add( + * new NodeJsFunctionDefaultsInjector({ + * sourceMaps: true, + * esm: true, + * minify: true, + * }).withProps({ + * timeout: Duration.seconds(30), + * memorySize: 256, + * }) + * ); + * + * // Functions automatically inherit configuration defaults + * new Function(stack, 'MyFunction', { + * code: Code.fromAsset('src/lambda'), + * handler: 'index.handler', + * // bundling and runtime config applied automatically + * }); + * ``` + * + * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html + */ +export class NodeJsFunctionDefaultsInjector implements IPropertyInjector { + public readonly constructUniqueId = NodejsFunction.PROPERTY_INJECTION_ID; + private readonly config: Config; + private defaultProps: NodejsFunctionProps; + + /** + * Creates a new NodeJsFunctionDefaultsInjector + * + * @param config - Configuration identifier used to select appropriate defaults. Uses production defaults if not specified. + */ + constructor(config: Config = { sourceMap: true }) { + this.config = { ...config }; + this.defaultProps = { runtime: Runtime.NODEJS_22_X, tracing: Tracing.ACTIVE }; + } + + /** + * Creates a new injector instance with additional properties + * + * Returns a new injector that inherits the current configuration but includes + * additional properties that override the configuration defaults. + * + * @param props - Additional properties to merge with configuration defaults + * @returns A new injector instance with merged properties + * + * @example + * ```typescript + * const customInjector = new NodeJsFunctionDefaultsInjector({ + * sourceMaps: false, + * }) + * .withProps({ + * timeout: Duration.minutes(5), + * memorySize: 1024, + * }); + * ``` + * + * TODO: Provide a nice way to inherit global properties from previous injectors + */ + public withProps(props: NodejsFunctionProps) { + const modifiedInjector = new NodeJsFunctionDefaultsInjector(this.config); + modifiedInjector.defaultProps = { ...this.defaultProps, ...props }; + return modifiedInjector; + } + + /** + * Injects configuration-appropriate defaults into Lambda function properties + * + * Merges configuration-specific defaults with user-provided properties, + * automatically configuring bundling options and runtime settings. + * + * @param originalProps - Properties provided when creating the function + * @returns Merged properties with injected defaults + */ + public inject(originalProps: NodejsFunctionProps) { + // The NodeJsFunction constructor pre-sets runtime to 16.x or LATEST depending on feature flags + // We assume that using this injector means you want to standardise the runtime across all lambdas + const props = { + ...this.defaultProps, + ...originalProps, + runtime: this.defaultProps.runtime, + }; + + // If source maps are enabled in our bundling, add the required NODE_OPTIONS flag to the environment + const environment = { + ...props.environment, + ...(this.config.sourceMap ? { NODE_OPTIONS: '--enable-source-maps' } : {}), + }; + + return { ...props, environment }; + } +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/_internal/step-function-defaults-injector.ts.template b/packages/nx-cdk/src/generators/preset/files/application/_internal/step-function-defaults-injector.ts.template new file mode 100644 index 0000000..03b2380 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/_internal/step-function-defaults-injector.ts.template @@ -0,0 +1,126 @@ +import { type InjectionContext, type IPropertyInjector } from 'aws-cdk-lib'; +import { LogGroup } from 'aws-cdk-lib/aws-logs'; +import { + LogLevel, + StateMachine, + StateMachineType, + type StateMachineProps, +} from 'aws-cdk-lib/aws-stepfunctions'; +import type { Construct } from 'constructs'; + +type StepFunctionDefaults = Omit; + +/** + * Property injector for Step Functions with configuration-aware defaults + * + * Applies configuration-specific settings to Step Functions. All configurations enable + * X-Ray tracing by default for observability. For EXPRESS state machines, automatically + * creates log groups and configures comprehensive logging. + * + * @example + * ```typescript + * // Apply configuration-specific defaults + * PropertyInjectors.of(scope).add( + * new StepFunctionDefaultsInjector('dev').withProps({ + * timeout: Duration.minutes(30), + * }) + * ); + * + * // Step Functions automatically inherit defaults + * new StateMachine(stack, 'MyWorkflow', { + * stateMachineType: StateMachineType.EXPRESS, + * definitionBody: DefinitionBody.fromFile('workflow.asl.yaml'), + * // tracing enabled and logging configured automatically for EXPRESS + * }); + * ``` + * + * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_stepfunctions.StateMachine.html + */ +export class StepFunctionDefaultsInjector implements IPropertyInjector { + public readonly constructUniqueId = StateMachine.PROPERTY_INJECTION_ID; + private readonly config: Record; + private defaultProps: StateMachineProps; + + /** + * Creates a new StepFunctionDefaultsInjector + * + * @param config - Configuration identifier (currently unused but maintained for consistency). + * All configurations enable tracing by default. + */ + constructor(config: Record = {}) { + this.config = { ...config }; + this.defaultProps = { tracingEnabled: true }; + } + + /** + * Creates a new injector instance with additional properties + * + * Returns a new injector that inherits the current configuration but includes + * additional properties that override the configuration defaults. + * + * @param props - Additional properties to merge with configuration defaults + * @returns A new injector instance with merged properties + * + * @example + * ```typescript + * const customInjector = new StepFunctionDefaultsInjector('prod') + * .withProps({ + * timeout: Duration.hours(1), + * stateMachineName: 'custom-workflow', + * }); + * ``` + */ + public withProps(props: StateMachineProps) { + const modifiedInjector = new StepFunctionDefaultsInjector(this.config); + modifiedInjector.defaultProps = { ...this.defaultProps, ...props }; + return modifiedInjector; + } + + /** + * Injects configuration-appropriate defaults into Step Function properties + * + * Enables X-Ray tracing for all state machines. For EXPRESS state machines, + * automatically creates log groups and configures comprehensive logging. + * + * @param originalProps - Properties provided when creating the state machine + * @param context - CDK injection context containing construct information + * @returns Merged properties with injected defaults and logging configuration + */ + public inject(originalProps: StateMachineProps, context: InjectionContext) { + // Prepare logging configuration for EXPRESS step functions + const logging = expressLogProperties(context.scope, context.id, originalProps); + return { ...this.defaultProps, ...originalProps, ...logging }; + } +} + +/** + * Build the logging configuration for an express step function, respecting + * existing logging configuration. + * + * @param machineScope - The scope of the step function. + * @param machineId - The id of the step function. + * @param props - The properties for the step function. + * @returns The logging configuration for an express step function + */ +function expressLogProperties( + machineScope: Construct, + machineId: string, + props: StepFunctionDefaults +) { + if (props.stateMachineType !== StateMachineType.EXPRESS) { + return {}; + } + + // Create a new log group if one is not provided + const logGroup = + props.logs?.destination ?? new LogGroup(machineScope, `/aws/states/${machineId}`); + + return { + logs: { + destination: logGroup, + level: LogLevel.ALL, + includeExecutionData: true, + ...props.logs, + }, + }; +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/_internal/version-functions-aspect.ts.template b/packages/nx-cdk/src/generators/preset/files/application/_internal/version-functions-aspect.ts.template new file mode 100644 index 0000000..11983a7 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/_internal/version-functions-aspect.ts.template @@ -0,0 +1,74 @@ +import type { IAspect } from 'aws-cdk-lib'; +import { Function } from 'aws-cdk-lib/aws-lambda'; +import { + CfnStateMachineAlias, + CfnStateMachineVersion, + StateMachine, +} from 'aws-cdk-lib/aws-stepfunctions'; +import { IConstruct } from 'constructs'; + +/** + * Aspect that automatically adds versioning and aliases to Lambda and Step Functions + * + * Visits all constructs in the scope and automatically creates versions and aliases + * for supported resource types. This enables blue-green deployments, traffic shifting, + * and provides stable ARNs for external integrations. + * + * Currently supports: + * - Lambda Functions: Creates function aliases + * - Step Functions: Creates versions and aliases with 100% traffic routing + * + * @example + * ```typescript + * // Apply to entire app for automatic versioning + * Aspects.of(app).add(new VersionFunctionsAspect()); + * + * // Or with custom alias name + * Aspects.of(app).add(new VersionFunctionsAspect({ alias: 'PROD' })); + * ``` + */ +export class VersionFunctionsAspect implements IAspect { + /** + * Creates a new VersionFunctionsAspect + * + * @param props - Configuration for the aspect + * @param props.alias - Name for the alias to create. Defaults to 'LATEST' + */ + constructor( + private readonly props: { + alias: string; + } = { + alias: 'LATEST', + } + ) {} + + /** + * Visits a construct and applies versioning if it's a supported resource type + * + * For Lambda Functions: Adds a function alias pointing to $LATEST + * For Step Functions: Creates a version and alias with 100% traffic routing + * + * @param node - The construct to potentially add versioning to + */ + visit(node: IConstruct): void { + if (node instanceof StateMachine) { + const version = new CfnStateMachineVersion(node, `Version`, { + stateMachineArn: node.stateMachineArn, + }); + + new CfnStateMachineAlias(node, `Alias`, { + name: this.props.alias, + routingConfiguration: [ + { + stateMachineVersionArn: version.attrArn, + weight: 100, + }, + ], + }); + } + + if (node instanceof Function) { + node.addAlias(this.props.alias); + } + } +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template new file mode 100644 index 0000000..8371737 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template @@ -0,0 +1,42 @@ +#!/usr/bin/env node +import { App, Aspects, Tags } from 'aws-cdk-lib'; +import { ApplicationStage } from './lib/service-stacks.js'; + +// TODO Consider to pull this out to a separate construct repo so we can import and use later +import { LogGroupDefaultsInjector } from './_internal/log-group-defaults-injector.js'; +import { MicroserviceChecks } from './_internal/microservice-checks.js'; +import { NodeJsFunctionDefaultsInjector } from './_internal/nodejs-function-defaults-injector.js'; +import { StepFunctionDefaultsInjector } from './_internal/step-function-defaults-injector.ts'; +import { VersionFunctionsAspect } from './_internal/version-functions-aspect.js'; + +const APPLICATION_CONTEXT = { APPLICATION_OWNER: 'aligent' } as const; + +const app = new App({ + context: APPLICATION_CONTEXT, + propertyInjectors: [new NodeJsFunctionDefaultsInjector(), new StepFunctionDefaultsInjector()], +}); +Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER); + +// TODO: explain why we choose this setup instead of dynamic or use context +// https://dev.to/aws-heroes/how-to-use-aws-cdk-stage-and-when-to-choose-static-vs-dynamic-stack-creation-35h + +// Set up application stages +// NOTE: Property Injectors will only apply ONCE each, so adding one in stage +// overrides the same injector at the app level +const dev = new ApplicationStage(app, 'dev', { + propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'SHORT' })], +}); +Aspects.of(dev).add(new MicroserviceChecks()); + +const stg = new ApplicationStage(app, 'stg', { + propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'MEDIUM' })], +}); +Aspects.of(stg).add(new MicroserviceChecks()); + +const prd = new ApplicationStage(app, 'prd', { + propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'LONG' })], +}); +Aspects.of(prd).add(new MicroserviceChecks()); + +// Ensure lambdas and step functions are versioned and have the default alias +Aspects.of(prd).add(new VersionFunctionsAspect()); diff --git a/packages/nx-cdk/src/generators/preset/files/application/cdk.context.json.template b/packages/nx-cdk/src/generators/preset/files/application/cdk.context.json.template new file mode 100644 index 0000000..349dbe6 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/cdk.context.json.template @@ -0,0 +1,4 @@ +{ + "cli-telemetry": false, + "acknowledged-issue-numbers": [34892] +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/cdk.json.template b/packages/nx-cdk/src/generators/preset/files/application/cdk.json.template new file mode 100644 index 0000000..38e1a3a --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/cdk.json.template @@ -0,0 +1,92 @@ +{ + "app": "npx tsx bin/main.ts", + "watch": { + "include": ["**"], + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + "test" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": ["aws", "aws-cn"], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true, + "@aws-cdk/aws-eks:nodegroupNameAttribute": true, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": false, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": true, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": true, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": true, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": true, + "@aws-cdk/core:enableAdditionalMetadataCollection": true, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": false, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": true, + "@aws-cdk/aws-events:requireEventBusPolicySid": true, + "@aws-cdk/core:aspectPrioritiesMutating": true, + "@aws-cdk/aws-dynamodb:retainTableReplica": true, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": true, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": true, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": true, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": true, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": true + } +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template b/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template new file mode 100644 index 0000000..f96a879 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template @@ -0,0 +1,17 @@ +import { Stage, Tags, type StageProps } from 'aws-cdk-lib'; +import type { Construct } from 'constructs'; + +/** + * Application stage + * + * This is the main entry point for the application. + * It is used to define context and compose service stacks. + */ +export class ApplicationStage extends Stage { + constructor(scope: Construct, id: string, props?: StageProps) { + super(scope, id, props); + Tags.of(this).add('STAGE', id); + + // Instantiate service stacks here as required + } +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/package.json.template b/packages/nx-cdk/src/generators/preset/files/application/package.json.template new file mode 100644 index 0000000..288ed69 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/package.json.template @@ -0,0 +1,27 @@ +{ + "name": "application", + "type": "module", + "main": "./bin/main.ts", + "types": "./bin/main.ts", + "nx": { + "tags": [ + "scope:application" + ], + "targets": { + "cdk": { + "executor": "nx:run-commands", + "options": { + "color": true, + "command": "cdk", + "cwd": "{projectRoot}" + } + }, + "parameters": { + "executor": "nx:run-commands", + "options": { + "path": "/application/dev" + } + } + } + } +} diff --git a/packages/nx-cdk/src/generators/preset/files/cdk-config.yml.template b/packages/nx-cdk/src/generators/preset/files/cdk-config.yml.template new file mode 100644 index 0000000..067c911 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/cdk-config.yml.template @@ -0,0 +1,16 @@ +cdk-pipe: + commands: + cdk: + bootstrap: yarn nx run application:cdk bootstrap + deploy: yarn nx run application:cdk deploy + synth: yarn nx run application:cdk synth + diff: yarn nx run application:cdk diff + npm: + checks: + lint: yarn lint + format: yarn lint # Formatting is controlled by the lint step, we turn this off in the pipeline anyway + install: yarn install --immutable + beforeScripts: + - yarn --version + afterScripts: + - echo "Deployment is completed" diff --git a/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template b/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template new file mode 100644 index 0000000..2e9270c --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template @@ -0,0 +1,63 @@ +import { eslintConfigs } from '@aligent/ts-code-standards'; +import nxEslintPlugin from '@nx/eslint-plugin'; +import jsonParser from 'jsonc-eslint-parser'; + +const eslintBaseConfig = [ + ...eslintConfigs.base, + { + ignores: [ + '**/*.js', + '**/*.cjs', + '**/*.mjs', + '**/coverage', + '**/cdk.out', + '**/dist', + '**/out-tsc', + '**/vite.config.*.timestamp*', + '**/vitest.config.*.timestamp*', + ], + }, + { + files: ['**/*.ts'], + plugins: { '@nx': nxEslintPlugin }, + rules: { + '@nx/enforce-module-boundaries': [ + 'error', + { + allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?[jt]s$'], + enforceBuildableLibDependency: true, + depConstraints: [ + { + sourceTag: 'scope:applications', + onlyDependOnLibsWithTags: ['scope:libs', 'scope:services'], + }, + { + sourceTag: 'scope:services', + onlyDependOnLibsWithTags: ['scope:libs', 'scope:services'], + }, + { + sourceTag: 'scope:libs', + onlyDependOnLibsWithTags: ['scope:libs'], + }, + ], + }, + ], + 'import/no-extraneous-dependencies': [ + 'warn', + { + optionalDependencies: false, + peerDependencies: false, + bundledDependencies: false, + packageDir: ['.', '..', '../..'], + }, + ], + 'no-console': 'warn', + }, + }, + { + files: ['**/*.json'], + languageOptions: { parser: jsonParser }, + }, +]; + +export default eslintBaseConfig; diff --git a/packages/nx-cdk/src/generators/preset/files/prettier.config.mjs.template b/packages/nx-cdk/src/generators/preset/files/prettier.config.mjs.template new file mode 100644 index 0000000..1ed145e --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/prettier.config.mjs.template @@ -0,0 +1,3 @@ +import { prettierConfig } from '@aligent/ts-code-standards'; + +export default prettierConfig; diff --git a/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template b/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template new file mode 100644 index 0000000..c15f48b --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template @@ -0,0 +1,67 @@ +import { defineConfig } from '@rsbuild/core'; +import fg from 'fast-glob'; +import { extname, resolve } from 'node:path'; + +const HANDLERS_PATH = 'src/runtime/handlers'; + +/** + * Prepare Rsbuild config that bundles all typescript files in a single directory in to separate files + * This is used to bundle lambda handlers with their own dependencies for separate upload to AWS Lambda + * + * @param {string} configPath Full path to the rsbuild.config.mjs file this is used in - usually import.meta.dirname; + * @param {string} subPath Relative path to the handlers directory. Default is 'src/runtime/handlers' + * @returns Rsbuild config for multiple lambda handlers + */ +export function defineLambdaConfig(configPath, subPath = HANDLERS_PATH) { + if (subPath.includes('..')) throw new Error('Invalid path provided'); + const basePath = resolve(configPath, subPath); + const handlers = fg.sync(`${basePath}/**/*.ts`); + + // Format an entry object containing each file found in the folder + // Maintains subfolder structure + // e.g. { 'test/log-object': 'test/log-object' } + const entry = Object.fromEntries( + handlers.map(handler => { + const bundledPath = handler.replace(`${basePath}/`, ''); + const entryName = bundledPath.replace(extname(bundledPath), ''); + return [entryName, handler]; + }) + ); + + return defineConfig({ + source: { + entry, + tsconfigPath: './tsconfig.lib.json', + }, + performance: { + chunkSplit: { + // Not sure this is necessary for single-file-bundling but seems safer to set it + strategy: 'all-in-one', + }, + }, + output: { + // Only bundle javascript/typescript code + target: 'node', + // Output ESM modules + module: true, + filename: { js: '[name]/index.mjs' }, + // Don't output license comments in bundled code + legalComments: 'none', + // FIXME: handle the following things by stag/environment + // sourceMap: true, + // minify: true, + }, + tools: { + rspack: { + output: { + // Forces bundler to include all dependencies in one file + asyncChunks: false, + }, + optimization: { + // Prevent bundler from wrapping handlers in an IIFE + avoidEntryIife: true, + }, + }, + }, + }); +} diff --git a/packages/nx-cdk/src/generators/preset/files/tsconfig.json.template b/packages/nx-cdk/src/generators/preset/files/tsconfig.json.template new file mode 100644 index 0000000..ad107c5 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/tsconfig.json.template @@ -0,0 +1,6 @@ +{ + "extends": "@aligent/ts-code-standards/tsconfigs-extend", + "compileOnSave": false, + "files": [], + "references": [{"path": "./application"}] +} diff --git a/packages/nx-cdk/src/generators/preset/files/vitest.config.base.mjs.template b/packages/nx-cdk/src/generators/preset/files/vitest.config.base.mjs.template new file mode 100644 index 0000000..9f64862 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/vitest.config.base.mjs.template @@ -0,0 +1,39 @@ +import { resolve } from 'node:path'; +import { defineConfig } from 'vitest/config'; + +// More information about mode: https://vite.dev/guide/env-and-mode.html#node-env-and-modes +export const vitestBaseConfig = defineConfig(({ command, mode }) => { + return { + test: { + globals: true, + watch: false, + environment: 'node', + reporters: ['default'], + coverage: { + provider: 'v8', + exclude: [ + 'node_modules/', + '**/types', + '*.mjs', + '**/__data__', + '**/dist', + '**/out-tsc', + ], + thresholds: { + branches: 80, + functions: 80, + lines: 80, + statements: 80, + }, + }, + include: [ + 'src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}', + 'tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}', + ], + setupFiles: [ + // Include the root setup file in all tests that extend this config + resolve(import.meta.dirname, './vitest.global.setup.mjs'), + ], + }, + }; +}); diff --git a/packages/nx-cdk/src/generators/preset/files/vitest.global.setup.mjs.template b/packages/nx-cdk/src/generators/preset/files/vitest.global.setup.mjs.template new file mode 100644 index 0000000..6fef67a --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/vitest.global.setup.mjs.template @@ -0,0 +1,109 @@ +import { beforeAll } from 'vitest' + +beforeAll(() => { + expect.addSnapshotSerializer( + replaceProperties({ property: [ + // Replace asset storage locations in Lambda function snapshots + 'Code.S3Bucket', + 'Code.S3Key', + // Replace asset storage locations in Step Function snapshots + 'DefinitionS3Location.Bucket', + 'DefinitionS3Location.Key' + ] }) + ); +}) + +const PLACEHOLDER = '[SNAPSHOT_PLACEHOLDER]'; +const isObject = (val) => !!val && typeof val === 'object'; + +// Helper function to traverse object and find properties to replace +const findPropertiesToReplace = ( + obj, + property, + path = [] +) => { + const results = []; + + for (const [key, value] of Object.entries(obj)) { + const currentPath = [...path, key]; + const fullPath = currentPath.join('.'); + + let shouldReplace = false; + + if (property instanceof RegExp) { + shouldReplace = property.test(fullPath); + } else if (Array.isArray(property)) { + shouldReplace = property.includes(fullPath); + } else { + shouldReplace = fullPath === property; + } + + if (shouldReplace && value !== PLACEHOLDER) { + results.push({ path: currentPath, value }); + } + + if (isObject(value)) { + results.push(...findPropertiesToReplace(value, property, currentPath)); + } + } + + return results; +}; + +// Helper function to set value at nested path +const setValueAtPath = (obj, path, value) => { + let current = obj; + + for (let i = 0; i < path.length - 1; i++) { + const key = path[i]; + if (!isObject(current[key])) { + current[key] = {}; + } + current = current[key]; + } + + current[path[path.length - 1]] = value; +}; + +/** + * Custom serializer for vitest snapshot tests + * Allows replacing properties in a snapshot with placeholder values. + * + * Properties to replace can be specified as a string, array of strings, or a single regular expression + * Nested properties can be specified using dot notation. + * + * @example + * ``` + * beforeAll(() => { + * expect.addSnapshotSerializer( + * // Will replace the value of Code: { S3Bucket: '...', S3Key: '...' } anywhere in the object structure + * replaceProperties({ property: ['Code.S3Bucket', 'Code.S3Key'] }) + * ); + * }) + * ``` + * + * @param {{ property: string | string[] | RegExp, placeholder?: string }} input + * @returns + */ +export const replaceProperties = ({ + property, + placeholder = PLACEHOLDER, +}) => { + return { + test(val) { + if (!isObject(val)) return false; + const propertiesToReplace = findPropertiesToReplace(val, property); + return propertiesToReplace.length > 0; + }, + serialize(val, config, indentation, depth, refs, printer) { + const clone = { ...val }; + const propertiesToReplace = findPropertiesToReplace(clone, property); + + for (const { path } of propertiesToReplace) { + setValueAtPath(clone, path, placeholder); + } + + return printer(clone, config, indentation, depth, refs); + }, + } +}; diff --git a/packages/nx-cdk/src/generators/preset/preset.ts b/packages/nx-cdk/src/generators/preset/preset.ts index 8739a11..28627d6 100644 --- a/packages/nx-cdk/src/generators/preset/preset.ts +++ b/packages/nx-cdk/src/generators/preset/preset.ts @@ -1,17 +1,33 @@ -import { addProjectConfiguration, formatFiles, generateFiles, Tree } from '@nx/devkit'; -import * as path from 'path'; +import { formatFiles, generateFiles, Tree, updateNxJson, writeJson } from '@nx/devkit'; +import { join } from 'path'; +import { NX_JSON } from '../helpers/configs/nxJson'; +import { + constructPackageJsonFile, + constructProjectTsConfigFiles, + getGeneratorVersion, +} from '../helpers/utilities'; import { PresetGeneratorSchema } from './schema'; export async function presetGenerator(tree: Tree, options: PresetGeneratorSchema) { - // TODO implement the preset generator here - const projectRoot = `libs/${options.name}`; - addProjectConfiguration(tree, options.name, { - root: projectRoot, - projectType: 'library', - sourceRoot: `${projectRoot}/src`, - targets: {}, + const { name, nodeVersion } = options; + const version = getGeneratorVersion(); + + generateFiles(tree, join(__dirname, 'files'), '.', { + ...options, + template: '', }); - generateFiles(tree, path.join(__dirname, 'files'), projectRoot, options); + + updateNxJson(tree, { ...NX_JSON }); + + const packageJson = constructPackageJsonFile(name, version, nodeVersion); + writeJson(tree, 'package.json', packageJson); + + // Generate application's tsconfigs + const { tsConfig, tsConfigLib, tsConfigSpec } = constructProjectTsConfigFiles('application'); + writeJson(tree, 'application/tsconfig.json', tsConfig); + writeJson(tree, 'application/tsconfig.lib.json', tsConfigLib); + writeJson(tree, 'application/tsconfig.spec.json', tsConfigSpec); + await formatFiles(tree); } diff --git a/packages/nx-cdk/src/generators/preset/schema.d.ts b/packages/nx-cdk/src/generators/preset/schema.d.ts index 9ddd208..39eb3a4 100644 --- a/packages/nx-cdk/src/generators/preset/schema.d.ts +++ b/packages/nx-cdk/src/generators/preset/schema.d.ts @@ -1,3 +1,4 @@ export interface PresetGeneratorSchema { name: string; + nodeVersion: string; } diff --git a/packages/nx-cdk/src/generators/preset/schema.json b/packages/nx-cdk/src/generators/preset/schema.json index a4b0aed..ef8cc5d 100644 --- a/packages/nx-cdk/src/generators/preset/schema.json +++ b/packages/nx-cdk/src/generators/preset/schema.json @@ -6,12 +6,26 @@ "properties": { "name": { "type": "string", - "description": "", + "description": "The name of the project/application", "$default": { "$source": "argv", "index": 0 }, - "x-prompt": "What name would you like to use?" + "x-prompt": "What is the name of the project?", + "pattern": "^[A-Za-z0-9-]+$", + "patternErrorMessage": "Project name must contain only alphanumeric characters and dashes" + }, + "nodeVersion": { + "type": "string", + "description": "The target Node.js version", + "$default": { + "$source": "argv", + "index": 1 + }, + "default": "24.11.0", + "x-prompt": "What is the target Node.js version the project?", + "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$", + "patternErrorMessage": "Node.js version must be a valid semantic version (semver), e.g. 22.10.0 or 24.10.0" } }, "required": ["name"] diff --git a/packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template b/packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template index d55869b..67fc241 100644 --- a/packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template +++ b/packages/nx-cdk/src/generators/service/files/vitest.config.mjs.template @@ -1,9 +1,9 @@ import { defineConfig, mergeConfig } from 'vitest/config'; -import { viteBaseConfig } from '../../vitest.config.base.mjs'; +import { vitestBaseConfig } from '../../vitest.config.base.mjs'; export default defineConfig(configEnv => { return mergeConfig( - viteBaseConfig(configEnv), + vitestBaseConfig(configEnv), defineConfig({ cacheDir: '../../node_modules/.vite/<%= name %>', test: { diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index 72a17a3..e161de1 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -1,4 +1,5 @@ -import { formatFiles, generateFiles, Tree, updateJson } from '@nx/devkit'; +import { formatFiles, generateFiles, Tree, updateJson, writeJson } from '@nx/devkit'; +import { constructProjectTsConfigFiles } from '../helpers/utilities'; import { ServiceGeneratorSchema } from './schema'; const SERVICES_FOLDER = 'services'; @@ -21,37 +22,37 @@ function addTsConfigReference(tree: Tree, referencePath: string) { }); } -function registerWithTypecheckPlugin(tree: Tree, referencePath: string) { - updateJson(tree, 'nx.json', json => { - json.plugins ??= []; - - // Services should be non-buildable, so we need to register them with the typescript plugin configuration - // that adds typechecking but not a build argument - const plugin = json.plugins.find( - (p: { - plugin: string; - include: string[]; - options?: { typecheck?: unknown; build?: unknown }; - }) => p.plugin === '@nx/js/typescript' && p.options?.typecheck && !p.options?.build - ); - - if (!plugin) { - json.plugins.push({ - plugin: '@nx/js/typescript', - options: { - typecheck: { - targetName: 'typecheck', - }, - }, - include: [referencePath], - }); - } else { - plugin.include.push(referencePath); - } +// function registerWithTypecheckPlugin(tree: Tree, referencePath: string) { +// updateJson(tree, 'nx.json', json => { +// json.plugins ??= []; - return json; - }); -} +// // Services should be non-buildable, so we need to register them with the typescript plugin configuration +// // that adds typechecking but not a build argument +// const plugin = json.plugins.find( +// (p: { +// plugin: string; +// include: string[]; +// options?: { typecheck?: unknown; build?: unknown }; +// }) => p.plugin === '@nx/js/typescript' && p.options?.typecheck && !p.options?.build +// ); + +// if (!plugin) { +// json.plugins.push({ +// plugin: '@nx/js/typescript', +// options: { +// typecheck: { +// targetName: 'typecheck', +// }, +// }, +// include: [referencePath], +// }); +// } else { +// plugin.include.push(referencePath); +// } + +// return json; +// }); +// } export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSchema) { const projectRoot = `${SERVICES_FOLDER}/${options.name}`; @@ -60,15 +61,20 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche tree.write(`${SERVICES_FOLDER}/.gitkeep`, ''); } - generateFiles(tree, 'files', projectRoot, { - ...options, - template: '', - }); + generateFiles(tree, 'files', projectRoot, { ...options, template: '' }); - // Add the service to tsconfig.json references and nx.json plugins + // Generate service's tsconfigs + const { tsConfig, tsConfigLib, tsConfigSpec } = constructProjectTsConfigFiles('service'); + writeJson(tree, `${projectRoot}/tsconfig.json`, tsConfig); + writeJson(tree, `${projectRoot}/tsconfig.lib.json`, tsConfigLib); + writeJson(tree, `${projectRoot}/tsconfig.spec.json`, tsConfigSpec); + + // Add the service to tsconfig.json references // The root application needs to import stacks from the service addTsConfigReference(tree, `./${projectRoot}`); - registerWithTypecheckPlugin(tree, `${projectRoot}/*`); + + // FIXME Double check if this is needed or not + // registerWithTypecheckPlugin(tree, `${projectRoot}/*`); await formatFiles(tree); } From c2c6e48f3d7874d3a953980284a46e2bce6bd375 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Fri, 28 Nov 2025 14:10:44 +1100 Subject: [PATCH 03/24] MI-250: Added main readme for nx-cdk --- packages/nx-cdk/README.md | 142 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/packages/nx-cdk/README.md b/packages/nx-cdk/README.md index bf7f629..da75a15 100644 --- a/packages/nx-cdk/README.md +++ b/packages/nx-cdk/README.md @@ -1,11 +1,143 @@ # Nx Cloud Development Kit -The `@aligent/nx-cdk` package provides Nx generators for AWS CDK development. +The `@aligent/nx-cdk` package provides Nx generators for AWS CDK development. It helps you scaffold new CDK projects and services within an Nx monorepo structure. -## Preset Generator +## Generators - +### Preset Generator -## Service Generator +The preset generator initializes a new CDK project with a complete workspace structure, including configuration files, build tools, and an application scaffold. - +#### Usage + +```bash +npx nx g @aligent/nx-cdk:preset [options] +``` + +Or when creating a new workspace: + +```bash +npx create-nx-workspace@latest --preset=@aligent/nx-cdk +``` + +#### Options + +| Option | Type | Required | Default | Description | +| ------------- | ------ | -------- | --------- | -------------------------------------------------------------------------------- | +| `name` | string | Yes | - | The name of the project/application (alphanumeric and dashes only) | +| `nodeVersion` | string | No | `24.11.0` | The target Node.js version for the project (must be valid semver, e.g., 22.10.0) | + +#### What it creates + +The preset generator scaffolds: + +- **Root configuration files**: + - `eslint.config.mjs` - ESLint configuration + - `prettier.config.mjs` - Prettier configuration + - `rsbuild.config.base.mjs` - Base RSBuild configuration + - `vitest.config.base.mjs` - Base Vitest configuration + - `vitest.global.setup.mjs` - Global Vitest setup + - `tsconfig.json` - Root TypeScript configuration + - `nx.json` - Nx workspace configuration + - `package.json` - Project dependencies and scripts + - `cdk-config.yml` - CDK configuration + - `LICENSE` - Project license + +- **Application folder** (`application/`): + - `cdk.json` - CDK app configuration + - `cdk.context.json` - CDK context + - `bin/main.ts` - CDK app entry point + - `lib/service-stacks.ts` - Service stacks definition + - TypeScript configurations (`tsconfig.json`, `tsconfig.lib.json`, `tsconfig.spec.json`) + +#### Example + +```bash +# Create a new project named "my-cdk-app" with Node.js 22.10.0 +npx nx g @aligent/nx-cdk:preset my-cdk-app --nodeVersion=22.10.0 +``` + +### Service Generator + +The service generator creates a new CDK service within the `services/` folder of your existing CDK project. Each service is configured as a separate package with its own build configuration and testing setup. + +#### Usage + +```bash +npx nx g @aligent/nx-cdk:service +``` + +#### Options + +| Option | Type | Required | Description | +| ------ | ------ | -------- | ------------------------------------------------------------------------- | +| `name` | string | Yes | The name of the service (cannot contain 'Stack' or 'Service' in the name) | + +#### What it creates + +The service generator creates a new service in `services//` with: + +- **Service files**: + - `src/index.ts` - Service entry point + - `package.json` - Service-specific dependencies + - `README.md` - Service documentation + - `eslint.config.mjs` - ESLint configuration + - `rsbuild.config.mjs` - RSBuild configuration + - `vitest.config.mjs` - Vitest configuration + - TypeScript configurations (`tsconfig.json`, `tsconfig.lib.json`, `tsconfig.spec.json`) + +- **Root updates**: + - Adds the service to the root `tsconfig.json` references for proper TypeScript project references + +- **Application updates**: + - Adds the stack to the main CDK application + +#### Example + +```bash +# Create a new service named "user-management" +npx nx g @aligent/nx-cdk:service user-management + +# Create a new service named "payment-processing" +npx nx g @aligent/nx-cdk:service payment-processing +``` + +## Project Structure + +After using both generators, your project structure will look like: + +``` +my-cdk-app/ +ā”œā”€ā”€ application/ +│ ā”œā”€ā”€ bin/ +│ │ └── main.ts +│ ā”œā”€ā”€ lib/ +│ │ └── service-stacks.ts +│ ā”œā”€ā”€ _internal/ +│ │ ā”œā”€ā”€ version-functions-aspect.ts +│ │ ā”œā”€ā”€ nodejs-function-defaults-injector.ts +│ │ ā”œā”€ā”€ step-function-defaults-injector.ts +│ │ ā”œā”€ā”€ log-group-defaults-injector.ts +│ │ └── microservice-checks.ts +│ ā”œā”€ā”€ cdk.json +│ ā”œā”€ā”€ cdk.context.json +│ └── package.json +ā”œā”€ā”€ services/ +│ ā”œā”€ā”€ user-management/ +│ │ ā”œā”€ā”€ src/ +│ │ │ └── index.ts +│ │ ā”œā”€ā”€ package.json +│ │ └── ... +│ └── payment-processing/ +│ ā”œā”€ā”€ src/ +│ │ └── index.ts +│ ā”œā”€ā”€ package.json +│ └── ... +ā”œā”€ā”€ nx.json +ā”œā”€ā”€ package.json +└── tsconfig.json +``` + +## License + +MIT From 08b8d7240ba185bc033c1253dd99a3937aba7a28 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Fri, 28 Nov 2025 14:57:50 +1100 Subject: [PATCH 04/24] MI-250: Update documents --- README.md | 6 ++- .../generators/helpers/configs/packageJson.ts | 8 ++-- .../files/application/README.md.template | 13 +++--- .../files/application/bin/main.ts.template | 42 +++++++++++++++---- .../service/files/README.md.template | 6 ++- 5 files changed, 53 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index df89abc..a3a6eff 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Aligent's monorepo for Microservice Development Utilities. For more details abou # Packages - [Microservice Util Lib](/packages/microservice-util-lib/README.md) +- [Nx CDK](/packages/nx-cdk/README.md) - [Nx Openapi](/packages/nx-openapi/README.md) - [Nx Serverless](/packages/nx-serverless/README.md) (obsoleted) @@ -108,8 +109,10 @@ npx nx run-many -t publish # Stop local registry when done npx nx stop-local-registry ``` + ### Note -- At the moment, we do not include `verdaccio` in our dev dependencies yet because of [CVE-2025-56200]https://github.com/advisories/GHSA-9965-vmph-33xx vulnerable in one of Verdaccio v6.2.1 dependencies. It will be added back once they resolve the issue. For now, we will need to add it in when we use it and remove it before making a PR. + +- At the moment, we do not include `verdaccio` in our dev dependencies yet because of [CVE-2025-56200]https://github.com/advisories/GHSA-9965-vmph-33xx vulnerable in one of Verdaccio v6.2.1 dependencies. It will be added back once they resolve the issue. For now, we will need to add it in when we use it and remove it before making a PR. ## Project Structure @@ -117,6 +120,7 @@ npx nx stop-local-registry microservice-development-utilities/ ā”œā”€ā”€ packages/ │ ā”œā”€ā”€ microservice-util-lib/ # Utility library for microservices +│ ā”œā”€ā”€ nx-cdk/ # Nx plugin for CDK project generation │ ā”œā”€ā”€ nx-openapi/ # Nx plugin for OpenAPI code generation │ └── nx-serverless/ # Nx plugin for Serverless project generation (obsoleted) └── package.json # Root package configuration diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 386cab2..0b677a6 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -18,11 +18,11 @@ export const PACKAGE_JSON = { }, dependencies: {}, devDependencies: { - // '@aligent/cdk-constructs': '^0.0.1', FIXME: this one seems to be a private package + '@aligent/step-function-from-file': '^0.3.2', '@aligent/ts-code-standards': '^4.1.0', '@nx/eslint': '21.5.2', '@nx/eslint-plugin': '21.5.2', - '@nx/js': '21.5.2', // TODO we may want to remove this package, double check if it's actually needed + // '@nx/js': '21.5.2', // TODO double check if it's actually needed '@nx/rsbuild': '21.5.2', '@nx/vite': '21.5.2', '@rsbuild/core': '^1.5.6', @@ -39,7 +39,7 @@ export const PACKAGE_JSON = { 'aws-cdk-lib': '^2.230.0', 'cdk-nag': '^2.37.55', constructs: '^10.4.3', - esbuild: '~0.25.8', // TODO: Do we need this package now that we're using rsbuild instead + esbuild: '~0.25.8', // TODO Do we need this package now that we're using rsbuild instead 'esbuild-visualizer': '^0.7.0', eslint: '^9.32.0', 'eslint-config-prettier': '10.1.8', @@ -47,7 +47,7 @@ export const PACKAGE_JSON = { jiti: '2.5.1', 'jsonc-eslint-parser': '^2.4.0', nx: '21.5.2', - // open: '^10.2.0', TODO Double check what is this and why it's here? + // open: '^10.2.0', // TODO Double check what is this and why it's here? prettier: '^3.6.2', 'store-parameters': '^1.0.6', tslib: '^2.8.1', diff --git a/packages/nx-cdk/src/generators/preset/files/application/README.md.template b/packages/nx-cdk/src/generators/preset/files/application/README.md.template index b32e0f1..b34e3c5 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/README.md.template +++ b/packages/nx-cdk/src/generators/preset/files/application/README.md.template @@ -4,9 +4,12 @@ This application manages the deployment of microservices and their shared infras ## Architecture -This application deploys: + -_add details here_ +## Services + + + ## Configuration @@ -43,12 +46,6 @@ yarn pg:deploy yarn nx run application:cdk ``` -## Services - -This application deploys the following services: - -- _list services here_ - ## Testing ### Mock Services diff --git a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template index 8371737..e9145d8 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template @@ -2,7 +2,7 @@ import { App, Aspects, Tags } from 'aws-cdk-lib'; import { ApplicationStage } from './lib/service-stacks.js'; -// TODO Consider to pull this out to a separate construct repo so we can import and use later +// TODO Pull this out to constructs repo so we can import and use later import { LogGroupDefaultsInjector } from './_internal/log-group-defaults-injector.js'; import { MicroserviceChecks } from './_internal/microservice-checks.js'; import { NodeJsFunctionDefaultsInjector } from './_internal/nodejs-function-defaults-injector.js'; @@ -17,12 +17,34 @@ const app = new App({ }); Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER); -// TODO: explain why we choose this setup instead of dynamic or use context -// https://dev.to/aws-heroes/how-to-use-aws-cdk-stage-and-when-to-choose-static-vs-dynamic-stack-creation-35h - -// Set up application stages -// NOTE: Property Injectors will only apply ONCE each, so adding one in stage -// overrides the same injector at the app level +/** + * Static Stage Creation Approach + * + * We use static stage creation (explicitly defining dev, stg, prd) for several reasons: + * + * 1. **Predictability**: All stages are known at synthesis time, making the CDK app + * behavior deterministic and easier to reason about. + * + * 2. **Type Safety**: Static definitions provide better IDE support, autocompletion, + * and compile-time type checking for stage-specific configurations. + * + * 3. **Explicit Configuration**: Each stage's unique settings (e.g., log retention + * durations, aspects, property injectors) are clearly visible in the code without + * needing to trace through dynamic logic. + * + * 4. **Simpler Deployment**: CDK can synthesize all stages in a single pass without + * requiring runtime context lookups or conditional logic. + * + * 5. **CI/CD Integration**: Static stages integrate seamlessly with standard CI/CD + * pipelines where environment configuration is managed externally. + * + * @see {@link https://dev.to/aws-heroes/how-to-use-aws-cdk-stage-and-when-to-choose-static-vs-dynamic-stack-creation-35h|Static vs Dynamic Stack Creation} + * + * @remarks Property Injector Behavior + * Property injectors are applied based on their class type and will only execute once per + * construct tree. When the same injector type is defined at both app and stage levels, the + * stage-level injector takes precedence and overrides the app-level configuration. + */ const dev = new ApplicationStage(app, 'dev', { propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'SHORT' })], }); @@ -38,5 +60,9 @@ const prd = new ApplicationStage(app, 'prd', { }); Aspects.of(prd).add(new MicroserviceChecks()); -// Ensure lambdas and step functions are versioned and have the default alias +/** + * This aspect ensures all Lambda functions and Step Functions in production + * are automatically versioned and have a stable 'live' alias pointing to the + * current version, enabling zero-downtime deployments. + */ Aspects.of(prd).add(new VersionFunctionsAspect()); diff --git a/packages/nx-cdk/src/generators/service/files/README.md.template b/packages/nx-cdk/src/generators/service/files/README.md.template index c6e9533..0146d47 100644 --- a/packages/nx-cdk/src/generators/service/files/README.md.template +++ b/packages/nx-cdk/src/generators/service/files/README.md.template @@ -4,7 +4,11 @@ This is a CDK service generated using `@aligent/nx-cdk` for Nx. ## Architecture -[Add your architecture documentation here] + + +# Technical Decisions + + ## Development From 294d40a4f075291c660ebe539bbb990975601008 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Fri, 28 Nov 2025 16:00:19 +1100 Subject: [PATCH 05/24] MI-250: Couple of minor bug fixes --- README.md | 6 ++-- packages/nx-cdk/README.md | 13 ------- packages/nx-cdk/project.json | 5 +++ .../src/generators/helpers/utilities.ts | 4 +-- .../preset/files/.gitignore.template | 36 +++++++++++++------ 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index a3a6eff..0801777 100644 --- a/README.md +++ b/README.md @@ -101,13 +101,13 @@ To test packages locally before publishing, you can use the local `verdaccio` re ```bash # Start local registry -npx nx start-local-registry +npx nx start-local-registry microservice-development-utilities # In another terminal, publish packages locally -npx nx run-many -t publish +npx nx release publish # Stop local registry when done -npx nx stop-local-registry +npx nx stop-local-registry microservice-development-utilities ``` ### Note diff --git a/packages/nx-cdk/README.md b/packages/nx-cdk/README.md index da75a15..85d0c07 100644 --- a/packages/nx-cdk/README.md +++ b/packages/nx-cdk/README.md @@ -10,12 +10,6 @@ The preset generator initializes a new CDK project with a complete workspace str #### Usage -```bash -npx nx g @aligent/nx-cdk:preset [options] -``` - -Or when creating a new workspace: - ```bash npx create-nx-workspace@latest --preset=@aligent/nx-cdk ``` @@ -50,13 +44,6 @@ The preset generator scaffolds: - `lib/service-stacks.ts` - Service stacks definition - TypeScript configurations (`tsconfig.json`, `tsconfig.lib.json`, `tsconfig.spec.json`) -#### Example - -```bash -# Create a new project named "my-cdk-app" with Node.js 22.10.0 -npx nx g @aligent/nx-cdk:preset my-cdk-app --nodeVersion=22.10.0 -``` - ### Service Generator The service generator creates a new CDK service within the `services/` folder of your existing CDK project. Each service is configured as a separate package with its own build configuration and testing setup. diff --git a/packages/nx-cdk/project.json b/packages/nx-cdk/project.json index ddeb1bc..73ee101 100644 --- a/packages/nx-cdk/project.json +++ b/packages/nx-cdk/project.json @@ -35,6 +35,11 @@ } ] } + }, + "nx-release-publish": { + "options": { + "packageRoot": "dist/nx-cdk" + } } }, "tags": ["nx", "plugin", "cdk"] diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts index 75cee60..287f222 100644 --- a/packages/nx-cdk/src/generators/helpers/utilities.ts +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -15,13 +15,13 @@ export function constructPackageJsonFile(name: string, version: string, nodeVers const packageJson = Object.fromEntries( Object.entries({ - ...PACKAGE_JSON, name: `@${name}/integrations`, description: `${name} integrations mono-repository`, version, + ...PACKAGE_JSON, devDependencies, engines: { node: `^${nodeVersionMajor}.${nodeVersionMinor}.0` }, - }).sort() + }) ); return packageJson; diff --git a/packages/nx-cdk/src/generators/preset/files/.gitignore.template b/packages/nx-cdk/src/generators/preset/files/.gitignore.template index 6a3d32b..8a0784f 100644 --- a/packages/nx-cdk/src/generators/preset/files/.gitignore.template +++ b/packages/nx-cdk/src/generators/preset/files/.gitignore.template @@ -4,14 +4,18 @@ # Project standard configurations !**/*.md -!.githooks +!.git-hooks +!.git-hooks/* !.github +!.github/* +!.github/**/* !.editorconfig !.gitignore !.nvmrc !.prettierignore !cdk-config.yml !eslint.config.mjs +!LICENSE !nx.json !package.json !prettier.config.mjs @@ -20,14 +24,12 @@ !vitest.global.setup.mjs !vitest.config.base.mjs -# IDE - VSCode -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json - # Package manager +!.yarn !.yarn/patches !.yarn/plugins +!.yarn/plugins/* +!.yarn/plugins/**/* !.yarn/releases !.yarn/sdks !.yarn/versions @@ -35,12 +37,26 @@ !yarn.lock # Application -!applications +!application +!application/* +!application/**/* +!collection +!collection/* +!collection/**/* !docs +!docs/* +!docs/**/* !libs +!libs/* +!libs/**/* !services +!services/* +!services/**/* # Test and bundle artifacts -# **/cdk.out -# **/dist -# **/coverage +**/cdk.out +**/dist +**/coverage + +# Environment files +*.env From d338634238f4739b914d309ea9ad3d66078efdcb Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Fri, 28 Nov 2025 16:16:52 +1100 Subject: [PATCH 06/24] MI-250: Few minor bug fixes for service generator --- packages/nx-cdk/src/generators/helpers/configs/packageJson.ts | 3 ++- .../src/generators/preset/files/eslint.config.mjs.template | 3 ++- .../nx-cdk/src/generators/service/files/package.json.template | 3 +-- packages/nx-cdk/src/generators/service/generator.ts | 3 ++- packages/nx-cdk/src/generators/service/schema.json | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 0b677a6..881854a 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -42,7 +42,8 @@ export const PACKAGE_JSON = { esbuild: '~0.25.8', // TODO Do we need this package now that we're using rsbuild instead 'esbuild-visualizer': '^0.7.0', eslint: '^9.32.0', - 'eslint-config-prettier': '10.1.8', + 'eslint-config-prettier': '^10.1.8', + 'eslint-plugin-import': '^2.32.0', 'fast-glob': '^3.3.3', jiti: '2.5.1', 'jsonc-eslint-parser': '^2.4.0', diff --git a/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template b/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template index 2e9270c..57b5c13 100644 --- a/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template +++ b/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template @@ -1,5 +1,6 @@ import { eslintConfigs } from '@aligent/ts-code-standards'; import nxEslintPlugin from '@nx/eslint-plugin'; +import eslintPluginImport from 'eslint-plugin-import'; import jsonParser from 'jsonc-eslint-parser'; const eslintBaseConfig = [ @@ -19,7 +20,7 @@ const eslintBaseConfig = [ }, { files: ['**/*.ts'], - plugins: { '@nx': nxEslintPlugin }, + plugins: { '@nx': nxEslintPlugin, import: eslintPluginImport }, rules: { '@nx/enforce-module-boundaries': [ 'error', diff --git a/packages/nx-cdk/src/generators/service/files/package.json.template b/packages/nx-cdk/src/generators/service/files/package.json.template index 1a1c5a2..27ce670 100644 --- a/packages/nx-cdk/src/generators/service/files/package.json.template +++ b/packages/nx-cdk/src/generators/service/files/package.json.template @@ -1,6 +1,5 @@ { - "name": "@services/<%= name %>", - "version": "0.0.1", + "name": "<%= name %>", "type": "module", "main": "./src/index.ts", "types": "./src/index.ts", diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index e161de1..bd8fbba 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -1,4 +1,5 @@ import { formatFiles, generateFiles, Tree, updateJson, writeJson } from '@nx/devkit'; +import { join } from 'path'; import { constructProjectTsConfigFiles } from '../helpers/utilities'; import { ServiceGeneratorSchema } from './schema'; @@ -61,7 +62,7 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche tree.write(`${SERVICES_FOLDER}/.gitkeep`, ''); } - generateFiles(tree, 'files', projectRoot, { ...options, template: '' }); + generateFiles(tree, join(__dirname, 'files'), projectRoot, { ...options, template: '' }); // Generate service's tsconfigs const { tsConfig, tsConfigLib, tsConfigSpec } = constructProjectTsConfigFiles('service'); diff --git a/packages/nx-cdk/src/generators/service/schema.json b/packages/nx-cdk/src/generators/service/schema.json index 82e164c..013051f 100644 --- a/packages/nx-cdk/src/generators/service/schema.json +++ b/packages/nx-cdk/src/generators/service/schema.json @@ -16,5 +16,5 @@ "patternErrorMessage": "Service name cannot contain '[Ss]tack' or '[Ss]ervice'" } }, - "required": ["brand", "name"] + "required": ["name"] } From 10419e2762bb33eea18d3af65105262ec83525cb Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Fri, 28 Nov 2025 19:59:13 +1100 Subject: [PATCH 07/24] MI-250: Few other minor bug fixes --- .../nx-cdk/src/generators/helpers/configs/packageJson.ts | 2 +- .../src/generators/preset/files/.prettierignore.template | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 881854a..760a523 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -56,7 +56,7 @@ export const PACKAGE_JSON = { vite: '7.1.6', vitest: '^3.2.4', }, - workspaces: ['libs/*', 'services/*', 'application/*'], + workspaces: ['application', 'libs/*', 'services/*'], packageManager: 'yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c', } as const; diff --git a/packages/nx-cdk/src/generators/preset/files/.prettierignore.template b/packages/nx-cdk/src/generators/preset/files/.prettierignore.template index 89abafc..4bf4836 100644 --- a/packages/nx-cdk/src/generators/preset/files/.prettierignore.template +++ b/packages/nx-cdk/src/generators/preset/files/.prettierignore.template @@ -4,8 +4,7 @@ **/dist **/coverage -# lock file is autogenerated -yarn.lock - -# Tools and misc +# Tools, misc and autogenerated files .nx +**/tsconfig.* +yarn.lock From 3e8ffec626e54b2158bda727df895c54993cbd0a Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Sat, 29 Nov 2025 09:21:03 +1100 Subject: [PATCH 08/24] MI-250: Service name improvements --- .../nx-cdk/src/generators/helpers/configs/nxJson.ts | 4 +--- .../src/generators/helpers/configs/packageJson.ts | 2 +- .../src/generators/service/files/src/index.ts.template | 9 +++++---- packages/nx-cdk/src/generators/service/generator.ts | 10 +++++++++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts index 0d24bdd..2030369 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts @@ -6,6 +6,7 @@ export const NX_JSON: NxJsonConfiguration & { $schema: string } = { plugins: [ { plugin: '@nx/eslint/plugin', options: {} }, { plugin: '@nx/vite/plugin', options: {} }, + { plugin: '@nx/js/typescript', options: { build: false } }, { plugin: '@nx/rsbuild', options: { @@ -20,9 +21,6 @@ export const NX_JSON: NxJsonConfiguration & { $schema: string } = { exclude: [], }, ], - generators: { - '@nx/js:library': { bundler: 'none', linter: 'eslint', unitTestRunner: 'vitest' }, - }, namedInputs: { default: ['{projectRoot}/**/*', 'sharedGlobals'], production: [ diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 760a523..47235e1 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -22,7 +22,7 @@ export const PACKAGE_JSON = { '@aligent/ts-code-standards': '^4.1.0', '@nx/eslint': '21.5.2', '@nx/eslint-plugin': '21.5.2', - // '@nx/js': '21.5.2', // TODO double check if it's actually needed + '@nx/js': '21.5.2', '@nx/rsbuild': '21.5.2', '@nx/vite': '21.5.2', '@rsbuild/core': '^1.5.6', diff --git a/packages/nx-cdk/src/generators/service/files/src/index.ts.template b/packages/nx-cdk/src/generators/service/files/src/index.ts.template index 5a642d7..7af779d 100644 --- a/packages/nx-cdk/src/generators/service/files/src/index.ts.template +++ b/packages/nx-cdk/src/generators/service/files/src/index.ts.template @@ -3,9 +3,10 @@ import { Code } from 'aws-cdk-lib/aws-lambda'; import { Construct } from 'constructs'; import path from 'node:path'; -const SERVICE_NAME = '<%= name %>' as const; +export const SERVICE_NAME = '<%= name %>' as const; +type ServiceName = typeof SERVICE_NAME | (string & {}); -export interface <%= name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('') %>StackProps extends StackProps { +export interface <%= stackName %>Props extends StackProps { description: string; } @@ -16,8 +17,8 @@ export interface <%= name.split('-').map(part => part.charAt(0).toUpperCase() + * * Use 'resolve' helpers below when referencing lambda handlers, step function files etc. */ -export class <%= name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('') %>Stack extends Stack { - constructor(scope: Construct, id: typeof SERVICE_NAME | (string & {}), props?: <%= name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('') %>StackProps) { +export class <%= stackName %> extends Stack { + constructor(scope: Construct, id: ServiceName, props?: <%= stackName %>Props) { super(scope, id, props); const STAGE = Stage.of(this)?.stageName; diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index bd8fbba..1a05775 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -57,12 +57,20 @@ function addTsConfigReference(tree: Tree, referencePath: string) { export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSchema) { const projectRoot = `${SERVICES_FOLDER}/${options.name}`; + const stackName = `${options.name + .split('-') + .map(part => part.charAt(0).toUpperCase() + part.slice(1)) + .join('')}Stack`; if (!tree.exists(SERVICES_FOLDER)) { tree.write(`${SERVICES_FOLDER}/.gitkeep`, ''); } - generateFiles(tree, join(__dirname, 'files'), projectRoot, { ...options, template: '' }); + generateFiles(tree, join(__dirname, 'files'), projectRoot, { + ...options, + stackName, + template: '', + }); // Generate service's tsconfigs const { tsConfig, tsConfigLib, tsConfigSpec } = constructProjectTsConfigFiles('service'); From ce2d170beafdab6709170f6ecf2c9fe4ee727105 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Sat, 29 Nov 2025 09:44:51 +1100 Subject: [PATCH 09/24] MI-250: Fixed hard-coded stack name --- .../service/files/src/index.ts.template | 15 ++++++++++----- .../nx-cdk/src/generators/service/generator.ts | 8 +++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/nx-cdk/src/generators/service/files/src/index.ts.template b/packages/nx-cdk/src/generators/service/files/src/index.ts.template index 7af779d..9257516 100644 --- a/packages/nx-cdk/src/generators/service/files/src/index.ts.template +++ b/packages/nx-cdk/src/generators/service/files/src/index.ts.template @@ -3,10 +3,15 @@ import { Code } from 'aws-cdk-lib/aws-lambda'; import { Construct } from 'constructs'; import path from 'node:path'; -export const SERVICE_NAME = '<%= name %>' as const; -type ServiceName = typeof SERVICE_NAME | (string & {}); +/** +* @important +* Due to the immutable nature of CloudFormation, +* CDK will generate new CloudFormation template and deploy if you change stack name +*/ +export const <%= stack %>Name = '<%= name %>' as const; +type ServiceName = typeof <%= stack %>Name | (string & {}); -export interface <%= stackName %>Props extends StackProps { +export interface <%= stack %>StackProps extends StackProps { description: string; } @@ -17,8 +22,8 @@ export interface <%= stackName %>Props extends StackProps { * * Use 'resolve' helpers below when referencing lambda handlers, step function files etc. */ -export class <%= stackName %> extends Stack { - constructor(scope: Construct, id: ServiceName, props?: <%= stackName %>Props) { +export class <%= stack %>Stack extends Stack { + constructor(scope: Construct, id: ServiceName, props?: <%= stack %>StackProps) { super(scope, id, props); const STAGE = Stage.of(this)?.stageName; diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index 1a05775..f2d0aa8 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -57,10 +57,10 @@ function addTsConfigReference(tree: Tree, referencePath: string) { export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSchema) { const projectRoot = `${SERVICES_FOLDER}/${options.name}`; - const stackName = `${options.name + const stack = `${options.name .split('-') .map(part => part.charAt(0).toUpperCase() + part.slice(1)) - .join('')}Stack`; + .join('')}`; if (!tree.exists(SERVICES_FOLDER)) { tree.write(`${SERVICES_FOLDER}/.gitkeep`, ''); @@ -68,7 +68,7 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche generateFiles(tree, join(__dirname, 'files'), projectRoot, { ...options, - stackName, + stack, template: '', }); @@ -85,6 +85,8 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche // FIXME Double check if this is needed or not // registerWithTypecheckPlugin(tree, `${projectRoot}/*`); + // TODO ts-morph for stack initiation within application/lib/service-stacks.ts + await formatFiles(tree); } From d4b490ee8ce78e44e80315b04cc9ba4f22695495 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Sat, 29 Nov 2025 09:49:51 +1100 Subject: [PATCH 10/24] MI-250: Simplify stack name type --- .../nx-cdk/src/generators/service/files/src/index.ts.template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nx-cdk/src/generators/service/files/src/index.ts.template b/packages/nx-cdk/src/generators/service/files/src/index.ts.template index 9257516..0c51a25 100644 --- a/packages/nx-cdk/src/generators/service/files/src/index.ts.template +++ b/packages/nx-cdk/src/generators/service/files/src/index.ts.template @@ -9,7 +9,7 @@ import path from 'node:path'; * CDK will generate new CloudFormation template and deploy if you change stack name */ export const <%= stack %>Name = '<%= name %>' as const; -type ServiceName = typeof <%= stack %>Name | (string & {}); +type Name = typeof <%= stack %>Name | (string & {}); export interface <%= stack %>StackProps extends StackProps { description: string; @@ -23,7 +23,7 @@ export interface <%= stack %>StackProps extends StackProps { * Use 'resolve' helpers below when referencing lambda handlers, step function files etc. */ export class <%= stack %>Stack extends Stack { - constructor(scope: Construct, id: ServiceName, props?: <%= stack %>StackProps) { + constructor(scope: Construct, id: Name, props?: <%= stack %>StackProps) { super(scope, id, props); const STAGE = Stage.of(this)?.stageName; From a007e57e88281eb6554bb9f8fc46e1bc7d759709 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Sun, 30 Nov 2025 16:29:16 +1100 Subject: [PATCH 11/24] MI-250: Auto stack registration to main application --- package-lock.json | 76 ++++++++++++++++++- package.json | 3 +- packages/nx-cdk/package.json | 3 +- .../src/generators/helpers/utilities.ts | 39 +++++++++- .../lib/service-stacks.ts.template | 8 +- .../service/files/src/index.ts.template | 13 ++-- .../src/generators/service/generator.ts | 59 ++++---------- 7 files changed, 144 insertions(+), 57 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9f2733b..4aab0ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,8 @@ "@aws-sdk/client-ssm": "^3.922.0", "@redocly/openapi-core": "^1.34.2", "object-hash": "^3.0.0", - "openapi-typescript": "7.7.3" + "openapi-typescript": "7.7.3", + "ts-morph": "^27.0.2" }, "devDependencies": { "@aligent/ts-code-standards": "^3.0.0", @@ -3643,6 +3644,27 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -6532,6 +6554,32 @@ "@swc/counter": "^0.1.3" } }, + "node_modules/@ts-morph/common": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.28.1.tgz", + "integrity": "sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==", + "license": "MIT", + "dependencies": { + "minimatch": "^10.0.1", + "path-browserify": "^1.0.1", + "tinyglobby": "^0.2.14" + } + }, + "node_modules/@ts-morph/common/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", @@ -8296,6 +8344,12 @@ "node": ">= 0.12.0" } }, + "node_modules/code-block-writer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", + "license": "MIT" + }, "node_modules/collect-v8-coverage": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", @@ -12982,6 +13036,12 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -14597,6 +14657,16 @@ "typescript": ">=4.8.4" } }, + "node_modules/ts-morph": { + "version": "27.0.2", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-27.0.2.tgz", + "integrity": "sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==", + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.28.1", + "code-block-writer": "^13.0.3" + } + }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -15469,8 +15539,10 @@ "packages/nx-cdk": { "name": "@aligent/nx-cdk", "version": "0.0.1", + "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@nx/devkit": "20.8.1", + "ts-morph": "^27.0.2" } }, "packages/nx-openapi": { diff --git a/package.json b/package.json index 743c123..4bf2181 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "@aws-sdk/client-ssm": "^3.922.0", "@redocly/openapi-core": "^1.34.2", "object-hash": "^3.0.0", - "openapi-typescript": "7.7.3" + "openapi-typescript": "7.7.3", + "ts-morph": "^27.0.2" }, "devDependencies": { "@aligent/ts-code-standards": "^3.0.0", diff --git a/packages/nx-cdk/package.json b/packages/nx-cdk/package.json index e5a5a00..66182a6 100644 --- a/packages/nx-cdk/package.json +++ b/packages/nx-cdk/package.json @@ -10,7 +10,8 @@ "directory": "packages/nx-cdk" }, "dependencies": { - "@nx/devkit": "20.8.1" + "@nx/devkit": "20.8.1", + "ts-morph": "^27.0.2" }, "generators": "./generators.json", "author": "Aligent", diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts index 287f222..c31f2ef 100644 --- a/packages/nx-cdk/src/generators/helpers/utilities.ts +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -1,8 +1,15 @@ -import { readJsonFile } from '@nx/devkit'; +import { readJsonFile, readProjectConfiguration, Tree, workspaceRoot } from '@nx/devkit'; import { join } from 'path'; +import { Project } from 'ts-morph'; import { PACKAGE_JSON } from './configs/packageJson'; import { TS_CONFIG_JSON, TS_CONFIG_LIB_JSON, TS_CONFIG_SPEC_JSON } from './configs/tsConfigs'; +interface Service { + name: string; + constant: string; + stack: string; +} + export function constructPackageJsonFile(name: string, version: string, nodeVersion: string) { const [nodeVersionMajor, nodeVersionMinor] = nodeVersion.split('.'); @@ -59,3 +66,33 @@ export function getGeneratorVersion() { throw new Error(`Unable to get generator version from ${packagePath}`); } + +export async function addServiceStackToMainApplication( + tree: Tree, + service: Service, + projectName: string +) { + const application = readProjectConfiguration(tree, projectName); + const stacksPath = join(workspaceRoot, application.root, 'lib/service-stacks.ts'); + + const project = new Project(); + const stackSource = project.addSourceFileAtPath(stacksPath); + + const applicationStage = stackSource.getClassOrThrow('ApplicationStage'); + const stageConstructors = applicationStage?.getConstructors(); + + if (!stageConstructors?.length) { + throw new Error('Unable to find main application stage constructor'); + } + + stackSource.addImportDeclaration({ + moduleSpecifier: `@services/${service.name}`, + namedImports: [service.constant, service.stack], + }); + + stageConstructors[0]?.addStatements( + `new ${service.stack}(this, ${service.constant}.NAME, { ...props, description: ${service.constant}.DESCRIPTION });` + ); + + await stackSource?.save(); +} diff --git a/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template b/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template index f96a879..83bee9d 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template @@ -12,6 +12,12 @@ export class ApplicationStage extends Stage { super(scope, id, props); Tags.of(this).add('STAGE', id); - // Instantiate service stacks here as required + /** + * Service stack initialization + * + * Service stacks are automatically instantiated here when generated using the service generator. + * Each service stack will be initialized with this stage as the parent scope, ensuring proper + * stack composition and resource organization within the CDK application. + */ } } diff --git a/packages/nx-cdk/src/generators/service/files/src/index.ts.template b/packages/nx-cdk/src/generators/service/files/src/index.ts.template index 0c51a25..7cdf080 100644 --- a/packages/nx-cdk/src/generators/service/files/src/index.ts.template +++ b/packages/nx-cdk/src/generators/service/files/src/index.ts.template @@ -8,10 +8,13 @@ import path from 'node:path'; * Due to the immutable nature of CloudFormation, * CDK will generate new CloudFormation template and deploy if you change stack name */ -export const <%= stack %>Name = '<%= name %>' as const; -type Name = typeof <%= stack %>Name | (string & {}); +export const <%= constant %> = { + NAME: '<%= name %>', + DESCRIPTION: '<%= name %> service description' +} as const; -export interface <%= stack %>StackProps extends StackProps { +type Id = typeof <%= constant %>.NAME | (string & {}); +interface Props extends StackProps { description: string; } @@ -22,8 +25,8 @@ export interface <%= stack %>StackProps extends StackProps { * * Use 'resolve' helpers below when referencing lambda handlers, step function files etc. */ -export class <%= stack %>Stack extends Stack { - constructor(scope: Construct, id: Name, props?: <%= stack %>StackProps) { +export class <%= stack %> extends Stack { + constructor(scope: Construct, id: Id, props?: Props) { super(scope, id, props); const STAGE = Stage.of(this)?.stageName; diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index f2d0aa8..eced4d2 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -1,6 +1,9 @@ import { formatFiles, generateFiles, Tree, updateJson, writeJson } from '@nx/devkit'; import { join } from 'path'; -import { constructProjectTsConfigFiles } from '../helpers/utilities'; +import { + addServiceStackToMainApplication, + constructProjectTsConfigFiles, +} from '../helpers/utilities'; import { ServiceGeneratorSchema } from './schema'; const SERVICES_FOLDER = 'services'; @@ -15,52 +18,20 @@ function addTsConfigReference(tree: Tree, referencePath: string) { ); } - json.references.push({ - path: referencePath, - }); + json.references.push({ path: referencePath }); return json; }); } -// function registerWithTypecheckPlugin(tree: Tree, referencePath: string) { -// updateJson(tree, 'nx.json', json => { -// json.plugins ??= []; - -// // Services should be non-buildable, so we need to register them with the typescript plugin configuration -// // that adds typechecking but not a build argument -// const plugin = json.plugins.find( -// (p: { -// plugin: string; -// include: string[]; -// options?: { typecheck?: unknown; build?: unknown }; -// }) => p.plugin === '@nx/js/typescript' && p.options?.typecheck && !p.options?.build -// ); - -// if (!plugin) { -// json.plugins.push({ -// plugin: '@nx/js/typescript', -// options: { -// typecheck: { -// targetName: 'typecheck', -// }, -// }, -// include: [referencePath], -// }); -// } else { -// plugin.include.push(referencePath); -// } - -// return json; -// }); -// } - export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSchema) { const projectRoot = `${SERVICES_FOLDER}/${options.name}`; - const stack = `${options.name + const nameParts = options.name .split('-') - .map(part => part.charAt(0).toUpperCase() + part.slice(1)) - .join('')}`; + .map(part => part.charAt(0).toUpperCase() + part.slice(1)); + + const constant = nameParts.map(name => name.toUpperCase()).join('_'); + const stack = `${nameParts.join('')}Stack`; if (!tree.exists(SERVICES_FOLDER)) { tree.write(`${SERVICES_FOLDER}/.gitkeep`, ''); @@ -68,6 +39,7 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche generateFiles(tree, join(__dirname, 'files'), projectRoot, { ...options, + constant, stack, template: '', }); @@ -78,14 +50,9 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche writeJson(tree, `${projectRoot}/tsconfig.lib.json`, tsConfigLib); writeJson(tree, `${projectRoot}/tsconfig.spec.json`, tsConfigSpec); - // Add the service to tsconfig.json references - // The root application needs to import stacks from the service + // Integrate the new service with the root application addTsConfigReference(tree, `./${projectRoot}`); - - // FIXME Double check if this is needed or not - // registerWithTypecheckPlugin(tree, `${projectRoot}/*`); - - // TODO ts-morph for stack initiation within application/lib/service-stacks.ts + addServiceStackToMainApplication(tree, { name: options.name, constant, stack }, 'application'); await formatFiles(tree); } From ea62e2230a490422e00e58ba7adfa231dda9de6c Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Mon, 1 Dec 2025 11:44:18 +1100 Subject: [PATCH 12/24] MI-250: Allow default injector to accept node version --- packages/nx-cdk/src/generators/helpers/utilities.ts | 4 +--- .../nodejs-function-defaults-injector.ts.template | 11 ++++++----- .../preset/files/application/bin/main.ts.template | 5 ++++- packages/nx-cdk/src/generators/preset/preset.ts | 5 +++-- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts index c31f2ef..b78b8f5 100644 --- a/packages/nx-cdk/src/generators/helpers/utilities.ts +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -11,8 +11,6 @@ interface Service { } export function constructPackageJsonFile(name: string, version: string, nodeVersion: string) { - const [nodeVersionMajor, nodeVersionMinor] = nodeVersion.split('.'); - const devDependencies = Object.fromEntries( Object.entries({ '@aligent/nx-cdk': version, @@ -27,7 +25,7 @@ export function constructPackageJsonFile(name: string, version: string, nodeVers version, ...PACKAGE_JSON, devDependencies, - engines: { node: `^${nodeVersionMajor}.${nodeVersionMinor}.0` }, + engines: { node: `^${nodeVersion}` }, }) ); diff --git a/packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template b/packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template index 5e3c3e6..da6391c 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template @@ -3,7 +3,8 @@ import { Runtime, Tracing } from 'aws-cdk-lib/aws-lambda'; import { NodejsFunction, type NodejsFunctionProps } from 'aws-cdk-lib/aws-lambda-nodejs'; interface Config { - sourceMap: boolean; + runtime: Runtime; + sourceMap?: boolean; } /** @@ -39,7 +40,7 @@ interface Config { */ export class NodeJsFunctionDefaultsInjector implements IPropertyInjector { public readonly constructUniqueId = NodejsFunction.PROPERTY_INJECTION_ID; - private readonly config: Config; + private readonly config: Required; private defaultProps: NodejsFunctionProps; /** @@ -47,9 +48,9 @@ export class NodeJsFunctionDefaultsInjector implements IPropertyInjector { * * @param config - Configuration identifier used to select appropriate defaults. Uses production defaults if not specified. */ - constructor(config: Config = { sourceMap: true }) { - this.config = { ...config }; - this.defaultProps = { runtime: Runtime.NODEJS_22_X, tracing: Tracing.ACTIVE }; + constructor(config: Config) { + this.config = { ...config, sourceMap: config.sourceMap || true }; + this.defaultProps = { runtime: config.runtime, tracing: Tracing.ACTIVE }; } /** diff --git a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template index e9145d8..efe502c 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template @@ -13,7 +13,10 @@ const APPLICATION_CONTEXT = { APPLICATION_OWNER: 'aligent' } as const; const app = new App({ context: APPLICATION_CONTEXT, - propertyInjectors: [new NodeJsFunctionDefaultsInjector(), new StepFunctionDefaultsInjector()], + propertyInjectors: [ + new NodeJsFunctionDefaultsInjector({ runtime: <%= nodeRuntime %> }), + new StepFunctionDefaultsInjector(), + ], }); Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER); diff --git a/packages/nx-cdk/src/generators/preset/preset.ts b/packages/nx-cdk/src/generators/preset/preset.ts index 28627d6..4a68548 100644 --- a/packages/nx-cdk/src/generators/preset/preset.ts +++ b/packages/nx-cdk/src/generators/preset/preset.ts @@ -9,17 +9,18 @@ import { import { PresetGeneratorSchema } from './schema'; export async function presetGenerator(tree: Tree, options: PresetGeneratorSchema) { - const { name, nodeVersion } = options; + const [nodeVersionMajor] = options.nodeVersion.split('.'); const version = getGeneratorVersion(); generateFiles(tree, join(__dirname, 'files'), '.', { ...options, + nodeRuntime: `Runtime.NODEJS_${nodeVersionMajor}_X`, template: '', }); updateNxJson(tree, { ...NX_JSON }); - const packageJson = constructPackageJsonFile(name, version, nodeVersion); + const packageJson = constructPackageJsonFile(options.name, version, options.nodeVersion); writeJson(tree, 'package.json', packageJson); // Generate application's tsconfigs From 753637cde6d392d0574af90a54c9a5fc71153688 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Wed, 3 Dec 2025 17:30:04 +1100 Subject: [PATCH 13/24] MI-250: A bunch of bug fixes and improvement --- .../generators/helpers/configs/packageJson.ts | 6 +- .../generators/helpers/configs/tsConfigs.ts | 10 ++- .../src/generators/helpers/utilities.ts | 42 +++++++++-- .../preset/files/README.md.template | 74 +++++++++++++++++++ .../files/application/README.md.template | 15 +--- .../files/application/bin/main.ts.template | 13 ++-- .../application/eslint.config.mjs.template | 3 + .../lib/service-stacks.ts.template | 14 ++-- .../preset/files/eslint.config.mjs.template | 14 +--- .../files/rsbuild.config.base.mjs.template | 33 ++++----- .../nx-cdk/src/generators/preset/preset.ts | 16 +++- .../nx-cdk/src/generators/preset/schema.d.ts | 1 + .../nx-cdk/src/generators/preset/schema.json | 15 +++- .../service/files/eslint.config.mjs.template | 20 ++++- .../service/files/package.json.template | 9 +-- .../src/generators/service/generator.ts | 5 +- 16 files changed, 205 insertions(+), 85 deletions(-) create mode 100644 packages/nx-cdk/src/generators/preset/files/README.md.template create mode 100644 packages/nx-cdk/src/generators/preset/files/application/eslint.config.mjs.template diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 47235e1..2cefaa0 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -39,8 +39,6 @@ export const PACKAGE_JSON = { 'aws-cdk-lib': '^2.230.0', 'cdk-nag': '^2.37.55', constructs: '^10.4.3', - esbuild: '~0.25.8', // TODO Do we need this package now that we're using rsbuild instead - 'esbuild-visualizer': '^0.7.0', eslint: '^9.32.0', 'eslint-config-prettier': '^10.1.8', 'eslint-plugin-import': '^2.32.0', @@ -48,15 +46,15 @@ export const PACKAGE_JSON = { jiti: '2.5.1', 'jsonc-eslint-parser': '^2.4.0', nx: '21.5.2', - // open: '^10.2.0', // TODO Double check what is this and why it's here? prettier: '^3.6.2', 'store-parameters': '^1.0.6', tslib: '^2.8.1', + tsx: '^4.21.0', typescript: '~5.9.2', vite: '7.1.6', vitest: '^3.2.4', }, workspaces: ['application', 'libs/*', 'services/*'], packageManager: - 'yarn@4.9.2+sha512.1fc009bc09d13cfd0e19efa44cbfc2b9cf6ca61482725eb35bbc5e257e093ebf4130db6dfe15d604ff4b79efd8e1e8e99b25fa7d0a6197c9f9826358d4d65c3c', + 'yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8', } as const; diff --git a/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts b/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts index 5ad5ed5..a8bfa0f 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts @@ -36,6 +36,14 @@ export const TS_CONFIG_SPEC_JSON: TsConfig = { outDir: './out-tsc/vitest', types: ['vitest/globals', 'vitest/importMeta', 'vite/client', 'node', 'vitest'], }, - include: ['vite.config.mjs', 'src/**/*.test.ts', 'src/**/*.spec.ts', 'src/**/*.d.ts'], + include: [ + 'vite.config.mjs', + 'src/**/*.test.ts', + 'src/**/*.spec.ts', + 'src/**/*.d.ts', + 'tests/**/*.test.ts', + 'tests/**/*.spec.ts', + 'tests/**/*.d.ts', + ], references: [{ path: './tsconfig.lib.json' }], }; diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts index b78b8f5..fbe86b9 100644 --- a/packages/nx-cdk/src/generators/helpers/utilities.ts +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -4,28 +4,35 @@ import { Project } from 'ts-morph'; import { PACKAGE_JSON } from './configs/packageJson'; import { TS_CONFIG_JSON, TS_CONFIG_LIB_JSON, TS_CONFIG_SPEC_JSON } from './configs/tsConfigs'; +interface PackageJsonInput { + name: string; + projectName: string; + version: string; + nodeVersion: string; +} + interface Service { name: string; constant: string; stack: string; } -export function constructPackageJsonFile(name: string, version: string, nodeVersion: string) { +export function constructPackageJsonFile(input: PackageJsonInput) { const devDependencies = Object.fromEntries( Object.entries({ - '@aligent/nx-cdk': version, + '@aligent/nx-cdk': input.version, ...PACKAGE_JSON.devDependencies, }).sort() ); const packageJson = Object.fromEntries( Object.entries({ - name: `@${name}/integrations`, - description: `${name} integrations mono-repository`, - version, + name: `@${input.name}/integrations`, + description: `${input.projectName} integrations mono-repository`, + version: input.version, ...PACKAGE_JSON, devDependencies, - engines: { node: `^${nodeVersion}` }, + engines: { node: `^${input.nodeVersion}` }, }) ); @@ -65,6 +72,19 @@ export function getGeneratorVersion() { throw new Error(`Unable to get generator version from ${packagePath}`); } +/** + * Automatically registers a service stack to the main CDK application's ApplicationStage. + * + * This function modifies the service-stacks.ts file by: + * 1. Adding import statements for the service's stack class and constants + * 2. Instantiating the stack within the ApplicationStage constructor + * + * @param tree - The Nx virtual file system tree + * @param service - Service information containing name, constant, and stack class names + * @param projectName - The name of the main application project to register the service to + * + * @throws {Error} If the ApplicationStage constructor cannot be found in service-stacks.ts + */ export async function addServiceStackToMainApplication( tree: Tree, service: Service, @@ -94,3 +114,13 @@ export async function addServiceStackToMainApplication( await stackSource?.save(); } + +/** + * Splits a kebab-case name into an array of capitalized parts. + * + * @param name - The kebab-case string to split (e.g., "my-service-name") + * @returns An array of strings with each part capitalized (e.g., ["My", "Service", "Name"]) + */ +export function splitInputName(name: string) { + return name.split('-').map(part => part.charAt(0).toUpperCase() + part.slice(1)); +} diff --git a/packages/nx-cdk/src/generators/preset/files/README.md.template b/packages/nx-cdk/src/generators/preset/files/README.md.template new file mode 100644 index 0000000..adebb7b --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/README.md.template @@ -0,0 +1,74 @@ +# <%= projectName %> Integrations + +A monorepo containing integration services that support the <%= projectName %> project. This repository manages the deployment of microservices and their shared infrastructure using AWS CDK. + +## Overview + + + +## Services + +Services deployment are managed by the main [CDK Application](./application/README.md) + + + + +## Project Structure + +``` +<%= folderName %>/ +ā”œā”€ā”€ application/ # CDK Application & orchestration +│ ā”œā”€ā”€ bin/main.ts # CDK App entry point (dev/stg/prd stages) +│ ā”œā”€ā”€ lib/ # Service stack composition +│ └── cdk.json # CDK configuration +│ +ā”œā”€ā”€ services/ # Microservices workspace +│ +ā”œā”€ā”€ nx.json # Nx monorepo configuration +ā”œā”€ā”€ rsbuild.config.base.mjs # Base Lambda bundling config +ā”œā”€ā”€ vitest.config.base.mjs # Base test configuration +└── eslint.config.mjs # ESLint configuration +``` + +## Getting Started + +### Prerequisites + +- Node.js <%= nodeVersion %> (see [.nvmrc](.nvmrc)) +- Yarn 4.12.0+ +- AWS CLI configured with appropriate credentials + +### Installation + +```bash +# Use correct Node version +nvm use + +# Install dependencies +yarn install +``` + +## Contributing + +1. Create new branch from `production` +2. Make your changes following code standards +3. Ensure your changes pass linting, type checks and testes +4. Submit a pull request to `staging` + +## Adding New Services + +To add a new service to the monorepo: + +1. Use the Aligent CDK generator `@aligent/nx-cdk` +2. Add service infrastructure in + - `services/{service-name}/src/index.ts` + - `services/{service-name}/src/infra/` +3. Add Lambda handlers in `services/{service-name}/src/runtime/handlers/` + +## License + +MIT + +## Support + +For questions or issues, please contact the Aligent Microservices guild. diff --git a/packages/nx-cdk/src/generators/preset/files/application/README.md.template b/packages/nx-cdk/src/generators/preset/files/application/README.md.template index b34e3c5..dd1eadb 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/README.md.template +++ b/packages/nx-cdk/src/generators/preset/files/application/README.md.template @@ -1,16 +1,7 @@ -# <%= name %> Application +# Application This application manages the deployment of microservices and their shared infrastructure. -## Architecture - - - -## Services - - - - ## Configuration ### Environment Parameters @@ -50,9 +41,9 @@ yarn nx run application:cdk ### Mock Services -The application includes mock services for testing integrations without external dependencies. +The application may include mock services for testing integrations without external dependencies. -- _list mock services here_ + Change the value of the `/application/dev/url` SSM Parameter to switch between real and mock endpoints diff --git a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template index efe502c..ecbaa2a 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template @@ -1,13 +1,14 @@ #!/usr/bin/env node import { App, Aspects, Tags } from 'aws-cdk-lib'; -import { ApplicationStage } from './lib/service-stacks.js'; +import { Runtime } from 'aws-cdk-lib/aws-lambda'; +import { ApplicationStage } from '../lib/service-stacks.js'; // TODO Pull this out to constructs repo so we can import and use later -import { LogGroupDefaultsInjector } from './_internal/log-group-defaults-injector.js'; -import { MicroserviceChecks } from './_internal/microservice-checks.js'; -import { NodeJsFunctionDefaultsInjector } from './_internal/nodejs-function-defaults-injector.js'; -import { StepFunctionDefaultsInjector } from './_internal/step-function-defaults-injector.ts'; -import { VersionFunctionsAspect } from './_internal/version-functions-aspect.js'; +import { LogGroupDefaultsInjector } from '../_internal/log-group-defaults-injector.js'; +import { MicroserviceChecks } from '../_internal/microservice-checks.js'; +import { NodeJsFunctionDefaultsInjector } from '../_internal/nodejs-function-defaults-injector.js'; +import { StepFunctionDefaultsInjector } from '../_internal/step-function-defaults-injector.ts'; +import { VersionFunctionsAspect } from '../_internal/version-functions-aspect.js'; const APPLICATION_CONTEXT = { APPLICATION_OWNER: 'aligent' } as const; diff --git a/packages/nx-cdk/src/generators/preset/files/application/eslint.config.mjs.template b/packages/nx-cdk/src/generators/preset/files/application/eslint.config.mjs.template new file mode 100644 index 0000000..fef103b --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/application/eslint.config.mjs.template @@ -0,0 +1,3 @@ +import baseConfig from '../eslint.config.mjs'; + +export default [...baseConfig]; diff --git a/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template b/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template index 83bee9d..f3a481d 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/lib/service-stacks.ts.template @@ -2,22 +2,20 @@ import { Stage, Tags, type StageProps } from 'aws-cdk-lib'; import type { Construct } from 'constructs'; /** - * Application stage + * Application Stage * * This is the main entry point for the application. * It is used to define context and compose service stacks. + * + * Service stacks are automatically instantiated here when generated using the service generator. + * Each service stack will be initialized with this stage as the parent scope, ensuring proper + * stack composition and resource organization within the CDK application. */ export class ApplicationStage extends Stage { constructor(scope: Construct, id: string, props?: StageProps) { super(scope, id, props); Tags.of(this).add('STAGE', id); - /** - * Service stack initialization - * - * Service stacks are automatically instantiated here when generated using the service generator. - * Each service stack will be initialized with this stage as the parent scope, ensuring proper - * stack composition and resource organization within the CDK application. - */ + // Service stacks initialization } } diff --git a/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template b/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template index 57b5c13..9e0486e 100644 --- a/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template +++ b/packages/nx-cdk/src/generators/preset/files/eslint.config.mjs.template @@ -1,6 +1,5 @@ import { eslintConfigs } from '@aligent/ts-code-standards'; import nxEslintPlugin from '@nx/eslint-plugin'; -import eslintPluginImport from 'eslint-plugin-import'; import jsonParser from 'jsonc-eslint-parser'; const eslintBaseConfig = [ @@ -20,7 +19,7 @@ const eslintBaseConfig = [ }, { files: ['**/*.ts'], - plugins: { '@nx': nxEslintPlugin, import: eslintPluginImport }, + plugins: { '@nx': nxEslintPlugin }, rules: { '@nx/enforce-module-boundaries': [ 'error', @@ -29,7 +28,7 @@ const eslintBaseConfig = [ enforceBuildableLibDependency: true, depConstraints: [ { - sourceTag: 'scope:applications', + sourceTag: 'scope:application', onlyDependOnLibsWithTags: ['scope:libs', 'scope:services'], }, { @@ -43,15 +42,6 @@ const eslintBaseConfig = [ ], }, ], - 'import/no-extraneous-dependencies': [ - 'warn', - { - optionalDependencies: false, - peerDependencies: false, - bundledDependencies: false, - packageDir: ['.', '..', '../..'], - }, - ], 'no-console': 'warn', }, }, diff --git a/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template b/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template index c15f48b..49af6d9 100644 --- a/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template +++ b/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template @@ -14,12 +14,17 @@ const HANDLERS_PATH = 'src/runtime/handlers'; */ export function defineLambdaConfig(configPath, subPath = HANDLERS_PATH) { if (subPath.includes('..')) throw new Error('Invalid path provided'); + const basePath = resolve(configPath, subPath); const handlers = fg.sync(`${basePath}/**/*.ts`); + // FIXME: We need a way to skip bundling instead of throwing error here + if (!handlers.length) { + throw new Error('Unable to find any handler'); + } + // Format an entry object containing each file found in the folder - // Maintains subfolder structure - // e.g. { 'test/log-object': 'test/log-object' } + // Maintains subfolder structure. E.g. { 'test/log-object': 'test/log-object' } const entry = Object.fromEntries( handlers.map(handler => { const bundledPath = handler.replace(`${basePath}/`, ''); @@ -29,10 +34,7 @@ export function defineLambdaConfig(configPath, subPath = HANDLERS_PATH) { ); return defineConfig({ - source: { - entry, - tsconfigPath: './tsconfig.lib.json', - }, + source: { entry, disableDefaultEntry: true, tsconfigPath: './tsconfig.lib.json' }, performance: { chunkSplit: { // Not sure this is necessary for single-file-bundling but seems safer to set it @@ -40,27 +42,20 @@ export function defineLambdaConfig(configPath, subPath = HANDLERS_PATH) { }, }, output: { - // Only bundle javascript/typescript code target: 'node', - // Output ESM modules - module: true, + module: true, // Output ESM modules filename: { js: '[name]/index.mjs' }, - // Don't output license comments in bundled code - legalComments: 'none', + legalComments: 'none', // Don't output license comments in bundled code // FIXME: handle the following things by stag/environment // sourceMap: true, // minify: true, }, tools: { rspack: { - output: { - // Forces bundler to include all dependencies in one file - asyncChunks: false, - }, - optimization: { - // Prevent bundler from wrapping handlers in an IIFE - avoidEntryIife: true, - }, + // Forces bundler to include all dependencies in one file + output: { asyncChunks: false }, + // Prevent bundler from wrapping handlers in an IIFE + optimization: { avoidEntryIife: true }, }, }, }); diff --git a/packages/nx-cdk/src/generators/preset/preset.ts b/packages/nx-cdk/src/generators/preset/preset.ts index 4a68548..4c8f27b 100644 --- a/packages/nx-cdk/src/generators/preset/preset.ts +++ b/packages/nx-cdk/src/generators/preset/preset.ts @@ -5,22 +5,32 @@ import { constructPackageJsonFile, constructProjectTsConfigFiles, getGeneratorVersion, + splitInputName, } from '../helpers/utilities'; import { PresetGeneratorSchema } from './schema'; export async function presetGenerator(tree: Tree, options: PresetGeneratorSchema) { - const [nodeVersionMajor] = options.nodeVersion.split('.'); - const version = getGeneratorVersion(); + const { name, destination, nodeVersion } = options; + const [nodeVersionMajor] = nodeVersion.split('.'); + const nameParts = splitInputName(name); + const projectName = nameParts.join(' '); generateFiles(tree, join(__dirname, 'files'), '.', { ...options, + projectName, + folderName: destination || name, nodeRuntime: `Runtime.NODEJS_${nodeVersionMajor}_X`, template: '', }); updateNxJson(tree, { ...NX_JSON }); - const packageJson = constructPackageJsonFile(options.name, version, options.nodeVersion); + const packageJson = constructPackageJsonFile({ + name: options.name, + projectName, + version: getGeneratorVersion(), + nodeVersion, + }); writeJson(tree, 'package.json', packageJson); // Generate application's tsconfigs diff --git a/packages/nx-cdk/src/generators/preset/schema.d.ts b/packages/nx-cdk/src/generators/preset/schema.d.ts index 39eb3a4..e1d0203 100644 --- a/packages/nx-cdk/src/generators/preset/schema.d.ts +++ b/packages/nx-cdk/src/generators/preset/schema.d.ts @@ -1,4 +1,5 @@ export interface PresetGeneratorSchema { name: string; nodeVersion: string; + destination?: string; } diff --git a/packages/nx-cdk/src/generators/preset/schema.json b/packages/nx-cdk/src/generators/preset/schema.json index ef8cc5d..36ddf28 100644 --- a/packages/nx-cdk/src/generators/preset/schema.json +++ b/packages/nx-cdk/src/generators/preset/schema.json @@ -12,8 +12,8 @@ "index": 0 }, "x-prompt": "What is the name of the project?", - "pattern": "^[A-Za-z0-9-]+$", - "patternErrorMessage": "Project name must contain only alphanumeric characters and dashes" + "pattern": "^[a-z0-9-]+$", + "patternErrorMessage": "Project name must contain only lowercase alphanumeric characters and dashes" }, "nodeVersion": { "type": "string", @@ -26,6 +26,17 @@ "x-prompt": "What is the target Node.js version the project?", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$", "patternErrorMessage": "Node.js version must be a valid semantic version (semver), e.g. 22.10.0 or 24.10.0" + }, + "destination": { + "type": "string", + "description": "The folder name of the project/application", + "$default": { + "$source": "argv", + "index": 2 + }, + "x-prompt": "Where should the project be stored", + "pattern": "^[a-z0-9-]+$", + "patternErrorMessage": "Destination folder name must contain only lowercase alphanumeric characters and dashes" } }, "required": ["name"] diff --git a/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template b/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template index 66a4fbe..39fb730 100644 --- a/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template +++ b/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template @@ -1,3 +1,21 @@ +import eslintPluginImport from 'eslint-plugin-import'; import baseConfig from '../../eslint.config.mjs'; -export default [...baseConfig]; \ No newline at end of file +export default [ + ...baseConfig, + { + files: ['**/*.ts'], + plugins: { import: eslintPluginImport }, + rules: { + 'import/no-extraneous-dependencies': [ + 'warn', + { + optionalDependencies: false, + peerDependencies: false, + bundledDependencies: false, + packageDir: ['.', '..', '../..'], + }, + ], + }, + }, +]; diff --git a/packages/nx-cdk/src/generators/service/files/package.json.template b/packages/nx-cdk/src/generators/service/files/package.json.template index 27ce670..929dcb9 100644 --- a/packages/nx-cdk/src/generators/service/files/package.json.template +++ b/packages/nx-cdk/src/generators/service/files/package.json.template @@ -14,13 +14,6 @@ "nx": { "tags": [ "scope:services" - ], - "targets": { - "pg": { - "options": { - "stack": "dev/<%= name %>" - } - } - } + ] } } diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index eced4d2..2f4e12e 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -3,6 +3,7 @@ import { join } from 'path'; import { addServiceStackToMainApplication, constructProjectTsConfigFiles, + splitInputName, } from '../helpers/utilities'; import { ServiceGeneratorSchema } from './schema'; @@ -26,9 +27,7 @@ function addTsConfigReference(tree: Tree, referencePath: string) { export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSchema) { const projectRoot = `${SERVICES_FOLDER}/${options.name}`; - const nameParts = options.name - .split('-') - .map(part => part.charAt(0).toUpperCase() + part.slice(1)); + const nameParts = splitInputName(options.name); const constant = nameParts.map(name => name.toUpperCase()).join('_'); const stack = `${nameParts.join('')}Stack`; From 49596def2b790722887d6fe613b6216a4ab5400c Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Wed, 3 Dec 2025 17:35:20 +1100 Subject: [PATCH 14/24] MI-250: Use full stage name to match with DevOps naming convention --- .../generators/helpers/configs/packageJson.ts | 6 +++--- .../generators/preset/files/README.md.template | 2 +- .../files/application/bin/main.ts.template | 16 ++++++++-------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 2cefaa0..6323634 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -11,9 +11,9 @@ export const PACKAGE_JSON = { typecheck: 'nx affected -t typecheck', 'typecheck:all': 'nx run-many -t typecheck', postinstall: `[ -d .git ] && git config core.hooksPath '.git-hooks' || true`, - 'pg:synth': `nx run application:cdk synth 'dev/**' --exclusively --profile playground`, - 'pg:deploy': `nx run application:cdk deploy --method 'direct' 'dev/**' --exclusively --require-approval never --profile playground`, - 'pg:destroy': "nx run application:cdk destroy 'dev/**' --profile playground", + 'pg:synth': `nx run application:cdk synth 'development/**' --exclusively --profile playground`, + 'pg:deploy': `nx run application:cdk deploy --method 'direct' 'development/**' --exclusively --require-approval never --profile playground`, + 'pg:destroy': "nx run application:cdk destroy 'development/**' --profile playground", audit: 'nx run-many -t lint typecheck test --configuration coverage --skip-nx-cache', }, dependencies: {}, diff --git a/packages/nx-cdk/src/generators/preset/files/README.md.template b/packages/nx-cdk/src/generators/preset/files/README.md.template index adebb7b..9f7d454 100644 --- a/packages/nx-cdk/src/generators/preset/files/README.md.template +++ b/packages/nx-cdk/src/generators/preset/files/README.md.template @@ -18,7 +18,7 @@ Services deployment are managed by the main [CDK Application](./application/READ ``` <%= folderName %>/ ā”œā”€ā”€ application/ # CDK Application & orchestration -│ ā”œā”€ā”€ bin/main.ts # CDK App entry point (dev/stg/prd stages) +│ ā”œā”€ā”€ bin/main.ts # CDK App entry point (development/staging/production stages) │ ā”œā”€ā”€ lib/ # Service stack composition │ └── cdk.json # CDK configuration │ diff --git a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template index ecbaa2a..a160afa 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template @@ -24,7 +24,7 @@ Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER); /** * Static Stage Creation Approach * - * We use static stage creation (explicitly defining dev, stg, prd) for several reasons: + * We use static stage creation (explicitly defining development, staging, production) for several reasons: * * 1. **Predictability**: All stages are known at synthesis time, making the CDK app * behavior deterministic and easier to reason about. @@ -49,24 +49,24 @@ Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER); * construct tree. When the same injector type is defined at both app and stage levels, the * stage-level injector takes precedence and overrides the app-level configuration. */ -const dev = new ApplicationStage(app, 'dev', { +const development = new ApplicationStage(app, 'development', { propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'SHORT' })], }); -Aspects.of(dev).add(new MicroserviceChecks()); +Aspects.of(development).add(new MicroserviceChecks()); -const stg = new ApplicationStage(app, 'stg', { +const staging = new ApplicationStage(app, 'staging', { propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'MEDIUM' })], }); -Aspects.of(stg).add(new MicroserviceChecks()); +Aspects.of(staging).add(new MicroserviceChecks()); -const prd = new ApplicationStage(app, 'prd', { +const production = new ApplicationStage(app, 'production', { propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'LONG' })], }); -Aspects.of(prd).add(new MicroserviceChecks()); +Aspects.of(production).add(new MicroserviceChecks()); /** * This aspect ensures all Lambda functions and Step Functions in production * are automatically versioned and have a stable 'live' alias pointing to the * current version, enabling zero-downtime deployments. */ -Aspects.of(prd).add(new VersionFunctionsAspect()); +Aspects.of(production).add(new VersionFunctionsAspect()); From 9b8fd445a6ed542adcef249c339dbcbc70cb5745 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Thu, 4 Dec 2025 11:08:32 +1100 Subject: [PATCH 15/24] MI-250: Few final touch up and it's ready --- .../generators/helpers/configs/packageJson.ts | 25 +++++++++++-------- .../preset/files/README.md.template | 7 ++++-- .../service/files/README.md.template | 2 +- .../src/generators/service/generator.ts | 1 + 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 6323634..220c8bc 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -10,21 +10,24 @@ export const PACKAGE_JSON = { 'lint:all': 'nx run-many -t lint', typecheck: 'nx affected -t typecheck', 'typecheck:all': 'nx run-many -t typecheck', - postinstall: `[ -d .git ] && git config core.hooksPath '.git-hooks' || true`, + postinstall: `[ -d .git ] && git config core.hooksPath '.git-hooks' && chmod +x .git-hooks/* || true`, 'pg:synth': `nx run application:cdk synth 'development/**' --exclusively --profile playground`, 'pg:deploy': `nx run application:cdk deploy --method 'direct' 'development/**' --exclusively --require-approval never --profile playground`, 'pg:destroy': "nx run application:cdk destroy 'development/**' --profile playground", audit: 'nx run-many -t lint typecheck test --configuration coverage --skip-nx-cache', }, - dependencies: {}, + dependencies: { + '@aligent/microservice-util-lib': '^1.2.0', + }, devDependencies: { - '@aligent/step-function-from-file': '^0.3.2', + '@aligent/cdk-step-function-from-file': '^0.3.2', + '@aligent/nx-openapi': '^1.0.0', '@aligent/ts-code-standards': '^4.1.0', - '@nx/eslint': '21.5.2', - '@nx/eslint-plugin': '21.5.2', - '@nx/js': '21.5.2', - '@nx/rsbuild': '21.5.2', - '@nx/vite': '21.5.2', + '@nx/eslint': '22.1.3', + '@nx/eslint-plugin': '22.1.3', + '@nx/js': '22.1.3', + '@nx/rsbuild': '22.1.3', + '@nx/vite': '22.1.3', '@rsbuild/core': '^1.5.6', '@swc-node/register': '^1.10.10', '@swc/core': '^1.13.3', @@ -45,13 +48,13 @@ export const PACKAGE_JSON = { 'fast-glob': '^3.3.3', jiti: '2.5.1', 'jsonc-eslint-parser': '^2.4.0', - nx: '21.5.2', + nx: '22.1.3', prettier: '^3.6.2', - 'store-parameters': '^1.0.6', + 'store-parameters': '^1.1.3', tslib: '^2.8.1', tsx: '^4.21.0', typescript: '~5.9.2', - vite: '7.1.6', + vite: '^7.2.6', vitest: '^3.2.4', }, workspaces: ['application', 'libs/*', 'services/*'], diff --git a/packages/nx-cdk/src/generators/preset/files/README.md.template b/packages/nx-cdk/src/generators/preset/files/README.md.template index 9f7d454..f780194 100644 --- a/packages/nx-cdk/src/generators/preset/files/README.md.template +++ b/packages/nx-cdk/src/generators/preset/files/README.md.template @@ -50,10 +50,13 @@ yarn install ## Contributing -1. Create new branch from `production` +We follow [trunk-based development framework](https://trunkbaseddevelopment.com/) as a start and will evolve depending on our need. + +1. Create new branch from `main` 2. Make your changes following code standards 3. Ensure your changes pass linting, type checks and testes -4. Submit a pull request to `staging` +4. Submit a pull request back to `main` +5. For deployment, submit a pull request from `main` to `staging` or `production` ## Adding New Services diff --git a/packages/nx-cdk/src/generators/service/files/README.md.template b/packages/nx-cdk/src/generators/service/files/README.md.template index 0146d47..f3d4fc2 100644 --- a/packages/nx-cdk/src/generators/service/files/README.md.template +++ b/packages/nx-cdk/src/generators/service/files/README.md.template @@ -1,4 +1,4 @@ -# <%= name %> +# <%= serviceName %> This is a CDK service generated using `@aligent/nx-cdk` for Nx. diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index 2f4e12e..8c12dbc 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -38,6 +38,7 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche generateFiles(tree, join(__dirname, 'files'), projectRoot, { ...options, + serviceName: nameParts.join(' '), constant, stack, template: '', From 6d22580f47010e7928e3c267fd5411d746a7fbc8 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Thu, 4 Dec 2025 11:22:03 +1100 Subject: [PATCH 16/24] MI-250: Added version plan --- .../version-plan-1764807248032.md | 20 +++++++++++++++++++ packages/nx-cdk/package.json | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 .nx/version-plans/version-plan-1764807248032.md diff --git a/.nx/version-plans/version-plan-1764807248032.md b/.nx/version-plans/version-plan-1764807248032.md new file mode 100644 index 0000000..4c9f60d --- /dev/null +++ b/.nx/version-plans/version-plan-1764807248032.md @@ -0,0 +1,20 @@ +--- +nx-cdk: patch +--- + +This is the initial release of `@aligent/nx-cdk`, an Nx plugin for AWS CDK development that helps scaffold and manage CDK projects within an Nx monorepo structure. + +### Preset Generator: + +- Initialize new AWS CDK projects with complete Nx workspace structure +- Creates root configuration files (ESLint, Prettier, RSBuild, Vitest, TypeScript) +- Scaffolds CDK application with bin/main.ts entry point and service stacks +- Configurable Node.js version support (default: 24.11.0) +- Includes CDK configuration files (cdk.json, cdk.context.json) + +### Service Generator: + +- Create new CDK services within existing projects +- Generates service structure in `services//` directory +- Includes build configuration (RSBuild), testing setup (Vitest), and linting (ESLint) +- Auto-registers stacks to main CDK application diff --git a/packages/nx-cdk/package.json b/packages/nx-cdk/package.json index 66182a6..49f2a6d 100644 --- a/packages/nx-cdk/package.json +++ b/packages/nx-cdk/package.json @@ -1,6 +1,6 @@ { "name": "@aligent/nx-cdk", - "version": "0.0.1", + "version": "0.0.0", "type": "commonjs", "main": "./src/index.js", "typings": "./src/index.d.ts", From e215283344457b4b9f07fec11d5d192dd63b6048 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Thu, 4 Dec 2025 11:25:46 +1100 Subject: [PATCH 17/24] MI-250: Address Aikido suggestion --- packages/nx-cdk/src/generators/helpers/utilities.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts index fbe86b9..ba90697 100644 --- a/packages/nx-cdk/src/generators/helpers/utilities.ts +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -91,6 +91,11 @@ export async function addServiceStackToMainApplication( projectName: string ) { const application = readProjectConfiguration(tree, projectName); + + if (application.root.includes('..')) { + throw new Error('Invalid application root path'); + } + const stacksPath = join(workspaceRoot, application.root, 'lib/service-stacks.ts'); const project = new Project(); From dc1fb75750cb97d4f0b173f40e6d1e47d06efde0 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Thu, 4 Dec 2025 12:03:42 +1100 Subject: [PATCH 18/24] MI-250: Fixed few test cases & lint issues --- .../generators/helpers/configs/tsConfigs.ts | 2 +- .../src/generators/helpers/utilities.ts | 13 +++-- .../src/generators/preset/preset.spec.ts | 6 +-- .../nx-cdk/src/generators/preset/schema.d.ts | 2 + .../nx-cdk/src/generators/preset/schema.json | 11 ---- .../src/generators/service/generator.spec.ts | 50 ++++--------------- 6 files changed, 26 insertions(+), 58 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts b/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts index a8bfa0f..71c478d 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/tsConfigs.ts @@ -4,7 +4,7 @@ interface TsConfig { files?: string[]; include: string[]; exclude?: string[]; - references: Record[]; + references: Array>; } const BASE_CONFIG = '@aligent/ts-code-standards/tsconfigs-extend'; diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts index ba90697..ad4c9f5 100644 --- a/packages/nx-cdk/src/generators/helpers/utilities.ts +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -1,4 +1,6 @@ -import { readJsonFile, readProjectConfiguration, Tree, workspaceRoot } from '@nx/devkit'; +/* v8 ignore start */ +import { readJsonFile, readProjectConfiguration, Tree } from '@nx/devkit'; +import { existsSync } from 'fs'; import { join } from 'path'; import { Project } from 'ts-morph'; import { PACKAGE_JSON } from './configs/packageJson'; @@ -57,7 +59,7 @@ function isPackageJsonWithVersion(obj: unknown): obj is { version: string } { typeof obj === 'object' && obj !== null && 'version' in obj && - typeof (obj as any).version === 'string' + typeof obj.version === 'string' ); } @@ -96,7 +98,12 @@ export async function addServiceStackToMainApplication( throw new Error('Invalid application root path'); } - const stacksPath = join(workspaceRoot, application.root, 'lib/service-stacks.ts'); + const stacksPath = join(tree.root, application.root, 'lib/service-stacks.ts'); + + if (!existsSync(stacksPath)) { + console.log('Service Stacks does not exist, skipping service stacks registration.'); + return; + } const project = new Project(); const stackSource = project.addSourceFileAtPath(stacksPath); diff --git a/packages/nx-cdk/src/generators/preset/preset.spec.ts b/packages/nx-cdk/src/generators/preset/preset.spec.ts index 02b1284..67218c9 100644 --- a/packages/nx-cdk/src/generators/preset/preset.spec.ts +++ b/packages/nx-cdk/src/generators/preset/preset.spec.ts @@ -1,4 +1,4 @@ -import { Tree, readProjectConfiguration } from '@nx/devkit'; +import { Tree, readNxJson } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { presetGenerator } from './preset'; @@ -6,7 +6,7 @@ import { PresetGeneratorSchema } from './schema'; describe('preset generator', () => { let tree: Tree; - const options: PresetGeneratorSchema = { name: 'test' }; + const options: PresetGeneratorSchema = { name: 'test', nodeVersion: '24.11.0' }; beforeEach(() => { tree = createTreeWithEmptyWorkspace(); @@ -14,7 +14,7 @@ describe('preset generator', () => { it('should run successfully', async () => { await presetGenerator(tree, options); - const config = readProjectConfiguration(tree, 'test'); + const config = readNxJson(tree); expect(config).toBeDefined(); }); }); diff --git a/packages/nx-cdk/src/generators/preset/schema.d.ts b/packages/nx-cdk/src/generators/preset/schema.d.ts index e1d0203..8d9a0be 100644 --- a/packages/nx-cdk/src/generators/preset/schema.d.ts +++ b/packages/nx-cdk/src/generators/preset/schema.d.ts @@ -1,5 +1,7 @@ +/* v8 ignore start */ export interface PresetGeneratorSchema { name: string; nodeVersion: string; + // FIXME: Add this into schema.json once we move to our own cli tool destination?: string; } diff --git a/packages/nx-cdk/src/generators/preset/schema.json b/packages/nx-cdk/src/generators/preset/schema.json index 36ddf28..1602429 100644 --- a/packages/nx-cdk/src/generators/preset/schema.json +++ b/packages/nx-cdk/src/generators/preset/schema.json @@ -26,17 +26,6 @@ "x-prompt": "What is the target Node.js version the project?", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$", "patternErrorMessage": "Node.js version must be a valid semantic version (semver), e.g. 22.10.0 or 24.10.0" - }, - "destination": { - "type": "string", - "description": "The folder name of the project/application", - "$default": { - "$source": "argv", - "index": 2 - }, - "x-prompt": "Where should the project be stored", - "pattern": "^[a-z0-9-]+$", - "patternErrorMessage": "Destination folder name must contain only lowercase alphanumeric characters and dashes" } }, "required": ["name"] diff --git a/packages/nx-cdk/src/generators/service/generator.spec.ts b/packages/nx-cdk/src/generators/service/generator.spec.ts index ba16c77..b2c982a 100644 --- a/packages/nx-cdk/src/generators/service/generator.spec.ts +++ b/packages/nx-cdk/src/generators/service/generator.spec.ts @@ -1,9 +1,16 @@ import { Tree } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; - import { serviceGenerator } from './generator'; import { ServiceGeneratorSchema } from './schema'; +const application = { + name: 'application', + type: 'module', + main: './bin/main.ts', + types: './bin/main.ts', + nx: { tags: ['scope:application'] }, +}; + describe('service generator', () => { let tree: Tree; beforeEach(() => { @@ -17,9 +24,10 @@ describe('service generator', () => { "references": [] }` ); + tree.write('application/package.json', JSON.stringify(application)); }); - it('should run successfully when type is general', async () => { + it('should run successfully', async () => { const options: ServiceGeneratorSchema = { name: 'test' }; await expect(serviceGenerator(tree, options)).resolves.not.toThrow(); }); @@ -37,42 +45,4 @@ describe('service generator', () => { expect(references).toEqual([{ path: './services/test' }]); }); - - it('should register the services as a no-buildable typecheck target', async () => { - const options: ServiceGeneratorSchema = { name: 'test' }; - - await serviceGenerator(tree, options); - - const nxJson = tree.read('nx.json', 'utf-8'); - - assert.isNotNull(nxJson); - - const plugins = JSON.parse(nxJson).plugins; - - expect(plugins).toEqual([ - { - plugin: '@nx/js/typescript', - options: { - typecheck: { - targetName: 'typecheck', - }, - }, - include: ['services/test/*'], - }, - ]); - }); - - it('should not add paths to the base tsconfig', async () => { - const options: ServiceGeneratorSchema = { name: 'test' }; - - await serviceGenerator(tree, options); - - const tsconfig = tree.read('tsconfig.base.json', 'utf-8'); - - assert.isNotNull(tsconfig); - - const paths = JSON.parse(tsconfig).paths; - - expect(paths).toBe(undefined); - }); }); From 7b18567400763333b55a36e3dbd2c02f8ce3bfd8 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Fri, 5 Dec 2025 11:23:52 +1100 Subject: [PATCH 19/24] MI-250: Few small tweaks to support nx-openapi generator --- packages/nx-cdk/src/generators/helpers/configs/packageJson.ts | 2 +- .../src/generators/service/files/eslint.config.mjs.template | 1 - .../nx-cdk/src/generators/service/files/package.json.template | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 220c8bc..0b143bc 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -57,7 +57,7 @@ export const PACKAGE_JSON = { vite: '^7.2.6', vitest: '^3.2.4', }, - workspaces: ['application', 'libs/*', 'services/*'], + workspaces: ['application', 'clients', 'libs/*', 'services/*'], packageManager: 'yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8', } as const; diff --git a/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template b/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template index 39fb730..7577373 100644 --- a/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template +++ b/packages/nx-cdk/src/generators/service/files/eslint.config.mjs.template @@ -12,7 +12,6 @@ export default [ { optionalDependencies: false, peerDependencies: false, - bundledDependencies: false, packageDir: ['.', '..', '../..'], }, ], diff --git a/packages/nx-cdk/src/generators/service/files/package.json.template b/packages/nx-cdk/src/generators/service/files/package.json.template index 929dcb9..73e6940 100644 --- a/packages/nx-cdk/src/generators/service/files/package.json.template +++ b/packages/nx-cdk/src/generators/service/files/package.json.template @@ -11,6 +11,9 @@ }, "./package.json": "./package.json" }, + "bundleDependencies": [ + "clients" + ], "nx": { "tags": [ "scope:services" From 11683e69cbee621c862b99e59c567b704ee63f1c Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Wed, 10 Dec 2025 08:47:40 +1030 Subject: [PATCH 20/24] MI-250: Added Verdaccio for local development --- README.md | 4 - package-lock.json | 3342 ++++++++++++++++++++++++++++++++++++++++++--- package.json | 1 + 3 files changed, 3170 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 0801777..6033803 100644 --- a/README.md +++ b/README.md @@ -110,10 +110,6 @@ npx nx release publish npx nx stop-local-registry microservice-development-utilities ``` -### Note - -- At the moment, we do not include `verdaccio` in our dev dependencies yet because of [CVE-2025-56200]https://github.com/advisories/GHSA-9965-vmph-33xx vulnerable in one of Verdaccio v6.2.1 dependencies. It will be added back once they resolve the issue. For now, we will need to add it in when we use it and remove it before making a PR. - ## Project Structure ``` diff --git a/package-lock.json b/package-lock.json index 74a36f8..bc2dbe1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,6 +46,7 @@ "typedoc": "^0.28.14", "typedoc-plugin-markdown": "^4.9.0", "typescript": "^5.9.3", + "verdaccio": "^6.2.4", "vite": "^6.4.1", "vitest": "3.1.2" } @@ -2895,6 +2896,36 @@ "dev": true, "license": "MIT" }, + "node_modules/@cypress/request": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.9.tgz", + "integrity": "sha512-I3l7FdGRXluAS44/0NguwWlO83J18p0vlr2FYHrJkWdNYhgVoiYo61IXPqaOsL+vNxU1ZqMACzItGK3/KKDsdw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~4.0.4", + "http-signature": "~1.4.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.14.0", + "safe-buffer": "^5.1.2", + "tough-cookie": "^5.0.0", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@emnapi/core": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", @@ -4813,6 +4844,13 @@ "typescript": "^3 || ^4 || ^5" } }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -5269,6 +5307,19 @@ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "license": "MIT" }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -6554,6 +6605,19 @@ "@swc/counter": "^0.1.3" } }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@ts-morph/common": { "version": "0.28.1", "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.28.1.tgz", @@ -6706,7 +6770,7 @@ "version": "22.19.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz", "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -6725,6 +6789,16 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "license": "MIT" }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/sinon": { "version": "17.0.4", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.4.tgz", @@ -7034,221 +7108,737 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@vitest/coverage-v8": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.2.tgz", - "integrity": "sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==", - "dev": true, + "node_modules/@verdaccio/auth": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/auth/-/auth-8.0.0-next-8.28.tgz", + "integrity": "sha512-tM0URyKFq1dGFaoBN0whT1SDur1lBKG+pkQwxgJIXgH04DmefLCH63pn/K1iDDfLwqyxMewpmvMTBS390SSR+A==", + "devOptional": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^1.0.2", - "debug": "^4.4.0", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.17", - "magicast": "^0.3.5", - "std-env": "^3.9.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^2.0.0" + "@verdaccio/config": "8.0.0-next-8.28", + "@verdaccio/core": "8.0.0-next-8.28", + "@verdaccio/loaders": "8.0.0-next-8.18", + "@verdaccio/signature": "8.0.0-next-8.20", + "debug": "4.4.3", + "lodash": "4.17.21", + "verdaccio-htpasswd": "13.0.0-next-8.28" }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "3.1.2", - "vitest": "3.1.2" + "engines": { + "node": ">=18" }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/coverage-v8/node_modules/@bcoe/v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", - "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", - "dev": true, + "node_modules/@verdaccio/config": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/config/-/config-8.0.0-next-8.28.tgz", + "integrity": "sha512-yl7lcSOzT9y7EgUald4bZXIKxhZdAPRvtDZwmsPL433bc+CInyriqYCo6L4fZgFxYAdj9iDzvZIJtCtsFc+8NA==", + "devOptional": true, "license": "MIT", + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.28", + "debug": "4.4.3", + "js-yaml": "4.1.1", + "lodash": "4.17.21" + }, "engines": { "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/coverage-v8/node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@verdaccio/core": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/core/-/core-8.0.0-next-8.28.tgz", + "integrity": "sha512-W/wBvgF53CLr7m2zDV4QnHGYh0M/D3HTm5OuTxIjeclwDZGH2UHSdiI2BFFhvW7zt6MQVjfTQdgtcH4cmLGXhQ==", + "devOptional": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" + "ajv": "8.17.1", + "http-errors": "2.0.0", + "http-status-codes": "2.3.0", + "minimatch": "7.4.6", + "process-warning": "1.0.0", + "semver": "7.7.3" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/expect": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", - "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", - "dev": true, + "node_modules/@verdaccio/core/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "devOptional": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.2", - "@vitest/utils": "3.1.2", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@vitest/mocker": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", - "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", - "dev": true, - "license": "MIT", + "node_modules/@verdaccio/core/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "devOptional": true, + "license": "ISC", "dependencies": { - "@vitest/spy": "3.1.2", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "brace-expansion": "^2.0.1" }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0" + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@vitest/pretty-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", - "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", - "dev": true, + "node_modules/@verdaccio/file-locking": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@verdaccio/file-locking/-/file-locking-10.3.1.tgz", + "integrity": "sha512-oqYLfv3Yg3mAgw9qhASBpjD50osj2AX4IwbkUtyuhhKGyoFU9eZdrbeW6tpnqUnj6yBMtAPm2eGD4BwQuX400g==", + "devOptional": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^2.0.0" + "lockfile": "1.0.4" + }, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/runner": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", - "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", - "dev": true, + "node_modules/@verdaccio/hooks": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/hooks/-/hooks-8.0.0-next-8.28.tgz", + "integrity": "sha512-K+Cu9Pls8G2Wvu6pOYuelCTNBLpSOpmodJaPbUVv/kkhsTphgRiRENhOZGbiPhfVKehQeUCj9WiF8C7xzTf2Vg==", + "devOptional": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.2", - "pathe": "^2.0.3" + "@verdaccio/core": "8.0.0-next-8.28", + "@verdaccio/logger": "8.0.0-next-8.28", + "debug": "4.4.3", + "got-cjs": "12.5.4", + "handlebars": "4.7.8" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/snapshot": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", - "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", - "dev": true, + "node_modules/@verdaccio/loaders": { + "version": "8.0.0-next-8.18", + "resolved": "https://registry.npmjs.org/@verdaccio/loaders/-/loaders-8.0.0-next-8.18.tgz", + "integrity": "sha512-p8o/DST+TPLz1pTqnduYKMggNxYO5ET+3a4UXLArVDWbhqNnYFRmZVyIW8r0JFOuRwUKdpcJMkXefufMRm8B8g==", + "devOptional": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.2", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" + "@verdaccio/core": "8.0.0-next-8.28", + "debug": "4.4.3", + "lodash": "4.17.21" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/spy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", - "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", - "dev": true, + "node_modules/@verdaccio/local-storage-legacy": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@verdaccio/local-storage-legacy/-/local-storage-legacy-11.1.1.tgz", + "integrity": "sha512-P6ahH2W6/KqfJFKP+Eid7P134FHDLNvHa+i8KVgRVBeo2/IXb6FEANpM1mCVNvPANu0LCAmNJBOXweoUKViaoA==", + "devOptional": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.2" + "@verdaccio/core": "8.0.0-next-8.21", + "@verdaccio/file-locking": "10.3.1", + "@verdaccio/streams": "10.2.1", + "async": "3.2.6", + "debug": "4.4.1", + "lodash": "4.17.21", + "lowdb": "1.0.0", + "mkdirp": "1.0.4" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/ui": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.1.2.tgz", - "integrity": "sha512-+YPgKiLpFEyBVJNHDkRcSDcLrrnr20lyU4HQoI9Jtq1MdvoX8usql9h38mQw82MBU1Zo5BPC6sw+sXZ6NS18CQ==", - "dev": true, + "node_modules/@verdaccio/local-storage-legacy/node_modules/@verdaccio/core": { + "version": "8.0.0-next-8.21", + "resolved": "https://registry.npmjs.org/@verdaccio/core/-/core-8.0.0-next-8.21.tgz", + "integrity": "sha512-n3Y8cqf84cwXxUUdTTfEJc8fV55PONPKijCt2YaC0jilb5qp1ieB3d4brqTOdCdXuwkmnG2uLCiGpUd/RuSW0Q==", + "devOptional": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.2", - "fflate": "^0.8.2", - "flatted": "^3.3.3", - "pathe": "^2.0.3", - "sirv": "^3.0.1", - "tinyglobby": "^0.2.13", - "tinyrainbow": "^2.0.0" + "ajv": "8.17.1", + "http-errors": "2.0.0", + "http-status-codes": "2.3.0", + "minimatch": "7.4.6", + "process-warning": "1.0.0", + "semver": "7.7.2" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">=18" }, - "peerDependencies": { - "vitest": "3.1.2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" } }, - "node_modules/@vitest/utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", - "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", - "dev": true, + "node_modules/@verdaccio/local-storage-legacy/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "devOptional": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.2", - "loupe": "^3.1.3", - "tinyrainbow": "^2.0.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "license": "BSD-2-Clause" - }, - "node_modules/@yarnpkg/parsers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.2.tgz", - "integrity": "sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==", - "license": "BSD-2-Clause", + "node_modules/@verdaccio/local-storage-legacy/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "devOptional": true, + "license": "MIT", "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" + "ms": "^2.1.3" }, "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/@yarnpkg/parsers/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@verdaccio/local-storage-legacy/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@verdaccio/local-storage-legacy/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@verdaccio/logger": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/logger/-/logger-8.0.0-next-8.28.tgz", + "integrity": "sha512-Iss+5mUJSvkDIwOWv6lk9OZjHl9PKHXf4FwM/YI5a77B06r5LYvdpppKVwGxBFn8jFcyGBl97zz8uqz6uD/rhQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/logger-commons": "8.0.0-next-8.28", + "pino": "9.14.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/logger-commons": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-commons/-/logger-commons-8.0.0-next-8.28.tgz", + "integrity": "sha512-GlIpSCKC6uKR4D9BZFbCiiJHeAaZ/n8izYqMKqFV5RKOrdMaMmYKjVFLvjGDpd22AFnCvSUfgrKCX1FXe8ZFqw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.28", + "@verdaccio/logger-prettify": "8.0.0-next-8.4", + "colorette": "2.0.20", + "debug": "4.4.3" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/logger-commons/node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@verdaccio/logger-prettify": { + "version": "8.0.0-next-8.4", + "resolved": "https://registry.npmjs.org/@verdaccio/logger-prettify/-/logger-prettify-8.0.0-next-8.4.tgz", + "integrity": "sha512-gjI/JW29fyalutn/X1PQ0iNuGvzeVWKXRmnLa7gXVKhdi4p37l/j7YZ7n44XVbbiLIKAK0pbavEg9Yr66QrYaA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "colorette": "2.0.20", + "dayjs": "1.11.13", + "lodash": "4.17.21", + "on-exit-leak-free": "2.1.2", + "pino-abstract-transport": "1.2.0", + "sonic-boom": "3.8.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/logger-prettify/node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@verdaccio/middleware": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/middleware/-/middleware-8.0.0-next-8.28.tgz", + "integrity": "sha512-L2PL4JJQ6dKipNrA/weWTEw47ZUgiJrvKb7g/z3yuDR5O/C7AJ+mOxqsWww0kgq0cvQm+kOXMVY9Oq1g9a+Agw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/config": "8.0.0-next-8.28", + "@verdaccio/core": "8.0.0-next-8.28", + "@verdaccio/url": "13.0.0-next-8.28", + "debug": "4.4.3", + "express": "4.21.2", + "express-rate-limit": "5.5.1", + "lodash": "4.17.21", + "lru-cache": "7.18.3" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/middleware/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@verdaccio/search-indexer": { + "version": "8.0.0-next-8.5", + "resolved": "https://registry.npmjs.org/@verdaccio/search-indexer/-/search-indexer-8.0.0-next-8.5.tgz", + "integrity": "sha512-0GC2tJKstbPg/W2PZl2yE+hoAxffD2ZWilEnEYSEo2e9UQpNIy2zg7KE/uMUq2P72Vf5EVfVzb8jdaH4KV4QeA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/signature": { + "version": "8.0.0-next-8.20", + "resolved": "https://registry.npmjs.org/@verdaccio/signature/-/signature-8.0.0-next-8.20.tgz", + "integrity": "sha512-1kwO+l7cLiDjXUwqVTvaKXvcI4C23u4cZCVnGGKXRcahrbVm7Hdh12wSIX5V9gV6O3VlWH458JxoimpPAo4Oxw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/config": "8.0.0-next-8.28", + "@verdaccio/core": "8.0.0-next-8.28", + "debug": "4.4.3", + "jsonwebtoken": "9.0.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/streams": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/@verdaccio/streams/-/streams-10.2.1.tgz", + "integrity": "sha512-OojIG/f7UYKxC4dYX8x5ax8QhRx1b8OYUAMz82rUottCuzrssX/4nn5QE7Ank0DUSX3C9l/HPthc4d9uKRJqJQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/tarball": { + "version": "13.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/tarball/-/tarball-13.0.0-next-8.28.tgz", + "integrity": "sha512-89FHelT4xsrBeAk6WYhhUR6cgpky1IAgBiN3VtWs2b3KA8XesZeG7G0UDygTVEe2O0etXYtrz9vlqZ9nYEaAGA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.28", + "@verdaccio/url": "13.0.0-next-8.28", + "debug": "4.4.3", + "gunzip-maybe": "1.4.2", + "tar-stream": "3.1.7" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/tarball/node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/@verdaccio/ui-theme": { + "version": "8.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/ui-theme/-/ui-theme-8.0.0-next-8.28.tgz", + "integrity": "sha512-TzhdphchcvsI38UPP5hdNJh+LAFvRhYlfrtBuqlZy0BHeGM2i2MNioGl2il2NLVteqXAK9MqnuC5WGxCFXoDYw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@verdaccio/url": { + "version": "13.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/url/-/url-13.0.0-next-8.28.tgz", + "integrity": "sha512-42wA5LkXWpY42pONEHQhAC5h8nFXdDHChP22swOitTp1xzvAs+PmwUlrol7kMXMWO04skDCSSW1Q54eNkTx/rA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.28", + "debug": "4.4.3", + "validator": "13.15.23" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/utils": { + "version": "8.1.0-next-8.28", + "resolved": "https://registry.npmjs.org/@verdaccio/utils/-/utils-8.1.0-next-8.28.tgz", + "integrity": "sha512-/AYNGafG9T90NPGsq6eDMuXx+41tlWfiYsCchgwz074GWEitZ2nAZQWWNvYvFVB2hXzord52muEVTWjgaZPOdQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.28", + "lodash": "4.17.21", + "minimatch": "7.4.6" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/@verdaccio/utils/node_modules/minimatch": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.1.2.tgz", + "integrity": "sha512-XDdaDOeaTMAMYW7N63AqoK32sYUWbXnTkC6tEbVcu3RlU1bB9of32T+PGf8KZvxqLNqeXhafDFqCkwpf2+dyaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^1.0.2", + "debug": "^4.4.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.17", + "magicast": "^0.3.5", + "std-env": "^3.9.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "3.1.2", + "vitest": "3.1.2" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/coverage-v8/node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@vitest/coverage-v8/node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@vitest/expect": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", + "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", + "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.1.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", + "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.1.2", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", + "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.1.2", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", + "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/ui": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.1.2.tgz", + "integrity": "sha512-+YPgKiLpFEyBVJNHDkRcSDcLrrnr20lyU4HQoI9Jtq1MdvoX8usql9h38mQw82MBU1Zo5BPC6sw+sXZ6NS18CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.1.2", + "fflate": "^0.8.2", + "flatted": "^3.3.3", + "pathe": "^2.0.3", + "sirv": "^3.0.1", + "tinyglobby": "^0.2.13", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "3.1.2" + } + }, + "node_modules/@vitest/utils": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", + "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.1.2", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "license": "BSD-2-Clause" + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.2.tgz", + "integrity": "sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==", + "license": "BSD-2-Clause", + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/@yarnpkg/parsers/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "license": "MIT", "dependencies": { @@ -7280,6 +7870,43 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -7421,6 +8048,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/apache-md5": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.8.tgz", + "integrity": "sha512-FCAJojipPn0bXjuEpjOOOMN8FZDkxfWWp4JGN9mifU2IhxvKyXZYqpzPHdnTSUpmPDy+tsslB6Z1g+Vg6nVbYA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -7454,6 +8091,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/array-includes": { "version": "3.1.9", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", @@ -7597,6 +8241,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -7636,6 +8300,16 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -7664,6 +8338,23 @@ "tslib": "^2.1.0" } }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/axe-core": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz", @@ -7695,6 +8386,21 @@ "node": ">= 0.4" } }, + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "devOptional": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -7952,6 +8658,21 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "devOptional": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -7994,6 +8715,23 @@ "node": ">= 0.8" } }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -8005,6 +8743,77 @@ "readable-stream": "^3.4.0" } }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bowser": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", @@ -8033,6 +8842,16 @@ "node": ">=8" } }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "pako": "~0.2.0" + } + }, "node_modules/browserslist": { "version": "4.28.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", @@ -8100,12 +8919,29 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "devOptional": true, + "license": "BSD-3-Clause" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -8116,6 +8952,62 @@ "node": ">=8" } }, + "node_modules/cacheable-lookup": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz", + "integrity": "sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -8152,7 +9044,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -8204,6 +9096,13 @@ ], "license": "CC-BY-4.0" }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "devOptional": true, + "license": "Apache-2.0" + }, "node_modules/chai": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", @@ -8310,6 +9209,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/clipanion": { + "version": "4.0.0-rc.4", + "resolved": "https://registry.npmjs.org/clipanion/-/clipanion-4.0.0-rc.4.tgz", + "integrity": "sha512-CXkMQxU6s9GklO/1f714dkKBMu1lopS1WFF0B8o4AxPykR1hpozxSiUZ5ZUeBjfPgCWqbcNOtZVFhB8Lkfp1+Q==", + "devOptional": true, + "license": "MIT", + "workspaces": [ + "website" + ], + "dependencies": { + "typanion": "^3.8.0" + }, + "peerDependencies": { + "typanion": "*" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -8333,6 +9248,19 @@ "node": ">=0.8" } }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -8406,6 +9334,76 @@ "node": ">= 0.8" } }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -8420,12 +9418,73 @@ "dev": true, "license": "MIT" }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/core-js-compat": { "version": "3.46.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", @@ -8439,6 +9498,27 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/corser": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", @@ -8496,6 +9576,19 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -8550,6 +9643,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -8567,6 +9667,35 @@ } } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dedent": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", @@ -8621,6 +9750,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -8675,6 +9814,27 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8767,12 +9927,58 @@ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, "node_modules/eastasianwidth": { @@ -8782,6 +9988,34 @@ "dev": true, "license": "MIT" }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "devOptional": true, + "license": "MIT" + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -8823,6 +10057,16 @@ "dev": true, "license": "MIT" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -8857,6 +10101,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/envinfo": { + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.15.0.tgz", + "integrity": "sha512-chR+t7exF6y59kelhXw5I3849nTy7KIRO+ePdLMhCD+JRP/JvmkenDWP7QSFGlsHX+kxGxdDutOPrmj5j1HR6g==", + "devOptional": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -9097,6 +10354,13 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "devOptional": true, + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -9748,6 +11012,26 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -9755,6 +11039,26 @@ "dev": true, "license": "MIT" }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -9791,6 +11095,138 @@ "node": ">=12.0.0" } }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", + "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "devOptional": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -9804,6 +11240,13 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", @@ -9997,6 +11440,42 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "devOptional": true, + "license": "MIT" + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -10107,6 +11586,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, "node_modules/form-data": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", @@ -10123,6 +11612,33 @@ "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/front-matter": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", @@ -10297,6 +11813,19 @@ "node": ">= 0.4" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", @@ -10315,6 +11844,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -10416,11 +11955,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/got-cjs": { + "version": "12.5.4", + "resolved": "https://registry.npmjs.org/got-cjs/-/got-cjs-12.5.4.tgz", + "integrity": "sha512-Uas6lAsP8bRCt5WXGMhjFf/qEHTrm4v4qxGR02rLG2kdG9qedctvlkdwXVcDJ7Cs84X+r4dPU7vdwGjCaspXug==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "4.6.0", + "@szmarczak/http-timer": "4.0.6", + "@types/responselike": "1.0.0", + "cacheable-lookup": "6.1.0", + "cacheable-request": "7.0.2", + "decompress-response": "^6.0.0", + "form-data-encoder": "1.7.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "2.0.0", + "p-cancelable": "2.1.1", + "responselike": "2.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/graphemer": { @@ -10430,6 +11996,46 @@ "dev": true, "license": "MIT" }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" + } + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, "node_modules/harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", @@ -10575,6 +12181,30 @@ "dev": true, "license": "MIT" }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "devOptional": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", @@ -10618,6 +12248,42 @@ "node": ">=12" } }, + "node_modules/http-signature": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", + "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.18.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -10763,7 +12429,17 @@ "side-channel": "^1.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" } }, "node_modules/is-array-buffer": { @@ -10906,6 +12582,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -10999,6 +12682,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -11061,6 +12754,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -11160,6 +12860,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -11244,6 +12951,13 @@ "dev": true, "license": "ISC" }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "devOptional": true, + "license": "MIT" + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -11918,6 +13632,13 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -11934,7 +13655,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { @@ -11943,6 +13664,13 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "devOptional": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -11956,6 +13684,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "devOptional": true, + "license": "ISC" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -12011,6 +13746,72 @@ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "license": "MIT" }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "devOptional": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "devOptional": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "devOptional": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -12034,11 +13835,34 @@ "dev": true, "license": "MIT" }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", + "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "jwa": "^1.4.2", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -12120,12 +13944,71 @@ "node": ">=8" } }, + "node_modules/lockfile": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "signal-exit": "^3.0.2" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "license": "MIT" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -12133,6 +14016,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -12169,6 +14059,33 @@ "dev": true, "license": "MIT" }, + "node_modules/lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -12267,6 +14184,26 @@ "dev": true, "license": "MIT" }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "devOptional": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -12284,6 +14221,16 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -12315,7 +14262,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "mime": "cli.js" @@ -12354,6 +14301,16 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -12388,6 +14345,19 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "devOptional": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -12430,6 +14400,23 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/nise": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", @@ -12454,6 +14441,27 @@ "@sinonjs/commons": "^3.0.1" } }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -12483,6 +14491,19 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npm-package-arg": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", @@ -12594,7 +14615,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12613,7 +14634,7 @@ "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -12722,6 +14743,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -12938,6 +14992,16 @@ "@oxc-resolver/binding-win32-x64-msvc": "11.13.2" } }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -13000,6 +15064,13 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -13036,6 +15107,16 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -13138,6 +15219,25 @@ "node": ">= 14.16" } }, + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "devOptional": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -13156,6 +15256,136 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pino": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", + "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pino/node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino/node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/pino/node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/pirates": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", @@ -13406,6 +15636,30 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==", + "devOptional": true, + "license": "MIT" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -13425,12 +15679,49 @@ "dev": true, "license": "MIT" }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -13472,7 +15763,7 @@ "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -13505,6 +15796,65 @@ ], "license": "MIT" }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -13525,6 +15875,16 @@ "node": ">= 6" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -13667,6 +16027,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "devOptional": true, + "license": "MIT" + }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -13686,6 +16053,19 @@ "node": ">=10" } }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -13800,7 +16180,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/safe-push-apply": { @@ -13838,11 +16218,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/secure-compare": { @@ -13864,6 +16254,74 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -13913,6 +16371,13 @@ "node": ">= 0.4" } }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "devOptional": true, + "license": "ISC" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -13940,7 +16405,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -13960,7 +16425,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -13977,7 +16442,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -13996,7 +16461,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -14079,6 +16544,16 @@ "node": ">=8" } }, + "node_modules/sonic-boom": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -14108,12 +16583,48 @@ "source-map": "^0.6.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -14144,6 +16655,16 @@ "dev": true, "license": "MIT" }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/std-env": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", @@ -14151,6 +16672,16 @@ "dev": true, "license": "MIT" }, + "node_modules/steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha512-EEHMVYHNXFHfGtgjNITnka0aHhiAlo93F7z2/Pwd+g0teG9CnM3JIINM7hVVB5/rhw9voufD7Wukwgtw2uqh6w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.3" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", @@ -14165,6 +16696,25 @@ "node": ">= 0.4" } }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -14533,6 +17083,77 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -14605,6 +17226,26 @@ "node": ">=14.0.0" } }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/tmp": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", @@ -14634,6 +17275,16 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -14644,6 +17295,26 @@ "node": ">=6" } }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -14696,6 +17367,36 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "devOptional": true, + "license": "Unlicense" + }, + "node_modules/typanion": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/typanion/-/typanion-3.14.0.tgz", + "integrity": "sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==", + "devOptional": true, + "license": "MIT", + "workspaces": [ + "website" + ] + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -14732,6 +17433,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -14907,6 +17622,20 @@ "dev": true, "license": "MIT" }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -14930,7 +17659,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -14985,6 +17714,23 @@ "node": ">= 0.8.0" } }, + "node_modules/unix-crypt-td-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz", + "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==", + "devOptional": true, + "license": "BSD-3-Clause" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", @@ -15038,6 +17784,26 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "devOptional": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -15062,6 +17828,201 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validator": { + "version": "13.15.23", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.23.tgz", + "integrity": "sha512-4yoz1kEWqUjzi5zsPbAS/903QXSYp0UOtHsPpp7p9rHAw/W+dkInskAE386Fat3oKRROwO98d9ZB0G4cObgUyw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verdaccio": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/verdaccio/-/verdaccio-6.2.4.tgz", + "integrity": "sha512-1riItDS5ZmkLVclEOI4ibmJPCTfg1f8iEbdZWo7mgaEDHs1KS2JJnGq+dnoDlbo4efJ5mCyy1g7p32k/xx2+wg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@cypress/request": "3.0.9", + "@verdaccio/auth": "8.0.0-next-8.28", + "@verdaccio/config": "8.0.0-next-8.28", + "@verdaccio/core": "8.0.0-next-8.28", + "@verdaccio/hooks": "8.0.0-next-8.28", + "@verdaccio/loaders": "8.0.0-next-8.18", + "@verdaccio/local-storage-legacy": "11.1.1", + "@verdaccio/logger": "8.0.0-next-8.28", + "@verdaccio/middleware": "8.0.0-next-8.28", + "@verdaccio/search-indexer": "8.0.0-next-8.5", + "@verdaccio/signature": "8.0.0-next-8.20", + "@verdaccio/streams": "10.2.1", + "@verdaccio/tarball": "13.0.0-next-8.28", + "@verdaccio/ui-theme": "8.0.0-next-8.28", + "@verdaccio/url": "13.0.0-next-8.28", + "@verdaccio/utils": "8.1.0-next-8.28", + "async": "3.2.6", + "clipanion": "4.0.0-rc.4", + "compression": "1.8.1", + "cors": "2.8.5", + "debug": "4.4.3", + "envinfo": "7.15.0", + "express": "4.21.2", + "JSONStream": "1.3.5", + "lodash": "4.17.21", + "lru-cache": "7.18.3", + "mime": "3.0.0", + "semver": "7.7.3", + "verdaccio-audit": "13.0.0-next-8.28", + "verdaccio-htpasswd": "13.0.0-next-8.28" + }, + "bin": { + "verdaccio": "bin/verdaccio" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/verdaccio-audit": { + "version": "13.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/verdaccio-audit/-/verdaccio-audit-13.0.0-next-8.28.tgz", + "integrity": "sha512-vcl+V4R43QFSrch0QggG92hEd+aGh7fGBqkA1pcF/m4eJ2JQw7+/8JD5VJ/qCnt7Udnz9Jmey6SvgFgxsB6ODA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/config": "8.0.0-next-8.28", + "@verdaccio/core": "8.0.0-next-8.28", + "express": "4.21.2", + "https-proxy-agent": "5.0.1", + "node-fetch": "cjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/verdaccio-audit/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/verdaccio-audit/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/verdaccio-htpasswd": { + "version": "13.0.0-next-8.28", + "resolved": "https://registry.npmjs.org/verdaccio-htpasswd/-/verdaccio-htpasswd-13.0.0-next-8.28.tgz", + "integrity": "sha512-iAkhusaNUEvBeq+7Xn8YUqq4hXoVuAteZPrG4dwsqSjVliS7YQGdysQKYG89QnN9iMKAEvuSzhb+GP0c5dbL0g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@verdaccio/core": "8.0.0-next-8.28", + "@verdaccio/file-locking": "13.0.0-next-8.6", + "apache-md5": "1.1.8", + "bcryptjs": "2.4.3", + "debug": "4.4.3", + "http-errors": "2.0.0", + "unix-crypt-td-js": "1.1.4" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/verdaccio-htpasswd/node_modules/@verdaccio/file-locking": { + "version": "13.0.0-next-8.6", + "resolved": "https://registry.npmjs.org/@verdaccio/file-locking/-/file-locking-13.0.0-next-8.6.tgz", + "integrity": "sha512-F6xQWvsZnEyGjugrYfe+D/ChSVudXmBFWi8xuTIX6PAdp7dk9x9biOGQFW8O3GSAK8UhJ6WlRisQKJeYRa6vWQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "lockfile": "1.0.4" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/verdaccio" + } + }, + "node_modules/verdaccio/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/verdaccio/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "devOptional": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "devOptional": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/vite": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", @@ -15250,6 +18211,13 @@ "defaults": "^1.0.3" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "devOptional": true, + "license": "BSD-2-Clause" + }, "node_modules/whatwg-encoding": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", @@ -15263,6 +18231,17 @@ "node": ">=12" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -15395,6 +18374,13 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "devOptional": true, + "license": "MIT" + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -15451,6 +18437,16 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -15538,7 +18534,7 @@ }, "packages/nx-cdk": { "name": "@aligent/nx-cdk", - "version": "0.0.1", + "version": "0.0.0", "license": "MIT", "dependencies": { "@nx/devkit": "20.8.1", diff --git a/package.json b/package.json index 4bf2181..9bbc3f2 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "typedoc": "^0.28.14", "typedoc-plugin-markdown": "^4.9.0", "typescript": "^5.9.3", + "verdaccio": "^6.2.4", "vite": "^6.4.1", "vitest": "3.1.2" }, From be2d7542e971d3371c93aaa712390d649bbca1e8 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Wed, 10 Dec 2025 11:36:25 +1030 Subject: [PATCH 21/24] MI-250: Switch to rolldown as rsbuild cannot handle the work --- .../version-plan-1764807248032.md | 4 +- packages/nx-cdk/README.md | 4 +- .../src/generators/helpers/configs/nxJson.ts | 13 ---- .../generators/helpers/configs/packageJson.ts | 4 +- .../preset/files/.gitignore.template | 2 +- .../preset/files/README.md.template | 18 +++--- .../files/rolldown.config.base.mjs.template | 46 ++++++++++++++ .../files/rsbuild.config.base.mjs.template | 62 ------------------- .../files/rolldown.config.mjs.template | 3 + .../service/files/rsbuild.config.mjs.template | 3 - 10 files changed, 65 insertions(+), 94 deletions(-) create mode 100644 packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template delete mode 100644 packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template create mode 100644 packages/nx-cdk/src/generators/service/files/rolldown.config.mjs.template delete mode 100644 packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template diff --git a/.nx/version-plans/version-plan-1764807248032.md b/.nx/version-plans/version-plan-1764807248032.md index 4c9f60d..7ab510d 100644 --- a/.nx/version-plans/version-plan-1764807248032.md +++ b/.nx/version-plans/version-plan-1764807248032.md @@ -7,7 +7,7 @@ This is the initial release of `@aligent/nx-cdk`, an Nx plugin for AWS CDK devel ### Preset Generator: - Initialize new AWS CDK projects with complete Nx workspace structure -- Creates root configuration files (ESLint, Prettier, RSBuild, Vitest, TypeScript) +- Creates root configuration files (ESLint, Prettier, Rolldown, Vitest, TypeScript) - Scaffolds CDK application with bin/main.ts entry point and service stacks - Configurable Node.js version support (default: 24.11.0) - Includes CDK configuration files (cdk.json, cdk.context.json) @@ -16,5 +16,5 @@ This is the initial release of `@aligent/nx-cdk`, an Nx plugin for AWS CDK devel - Create new CDK services within existing projects - Generates service structure in `services//` directory -- Includes build configuration (RSBuild), testing setup (Vitest), and linting (ESLint) +- Includes build configuration (Rolldown), testing setup (Vitest), and linting (ESLint) - Auto-registers stacks to main CDK application diff --git a/packages/nx-cdk/README.md b/packages/nx-cdk/README.md index 85d0c07..cca1970 100644 --- a/packages/nx-cdk/README.md +++ b/packages/nx-cdk/README.md @@ -28,7 +28,7 @@ The preset generator scaffolds: - **Root configuration files**: - `eslint.config.mjs` - ESLint configuration - `prettier.config.mjs` - Prettier configuration - - `rsbuild.config.base.mjs` - Base RSBuild configuration + - `rolldown.config.base.mjs` - Base Rolldown configuration - `vitest.config.base.mjs` - Base Vitest configuration - `vitest.global.setup.mjs` - Global Vitest setup - `tsconfig.json` - Root TypeScript configuration @@ -69,7 +69,7 @@ The service generator creates a new service in `services//` with: - `package.json` - Service-specific dependencies - `README.md` - Service documentation - `eslint.config.mjs` - ESLint configuration - - `rsbuild.config.mjs` - RSBuild configuration + - `rolldown.config.mjs` - Rolldown configuration - `vitest.config.mjs` - Vitest configuration - TypeScript configurations (`tsconfig.json`, `tsconfig.lib.json`, `tsconfig.spec.json`) diff --git a/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts index 2030369..8eb73fb 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts @@ -7,19 +7,6 @@ export const NX_JSON: NxJsonConfiguration & { $schema: string } = { { plugin: '@nx/eslint/plugin', options: {} }, { plugin: '@nx/vite/plugin', options: {} }, { plugin: '@nx/js/typescript', options: { build: false } }, - { - plugin: '@nx/rsbuild', - options: { - buildTargetName: 'build:lambda', - devTargetName: 'dev:lambda', - inspectTargetName: 'inspect:lambda', - }, - // This plugin configuration is only for bundling lambda code in services - // The `**` glob is required to include all services - include: ['services/**'], - // Services with no lambda handlers should be excluded from here - exclude: [], - }, ], namedInputs: { default: ['{projectRoot}/**/*', 'sharedGlobals'], diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 0b143bc..78b3f0d 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -26,9 +26,7 @@ export const PACKAGE_JSON = { '@nx/eslint': '22.1.3', '@nx/eslint-plugin': '22.1.3', '@nx/js': '22.1.3', - '@nx/rsbuild': '22.1.3', '@nx/vite': '22.1.3', - '@rsbuild/core': '^1.5.6', '@swc-node/register': '^1.10.10', '@swc/core': '^1.13.3', '@swc/helpers': '^0.5.17', @@ -50,6 +48,8 @@ export const PACKAGE_JSON = { 'jsonc-eslint-parser': '^2.4.0', nx: '22.1.3', prettier: '^3.6.2', + // FIXME: Rolldown is still in beta. We pin the version and can upgrade with precaution. + rolldown: '1.0.0-beta.53', 'store-parameters': '^1.1.3', tslib: '^2.8.1', tsx: '^4.21.0', diff --git a/packages/nx-cdk/src/generators/preset/files/.gitignore.template b/packages/nx-cdk/src/generators/preset/files/.gitignore.template index 8a0784f..f4350b8 100644 --- a/packages/nx-cdk/src/generators/preset/files/.gitignore.template +++ b/packages/nx-cdk/src/generators/preset/files/.gitignore.template @@ -19,7 +19,7 @@ !nx.json !package.json !prettier.config.mjs -!rsbuild.config.base.mjs +!rolldown.config.base.mjs !tsconfig.json !vitest.global.setup.mjs !vitest.config.base.mjs diff --git a/packages/nx-cdk/src/generators/preset/files/README.md.template b/packages/nx-cdk/src/generators/preset/files/README.md.template index f780194..fb145b3 100644 --- a/packages/nx-cdk/src/generators/preset/files/README.md.template +++ b/packages/nx-cdk/src/generators/preset/files/README.md.template @@ -17,17 +17,17 @@ Services deployment are managed by the main [CDK Application](./application/READ ``` <%= folderName %>/ -ā”œā”€ā”€ application/ # CDK Application & orchestration -│ ā”œā”€ā”€ bin/main.ts # CDK App entry point (development/staging/production stages) -│ ā”œā”€ā”€ lib/ # Service stack composition -│ └── cdk.json # CDK configuration +ā”œā”€ā”€ application/ # CDK Application & orchestration +│ ā”œā”€ā”€ bin/main.ts # CDK App entry point (development/staging/production stages) +│ ā”œā”€ā”€ lib/ # Service stack composition +│ └── cdk.json # CDK configuration │ -ā”œā”€ā”€ services/ # Microservices workspace +ā”œā”€ā”€ services/ # Microservices workspace │ -ā”œā”€ā”€ nx.json # Nx monorepo configuration -ā”œā”€ā”€ rsbuild.config.base.mjs # Base Lambda bundling config -ā”œā”€ā”€ vitest.config.base.mjs # Base test configuration -└── eslint.config.mjs # ESLint configuration +ā”œā”€ā”€ nx.json # Nx monorepo configuration +ā”œā”€ā”€ rolldown.config.base.mjs # Base Lambda bundling config +ā”œā”€ā”€ vitest.config.base.mjs # Base test configuration +└── eslint.config.mjs # ESLint configuration ``` ## Getting Started diff --git a/packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template b/packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template new file mode 100644 index 0000000..459f744 --- /dev/null +++ b/packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template @@ -0,0 +1,46 @@ +import fg from 'fast-glob'; +import { builtinModules } from 'node:module'; +import { extname, resolve } from 'node:path'; +import { defineConfig } from 'rolldown'; + +/** + * Prepare Rolldown config that bundles all typescript files in a single directory in to separate files + * This is used to bundle lambda handlers with their own dependencies for separate upload to AWS Lambda + * + * @param {string} subPath Relative path to the handlers directory + * @returns Rolldown config for multiple lambda handlers + */ +export function defineLambdaConfig(subPath) { + if (subPath.includes('..')) throw new Error('Invalid path provided'); + const handlersPath = resolve(process.cwd(), subPath); + const handlers = fg.sync(`${handlersPath}/**/*.ts`); + + return handlers.map(handler => { + const bundledPath = handler.replace(`${handlersPath}/`, ''); + const entryName = bundledPath.replace(extname(bundledPath), ''); + + return defineConfig({ + input: { [entryName]: handler }, + platform: 'node', + tsconfig: 'tsconfig.lib.json', + logLevel: 'info', + watch: false, + external: [...builtinModules], + output: { + entryFileNames: '[name]/index.mjs', + format: 'esm', + // TODO: Support sourcemap enable/disable base on environment + sourcemap: true, + // FIXME: Rolldown is still in Beta and built-in minification is not production ready yet + minify: false, + legalComments: 'none', + inlineDynamicImports: true, + // TODO: Support shims only when needed instead consider looking at tsup, tsdown and rollup shims plugins + banner: `import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename);`, + }, + }); + }); +} diff --git a/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template b/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template deleted file mode 100644 index 49af6d9..0000000 --- a/packages/nx-cdk/src/generators/preset/files/rsbuild.config.base.mjs.template +++ /dev/null @@ -1,62 +0,0 @@ -import { defineConfig } from '@rsbuild/core'; -import fg from 'fast-glob'; -import { extname, resolve } from 'node:path'; - -const HANDLERS_PATH = 'src/runtime/handlers'; - -/** - * Prepare Rsbuild config that bundles all typescript files in a single directory in to separate files - * This is used to bundle lambda handlers with their own dependencies for separate upload to AWS Lambda - * - * @param {string} configPath Full path to the rsbuild.config.mjs file this is used in - usually import.meta.dirname; - * @param {string} subPath Relative path to the handlers directory. Default is 'src/runtime/handlers' - * @returns Rsbuild config for multiple lambda handlers - */ -export function defineLambdaConfig(configPath, subPath = HANDLERS_PATH) { - if (subPath.includes('..')) throw new Error('Invalid path provided'); - - const basePath = resolve(configPath, subPath); - const handlers = fg.sync(`${basePath}/**/*.ts`); - - // FIXME: We need a way to skip bundling instead of throwing error here - if (!handlers.length) { - throw new Error('Unable to find any handler'); - } - - // Format an entry object containing each file found in the folder - // Maintains subfolder structure. E.g. { 'test/log-object': 'test/log-object' } - const entry = Object.fromEntries( - handlers.map(handler => { - const bundledPath = handler.replace(`${basePath}/`, ''); - const entryName = bundledPath.replace(extname(bundledPath), ''); - return [entryName, handler]; - }) - ); - - return defineConfig({ - source: { entry, disableDefaultEntry: true, tsconfigPath: './tsconfig.lib.json' }, - performance: { - chunkSplit: { - // Not sure this is necessary for single-file-bundling but seems safer to set it - strategy: 'all-in-one', - }, - }, - output: { - target: 'node', - module: true, // Output ESM modules - filename: { js: '[name]/index.mjs' }, - legalComments: 'none', // Don't output license comments in bundled code - // FIXME: handle the following things by stag/environment - // sourceMap: true, - // minify: true, - }, - tools: { - rspack: { - // Forces bundler to include all dependencies in one file - output: { asyncChunks: false }, - // Prevent bundler from wrapping handlers in an IIFE - optimization: { avoidEntryIife: true }, - }, - }, - }); -} diff --git a/packages/nx-cdk/src/generators/service/files/rolldown.config.mjs.template b/packages/nx-cdk/src/generators/service/files/rolldown.config.mjs.template new file mode 100644 index 0000000..c76585c --- /dev/null +++ b/packages/nx-cdk/src/generators/service/files/rolldown.config.mjs.template @@ -0,0 +1,3 @@ +import { defineLambdaConfig } from '../../rolldown.config.base.mjs'; + +export default defineLambdaConfig('src/runtime/handlers'); diff --git a/packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template b/packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template deleted file mode 100644 index 0dafb4d..0000000 --- a/packages/nx-cdk/src/generators/service/files/rsbuild.config.mjs.template +++ /dev/null @@ -1,3 +0,0 @@ -import { defineLambdaConfig } from '../../rsbuild.config.base.mjs'; - -export default defineLambdaConfig(import.meta.dirname); From 3c09e2616a71f7f69a48a06700a3cf2527de8f80 Mon Sep 17 00:00:00 2001 From: KaiNguyen <108910975+kai-nguyen-aligent@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:09:03 +1030 Subject: [PATCH 22/24] Update packages/nx-cdk/src/generators/helpers/configs/packageJson.ts Co-authored-by: aligent-phil <85087316+aligent-phil@users.noreply.github.com> --- packages/nx-cdk/src/generators/helpers/configs/packageJson.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 78b3f0d..ff813cc 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -1,5 +1,5 @@ export const PACKAGE_JSON = { - author: 'Aligent Consulting', + author: 'Aligent', private: true, license: 'MIT', type: 'module', From 68e9b704476b258d3496dfa2672d779fe2c1c3aa Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Wed, 10 Dec 2025 15:19:54 +1030 Subject: [PATCH 23/24] MI-250: Add tickets to Todos --- .../nx-cdk/src/generators/helpers/configs/packageJson.ts | 2 +- .../preset/files/application/bin/main.ts.template | 2 +- .../preset/files/rolldown.config.base.mjs.template | 6 +++--- packages/nx-cdk/src/generators/preset/schema.d.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts index 78b3f0d..350abaa 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/packageJson.ts @@ -48,7 +48,7 @@ export const PACKAGE_JSON = { 'jsonc-eslint-parser': '^2.4.0', nx: '22.1.3', prettier: '^3.6.2', - // FIXME: Rolldown is still in beta. We pin the version and can upgrade with precaution. + // FIXME: [MI-251] Rolldown is still in beta. We pin the version and can upgrade with precaution. rolldown: '1.0.0-beta.53', 'store-parameters': '^1.1.3', tslib: '^2.8.1', diff --git a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template index a160afa..e42fea6 100644 --- a/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template +++ b/packages/nx-cdk/src/generators/preset/files/application/bin/main.ts.template @@ -3,7 +3,7 @@ import { App, Aspects, Tags } from 'aws-cdk-lib'; import { Runtime } from 'aws-cdk-lib/aws-lambda'; import { ApplicationStage } from '../lib/service-stacks.js'; -// TODO Pull this out to constructs repo so we can import and use later +// TODO [MI-277] Pull this out to constructs repo so we can import and use later import { LogGroupDefaultsInjector } from '../_internal/log-group-defaults-injector.js'; import { MicroserviceChecks } from '../_internal/microservice-checks.js'; import { NodeJsFunctionDefaultsInjector } from '../_internal/nodejs-function-defaults-injector.js'; diff --git a/packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template b/packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template index 459f744..725f4d4 100644 --- a/packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template +++ b/packages/nx-cdk/src/generators/preset/files/rolldown.config.base.mjs.template @@ -29,13 +29,13 @@ export function defineLambdaConfig(subPath) { output: { entryFileNames: '[name]/index.mjs', format: 'esm', - // TODO: Support sourcemap enable/disable base on environment + // TODO: [MI-251] Support sourcemap enable/disable base on environment sourcemap: true, - // FIXME: Rolldown is still in Beta and built-in minification is not production ready yet + // FIXME: [MI-251] Rolldown is still in Beta and built-in minification is not production ready yet minify: false, legalComments: 'none', inlineDynamicImports: true, - // TODO: Support shims only when needed instead consider looking at tsup, tsdown and rollup shims plugins + // TODO: [MI-251] Support shims only when needed instead consider looking at tsup, tsdown and rollup shims plugins banner: `import { fileURLToPath } from 'node:url'; import { dirname } from 'node:path'; const __filename = fileURLToPath(import.meta.url); diff --git a/packages/nx-cdk/src/generators/preset/schema.d.ts b/packages/nx-cdk/src/generators/preset/schema.d.ts index 8d9a0be..931bf3f 100644 --- a/packages/nx-cdk/src/generators/preset/schema.d.ts +++ b/packages/nx-cdk/src/generators/preset/schema.d.ts @@ -2,6 +2,6 @@ export interface PresetGeneratorSchema { name: string; nodeVersion: string; - // FIXME: Add this into schema.json once we move to our own cli tool + // FIXME: [MI-281] Add this into schema.json once we move to our own cli tool destination?: string; } From bdb9473ce94d135aaef58c9ecd1cbb0a3b996960 Mon Sep 17 00:00:00 2001 From: Kai Nguyen Date: Tue, 16 Dec 2025 14:13:15 +1100 Subject: [PATCH 24/24] MI-250: Update service package.json --- .../src/generators/service/files/package.json.template | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/nx-cdk/src/generators/service/files/package.json.template b/packages/nx-cdk/src/generators/service/files/package.json.template index 73e6940..e439c3d 100644 --- a/packages/nx-cdk/src/generators/service/files/package.json.template +++ b/packages/nx-cdk/src/generators/service/files/package.json.template @@ -15,6 +15,16 @@ "clients" ], "nx": { + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "rolldown -c rolldown.config.mjs", + "color": true, + "cwd": "{projectRoot}" + } + } + }, "tags": [ "scope:services" ]