diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ada9969..65cb261 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -21,7 +21,7 @@ updates: interval: 'monthly' open-pull-requests-limit: 5 commit-message: - prefix: 'TEMPLATE-UPDATE' + prefix: 'NX-CDK-TEMPLATE' groups: minor-and-patch: applies-to: version-updates @@ -35,7 +35,7 @@ updates: interval: 'monthly' open-pull-requests-limit: 5 commit-message: - prefix: 'TEMPLATE-UPDATE' + prefix: 'NX-APPBUILDER-TEMPLATE' groups: minor-and-patch: applies-to: version-updates diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5fa9803..9892c0a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,5 +44,5 @@ jobs: - name: 🚀 Publish versioned packages env: PUBLISH_OPTIONS: ${{ inputs.publish-options }} - run: npx nx release publish --verbose $PUBLISH_OPTIONS + run: npx nx release publish --verbose --access public $PUBLISH_OPTIONS shell: bash diff --git a/.nx/version-plans/version-plan-1777693034146.md b/.nx/version-plans/version-plan-1777693034146.md new file mode 100644 index 0000000..da74e37 --- /dev/null +++ b/.nx/version-plans/version-plan-1777693034146.md @@ -0,0 +1,16 @@ +--- +nx-cdk: minor +--- + +### New: remove-service generator + +- Added a new generator to remove services from an NX CDK workspace. + +### Improved: service generator + +- Extracted shared constants (`SERVICES_FOLDER`, `MAIN_APPLICATION_NAME`) into a dedicated constants module. + +### Infra: + +- Added `--access public` flag to the nx release publish command in publish workflow. +- Renamed prefix from TEMPLATE-UPDATE to NX-CDK-TEMPLATE & NX-APPBUILDER-TEMPLATE in dependabot. diff --git a/README.md b/README.md index 75f2664..1d1333d 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,19 @@ For more details, see [tools/generators/README.md](/tools/generators/README.md). Each of the packages in the monorepo have separate versioning and independent npm releases. To perform a release of one or more packages we use [Version Plans](https://nx.dev/recipes/nx-release/file-based-versioning-version-plans) to define the type of updates and provide change log. Nx will then detect the version plans and automatically update version numbers appropriately, as well as perform builds and deployments separately in the pipeline if a version plan is detected. -## Step-by-Step Guide +## Important - First publish must be done manually + +The first time a new package is published to `npm`, it must be published manually by a `maintainer`. Subsequent releases are then handled automatically by the release workflow. Contact with `DevOps` guild if you are not a maintainer of `@aligent/` on npm. + +Our release workflow uses [OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers). OIDC can only publish new versions of packages that already exist on npm — it cannot create a brand new package. The package name has to be registered on the npm registry before automated releases can take over. + +To bootstrap a new package: + +- Build the package locally: `npx nx build ` +- From the package directory, log in to npm (npm login) with maintainer credentials and publish: `npm publish --access public` +- Once the package exists on npm, future versions will be released automatically by the workflow. + +## Step-by-Step Guide for subsequence releases 1. Start by creating a new `releases/*` branch from the latest `main` branch. diff --git a/packages/nx-cdk/README.md b/packages/nx-cdk/README.md index 8776f97..e8e226d 100644 --- a/packages/nx-cdk/README.md +++ b/packages/nx-cdk/README.md @@ -59,13 +59,17 @@ The service generator creates a new CDK service within the `services/` folder of ```bash yarn nx g @aligent/nx-cdk:service + +# Or simply (since the generator name is unique): +yarn nx g service ``` #### Options -| Option | Type | Required | Description | -| ------ | ------ | -------- | ------------------------------------------------------------------------- | -| `name` | string | Yes | The name of the service (cannot contain 'Stack' or 'Service' in the name) | +| Option | Type | Required | Default | Description | +| --------- | ------- | -------- | ------- | ------------------------------------------------------------------------- | +| `name` | string | Yes | - | The name of the service (cannot contain 'Stack' or 'Service' in the name) | +| `example` | boolean | No | `false` | Generate example code with sample resources | #### What it creates @@ -89,11 +93,56 @@ The service generator creates a new service in `services//` with: #### Example ```bash -# Create a new service named "user-management" +# Create a new service named "user-management" (short form) +yarn nx g service user-management + +# Or with the full plugin prefix yarn nx g @aligent/nx-cdk:service user-management +``` + +### Remove Service Generator + +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. + +#### Usage + +```bash +yarn nx g @aligent/nx-cdk:remove-service + +# Or simply (since the generator name is unique): +yarn nx g remove-service +``` + +#### Options + +| Option | Type | Required | Default | Description | +| ------------- | ------- | -------- | ------- | ----------------------------------------------- | +| `name` | string | Yes | - | The name of the service to remove | +| `forceRemove` | boolean | No | `false` | Skip dependency check when removing the project | + +#### What it does + +The remove generator performs the following cleanup: + +- **Application updates**: + - Removes the service's import declaration from `application/lib/service-stacks.ts` + - Removes the stack instantiation from the `ApplicationStage` constructor + +- **Root updates**: + - Removes the service from the root `tsconfig.json` references + - Removes the service from the root `package.json` workspaces (if present) + +- **Service files**: + - Deletes the entire `services//` directory + +#### Example + +```bash +# Remove the "user-management" service (short form) +yarn nx g remove-service user-management -# Create a new service named "payment-processing" -yarn nx g @aligent/nx-cdk:service payment-processing +# Or with the full plugin prefix +yarn nx g @aligent/nx-cdk:remove-service user-management ``` ## Project Structure diff --git a/packages/nx-cdk/generators.json b/packages/nx-cdk/generators.json index 2c53592..0e029df 100644 --- a/packages/nx-cdk/generators.json +++ b/packages/nx-cdk/generators.json @@ -10,6 +10,11 @@ "factory": "./src/generators/service/generator", "schema": "./src/generators/service/schema.json", "description": "Generate a new service" + }, + "remove-service": { + "factory": "./src/generators/remove-service/generator", + "schema": "./src/generators/remove-service/schema.json", + "description": "Remove a service and clean up its references" } } } diff --git a/packages/nx-cdk/src/generators/constants.ts b/packages/nx-cdk/src/generators/constants.ts new file mode 100644 index 0000000..f9e6f92 --- /dev/null +++ b/packages/nx-cdk/src/generators/constants.ts @@ -0,0 +1,7 @@ +export type ProjectType = 'application' | 'service'; + +export const MAIN_APPLICATION_FOLDER = 'application'; +export const MAIN_APPLICATION_NAME = 'application'; + +export const SERVICES_FOLDER = 'services'; +export const SERVICES_SCOPE = '@services'; diff --git a/packages/nx-cdk/src/generators/helpers/configs/base-package/package.json b/packages/nx-cdk/src/generators/helpers/configs/base-package/package.json index 7977c73..fe11543 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/base-package/package.json +++ b/packages/nx-cdk/src/generators/helpers/configs/base-package/package.json @@ -24,7 +24,7 @@ "@aligent/cdk-aspects": "^0.5.5", "@aligent/cdk-nodejs-function-from-entry": "^0.2.1", "@aligent/cdk-step-function-from-file": "^0.5.1", - "@aligent/nx-openapi": "^2.2.1", + "@aligent/nx-openapi": "^2.1.1", "@aligent/ts-code-standards": "^4.2.1", "@nx/eslint": "22.1.3", "@nx/eslint-plugin": "22.1.3", diff --git a/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts index 234a0c8..d78fffa 100644 --- a/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts +++ b/packages/nx-cdk/src/generators/helpers/configs/nxJson.ts @@ -1,4 +1,5 @@ import { NxJsonConfiguration } from '@nx/devkit'; +import { SERVICES_SCOPE } from '../../constants'; export const NX_JSON: NxJsonConfiguration & { $schema: string } = { $schema: './node_modules/nx/schemas/nx-schema.json', @@ -36,7 +37,11 @@ export const NX_JSON: NxJsonConfiguration & { $schema: string } = { configurations: { coverage: { coverage: true } }, }, typecheck: { cache: true, inputs: ['default', '^production'] }, - cdk: { dependsOn: [{ target: 'build', params: 'forward', projects: '@services/*' }] }, - pg: { dependsOn: [{ target: 'build', params: 'forward', projects: '@services/*' }] }, + cdk: { + dependsOn: [{ target: 'build', params: 'forward', projects: `${SERVICES_SCOPE}/*` }], + }, + pg: { + dependsOn: [{ target: 'build', params: 'forward', projects: `${SERVICES_SCOPE}/*` }], + }, }, } as const; diff --git a/packages/nx-cdk/src/generators/helpers/utilities.ts b/packages/nx-cdk/src/generators/helpers/utilities.ts index 358abae..6333ee4 100644 --- a/packages/nx-cdk/src/generators/helpers/utilities.ts +++ b/packages/nx-cdk/src/generators/helpers/utilities.ts @@ -1,7 +1,8 @@ /* v8 ignore start */ -import { readJsonFile, readProjectConfiguration, Tree } from '@nx/devkit'; +import { readJsonFile, readProjectConfiguration, Tree, updateJson } from '@nx/devkit'; import { join } from 'path'; import { InMemoryFileSystemHost, Project } from 'ts-morph'; +import { ProjectType, SERVICES_SCOPE } from '../constants'; import { TS_CONFIG_JSON, TS_CONFIG_LIB_JSON, TS_CONFIG_SPEC_JSON } from './configs/tsConfigs'; interface PackageJsonInput { @@ -68,7 +69,7 @@ export function constructPackageJsonFile(input: PackageJsonInput) { return packageJson; } -export function constructProjectTsConfigFiles(type: 'application' | 'service') { +export function constructProjectTsConfigFiles(type: ProjectType) { const tsConfig = { ...TS_CONFIG_JSON }; if (type === 'service') { tsConfig.references = [{ path: './tsconfig.lib.json' }, { path: './tsconfig.spec.json' }]; @@ -152,7 +153,7 @@ export function addServiceStackToMainApplication( } stackSource.addImportDeclaration({ - moduleSpecifier: `@services/${service.name}`, + moduleSpecifier: `${SERVICES_SCOPE}/${service.name}`, namedImports: [service.constant, service.stack], }); @@ -166,6 +167,88 @@ export function addServiceStackToMainApplication( tree.write(stacksRelativePath, stackSource.getFullText()); } +/** + * Removes a service stack registration from the main CDK application's ApplicationStage. + * + * This function modifies the service-stacks.ts file by: + * 1. Removing import statements that reference the service's module specifier + * 2. Removing statements in the ApplicationStage constructor that reference the service's stack class + * + * @param tree - The Nx virtual file system tree + * @param serviceName - The name of the service (e.g., "companies") + * @param projectName - The name of the main application project + */ +export function removeServiceFromMainApplication( + tree: Tree, + serviceName: string, + projectName: string +) { + const application = readProjectConfiguration(tree, projectName); + + if (application.root.includes('..')) { + throw new Error('Invalid application root path'); + } + + const stacksRelativePath = join(application.root, 'lib/service-stacks.ts'); + + if (!tree.exists(stacksRelativePath)) { + console.log('Service Stacks does not exist, skipping service stacks cleanup.'); + return; + } + + const content = tree.read(stacksRelativePath, 'utf-8'); + + if (content === null) { + throw new Error(`Failed to read file: ${stacksRelativePath}`); + } + + const fs = new InMemoryFileSystemHost(); + fs.writeFileSync(stacksRelativePath, content); + + const project = new Project({ fileSystem: fs }); + const stackSource = project.addSourceFileAtPath(stacksRelativePath); + + const imports = stackSource.getImportDeclarations(); + for (const importDecl of imports) { + if (importDecl.getModuleSpecifierValue() === `${SERVICES_SCOPE}/${serviceName}`) { + importDecl.remove(); + } + } + + const nameParts = splitInputName(serviceName); + const stackClassName = `${nameParts.join('')}Stack`; + + const applicationStage = stackSource.getClass('ApplicationStage'); + if (applicationStage) { + const stageConstructor = applicationStage.getConstructors()[0]; + if (stageConstructor) { + const statements = stageConstructor.getStatements(); + for (const statement of statements) { + if (statement.getText().includes(`new ${stackClassName}(`)) { + statement.remove(); + } + } + } + } + + tree.write(stacksRelativePath, stackSource.getFullText()); +} + +/** + * Removes a project reference from the root tsconfig.json. + * + * @param tree - The Nx virtual file system tree + * @param referencePath - The path to remove from the references array + */ +export function removeTsConfigReference(tree: Tree, referencePath: string) { + updateJson(tree, 'tsconfig.json', json => { + json.references = (json.references ?? []).filter( + (r: { path: string }) => r.path !== referencePath + ); + return json; + }); +} + /** * Splits a kebab-case name into an array of capitalized parts. * diff --git a/packages/nx-cdk/src/generators/preset/preset.ts b/packages/nx-cdk/src/generators/preset/preset.ts index 81c968f..db2deb7 100644 --- a/packages/nx-cdk/src/generators/preset/preset.ts +++ b/packages/nx-cdk/src/generators/preset/preset.ts @@ -1,5 +1,6 @@ import { formatFiles, generateFiles, Tree, updateNxJson, writeJson } from '@nx/devkit'; import { join } from 'path'; +import { MAIN_APPLICATION_FOLDER, MAIN_APPLICATION_NAME } from '../constants'; import { NX_JSON } from '../helpers/configs/nxJson'; import { constructPackageJsonFile, @@ -40,8 +41,8 @@ export async function presetGenerator(tree: Tree, options: PresetGeneratorSchema writeJson(tree, 'package.json', packageJson); // Generate application's tsconfigs - const { tsConfig } = constructProjectTsConfigFiles('application'); - writeJson(tree, 'application/tsconfig.json', tsConfig); + const { tsConfig } = constructProjectTsConfigFiles(MAIN_APPLICATION_NAME); + writeJson(tree, `${MAIN_APPLICATION_FOLDER}/tsconfig.json`, tsConfig); await formatFiles(tree); } diff --git a/packages/nx-cdk/src/generators/remove-service/generator.spec.ts b/packages/nx-cdk/src/generators/remove-service/generator.spec.ts new file mode 100644 index 0000000..e25a6f5 --- /dev/null +++ b/packages/nx-cdk/src/generators/remove-service/generator.spec.ts @@ -0,0 +1,199 @@ +import * as devkit from '@nx/devkit'; +import { Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { serviceGenerator } from '../service/generator'; +import { removeGenerator } from './generator'; + +const serviceStacksContent = `import { SharedInfraStack } from '@libs/infra'; +import { Stage, type StageProps } from 'aws-cdk-lib'; +import type { Construct } from 'constructs'; + +export class ApplicationStage extends Stage { + constructor(scope: Construct, id: string, props?: StageProps) { + super(scope, id, props); + + const sharedInfra = new SharedInfraStack(this, 'shared-infra', props); + + // Service stacks initialization + } +} +`; + +const application = { + name: 'application', + type: 'module', + main: './bin/main.ts', + types: './bin/main.ts', + nx: { tags: ['scope:application'] }, +}; + +const rootPackageJson = { + name: '@test/integrations', + workspaces: ['application', 'libs/*'], +}; + +function setupTree() { + const tree = createTreeWithEmptyWorkspace(); + tree.write( + 'tsconfig.json', + JSON.stringify({ + extends: './tsconfig.base.json', + compileOnSave: false, + files: [], + references: [], + }) + ); + tree.write('application/package.json', JSON.stringify(application)); + tree.write('application/lib/service-stacks.ts', serviceStacksContent); + tree.write('package.json', JSON.stringify(rootPackageJson)); + return tree; +} + +describe('remove generator', () => { + let tree: Tree; + + beforeEach(() => { + tree = setupTree(); + }); + + it('should remove the service directory', async () => { + await serviceGenerator(tree, { name: 'companies' }); + expect(tree.exists('services/companies')).toBe(true); + + await removeGenerator(tree, { name: 'companies', forceRemove: true }); + expect(tree.exists('services/companies')).toBe(false); + }); + + it('should remove the tsconfig reference', async () => { + await serviceGenerator(tree, { name: 'companies' }); + + const tsconfigBefore = JSON.parse(tree.read('tsconfig.json', 'utf-8') ?? '{}'); + expect(tsconfigBefore.references).toContainEqual({ path: './services/companies' }); + + await removeGenerator(tree, { name: 'companies', forceRemove: true }); + + const tsconfigAfter = JSON.parse(tree.read('tsconfig.json', 'utf-8') ?? '{}'); + expect(tsconfigAfter.references).not.toContainEqual({ path: './services/companies' }); + }); + + it('should remove the import from service-stacks.ts', async () => { + await serviceGenerator(tree, { name: 'companies' }); + + const stacksBefore = tree.read('application/lib/service-stacks.ts', 'utf-8'); + expect(stacksBefore).toContain('@services/companies'); + + await removeGenerator(tree, { name: 'companies', forceRemove: true }); + + const stacksAfter = tree.read('application/lib/service-stacks.ts', 'utf-8'); + expect(stacksAfter).not.toContain('@services/companies'); + }); + + it('should remove the stack instantiation from service-stacks.ts', async () => { + await serviceGenerator(tree, { name: 'companies' }); + + const stacksBefore = tree.read('application/lib/service-stacks.ts', 'utf-8'); + expect(stacksBefore).toContain('new CompaniesStack('); + + await removeGenerator(tree, { name: 'companies', forceRemove: true }); + + const stacksAfter = tree.read('application/lib/service-stacks.ts', 'utf-8'); + expect(stacksAfter).not.toContain('new CompaniesStack('); + }); + + it('should only remove the targeted service when multiple services exist', async () => { + await serviceGenerator(tree, { name: 'companies' }); + await serviceGenerator(tree, { name: 'orders' }); + + await removeGenerator(tree, { name: 'companies', forceRemove: true }); + + // Companies should be removed + expect(tree.exists('services/companies')).toBe(false); + const stacks = tree.read('application/lib/service-stacks.ts', 'utf-8'); + expect(stacks).not.toContain('@services/companies'); + expect(stacks).not.toContain('new CompaniesStack('); + + // Orders should remain + expect(tree.exists('services/orders')).toBe(true); + expect(stacks).toContain('@services/orders'); + expect(stacks).toContain('new OrdersStack('); + + const tsconfig = JSON.parse(tree.read('tsconfig.json', 'utf-8') ?? '{}'); + expect(tsconfig.references).not.toContainEqual({ path: './services/companies' }); + expect(tsconfig.references).toContainEqual({ path: './services/orders' }); + }); + + it('should handle removal when service-stacks.ts does not exist', async () => { + tree.delete('application/lib/service-stacks.ts'); + tree.write('services/companies/package.json', '{}'); + tree.write( + 'tsconfig.json', + JSON.stringify({ + references: [{ path: './services/companies' }], + }) + ); + + await expect( + removeGenerator(tree, { name: 'companies', forceRemove: true }) + ).resolves.not.toThrow(); + expect(tree.exists('services/companies')).toBe(false); + }); + + it('should remove workspace entry from root package.json', async () => { + tree.write( + 'package.json', + JSON.stringify({ + ...rootPackageJson, + workspaces: ['application', 'libs/*', 'services/companies'], + }) + ); + + await serviceGenerator(tree, { name: 'companies' }); + await removeGenerator(tree, { name: 'companies', forceRemove: true }); + + const pkg = JSON.parse(tree.read('package.json', 'utf-8') ?? '{}'); + expect(pkg.workspaces).not.toContain('services/companies'); + }); + + it('should throw when service has dependents and forceRemove is false', async () => { + vi.spyOn(devkit, 'createProjectGraphAsync').mockResolvedValue({ + nodes: {}, + dependencies: { + application: [ + { + source: 'application', + target: '@services/companies', + type: 'static', + }, + ], + }, + }); + + await serviceGenerator(tree, { name: 'companies' }); + + await expect(removeGenerator(tree, { name: 'companies' })).rejects.toThrow( + /Cannot remove "companies": it is depended on by application/ + ); + + expect(tree.exists('services/companies')).toBe(true); + }); + + it('should throw when the service does not exist', async () => { + await expect( + removeGenerator(tree, { name: 'non-existent', forceRemove: true }) + ).rejects.toThrow(/Service "non-existent" does not exist/); + }); + + it('should proceed when service has no dependents and forceRemove is false', async () => { + vi.spyOn(devkit, 'createProjectGraphAsync').mockResolvedValue({ + nodes: {}, + dependencies: { + '@services/companies': [], + }, + }); + + await serviceGenerator(tree, { name: 'companies' }); + await removeGenerator(tree, { name: 'companies' }); + + expect(tree.exists('services/companies')).toBe(false); + }); +}); diff --git a/packages/nx-cdk/src/generators/remove-service/generator.ts b/packages/nx-cdk/src/generators/remove-service/generator.ts new file mode 100644 index 0000000..ff8b054 --- /dev/null +++ b/packages/nx-cdk/src/generators/remove-service/generator.ts @@ -0,0 +1,48 @@ +import { createProjectGraphAsync, formatFiles, Tree, updateJson } from '@nx/devkit'; +import { MAIN_APPLICATION_NAME, SERVICES_FOLDER, SERVICES_SCOPE } from '../constants'; +import { removeServiceFromMainApplication, removeTsConfigReference } from '../helpers/utilities'; +import { RemoveGeneratorSchema } from './schema'; + +export async function removeGenerator(tree: Tree, options: RemoveGeneratorSchema) { + const { name, forceRemove } = options; + + const projectRoot = `${SERVICES_FOLDER}/${name}`; + const projectName = `${SERVICES_SCOPE}/${name}`; + + if (!tree.exists(projectRoot)) { + throw new Error(`Service "${name}" does not exist at "${projectRoot}".`); + } + + if (!forceRemove) { + const graph = await createProjectGraphAsync(); + const dependents = Object.entries(graph.dependencies) + .filter(([source]) => source !== projectName) + .filter(([, deps]) => deps.some(d => d.target === projectName)) + .map(([source]) => source); + + if (dependents.length > 0) { + throw new Error( + `Cannot remove "${name}": it is depended on by ${dependents.join(', ')}. ` + + 'Use --forceRemove to skip this check.' + ); + } + } + + removeServiceFromMainApplication(tree, name, MAIN_APPLICATION_NAME); + removeTsConfigReference(tree, `./${projectRoot}`); + + tree.delete(projectRoot); + + if (tree.exists('package.json')) { + updateJson(tree, 'package.json', json => { + if (Array.isArray(json.workspaces)) { + json.workspaces = json.workspaces.filter((w: string) => w !== projectRoot); + } + return json; + }); + } + + await formatFiles(tree); +} + +export default removeGenerator; diff --git a/packages/nx-cdk/src/generators/remove-service/schema.d.ts b/packages/nx-cdk/src/generators/remove-service/schema.d.ts new file mode 100644 index 0000000..c21ab8e --- /dev/null +++ b/packages/nx-cdk/src/generators/remove-service/schema.d.ts @@ -0,0 +1,4 @@ +export interface RemoveGeneratorSchema { + name: string; + forceRemove?: boolean; +} diff --git a/packages/nx-cdk/src/generators/remove-service/schema.json b/packages/nx-cdk/src/generators/remove-service/schema.json new file mode 100644 index 0000000..d42ab80 --- /dev/null +++ b/packages/nx-cdk/src/generators/remove-service/schema.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "RemoveServiceGenerator", + "title": "Remove a service and clean up its references", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the service to remove", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "What is the name of the service to remove?" + }, + "forceRemove": { + "type": "boolean", + "description": "Skip dependency check when removing the project", + "default": false + } + }, + "required": ["name"] +} diff --git a/packages/nx-cdk/src/generators/service/generator.ts b/packages/nx-cdk/src/generators/service/generator.ts index 704cf9d..f90e746 100644 --- a/packages/nx-cdk/src/generators/service/generator.ts +++ b/packages/nx-cdk/src/generators/service/generator.ts @@ -1,5 +1,6 @@ import { formatFiles, generateFiles, Tree, updateJson, writeJson } from '@nx/devkit'; import { join } from 'path'; +import { MAIN_APPLICATION_NAME, SERVICES_FOLDER } from '../constants'; import { addServiceStackToMainApplication, constructProjectTsConfigFiles, @@ -7,8 +8,6 @@ import { } from '../helpers/utilities'; import { ServiceGeneratorSchema } from './schema'; -const SERVICES_FOLDER = 'services'; - function addTsConfigReference(tree: Tree, referencePath: string) { updateJson(tree, 'tsconfig.json', json => { json.references ??= []; @@ -58,7 +57,11 @@ export async function serviceGenerator(tree: Tree, options: ServiceGeneratorSche // Integrate the new service with the root application addTsConfigReference(tree, `./${projectRoot}`); - addServiceStackToMainApplication(tree, { name: options.name, constant, stack }, 'application'); + addServiceStackToMainApplication( + tree, + { name: options.name, constant, stack }, + MAIN_APPLICATION_NAME + ); await formatFiles(tree); }