@aligent/nx-cdk 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -6
- package/generators.json +5 -0
- package/package.json +1 -1
- package/src/generators/constants.d.ts +5 -0
- package/src/generators/constants.js +7 -0
- package/src/generators/helpers/configs/base-package/package.json +10 -27
- package/src/generators/helpers/configs/nxJson.js +7 -2
- package/src/generators/helpers/utilities.d.ts +21 -1
- package/src/generators/helpers/utilities.js +67 -1
- package/src/generators/preset/files/.gitignore.template +3 -3
- package/src/generators/preset/files/README.md.template +1 -21
- package/src/generators/preset/files/application/README.md.template +16 -6
- package/src/generators/preset/files/libs/infra/src/index.ts.template +3 -22
- package/src/generators/preset/files-example/libs/infra/src/index.ts.template +49 -0
- package/src/generators/preset/preset.js +9 -4
- package/src/generators/preset/schema.json +2 -1
- package/src/generators/remove-service/generator.d.ts +4 -0
- package/src/generators/remove-service/generator.js +38 -0
- package/src/generators/remove-service/schema.d.ts +4 -0
- package/src/generators/remove-service/schema.json +23 -0
- package/src/generators/service/files/src/index.ts.template +1 -3
- package/src/generators/service/files-example/src/index.ts.template +45 -0
- package/src/generators/service/files-example/src/infra/stepfunctions/example.yml.template +7 -0
- package/src/generators/service/files-example/src/runtime/handlers/example.ts.template +7 -0
- package/src/generators/service/generator.js +11 -7
- package/src/generators/service/schema.d.ts +1 -0
- package/src/generators/service/schema.json +6 -0
- package/src/generators/preset/files/.github/dependabot.yml.template +0 -7
- package/src/generators/preset/files/parameters/dev.csv.template +0 -2
package/README.md
CHANGED
|
@@ -59,13 +59,17 @@ The service generator creates a new CDK service within the `services/` folder of
|
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
61
|
yarn nx g @aligent/nx-cdk:service <service-name>
|
|
62
|
+
|
|
63
|
+
# Or simply (since the generator name is unique):
|
|
64
|
+
yarn nx g service <service-name>
|
|
62
65
|
```
|
|
63
66
|
|
|
64
67
|
#### Options
|
|
65
68
|
|
|
66
|
-
| Option
|
|
67
|
-
|
|
|
68
|
-
| `name`
|
|
69
|
+
| Option | Type | Required | Default | Description |
|
|
70
|
+
| --------- | ------- | -------- | ------- | ------------------------------------------------------------------------- |
|
|
71
|
+
| `name` | string | Yes | - | The name of the service (cannot contain 'Stack' or 'Service' in the name) |
|
|
72
|
+
| `example` | boolean | No | `false` | Generate example code with sample resources |
|
|
69
73
|
|
|
70
74
|
#### What it creates
|
|
71
75
|
|
|
@@ -89,11 +93,56 @@ The service generator creates a new service in `services/<service-name>/` with:
|
|
|
89
93
|
#### Example
|
|
90
94
|
|
|
91
95
|
```bash
|
|
92
|
-
# Create a new service named "user-management"
|
|
96
|
+
# Create a new service named "user-management" (short form)
|
|
97
|
+
yarn nx g service user-management
|
|
98
|
+
|
|
99
|
+
# Or with the full plugin prefix
|
|
93
100
|
yarn nx g @aligent/nx-cdk:service user-management
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Remove Service Generator
|
|
104
|
+
|
|
105
|
+
The remove-service generator cleanly removes a service and all of its references from the project. It reverses the changes made by the service generator, ensuring no dangling imports or references are left behind.
|
|
106
|
+
|
|
107
|
+
#### Usage
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
yarn nx g @aligent/nx-cdk:remove-service <service-name>
|
|
111
|
+
|
|
112
|
+
# Or simply (since the generator name is unique):
|
|
113
|
+
yarn nx g remove-service <service-name>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Options
|
|
117
|
+
|
|
118
|
+
| Option | Type | Required | Default | Description |
|
|
119
|
+
| ------------- | ------- | -------- | ------- | ----------------------------------------------- |
|
|
120
|
+
| `name` | string | Yes | - | The name of the service to remove |
|
|
121
|
+
| `forceRemove` | boolean | No | `false` | Skip dependency check when removing the project |
|
|
122
|
+
|
|
123
|
+
#### What it does
|
|
124
|
+
|
|
125
|
+
The remove generator performs the following cleanup:
|
|
126
|
+
|
|
127
|
+
- **Application updates**:
|
|
128
|
+
- Removes the service's import declaration from `application/lib/service-stacks.ts`
|
|
129
|
+
- Removes the stack instantiation from the `ApplicationStage` constructor
|
|
130
|
+
|
|
131
|
+
- **Root updates**:
|
|
132
|
+
- Removes the service from the root `tsconfig.json` references
|
|
133
|
+
- Removes the service from the root `package.json` workspaces (if present)
|
|
134
|
+
|
|
135
|
+
- **Service files**:
|
|
136
|
+
- Deletes the entire `services/<service-name>/` directory
|
|
137
|
+
|
|
138
|
+
#### Example
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Remove the "user-management" service (short form)
|
|
142
|
+
yarn nx g remove-service user-management
|
|
94
143
|
|
|
95
|
-
#
|
|
96
|
-
yarn nx g @aligent/nx-cdk:service
|
|
144
|
+
# Or with the full plugin prefix
|
|
145
|
+
yarn nx g @aligent/nx-cdk:remove-service user-management
|
|
97
146
|
```
|
|
98
147
|
|
|
99
148
|
## Project Structure
|
package/generators.json
CHANGED
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"factory": "./src/generators/service/generator",
|
|
11
11
|
"schema": "./src/generators/service/schema.json",
|
|
12
12
|
"description": "Generate a new service"
|
|
13
|
+
},
|
|
14
|
+
"remove-service": {
|
|
15
|
+
"factory": "./src/generators/remove-service/generator",
|
|
16
|
+
"schema": "./src/generators/remove-service/schema.json",
|
|
17
|
+
"description": "Remove a service and clean up its references"
|
|
13
18
|
}
|
|
14
19
|
}
|
|
15
20
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type ProjectType = 'application' | 'service';
|
|
2
|
+
export declare const MAIN_APPLICATION_FOLDER = "application";
|
|
3
|
+
export declare const MAIN_APPLICATION_NAME = "application";
|
|
4
|
+
export declare const SERVICES_FOLDER = "services";
|
|
5
|
+
export declare const SERVICES_SCOPE = "@services";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SERVICES_SCOPE = exports.SERVICES_FOLDER = exports.MAIN_APPLICATION_NAME = exports.MAIN_APPLICATION_FOLDER = void 0;
|
|
4
|
+
exports.MAIN_APPLICATION_FOLDER = 'application';
|
|
5
|
+
exports.MAIN_APPLICATION_NAME = 'application';
|
|
6
|
+
exports.SERVICES_FOLDER = 'services';
|
|
7
|
+
exports.SERVICES_SCOPE = '@services';
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
"@aligent/microservice-util-lib": "^1.2.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@aligent/cdk-aspects": "^0.5.
|
|
25
|
-
"@aligent/cdk-
|
|
26
|
-
"@aligent/
|
|
27
|
-
"@aligent/
|
|
24
|
+
"@aligent/cdk-aspects": "^0.5.5",
|
|
25
|
+
"@aligent/cdk-nodejs-function-from-entry": "^0.2.1",
|
|
26
|
+
"@aligent/cdk-step-function-from-file": "^0.5.1",
|
|
27
|
+
"@aligent/nx-openapi": "^2.1.1",
|
|
28
|
+
"@aligent/ts-code-standards": "^4.2.1",
|
|
28
29
|
"@nx/eslint": "22.1.3",
|
|
29
30
|
"@nx/eslint-plugin": "22.1.3",
|
|
30
31
|
"@nx/js": "22.1.3",
|
|
@@ -39,10 +40,10 @@
|
|
|
39
40
|
"@typescript-eslint/parser": "8.44.0",
|
|
40
41
|
"@vitest/coverage-v8": "^3.2.4",
|
|
41
42
|
"@vitest/ui": "^3.2.4",
|
|
42
|
-
"aws-cdk": "^2.
|
|
43
|
-
"aws-cdk-lib": "^2.
|
|
44
|
-
"cdk-nag": "^2.
|
|
45
|
-
"constructs": "^10.
|
|
43
|
+
"aws-cdk": "^2.1120.0",
|
|
44
|
+
"aws-cdk-lib": "^2.251.0",
|
|
45
|
+
"cdk-nag": "^2.38.2",
|
|
46
|
+
"constructs": "^10.6.0",
|
|
46
47
|
"eslint": "^9.32.0",
|
|
47
48
|
"eslint-config-prettier": "^10.1.8",
|
|
48
49
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -52,7 +53,6 @@
|
|
|
52
53
|
"nx": "22.1.3",
|
|
53
54
|
"prettier": "^3.6.2",
|
|
54
55
|
"rolldown": "1.0.0-rc.1",
|
|
55
|
-
"store-parameters": "^1.1.3",
|
|
56
56
|
"tslib": "^2.8.1",
|
|
57
57
|
"tsx": "^4.21.0",
|
|
58
58
|
"typescript": "~5.9.2",
|
|
@@ -60,24 +60,7 @@
|
|
|
60
60
|
"vitest": "^3.2.4"
|
|
61
61
|
},
|
|
62
62
|
"nx": {
|
|
63
|
-
"includedScripts": []
|
|
64
|
-
"targets": {
|
|
65
|
-
"parameters": {
|
|
66
|
-
"executor": "nx:run-commands",
|
|
67
|
-
"options": {
|
|
68
|
-
"color": true,
|
|
69
|
-
"cwd": "parameters"
|
|
70
|
-
},
|
|
71
|
-
"configurations": {
|
|
72
|
-
"import": {
|
|
73
|
-
"command": "store-parameters import {args.file} --delimiter=|"
|
|
74
|
-
},
|
|
75
|
-
"export": {
|
|
76
|
-
"command": "store-parameters export {args.file} --path={args.path} --delimiter=|"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
63
|
+
"includedScripts": []
|
|
81
64
|
},
|
|
82
65
|
"workspaces": [
|
|
83
66
|
"application",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NX_JSON = void 0;
|
|
4
|
+
const constants_1 = require("../../constants");
|
|
4
5
|
exports.NX_JSON = {
|
|
5
6
|
$schema: './node_modules/nx/schemas/nx-schema.json',
|
|
6
7
|
defaultBase: 'origin/staging',
|
|
@@ -37,7 +38,11 @@ exports.NX_JSON = {
|
|
|
37
38
|
configurations: { coverage: { coverage: true } },
|
|
38
39
|
},
|
|
39
40
|
typecheck: { cache: true, inputs: ['default', '^production'] },
|
|
40
|
-
cdk: {
|
|
41
|
-
|
|
41
|
+
cdk: {
|
|
42
|
+
dependsOn: [{ target: 'build', params: 'forward', projects: `${constants_1.SERVICES_SCOPE}/*` }],
|
|
43
|
+
},
|
|
44
|
+
pg: {
|
|
45
|
+
dependsOn: [{ target: 'build', params: 'forward', projects: `${constants_1.SERVICES_SCOPE}/*` }],
|
|
46
|
+
},
|
|
42
47
|
},
|
|
43
48
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Tree } from '@nx/devkit';
|
|
2
|
+
import { ProjectType } from '../constants';
|
|
2
3
|
interface PackageJsonInput {
|
|
3
4
|
name: string;
|
|
4
5
|
projectName: string;
|
|
@@ -20,7 +21,7 @@ export declare function constructPackageJsonFile(input: PackageJsonInput): {
|
|
|
20
21
|
node?: never;
|
|
21
22
|
};
|
|
22
23
|
};
|
|
23
|
-
export declare function constructProjectTsConfigFiles(type:
|
|
24
|
+
export declare function constructProjectTsConfigFiles(type: ProjectType): {
|
|
24
25
|
tsConfig: {
|
|
25
26
|
extends: string;
|
|
26
27
|
compilerOptions?: Record<string, unknown>;
|
|
@@ -61,6 +62,25 @@ export declare function getGeneratorVersion(): string;
|
|
|
61
62
|
* @throws {Error} If the ApplicationStage constructor cannot be found in service-stacks.ts
|
|
62
63
|
*/
|
|
63
64
|
export declare function addServiceStackToMainApplication(tree: Tree, service: Service, projectName: string): void;
|
|
65
|
+
/**
|
|
66
|
+
* Removes a service stack registration from the main CDK application's ApplicationStage.
|
|
67
|
+
*
|
|
68
|
+
* This function modifies the service-stacks.ts file by:
|
|
69
|
+
* 1. Removing import statements that reference the service's module specifier
|
|
70
|
+
* 2. Removing statements in the ApplicationStage constructor that reference the service's stack class
|
|
71
|
+
*
|
|
72
|
+
* @param tree - The Nx virtual file system tree
|
|
73
|
+
* @param serviceName - The name of the service (e.g., "companies")
|
|
74
|
+
* @param projectName - The name of the main application project
|
|
75
|
+
*/
|
|
76
|
+
export declare function removeServiceFromMainApplication(tree: Tree, serviceName: string, projectName: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* Removes a project reference from the root tsconfig.json.
|
|
79
|
+
*
|
|
80
|
+
* @param tree - The Nx virtual file system tree
|
|
81
|
+
* @param referencePath - The path to remove from the references array
|
|
82
|
+
*/
|
|
83
|
+
export declare function removeTsConfigReference(tree: Tree, referencePath: string): void;
|
|
64
84
|
/**
|
|
65
85
|
* Splits a kebab-case name into an array of capitalized parts.
|
|
66
86
|
*
|
|
@@ -4,11 +4,14 @@ exports.constructPackageJsonFile = constructPackageJsonFile;
|
|
|
4
4
|
exports.constructProjectTsConfigFiles = constructProjectTsConfigFiles;
|
|
5
5
|
exports.getGeneratorVersion = getGeneratorVersion;
|
|
6
6
|
exports.addServiceStackToMainApplication = addServiceStackToMainApplication;
|
|
7
|
+
exports.removeServiceFromMainApplication = removeServiceFromMainApplication;
|
|
8
|
+
exports.removeTsConfigReference = removeTsConfigReference;
|
|
7
9
|
exports.splitInputName = splitInputName;
|
|
8
10
|
/* v8 ignore start */
|
|
9
11
|
const devkit_1 = require("@nx/devkit");
|
|
10
12
|
const path_1 = require("path");
|
|
11
13
|
const ts_morph_1 = require("ts-morph");
|
|
14
|
+
const constants_1 = require("../constants");
|
|
12
15
|
const tsConfigs_1 = require("./configs/tsConfigs");
|
|
13
16
|
/**
|
|
14
17
|
* Reads the base package.json configuration from a JSON file.
|
|
@@ -101,7 +104,7 @@ function addServiceStackToMainApplication(tree, service, projectName) {
|
|
|
101
104
|
throw new Error('Unable to find main application stage constructor');
|
|
102
105
|
}
|
|
103
106
|
stackSource.addImportDeclaration({
|
|
104
|
-
moduleSpecifier:
|
|
107
|
+
moduleSpecifier: `${constants_1.SERVICES_SCOPE}/${service.name}`,
|
|
105
108
|
namedImports: [service.constant, service.stack],
|
|
106
109
|
});
|
|
107
110
|
const sharedInfra = stageConstructor.getVariableStatement('sharedInfra');
|
|
@@ -109,6 +112,69 @@ function addServiceStackToMainApplication(tree, service, projectName) {
|
|
|
109
112
|
stageConstructor.addStatements(`new ${service.stack}(this, ${service.constant}.NAME, { ...props, ${sharedPropsStatement} description: ${service.constant}.DESCRIPTION });`);
|
|
110
113
|
tree.write(stacksRelativePath, stackSource.getFullText());
|
|
111
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Removes a service stack registration from the main CDK application's ApplicationStage.
|
|
117
|
+
*
|
|
118
|
+
* This function modifies the service-stacks.ts file by:
|
|
119
|
+
* 1. Removing import statements that reference the service's module specifier
|
|
120
|
+
* 2. Removing statements in the ApplicationStage constructor that reference the service's stack class
|
|
121
|
+
*
|
|
122
|
+
* @param tree - The Nx virtual file system tree
|
|
123
|
+
* @param serviceName - The name of the service (e.g., "companies")
|
|
124
|
+
* @param projectName - The name of the main application project
|
|
125
|
+
*/
|
|
126
|
+
function removeServiceFromMainApplication(tree, serviceName, projectName) {
|
|
127
|
+
const application = (0, devkit_1.readProjectConfiguration)(tree, projectName);
|
|
128
|
+
if (application.root.includes('..')) {
|
|
129
|
+
throw new Error('Invalid application root path');
|
|
130
|
+
}
|
|
131
|
+
const stacksRelativePath = (0, path_1.join)(application.root, 'lib/service-stacks.ts');
|
|
132
|
+
if (!tree.exists(stacksRelativePath)) {
|
|
133
|
+
console.log('Service Stacks does not exist, skipping service stacks cleanup.');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const content = tree.read(stacksRelativePath, 'utf-8');
|
|
137
|
+
if (content === null) {
|
|
138
|
+
throw new Error(`Failed to read file: ${stacksRelativePath}`);
|
|
139
|
+
}
|
|
140
|
+
const fs = new ts_morph_1.InMemoryFileSystemHost();
|
|
141
|
+
fs.writeFileSync(stacksRelativePath, content);
|
|
142
|
+
const project = new ts_morph_1.Project({ fileSystem: fs });
|
|
143
|
+
const stackSource = project.addSourceFileAtPath(stacksRelativePath);
|
|
144
|
+
const imports = stackSource.getImportDeclarations();
|
|
145
|
+
for (const importDecl of imports) {
|
|
146
|
+
if (importDecl.getModuleSpecifierValue() === `${constants_1.SERVICES_SCOPE}/${serviceName}`) {
|
|
147
|
+
importDecl.remove();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const nameParts = splitInputName(serviceName);
|
|
151
|
+
const stackClassName = `${nameParts.join('')}Stack`;
|
|
152
|
+
const applicationStage = stackSource.getClass('ApplicationStage');
|
|
153
|
+
if (applicationStage) {
|
|
154
|
+
const stageConstructor = applicationStage.getConstructors()[0];
|
|
155
|
+
if (stageConstructor) {
|
|
156
|
+
const statements = stageConstructor.getStatements();
|
|
157
|
+
for (const statement of statements) {
|
|
158
|
+
if (statement.getText().includes(`new ${stackClassName}(`)) {
|
|
159
|
+
statement.remove();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
tree.write(stacksRelativePath, stackSource.getFullText());
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Removes a project reference from the root tsconfig.json.
|
|
168
|
+
*
|
|
169
|
+
* @param tree - The Nx virtual file system tree
|
|
170
|
+
* @param referencePath - The path to remove from the references array
|
|
171
|
+
*/
|
|
172
|
+
function removeTsConfigReference(tree, referencePath) {
|
|
173
|
+
(0, devkit_1.updateJson)(tree, 'tsconfig.json', json => {
|
|
174
|
+
json.references = (json.references ?? []).filter((r) => r.path !== referencePath);
|
|
175
|
+
return json;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
112
178
|
/**
|
|
113
179
|
* Splits a kebab-case name into an array of capitalized parts.
|
|
114
180
|
*
|
|
@@ -43,15 +43,15 @@
|
|
|
43
43
|
!collection
|
|
44
44
|
!collection/*
|
|
45
45
|
!collection/**/*
|
|
46
|
+
!clients
|
|
47
|
+
!clients/*
|
|
48
|
+
!clients/**/*
|
|
46
49
|
!docs
|
|
47
50
|
!docs/*
|
|
48
51
|
!docs/**/*
|
|
49
52
|
!libs
|
|
50
53
|
!libs/*
|
|
51
54
|
!libs/**/*
|
|
52
|
-
!parameters
|
|
53
|
-
!parameters/*
|
|
54
|
-
!parameters/**/*
|
|
55
55
|
!services
|
|
56
56
|
!services/*
|
|
57
57
|
!services/**/*
|
|
@@ -53,15 +53,6 @@ yarn install
|
|
|
53
53
|
Before committing this repository, review and update the following generated defaults:
|
|
54
54
|
|
|
55
55
|
- **`.github/CODEOWNERS`** — The default file references Aligent's GitHub teams (`@aligent/microservices`, `@aligent/devops`). Replace these with your own organisation's team handles.
|
|
56
|
-
- **`package.json` `pg:*` scripts** — The playground scripts use `--profile playground`. Ensure you have a matching profile in your `~/.aws/config` file:
|
|
57
|
-
|
|
58
|
-
```ini
|
|
59
|
-
[profile playground]
|
|
60
|
-
source_profile = default
|
|
61
|
-
role_arn = arn:aws:iam::11111111111:role/RoleName
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
If your profile has a different name, update the `pg:*` scripts in the root `package.json` to match.
|
|
65
56
|
|
|
66
57
|
### Deployment
|
|
67
58
|
|
|
@@ -89,18 +80,7 @@ To add a new service to the monorepo:
|
|
|
89
80
|
- `services/{service-name}/src/index.ts`
|
|
90
81
|
- `services/{service-name}/src/infra/`
|
|
91
82
|
3. Add Lambda handlers in `services/{service-name}/src/runtime/handlers/`
|
|
92
|
-
|
|
93
|
-
## Environment Parameters Management
|
|
94
|
-
|
|
95
|
-
Parameters are managed through the `parameters/{env}.csv` file by default
|
|
96
|
-
|
|
97
|
-
```bash
|
|
98
|
-
# Import values from `parameters/{env}.csv` to Parameter Store in AWS
|
|
99
|
-
yarn nx run <%= name %>-int:parameters:import --file=dev.csv
|
|
100
|
-
|
|
101
|
-
# Custom filename and parameter path can be passed in as arguments
|
|
102
|
-
yarn nx run <%= name %>-int:parameters:export --file=dev.csv --path=/my/dev/path
|
|
103
|
-
```
|
|
83
|
+
4. Run `yarn install` again so Yarn Workspace get synced.
|
|
104
84
|
|
|
105
85
|
## License
|
|
106
86
|
|
|
@@ -6,11 +6,21 @@ This application manages the deployment of microservices and their shared infras
|
|
|
6
6
|
|
|
7
7
|
### Using yarn script from workspace root (Recommended)
|
|
8
8
|
|
|
9
|
+
**The `pg:*` scripts** — The playground scripts use `--profile playground`. Ensure you have a matching profile in your `~/.aws/config` file:
|
|
10
|
+
|
|
11
|
+
```ini
|
|
12
|
+
[profile playground]
|
|
13
|
+
source_profile = default
|
|
14
|
+
role_arn = arn:aws:iam::11111111111:role/RoleName
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
If your profile has a different name, update the `pg:*` scripts in the root `package.json` to match.
|
|
18
|
+
|
|
9
19
|
##### Synthesize
|
|
10
20
|
|
|
11
21
|
```bash
|
|
12
22
|
# Synthesize for default environment/stage (dev)
|
|
13
|
-
yarn pg:synth
|
|
23
|
+
yarn pg:synth --args="dev/**"
|
|
14
24
|
|
|
15
25
|
# Synthesize for a custom environment/stage
|
|
16
26
|
yarn pg:synth --args="plg/** -c environment=plg"
|
|
@@ -20,7 +30,7 @@ yarn pg:synth --args="plg/** -c environment=plg"
|
|
|
20
30
|
|
|
21
31
|
```bash
|
|
22
32
|
# Deploy for default environment/stage (dev)
|
|
23
|
-
yarn pg:deploy
|
|
33
|
+
yarn pg:deploy --args="dev/**"
|
|
24
34
|
|
|
25
35
|
# Deploy to a custom environment/stage
|
|
26
36
|
yarn pg:deploy --args="plg/** -c environment=plg"
|
|
@@ -30,20 +40,20 @@ yarn pg:deploy --args="plg/** -c environment=plg"
|
|
|
30
40
|
|
|
31
41
|
```bash
|
|
32
42
|
# Diff checking for default environment/stage (dev)
|
|
33
|
-
yarn pg:diff
|
|
43
|
+
yarn pg:diff --args="dev/**"
|
|
34
44
|
|
|
35
45
|
# Diff checking for a custom environment/stage
|
|
36
|
-
yarn pg:diff --args="-c environment=plg"
|
|
46
|
+
yarn pg:diff --args="plg/** -c environment=plg"
|
|
37
47
|
```
|
|
38
48
|
|
|
39
49
|
##### Destroy
|
|
40
50
|
|
|
41
51
|
```bash
|
|
42
52
|
# Destroy default environment/stage (dev)
|
|
43
|
-
yarn pg:destroy
|
|
53
|
+
yarn pg:destroy --args="dev/**"
|
|
44
54
|
|
|
45
55
|
# Destroy a custom environment/stage
|
|
46
|
-
yarn pg:destroy --args="-c environment=plg"
|
|
56
|
+
yarn pg:destroy --args="plg/** -c environment=plg"
|
|
47
57
|
```
|
|
48
58
|
|
|
49
59
|
### Direct Nx Commands
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { Stack, Stage, StackProps, Tags } from 'aws-cdk-lib';
|
|
2
2
|
import { Construct } from 'constructs';
|
|
3
|
-
<% if (example) { %>import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
|
|
4
|
-
import { IStringParameter, StringParameter } from 'aws-cdk-lib/aws-ssm';<% } %>
|
|
5
3
|
|
|
6
4
|
export interface SharedInfraProps {
|
|
7
|
-
|
|
8
|
-
secretExample: Secret;<% } %>
|
|
5
|
+
// TODO: Add shared infrastructure properties (e.g. SSM parameters, secrets)
|
|
9
6
|
}
|
|
10
7
|
|
|
11
8
|
export class SharedInfraStack extends Stack {
|
|
12
|
-
|
|
13
|
-
readonly secretExample: Secret;<% } %>
|
|
9
|
+
// TODO: Add readonly properties for shared resources
|
|
14
10
|
|
|
15
11
|
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
16
12
|
super(scope, id, props);
|
|
@@ -20,24 +16,9 @@ export class SharedInfraStack extends Stack {
|
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
Tags.of(this).add('SERVICE', id);
|
|
23
|
-
<% if (example) { %>
|
|
24
|
-
this.paramExample = StringParameter.fromStringParameterName(
|
|
25
|
-
this,
|
|
26
|
-
'ParamExample',
|
|
27
|
-
`/example/param`
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
this.secretExample = new Secret(this, 'SecretExample', {
|
|
31
|
-
description: 'Example secret shared across services',
|
|
32
|
-
});
|
|
33
|
-
<% } %>
|
|
34
19
|
}
|
|
35
20
|
|
|
36
21
|
getProps(): SharedInfraProps {
|
|
37
|
-
return {
|
|
38
|
-
<% if (example) { %>paramExample: this.paramExample,
|
|
39
|
-
secretExample: this.secretExample,
|
|
40
|
-
<% } %>
|
|
41
|
-
};
|
|
22
|
+
return {};
|
|
42
23
|
}
|
|
43
24
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Stack, Stage, StackProps, Tags } from 'aws-cdk-lib';
|
|
2
|
+
import { Construct } from 'constructs';
|
|
3
|
+
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
|
|
4
|
+
import { IStringParameter, StringParameter } from 'aws-cdk-lib/aws-ssm';
|
|
5
|
+
|
|
6
|
+
export interface SharedInfraProps {
|
|
7
|
+
paramExample: IStringParameter;
|
|
8
|
+
secretExample: Secret;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class SharedInfraStack extends Stack {
|
|
12
|
+
readonly paramExample: IStringParameter;
|
|
13
|
+
readonly secretExample: Secret;
|
|
14
|
+
|
|
15
|
+
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
16
|
+
super(scope, id, props);
|
|
17
|
+
|
|
18
|
+
if (!Stage.of(this)?.stageName) {
|
|
19
|
+
throw new Error('This construct must be used within a CDK Stage');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Tags.of(this).add('SERVICE', id);
|
|
23
|
+
|
|
24
|
+
this.paramExample = new StringParameter(this,'ParamExample',
|
|
25
|
+
{
|
|
26
|
+
parameterName: `/example/param`,
|
|
27
|
+
stringValue: 'example-value'
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
this.secretExample = new Secret(this, 'SecretExample', {
|
|
32
|
+
description: 'Example secret shared across services',
|
|
33
|
+
generateSecretString: {
|
|
34
|
+
secretStringTemplate: JSON.stringify({
|
|
35
|
+
username: 'placeholder',
|
|
36
|
+
password: 'placeholder',
|
|
37
|
+
}),
|
|
38
|
+
generateStringKey: '_generatedKey',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getProps(): SharedInfraProps {
|
|
44
|
+
return {
|
|
45
|
+
paramExample: this.paramExample,
|
|
46
|
+
secretExample: this.secretExample,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.presetGenerator = presetGenerator;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
+
const constants_1 = require("../constants");
|
|
6
7
|
const nxJson_1 = require("../helpers/configs/nxJson");
|
|
7
8
|
const utilities_1 = require("../helpers/utilities");
|
|
8
9
|
async function presetGenerator(tree, options) {
|
|
@@ -10,13 +11,17 @@ async function presetGenerator(tree, options) {
|
|
|
10
11
|
const [nodeVersionMajor] = nodeVersion.split('.');
|
|
11
12
|
const nameParts = (0, utilities_1.splitInputName)(name);
|
|
12
13
|
const projectName = nameParts.join(' ');
|
|
13
|
-
|
|
14
|
+
const templateVars = {
|
|
14
15
|
...options,
|
|
15
16
|
projectName,
|
|
16
17
|
folderName: destination || name,
|
|
17
18
|
nodeRuntime: `${nodeVersionMajor}_X`,
|
|
18
19
|
template: '',
|
|
19
|
-
}
|
|
20
|
+
};
|
|
21
|
+
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), '.', templateVars);
|
|
22
|
+
if (options.example) {
|
|
23
|
+
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files-example'), '.', templateVars);
|
|
24
|
+
}
|
|
20
25
|
(0, devkit_1.updateNxJson)(tree, { ...nxJson_1.NX_JSON });
|
|
21
26
|
const packageJson = (0, utilities_1.constructPackageJsonFile)({
|
|
22
27
|
name: options.name,
|
|
@@ -26,8 +31,8 @@ async function presetGenerator(tree, options) {
|
|
|
26
31
|
});
|
|
27
32
|
(0, devkit_1.writeJson)(tree, 'package.json', packageJson);
|
|
28
33
|
// Generate application's tsconfigs
|
|
29
|
-
const { tsConfig } = (0, utilities_1.constructProjectTsConfigFiles)(
|
|
30
|
-
(0, devkit_1.writeJson)(tree,
|
|
34
|
+
const { tsConfig } = (0, utilities_1.constructProjectTsConfigFiles)(constants_1.MAIN_APPLICATION_NAME);
|
|
35
|
+
(0, devkit_1.writeJson)(tree, `${constants_1.MAIN_APPLICATION_FOLDER}/tsconfig.json`, tsConfig);
|
|
31
36
|
await (0, devkit_1.formatFiles)(tree);
|
|
32
37
|
}
|
|
33
38
|
exports.default = presetGenerator;
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"example": {
|
|
37
37
|
"type": "boolean",
|
|
38
38
|
"description": "Generate example code with sample resources",
|
|
39
|
-
"default": false
|
|
39
|
+
"default": false,
|
|
40
|
+
"x-prompt": "Would you like to generate example code with sample resources?"
|
|
40
41
|
}
|
|
41
42
|
},
|
|
42
43
|
"required": ["name"]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeGenerator = removeGenerator;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const utilities_1 = require("../helpers/utilities");
|
|
7
|
+
async function removeGenerator(tree, options) {
|
|
8
|
+
const { name, forceRemove } = options;
|
|
9
|
+
const projectRoot = `${constants_1.SERVICES_FOLDER}/${name}`;
|
|
10
|
+
const projectName = `${constants_1.SERVICES_SCOPE}/${name}`;
|
|
11
|
+
if (!tree.exists(projectRoot)) {
|
|
12
|
+
throw new Error(`Service "${name}" does not exist at "${projectRoot}".`);
|
|
13
|
+
}
|
|
14
|
+
if (!forceRemove) {
|
|
15
|
+
const graph = await (0, devkit_1.createProjectGraphAsync)();
|
|
16
|
+
const dependents = Object.entries(graph.dependencies)
|
|
17
|
+
.filter(([source]) => source !== projectName)
|
|
18
|
+
.filter(([, deps]) => deps.some(d => d.target === projectName))
|
|
19
|
+
.map(([source]) => source);
|
|
20
|
+
if (dependents.length > 0) {
|
|
21
|
+
throw new Error(`Cannot remove "${name}": it is depended on by ${dependents.join(', ')}. ` +
|
|
22
|
+
'Use --forceRemove to skip this check.');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
(0, utilities_1.removeServiceFromMainApplication)(tree, name, constants_1.MAIN_APPLICATION_NAME);
|
|
26
|
+
(0, utilities_1.removeTsConfigReference)(tree, `./${projectRoot}`);
|
|
27
|
+
tree.delete(projectRoot);
|
|
28
|
+
if (tree.exists('package.json')) {
|
|
29
|
+
(0, devkit_1.updateJson)(tree, 'package.json', json => {
|
|
30
|
+
if (Array.isArray(json.workspaces)) {
|
|
31
|
+
json.workspaces = json.workspaces.filter((w) => w !== projectRoot);
|
|
32
|
+
}
|
|
33
|
+
return json;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
37
|
+
}
|
|
38
|
+
exports.default = removeGenerator;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "RemoveServiceGenerator",
|
|
4
|
+
"title": "Remove a service and clean up its references",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The name of the service to remove",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
},
|
|
14
|
+
"x-prompt": "What is the name of the service to remove?"
|
|
15
|
+
},
|
|
16
|
+
"forceRemove": {
|
|
17
|
+
"type": "boolean",
|
|
18
|
+
"description": "Skip dependency check when removing the project",
|
|
19
|
+
"default": false
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"required": ["name"]
|
|
23
|
+
}
|
|
@@ -20,8 +20,6 @@ interface Props extends StackProps, SharedInfraProps {
|
|
|
20
20
|
/**
|
|
21
21
|
* Entrypoint for the <%= name %> service
|
|
22
22
|
*
|
|
23
|
-
* Instantiate in a CDK Application Stage to deploy to AWS.
|
|
24
|
-
*
|
|
25
23
|
* @note Aligent provides the following standard CDK constructs:
|
|
26
24
|
* - {@link NodejsFunctionFromEntry} from '@aligent/cdk-nodejs-function-from-entry'
|
|
27
25
|
* - {@link StepFunctionFromFile} from '@aligent/cdk-step-function-from-file'
|
|
@@ -34,7 +32,7 @@ interface Props extends StackProps, SharedInfraProps {
|
|
|
34
32
|
*
|
|
35
33
|
* new StepFunctionFromFile(this, 'ExampleStepFunction', {
|
|
36
34
|
* baseDir: import.meta.dirname,
|
|
37
|
-
* filepath: 'infra/stepfunctions/example.
|
|
35
|
+
* filepath: 'infra/stepfunctions/example.yml',
|
|
38
36
|
* });
|
|
39
37
|
*/
|
|
40
38
|
export class <%= stack %> extends Stack {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { SharedInfraProps } from '@libs/infra';
|
|
2
|
+
import { Stack, StackProps, Stage, Tags } from 'aws-cdk-lib';
|
|
3
|
+
import { Construct } from 'constructs';
|
|
4
|
+
import { NodejsFunctionFromEntry } from '@aligent/cdk-nodejs-function-from-entry';
|
|
5
|
+
import { StepFunctionFromFile } from '@aligent/cdk-step-function-from-file';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @important
|
|
9
|
+
* Due to the immutable nature of CloudFormation,
|
|
10
|
+
* CDK will generate new CloudFormation template and deploy if you change stack name
|
|
11
|
+
*/
|
|
12
|
+
export const <%= constant %> = {
|
|
13
|
+
NAME: '<%= name %>',
|
|
14
|
+
DESCRIPTION: '<%= name %> service description'
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
type Id = typeof <%= constant %>.NAME | (string & {});
|
|
18
|
+
interface Props extends StackProps, SharedInfraProps {
|
|
19
|
+
description: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Entrypoint for the <%= name %> service
|
|
24
|
+
*/
|
|
25
|
+
export class <%= stack %> extends Stack {
|
|
26
|
+
constructor(scope: Construct, id: Id, props: Props) {
|
|
27
|
+
super(scope, id, props);
|
|
28
|
+
|
|
29
|
+
if (!Stage.of(this)?.stageName) {
|
|
30
|
+
throw new Error('This construct must be used within a CDK Stage');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Tags.of(this).add('SERVICE', id);
|
|
34
|
+
|
|
35
|
+
new NodejsFunctionFromEntry(this, 'ExampleLambda', {
|
|
36
|
+
baseDir: import.meta.dirname,
|
|
37
|
+
entry: 'runtime/handlers/example.ts',
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
new StepFunctionFromFile(this, 'ExampleStepFunction', {
|
|
41
|
+
baseDir: import.meta.dirname,
|
|
42
|
+
filepath: 'infra/stepfunctions/example.yml',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.serviceGenerator = serviceGenerator;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
+
const constants_1 = require("../constants");
|
|
6
7
|
const utilities_1 = require("../helpers/utilities");
|
|
7
|
-
const SERVICES_FOLDER = 'services';
|
|
8
8
|
function addTsConfigReference(tree, referencePath) {
|
|
9
9
|
(0, devkit_1.updateJson)(tree, 'tsconfig.json', json => {
|
|
10
10
|
json.references ??= [];
|
|
@@ -16,20 +16,24 @@ function addTsConfigReference(tree, referencePath) {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
async function serviceGenerator(tree, options) {
|
|
19
|
-
const projectRoot = `${SERVICES_FOLDER}/${options.name}`;
|
|
19
|
+
const projectRoot = `${constants_1.SERVICES_FOLDER}/${options.name}`;
|
|
20
20
|
const nameParts = (0, utilities_1.splitInputName)(options.name);
|
|
21
21
|
const constant = nameParts.map(name => name.toUpperCase()).join('_');
|
|
22
22
|
const stack = `${nameParts.join('')}Stack`;
|
|
23
|
-
if (!tree.exists(SERVICES_FOLDER)) {
|
|
24
|
-
tree.write(`${SERVICES_FOLDER}/.gitkeep`, '');
|
|
23
|
+
if (!tree.exists(constants_1.SERVICES_FOLDER)) {
|
|
24
|
+
tree.write(`${constants_1.SERVICES_FOLDER}/.gitkeep`, '');
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
const templateVars = {
|
|
27
27
|
...options,
|
|
28
28
|
serviceName: nameParts.join(' '),
|
|
29
29
|
constant,
|
|
30
30
|
stack,
|
|
31
31
|
template: '',
|
|
32
|
-
}
|
|
32
|
+
};
|
|
33
|
+
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files'), projectRoot, templateVars);
|
|
34
|
+
if (options.example) {
|
|
35
|
+
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, 'files-example'), projectRoot, templateVars);
|
|
36
|
+
}
|
|
33
37
|
// Generate service's tsconfigs
|
|
34
38
|
const { tsConfig, tsConfigLib, tsConfigSpec } = (0, utilities_1.constructProjectTsConfigFiles)('service');
|
|
35
39
|
(0, devkit_1.writeJson)(tree, `${projectRoot}/tsconfig.json`, tsConfig);
|
|
@@ -37,7 +41,7 @@ async function serviceGenerator(tree, options) {
|
|
|
37
41
|
(0, devkit_1.writeJson)(tree, `${projectRoot}/tsconfig.spec.json`, tsConfigSpec);
|
|
38
42
|
// Integrate the new service with the root application
|
|
39
43
|
addTsConfigReference(tree, `./${projectRoot}`);
|
|
40
|
-
(0, utilities_1.addServiceStackToMainApplication)(tree, { name: options.name, constant, stack },
|
|
44
|
+
(0, utilities_1.addServiceStackToMainApplication)(tree, { name: options.name, constant, stack }, constants_1.MAIN_APPLICATION_NAME);
|
|
41
45
|
await (0, devkit_1.formatFiles)(tree);
|
|
42
46
|
}
|
|
43
47
|
exports.default = serviceGenerator;
|
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
"x-prompt": "What is the name of the service?",
|
|
15
15
|
"pattern": "^(?!.*[Ss]tack|.*[Ss]ervice).*$",
|
|
16
16
|
"patternErrorMessage": "Service name cannot contain '[Ss]tack' or '[Ss]ervice'"
|
|
17
|
+
},
|
|
18
|
+
"example": {
|
|
19
|
+
"type": "boolean",
|
|
20
|
+
"description": "Generate example code with sample resources",
|
|
21
|
+
"default": false,
|
|
22
|
+
"x-prompt": "Would you like to generate example code with sample resources?"
|
|
17
23
|
}
|
|
18
24
|
},
|
|
19
25
|
"required": ["name"]
|