From cf27791aa678d03306318cb4429616f0385611e2 Mon Sep 17 00:00:00 2001 From: khalilou88 <32600911+khalilou88@users.noreply.github.com> Date: Wed, 31 May 2023 17:40:56 +0200 Subject: [PATCH] feat(plugins): add nx-micronaut-maven plugin (#222) * feat: add nx-micronaut-maven plugin * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress * build: work in progress [skip ci] * build: work in progress * build: work in progress [skip ci] * build: work in progress [skip ci] * build: work in progress [skip ci] * build: work in progress [skip ci] * build: work in progress [skip ci] * build: work in progress [skip ci] * build: work in progress [skip ci] --- .../build-image/micronaut/executor.spec.ts | 38 + .../build-image/micronaut/executor.ts | 13 + .../build-image/micronaut/schema.d.ts | 3 + .../build-image/micronaut/schema.json | 14 + .../src/executors/build/executor.spec.ts | 42 + .../maven/src/executors/build/executor.ts | 53 + .../maven/src/executors/build/schema.d.ts | 8 + .../maven/src/executors/build/schema.json | 27 + .../serve/micronaut/executor.spec.ts | 53 + .../src/executors/serve/micronaut/executor.ts | 26 + .../src/executors/serve/micronaut/schema.d.ts | 3 + .../src/executors/serve/micronaut/schema.json | 14 + packages/nx-micronaut-maven/.babelrc | 10 + packages/nx-micronaut-maven/.eslintrc.json | 18 + packages/nx-micronaut-maven/CHANGELOG.md | 0 packages/nx-micronaut-maven/README.md | 58 + packages/nx-micronaut-maven/executors.json | 50 + packages/nx-micronaut-maven/generators.json | 36 + packages/nx-micronaut-maven/generators.ts | 11 + packages/nx-micronaut-maven/jest.config.ts | 18 + packages/nx-micronaut-maven/package.json | 43 + packages/nx-micronaut-maven/project.json | 102 + .../src/dep-graph/lookup-deps.ts | 17 + .../application/files/java/README.md | 10 + .../files/java/pom.xml__template__ | 102 + .../files/java/src/main/java/.gitkeep | 0 .../__packageDirectory__/Application.java | 10 + .../__packageDirectory__/HelloController.java | 15 + .../resources/application__configFormat__ | 20 + .../files/java/src/main/resources/logback.xml | 14 + .../files/java/src/test/java/.gitkeep | 0 .../HelloControllerTest.java | 29 + .../__appClassName__Test.java | 21 + .../resources/application__configFormat__ | 8 + .../application/files/kotlin/README.md | 16 + .../files/kotlin/pom.xml__template__ | 239 ++ .../files/kotlin/src/main/kotlin/.gitkeep | 0 .../__packageDirectory__/Application.kt | 7 + .../__packageDirectory__/HelloController.kt | 14 + .../resources/application__configFormat__ | 21 + .../kotlin/src/main/resources/logback.xml | 14 + .../files/kotlin/src/test/kotlin/.gitkeep | 0 .../HelloControllerTest.kt | 21 + .../__appClassName__Test.kt | 20 + .../resources/application__configFormat__ | 8 + .../generators/application/generator.spec.ts | 41 + .../src/generators/application/generator.ts | 257 +++ .../src/generators/application/schema.d.ts | 16 + .../src/generators/application/schema.json | 110 + .../init/files/linters/checkstyle.xml | 99 + .../src/generators/init/files/linters/pmd.xml | 38 + .../files/maven/config/pom.xml__template__ | 30 + .../src/generators/init/generator.spec.ts | 26 + .../src/generators/init/generator.ts | 82 + .../src/generators/init/schema.d.ts | 6 + .../src/generators/init/schema.json | 58 + .../library/files/java/pom.xml__template__ | 39 + .../library/files/java/src/main/java/.gitkeep | 0 .../__packageDirectory__/HelloService.java | 11 + .../library/files/java/src/test/java/.gitkeep | 0 .../HelloServiceTest.java | 20 + .../library/files/kotlin/pom.xml__template__ | 203 ++ .../files/kotlin/src/main/kotlin/.gitkeep | 0 .../__packageDirectory__/HelloService.kt | 11 + .../files/kotlin/src/test/kotlin/.gitkeep | 0 .../__packageDirectory__/HelloServiceTest.kt | 25 + .../src/generators/library/generator.spec.ts | 30 + .../src/generators/library/generator.ts | 232 ++ .../src/generators/library/schema.d.ts | 15 + .../src/generators/library/schema.json | 83 + .../src/generators/migrate/generator.spec.ts | 26 + .../src/generators/migrate/generator.ts | 44 + .../src/generators/migrate/schema.d.ts | 1 + .../src/generators/migrate/schema.json | 8 + .../parent-project/files/pom.xml__template__ | 18 + .../parent-project/generator.spec.ts | 29 + .../generators/parent-project/generator.ts | 130 ++ .../src/generators/parent-project/schema.d.ts | 12 + .../src/generators/parent-project/schema.json | 69 + packages/nx-micronaut-maven/src/index.ts | 1 + .../src/scripts/install-linters.ts | 25 + packages/nx-micronaut-maven/tsconfig.json | 22 + packages/nx-micronaut-maven/tsconfig.lib.json | 11 + .../nx-micronaut-maven/tsconfig.spec.json | 16 + .../e2e/nx-micronaut-maven-e2e/jest.config.js | 16 + .../e2e/nx-micronaut-maven-e2e/project.json | 18 + .../tests/nx-micronaut-maven.spec.ts | 1918 +++++++++++++++++ .../e2e/nx-micronaut-maven-e2e/tsconfig.json | 10 + .../nx-micronaut-maven-e2e/tsconfig.spec.json | 9 + tsconfig.base.json | 3 + 90 files changed, 5064 insertions(+) create mode 100644 packages/maven/src/executors/build-image/micronaut/executor.spec.ts create mode 100644 packages/maven/src/executors/build-image/micronaut/executor.ts create mode 100644 packages/maven/src/executors/build-image/micronaut/schema.d.ts create mode 100644 packages/maven/src/executors/build-image/micronaut/schema.json create mode 100644 packages/maven/src/executors/build/executor.spec.ts create mode 100644 packages/maven/src/executors/build/executor.ts create mode 100644 packages/maven/src/executors/build/schema.d.ts create mode 100644 packages/maven/src/executors/build/schema.json create mode 100644 packages/maven/src/executors/serve/micronaut/executor.spec.ts create mode 100644 packages/maven/src/executors/serve/micronaut/executor.ts create mode 100644 packages/maven/src/executors/serve/micronaut/schema.d.ts create mode 100644 packages/maven/src/executors/serve/micronaut/schema.json create mode 100644 packages/nx-micronaut-maven/.babelrc create mode 100644 packages/nx-micronaut-maven/.eslintrc.json create mode 100644 packages/nx-micronaut-maven/CHANGELOG.md create mode 100644 packages/nx-micronaut-maven/README.md create mode 100644 packages/nx-micronaut-maven/executors.json create mode 100644 packages/nx-micronaut-maven/generators.json create mode 100644 packages/nx-micronaut-maven/generators.ts create mode 100644 packages/nx-micronaut-maven/jest.config.ts create mode 100644 packages/nx-micronaut-maven/package.json create mode 100644 packages/nx-micronaut-maven/project.json create mode 100644 packages/nx-micronaut-maven/src/dep-graph/lookup-deps.ts create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/README.md create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/pom.xml__template__ create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/Application.java create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/HelloController.java create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/application__configFormat__ create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/logback.xml create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/HelloControllerTest.java create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/__appClassName__Test.java create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/java/src/test/resources/application__configFormat__ create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/README.md create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/pom.xml__template__ create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/Application.kt create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/HelloController.kt create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/application__configFormat__ create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/logback.xml create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/HelloControllerTest.kt create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/__appClassName__Test.kt create mode 100644 packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/resources/application__configFormat__ create mode 100644 packages/nx-micronaut-maven/src/generators/application/generator.spec.ts create mode 100644 packages/nx-micronaut-maven/src/generators/application/generator.ts create mode 100644 packages/nx-micronaut-maven/src/generators/application/schema.d.ts create mode 100644 packages/nx-micronaut-maven/src/generators/application/schema.json create mode 100644 packages/nx-micronaut-maven/src/generators/init/files/linters/checkstyle.xml create mode 100644 packages/nx-micronaut-maven/src/generators/init/files/linters/pmd.xml create mode 100644 packages/nx-micronaut-maven/src/generators/init/files/maven/config/pom.xml__template__ create mode 100644 packages/nx-micronaut-maven/src/generators/init/generator.spec.ts create mode 100644 packages/nx-micronaut-maven/src/generators/init/generator.ts create mode 100644 packages/nx-micronaut-maven/src/generators/init/schema.d.ts create mode 100644 packages/nx-micronaut-maven/src/generators/init/schema.json create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/java/pom.xml__template__ create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/java/src/main/java/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/java/src/main/java/__packageDirectory__/HelloService.java create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/java/src/test/java/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/java/src/test/java/__packageDirectory__/HelloServiceTest.java create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/kotlin/pom.xml__template__ create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/main/kotlin/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/main/kotlin/__packageDirectory__/HelloService.kt create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/test/kotlin/.gitkeep create mode 100644 packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/test/kotlin/__packageDirectory__/HelloServiceTest.kt create mode 100644 packages/nx-micronaut-maven/src/generators/library/generator.spec.ts create mode 100644 packages/nx-micronaut-maven/src/generators/library/generator.ts create mode 100644 packages/nx-micronaut-maven/src/generators/library/schema.d.ts create mode 100644 packages/nx-micronaut-maven/src/generators/library/schema.json create mode 100644 packages/nx-micronaut-maven/src/generators/migrate/generator.spec.ts create mode 100644 packages/nx-micronaut-maven/src/generators/migrate/generator.ts create mode 100644 packages/nx-micronaut-maven/src/generators/migrate/schema.d.ts create mode 100644 packages/nx-micronaut-maven/src/generators/migrate/schema.json create mode 100644 packages/nx-micronaut-maven/src/generators/parent-project/files/pom.xml__template__ create mode 100644 packages/nx-micronaut-maven/src/generators/parent-project/generator.spec.ts create mode 100644 packages/nx-micronaut-maven/src/generators/parent-project/generator.ts create mode 100644 packages/nx-micronaut-maven/src/generators/parent-project/schema.d.ts create mode 100644 packages/nx-micronaut-maven/src/generators/parent-project/schema.json create mode 100644 packages/nx-micronaut-maven/src/index.ts create mode 100644 packages/nx-micronaut-maven/src/scripts/install-linters.ts create mode 100644 packages/nx-micronaut-maven/tsconfig.json create mode 100644 packages/nx-micronaut-maven/tsconfig.lib.json create mode 100644 packages/nx-micronaut-maven/tsconfig.spec.json create mode 100644 testing-projects/e2e/nx-micronaut-maven-e2e/jest.config.js create mode 100644 testing-projects/e2e/nx-micronaut-maven-e2e/project.json create mode 100644 testing-projects/e2e/nx-micronaut-maven-e2e/tests/nx-micronaut-maven.spec.ts create mode 100644 testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.json create mode 100644 testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.spec.json diff --git a/packages/maven/src/executors/build-image/micronaut/executor.spec.ts b/packages/maven/src/executors/build-image/micronaut/executor.spec.ts new file mode 100644 index 000000000..cd6af4312 --- /dev/null +++ b/packages/maven/src/executors/build-image/micronaut/executor.spec.ts @@ -0,0 +1,38 @@ +import { ExecutorContext } from '@nx/devkit'; +import { runCommand } from '@jnxplus/common'; +import executor from './executor'; +import { BuildImageExecutorSchema } from './schema'; +jest.mock('@jnxplus/common'); + +const options: BuildImageExecutorSchema = { + args: '', +}; +const context: ExecutorContext = { + root: '/root', + cwd: '/root', + projectName: 'my-app', + targetName: 'build', + workspace: { + version: 2, + projects: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + 'my-app': { + root: 'apps/wibble', + sourceRoot: 'apps/wibble', + }, + }, + npmScope: 'test', + }, + isVerbose: false, +}; + +describe('Build Image Executor', () => { + beforeEach(async () => { + (runCommand as jest.Mock).mockReturnValue({ success: true }); + }); + + xit('can run', async () => { + const output = await executor(options, context); + expect(output.success).toBe(true); + }); +}); diff --git a/packages/maven/src/executors/build-image/micronaut/executor.ts b/packages/maven/src/executors/build-image/micronaut/executor.ts new file mode 100644 index 000000000..2f882ca76 --- /dev/null +++ b/packages/maven/src/executors/build-image/micronaut/executor.ts @@ -0,0 +1,13 @@ +import { runCommand } from '@jnxplus/common'; +import { ExecutorContext, logger } from '@nx/devkit'; +import { BuildImageExecutorSchema } from './schema'; + +export default async function runExecutor( + options: BuildImageExecutorSchema, + context: ExecutorContext +) { + logger.info(`Executor ran for Build Image: ${JSON.stringify(options)}`); + return runCommand( + `getExecutable() package -pl :${context.projectName} ${options.args}` + ); +} diff --git a/packages/maven/src/executors/build-image/micronaut/schema.d.ts b/packages/maven/src/executors/build-image/micronaut/schema.d.ts new file mode 100644 index 000000000..b9e8b7172 --- /dev/null +++ b/packages/maven/src/executors/build-image/micronaut/schema.d.ts @@ -0,0 +1,3 @@ +export interface BuildImageExecutorSchema { + args: string; +} diff --git a/packages/maven/src/executors/build-image/micronaut/schema.json b/packages/maven/src/executors/build-image/micronaut/schema.json new file mode 100644 index 000000000..29ea686ad --- /dev/null +++ b/packages/maven/src/executors/build-image/micronaut/schema.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "outputCapture": "pipe", + "$schema": "http://json-schema.org/schema", + "title": "Build Image executor", + "description": "", + "type": "object", + "properties": { + "args": { + "type": "string" + } + }, + "required": [] +} diff --git a/packages/maven/src/executors/build/executor.spec.ts b/packages/maven/src/executors/build/executor.spec.ts new file mode 100644 index 000000000..f9bd8abea --- /dev/null +++ b/packages/maven/src/executors/build/executor.spec.ts @@ -0,0 +1,42 @@ +import { ExecutorContext } from '@nx/devkit'; +import { runCommand } from '@jnxplus/common'; +import executor from './executor'; +import { BuildExecutorSchema } from './schema'; +jest.mock('@jnxplus/common'); + +const options: BuildExecutorSchema = { + mvnArgs: '--no-transfer-progress', + mvnBuildCommand: 'compile', + mvnBuildArgs: '-Dquarkus.package.type=uber-jar', + skipClean: true, +}; + +const context: ExecutorContext = { + root: '/root', + cwd: '/root', + projectName: 'my-app', + targetName: 'build', + workspace: { + version: 2, + projects: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + 'my-app': { + root: 'apps/wibble', + sourceRoot: 'apps/wibble', + }, + }, + npmScope: 'test', + }, + isVerbose: false, +}; + +describe('Build Executor', () => { + beforeEach(async () => { + (runCommand as jest.Mock).mockReturnValue({ success: true }); + }); + + xit('can run', async () => { + const output = await executor(options, context); + expect(output.success).toBe(true); + }); +}); diff --git a/packages/maven/src/executors/build/executor.ts b/packages/maven/src/executors/build/executor.ts new file mode 100644 index 000000000..73f29f98d --- /dev/null +++ b/packages/maven/src/executors/build/executor.ts @@ -0,0 +1,53 @@ +import { getProjectType, isRootProject, runCommand } from '@jnxplus/common'; +import { getExecutable, isPomPackaging } from '../../lib/utils'; +import { ExecutorContext, logger } from '@nx/devkit'; +import { BuildExecutorSchema } from './schema'; + +export default async function runExecutor( + options: BuildExecutorSchema, + context: ExecutorContext +) { + logger.info(`Executor ran for Build: ${JSON.stringify(options)}`); + + if (process.env['NX_MAVEN_CLI_OPTS']) { + if (options.mvnArgs) { + options.mvnArgs += ` ${process.env['NX_MAVEN_CLI_OPTS']}`; + } else { + options.mvnArgs = `${process.env['NX_MAVEN_CLI_OPTS']}`; + } + } + + let command = getExecutable(); + + if (options.mvnArgs) { + command += ` ${options.mvnArgs}`; + } + + if (!options.skipClean) { + command += ' clean'; + } + + if (isPomPackaging(context)) { + command += isRootProject(context) ? ' install -N' : ' install'; + + return runCommand(`${command} -pl :${context.projectName}`); + } + + if (options.mvnBuildCommand) { + command += ` ${options.mvnBuildCommand}`; + } else { + if (getProjectType(context) === 'application') { + command += ' compile'; + } + + if (getProjectType(context) === 'library') { + command += ' install'; + } + } + + if (options.mvnBuildArgs) { + command += ` ${options.mvnBuildArgs}`; + } + + return runCommand(`${command} -DskipTests=true -pl :${context.projectName}`); +} diff --git a/packages/maven/src/executors/build/schema.d.ts b/packages/maven/src/executors/build/schema.d.ts new file mode 100644 index 000000000..7a57b4cab --- /dev/null +++ b/packages/maven/src/executors/build/schema.d.ts @@ -0,0 +1,8 @@ +import { MvnBuildCommandType } from '@jnxplus/common'; + +export interface BuildExecutorSchema { + mvnArgs: string; + mvnBuildCommand: MvnBuildCommandType; + mvnBuildArgs: string; + skipClean: boolean; +} diff --git a/packages/maven/src/executors/build/schema.json b/packages/maven/src/executors/build/schema.json new file mode 100644 index 000000000..09376e6b1 --- /dev/null +++ b/packages/maven/src/executors/build/schema.json @@ -0,0 +1,27 @@ +{ + "version": 2, + "outputCapture": "pipe", + "$schema": "http://json-schema.org/schema", + "title": "Build executor", + "description": "", + "type": "object", + "properties": { + "mvnArgs": { + "type": "string", + "description": "Arguments to pass to the maven cli" + }, + "mvnBuildCommand": { + "type": "string", + "description": "Maven build command to use : compile, package or install" + }, + "mvnBuildArgs": { + "type": "string", + "description": "Arguments to pass to the maven build command" + }, + "skipClean": { + "type": "boolean", + "default": true + } + }, + "required": [] +} diff --git a/packages/maven/src/executors/serve/micronaut/executor.spec.ts b/packages/maven/src/executors/serve/micronaut/executor.spec.ts new file mode 100644 index 000000000..8ebd77475 --- /dev/null +++ b/packages/maven/src/executors/serve/micronaut/executor.spec.ts @@ -0,0 +1,53 @@ +import { ExecutorContext } from '@nx/devkit'; +import { runCommand } from '@jnxplus/common'; +import executor from './executor'; +import { ServeExecutorSchema } from './schema'; +jest.mock('@jnxplus/common'); + +const options: ServeExecutorSchema = { + args: 'args', +}; +const context: ExecutorContext = { + root: '/root', + cwd: '/root', + projectName: 'my-app', + targetName: 'serve', + workspace: { + version: 2, + projects: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + 'my-app': { + root: 'apps/wibble', + sourceRoot: 'apps/wibble', + }, + }, + npmScope: 'test', + }, + isVerbose: false, +}; + +describe('Serve Executor', () => { + beforeEach(async () => { + (runCommand as jest.Mock).mockReturnValue({ success: true }); + }); + + xit('can run', async () => { + const output = await executor(options, context); + + expect(output.success).toBe(true); + expect(runCommand).toHaveBeenCalledWith( + expect.stringMatching(/quarkus:dev -pl :my-app args$/) + ); + }); + + describe('when args option is undefined', () => { + xit('run without extra args', async () => { + const output = await executor({} as ServeExecutorSchema, context); + + expect(output.success).toBe(true); + expect(runCommand).toHaveBeenCalledWith( + expect.stringMatching(/quarkus:dev -pl :my-app$/) + ); + }); + }); +}); diff --git a/packages/maven/src/executors/serve/micronaut/executor.ts b/packages/maven/src/executors/serve/micronaut/executor.ts new file mode 100644 index 000000000..db462d0c1 --- /dev/null +++ b/packages/maven/src/executors/serve/micronaut/executor.ts @@ -0,0 +1,26 @@ +import { ExecutorContext, logger } from '@nx/devkit'; +import { runCommand, waitForever } from '@jnxplus/common'; +import { ServeExecutorSchema } from './schema'; +import { getExecutable } from '../../../.'; + +export default async function runExecutor( + options: ServeExecutorSchema, + context: ExecutorContext +) { + logger.info(`Executor ran for serve: ${JSON.stringify(options)}`); + + let command = `${getExecutable()} mn:run -pl :${context.projectName}`; + + if (options.args) { + command += ` ${options.args}`; + } + + const result = runCommand(command); + + if (!result.success) { + return { success: false }; + } + + await waitForever(); + return { success: true }; +} diff --git a/packages/maven/src/executors/serve/micronaut/schema.d.ts b/packages/maven/src/executors/serve/micronaut/schema.d.ts new file mode 100644 index 000000000..6d76b1fa9 --- /dev/null +++ b/packages/maven/src/executors/serve/micronaut/schema.d.ts @@ -0,0 +1,3 @@ +export interface ServeExecutorSchema { + args: string; +} diff --git a/packages/maven/src/executors/serve/micronaut/schema.json b/packages/maven/src/executors/serve/micronaut/schema.json new file mode 100644 index 000000000..d257439b2 --- /dev/null +++ b/packages/maven/src/executors/serve/micronaut/schema.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "outputCapture": "direct-nodejs", + "$schema": "http://json-schema.org/schema", + "title": "Serve executor", + "description": "", + "type": "object", + "properties": { + "args": { + "type": "string" + } + }, + "required": [] +} diff --git a/packages/nx-micronaut-maven/.babelrc b/packages/nx-micronaut-maven/.babelrc new file mode 100644 index 000000000..fd4cbcdef --- /dev/null +++ b/packages/nx-micronaut-maven/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + [ + "@nx/js/babel", + { + "useBuiltIns": "usage" + } + ] + ] +} diff --git a/packages/nx-micronaut-maven/.eslintrc.json b/packages/nx-micronaut-maven/.eslintrc.json new file mode 100644 index 000000000..9d9c0db55 --- /dev/null +++ b/packages/nx-micronaut-maven/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/packages/nx-micronaut-maven/CHANGELOG.md b/packages/nx-micronaut-maven/CHANGELOG.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/README.md b/packages/nx-micronaut-maven/README.md new file mode 100644 index 000000000..b2527daf4 --- /dev/null +++ b/packages/nx-micronaut-maven/README.md @@ -0,0 +1,58 @@ +# @jnxplus/nx-micronaut-maven + +[![npm version](https://badge.fury.io/js/@jnxplus%2Fnx-micronaut-maven.svg)](https://badge.fury.io/js/@jnxplus%2Fnx-micronaut-maven) + +This plugin adds micronaut and Maven multi-module capabilities to Nx workspace. + +Here is a quick overview of the plugin, to know more, please visit [the documentation](https://khalilou88.github.io/jnxplus/). + +## Supported versions + +| @jnxplus/nx-micronaut-maven | Nx | micronaut | +| --------------------------- | ------ | ------------ | +| 0.1.x | 16.x.x | 2.16.6.Final | +| 0.0.x | 15.x.x | 2.16.6.Final | + +## Getting Started + +### 0. Prerequisites + +`@jnxplus/nx-micronaut-maven` requires a Java 17 or higher Runtime Environment and the current Long Term Support (LTS) version of node.js. + +### 1. Install the plugin + +In the Nx workspace root folder, run this command to install the plugin : + +```bash +npm install --save-dev @jnxplus/nx-micronaut-maven +``` + +### 2. Add micronaut and Maven wrapper support + +The following command adds micronaut and Maven support (Maven wrapper and config files) to the workspace. This only needs to be performed once per workspace. + +```bash +nx generate @jnxplus/nx-micronaut-maven:init +``` + +### 3. Usage + +| Action | Command | +| ------------------------------------ | --------------------------------------------------------------------- | +| Generate an application | `nx generate @jnxplus/nx-micronaut-maven:application my-app-name` | +| Generate a library | `nx generate @jnxplus/nx-micronaut-maven:library my-lib-name` | +| Build a project | `nx build my-project-name` | +| Build an image | `nx build-image my-app-name` | +| Serve an application | `nx serve my-app-name` | +| Test a project | `nx test my-project-name` | +| Integration Test an application | `nx integration-test my-app-name` | +| Lint a project | `nx lint my-project-name` | +| Format a java project | `nx format --projects my-project-name` | +| Format a kotlin project | `nx ktformat my-project-name` | +| Run a custom task | `nx run-task my-project-name --task="clean install -DskipTests=true"` | +| Publish a project | `nx publish my-project-name` | +| Visualize project's dependency graph | `nx dep-graph` | + +## License + +MIT © 2023-2023 Khalil LAGRIDA diff --git a/packages/nx-micronaut-maven/executors.json b/packages/nx-micronaut-maven/executors.json new file mode 100644 index 000000000..e6a6f3d1d --- /dev/null +++ b/packages/nx-micronaut-maven/executors.json @@ -0,0 +1,50 @@ +{ + "$schema": "http://json-schema.org/schema", + "executors": { + "build": { + "implementation": "@jnxplus/maven/src/executors/build/executor", + "schema": "@jnxplus/maven/src/executors/build/schema.json", + "description": "build executor" + }, + "build-image": { + "implementation": "@jnxplus/common/src/executors/build-image/micronaut/executor", + "schema": "@jnxplus/common/src/executors/build-image/micronaut/schema.json", + "description": "build-image executor" + }, + "serve": { + "implementation": "@jnxplus/maven/src/executors/serve/micronaut/executor", + "schema": "@jnxplus/maven/src/executors/serve/micronaut/schema.json", + "description": "serve executor" + }, + "lint": { + "implementation": "@jnxplus/maven/src/executors/lint/executor", + "schema": "@jnxplus/common/src/executors/lint/schema.json", + "description": "lint executor" + }, + "test": { + "implementation": "@jnxplus/maven/src/executors/test/executor", + "schema": "@jnxplus/maven/src/executors/test/schema.json", + "description": "test executor" + }, + "integration-test": { + "implementation": "@jnxplus/maven/src/executors/integration-test/executor", + "schema": "@jnxplus/maven/src/executors/integration-test/schema.json", + "description": "integration-test executor" + }, + "ktformat": { + "implementation": "@jnxplus/maven/src/executors/ktformat/executor", + "schema": "@jnxplus/common/src/executors/ktformat/schema.json", + "description": "kotlin format executor" + }, + "run-task": { + "implementation": "@jnxplus/maven/src/executors/run-task/executor", + "schema": "@jnxplus/maven/src/executors/run-task/schema.json", + "description": "run-task executor" + }, + "publish": { + "implementation": "@jnxplus/maven/src/executors/publish/executor", + "schema": "@jnxplus/maven/src/executors/publish/schema.json", + "description": "publish executor" + } + } +} diff --git a/packages/nx-micronaut-maven/generators.json b/packages/nx-micronaut-maven/generators.json new file mode 100644 index 000000000..3fe9dcc33 --- /dev/null +++ b/packages/nx-micronaut-maven/generators.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/schema", + "name": "nx-micronaut-maven", + "version": "0.0.1", + "generators": { + "init": { + "factory": "./src/generators/init/generator", + "schema": "./src/generators/init/schema.json", + "description": "init generator" + }, + "migrate": { + "factory": "./src/generators/migrate/generator", + "schema": "./src/generators/migrate/schema.json", + "description": "migrate generator" + }, + "application": { + "factory": "./src/generators/application/generator", + "schema": "./src/generators/application/schema.json", + "aliases": ["app"], + "x-type": "application", + "description": "application generator" + }, + "library": { + "factory": "./src/generators/library/generator", + "schema": "./src/generators/library/schema.json", + "aliases": ["lib"], + "x-type": "library", + "description": "library generator" + }, + "parent-project": { + "factory": "./src/generators/parent-project/generator", + "schema": "./src/generators/parent-project/schema.json", + "description": "parent-project generator" + } + } +} diff --git a/packages/nx-micronaut-maven/generators.ts b/packages/nx-micronaut-maven/generators.ts new file mode 100644 index 000000000..3663f4329 --- /dev/null +++ b/packages/nx-micronaut-maven/generators.ts @@ -0,0 +1,11 @@ +import initGenerator from './src/generators/init/generator'; +import libraryGenerator from './src/generators/library/generator'; +import applicationGenerator from './src/generators/application/generator'; +import migrateGenerator from './src/generators/migrate/generator'; + +export { + initGenerator, + libraryGenerator, + applicationGenerator, + migrateGenerator, +}; diff --git a/packages/nx-micronaut-maven/jest.config.ts b/packages/nx-micronaut-maven/jest.config.ts new file mode 100644 index 000000000..868c0ae54 --- /dev/null +++ b/packages/nx-micronaut-maven/jest.config.ts @@ -0,0 +1,18 @@ +/* eslint-disable */ +export default { + displayName: 'nx-micronaut-maven', + + globals: {}, + testEnvironment: 'node', + transform: { + '^.+\\.[tj]sx?$': [ + 'ts-jest', + { + tsconfig: '/tsconfig.spec.json', + }, + ], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/packages/nx-micronaut-maven', + preset: '../../jest.preset.js', +}; diff --git a/packages/nx-micronaut-maven/package.json b/packages/nx-micronaut-maven/package.json new file mode 100644 index 000000000..f27230f35 --- /dev/null +++ b/packages/nx-micronaut-maven/package.json @@ -0,0 +1,43 @@ +{ + "name": "@jnxplus/nx-micronaut-maven", + "version": "0.0.1", + "type": "commonjs", + "main": "src/index.js", + "generators": "./generators.json", + "executors": "./executors.json", + "private": false, + "publishConfig": { + "access": "public" + }, + "license": "MIT", + "author": "Khalil LAGRIDA", + "homepage": "https://github.com/khalilou88/jnxplus/blob/main/packages/nx-micronaut-maven/README.md", + "bugs": { + "url": "https://github.com/khalilou88/jnxplus/issues" + }, + "keywords": [ + "nx", + "nx-workspace", + "nx-plugin", + "java", + "micronaut", + "maven", + "maven multi-module project" + ], + "exports": { + ".": "./src/index.js", + "./generators": "./generators.js", + "./package.json": "./package.json" + }, + "scripts": { + "postinstall": "node src/scripts/install-linters.js" + }, + "dependencies": { + "prettier-plugin-java": "^2.1.0", + "@prettier/plugin-xml": "^2.2.0", + "xmldoc": "~1.3.0" + }, + "peerDependencies": { + "@nx/devkit": ">=16.0.0" + } +} diff --git a/packages/nx-micronaut-maven/project.json b/packages/nx-micronaut-maven/project.json new file mode 100644 index 000000000..8ac3cdd79 --- /dev/null +++ b/packages/nx-micronaut-maven/project.json @@ -0,0 +1,102 @@ +{ + "name": "nx-micronaut-maven", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/nx-micronaut-maven/src", + "projectType": "library", + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["packages/nx-micronaut-maven/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/packages/nx-micronaut-maven"], + "options": { + "jestConfig": "packages/nx-micronaut-maven/jest.config.ts", + "passWithNoTests": true + } + }, + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/packages/nx-micronaut-maven", + "main": "packages/nx-micronaut-maven/src/index.ts", + "packageJson": "packages/nx-micronaut-maven/package.json", + "tsConfig": "packages/nx-micronaut-maven/tsconfig.lib.json", + "updateBuildableProjectDepsInPackageJson": true, + "buildableProjectDepsInPackageJsonType": "dependencies", + "assets": [ + "packages/nx-micronaut-maven/*.md", + { + "input": "./packages/nx-micronaut-maven/src", + "glob": "**/!(*.ts)", + "output": "./src" + }, + { + "input": "./packages/nx-micronaut-maven/src", + "glob": "**/*.d.ts", + "output": "./src" + }, + { + "input": "./packages/nx-micronaut-maven", + "glob": "generators.json", + "output": "." + }, + { + "input": "./packages/nx-micronaut-maven", + "glob": "executors.json", + "output": "." + }, + { + "input": "./packages/maven-wrapper/.mvn", + "glob": "wrapper/**", + "output": "./src/generators/init/files/maven/wrapper/__dot__mvn" + }, + { + "input": "./packages/maven-wrapper", + "glob": "mvnw", + "output": "./src/generators/init/files/maven/wrapper" + }, + { + "input": "./packages/maven-wrapper", + "glob": "mvnw.cmd", + "output": "./src/generators/init/files/maven/wrapper" + } + ] + } + }, + "version": { + "executor": "@jscutlery/semver:version", + "options": { + "preset": "angular", + "trackDeps": true, + "push": true, + "noVerify": true, + "postTargets": [ + "nx-micronaut-maven:github", + "nx-micronaut-maven:publish" + ], + "commitMessageFormat": "release(${projectName}): cut release ${version} [skip ci]" + } + }, + "github": { + "executor": "@jscutlery/semver:github", + "options": { + "tag": "${tag}", + "notes": "${notes}" + } + }, + "publish": { + "executor": "ngx-deploy-npm:deploy", + "options": { + "access": "public" + } + } + }, + "tags": [], + "implicitDependencies": [] +} diff --git a/packages/nx-micronaut-maven/src/dep-graph/lookup-deps.ts b/packages/nx-micronaut-maven/src/dep-graph/lookup-deps.ts new file mode 100644 index 000000000..e606197d2 --- /dev/null +++ b/packages/nx-micronaut-maven/src/dep-graph/lookup-deps.ts @@ -0,0 +1,17 @@ +import { addProjectsAndDependencies } from '@jnxplus/maven'; +import { + Hasher, + ProjectGraph, + ProjectGraphBuilder, + ProjectGraphProcessorContext, +} from '@nx/devkit'; + +export function processProjectGraph( + graph: ProjectGraph, + context: ProjectGraphProcessorContext +): ProjectGraph { + const builder = new ProjectGraphBuilder(graph); + const hasher = new Hasher(graph, context.nxJsonConfiguration, {}); + addProjectsAndDependencies(builder, hasher, '@jnxplus/nx-micronaut-maven'); + return builder.getUpdatedProjectGraph(); +} diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/README.md b/packages/nx-micronaut-maven/src/generators/application/files/java/README.md new file mode 100644 index 000000000..3a199b958 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/README.md @@ -0,0 +1,10 @@ +## Micronaut 4.0.0-M2 Documentation + +- [User Guide](https://docs.micronaut.io/4.0.0-M2/guide/index.html) +- [API Reference](https://docs.micronaut.io/4.0.0-M2/api/index.html) +- [Configuration Reference](https://docs.micronaut.io/4.0.0-M2/guide/configurationreference.html) +- [Micronaut Guides](https://guides.micronaut.io/index.html) + +--- + +- [Micronaut Maven Plugin documentation](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/) diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/pom.xml__template__ b/packages/nx-micronaut-maven/src/generators/application/files/java/pom.xml__template__ new file mode 100644 index 000000000..cd9a085b5 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/pom.xml__template__ @@ -0,0 +1,102 @@ + + + 4.0.0 + <%= groupId %> + <%= projectName %> + <%= projectVersion %> + ${packaging} + <%= projectName %> + This project was generated with nx-micronaut-maven + + + <%= parentGroupId %> + <%= parentProjectName %> + <%= parentProjectVersion %> + <%= relativePath %> + + + + jar + netty + <%= packageName %>.Application + + + + + central + https://repo.maven.apache.org/maven2 + + + + + + io.micronaut + micronaut-http-server-netty + compile + + + io.micronaut + micronaut-jackson-databind + compile + + + ch.qos.logback + logback-classic + runtime + +<% if(configFormat === '.yml') { -%> + + org.yaml + snakeyaml + runtime + +<% } -%> + + io.micronaut + micronaut-http-client + test + + + io.micronaut.test + micronaut-test-junit5 + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + io.micronaut.maven + micronaut-maven-plugin + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + + + -Amicronaut.processing.group=com.example + -Amicronaut.processing.module=demo + + + + + + + diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/.gitkeep b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/Application.java b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/Application.java new file mode 100644 index 000000000..c62bcbf95 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/Application.java @@ -0,0 +1,10 @@ +package <%= packageName %>; + +import io.micronaut.runtime.Micronaut; + +public class Application { + + public static void main(String[] args) { + Micronaut.run(Application.class, args); + } +} \ No newline at end of file diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/HelloController.java b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/HelloController.java new file mode 100644 index 000000000..218a8d89f --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/java/__packageDirectory__/HelloController.java @@ -0,0 +1,15 @@ +package <%= packageName %>; + +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.Produces; + +@Controller("/hello") // <1> +public class HelloController { + @Get // <2> + @Produces(MediaType.TEXT_PLAIN) // <3> + public String index() { + return "Hello World"; // <4> + } +} diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/application__configFormat__ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/application__configFormat__ new file mode 100644 index 000000000..4e5b4677c --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/application__configFormat__ @@ -0,0 +1,20 @@ +<% if(configFormat === '.properties') { -%> +micronaut.application.name=<%= projectName %> +<% if(isCustomPort) { -%> +micronaut.server.port=<%= port %> +<% } -%> +netty.default.allocator.max-order=3 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + application: + name: <%= projectName %> +<% if(isCustomPort) { -%> + server: + port: <%= port %> +<% } -%> +netty: + default: + allocator: + max-order: 3 +<% } -%> diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/logback.xml b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/logback.xml new file mode 100644 index 000000000..44b79c40d --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/.gitkeep b/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/HelloControllerTest.java b/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/HelloControllerTest.java new file mode 100644 index 000000000..4c5b94a1e --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/HelloControllerTest.java @@ -0,0 +1,29 @@ +package <%= packageName %>; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import io.micronaut.http.HttpRequest; +import io.micronaut.http.client.HttpClient; +import io.micronaut.http.client.annotation.Client; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import org.junit.jupiter.api.Test; + +import jakarta.inject.Inject; + +@MicronautTest // <1> +public class HelloControllerTest { + + @Inject + @Client("/") // <2> + HttpClient client; + + @Test + public void testHello() { + HttpRequest request = HttpRequest.GET("/hello"); // <3> + String body = client.toBlocking().retrieve(request); + + assertNotNull(body); + assertEquals("Hello World", body); + } +} diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/__appClassName__Test.java b/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/__appClassName__Test.java new file mode 100644 index 000000000..dcba11634 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/java/__packageDirectory__/__appClassName__Test.java @@ -0,0 +1,21 @@ +package <%= packageName %>; + +import io.micronaut.runtime.EmbeddedApplication; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Assertions; + +import jakarta.inject.Inject; + +@MicronautTest +class <%= appClassName %>Test { + + @Inject + EmbeddedApplication application; + + @Test + void testItWorks() { + Assertions.assertTrue(application.isRunning()); + } + +} diff --git a/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/resources/application__configFormat__ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/resources/application__configFormat__ new file mode 100644 index 000000000..6370102ce --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/java/src/test/resources/application__configFormat__ @@ -0,0 +1,8 @@ +<% if(configFormat === '.properties') { -%> +micronaut.server.port=-1 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + server: + port: -1 +<% } -%> diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/README.md b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/README.md new file mode 100644 index 000000000..71ebd69f4 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/README.md @@ -0,0 +1,16 @@ +## Micronaut 4.0.0-M2 Documentation + +- [User Guide](https://docs.micronaut.io/4.0.0-M2/guide/index.html) +- [API Reference](https://docs.micronaut.io/4.0.0-M2/api/index.html) +- [Configuration Reference](https://docs.micronaut.io/4.0.0-M2/guide/configurationreference.html) +- [Micronaut Guides](https://guides.micronaut.io/index.html) + +--- + +- [Micronaut Maven Plugin documentation](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/) + +## Feature kapt documentation + +- [Micronaut Kotlin Annotation Processing (KAPT) documentation](https://docs.micronaut.io/snapshot/guide/#kapt) + +- [https://kotlinlang.org/docs/kapt.html](https://kotlinlang.org/docs/kapt.html) diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/pom.xml__template__ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/pom.xml__template__ new file mode 100644 index 000000000..457706e71 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/pom.xml__template__ @@ -0,0 +1,239 @@ + + + 4.0.0 + <%= groupId %> + <%= projectName %> + <%= projectVersion %> + ${packaging} + <%= projectName %> + This project was generated with nx-micronaut-maven + + + <%= parentGroupId %> + <%= parentProjectName %> + <%= parentProjectVersion %> + <%= relativePath %> + + + + jar + netty + <%= packageName %>.ApplicationKt + + + + + central + https://repo.maven.apache.org/maven2 + + + + + + io.micronaut + micronaut-http-server-netty + compile + + + io.micronaut + micronaut-jackson-databind + compile + + + io.micronaut.kotlin + micronaut-kotlin-runtime + compile + + + org.jetbrains.kotlin + kotlin-reflect + ${kotlinVersion} + compile + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlinVersion} + compile + + + ch.qos.logback + logback-classic + runtime + + <% if(configFormat === '.yml') { -%> + + org.yaml + snakeyaml + runtime + + <% } -%> + + com.fasterxml.jackson.module + jackson-module-kotlin + runtime + + + io.micronaut + micronaut-http-client + test + + + io.micronaut.test + micronaut-test-junit5 + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + io.micronaut.maven + micronaut-maven-plugin + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlinVersion} + + ${jdk.version} + + all-open + + + + + + + + kapt + + kapt + + + + ${project.basedir}/src/main/kotlin + + + + io.micronaut + micronaut-inject-java + ${micronaut.core.version} + + + io.micronaut + micronaut-graal + ${micronaut.core.version} + + + + micronaut.processing.group=com.example + micronaut.processing.module=demoKotlin + + + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + + + + + test-kapt + + test-kapt + + + + ${project.basedir}/src/test/kotlin + + + + io.micronaut + micronaut-inject-java + ${micronaut.core.version} + + + io.micronaut + micronaut-graal + ${micronaut.core.version} + + + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + ${project.basedir}/target/generated-sources/kapt/test + + + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlinVersion} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + none + ${jdk.version} + ${jdk.version} + + + + default-compile + none + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + + + + + diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/.gitkeep b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/Application.kt b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/Application.kt new file mode 100644 index 000000000..813480268 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/Application.kt @@ -0,0 +1,7 @@ +package <%= packageName %> + +import io.micronaut.runtime.Micronaut.run +fun main(args: Array) { + run(*args) +} + diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/HelloController.kt b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/HelloController.kt new file mode 100644 index 000000000..63d28d162 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/HelloController.kt @@ -0,0 +1,14 @@ +package <%= packageName %> + +import io.micronaut.http.MediaType +import io.micronaut.http.annotation.Controller +import io.micronaut.http.annotation.Get +import io.micronaut.http.annotation.Produces + +@Controller("/hello") +class HelloController { + + @Get + @Produces(MediaType.TEXT_PLAIN) + fun index() = "Hello World" +} \ No newline at end of file diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/application__configFormat__ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/application__configFormat__ new file mode 100644 index 000000000..a2a24dac0 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/application__configFormat__ @@ -0,0 +1,21 @@ +<% if(configFormat === '.properties') { -%> +micronaut.application.name=<%= projectName %> +<% if(isCustomPort) { -%> +micronaut.server.port=<%= port %> +<% } -%> +netty.default.allocator.max-order=3 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + application: + name: <%= projectName %> +<% if(isCustomPort) { -%> + server: + port: <%= port %> +<% } -%> +netty: + default: + allocator: + max-order: 3 +<% } -%> + \ No newline at end of file diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/logback.xml b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/logback.xml new file mode 100644 index 000000000..44b79c40d --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/.gitkeep b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/HelloControllerTest.kt b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/HelloControllerTest.kt new file mode 100644 index 000000000..48ae65edf --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/HelloControllerTest.kt @@ -0,0 +1,21 @@ +package <%= packageName %> + +import io.micronaut.http.HttpRequest +import io.micronaut.http.client.HttpClient +import io.micronaut.http.client.annotation.Client +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Test + +@MicronautTest +class HelloControllerTest(@Client("/") val client: HttpClient) { + + @Test + fun testHello() { + val request: HttpRequest = HttpRequest.GET("/hello") + val body = client.toBlocking().retrieve(request) + assertNotNull(body) + assertEquals("Hello World", body) + } +} \ No newline at end of file diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/__appClassName__Test.kt b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/__appClassName__Test.kt new file mode 100644 index 000000000..fa650f93a --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/__appClassName__Test.kt @@ -0,0 +1,20 @@ +package <%= packageName %> + +import io.micronaut.runtime.EmbeddedApplication +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import jakarta.inject.Inject + +@MicronautTest +class <%= appClassName %>Test { + + @Inject + lateinit var application: EmbeddedApplication<*> + + @Test + fun testItWorks() { + Assertions.assertTrue(application.isRunning) + } + +} diff --git a/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/resources/application__configFormat__ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/resources/application__configFormat__ new file mode 100644 index 000000000..6370102ce --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/files/kotlin/src/test/resources/application__configFormat__ @@ -0,0 +1,8 @@ +<% if(configFormat === '.properties') { -%> +micronaut.server.port=-1 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + server: + port: -1 +<% } -%> diff --git a/packages/nx-micronaut-maven/src/generators/application/generator.spec.ts b/packages/nx-micronaut-maven/src/generators/application/generator.spec.ts new file mode 100644 index 000000000..f95c9d91f --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/generator.spec.ts @@ -0,0 +1,41 @@ +import { readProjectConfiguration, Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { NxMicronautMavenAppGeneratorSchema } from './schema'; +import generator from './generator'; + +describe('application generator', () => { + let appTree: Tree; + const options: NxMicronautMavenAppGeneratorSchema = { + name: 'test', + language: 'java', + groupId: 'com.example', + projectVersion: '0.0.1-SNAPSHOT', + configFormat: '.yml', + parentProject: '', + port: 8080, + }; + + beforeEach(() => { + jest.setTimeout(60000); + appTree = createTreeWithEmptyWorkspace(); + appTree.write( + './pom.xml', + ` + com.example + micronaut-multi-module + 0.0.1-SNAPSHOT + + 1.7.22 + + + ` + ); + }); + + //TODO this test don't work on macOS + xit('should run successfully', async () => { + await generator(appTree, options); + const config = readProjectConfiguration(appTree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/packages/nx-micronaut-maven/src/generators/application/generator.ts b/packages/nx-micronaut-maven/src/generators/application/generator.ts new file mode 100644 index 000000000..9674e3ea8 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/generator.ts @@ -0,0 +1,257 @@ +import { LinterType, normalizeName } from '@jnxplus/common'; +import { addProjectToAggregator, readXmlTree } from '@jnxplus/maven'; +import { + addProjectConfiguration, + formatFiles, + generateFiles, + getWorkspaceLayout, + joinPathFragments, + names, + offsetFromRoot, + readProjectConfiguration, + Tree, +} from '@nx/devkit'; +import * as path from 'path'; +import { NxMicronautMavenAppGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxMicronautMavenAppGeneratorSchema { + projectName: string; + projectRoot: string; + projectDirectory: string; + parsedTags: string[]; + appClassName: string; + packageName: string; + packageDirectory: string; + linter: LinterType; + parentGroupId: string; + parentProjectName: string; + parentProjectVersion: string; + relativePath: string; + //quarkusVersion: string; + parentProjectRoot: string; + isCustomPort: boolean; +} + +function normalizeOptions( + tree: Tree, + options: NxMicronautMavenAppGeneratorSchema +): NormalizedSchema { + const simpleProjectName = names(normalizeName(options.name)).fileName; + + let projectName: string; + if (options.simpleName) { + projectName = simpleProjectName; + } else { + projectName = options.directory + ? `${normalizeName( + names(options.directory).fileName + )}-${simpleProjectName}` + : simpleProjectName; + } + + const projectDirectory = options.directory + ? `${names(options.directory).fileName}/${simpleProjectName}` + : simpleProjectName; + const projectRoot = `${getWorkspaceLayout(tree).appsDir}/${projectDirectory}`; + const parsedTags = options.tags + ? options.tags.split(',').map((s) => s.trim()) + : []; + + const appClassName = `${names(projectName).className}Application`; + + let packageName: string; + if (options.simplePackageName) { + packageName = `${options.groupId}.${names( + simpleProjectName + ).className.toLocaleLowerCase()}`.replace(new RegExp(/-/, 'g'), ''); + } else { + packageName = `${options.groupId}.${ + options.directory + ? `${names(options.directory).fileName.replace( + new RegExp(/\//, 'g'), + '.' + )}.${names(simpleProjectName).className.toLocaleLowerCase()}` + : names(simpleProjectName).className.toLocaleLowerCase() + }`.replace(new RegExp(/-/, 'g'), ''); + } + + const packageDirectory = packageName.replace(new RegExp(/\./, 'g'), '/'); + + const linter = options.language === 'java' ? 'checkstyle' : 'ktlint'; + + const parentProjectRoot = options.parentProject + ? readProjectConfiguration(tree, options.parentProject).root + : ''; + + const parentProjectPomPath = path.join(parentProjectRoot, 'pom.xml'); + + const pomXmlContent = readXmlTree(tree, parentProjectPomPath); + const relativePath = path + .relative(projectRoot, parentProjectRoot) + .replace(new RegExp(/\\/, 'g'), '/'); + + const parentGroupId = + pomXmlContent?.childNamed('groupId')?.val || 'parentGroupId'; + const parentProjectName = + pomXmlContent?.childNamed('artifactId')?.val || 'parentProjectName'; + const parentProjectVersion = + pomXmlContent?.childNamed('version')?.val || 'parentProjectVersion'; + + // const rootPomXmlContent = readXmlTree(tree, 'pom.xml'); + // const quarkusVersion = + // rootPomXmlContent + // ?.childNamed('properties') + // ?.childNamed('quarkus.platform.version')?.val || 'quarkusVersion'; + + const isCustomPort = !!options.port && +options.port !== 8080; + + return { + ...options, + projectName, + projectRoot, + projectDirectory, + parsedTags, + appClassName, + packageName, + packageDirectory, + linter, + parentGroupId, + parentProjectName, + parentProjectVersion, + relativePath, + //quarkusVersion, + parentProjectRoot, + isCustomPort, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + ...names(options.name), + offsetFromRoot: offsetFromRoot(options.projectRoot), + template: '', + }; + generateFiles( + tree, + path.join(__dirname, 'files', options.language), + options.projectRoot, + templateOptions + ); + + if (options.minimal) { + const fileExtension = options.language === 'java' ? 'java' : 'kt'; + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/main/${options.language}/${options.packageDirectory}/HelloController.${fileExtension}` + ) + ); + + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/test/${options.language}/${options.packageDirectory}/HelloControllerTest.${fileExtension}` + ) + ); + } else { + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/main/${options.language}/.gitkeep` + ) + ); + + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/test/${options.language}/.gitkeep` + ) + ); + } +} + +export default async function ( + tree: Tree, + options: NxMicronautMavenAppGeneratorSchema +) { + const normalizedOptions = normalizeOptions(tree, options); + + if (options.language === 'java') { + addProjectConfiguration(tree, normalizedOptions.projectName, { + root: normalizedOptions.projectRoot, + projectType: 'application', + sourceRoot: `${normalizedOptions.projectRoot}/src`, + targets: { + build: { + executor: '@jnxplus/nx-micronaut-maven:build', + outputs: [`${normalizedOptions.projectRoot}/target`], + }, + 'build-image': { + executor: '@jnxplus/nx-micronaut-maven:build-image', + }, + serve: { + executor: '@jnxplus/nx-micronaut-maven:serve', + dependsOn: ['build'], + }, + lint: { + executor: '@jnxplus/nx-micronaut-maven:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-maven:test', + dependsOn: ['build'], + }, + 'integration-test': { + executor: '@jnxplus/nx-micronaut-maven:integration-test', + }, + }, + tags: normalizedOptions.parsedTags, + }); + } else { + addProjectConfiguration(tree, normalizedOptions.projectName, { + root: normalizedOptions.projectRoot, + projectType: 'application', + sourceRoot: `${normalizedOptions.projectRoot}/src`, + targets: { + build: { + executor: '@jnxplus/nx-micronaut-maven:build', + outputs: [`${normalizedOptions.projectRoot}/target`], + }, + 'build-image': { + executor: '@jnxplus/nx-micronaut-maven:build-image', + }, + serve: { + executor: '@jnxplus/nx-micronaut-maven:serve', + dependsOn: ['build'], + }, + lint: { + executor: '@jnxplus/nx-micronaut-maven:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-maven:test', + dependsOn: ['build'], + }, + 'integration-test': { + executor: '@jnxplus/nx-micronaut-maven:integration-test', + }, + ktformat: { + executor: '@jnxplus/nx-micronaut-maven:ktformat', + }, + }, + tags: normalizedOptions.parsedTags, + }); + } + + addFiles(tree, normalizedOptions); + addProjectToAggregator(tree, { + projectRoot: normalizedOptions.projectRoot, + aggregatorProject: normalizedOptions.parentProject, + }); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-maven/src/generators/application/schema.d.ts b/packages/nx-micronaut-maven/src/generators/application/schema.d.ts new file mode 100644 index 000000000..a5c60566c --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/schema.d.ts @@ -0,0 +1,16 @@ +import { LanguageType } from '@jnxplus/common'; + +export interface NxMicronautMavenAppGeneratorSchema { + name: string; + tags?: string; + directory?: string; + simpleName?: boolean; + simplePackageName?: boolean; + language: LanguageType; + groupId: string; + projectVersion: string; + configFormat: '.properties' | '.yml'; + parentProject?: string; + minimal?: boolean; + port?: string | number; +} diff --git a/packages/nx-micronaut-maven/src/generators/application/schema.json b/packages/nx-micronaut-maven/src/generators/application/schema.json new file mode 100644 index 000000000..97bd81060 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/application/schema.json @@ -0,0 +1,110 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxMicronautMavenApp", + "title": "Create an application", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "What name would you like to use?", + "pattern": "^[a-zA-Z].*$" + }, + "tags": { + "type": "string", + "description": "Add tags to the project (used for linting)", + "alias": "t" + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed", + "alias": "dir" + }, + "simpleName": { + "description": "Don't include the directory in the app name", + "type": "boolean", + "default": false + }, + "simplePackageName": { + "description": "Don't include the directory in the package name", + "type": "boolean", + "default": false + }, + "language": { + "description": "Language of the project", + "type": "string", + "default": "java", + "x-prompt": { + "message": "Which language would you like to use?", + "type": "list", + "items": [ + { + "value": "java", + "label": "Java" + }, + { + "value": "kotlin", + "label": "Kotlin" + } + ] + } + }, + "groupId": { + "type": "string", + "default": "com.example", + "x-prompt": "What groupId would you like to use?" + }, + "projectVersion": { + "type": "string", + "default": "0.0.1-SNAPSHOT", + "description": "Version of the project to generate", + "alias": "v", + "x-prompt": "What project version would you like to use?" + }, + "configFormat": { + "description": "Configuration format of the project", + "type": "string", + "default": ".properties", + "x-prompt": { + "message": "Which configuration format would you like to use?", + "type": "list", + "items": [ + { + "value": ".properties", + "label": "Properties" + }, + { + "value": ".yml", + "label": "Yaml" + } + ] + } + }, + "parentProject": { + "type": "string", + "description": "ArtifactId of the parent project or leave it blank for the root project" + }, + "minimal": { + "description": "Generate an app with a minimal setup", + "type": "boolean", + "default": false + }, + "port": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ], + "default": 8080, + "description": "Port to start the server at. Default is 8080." + } + }, + "required": ["name", "language", "groupId", "projectVersion", "configFormat"] +} diff --git a/packages/nx-micronaut-maven/src/generators/init/files/linters/checkstyle.xml b/packages/nx-micronaut-maven/src/generators/init/files/linters/checkstyle.xml new file mode 100644 index 000000000..6e8881117 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/init/files/linters/checkstyle.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/nx-micronaut-maven/src/generators/init/files/linters/pmd.xml b/packages/nx-micronaut-maven/src/generators/init/files/linters/pmd.xml new file mode 100644 index 000000000..9e5e30b29 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/init/files/linters/pmd.xml @@ -0,0 +1,38 @@ + + + + Every Java Rule in PMD + + + + .*/ant/java/EncodingTestClass.java + .*/net/sourceforge/pmd/cpd/badandgood/BadFile.java + + + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/assert_test5.java + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/assert_test5_a.java + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/assert_test7.java + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/jdk14_enum.java + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/jdk9_invalid_identifier.java + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java10/LocalVariableTypeInference_varAsAnnotationName.java + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java10/LocalVariableTypeInference_varAsEnumName.java + .*/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java10/LocalVariableTypeInference_varAsTypeIdentifier.java + + + .*/net/sourceforge/pmd/lang/java/ast/InfiniteLoopInLookahead.java + + + + + + + + + + + \ No newline at end of file diff --git a/packages/nx-micronaut-maven/src/generators/init/files/maven/config/pom.xml__template__ b/packages/nx-micronaut-maven/src/generators/init/files/maven/config/pom.xml__template__ new file mode 100644 index 000000000..dd9ed1a12 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/init/files/maven/config/pom.xml__template__ @@ -0,0 +1,30 @@ + + + 4.0.0 + <%= groupId %> + <%= parentProjectName %> + <%= parentProjectVersion %> + pom + + + io.micronaut.platform + micronaut-parent + <%= micronautVersion %> + + + + <%= javaVersion %> + <%= javaVersion %> + <%= micronautVersion %> + <%= javaVersion %> + <%= kotlinVersion %> + <%= kotlinVersion %> + <%= checkstyleVersion %> + <%= ktlintVersion %> + + + + + + diff --git a/packages/nx-micronaut-maven/src/generators/init/generator.spec.ts b/packages/nx-micronaut-maven/src/generators/init/generator.spec.ts new file mode 100644 index 000000000..7cb31036b --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/init/generator.spec.ts @@ -0,0 +1,26 @@ +import { Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import generator from './generator'; +import { NxMicronautMavenGeneratorSchema } from './schema'; + +describe('init generator', () => { + let appTree: Tree; + const options: NxMicronautMavenGeneratorSchema = { + javaVersion: 17, + groupId: 'com.example', + parentProjectName: 'test-quarkus-multiproject', + parentProjectVersion: '1.0.0', + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write('./.gitignore', ''); + appTree.write('./.prettierignore', ''); + }); + + xit('should run successfully', async () => { + await generator(appTree, options); + const pomXmlExists = appTree.exists('pom.xml'); + expect(pomXmlExists).toBeTruthy(); + }); +}); diff --git a/packages/nx-micronaut-maven/src/generators/init/generator.ts b/packages/nx-micronaut-maven/src/generators/init/generator.ts new file mode 100644 index 000000000..d1793acf1 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/init/generator.ts @@ -0,0 +1,82 @@ +import { + checkstyleVersion, + ktlintVersion, + micronautKotlinVersion, + micronautVersion, + updateNxJson, +} from '@jnxplus/common'; +import { + addOrUpdateGitattributes, + addOrUpdatePrettierIgnore, + addOrUpdatePrettierRc, + updateGitIgnore, +} from '@jnxplus/maven'; +import { Tree, formatFiles, generateFiles, offsetFromRoot } from '@nx/devkit'; +import * as path from 'path'; +import { NxMicronautMavenGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxMicronautMavenGeneratorSchema { + dot: string; + kotlinVersion: string; + micronautVersion: string; + checkstyleVersion: string; + ktlintVersion: string; +} + +function normalizeOptions( + tree: Tree, + options: NxMicronautMavenGeneratorSchema +): NormalizedSchema { + const dot = '.'; + + return { + ...options, + dot, + kotlinVersion: micronautKotlinVersion, + micronautVersion, + checkstyleVersion, + ktlintVersion, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + offsetFromRoot: offsetFromRoot(tree.root), + template: '', + }; + generateFiles( + tree, + path.join(__dirname, 'files', 'maven', 'wrapper'), + '', + templateOptions + ); + generateFiles( + tree, + path.join(__dirname, 'files', 'maven', 'config'), + '', + templateOptions + ); + generateFiles( + tree, + path.join(__dirname, 'files', 'linters'), + 'tools/linters', + templateOptions + ); +} + +export default async function ( + tree: Tree, + options: NxMicronautMavenGeneratorSchema +) { + const normalizedOptions = normalizeOptions(tree, options); + addFiles(tree, normalizedOptions); + updateNxJson(tree, '@jnxplus/nx-micronaut-maven'); + updateGitIgnore(tree); + addOrUpdatePrettierRc(tree); + addOrUpdatePrettierIgnore(tree); + addOrUpdateGitattributes(tree); + tree.changePermissions('mvnw', '755'); + tree.changePermissions('mvnw.cmd', '755'); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-maven/src/generators/init/schema.d.ts b/packages/nx-micronaut-maven/src/generators/init/schema.d.ts new file mode 100644 index 000000000..960752c60 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/init/schema.d.ts @@ -0,0 +1,6 @@ +export interface NxMicronautMavenGeneratorSchema { + javaVersion: string | number; + groupId: string; + parentProjectName: string; + parentProjectVersion: string; +} diff --git a/packages/nx-micronaut-maven/src/generators/init/schema.json b/packages/nx-micronaut-maven/src/generators/init/schema.json new file mode 100644 index 000000000..2ba5e2f70 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/init/schema.json @@ -0,0 +1,58 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxMicronautMavenInit", + "title": "Init", + "type": "object", + "properties": { + "javaVersion": { + "description": "Java version", + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ], + "default": "17", + "x-prompt": { + "message": "Which version of Java would you like to use?", + "type": "list", + "items": [ + { + "value": "19", + "label": "19" + }, + { + "value": "17", + "label": "17" + } + ] + } + }, + "groupId": { + "type": "string", + "default": "com.example", + "x-prompt": "What groupId would you like to use?" + }, + "parentProjectName": { + "type": "string", + "default": "micronaut-parent-project", + "x-prompt": "What parentProjectName would you like to use?", + "pattern": "^[a-zA-Z].*$" + }, + "parentProjectVersion": { + "type": "string", + "default": "0.0.1-SNAPSHOT", + "description": "Version of the project to generate", + "alias": "v", + "x-prompt": "What project version would you like to use?" + } + }, + "required": [ + "javaVersion", + "groupId", + "parentProjectName", + "parentProjectVersion" + ] +} diff --git a/packages/nx-micronaut-maven/src/generators/library/files/java/pom.xml__template__ b/packages/nx-micronaut-maven/src/generators/library/files/java/pom.xml__template__ new file mode 100644 index 000000000..0e3b74d36 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/files/java/pom.xml__template__ @@ -0,0 +1,39 @@ + + + 4.0.0 + + <%= parentGroupId %> + <%= parentProjectName %> + <%= parentProjectVersion %> + <%= relativePath %> + + <%= groupId %> + <%= projectName %> + <%= projectVersion %> + <%= projectName %> + This project was generated with nx-micronaut-maven + + + + io.micronaut + micronaut-inject-java + + + io.micronaut.test + micronaut-test-junit5 + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + diff --git a/packages/nx-micronaut-maven/src/generators/library/files/java/src/main/java/.gitkeep b/packages/nx-micronaut-maven/src/generators/library/files/java/src/main/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/library/files/java/src/main/java/__packageDirectory__/HelloService.java b/packages/nx-micronaut-maven/src/generators/library/files/java/src/main/java/__packageDirectory__/HelloService.java new file mode 100644 index 000000000..554edeccb --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/files/java/src/main/java/__packageDirectory__/HelloService.java @@ -0,0 +1,11 @@ +package <%= packageName %>; + +import jakarta.inject.Singleton; + +@Singleton +public class HelloService { + + public String greeting() { + return "Hello World"; + } +} diff --git a/packages/nx-micronaut-maven/src/generators/library/files/java/src/test/java/.gitkeep b/packages/nx-micronaut-maven/src/generators/library/files/java/src/test/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/library/files/java/src/test/java/__packageDirectory__/HelloServiceTest.java b/packages/nx-micronaut-maven/src/generators/library/files/java/src/test/java/__packageDirectory__/HelloServiceTest.java new file mode 100644 index 000000000..f84f85be9 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/files/java/src/test/java/__packageDirectory__/HelloServiceTest.java @@ -0,0 +1,20 @@ +package <%= packageName %>; + +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; + +@MicronautTest +public class HelloServiceTest { + + @Inject + HelloService service; + + @Test + public void testGreetingService() { + Assertions.assertEquals("Hello World", service.greeting()); + } +} diff --git a/packages/nx-micronaut-maven/src/generators/library/files/kotlin/pom.xml__template__ b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/pom.xml__template__ new file mode 100644 index 000000000..f02b79ebe --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/pom.xml__template__ @@ -0,0 +1,203 @@ + + + 4.0.0 + + <%= parentGroupId %> + <%= parentProjectName %> + <%= parentProjectVersion %> + <%= relativePath %> + + <%= groupId %> + <%= projectName %> + <%= projectVersion %> + <%= projectName %> + This project was generated with nx-micronaut-maven + + + + central + https://repo.maven.apache.org/maven2 + + + + + + + io.micronaut + micronaut-inject-java + + + + org.jetbrains.kotlin + kotlin-reflect + ${kotlinVersion} + compile + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlinVersion} + compile + + + + io.micronaut.test + micronaut-test-junit5 + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlinVersion} + + ${jdk.version} + + all-open + + + + + + + + kapt + + kapt + + + + ${project.basedir}/src/main/kotlin + + + + io.micronaut + micronaut-inject-java + ${micronaut.core.version} + + + io.micronaut + micronaut-graal + ${micronaut.core.version} + + + + + micronaut.processing.group=com.example + + + micronaut.processing.module=demo + + + + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + + + + + test-kapt + + test-kapt + + + + ${project.basedir}/src/test/kotlin + + + + io.micronaut + micronaut-inject-java + ${micronaut.core.version} + + + io.micronaut + micronaut-graal + ${micronaut.core.version} + + + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + + ${project.basedir}/target/generated-sources/kapt/test + + + + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlinVersion} + + + + + org.apache.maven.plugins + maven-compiler-plugin + + none + ${jdk.version} + ${jdk.version} + + + + default-compile + none + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + + + + diff --git a/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/main/kotlin/.gitkeep b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/main/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/main/kotlin/__packageDirectory__/HelloService.kt b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/main/kotlin/__packageDirectory__/HelloService.kt new file mode 100644 index 000000000..09c3d45b4 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/main/kotlin/__packageDirectory__/HelloService.kt @@ -0,0 +1,11 @@ +package <%= packageName %> + +import jakarta.inject.Singleton + +@Singleton +class HelloService { + + fun greeting():String { + return "Hello World" + } +} diff --git a/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/test/kotlin/.gitkeep b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/test/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/test/kotlin/__packageDirectory__/HelloServiceTest.kt b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/test/kotlin/__packageDirectory__/HelloServiceTest.kt new file mode 100644 index 000000000..e65a5650b --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/files/kotlin/src/test/kotlin/__packageDirectory__/HelloServiceTest.kt @@ -0,0 +1,25 @@ +package <%= packageName %> + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject + + +@MicronautTest +class HelloServiceTest { + + + @Inject + lateinit var service: HelloService + + + @Test + fun `Should return Hello World`() { + println(">> Should return Hello World") + Assertions.assertTrue(service.greeting().contains("Hello World")); + } + + +} + diff --git a/packages/nx-micronaut-maven/src/generators/library/generator.spec.ts b/packages/nx-micronaut-maven/src/generators/library/generator.spec.ts new file mode 100644 index 000000000..ba60e434e --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/generator.spec.ts @@ -0,0 +1,30 @@ +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { Tree, readProjectConfiguration } from '@nx/devkit'; + +import generator from './generator'; +import { NxQuarkusMavenLibGeneratorSchema } from './schema'; + +describe('library generator', () => { + let appTree: Tree; + const options: NxQuarkusMavenLibGeneratorSchema = { + name: 'test', + language: 'java', + groupId: 'com.example', + projectVersion: '0.0.1-SNAPSHOT', + parentProject: '', + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write( + './pom.xml', + 'com.examplequarkus-multi-module0.0.1-SNAPSHOT' + ); + }); + + it('should run successfully', async () => { + await generator(appTree, options); + const config = readProjectConfiguration(appTree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/packages/nx-micronaut-maven/src/generators/library/generator.ts b/packages/nx-micronaut-maven/src/generators/library/generator.ts new file mode 100644 index 000000000..271613d5f --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/generator.ts @@ -0,0 +1,232 @@ +import { LinterType, normalizeName } from '@jnxplus/common'; +import { + addLibraryToProjects, + addProjectToAggregator, + readXmlTree, +} from '@jnxplus/maven'; +import { + addProjectConfiguration, + formatFiles, + generateFiles, + getWorkspaceLayout, + joinPathFragments, + names, + offsetFromRoot, + readProjectConfiguration, + Tree, +} from '@nx/devkit'; +import * as path from 'path'; +import { NxQuarkusMavenLibGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxQuarkusMavenLibGeneratorSchema { + projectName: string; + projectRoot: string; + projectDirectory: string; + parsedTags: string[]; + packageName: string; + packageDirectory: string; + parsedProjects: string[]; + linter?: LinterType; + parentGroupId: string; + parentProjectName: string; + parentProjectVersion: string; + relativePath: string; + parentProjectRoot: string; +} + +function normalizeOptions( + tree: Tree, + options: NxQuarkusMavenLibGeneratorSchema +): NormalizedSchema { + const simpleProjectName = names(normalizeName(options.name)).fileName; + + let projectName: string; + if (options.simpleName) { + projectName = simpleProjectName; + } else { + projectName = options.directory + ? `${normalizeName( + names(options.directory).fileName + )}-${simpleProjectName}` + : simpleProjectName; + } + + const projectDirectory = options.directory + ? `${names(options.directory).fileName}/${simpleProjectName}` + : simpleProjectName; + const projectRoot = `${getWorkspaceLayout(tree).libsDir}/${projectDirectory}`; + const parsedTags = options.tags + ? options.tags.split(',').map((s) => s.trim()) + : []; + + let packageName: string; + if (options.simplePackageName) { + packageName = `${options.groupId}.${names( + simpleProjectName + ).className.toLocaleLowerCase()}`.replace(new RegExp(/-/, 'g'), ''); + } else { + packageName = `${options.groupId}.${ + options.directory + ? `${names(options.directory).fileName.replace( + new RegExp(/\//, 'g'), + '.' + )}.${names(simpleProjectName).className.toLocaleLowerCase()}` + : names(simpleProjectName).className.toLocaleLowerCase() + }`.replace(new RegExp(/-/, 'g'), ''); + } + + const packageDirectory = packageName.replace(new RegExp(/\./, 'g'), '/'); + + const parsedProjects = options.projects + ? options.projects.split(',').map((s) => s.trim()) + : []; + + const linter = options.language === 'java' ? 'checkstyle' : 'ktlint'; + + const parentProjectRoot = options.parentProject + ? readProjectConfiguration(tree, options.parentProject).root + : ''; + + const parentProjectPomPath = path.join(parentProjectRoot, 'pom.xml'); + + const pomXmlContent = readXmlTree(tree, parentProjectPomPath); + const relativePath = path + .relative(projectRoot, parentProjectRoot) + .replace(new RegExp(/\\/, 'g'), '/'); + + const parentGroupId = + pomXmlContent?.childNamed('groupId')?.val || 'parentGroupId'; + const parentProjectName = + pomXmlContent?.childNamed('artifactId')?.val || 'parentProjectName'; + const parentProjectVersion = + pomXmlContent?.childNamed('version')?.val || 'parentProjectVersion'; + + return { + ...options, + projectName, + projectRoot, + projectDirectory, + parsedTags, + packageName, + packageDirectory, + parsedProjects, + linter, + parentGroupId, + parentProjectName, + parentProjectVersion, + relativePath, + parentProjectRoot, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + ...names(options.name), + offsetFromRoot: offsetFromRoot(options.projectRoot), + template: '', + }; + generateFiles( + tree, + path.join(__dirname, 'files', options.language), + options.projectRoot, + templateOptions + ); + + if (options.skipStarterCode) { + const fileExtension = options.language === 'java' ? 'java' : 'kt'; + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/main/${options.language}/${options.packageDirectory}/HelloService.${fileExtension}` + ) + ); + + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/test/${options.language}/${options.packageDirectory}/HelloServiceTest.${fileExtension}` + ) + ); + } else { + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/main/${options.language}/.gitkeep` + ) + ); + + tree.delete( + joinPathFragments( + options.projectRoot, + `/src/test/${options.language}/.gitkeep` + ) + ); + } +} + +export default async function ( + tree: Tree, + options: NxQuarkusMavenLibGeneratorSchema +) { + const normalizedOptions = normalizeOptions(tree, options); + + if (options.language === 'java') { + addProjectConfiguration(tree, normalizedOptions.projectName, { + root: normalizedOptions.projectRoot, + projectType: 'library', + sourceRoot: `${normalizedOptions.projectRoot}/src`, + targets: { + build: { + executor: '@jnxplus/nx-micronaut-maven:build', + outputs: [`${normalizedOptions.projectRoot}/target`], + }, + lint: { + executor: '@jnxplus/nx-micronaut-maven:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-maven:test', + dependsOn: ['build'], + }, + }, + tags: normalizedOptions.parsedTags, + }); + } else { + addProjectConfiguration(tree, normalizedOptions.projectName, { + root: normalizedOptions.projectRoot, + projectType: 'library', + sourceRoot: `${normalizedOptions.projectRoot}/src`, + targets: { + build: { + executor: '@jnxplus/nx-micronaut-maven:build', + outputs: [`${normalizedOptions.projectRoot}/target`], + }, + lint: { + executor: '@jnxplus/nx-micronaut-maven:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-maven:test', + dependsOn: ['build'], + }, + ktformat: { + executor: '@jnxplus/nx-micronaut-maven:ktformat', + }, + }, + tags: normalizedOptions.parsedTags, + }); + } + + addFiles(tree, normalizedOptions); + addProjectToAggregator(tree, { + projectRoot: normalizedOptions.projectRoot, + aggregatorProject: normalizedOptions.parentProject, + }); + addLibraryToProjects(tree, normalizedOptions); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-maven/src/generators/library/schema.d.ts b/packages/nx-micronaut-maven/src/generators/library/schema.d.ts new file mode 100644 index 000000000..6891da312 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/schema.d.ts @@ -0,0 +1,15 @@ +import { LanguageType } from '@jnxplus/common'; + +export interface NxQuarkusMavenLibGeneratorSchema { + name: string; + tags?: string; + directory?: string; + simpleName?: boolean; + simplePackageName?: boolean; + language: LanguageType; + groupId: string; + projectVersion: string; + parentProject?: string; + projects?: string; + skipStarterCode?: boolean; +} diff --git a/packages/nx-micronaut-maven/src/generators/library/schema.json b/packages/nx-micronaut-maven/src/generators/library/schema.json new file mode 100644 index 000000000..f9f028a49 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/library/schema.json @@ -0,0 +1,83 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxQuarkusMavenLib", + "title": "Create a library", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "What name would you like to use?", + "pattern": "^[a-zA-Z].*$" + }, + "tags": { + "type": "string", + "description": "Add tags to the project (used for linting)", + "alias": "t" + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed", + "alias": "dir" + }, + "simpleName": { + "description": "Don't include the directory in the lib name", + "type": "boolean", + "default": false + }, + "simplePackageName": { + "description": "Don't include the directory in the package name", + "type": "boolean", + "default": false + }, + "language": { + "description": "Language of the project", + "type": "string", + "default": "java", + "x-prompt": { + "message": "Which language would you like to use?", + "type": "list", + "items": [ + { + "value": "java", + "label": "Java" + }, + { + "value": "kotlin", + "label": "Kotlin" + } + ] + } + }, + "groupId": { + "type": "string", + "default": "com.example", + "x-prompt": "What groupId would you like to use?" + }, + "projectVersion": { + "type": "string", + "default": "0.0.1-SNAPSHOT", + "description": "Version of the project to generate", + "alias": "v", + "x-prompt": "What project version would you like to use?" + }, + "parentProject": { + "type": "string", + "description": "ArtifactId of the parent project or leave it blank for the root project" + }, + "projects": { + "type": "string", + "description": "Projects where the library should be added (comma delimited)" + }, + "skipStarterCode": { + "description": "Skip starter code", + "type": "boolean", + "default": false + } + }, + "required": ["name", "language", "groupId", "projectVersion"] +} diff --git a/packages/nx-micronaut-maven/src/generators/migrate/generator.spec.ts b/packages/nx-micronaut-maven/src/generators/migrate/generator.spec.ts new file mode 100644 index 000000000..ee0edd084 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/migrate/generator.spec.ts @@ -0,0 +1,26 @@ +import { Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import generator from './generator'; +import { NxQuarkusMavenMigrateGeneratorSchema } from './schema'; + +describe('migrate generator', () => { + let appTree: Tree; + const options: NxQuarkusMavenMigrateGeneratorSchema = { + javaVersion: '17', + groupId: 'com.example', + parentProjectName: 'test-quarkus-multiproject', + parentProjectVersion: '1.0.0', + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write('./.gitignore', ''); + appTree.write('./.prettierignore', ''); + }); + + xit('should run successfully', async () => { + await generator(appTree, options); + const mvnwExists = appTree.exists('mvnw'); + expect(mvnwExists).toBeTruthy(); + }); +}); diff --git a/packages/nx-micronaut-maven/src/generators/migrate/generator.ts b/packages/nx-micronaut-maven/src/generators/migrate/generator.ts new file mode 100644 index 000000000..8357b8bb1 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/migrate/generator.ts @@ -0,0 +1,44 @@ +import { formatFiles, generateFiles, offsetFromRoot, Tree } from '@nx/devkit'; +import * as path from 'path'; +import { NxQuarkusMavenMigrateGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxQuarkusMavenMigrateGeneratorSchema { + dot: string; +} + +function normalizeOptions( + tree: Tree, + options: NxQuarkusMavenMigrateGeneratorSchema +): NormalizedSchema { + const dot = '.'; + + return { + ...options, + dot, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + offsetFromRoot: offsetFromRoot(tree.root), + template: '', + }; + generateFiles( + tree, + path.join(__dirname, '..', 'init', 'files', 'maven', 'wrapper'), + '', + templateOptions + ); +} + +export default async function ( + tree: Tree, + options: NxQuarkusMavenMigrateGeneratorSchema +) { + const normalizedOptions = normalizeOptions(tree, options); + addFiles(tree, normalizedOptions); + tree.changePermissions('mvnw', '755'); + tree.changePermissions('mvnw.cmd', '755'); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-maven/src/generators/migrate/schema.d.ts b/packages/nx-micronaut-maven/src/generators/migrate/schema.d.ts new file mode 100644 index 000000000..6c55e9d90 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/migrate/schema.d.ts @@ -0,0 +1 @@ +export interface NxQuarkusMavenMigrateGeneratorSchema {} // eslint-disable-line diff --git a/packages/nx-micronaut-maven/src/generators/migrate/schema.json b/packages/nx-micronaut-maven/src/generators/migrate/schema.json new file mode 100644 index 000000000..76debefe9 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/migrate/schema.json @@ -0,0 +1,8 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxQuarkusMavenMigrate", + "title": "Migrate", + "type": "object", + "properties": {}, + "required": [] +} diff --git a/packages/nx-micronaut-maven/src/generators/parent-project/files/pom.xml__template__ b/packages/nx-micronaut-maven/src/generators/parent-project/files/pom.xml__template__ new file mode 100644 index 000000000..ce784a257 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/parent-project/files/pom.xml__template__ @@ -0,0 +1,18 @@ + + + 4.0.0 + + <%= parentGroupId %> + <%= parentProjectName %> + <%= parentProjectVersion %> + <%= relativePath %> + + <%= groupId %> + <%= projectName %> + <%= projectVersion %> + pom + <%= projectName %> + This project was generated with nx-micronaut-maven + + \ No newline at end of file diff --git a/packages/nx-micronaut-maven/src/generators/parent-project/generator.spec.ts b/packages/nx-micronaut-maven/src/generators/parent-project/generator.spec.ts new file mode 100644 index 000000000..071cb59f1 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/parent-project/generator.spec.ts @@ -0,0 +1,29 @@ +import { readProjectConfiguration, Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import generator from './generator'; +import { NxQuarkusMavenParentProjectGeneratorSchema } from './schema'; + +describe('parent project generator', () => { + let appTree: Tree; + const options: NxQuarkusMavenParentProjectGeneratorSchema = { + name: 'test', + projectType: 'application', + groupId: 'com.example', + projectVersion: '0.0.1-SNAPSHOT', + parentProject: '', + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write( + './pom.xml', + 'com.examplequarkus-multi-module0.0.1-SNAPSHOT' + ); + }); + + it('should run successfully', async () => { + await generator(appTree, options); + const config = readProjectConfiguration(appTree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/packages/nx-micronaut-maven/src/generators/parent-project/generator.ts b/packages/nx-micronaut-maven/src/generators/parent-project/generator.ts new file mode 100644 index 000000000..c8cf74991 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/parent-project/generator.ts @@ -0,0 +1,130 @@ +import { normalizeName } from '@jnxplus/common'; +import { addProjectToAggregator, readXmlTree } from '@jnxplus/maven'; +import { + addProjectConfiguration, + formatFiles, + generateFiles, + getWorkspaceLayout, + names, + offsetFromRoot, + readProjectConfiguration, + Tree, +} from '@nx/devkit'; +import * as path from 'path'; +import { NxQuarkusMavenParentProjectGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxQuarkusMavenParentProjectGeneratorSchema { + projectName: string; + projectRoot: string; + projectDirectory: string; + parsedTags: string[]; + parentGroupId: string; + parentProjectName: string; + parentProjectVersion: string; + relativePath: string; + parentProjectRoot: string; +} + +function normalizeOptions( + tree: Tree, + options: NxQuarkusMavenParentProjectGeneratorSchema +): NormalizedSchema { + const simpleProjectName = names(normalizeName(options.name)).fileName; + + let projectName: string; + if (options.simpleName) { + projectName = simpleProjectName; + } else { + projectName = options.directory + ? `${normalizeName( + names(options.directory).fileName + )}-${simpleProjectName}` + : simpleProjectName; + } + + const projectDirectory = options.directory + ? `${names(options.directory).fileName}/${simpleProjectName}` + : simpleProjectName; + + let projectRoot: string; + if (options.projectType === 'application') { + projectRoot = `${getWorkspaceLayout(tree).appsDir}/${projectDirectory}`; + } else { + projectRoot = `${getWorkspaceLayout(tree).libsDir}/${projectDirectory}`; + } + + const parsedTags = options.tags + ? options.tags.split(',').map((s) => s.trim()) + : []; + + const parentProjectRoot = options.parentProject + ? readProjectConfiguration(tree, options.parentProject).root + : ''; + + const parentProjectPomPath = path.join(parentProjectRoot, 'pom.xml'); + + const pomXmlContent = readXmlTree(tree, parentProjectPomPath); + const relativePath = path + .relative(projectRoot, parentProjectRoot) + .replace(new RegExp(/\\/, 'g'), '/'); + + const parentGroupId = + pomXmlContent?.childNamed('groupId')?.val || 'parentGroupId'; + const parentProjectName = + pomXmlContent?.childNamed('artifactId')?.val || 'parentProjectName'; + const parentProjectVersion = + pomXmlContent?.childNamed('version')?.val || 'parentProjectVersion'; + + return { + ...options, + projectName, + projectRoot, + projectDirectory, + parsedTags, + parentGroupId, + parentProjectName, + parentProjectVersion, + relativePath, + parentProjectRoot, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + ...names(options.name), + offsetFromRoot: offsetFromRoot(options.projectRoot), + template: '', + }; + generateFiles( + tree, + path.join(__dirname, 'files'), + options.projectRoot, + templateOptions + ); +} + +export default async function ( + tree: Tree, + options: NxQuarkusMavenParentProjectGeneratorSchema +) { + const normalizedOptions = normalizeOptions(tree, options); + + addProjectConfiguration(tree, normalizedOptions.projectName, { + root: normalizedOptions.projectRoot, + projectType: normalizedOptions.projectType, + targets: { + build: { + executor: '@jnxplus/nx-micronaut-maven:build', + }, + }, + tags: normalizedOptions.parsedTags, + }); + + addFiles(tree, normalizedOptions); + addProjectToAggregator(tree, { + projectRoot: normalizedOptions.projectRoot, + aggregatorProject: normalizedOptions.parentProject, + }); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-maven/src/generators/parent-project/schema.d.ts b/packages/nx-micronaut-maven/src/generators/parent-project/schema.d.ts new file mode 100644 index 000000000..8a1153767 --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/parent-project/schema.d.ts @@ -0,0 +1,12 @@ +import { ProjectType } from '@jnxplus/common'; + +export interface NxQuarkusMavenParentProjectGeneratorSchema { + name: string; + tags?: string; + directory?: string; + simpleName?: boolean; + projectType: ProjectType; + groupId: string; + projectVersion: string; + parentProject?: string; +} diff --git a/packages/nx-micronaut-maven/src/generators/parent-project/schema.json b/packages/nx-micronaut-maven/src/generators/parent-project/schema.json new file mode 100644 index 000000000..b96fa315d --- /dev/null +++ b/packages/nx-micronaut-maven/src/generators/parent-project/schema.json @@ -0,0 +1,69 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxQuarkusMavenParentProject", + "title": "Create a parent project", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "What name would you like to use?", + "pattern": "^[a-zA-Z].*$" + }, + "tags": { + "type": "string", + "description": "Add tags to the project (used for linting)", + "alias": "t" + }, + "directory": { + "type": "string", + "description": "A directory where the project is placed", + "alias": "dir" + }, + "simpleName": { + "description": "Don't include the directory in the project name", + "type": "boolean", + "default": false + }, + "projectType": { + "description": "Type of the parent project", + "type": "string", + "default": "application", + "x-prompt": { + "message": "Which projectType would you like to generate?", + "type": "list", + "items": [ + { + "value": "application", + "label": "Application" + }, + { + "value": "library", + "label": "Library" + } + ] + } + }, + "groupId": { + "type": "string", + "default": "com.example", + "x-prompt": "What groupId would you like to use?" + }, + "projectVersion": { + "type": "string", + "default": "0.0.1-SNAPSHOT", + "description": "Version of the project to generate", + "alias": "v", + "x-prompt": "What project version would you like to use?" + }, + "parentProject": { + "type": "string", + "description": "ArtifactId of the parent project or leave it blank for the root project" + } + }, + "required": ["name", "projectType", "groupId", "projectVersion"] +} diff --git a/packages/nx-micronaut-maven/src/index.ts b/packages/nx-micronaut-maven/src/index.ts new file mode 100644 index 000000000..38c79a8c1 --- /dev/null +++ b/packages/nx-micronaut-maven/src/index.ts @@ -0,0 +1 @@ +export { processProjectGraph } from './dep-graph/lookup-deps'; diff --git a/packages/nx-micronaut-maven/src/scripts/install-linters.ts b/packages/nx-micronaut-maven/src/scripts/install-linters.ts new file mode 100644 index 000000000..61ee2143f --- /dev/null +++ b/packages/nx-micronaut-maven/src/scripts/install-linters.ts @@ -0,0 +1,25 @@ +import { getCheckstylePath, getKtlintPath, isE2eTest } from '@jnxplus/common'; +import { getCheckstyleVersion, getKtlintVersion } from '@jnxplus/maven'; +import { logger, workspaceRoot } from '@nx/devkit'; +import * as path from 'path'; + +(async () => { + if (process.env['NX_VERBOSE_LOGGING'] === 'true') { + logger.debug('Install Linters'); + } + + let workspaceRootToUse = workspaceRoot; + const tmpWorkspaceRoot = path.join( + workspaceRootToUse, + 'tmp', + 'nx-e2e', + 'proj' + ); + + if (isE2eTest(tmpWorkspaceRoot)) { + workspaceRootToUse = tmpWorkspaceRoot; + } + + await getCheckstylePath(getCheckstyleVersion, workspaceRootToUse); + await getKtlintPath(getKtlintVersion, workspaceRootToUse); +})(); diff --git a/packages/nx-micronaut-maven/tsconfig.json b/packages/nx-micronaut-maven/tsconfig.json new file mode 100644 index 000000000..f5b85657a --- /dev/null +++ b/packages/nx-micronaut-maven/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "commonjs", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/nx-micronaut-maven/tsconfig.lib.json b/packages/nx-micronaut-maven/tsconfig.lib.json new file mode 100644 index 000000000..3ce6be94e --- /dev/null +++ b/packages/nx-micronaut-maven/tsconfig.lib.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "exclude": ["**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] +} diff --git a/packages/nx-micronaut-maven/tsconfig.spec.json b/packages/nx-micronaut-maven/tsconfig.spec.json new file mode 100644 index 000000000..831ab6481 --- /dev/null +++ b/packages/nx-micronaut-maven/tsconfig.spec.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.spec.js", + "**/*.spec.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/testing-projects/e2e/nx-micronaut-maven-e2e/jest.config.js b/testing-projects/e2e/nx-micronaut-maven-e2e/jest.config.js new file mode 100644 index 000000000..0fa934774 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-maven-e2e/jest.config.js @@ -0,0 +1,16 @@ +module.exports = { + displayName: 'nx-micronaut-maven-e2e', + preset: '../../../jest.preset.js', + globals: {}, + testEnvironment: 'node', + transform: { + '^.+\\.[tj]s$': [ + 'ts-jest', + { + tsconfig: '/tsconfig.spec.json', + }, + ], + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../../coverage/e2e/nx-micronaut-maven-e2e', +}; diff --git a/testing-projects/e2e/nx-micronaut-maven-e2e/project.json b/testing-projects/e2e/nx-micronaut-maven-e2e/project.json new file mode 100644 index 000000000..6bbfafe4a --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-maven-e2e/project.json @@ -0,0 +1,18 @@ +{ + "name": "nx-micronaut-maven-e2e", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "testing-projects/e2e/nx-micronaut-maven-e2e/src", + "targets": { + "e2e": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "testing-projects/e2e/nx-micronaut-maven-e2e/jest.config.js", + "runInBand": true + }, + "dependsOn": ["nx-micronaut-maven:build"] + } + }, + "tags": [], + "implicitDependencies": ["nx-micronaut-maven"] +} diff --git a/testing-projects/e2e/nx-micronaut-maven-e2e/tests/nx-micronaut-maven.spec.ts b/testing-projects/e2e/nx-micronaut-maven-e2e/tests/nx-micronaut-maven.spec.ts new file mode 100644 index 000000000..b17dc0e4b --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-maven-e2e/tests/nx-micronaut-maven.spec.ts @@ -0,0 +1,1918 @@ +import { checkstyleVersion, normalizeName } from '@jnxplus/common'; +import { + addTmpToGitignore, + getData, + killPorts, + patchPackageJson, + patchRootPackageJson, + promisifiedTreeKill, + removeTmpFromGitignore, + runNxCommandUntil, + runNxNewCommand, + runPackageManagerInstallLinks, +} from '@jnxplus/e2e/testing'; +import { names, workspaceRoot } from '@nx/devkit'; +import { + checkFilesExist, + cleanup, + readFile, + readJson, + runNxCommandAsync, + tmpProjPath, + uniq, + updateFile, +} from '@nx/plugin/testing'; +import * as fse from 'fs-extra'; +import * as path from 'path'; + +describe('nx-micronaut-maven e2e', () => { + const isCI = + process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true'; + const isWin = process.platform === 'win32'; + const isMacOs = process.platform === 'darwin'; + const parentProjectName = uniq('micronaut-parent-project-'); + + beforeAll(async () => { + fse.ensureDirSync(tmpProjPath()); + cleanup(); + runNxNewCommand('', true); + + const pluginName = '@jnxplus/nx-micronaut-maven'; + const nxmicronautMavenDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'nx-micronaut-maven' + ); + + const commonDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'common' + ); + + const mavenDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'maven' + ); + + patchRootPackageJson(pluginName, nxmicronautMavenDistAbsolutePath); + patchRootPackageJson('@jnxplus/common', commonDistAbsolutePath); + patchRootPackageJson('@jnxplus/maven', mavenDistAbsolutePath); + patchPackageJson( + mavenDistAbsolutePath, + '@jnxplus/common', + commonDistAbsolutePath + ); + patchPackageJson( + nxmicronautMavenDistAbsolutePath, + '@jnxplus/common', + commonDistAbsolutePath + ); + patchPackageJson( + nxmicronautMavenDistAbsolutePath, + '@jnxplus/maven', + mavenDistAbsolutePath + ); + + runPackageManagerInstallLinks(); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:init --parentProjectName ${parentProjectName}` + ); + + if (isCI) { + removeTmpFromGitignore(); + } + }, 120000); + + afterAll(async () => { + if (isCI) { + addTmpToGitignore(); + } + + // `nx reset` kills the daemon, and performs + // some work which can help clean up e2e leftovers + await runNxCommandAsync('reset'); + }); + + it('should set NX_VERBOSE_LOGGING to true', async () => { + expect(process.env['NX_VERBOSE_LOGGING']).toBe('true'); + }, 120000); + + it('should init the workspace with @jnxplus/nx-micronaut-maven capabilities', async () => { + // Making sure the package.json file contains the @jnxplus/nx-micronaut-maven dependency + const packageJson = readJson('package.json'); + expect( + packageJson.devDependencies['@jnxplus/nx-micronaut-maven'] + ).toBeTruthy(); + + // Making sure the nx.json file contains the @jnxplus/nx-micronaut-maven inside the plugins section + const nxJson = readJson('nx.json'); + expect(nxJson.plugins.includes('@jnxplus/nx-micronaut-maven')).toBeTruthy(); + + expect(() => + checkFilesExist( + '.mvn/wrapper/maven-wrapper.jar', + '.mvn/wrapper/maven-wrapper.properties', + 'mvnw', + 'mvnw.cmd', + 'pom.xml', + 'tools/linters/checkstyle.xml', + 'tools/linters/pmd.xml' + ) + ).not.toThrow(); + + expect(() => + checkFilesExist( + `node_modules/@jnxplus/tools/linters/checkstyle/checkstyle-${checkstyleVersion}-all.jar`, + `node_modules/@jnxplus/tools/linters/ktlint/ktlint` + ) + ).not.toThrow(); + }, 120000); + + it('should migrate', async () => { + await runNxCommandAsync(`generate @jnxplus/nx-micronaut-maven:migrate`); + }, 120000); + + it('should create a java application', async () => { + const appName = uniq('micronaut-maven-app-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/pom.xml`, + `apps/${appName}/src/main/resources/application.properties`, + `apps/${appName}/src/main/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/Application.java`, + `apps/${appName}/src/main/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloController.java`, + `apps/${appName}/src/test/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const pomXml = readFile(`apps/${appName}/pom.xml`); + expect(pomXml.includes('com.example')).toBeTruthy(); + expect(pomXml.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + expect(() => checkFilesExist(`apps/${appName}/target`)).not.toThrow(); + + //should recreate target folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'apps', appName, 'target'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`apps/${appName}/target`)).toThrow(); + await runNxCommandAsync(`build ${appName}`); + expect(() => checkFilesExist(`apps/${appName}/target`)).not.toThrow(); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${appName}` + ); + expect(formatResult.stdout).toContain(''); + + //test run-task + const projectJson = readJson(`apps/${appName}/project.json`); + projectJson.targets = { + ...projectJson.targets, + 'run-task': { + executor: '@jnxplus/nx-micronaut-maven:run-task', + }, + }; + updateFile(`apps/${appName}/project.json`, JSON.stringify(projectJson)); + const runTaskResult = await runNxCommandAsync( + `run-task ${appName} --task="clean install -DskipTests=true"` + ); + expect(runTaskResult.stdout).toContain('Executor ran for Run Task'); + //end test run-task + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + const process = await runNxCommandUntil(`serve ${appName}`, (output) => + output.includes(`Server Running: http://localhost:8080`) + ); + + const dataResult = await getData(8080, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(8080); + } catch (err) { + // ignore err + } + }, 120000); + + xit('should build-image a java application', async () => { + if (!isWin && !isMacOs && isCI) { + const appName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName}` + ); + const buildImageResult = await runNxCommandAsync( + `build-image ${appName} --args="-Dpackaging=docker"` + ); + expect(buildImageResult.stdout).toContain('Executor ran for Build Image'); + } + }, 120000); + + it('should use specified options to create an application', async () => { + const randomName = uniq('micronaut-maven-app-'); + const appDir = 'deep/subdir'; + const appName = `${normalizeName(appDir)}-${randomName}`; + const port = 8181; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${randomName} --tags e2etag,e2ePackage --directory ${appDir} --groupId com.jnxplus --projectVersion 1.2.3 --packaging war --configFormat .yml --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appDir}/${randomName}/pom.xml`, + `apps/${appDir}/${randomName}/src/main/resources/application.yml`, + `apps/${appDir}/${randomName}/src/main/java/com/jnxplus/deep/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/Application.java`, + `apps/${appDir}/${randomName}/src/main/java/com/jnxplus/deep/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloController.java`, + + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/deep/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const pomXml = readFile(`apps/${appDir}/${randomName}/pom.xml`); + expect(pomXml.includes('com.jnxplus')).toBeTruthy(); + expect(pomXml.includes('1.2.3')).toBeTruthy(); + // expect(pomXml.includes('war')).toBeTruthy(); + // expect(pomXml.includes('spring-micronaut-starter-tomcat')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync( + `build ${appName} --mvnArgs='--no-transfer-progress'` + ); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${appName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args=""`, + (output) => output.includes(`Server Running: http://localhost:${port}`) + ); + + const dataResult = await getData(port, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 240000); + + it('should create a kotlin application', async () => { + const appName = uniq('micronaut-maven-app-'); + const port = 8282; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName} --language kotlin --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/pom.xml`, + `apps/${appName}/src/main/resources/application.properties`, + `apps/${appName}/src/main/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/Application.kt`, + `apps/${appName}/src/main/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloController.kt`, + + `apps/${appName}/src/test/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.kt` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const pomXml = readFile(`apps/${appName}/pom.xml`); + expect(pomXml.includes('com.example')).toBeTruthy(); + expect(pomXml.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const buildResult = await runNxCommandAsync( + `build ${appName} --mvnArgs="--no-transfer-progress"` + ); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate target folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'apps', appName, 'target'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`apps/${appName}/target`)).toThrow(); + await runNxCommandAsync(`build ${appName}`); + expect(() => checkFilesExist(`apps/${appName}/target`)).not.toThrow(); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const formatResult = await runNxCommandAsync(`ktformat ${appName}`); + expect(formatResult.stdout).toContain('Executor ran for Kotlin Format'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + const process = await runNxCommandUntil(`serve ${appName}`, (output) => + output.includes(`Server Running: http://localhost:${port}`) + ); + + const dataResult = await getData(port, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 120000); + + xit('should build-image a kotlin application', async () => { + if (!isWin && !isMacOs && isCI) { + const appName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName} --language kotlin` + ); + const buildImageResult = await runNxCommandAsync( + `build-image ${appName} --args="-Dpackaging=docker"` + ); + expect(buildImageResult.stdout).toContain('Executor ran for Build Image'); + } + }, 120000); + + it('--an app with aliases', async () => { + const randomName = uniq('micronaut-maven-app-'); + const appDir = 'subdir'; + const appName = `${appDir}-${randomName}`; + const port = 8383; + + await runNxCommandAsync( + `g @jnxplus/nx-micronaut-maven:app ${randomName} --t e2etag,e2ePackage --dir ${appDir} --groupId com.jnxplus --v 1.2.3 --packaging war --configFormat .yml --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appDir}/${randomName}/pom.xml`, + `apps/${appDir}/${randomName}/src/main/resources/application.yml`, + `apps/${appDir}/${randomName}/src/main/java/com/jnxplus/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/Application.java`, + `apps/${appDir}/${randomName}/src/main/java/com/jnxplus/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloController.java`, + + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good information + const pomXml = readFile(`apps/${appDir}/${randomName}/pom.xml`); + expect(pomXml.includes('com.jnxplus')).toBeTruthy(); + expect(pomXml.includes('1.2.3')).toBeTruthy(); + // expect(pomXml.includes('war')).toBeTruthy(); + // expect(pomXml.includes('spring-micronaut-starter-tomcat')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${appName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args=""`, + (output) => output.includes(`Server Running: http://localhost:${port}`) + ); + + const dataResult = await getData(port, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 240000); + + it('should generate an app with a simple package name', async () => { + const randomName = uniq('micronaut-maven-app-'); + const appDir = 'subdir'; + const appName = `${appDir}-${randomName}`; + + const port = 8484; + + await runNxCommandAsync( + `g @jnxplus/nx-micronaut-maven:app ${randomName} --t e2etag,e2ePackage --dir ${appDir} --groupId com.jnxplus --simplePackageName --v 1.2.3 --packaging war --configFormat .yml --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appDir}/${randomName}/pom.xml`, + `apps/${appDir}/${randomName}/src/main/resources/application.yml`, + `apps/${appDir}/${randomName}/src/main/java/com/jnxplus/${names( + randomName + ).className.toLocaleLowerCase()}/Application.java`, + `apps/${appDir}/${randomName}/src/main/java/com/jnxplus/${names( + randomName + ).className.toLocaleLowerCase()}/HelloController.java`, + + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const buildmaven = readFile(`apps/${appDir}/${randomName}/pom.xml`); + expect(buildmaven.includes('com.jnxplus')).toBeTruthy(); + expect(buildmaven.includes('1.2.3')).toBeTruthy(); + // expect(buildmaven.includes('war')).toBeTruthy(); + // expect(buildmaven.includes('spring-micronaut-starter-tomcat')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${appName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args=""`, + (output) => output.includes(`Server Running: http://localhost:${port}`) + ); + + const dataResult = await getData(port, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 240000); + + it('directory with dash', async () => { + const randomName = uniq('micronaut-maven-app-'); + const appName = `deep-sub-dir-${randomName}`; + const port = 8585; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${randomName} --directory deep/sub-dir --port ${port}` + ); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + const process = await runNxCommandUntil(`serve ${appName}`, (output) => + output.includes(`Server Running: http://localhost:${port}`) + ); + + const dataResult = await getData(port, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 120000); + + it('should create a library', async () => { + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName}` + ); + + expect(() => + checkFilesExist( + `libs/${libName}/pom.xml`, + `libs/${libName}/src/main/java/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloService.java`, + `libs/${libName}/src/test/java/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloServiceTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const pomXml = readFile(`libs/${libName}/pom.xml`); + expect(pomXml.includes('com.example')).toBeTruthy(); + expect(pomXml.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate target folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'libs', libName, 'target'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`libs/${libName}/target`)).toThrow(); + await runNxCommandAsync(`build ${libName}`); + expect(() => checkFilesExist(`libs/${libName}/target`)).not.toThrow(); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${libName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${libName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + }, 120000); + + it('should create a kotlin library', async () => { + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --language kotlin` + ); + + expect(() => + checkFilesExist( + `libs/${libName}/pom.xml`, + `libs/${libName}/src/main/kotlin/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloService.kt`, + `libs/${libName}/src/test/kotlin/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloServiceTest.kt` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const pomXml = readFile(`libs/${libName}/pom.xml`); + expect(pomXml.includes('com.example')).toBeTruthy(); + expect(pomXml.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate target folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'libs', libName, 'target'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`libs/${libName}/target`)).toThrow(); + await runNxCommandAsync(`build ${libName}`); + expect(() => checkFilesExist(`libs/${libName}/target`)).not.toThrow(); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const formatResult = await runNxCommandAsync(`ktformat ${libName}`); + expect(formatResult.stdout).toContain('Executor ran for Kotlin Format'); + + const lintResult = await runNxCommandAsync(`lint ${libName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + }, 120000); + + it('should use the the specified properties to create a library', async () => { + const randomName = uniq('micronaut-maven-lib-'); + const libDir = 'deep/subdir'; + const libName = `${normalizeName(libDir)}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${randomName} --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/pom.xml`, + `libs/${libDir}/${randomName}/src/main/java/com/jnxplus/deep/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloService.java`, + + `libs/${libDir}/${randomName}/src/test/java/com/jnxplus/deep/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloServiceTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good information + const pomXml = readFile(`libs/${libDir}/${randomName}/pom.xml`); + expect(pomXml.includes('com.jnxplus')).toBeTruthy(); + expect(pomXml.includes('1.2.3')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`libs/${libDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${libName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${libName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + }, 120000); + + it('should generare a lib with a simple package name', async () => { + const randomName = uniq('micronaut-maven-lib-'); + const libDir = 'deep/subdir'; + const libName = `${normalizeName(libDir)}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${randomName} --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --simplePackageName --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/pom.xml`, + `libs/${libDir}/${randomName}/src/main/java/com/jnxplus/${names( + randomName + ).className.toLocaleLowerCase()}/HelloService.java`, + + `libs/${libDir}/${randomName}/src/test/java/com/jnxplus/${names( + randomName + ).className.toLocaleLowerCase()}/HelloServiceTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const pomXml = readFile(`libs/${libDir}/${randomName}/pom.xml`); + expect(pomXml.includes('com.jnxplus')).toBeTruthy(); + expect(pomXml.includes('1.2.3')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`libs/${libDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${libName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${libName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + }, 120000); + + it('--a lib with aliases', async () => { + const randomName = uniq('micronaut-maven-lib-'); + const libDir = 'subdir'; + const libName = `${libDir}-${randomName}`; + + await runNxCommandAsync( + `g @jnxplus/nx-micronaut-maven:lib ${randomName} --dir ${libDir} --t e2etag,e2ePackage --groupId com.jnxplus --v 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/pom.xml`, + `libs/${libDir}/${randomName}/src/main/java/com/jnxplus/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloService.java`, + + `libs/${libDir}/${randomName}/src/test/java/com/jnxplus/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloServiceTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good information + const pomXml = readFile(`libs/${libDir}/${randomName}/pom.xml`); + expect(pomXml.includes('com.jnxplus')).toBeTruthy(); + expect(pomXml.includes('1.2.3')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`libs/${libDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${libName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${libName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + }, 120000); + + it('should add a lib to an app dependencies', async () => { + const appName = uniq('micronaut-maven-app-'); + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName}` + ); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --projects ${appName}` + ); + + // Making sure the app pom.xml file contains the lib + const pomXml = readFile(`apps/${appName}/pom.xml`); + expect(pomXml.includes(`${libName}`)).toBeTruthy(); + + const helloControllerPath = `apps/${appName}/src/main/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloController.java`; + const helloControllerContent = readFile(helloControllerPath); + + const regex1 = /package\s*com\.example\..*\s*;/; + + const regex2 = /public\s*class\s*HelloController\s*{/; + + const regex3 = /"Hello World"/; + + const newHelloControllerContent = helloControllerContent + .replace( + regex1, + `$&\nimport jakarta.inject.Inject;\nimport com.example.${names( + libName + ).className.toLocaleLowerCase()}.HelloService;` + ) + .replace(regex2, '$&\n@Inject\nprivate HelloService helloService;') + .replace(regex3, 'this.helloService.greeting()'); + + updateFile(helloControllerPath, newHelloControllerContent); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const formatResult = await runNxCommandAsync( + `format:write --projects ${appName}` + ); + expect(formatResult.stdout).toContain('HelloController.java'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + await runNxCommandAsync(`dep-graph --file=dep-graph.json`); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.nodes[appName]).toBeDefined(); + expect(depGraphJson.graph.nodes[libName]).toBeDefined(); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: libName, + }); + }, 120000); + + it('should add a kotlin lib to a kotlin app dependencies', async () => { + const appName = uniq('micronaut-maven-app-'); + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName} --language kotlin --packaging war` + ); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --language kotlin --projects ${appName}` + ); + + // Making sure the app pom.xml file contains the lib + const pomXml = readFile(`apps/${appName}/pom.xml`); + expect(pomXml.includes(`${libName}`)).toBeTruthy(); + + const helloControllerPath = `apps/${appName}/src/main/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloController.kt`; + const helloControllerContent = readFile(helloControllerPath); + + const regex1 = /package\s*com\.example\..*/; + + const regex2 = /class\s*HelloController/; + + const regex3 = /"Hello World"/; + + const newHelloControllerContent = helloControllerContent + .replace( + regex1, + `$&\nimport jakarta.inject.Inject\nimport com.example.${names( + libName + ).className.toLocaleLowerCase()}.HelloService` + ) + .replace(regex2, '$&(@Inject val helloService: HelloService)') + .replace(regex3, 'helloService.greeting()'); + + updateFile(helloControllerPath, newHelloControllerContent); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const formatResult = await runNxCommandAsync(`ktformat ${appName}`); + expect(formatResult.stdout).toContain('Executor ran for Kotlin Format'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + await runNxCommandAsync(`dep-graph --file=dep-graph.json`); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.nodes[appName]).toBeDefined(); + expect(depGraphJson.graph.nodes[libName]).toBeDefined(); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: libName, + }); + }, 120000); + + it("should dep-graph don't crash when pom.xml don't contains dependencies tag", async () => { + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName}` + ); + + const regex = /[\s\S]*?<\/dependencies>/; + const pomXml = `libs/${libName}/pom.xml`; + const pomXmlContent = readFile(pomXml); + const updatedPomXmlContent = pomXmlContent.replace(regex, ''); + updateFile(pomXml, updatedPomXmlContent); + + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + }, 120000); + + it('should generate java apps that use a parent project', async () => { + const appsParentProject = uniq('apps-parent-project-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${appsParentProject}` + ); + + const randomName = uniq('micronaut-maven-app-'); + const appDir = 'dir'; + const appName = `${normalizeName(appDir)}-${randomName}`; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${randomName} --parent-project ${appsParentProject} --directory ${appDir}` + ); + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const secondParentProject = uniq('apps-parent-project-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${secondParentProject} --parent-project ${appsParentProject}` + ); + + const secondAppName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${secondAppName} --parent-project ${secondParentProject}` + ); + const secondBuildResult = await runNxCommandAsync(`build ${secondAppName}`); + expect(secondBuildResult.stdout).toContain('Executor ran for Build'); + + const randomParentproject = uniq('apps-parent-project-'); + const parentProjectDir = 'deep/subdir'; + const thirdParentProject = `${normalizeName( + parentProjectDir + )}-${randomParentproject}`; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${randomParentproject} --parent-project ${secondParentProject} --directory ${parentProjectDir}` + ); + + const thirdAppName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${thirdAppName} --parent-project ${thirdParentProject}` + ); + const thirdBuildResult = await runNxCommandAsync(`build ${thirdAppName}`); + expect(thirdBuildResult.stdout).toContain('Executor ran for Build'); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appsParentProject]).toContainEqual({ + type: 'static', + source: appsParentProject, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: appsParentProject, + }); + + expect(depGraphJson.graph.dependencies[secondParentProject]).toContainEqual( + { + type: 'static', + source: secondParentProject, + target: appsParentProject, + } + ); + + expect(depGraphJson.graph.dependencies[secondAppName]).toContainEqual({ + type: 'static', + source: secondAppName, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdParentProject]).toContainEqual({ + type: 'static', + source: thirdParentProject, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdAppName]).toContainEqual({ + type: 'static', + source: thirdAppName, + target: thirdParentProject, + }); + }, 120000); + + it('should generate kotlin apps that use a parent project', async () => { + const appsParentProject = uniq('apps-parent-project-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${appsParentProject}` + ); + + const randomName = uniq('micronaut-maven-app-'); + const appDir = 'dir'; + const appName = `${normalizeName(appDir)}-${randomName}`; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${randomName} --parent-project ${appsParentProject} --directory ${appDir} --language kotlin` + ); + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const secondParentProject = uniq('apps-parent-project-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${secondParentProject} --parent-project ${appsParentProject}` + ); + + const secondAppName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${secondAppName} --parent-project ${secondParentProject} --language kotlin` + ); + const secondBuildResult = await runNxCommandAsync(`build ${secondAppName}`); + expect(secondBuildResult.stdout).toContain('Executor ran for Build'); + + const randomParentproject = uniq('apps-parent-project-'); + const parentProjectDir = 'deep/subdir'; + const thirdParentProject = `${normalizeName( + parentProjectDir + )}-${randomParentproject}`; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${randomParentproject} --parent-project ${secondParentProject} --directory ${parentProjectDir}` + ); + + const thirdAppName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${thirdAppName} --parent-project ${thirdParentProject} --language kotlin` + ); + const thirdBuildResult = await runNxCommandAsync(`build ${thirdAppName}`); + expect(thirdBuildResult.stdout).toContain('Executor ran for Build'); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appsParentProject]).toContainEqual({ + type: 'static', + source: appsParentProject, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: appsParentProject, + }); + + expect(depGraphJson.graph.dependencies[secondParentProject]).toContainEqual( + { + type: 'static', + source: secondParentProject, + target: appsParentProject, + } + ); + + expect(depGraphJson.graph.dependencies[secondAppName]).toContainEqual({ + type: 'static', + source: secondAppName, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdParentProject]).toContainEqual({ + type: 'static', + source: thirdParentProject, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdAppName]).toContainEqual({ + type: 'static', + source: thirdAppName, + target: thirdParentProject, + }); + }, 120000); + + it('should generate java libs that use a parent project', async () => { + const libsParentProject = uniq('libs-parent-project-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${libsParentProject} --projectType library` + ); + + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --parent-project ${libsParentProject}` + ); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const secondParentProject = uniq('libs-parent-project-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${secondParentProject} --projectType library --parent-project ${libsParentProject}` + ); + + const randomName = uniq('micronaut-maven-lib-'); + const libDir = 'subdir'; + const secondLibName = `${libDir}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${randomName} --parent-project ${secondParentProject} --dir ${libDir}` + ); + + const secondBuildResult = await runNxCommandAsync(`build ${secondLibName}`); + expect(secondBuildResult.stdout).toContain('Executor ran for Build'); + + const randomParentproject = uniq('libs-parent-project-'); + const parentProjectDir = 'deep/subdir'; + const thirdParentProject = `${normalizeName( + parentProjectDir + )}-${randomParentproject}`; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${randomParentproject} --projectType library --parent-project ${secondParentProject} --directory ${parentProjectDir}` + ); + + const thirdLibName = uniq('micronaut-maven-lib-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${thirdLibName} --parent-project ${thirdParentProject}` + ); + const thirdBuildResult = await runNxCommandAsync(`build ${thirdLibName}`); + expect(thirdBuildResult.stdout).toContain('Executor ran for Build'); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libsParentProject]).toContainEqual({ + type: 'static', + source: libsParentProject, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: libsParentProject, + }); + + expect(depGraphJson.graph.dependencies[secondParentProject]).toContainEqual( + { + type: 'static', + source: secondParentProject, + target: libsParentProject, + } + ); + + expect(depGraphJson.graph.dependencies[secondLibName]).toContainEqual({ + type: 'static', + source: secondLibName, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdParentProject]).toContainEqual({ + type: 'static', + source: thirdParentProject, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdLibName]).toContainEqual({ + type: 'static', + source: thirdLibName, + target: thirdParentProject, + }); + }, 120000); + + it('should generate kotlin libs that use a parent project', async () => { + const libsParentProject = uniq('libs-parent-project-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${libsParentProject} --projectType library` + ); + + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --parent-project ${libsParentProject} --language kotlin` + ); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const secondParentProject = uniq('libs-parent-project-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${secondParentProject} --projectType library --parent-project ${libsParentProject}` + ); + + const randomName = uniq('micronaut-maven-lib-'); + const libDir = 'subdir'; + const secondLibName = `${libDir}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${randomName} --parent-project ${secondParentProject} --dir ${libDir} --language kotlin` + ); + + const secondBuildResult = await runNxCommandAsync(`build ${secondLibName}`); + expect(secondBuildResult.stdout).toContain('Executor ran for Build'); + + const randomParentproject = uniq('libs-parent-project-'); + const parentProjectDir = 'deep/subdir'; + const thirdParentProject = `${normalizeName( + parentProjectDir + )}-${randomParentproject}`; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${randomParentproject} --projectType library --parent-project ${secondParentProject} --directory ${parentProjectDir}` + ); + + const thirdLibName = uniq('micronaut-maven-lib-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${thirdLibName} --parent-project ${thirdParentProject} --language kotlin` + ); + const thirdBuildResult = await runNxCommandAsync(`build ${thirdLibName}`); + expect(thirdBuildResult.stdout).toContain('Executor ran for Build'); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libsParentProject]).toContainEqual({ + type: 'static', + source: libsParentProject, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: libsParentProject, + }); + + expect(depGraphJson.graph.dependencies[secondParentProject]).toContainEqual( + { + type: 'static', + source: secondParentProject, + target: libsParentProject, + } + ); + + expect(depGraphJson.graph.dependencies[secondLibName]).toContainEqual({ + type: 'static', + source: secondLibName, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdParentProject]).toContainEqual({ + type: 'static', + source: thirdParentProject, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdLibName]).toContainEqual({ + type: 'static', + source: thirdLibName, + target: thirdParentProject, + }); + }, 120000); + + it('should create an application with a simple name', async () => { + const appName = uniq('micronaut-maven-app-'); + const appDir = 'deep/subdir'; + const port = 8686; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName} --simpleName --tags e2etag,e2ePackage --directory ${appDir} --groupId com.jnxplus --projectVersion 1.2.3 --packaging war --configFormat .yml --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appDir}/${appName}/pom.xml`, + `apps/${appDir}/${appName}/src/main/resources/application.yml`, + `apps/${appDir}/${appName}/src/main/java/com/jnxplus/deep/subdir/${names( + appName + ).className.toLocaleLowerCase()}/Application.java`, + `apps/${appDir}/${appName}/src/main/java/com/jnxplus/deep/subdir/${names( + appName + ).className.toLocaleLowerCase()}/HelloController.java`, + + `apps/${appDir}/${appName}/src/test/java/com/jnxplus/deep/subdir/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good informations + const pomXml = readFile(`apps/${appDir}/${appName}/pom.xml`); + expect(pomXml.includes('com.jnxplus')).toBeTruthy(); + expect(pomXml.includes('1.2.3')).toBeTruthy(); + // expect(pomXml.includes('war')).toBeTruthy(); + // expect(pomXml.includes('spring-micronaut-starter-tomcat')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${appName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync( + `build ${appName} --mvnArgs='--no-transfer-progress'` + ); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${appName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${appName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args=""`, + (output) => output.includes(`Server Running: http://localhost:${port}`) + ); + + const dataResult = await getData(port, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 240000); + + it('should create a library with a simple name', async () => { + const libName = uniq('micronaut-maven-lib-'); + const libDir = 'deep/subdir'; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --simpleName --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${libName}/pom.xml`, + `libs/${libDir}/${libName}/src/main/java/com/jnxplus/deep/subdir/${names( + libName + ).className.toLocaleLowerCase()}/HelloService.java`, + + `libs/${libDir}/${libName}/src/test/java/com/jnxplus/deep/subdir/${names( + libName + ).className.toLocaleLowerCase()}/HelloServiceTest.java` + ) + ).not.toThrow(); + + // Making sure the pom.xml file contains the good information + const pomXml = readFile(`libs/${libDir}/${libName}/pom.xml`); + expect(pomXml.includes('com.jnxplus')).toBeTruthy(); + expect(pomXml.includes('1.2.3')).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`libs/${libDir}/${libName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const lintResult = await runNxCommandAsync(`lint ${libName}`); + expect(lintResult.stdout).toContain('Executor ran for Lint'); + + const formatResult = await runNxCommandAsync( + `format:check --projects ${libName}` + ); + expect(formatResult.stdout).toContain(''); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: parentProjectName, + }); + }, 120000); + + it('should create a minimal java application', async () => { + const appName = uniq('micronaut-maven-app-'); + const port = 8787; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName} --minimal --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/pom.xml`, + `apps/${appName}/src/main/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/Application.java`, + `apps/${appName}/src/main/resources/application.properties`, + `apps/${appName}/src/test/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/${ + names(appName).className + }ApplicationTest.java` + ) + ).not.toThrow(); + + expect(() => + checkFilesExist( + `apps/${appName}/src/main/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloController.java`, + + `apps/${appName}/src/test/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).toThrow(); + + const process = await runNxCommandUntil(`serve ${appName}`, (output) => + output.includes(`Server Running: http://localhost:${port}`) + ); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 120000); + + it('should create a minimal kotlin application', async () => { + const appName = uniq('micronaut-maven-app-'); + const port = 8888; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName} --language kotlin --minimal --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/pom.xml`, + `apps/${appName}/src/main/resources/application.properties`, + `apps/${appName}/src/main/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/Application.kt`, + `apps/${appName}/src/test/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/${ + names(appName).className + }ApplicationTest.kt` + ) + ).not.toThrow(); + + expect(() => + checkFilesExist( + `apps/${appName}/src/main/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloController.kt`, + + `apps/${appName}/src/test/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.kt` + ) + ).toThrow(); + + const process = await runNxCommandUntil(`serve ${appName}`, (output) => + output.includes(`Server Running: http://localhost:${port}`) + ); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 120000); + + it('should skip starter code when generating a java library with skipStarterCode option', async () => { + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --skipStarterCode` + ); + + expect(() => checkFilesExist(`libs/${libName}/pom.xml`)).not.toThrow(); + + expect(() => + checkFilesExist( + `libs/${libName}/src/main/java/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloService.java`, + + `libs/${libName}/src/test/java/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloServiceTest.java` + ) + ).toThrow(); + }, 120000); + + it('should skip starter code when generating a kotlin library with skipStarterCode option', async () => { + const libName = uniq('micronaut-maven-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:library ${libName} --language kotlin --skipStarterCode` + ); + + expect(() => checkFilesExist(`libs/${libName}/pom.xml`)).not.toThrow(); + + expect(() => + checkFilesExist( + `libs/${libName}/src/main/kotlin/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloService.kt`, + `apps/${libName}/src/test/resources/junit-platform.properties`, + + `libs/${libName}/src/test/kotlin/com/example/${names( + libName + ).className.toLocaleLowerCase()}/HelloServiceTest.kt` + ) + ).toThrow(); + }, 120000); + + it('should generate java app inside a parent project', async () => { + const parentProject = uniq('parent-project-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${parentProject}` + ); + + const randomName = uniq('micronaut-maven-app-'); + const appName = `${parentProject}-${randomName}`; + const port = 8989; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${randomName} --parent-project ${parentProject} --directory ${parentProject} --port ${port}` + ); + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //graph + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: parentProject, + }); + + const process = await runNxCommandUntil(`serve ${appName}`, (output) => + output.includes(`Server Running: http://localhost:${port}`) + ); + + const dataResult = await getData(port, '/hello'); + expect(dataResult.status).toEqual(200); + expect(dataResult.message).toMatch('Hello World'); + + // port and process cleanup + try { + await promisifiedTreeKill(process.pid, 'SIGKILL'); + await killPorts(port); + } catch (err) { + // ignore err + } + }, 120000); + + it('should generate java nested sub-projects', async () => { + const appsParentProject = uniq('apps-parent-project-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${appsParentProject}` + ); + + const appName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${appName} --simpleName --parent-project ${appsParentProject} --directory ${appsParentProject}` + ); + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + const secondParentProject = uniq('apps-parent-project-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${secondParentProject} --simpleName --parent-project ${appsParentProject} --directory ${appsParentProject}` + ); + + const secondAppName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${secondAppName} --simpleName --parent-project ${secondParentProject} --directory ${appsParentProject}/${secondParentProject}` + ); + const secondBuildResult = await runNxCommandAsync(`build ${secondAppName}`); + expect(secondBuildResult.stdout).toContain('Executor ran for Build'); + + const thirdParentProject = uniq('apps-parent-project-'); + const parentProjectDir = `${appsParentProject}/${secondParentProject}/deep/subdir`; + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:parent-project ${thirdParentProject} --simpleName --parent-project ${secondParentProject} --directory ${parentProjectDir}` + ); + + const thirdAppName = uniq('micronaut-maven-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-maven:application ${thirdAppName} --parent-project ${thirdParentProject}` + ); + const thirdBuildResult = await runNxCommandAsync(`build ${thirdAppName}`); + expect(thirdBuildResult.stdout).toContain('Executor ran for Build'); + + //graph + const localTmpDir = path.dirname(tmpProjPath()); + const projectJson1 = path.join( + localTmpDir, + 'proj', + 'apps', + appsParentProject, + 'project.json' + ); + fse.removeSync(projectJson1); + const depGraphResult = await runNxCommandAsync( + `dep-graph --file=dep-graph.json` + ); + expect(depGraphResult.stderr).not.toContain( + 'Failed to process the project graph' + ); + const depGraphJson = readJson('dep-graph.json'); + expect(depGraphJson.graph.dependencies[appsParentProject]).toContainEqual({ + type: 'static', + source: appsParentProject, + target: parentProjectName, + }); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: appsParentProject, + }); + + expect(depGraphJson.graph.dependencies[secondParentProject]).toContainEqual( + { + type: 'static', + source: secondParentProject, + target: appsParentProject, + } + ); + + expect(depGraphJson.graph.dependencies[secondAppName]).toContainEqual({ + type: 'static', + source: secondAppName, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdParentProject]).toContainEqual({ + type: 'static', + source: thirdParentProject, + target: secondParentProject, + }); + + expect(depGraphJson.graph.dependencies[thirdAppName]).toContainEqual({ + type: 'static', + source: thirdAppName, + target: thirdParentProject, + }); + }, 120000); +}); diff --git a/testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.json b/testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.json new file mode 100644 index 000000000..b36041a2a --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.spec.json b/testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.spec.json new file mode 100644 index 000000000..5936dfcb1 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-maven-e2e/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 95a44f0f2..67afe0780 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -26,6 +26,9 @@ "@jnxplus/nx-quarkus-maven": ["packages/nx-quarkus-maven/src/index.ts"], "@jnxplus/nx-micronaut-gradle": [ "packages/nx-micronaut-gradle/src/index.ts" + ], + "@jnxplus/nx-micronaut-maven": [ + "packages/nx-micronaut-maven/src/index.ts" ] } },