diff --git a/.commitlintrc.json b/.commitlintrc.json index 3791b906c..d33e165c5 100644 --- a/.commitlintrc.json +++ b/.commitlintrc.json @@ -5,6 +5,7 @@ 2, "always", [ + "plugins", "generators", "executors", "graph", diff --git a/.github/workflows/check-plugin.yml b/.github/workflows/check-plugin.yml index 4df7db64a..59e37cec7 100644 --- a/.github/workflows/check-plugin.yml +++ b/.github/workflows/check-plugin.yml @@ -53,12 +53,6 @@ jobs: - name: Install dependencies run: npm ci - - name: Unit tests - run: npm run test nx-${{ github.event.inputs.framework }}-${{ github.event.inputs.buildTool }} - - - name: Build - run: npm run build nx-${{ github.event.inputs.framework }}-${{ github.event.inputs.buildTool }} - - name: E2E tests run: npm run e2e nx-${{ github.event.inputs.framework }}-${{ github.event.inputs.buildTool }}-e2e env: diff --git a/packages/common/src/lib/versions/index.ts b/packages/common/src/lib/versions/index.ts index 3b124f29d..53ed9f672 100644 --- a/packages/common/src/lib/versions/index.ts +++ b/packages/common/src/lib/versions/index.ts @@ -7,6 +7,10 @@ export const springKotlinVersion = '1.8.21'; export const quarkusPlatformVersion = '3.0.4.Final'; export const quarkusKotlinVersion = '1.8.10'; +//Micronaut +export const micronautVersion = '4.0.0-M2'; +export const micronautKotlinVersion = '1.8.20'; + //Linters export const checkstyleVersion = '10.11.0'; export const ktlintVersion = '0.49.1'; diff --git a/packages/gradle/src/executors/build-image/micronaut/executor.spec.ts b/packages/gradle/src/executors/build-image/micronaut/executor.spec.ts new file mode 100644 index 000000000..1aee1eb3d --- /dev/null +++ b/packages/gradle/src/executors/build-image/micronaut/executor.spec.ts @@ -0,0 +1,40 @@ +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 = { + useDocker: true, + native: true, + optimized: 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 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/gradle/src/executors/build-image/micronaut/executor.ts b/packages/gradle/src/executors/build-image/micronaut/executor.ts new file mode 100644 index 000000000..005da0888 --- /dev/null +++ b/packages/gradle/src/executors/build-image/micronaut/executor.ts @@ -0,0 +1,43 @@ +import { ExecutorContext, logger } from '@nx/devkit'; +import { getExecutable, getProjectPath } from '../../../.'; +import { runCommand } from '@jnxplus/common'; +import { BuildImageExecutorSchema } from './schema'; + +export default async function runExecutor( + options: BuildImageExecutorSchema, + context: ExecutorContext +) { + logger.info(`Executor ran for Build Image: ${JSON.stringify(options)}`); + + if (options.useDocker && options.native && options.optimized) { + return runCommand( + `${getExecutable()} ${getProjectPath(context)}:optimizedDockerBuildNative` + ); + } + + if (options.useDocker && !options.native && options.optimized) { + return runCommand( + `${getExecutable()} ${getProjectPath(context)}:optimizedDockerBuild` + ); + } + + if (options.useDocker && options.native && !options.optimized) { + return runCommand( + `${getExecutable()} ${getProjectPath(context)}:dockerBuildNative` + ); + } + + if (options.useDocker && !options.native && !options.optimized) { + return runCommand( + `${getExecutable()} ${getProjectPath(context)}:dockerBuild` + ); + } + + if (!options.useDocker) { + return runCommand( + `${getExecutable()} ${getProjectPath(context)}:nativeCompile` + ); + } + + throw new Error(`Case not handled`); +} diff --git a/packages/gradle/src/executors/build-image/micronaut/schema.d.ts b/packages/gradle/src/executors/build-image/micronaut/schema.d.ts new file mode 100644 index 000000000..9b213ee1a --- /dev/null +++ b/packages/gradle/src/executors/build-image/micronaut/schema.d.ts @@ -0,0 +1,5 @@ +export interface BuildImageExecutorSchema { + useDocker: boolean; + native: boolean; + optimized: boolean; +} diff --git a/packages/gradle/src/executors/build-image/micronaut/schema.json b/packages/gradle/src/executors/build-image/micronaut/schema.json new file mode 100644 index 000000000..b95781de5 --- /dev/null +++ b/packages/gradle/src/executors/build-image/micronaut/schema.json @@ -0,0 +1,20 @@ +{ + "version": 2, + "outputCapture": "pipe", + "$schema": "http://json-schema.org/schema", + "title": "Build Image executor", + "description": "", + "type": "object", + "properties": { + "useDocker": { + "type": "boolean" + }, + "native": { + "type": "boolean" + }, + "optimized": { + "type": "boolean" + } + }, + "required": [] +} diff --git a/packages/gradle/src/executors/build/micronaut/executor.spec.ts b/packages/gradle/src/executors/build/micronaut/executor.spec.ts new file mode 100644 index 000000000..8ae99e107 --- /dev/null +++ b/packages/gradle/src/executors/build/micronaut/executor.spec.ts @@ -0,0 +1,46 @@ +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 = {}; +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', + }, + projectsConfigurations: { + version: 2, + projects: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + 'my-app': { + root: 'apps/wibble', + sourceRoot: 'apps/wibble', + }, + }, + }, + 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/gradle/src/executors/build/micronaut/executor.ts b/packages/gradle/src/executors/build/micronaut/executor.ts new file mode 100644 index 000000000..8d9a333a8 --- /dev/null +++ b/packages/gradle/src/executors/build/micronaut/executor.ts @@ -0,0 +1,14 @@ +import { runCommand } from '@jnxplus/common'; +import { ExecutorContext, logger } from '@nx/devkit'; +import { getExecutable, getProjectPath } from '../../../.'; +import { BuildExecutorSchema } from './schema'; + +export default async function runExecutor( + options: BuildExecutorSchema, + context: ExecutorContext +) { + logger.info(`Executor ran for Build: ${JSON.stringify(options)}`); + return runCommand( + `${getExecutable()} ${getProjectPath(context)}:build -x test` + ); +} diff --git a/packages/gradle/src/executors/build/micronaut/schema.d.ts b/packages/gradle/src/executors/build/micronaut/schema.d.ts new file mode 100644 index 000000000..f8247abd5 --- /dev/null +++ b/packages/gradle/src/executors/build/micronaut/schema.d.ts @@ -0,0 +1 @@ +export interface BuildExecutorSchema {} // eslint-disable-line diff --git a/packages/gradle/src/executors/build/micronaut/schema.json b/packages/gradle/src/executors/build/micronaut/schema.json new file mode 100644 index 000000000..f970a7379 --- /dev/null +++ b/packages/gradle/src/executors/build/micronaut/schema.json @@ -0,0 +1,10 @@ +{ + "version": 2, + "outputCapture": "pipe", + "$schema": "http://json-schema.org/schema", + "title": "Build executor", + "description": "", + "type": "object", + "properties": {}, + "required": [] +} diff --git a/packages/gradle/src/executors/serve/micronaut/executor.spec.ts b/packages/gradle/src/executors/serve/micronaut/executor.spec.ts new file mode 100644 index 000000000..8b5f1dada --- /dev/null +++ b/packages/gradle/src/executors/serve/micronaut/executor.spec.ts @@ -0,0 +1,38 @@ +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); + }); +}); diff --git a/packages/gradle/src/executors/serve/micronaut/executor.ts b/packages/gradle/src/executors/serve/micronaut/executor.ts new file mode 100644 index 000000000..89243cbd7 --- /dev/null +++ b/packages/gradle/src/executors/serve/micronaut/executor.ts @@ -0,0 +1,27 @@ +import { runCommand, waitForever } from '@jnxplus/common'; +import { ExecutorContext, logger } from '@nx/devkit'; + +import { getExecutable, getProjectPath } from '../../../.'; +import { ServeExecutorSchema } from './schema'; + +export default async function runExecutor( + options: ServeExecutorSchema, + context: ExecutorContext +) { + logger.info(`Executor ran for serve: ${JSON.stringify(options)}`); + + let command = `${getExecutable()} ${getProjectPath(context)}:run`; + + if (options.args) { + command += ` --args='${options.args}'`; + } + + const result = runCommand(command); + + if (!result.success) { + return { success: false }; + } + + await waitForever(); + return { success: true }; +} diff --git a/packages/gradle/src/executors/serve/micronaut/schema.d.ts b/packages/gradle/src/executors/serve/micronaut/schema.d.ts new file mode 100644 index 000000000..6d76b1fa9 --- /dev/null +++ b/packages/gradle/src/executors/serve/micronaut/schema.d.ts @@ -0,0 +1,3 @@ +export interface ServeExecutorSchema { + args: string; +} diff --git a/packages/gradle/src/executors/serve/micronaut/schema.json b/packages/gradle/src/executors/serve/micronaut/schema.json new file mode 100644 index 000000000..bb7f863ba --- /dev/null +++ b/packages/gradle/src/executors/serve/micronaut/schema.json @@ -0,0 +1,14 @@ +{ + "version": 2, + "outputCapture": "pipe", + "$schema": "http://json-schema.org/schema", + "title": "Serve executor", + "description": "", + "type": "object", + "properties": { + "args": { + "type": "string" + } + }, + "required": [] +} diff --git a/packages/nx-micronaut-gradle/.babelrc b/packages/nx-micronaut-gradle/.babelrc new file mode 100644 index 000000000..fd4cbcdef --- /dev/null +++ b/packages/nx-micronaut-gradle/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + [ + "@nx/js/babel", + { + "useBuiltIns": "usage" + } + ] + ] +} diff --git a/packages/nx-micronaut-gradle/.eslintrc.json b/packages/nx-micronaut-gradle/.eslintrc.json new file mode 100644 index 000000000..9d9c0db55 --- /dev/null +++ b/packages/nx-micronaut-gradle/.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-gradle/CHANGELOG.md b/packages/nx-micronaut-gradle/CHANGELOG.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/README.md b/packages/nx-micronaut-gradle/README.md new file mode 100644 index 000000000..ee3121300 --- /dev/null +++ b/packages/nx-micronaut-gradle/README.md @@ -0,0 +1,55 @@ +# @jnxplus/nx-micronaut-gradle + +[![npm version](https://badge.fury.io/js/@jnxplus%2Fnx-micronaut-gradle.svg)](https://badge.fury.io/js/@jnxplus%2Fnx-micronaut-gradle) + +This plugin adds Spring micronaut and Gradle multi-project builds 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-gradle | Nx | Spring micronaut | +| ---------------------------- | ------ | ---------------- | +| 6.x.x | 16.x.x | 3.x.x | +| 5.x.x | 15.x.x | 3.x.x | + +## Getting Started + +### 0. Prerequisites + +`@jnxplus/nx-micronaut-gradle` 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-gradle +``` + +### 2. Add Spring micronaut and Gradle wrapper support + +The following command adds Spring micronaut and Gradle support (Gradle wrapper and config files) to the workspace. This only needs to be performed once per workspace. + +```bash +nx generate @jnxplus/nx-micronaut-gradle:init +``` + +### 3. Usage + +| Action | Command | +| ------------------------------------ | ------------------------------------------------------------------ | +| Generate an application | `nx generate @jnxplus/nx-micronaut-gradle:application my-app-name` | +| Generate a library | `nx generate @jnxplus/nx-micronaut-gradle:library my-lib-name` | +| Build a project | `nx build my-project-name` | +| Serve an application | `nx serve my-app-name` | +| Test a project | `nx test my-project-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="test"` | +| Visualize project's dependency graph | `nx dep-graph` | + +## License + +MIT © 2021-2023 Khalil LAGRIDA diff --git a/packages/nx-micronaut-gradle/executors.json b/packages/nx-micronaut-gradle/executors.json new file mode 100644 index 000000000..8124c59ce --- /dev/null +++ b/packages/nx-micronaut-gradle/executors.json @@ -0,0 +1,45 @@ +{ + "$schema": "http://json-schema.org/schema", + "executors": { + "build": { + "implementation": "@jnxplus/gradle/src/executors/build/micronaut/executor", + "schema": "@jnxplus/gradle/src/executors/build/micronaut/schema.json", + "description": "build executor" + }, + "build-image": { + "implementation": "@jnxplus/gradle/src/executors/build-image/micronaut/executor", + "schema": "@jnxplus/gradle/src/executors/build-image/micronaut/schema.json", + "description": "build-image executor" + }, + "serve": { + "implementation": "@jnxplus/gradle/src/executors/serve/micronaut/executor", + "schema": "@jnxplus/gradle/src/executors/serve/micronaut/schema.json", + "description": "serve executor" + }, + "lint": { + "implementation": "@jnxplus/gradle/src/executors/lint/executor", + "schema": "@jnxplus/common/src/executors/lint/schema.json", + "description": "lint executor" + }, + "test": { + "implementation": "@jnxplus/gradle/src/executors/test/executor", + "schema": "@jnxplus/gradle/src/executors/test/schema.json", + "description": "test executor" + }, + "ktformat": { + "implementation": "@jnxplus/gradle/src/executors/ktformat/executor", + "schema": "@jnxplus/common/src/executors/ktformat/schema.json", + "description": "kotlin format executor" + }, + "kformat": { + "implementation": "@jnxplus/gradle/src/executors/ktformat/executor", + "schema": "@jnxplus/common/src/executors/ktformat/schema.json", + "description": "(Deprecated) kotlin format executor" + }, + "run-task": { + "implementation": "@jnxplus/gradle/src/executors/run-task/executor", + "schema": "@jnxplus/gradle/src/executors/run-task/schema.json", + "description": "run-task executor" + } + } +} diff --git a/packages/nx-micronaut-gradle/generators.json b/packages/nx-micronaut-gradle/generators.json new file mode 100644 index 000000000..3cb084338 --- /dev/null +++ b/packages/nx-micronaut-gradle/generators.json @@ -0,0 +1,31 @@ +{ + "$schema": "http://json-schema.org/schema", + "name": "nx-micronaut-gradle", + "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" + } + } +} diff --git a/packages/nx-micronaut-gradle/jest.config.ts b/packages/nx-micronaut-gradle/jest.config.ts new file mode 100644 index 000000000..8307b2a29 --- /dev/null +++ b/packages/nx-micronaut-gradle/jest.config.ts @@ -0,0 +1,18 @@ +/* eslint-disable */ +export default { + displayName: 'nx-micronaut-gradle', + + globals: {}, + testEnvironment: 'node', + transform: { + '^.+\\.[tj]sx?$': [ + 'ts-jest', + { + tsconfig: '/tsconfig.spec.json', + }, + ], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/packages/nx-micronaut-gradle', + preset: '../../jest.preset.js', +}; diff --git a/packages/nx-micronaut-gradle/package.json b/packages/nx-micronaut-gradle/package.json new file mode 100644 index 000000000..24a998791 --- /dev/null +++ b/packages/nx-micronaut-gradle/package.json @@ -0,0 +1,37 @@ +{ + "name": "@jnxplus/nx-micronaut-gradle", + "version": "6.7.0", + "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-gradle/README.md", + "bugs": { + "url": "https://github.com/khalilou88/jnxplus/issues" + }, + "keywords": [ + "nx", + "nx-workspace", + "nx-plugin", + "java", + "spring", + "spring-micronaut", + "gradle", + "gradle multi-project build" + ], + "scripts": { + "postinstall": "node src/scripts/install-linters.js" + }, + "dependencies": { + "prettier-plugin-java": "^2.1.0" + }, + "peerDependencies": { + "@nx/devkit": ">=16.0.0" + } +} diff --git a/packages/nx-micronaut-gradle/project.json b/packages/nx-micronaut-gradle/project.json new file mode 100644 index 000000000..ca41ec805 --- /dev/null +++ b/packages/nx-micronaut-gradle/project.json @@ -0,0 +1,102 @@ +{ + "name": "nx-micronaut-gradle", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "packages/nx-micronaut-gradle/src", + "projectType": "library", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/packages/nx-micronaut-gradle", + "main": "packages/nx-micronaut-gradle/src/index.ts", + "packageJson": "packages/nx-micronaut-gradle/package.json", + "tsConfig": "packages/nx-micronaut-gradle/tsconfig.lib.json", + "updateBuildableProjectDepsInPackageJson": true, + "buildableProjectDepsInPackageJsonType": "dependencies", + "assets": [ + "packages/nx-micronaut-gradle/*.md", + { + "input": "./packages/nx-micronaut-gradle/src", + "glob": "**/!(*.ts)", + "output": "./src" + }, + { + "input": "./packages/nx-micronaut-gradle/src", + "glob": "**/*.d.ts", + "output": "./src" + }, + { + "input": "./packages/nx-micronaut-gradle", + "glob": "generators.json", + "output": "." + }, + { + "input": "./packages/nx-micronaut-gradle", + "glob": "executors.json", + "output": "." + }, + { + "input": "./packages/gradle-plugin", + "glob": "gradle/**", + "output": "./src/generators/init/files/gradle/wrapper" + }, + { + "input": "./packages/gradle-plugin", + "glob": "gradlew", + "output": "./src/generators/init/files/gradle/wrapper" + }, + { + "input": "./packages/gradle-plugin", + "glob": "gradlew.bat", + "output": "./src/generators/init/files/gradle/wrapper" + } + ] + } + }, + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["packages/nx-micronaut-gradle/**/*.ts"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/packages/nx-micronaut-gradle"], + "options": { + "jestConfig": "packages/nx-micronaut-gradle/jest.config.ts", + "passWithNoTests": true + } + }, + "version": { + "executor": "@jscutlery/semver:version", + "options": { + "preset": "angular", + "trackDeps": true, + "push": true, + "noVerify": true, + "postTargets": [ + "nx-micronaut-gradle:github", + "nx-micronaut-gradle: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-gradle/src/dep-graph/lookup-deps.ts b/packages/nx-micronaut-gradle/src/dep-graph/lookup-deps.ts new file mode 100644 index 000000000..c727efc07 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/dep-graph/lookup-deps.ts @@ -0,0 +1,17 @@ +import { addProjectsAndDependencies } from '@jnxplus/gradle'; +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-gradle'); + return builder.getUpdatedProjectGraph(); +} diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/java/README.md b/packages/nx-micronaut-gradle/src/generators/application/files/java/README.md new file mode 100644 index 000000000..3a199b958 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/java/build.gradle__kotlinExtension__ b/packages/nx-micronaut-gradle/src/generators/application/files/java/build.gradle__kotlinExtension__ new file mode 100644 index 000000000..93e598035 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/files/java/build.gradle__kotlinExtension__ @@ -0,0 +1,87 @@ +<% if(dsl === 'groovy') { -%> +plugins { + id "com.github.johnrengelman.shadow" + id "io.micronaut.application" +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + +repositories { + mavenCentral() +} + +dependencies { + implementation "io.micronaut:micronaut-jackson-databind" + runtimeOnly "ch.qos.logback:logback-classic" + testImplementation "io.micronaut:micronaut-http-client" +<% if(configFormat === '.yml') { -%> + runtimeOnly "org.yaml:snakeyaml" +<% } -%> +} + +application { + mainClass.set("<%= packageName %>.Application") +} + +java { + sourceCompatibility = JavaVersion.toVersion("${javaVersion}") + targetCompatibility = JavaVersion.toVersion("${javaVersion}") +} + +graalvmNative.toolchainDetection = false + +micronaut { + runtime("netty") + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> +<% if(dsl === 'kotlin') { -%> +val javaVersion: String by project + +plugins { + id("com.github.johnrengelman.shadow") + id("io.micronaut.application") +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + +repositories { + mavenCentral() +} + +dependencies { + implementation("io.micronaut:micronaut-jackson-databind") + runtimeOnly("ch.qos.logback:logback-classic") + testImplementation("io.micronaut:micronaut-http-client") +<% if(configFormat === '.yml') { -%> + runtimeOnly("org.yaml:snakeyaml") +<% } -%> +} + + +application { + mainClass.set("<%= packageName %>.Application") +} + +java { + sourceCompatibility = JavaVersion.toVersion(javaVersion) + targetCompatibility = JavaVersion.toVersion(javaVersion) +} + +graalvmNative.toolchainDetection.set(false) + +micronaut { + runtime("netty") + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/java/.gitkeep b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/java/__packageDirectory__/Application.java b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/java/__packageDirectory__/Application.java new file mode 100644 index 000000000..c62bcbf95 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/java/src/main/java/__packageDirectory__/HelloController.java b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/java/__packageDirectory__/HelloController.java new file mode 100644 index 000000000..0c8d1b597 --- /dev/null +++ b/packages/nx-micronaut-gradle/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") +public class HelloController { + @Get + @Produces(MediaType.TEXT_PLAIN) + public String index() { + return "Hello World"; + } +} diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/resources/application__configFormat__ b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/resources/application__configFormat__ new file mode 100644 index 000000000..2ce5623b0 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/resources/application__configFormat__ @@ -0,0 +1,20 @@ +<% if(configFormat === '.properties') { -%> +micronaut.application.name=<%= appClassName %> +<% if(isCustomPort) { -%> +micronaut.server.port=<%= port %> +<% } -%> +netty.default.allocator.max-order=3 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + application: + name: <%= appClassName %> +<% if(isCustomPort) { -%> + server: + port: <%= port %> +<% } -%> +netty: + default: + allocator: + max-order: 3 +<% } -%> diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/resources/logback.xml b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/main/resources/logback.xml new file mode 100644 index 000000000..44b79c40d --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/java/src/test/java/.gitkeep b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/test/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/java/src/test/java/__packageDirectory__/HelloControllerTest.java b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/test/java/__packageDirectory__/HelloControllerTest.java new file mode 100644 index 000000000..4c5b94a1e --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/java/src/test/java/__packageDirectory__/__appClassName__Test.java b/packages/nx-micronaut-gradle/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-gradle/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-gradle/src/generators/application/files/java/src/test/resources/application__configFormat__ b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/test/resources/application__configFormat__ new file mode 100644 index 000000000..62afe055d --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/files/java/src/test/resources/application__configFormat__ @@ -0,0 +1,9 @@ +<% if(configFormat === '.properties') { -%> +micronaut.server.port=-1 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + server: + port: -1 +<% } -%> + diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/README.md b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/README.md new file mode 100644 index 000000000..71ebd69f4 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/kotlin/build.gradle__kotlinExtension__ b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/build.gradle__kotlinExtension__ new file mode 100644 index 000000000..cbd2e00ed --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/build.gradle__kotlinExtension__ @@ -0,0 +1,130 @@ +<% if(dsl === 'groovy') { -%> +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.allopen" + id "com.google.devtools.ksp" + id "com.github.johnrengelman.shadow" + id "io.micronaut.application" +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + +repositories { + mavenCentral() +} + +dependencies { + implementation "io.micronaut:micronaut-jackson-databind" + implementation "io.micronaut.kotlin:micronaut-kotlin-runtime" + implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}" + runtimeOnly "ch.qos.logback:logback-classic" + runtimeOnly "com.fasterxml.jackson.module:jackson-module-kotlin" + testImplementation "io.micronaut:micronaut-http-client" +<% if(configFormat === '.yml') { -%> + runtimeOnly "org.yaml:snakeyaml" +<% } -%> +} + +application { + mainClass.set("<%= packageName %>.ApplicationKt") +} + +java { + sourceCompatibility = JavaVersion.toVersion("${javaVersion}") +} + +tasks { + compileKotlin { + compilerOptions { + jvmTarget = JvmTarget.valueOf("JVM_${javaVersion}") + } + } + compileTestKotlin { + compilerOptions { + jvmTarget = JvmTarget.valueOf("JVM_${javaVersion}") + } + } +} + +graalvmNative.toolchainDetection = false + +micronaut { + runtime("netty") + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> +<% if(dsl === 'kotlin') { -%> +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +val javaVersion: String by project +val kotlinVersion: String by project + +plugins { + id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.plugin.allopen") + id("com.google.devtools.ksp") + id("com.github.johnrengelman.shadow") + id("io.micronaut.application") +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + + +repositories { + mavenCentral() +} + +dependencies { + implementation("io.micronaut:micronaut-jackson-databind") + implementation("io.micronaut.kotlin:micronaut-kotlin-runtime") + implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}") + runtimeOnly("ch.qos.logback:logback-classic") + runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin") + testImplementation("io.micronaut:micronaut-http-client") +<% if(configFormat === '.yml') { -%> + runtimeOnly("org.yaml:snakeyaml") +<% } -%> +} + +application { + mainClass.set("<%= packageName %>.ApplicationKt") +} + +java { + sourceCompatibility = JavaVersion.toVersion(javaVersion) +} + +tasks { + compileKotlin { + compilerOptions { + jvmTarget.set(JvmTarget.valueOf("JVM_${javaVersion}")) + } + } + compileTestKotlin { + compilerOptions { + jvmTarget.set(JvmTarget.valueOf("JVM_${javaVersion}")) + } + } +} + +graalvmNative.toolchainDetection.set(false) + +micronaut { + runtime("netty") + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/kotlin/.gitkeep b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/Application.kt b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/Application.kt new file mode 100644 index 000000000..813480268 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/HelloController.kt b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/kotlin/__packageDirectory__/HelloController.kt new file mode 100644 index 000000000..63d28d162 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/kotlin/src/main/resources/application__configFormat__ b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/resources/application__configFormat__ new file mode 100644 index 000000000..2ce5623b0 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/resources/application__configFormat__ @@ -0,0 +1,20 @@ +<% if(configFormat === '.properties') { -%> +micronaut.application.name=<%= appClassName %> +<% if(isCustomPort) { -%> +micronaut.server.port=<%= port %> +<% } -%> +netty.default.allocator.max-order=3 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + application: + name: <%= appClassName %> +<% if(isCustomPort) { -%> + server: + port: <%= port %> +<% } -%> +netty: + default: + allocator: + max-order: 3 +<% } -%> diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/resources/logback.xml b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/main/resources/logback.xml new file mode 100644 index 000000000..44b79c40d --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/kotlin/src/test/kotlin/.gitkeep b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/test/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/HelloControllerTest.kt b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/HelloControllerTest.kt new file mode 100644 index 000000000..48ae65edf --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/application/files/kotlin/src/test/kotlin/__packageDirectory__/__appClassName__Test.kt b/packages/nx-micronaut-gradle/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-gradle/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-gradle/src/generators/application/files/kotlin/src/test/resources/application__configFormat__ b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/test/resources/application__configFormat__ new file mode 100644 index 000000000..62afe055d --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/files/kotlin/src/test/resources/application__configFormat__ @@ -0,0 +1,9 @@ +<% if(configFormat === '.properties') { -%> +micronaut.server.port=-1 +<% } -%> +<% if(configFormat === '.yml') { -%> +micronaut: + server: + port: -1 +<% } -%> + diff --git a/packages/nx-micronaut-gradle/src/generators/application/generator.spec.ts b/packages/nx-micronaut-gradle/src/generators/application/generator.spec.ts new file mode 100644 index 000000000..a9431e70e --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/generator.spec.ts @@ -0,0 +1,32 @@ +import { readProjectConfiguration, Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import generator from './generator'; +import { NxMicronautGradleAppGeneratorSchema } from './schema'; + +describe('application generator', () => { + let appTree: Tree; + const options: NxMicronautGradleAppGeneratorSchema = { + name: 'test', + language: 'java', + groupId: 'com.example', + projectVersion: '0.0.1-SNAPSHOT', + packaging: 'jar', + configFormat: '.yml', + minimal: false, + port: 8080, + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write( + './settings.gradle', + "rootProject.name = 'boot-multi-project'" + ); + }); + + it('should run successfully', async () => { + await generator(appTree, options); + const config = readProjectConfiguration(appTree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/packages/nx-micronaut-gradle/src/generators/application/generator.ts b/packages/nx-micronaut-gradle/src/generators/application/generator.ts new file mode 100644 index 000000000..e1517cdd3 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/generator.ts @@ -0,0 +1,250 @@ +import { + addProjectConfiguration, + formatFiles, + generateFiles, + getWorkspaceLayout, + joinPathFragments, + names, + offsetFromRoot, + Tree, +} from '@nx/devkit'; +import * as path from 'path'; +import { DSLType, normalizeName } from '@jnxplus/common'; +import { LinterType } from '@jnxplus/common'; +import { NxMicronautGradleAppGeneratorSchema } from './schema'; +import { getDsl } from '@jnxplus/gradle'; + +interface NormalizedSchema extends NxMicronautGradleAppGeneratorSchema { + projectName: string; + projectRoot: string; + projectDirectory: string; + parsedTags: string[]; + appClassName: string; + packageName: string; + packageDirectory: string; + linter?: LinterType; + isCustomPort: boolean; + dsl: DSLType; + kotlinExtension: string; +} + +function normalizeOptions( + tree: Tree, + options: NxMicronautGradleAppGeneratorSchema +): 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()) + : []; + + //TODO Change this property name + const appClassName = `${names(projectName).className}`; + + 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 isCustomPort = !!options.port && +options.port !== 8080; + + const dsl = getDsl(tree); + const kotlinExtension = dsl === 'kotlin' ? '.kts' : ''; + + return { + ...options, + projectName, + projectRoot, + projectDirectory, + parsedTags, + appClassName, + packageName, + packageDirectory, + linter, + isCustomPort, + dsl, + kotlinExtension, + }; +} + +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: NxMicronautGradleAppGeneratorSchema +) { + 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-gradle:build', + options: { + packaging: `${normalizedOptions.packaging}`, + }, + }, + 'build-image': { + executor: '@jnxplus/nx-micronaut-gradle:build-image', + }, + serve: { + executor: '@jnxplus/nx-micronaut-gradle:serve', + }, + lint: { + executor: '@jnxplus/nx-micronaut-gradle:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-gradle:test', + }, + }, + tags: normalizedOptions.parsedTags, + }); + } else { + addProjectConfiguration(tree, normalizedOptions.projectName, { + root: normalizedOptions.projectRoot, + projectType: 'application', + sourceRoot: `${normalizedOptions.projectRoot}/src`, + targets: { + build: { + executor: '@jnxplus/nx-micronaut-gradle:build', + options: { + packaging: `${normalizedOptions.packaging}`, + }, + }, + 'build-image': { + executor: '@jnxplus/nx-micronaut-gradle:build-image', + }, + serve: { + executor: '@jnxplus/nx-micronaut-gradle:serve', + }, + lint: { + executor: '@jnxplus/nx-micronaut-gradle:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-gradle:test', + }, + ktformat: { + executor: '@jnxplus/nx-micronaut-gradle:ktformat', + }, + }, + tags: normalizedOptions.parsedTags, + }); + } + + addFiles(tree, normalizedOptions); + addProjectToGradleSetting(tree, normalizedOptions); + await formatFiles(tree); +} + +function addProjectToGradleSetting(tree: Tree, options: NormalizedSchema) { + const filePath = `settings.gradle`; + const ktsFilePath = `settings.gradle.kts`; + const regex = /.*rootProject\.name.*/; + const gradleProjectPath = options.projectRoot.replace( + new RegExp('/', 'g'), + ':' + ); + + if (tree.exists(filePath)) { + const settingsContent = tree.read(filePath, 'utf-8') || ''; + + const newSettingsContent = settingsContent.replace( + regex, + `$&\ninclude('${gradleProjectPath}')` + ); + tree.write(filePath, newSettingsContent); + } + + if (tree.exists(ktsFilePath)) { + const settingsContent = tree.read(ktsFilePath, 'utf-8') || ''; + + const newSettingsContent = settingsContent.replace( + regex, + `$&\ninclude("${gradleProjectPath}")` + ); + tree.write(ktsFilePath, newSettingsContent); + } +} diff --git a/packages/nx-micronaut-gradle/src/generators/application/schema.d.ts b/packages/nx-micronaut-gradle/src/generators/application/schema.d.ts new file mode 100644 index 000000000..1c485b2e1 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/schema.d.ts @@ -0,0 +1,16 @@ +import { LanguageType, PackagingType } from '@jnxplus/common'; + +export interface NxMicronautGradleAppGeneratorSchema { + name: string; + tags?: string; + directory?: string; + simpleName?: boolean; + simplePackageName?: boolean; + language: LanguageType; + groupId: string; + projectVersion: string; + packaging: PackagingType; + configFormat: '.properties' | '.yml'; + minimal?: boolean; + port?: string | number; +} diff --git a/packages/nx-micronaut-gradle/src/generators/application/schema.json b/packages/nx-micronaut-gradle/src/generators/application/schema.json new file mode 100644 index 000000000..a90cfc173 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/application/schema.json @@ -0,0 +1,132 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxMicronautGradleApp", + "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?" + }, + "packaging": { + "description": "Packaging of the project", + "type": "string", + "default": "jar", + "x-prompt": { + "message": "Which packaging would you like to use?", + "type": "list", + "items": [ + { + "value": "jar", + "label": "Jar" + }, + { + "value": "war", + "label": "War" + } + ] + } + }, + "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" + } + ] + } + }, + "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", + "packaging", + "configFormat" + ] +} diff --git a/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/build.gradle__kotlinExtension__ b/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/build.gradle__kotlinExtension__ new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/build.gradle__kotlinExtension__ @@ -0,0 +1 @@ + diff --git a/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/gradle.properties b/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/gradle.properties new file mode 100644 index 000000000..f4d593ac5 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/gradle.properties @@ -0,0 +1,5 @@ +javaVersion=<%= javaVersion %> +kotlinVersion=<%= kotlinVersion %> +micronautVersion=<%= micronautVersion %> +checkstyleVersion=<%= checkstyleVersion %> +ktlintVersion=<%= ktlintVersion %> diff --git a/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/settings.gradle__kotlinExtension__ b/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/settings.gradle__kotlinExtension__ new file mode 100644 index 000000000..95984ecaf --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/files/gradle/config/settings.gradle__kotlinExtension__ @@ -0,0 +1,28 @@ +<% if(dsl === 'groovy') { -%> +pluginManagement { + plugins { + id 'org.jetbrains.kotlin.jvm' version "${kotlinVersion}" + id 'org.jetbrains.kotlin.plugin.allopen' version "${kotlinVersion}" + id 'com.google.devtools.ksp' version "1.8.20-1.0.10" + id 'com.github.johnrengelman.shadow' version "8.1.1" + id 'io.micronaut.application' version "${micronautVersion}" + id 'io.micronaut.library' version "${micronautVersion}" + } +} +rootProject.name = '<%= rootProjectName %>' +<% } -%> +<% if(dsl === 'kotlin') { -%> +pluginManagement { + val kotlinVersion: String by settings + val micronautVersion: String by settings + plugins { + id("org.jetbrains.kotlin.jvm") version kotlinVersion + id("org.jetbrains.kotlin.plugin.allopen") version kotlinVersion + id("com.google.devtools.ksp") version "1.8.20-1.0.10" + id("com.github.johnrengelman.shadow") version "8.1.1" + id("io.micronaut.application") version micronautVersion + id("io.micronaut.library") version micronautVersion + } +} +rootProject.name = "<%= rootProjectName %>" +<% } -%> diff --git a/packages/nx-micronaut-gradle/src/generators/init/files/linters/checkstyle.xml b/packages/nx-micronaut-gradle/src/generators/init/files/linters/checkstyle.xml new file mode 100644 index 000000000..6e8881117 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/files/linters/checkstyle.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/nx-micronaut-gradle/src/generators/init/files/linters/pmd.xml b/packages/nx-micronaut-gradle/src/generators/init/files/linters/pmd.xml new file mode 100644 index 000000000..9e5e30b29 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/init/generator.spec.ts b/packages/nx-micronaut-gradle/src/generators/init/generator.spec.ts new file mode 100644 index 000000000..b9e244e03 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/generator.spec.ts @@ -0,0 +1,25 @@ +import { Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import generator from './generator'; +import { NxMicronautGradleGeneratorSchema } from './schema'; + +describe('init generator', () => { + let appTree: Tree; + const options: NxMicronautGradleGeneratorSchema = { + javaVersion: 17, + dsl: 'groovy', + rootProjectName: 'test-boot-multiproject', + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write('./.gitignore', ''); + appTree.write('./.prettierignore', ''); + }); + + xit('should run successfully', async () => { + await generator(appTree, options); + const settingsGradleExists = appTree.exists('settings.gradle'); + expect(settingsGradleExists).toBeTruthy(); + }); +}); diff --git a/packages/nx-micronaut-gradle/src/generators/init/generator.ts b/packages/nx-micronaut-gradle/src/generators/init/generator.ts new file mode 100644 index 000000000..1f1c6e82d --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/generator.ts @@ -0,0 +1,80 @@ +import { + checkstyleVersion, + ktlintVersion, + micronautKotlinVersion, + micronautVersion, + updateNxJson, +} from '@jnxplus/common'; +import { + addOrUpdateGitattributes, + addOrUpdatePrettierIgnore, + updateGitIgnore, +} from '@jnxplus/gradle'; +import { Tree, formatFiles, generateFiles, offsetFromRoot } from '@nx/devkit'; +import * as path from 'path'; +import { NxMicronautGradleGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxMicronautGradleGeneratorSchema { + kotlinExtension: string; + micronautVersion: string; + kotlinVersion: string; + checkstyleVersion: string; + ktlintVersion: string; +} + +function normalizeOptions( + tree: Tree, + options: NxMicronautGradleGeneratorSchema +): NormalizedSchema { + const kotlinExtension = options.dsl === 'kotlin' ? '.kts' : ''; + + return { + ...options, + kotlinExtension, + micronautVersion, + kotlinVersion: micronautKotlinVersion, + checkstyleVersion, + ktlintVersion, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + offsetFromRoot: offsetFromRoot(tree.root), + template: '', + }; + generateFiles( + tree, + path.join(__dirname, 'files', 'gradle', 'wrapper'), + '', + templateOptions + ); + generateFiles( + tree, + path.join(__dirname, 'files', 'gradle', 'config'), + '', + templateOptions + ); + generateFiles( + tree, + path.join(__dirname, 'files', 'linters'), + 'tools/linters', + templateOptions + ); +} + +export default async function ( + tree: Tree, + options: NxMicronautGradleGeneratorSchema +) { + const normalizedOptions = normalizeOptions(tree, options); + addFiles(tree, normalizedOptions); + updateNxJson(tree, '@jnxplus/nx-micronaut-gradle'); + updateGitIgnore(tree); + addOrUpdatePrettierIgnore(tree); + addOrUpdateGitattributes(tree); + tree.changePermissions('gradlew', '755'); + tree.changePermissions('gradlew.bat', '755'); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-gradle/src/generators/init/schema.d.ts b/packages/nx-micronaut-gradle/src/generators/init/schema.d.ts new file mode 100644 index 000000000..d277d2a4b --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/schema.d.ts @@ -0,0 +1,7 @@ +import { DSLType } from '@jnxplus/common'; + +export interface NxMicronautGradleGeneratorSchema { + javaVersion: string | number; + dsl: DSLType; + rootProjectName: string; +} diff --git a/packages/nx-micronaut-gradle/src/generators/init/schema.json b/packages/nx-micronaut-gradle/src/generators/init/schema.json new file mode 100644 index 000000000..9fa445752 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/init/schema.json @@ -0,0 +1,60 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxMicronautGradleInit", + "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": "20", + "label": "20" + }, + { + "value": "17", + "label": "17" + } + ] + } + }, + "dsl": { + "description": "Build DSL", + "type": "string", + "default": "groovy", + "x-prompt": { + "message": "Which build DSL would you like to use?", + "type": "list", + "items": [ + { + "value": "groovy", + "label": "Groovy build DSL" + }, + { + "value": "kotlin", + "label": "Kotlin build DSL" + } + ] + } + }, + "rootProjectName": { + "type": "string", + "default": "spring-boot-root-project", + "x-prompt": "What rootProjectName would you like to use?", + "pattern": "^[a-zA-Z].*$" + } + }, + "required": ["javaVersion", "dsl", "rootProjectName"] +} diff --git a/packages/nx-micronaut-gradle/src/generators/library/files/java/build.gradle__kotlinExtension__ b/packages/nx-micronaut-gradle/src/generators/library/files/java/build.gradle__kotlinExtension__ new file mode 100644 index 000000000..1033e0259 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/library/files/java/build.gradle__kotlinExtension__ @@ -0,0 +1,64 @@ +<% if(dsl === 'groovy') { -%> +plugins { + id "com.github.johnrengelman.shadow" + id "io.micronaut.library" +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + +repositories { + mavenCentral() +} + +dependencies { + implementation "io.micronaut:micronaut-jackson-databind" + testImplementation "io.micronaut:micronaut-http-client" +} + +java { + sourceCompatibility = JavaVersion.toVersion("${javaVersion}") + targetCompatibility = JavaVersion.toVersion("${javaVersion}") +} + +micronaut { + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> +<% if(dsl === 'kotlin') { -%> +val javaVersion: String by project + +plugins { + id("com.github.johnrengelman.shadow") + id("io.micronaut.library") +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + +repositories { + mavenCentral() +} + +dependencies { + implementation("io.micronaut:micronaut-jackson-databind") + testImplementation("io.micronaut:micronaut-http-client") +} + +java { + sourceCompatibility = JavaVersion.toVersion(javaVersion) + targetCompatibility = JavaVersion.toVersion(javaVersion) +} + +micronaut { + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> diff --git a/packages/nx-micronaut-gradle/src/generators/library/files/java/src/main/java/.gitkeep b/packages/nx-micronaut-gradle/src/generators/library/files/java/src/main/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/library/files/java/src/main/java/__packageDirectory__/HelloService.java b/packages/nx-micronaut-gradle/src/generators/library/files/java/src/main/java/__packageDirectory__/HelloService.java new file mode 100644 index 000000000..73995e06f --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/library/files/java/src/test/java/.gitkeep b/packages/nx-micronaut-gradle/src/generators/library/files/java/src/test/java/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/library/files/java/src/test/java/__packageDirectory__/HelloServiceTest.java b/packages/nx-micronaut-gradle/src/generators/library/files/java/src/test/java/__packageDirectory__/HelloServiceTest.java new file mode 100644 index 000000000..f84f85be9 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/library/files/kotlin/build.gradle__kotlinExtension__ b/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/build.gradle__kotlinExtension__ new file mode 100644 index 000000000..4f336ffa9 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/build.gradle__kotlinExtension__ @@ -0,0 +1,109 @@ +<% if(dsl === 'groovy') { -%> +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + id "org.jetbrains.kotlin.jvm" + id "org.jetbrains.kotlin.plugin.allopen" + id "com.google.devtools.ksp" + id "com.github.johnrengelman.shadow" + id "io.micronaut.library" +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + +repositories { + mavenCentral() +} + +dependencies { + implementation "io.micronaut:micronaut-jackson-databind" + implementation "io.micronaut.kotlin:micronaut-kotlin-runtime" + implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}" + runtimeOnly "com.fasterxml.jackson.module:jackson-module-kotlin" + testImplementation "io.micronaut:micronaut-http-client" +} + +java { + sourceCompatibility = JavaVersion.toVersion("${javaVersion}") +} + +tasks { + compileKotlin { + compilerOptions { + jvmTarget = JvmTarget.valueOf("JVM_${javaVersion}") + } + } + compileTestKotlin { + compilerOptions { + jvmTarget = JvmTarget.valueOf("JVM_${javaVersion}") + } + } +} + +micronaut { + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> +<% if(dsl === 'kotlin') { -%> +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +val javaVersion: String by project +val kotlinVersion: String by project + +plugins { + id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.plugin.allopen") + id("com.google.devtools.ksp") + id("com.github.johnrengelman.shadow") + id("io.micronaut.library") +} + +version = "<%= projectVersion %>" +group = "<%= groupId %>" + + +repositories { + mavenCentral() +} + +dependencies { + implementation("io.micronaut:micronaut-jackson-databind") + implementation("io.micronaut.kotlin:micronaut-kotlin-runtime") + implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}") + runtimeOnly("com.fasterxml.jackson.module:jackson-module-kotlin") + testImplementation("io.micronaut:micronaut-http-client") +} + +java { + sourceCompatibility = JavaVersion.toVersion(javaVersion) +} + +tasks { + compileKotlin { + compilerOptions { + jvmTarget.set(JvmTarget.valueOf("JVM_${javaVersion}")) + } + } + compileTestKotlin { + compilerOptions { + jvmTarget.set(JvmTarget.valueOf("JVM_${javaVersion}")) + } + } +} + +micronaut { + runtime("netty") + testRuntime("junit5") + processing { + incremental(true) + annotations("<%= packageName %>.*") + } +} +<% } -%> diff --git a/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/src/main/kotlin/.gitkeep b/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/src/main/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/src/main/kotlin/__packageDirectory__/HelloService.kt b/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/src/main/kotlin/__packageDirectory__/HelloService.kt new file mode 100644 index 000000000..fef36567e --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/library/files/kotlin/src/test/kotlin/.gitkeep b/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/src/test/kotlin/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/src/test/kotlin/__packageDirectory__/HelloServiceTest.kt b/packages/nx-micronaut-gradle/src/generators/library/files/kotlin/src/test/kotlin/__packageDirectory__/HelloServiceTest.kt new file mode 100644 index 000000000..e65a5650b --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/src/generators/library/generator.spec.ts b/packages/nx-micronaut-gradle/src/generators/library/generator.spec.ts new file mode 100644 index 000000000..ea749c73b --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/library/generator.spec.ts @@ -0,0 +1,29 @@ +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { Tree, readProjectConfiguration } from '@nx/devkit'; + +import generator from './generator'; +import { NxMicronautGradleLibGeneratorSchema } from './schema'; + +describe('library generator', () => { + let appTree: Tree; + const options: NxMicronautGradleLibGeneratorSchema = { + name: 'test', + language: 'java', + groupId: 'com.example', + projectVersion: '0.0.1-SNAPSHOT', + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write( + './settings.gradle', + "rootProject.name = 'boot-multi-project'" + ); + }); + + it('should run successfully', async () => { + await generator(appTree, options); + const config = readProjectConfiguration(appTree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/packages/nx-micronaut-gradle/src/generators/library/generator.ts b/packages/nx-micronaut-gradle/src/generators/library/generator.ts new file mode 100644 index 000000000..3e03460ce --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/library/generator.ts @@ -0,0 +1,203 @@ +import { DSLType, LinterType, normalizeName } from '@jnxplus/common'; +import { + addLibraryToProjects, + addProjectToGradleSetting, + getDsl, +} from '@jnxplus/gradle'; +import { + addProjectConfiguration, + formatFiles, + generateFiles, + getWorkspaceLayout, + joinPathFragments, + names, + offsetFromRoot, + Tree, +} from '@nx/devkit'; +import { join } from 'path'; +import { NxMicronautGradleLibGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxMicronautGradleLibGeneratorSchema { + projectName: string; + projectRoot: string; + projectDirectory: string; + parsedTags: string[]; + packageName: string; + packageDirectory: string; + parsedProjects: string[]; + linter?: LinterType; + dsl: DSLType; + kotlinExtension: string; +} + +function normalizeOptions( + tree: Tree, + options: NxMicronautGradleLibGeneratorSchema +): 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 dsl = getDsl(tree); + const kotlinExtension = dsl === 'kotlin' ? '.kts' : ''; + + return { + ...options, + projectName, + projectRoot, + projectDirectory, + parsedTags, + packageName, + packageDirectory, + parsedProjects, + linter, + dsl, + kotlinExtension, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + ...names(options.name), + offsetFromRoot: offsetFromRoot(options.projectRoot), + template: '', + }; + generateFiles( + tree, + 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: NxMicronautGradleLibGeneratorSchema +) { + 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-gradle:build', + }, + lint: { + executor: '@jnxplus/nx-micronaut-gradle:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-gradle:test', + }, + }, + tags: normalizedOptions.parsedTags, + }); + } else { + addProjectConfiguration(tree, normalizedOptions.projectName, { + root: normalizedOptions.projectRoot, + projectType: 'library', + sourceRoot: `${normalizedOptions.projectRoot}/src`, + targets: { + build: { + executor: '@jnxplus/nx-micronaut-gradle:build', + }, + lint: { + executor: '@jnxplus/nx-micronaut-gradle:lint', + options: { + linter: `${normalizedOptions.linter}`, + }, + }, + test: { + executor: '@jnxplus/nx-micronaut-gradle:test', + }, + ktformat: { + executor: '@jnxplus/nx-micronaut-gradle:ktformat', + }, + }, + tags: normalizedOptions.parsedTags, + }); + } + + addFiles(tree, normalizedOptions); + addProjectToGradleSetting(tree, normalizedOptions); + addLibraryToProjects(tree, normalizedOptions); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-gradle/src/generators/library/schema.d.ts b/packages/nx-micronaut-gradle/src/generators/library/schema.d.ts new file mode 100644 index 000000000..a7014ee0b --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/library/schema.d.ts @@ -0,0 +1,14 @@ +import { LanguageType } from '@jnxplus/common'; + +export interface NxMicronautGradleLibGeneratorSchema { + name: string; + tags?: string; + directory?: string; + simpleName?: boolean; + simplePackageName?: boolean; + language: LanguageType; + groupId: string; + projectVersion: string; + projects?: string; + skipStarterCode?: boolean; +} diff --git a/packages/nx-micronaut-gradle/src/generators/library/schema.json b/packages/nx-micronaut-gradle/src/generators/library/schema.json new file mode 100644 index 000000000..02a6f7483 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/library/schema.json @@ -0,0 +1,79 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxMicronautGradleLib", + "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?" + }, + "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-gradle/src/generators/migrate/generator.spec.ts b/packages/nx-micronaut-gradle/src/generators/migrate/generator.spec.ts new file mode 100644 index 000000000..6735cba10 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/migrate/generator.spec.ts @@ -0,0 +1,25 @@ +import { Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import generator from './generator'; +import { NxMicronautGradleMigrateGeneratorSchema } from './schema'; + +describe('migrate generator', () => { + let appTree: Tree; + const options: NxMicronautGradleMigrateGeneratorSchema = { + javaVersion: '17', + dsl: 'groovy', + rootProjectName: 'test-boot-multiproject', + }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace(); + appTree.write('./.gitignore', ''); + appTree.write('./.prettierignore', ''); + }); + + xit('should run successfully', async () => { + await generator(appTree, options); + const gradlew = appTree.exists('gradlew'); + expect(gradlew).toBeTruthy(); + }); +}); diff --git a/packages/nx-micronaut-gradle/src/generators/migrate/generator.ts b/packages/nx-micronaut-gradle/src/generators/migrate/generator.ts new file mode 100644 index 000000000..caac4a1fd --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/migrate/generator.ts @@ -0,0 +1,39 @@ +import { formatFiles, generateFiles, offsetFromRoot, Tree } from '@nx/devkit'; +import * as path from 'path'; +import { NxMicronautGradleMigrateGeneratorSchema } from './schema'; + +interface NormalizedSchema extends NxMicronautGradleMigrateGeneratorSchema {} // eslint-disable-line + +function normalizeOptions( + tree: Tree, + options: NxMicronautGradleMigrateGeneratorSchema +): NormalizedSchema { + return { + ...options, + }; +} + +function addFiles(tree: Tree, options: NormalizedSchema) { + const templateOptions = { + ...options, + offsetFromRoot: offsetFromRoot(tree.root), + template: '', + }; + generateFiles( + tree, + path.join(__dirname, '..', 'init', 'files', 'gradle', 'wrapper'), + '', + templateOptions + ); +} + +export default async function ( + tree: Tree, + options: NxMicronautGradleMigrateGeneratorSchema +) { + const normalizedOptions = normalizeOptions(tree, options); + addFiles(tree, normalizedOptions); + tree.changePermissions('gradlew', '755'); + tree.changePermissions('gradlew.bat', '755'); + await formatFiles(tree); +} diff --git a/packages/nx-micronaut-gradle/src/generators/migrate/schema.d.ts b/packages/nx-micronaut-gradle/src/generators/migrate/schema.d.ts new file mode 100644 index 000000000..c3088c313 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/migrate/schema.d.ts @@ -0,0 +1 @@ +export interface NxMicronautGradleMigrateGeneratorSchema {} // eslint-disable-line diff --git a/packages/nx-micronaut-gradle/src/generators/migrate/schema.json b/packages/nx-micronaut-gradle/src/generators/migrate/schema.json new file mode 100644 index 000000000..e08be2d9b --- /dev/null +++ b/packages/nx-micronaut-gradle/src/generators/migrate/schema.json @@ -0,0 +1,8 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxMicronautGradleMigrate", + "title": "Migrate", + "type": "object", + "properties": {}, + "required": [] +} diff --git a/packages/nx-micronaut-gradle/src/index.ts b/packages/nx-micronaut-gradle/src/index.ts new file mode 100644 index 000000000..38c79a8c1 --- /dev/null +++ b/packages/nx-micronaut-gradle/src/index.ts @@ -0,0 +1 @@ +export { processProjectGraph } from './dep-graph/lookup-deps'; diff --git a/packages/nx-micronaut-gradle/src/scripts/install-linters.ts b/packages/nx-micronaut-gradle/src/scripts/install-linters.ts new file mode 100644 index 000000000..b7369c8bc --- /dev/null +++ b/packages/nx-micronaut-gradle/src/scripts/install-linters.ts @@ -0,0 +1,25 @@ +import { getCheckstylePath, getKtlintPath, isE2eTest } from '@jnxplus/common'; +import { getCheckstyleVersion, getKtlintVersion } from '@jnxplus/gradle'; +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-gradle/tsconfig.json b/packages/nx-micronaut-gradle/tsconfig.json new file mode 100644 index 000000000..f5b85657a --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/tsconfig.lib.json b/packages/nx-micronaut-gradle/tsconfig.lib.json new file mode 100644 index 000000000..3ce6be94e --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle/tsconfig.spec.json b/packages/nx-micronaut-gradle/tsconfig.spec.json new file mode 100644 index 000000000..831ab6481 --- /dev/null +++ b/packages/nx-micronaut-gradle/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-gradle-e2e/jest.config.js b/testing-projects/e2e/nx-micronaut-gradle-e2e/jest.config.js new file mode 100644 index 000000000..347e24b17 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-e2e/jest.config.js @@ -0,0 +1,16 @@ +module.exports = { + displayName: 'nx-micronaut-gradle-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-gradle-e2e', +}; diff --git a/testing-projects/e2e/nx-micronaut-gradle-e2e/project.json b/testing-projects/e2e/nx-micronaut-gradle-e2e/project.json new file mode 100644 index 000000000..b2d794a1b --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-e2e/project.json @@ -0,0 +1,18 @@ +{ + "name": "nx-micronaut-gradle-e2e", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "testing-projects/e2e/nx-micronaut-gradle-e2e/src", + "targets": { + "e2e": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "testing-projects/e2e/nx-micronaut-gradle-e2e/jest.config.js", + "runInBand": true + }, + "dependsOn": ["nx-micronaut-gradle:build"] + } + }, + "tags": [], + "implicitDependencies": ["nx-micronaut-gradle"] +} diff --git a/testing-projects/e2e/nx-micronaut-gradle-e2e/tests/nx-micronaut-gradle.spec.ts b/testing-projects/e2e/nx-micronaut-gradle-e2e/tests/nx-micronaut-gradle.spec.ts new file mode 100644 index 000000000..ab606bdf8 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-e2e/tests/nx-micronaut-gradle.spec.ts @@ -0,0 +1,1388 @@ +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'; +import { checkstyleVersion, normalizeName } from '@jnxplus/common'; +import { + addTmpToGitignore, + checkFilesDoNotExist, + getData, + killPorts, + patchPackageJson, + patchRootPackageJson, + promisifiedTreeKill, + removeTmpFromGitignore, + runNxCommandUntil, + runNxNewCommand, + runPackageManagerInstallLinks, +} from '@jnxplus/e2e/testing'; + +describe('nx-micronaut-gradle e2e', () => { + const isCI = + process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true'; + const isWin = process.platform === 'win32'; + const isMacOs = process.platform === 'darwin'; + const rootProjectName = uniq('micronaut-root-project-'); + + beforeAll(async () => { + fse.ensureDirSync(tmpProjPath()); + cleanup(); + runNxNewCommand('', true); + + const pluginName = '@jnxplus/nx-micronaut-gradle'; + const nxmicronautGradleDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'nx-micronaut-gradle' + ); + + const commonDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'common' + ); + + const gradleDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'gradle' + ); + + patchRootPackageJson(pluginName, nxmicronautGradleDistAbsolutePath); + patchRootPackageJson('@jnxplus/common', commonDistAbsolutePath); + patchRootPackageJson('@jnxplus/gradle', gradleDistAbsolutePath); + + patchPackageJson( + gradleDistAbsolutePath, + '@jnxplus/common', + commonDistAbsolutePath + ); + + patchPackageJson( + nxmicronautGradleDistAbsolutePath, + '@jnxplus/common', + commonDistAbsolutePath + ); + patchPackageJson( + nxmicronautGradleDistAbsolutePath, + '@jnxplus/gradle', + gradleDistAbsolutePath + ); + + runPackageManagerInstallLinks(); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:init --rootProjectName ${rootProjectName}` + ); + + 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-gradle capabilities', async () => { + // Making sure the package.json file contains the @jnxplus/nx-micronaut-gradle dependency + const packageJson = readJson('package.json'); + expect( + packageJson.devDependencies['@jnxplus/nx-micronaut-gradle'] + ).toBeTruthy(); + + // Making sure the nx.json file contains the @jnxplus/nx-micronaut-gradle inside the plugins section + const nxJson = readJson('nx.json'); + expect( + nxJson.plugins.includes('@jnxplus/nx-micronaut-gradle') + ).toBeTruthy(); + + expect(() => + checkFilesExist( + 'gradle/wrapper/gradle-wrapper.jar', + 'gradle/wrapper/gradle-wrapper.properties', + 'gradlew', + 'gradlew.bat', + 'gradle.properties', + 'settings.gradle', + 'tools/linters/checkstyle.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-gradle:migrate`); + }, 120000); + + it('should create a java application', async () => { + const appName = uniq('micronaut-gradle-app-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle`, + `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/resources/application.properties`, + `apps/${appName}/src/test/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle file contains the good information + const buildGradle = readFile(`apps/${appName}/build.gradle`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + 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'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'apps', appName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`apps/${appName}/build`)).toThrow(); + await runNxCommandAsync(`build ${appName}`); + expect(() => checkFilesExist(`apps/${appName}/build`)).not.toThrow(); + + 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-gradle:run-task', + }, + }; + updateFile(`apps/${appName}/project.json`, JSON.stringify(projectJson)); + const runTaskResult = await runNxCommandAsync( + `run-task ${appName} --task="test"` + ); + 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: rootProjectName, + }); + + const port = 8080; + 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 build-image a java application', async () => { + if (!isWin && !isMacOs && isCI) { + const appName = uniq('micronaut-gradle-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName}` + ); + const buildImageResult = await runNxCommandAsync( + `build-image ${appName} --useDocker` + ); + expect(buildImageResult.stdout).toContain('Executor ran for Build Image'); + } + }, 120000); + + it('should use specified options to create an application', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appDir = 'deep/subdir'; + const appName = `${normalizeName(appDir)}-${randomName}`; + const port = 8181; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle: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}/build.gradle`, + `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/resources/application.yml`, + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/deep/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle file contains the good information + const buildGradle = readFile(`apps/${appDir}/${randomName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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 an app with a simple package name', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appDir = 'deep/subdir'; + const appName = `${normalizeName(appDir)}-${randomName}`; + const port = 8282; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${randomName} --tags e2etag,e2ePackage --directory ${appDir} --groupId com.jnxplus --simplePackageName --projectVersion 1.2.3 --packaging war --configFormat .yml --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appDir}/${randomName}/build.gradle`, + `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/resources/application.yml`, + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle file contains the good informations + const buildGradle = readFile(`apps/${appDir}/${randomName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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 kotlin application', async () => { + const appName = uniq('micronaut-gradle-app-'); + const port = 8383; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle`, + `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/resources/application.properties`, + `apps/${appName}/src/test/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/${names(appName).className}Test.kt`, + `apps/${appName}/src/test/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.kt` + ) + ).not.toThrow(); + + // Making sure the build.gradle file contains the good information + const buildGradle = readFile(`apps/${appName}/build.gradle`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'apps', appName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`apps/${appName}/build`)).toThrow(); + await runNxCommandAsync(`build ${appName}`); + expect(() => checkFilesExist(`apps/${appName}/build`)).not.toThrow(); + + 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: rootProjectName, + }); + + 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 + } + }, 240000); + + xit('should build-image a kotlin application', async () => { + if (!isWin && !isMacOs && isCI) { + const appName = uniq('micronaut-gradle-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin` + ); + const buildImageResult = await runNxCommandAsync( + `build-image ${appName} --useDocker` + ); + expect(buildImageResult.stdout).toContain('Executor ran for Build Image'); + } + }, 120000); + + it('--an app with aliases', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appDir = 'subdir'; + const appName = `${appDir}-${randomName}`; + const port = 8484; + + await runNxCommandAsync( + `g @jnxplus/nx-micronaut-gradle: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}/build.gradle`, + `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/resources/application.yml`, + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle file contains the good information + const buildGradle = readFile(`apps/${appDir}/${randomName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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('directory with dash', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appName = `deep-sub-dir-${randomName}`; + const port = 8585; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle: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: rootProjectName, + }); + + 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-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName}` + ); + + expect(() => + checkFilesExist( + `libs/${libName}/build.gradle`, + `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 build.gradle file contains the good information + const buildGradle = readFile(`libs/${libName}/build.gradle`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'libs', libName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`libs/${libName}/build`)).toThrow(); + await runNxCommandAsync(`build ${libName}`); + expect(() => checkFilesExist(`libs/${libName}/build`)).not.toThrow(); + + 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: rootProjectName, + }); + }, 120000); + + it('should create a kotlin library', async () => { + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --language kotlin` + ); + + expect(() => + checkFilesExist( + `libs/${libName}/build.gradle`, + `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 build.gradle file contains the good information + const buildGradle = readFile(`libs/${libName}/build.gradle`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'libs', libName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`libs/${libName}/build`)).toThrow(); + await runNxCommandAsync(`build ${libName}`); + expect(() => checkFilesExist(`libs/${libName}/build`)).not.toThrow(); + + 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: rootProjectName, + }); + }, 120000); + + it('should create a library with the specified properties', async () => { + const randomName = uniq('micronaut-gradle-lib-'); + const libDir = 'deep/subdir'; + const libName = `${normalizeName(libDir)}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${randomName} --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/build.gradle`, + `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 build.gradle file contains the good information + const buildGradle = readFile(`libs/${libDir}/${randomName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('should generare a lib with a simple package name', async () => { + const randomName = uniq('micronaut-gradle-lib-'); + const libDir = 'deep/subdir'; + const libName = `${normalizeName(libDir)}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${randomName} --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --simplePackageName --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/build.gradle`, + `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 build.gradle file contains the good informations + const buildGradle = readFile(`libs/${libDir}/${randomName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('--a lib with aliases', async () => { + const randomName = uniq('micronaut-gradle-lib-'); + const libDir = 'subdir'; + const libName = `${libDir}-${randomName}`; + + await runNxCommandAsync( + `g @jnxplus/nx-micronaut-gradle:lib ${randomName} --dir ${libDir} --t e2etag,e2ePackage --groupId com.jnxplus --v 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/build.gradle`, + `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 build.gradle file contains the good information + const buildGradle = readFile(`libs/${libDir}/${randomName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('should add a lib to an app dependencies', async () => { + const appName = uniq('micronaut-gradle-app-'); + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName}` + ); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --projects ${appName}` + ); + + // Making sure the app build.gradle file contains the lib + const buildGradle = readFile(`apps/${appName}/build.gradle`); + expect(buildGradle.includes(`:libs:${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 testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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[rootProjectName]).toBeDefined(); + expect(depGraphJson.graph.nodes[appName]).toBeDefined(); + expect(depGraphJson.graph.nodes[libName]).toBeDefined(); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: rootProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: rootProjectName, + }); + + 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-gradle-app-'); + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin --packaging war` + ); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --language kotlin --projects ${appName}` + ); + + // Making sure the app build.gradle file contains the lib + const buildGradle = readFile(`apps/${appName}/build.gradle`); + expect(buildGradle.includes(`:libs:${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 testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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[rootProjectName]).toBeDefined(); + expect(depGraphJson.graph.nodes[appName]).toBeDefined(); + expect(depGraphJson.graph.nodes[libName]).toBeDefined(); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: rootProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: rootProjectName, + }); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: libName, + }); + }, 120000); + + it('should create an application with a simple name', async () => { + const appName = uniq('micronaut-gradle-app-'); + const appDir = 'deep/subdir'; + const port = 8686; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle: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}/build.gradle`, + `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/resources/application.yml`, + `apps/${appDir}/${appName}/src/test/java/com/jnxplus/deep/subdir/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle file contains the good information + const buildGradle = readFile(`apps/${appDir}/${appName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${appName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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 with a simple name', async () => { + const libName = uniq('micronaut-gradle-lib-'); + const libDir = 'deep/subdir'; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --simpleName --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${libName}/build.gradle`, + `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 build.gradle file contains the good information + const buildGradle = readFile(`libs/${libDir}/${libName}/build.gradle`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('should create a minimal java application', async () => { + const appName = uniq('micronaut-gradle-app-'); + const port = 8787; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --minimal --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle`, + `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}Test.java` + ) + ).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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(); + + 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-gradle-app-'); + const port = 8888; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin --minimal --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle`, + `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}Test.kt` + ) + ).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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(); + + 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-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --skipStarterCode` + ); + + expect(() => checkFilesExist(`libs/${libName}/build.gradle`)).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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(); + }, 120000); + + it('should skip starter code when generating a kotlin library with skipStarterCode option', async () => { + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --language kotlin --skipStarterCode` + ); + + expect(() => checkFilesExist(`libs/${libName}/build.gradle`)).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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` + ) + ).not.toThrow(); + }, 120000); +}); diff --git a/testing-projects/e2e/nx-micronaut-gradle-e2e/tsconfig.json b/testing-projects/e2e/nx-micronaut-gradle-e2e/tsconfig.json new file mode 100644 index 000000000..b36041a2a --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-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-gradle-e2e/tsconfig.spec.json b/testing-projects/e2e/nx-micronaut-gradle-e2e/tsconfig.spec.json new file mode 100644 index 000000000..5936dfcb1 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-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/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/jest.config.js b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/jest.config.js new file mode 100644 index 000000000..24998fde3 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/jest.config.js @@ -0,0 +1,16 @@ +module.exports = { + displayName: 'nx-micronaut-gradle-kt-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-gradle-kt-e2e', +}; diff --git a/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/project.json b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/project.json new file mode 100644 index 000000000..237587fd2 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/project.json @@ -0,0 +1,18 @@ +{ + "name": "nx-micronaut-gradle-kt-e2e", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "testing-projects/e2e/nx-micronaut-gradle-kt-e2e/src", + "targets": { + "e2e": { + "executor": "@nx/jest:jest", + "options": { + "jestConfig": "testing-projects/e2e/nx-micronaut-gradle-kt-e2e/jest.config.js", + "runInBand": true + }, + "dependsOn": ["nx-micronaut-gradle:build"] + } + }, + "tags": [], + "implicitDependencies": ["nx-micronaut-gradle"] +} diff --git a/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/tests/nx-micronaut-gradle-kt.spec.ts b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/tests/nx-micronaut-gradle-kt.spec.ts new file mode 100644 index 000000000..2f0b601ef --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/tests/nx-micronaut-gradle-kt.spec.ts @@ -0,0 +1,1405 @@ +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'; + +import { checkstyleVersion, normalizeName } from '@jnxplus/common'; +import { + addTmpToGitignore, + checkFilesDoNotExist, + getData, + killPorts, + patchPackageJson, + patchRootPackageJson, + promisifiedTreeKill, + removeTmpFromGitignore, + runNxCommandUntil, + runNxNewCommand, + runPackageManagerInstallLinks, +} from '@jnxplus/e2e/testing'; + +describe('nx-micronaut-gradle kt e2e', () => { + const isCI = + process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true'; + const isWin = process.platform === 'win32'; + const isMacOs = process.platform === 'darwin'; + const rootProjectName = uniq('micronaut-root-project-'); + + beforeAll(async () => { + fse.ensureDirSync(tmpProjPath()); + cleanup(); + runNxNewCommand('', true); + + const pluginName = '@jnxplus/nx-micronaut-gradle'; + const nxmicronautGradleDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'nx-micronaut-gradle' + ); + + const commonDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'common' + ); + + const gradleDistAbsolutePath = path.join( + workspaceRoot, + 'dist', + 'packages', + 'gradle' + ); + + patchRootPackageJson(pluginName, nxmicronautGradleDistAbsolutePath); + patchRootPackageJson('@jnxplus/common', commonDistAbsolutePath); + patchRootPackageJson('@jnxplus/gradle', gradleDistAbsolutePath); + + patchPackageJson( + gradleDistAbsolutePath, + '@jnxplus/common', + commonDistAbsolutePath + ); + + patchPackageJson( + nxmicronautGradleDistAbsolutePath, + '@jnxplus/common', + commonDistAbsolutePath + ); + patchPackageJson( + nxmicronautGradleDistAbsolutePath, + '@jnxplus/gradle', + gradleDistAbsolutePath + ); + + runPackageManagerInstallLinks(); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:init --dsl kotlin --rootProjectName ${rootProjectName}` + ); + + 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 use dsl option when initiating the workspace', async () => { + // Making sure the package.json file contains the @jnxplus/nx-micronaut-gradle dependency + const packageJson = readJson('package.json'); + expect( + packageJson.devDependencies['@jnxplus/nx-micronaut-gradle'] + ).toBeTruthy(); + + // Making sure the nx.json file contains the @jnxplus/nx-micronaut-gradle inside the plugins section + const nxJson = readJson('nx.json'); + expect( + nxJson.plugins.includes('@jnxplus/nx-micronaut-gradle') + ).toBeTruthy(); + + expect(() => + checkFilesExist( + 'gradle/wrapper/gradle-wrapper.jar', + 'gradle/wrapper/gradle-wrapper.properties', + 'gradlew', + 'gradlew.bat', + 'gradle.properties', + 'settings.gradle.kts', + 'tools/linters/checkstyle.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-gradle:migrate`); + }, 120000); + + it('should create a java application', async () => { + const appName = uniq('micronaut-gradle-app-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle.kts`, + `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/resources/application.properties`, + `apps/${appName}/src/test/java/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle.kts file contains the good information + const buildGradle = readFile(`apps/${appName}/build.gradle.kts`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'apps', appName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`apps/${appName}/build`)).toThrow(); + await runNxCommandAsync(`build ${appName}`); + expect(() => checkFilesExist(`apps/${appName}/build`)).not.toThrow(); + + 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-gradle:run-task', + }, + }; + updateFile(`apps/${appName}/project.json`, JSON.stringify(projectJson)); + const runTaskResult = await runNxCommandAsync( + `run-task ${appName} --task="test"` + ); + 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: rootProjectName, + }); + + const port = 8080; + 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 build-image a java application', async () => { + if (!isWin && !isMacOs && isCI) { + const appName = uniq('micronaut-gradle-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName}` + ); + const buildImageResult = await runNxCommandAsync( + `build-image ${appName} --useDocker` + ); + expect(buildImageResult.stdout).toContain('Executor ran for Build Image'); + } + }, 120000); + + it('should use specified options to create an application', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appDir = 'deep/subdir'; + const appName = `${normalizeName(appDir)}-${randomName}`; + const port = 8181; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle: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}/build.gradle.kts`, + `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/resources/application.yml`, + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/deep/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle.kts file contains the good information + const buildGradle = readFile( + `apps/${appDir}/${randomName}/build.gradle.kts` + ); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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 an app with a simple package name', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appDir = 'deep/subdir'; + const appName = `${normalizeName(appDir)}-${randomName}`; + const port = 8282; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${randomName} --tags e2etag,e2ePackage --directory ${appDir} --groupId com.jnxplus --simplePackageName --projectVersion 1.2.3 --packaging war --configFormat .yml --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appDir}/${randomName}/build.gradle.kts`, + `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/resources/application.yml`, + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle.kts file contains the good informations + const buildGradle = readFile( + `apps/${appDir}/${randomName}/build.gradle.kts` + ); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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 kotlin application', async () => { + const appName = uniq('micronaut-gradle-app-'); + const port = 8383; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle.kts`, + `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/resources/application.properties`, + `apps/${appName}/src/test/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/${names(appName).className}Test.kt`, + `apps/${appName}/src/test/kotlin/com/example/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.kt` + ) + ).not.toThrow(); + + // Making sure the build.gradle.kts file contains the good information + const buildGradle = readFile(`apps/${appName}/build.gradle.kts`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'apps', appName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`apps/${appName}/build`)).toThrow(); + await runNxCommandAsync(`build ${appName}`); + expect(() => checkFilesExist(`apps/${appName}/build`)).not.toThrow(); + + 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: rootProjectName, + }); + + 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-gradle-app-'); + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin` + ); + const buildImageResult = await runNxCommandAsync( + `build-image ${appName} --useDocker` + ); + expect(buildImageResult.stdout).toContain('Executor ran for Build Image'); + } + }, 120000); + + it('--an app with aliases', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appDir = 'subdir'; + const appName = `${appDir}-${randomName}`; + const port = 8484; + + await runNxCommandAsync( + `g @jnxplus/nx-micronaut-gradle: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}/build.gradle.kts`, + `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/resources/application.yml`, + `apps/${appDir}/${randomName}/src/test/java/com/jnxplus/subdir/${names( + randomName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle.kts file contains the good information + const buildGradle = readFile( + `apps/${appDir}/${randomName}/build.gradle.kts` + ); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${randomName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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('directory with dash', async () => { + const randomName = uniq('micronaut-gradle-app-'); + const appName = `deep-sub-dir-${randomName}`; + const port = 8585; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle: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: rootProjectName, + }); + + 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-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName}` + ); + + expect(() => + checkFilesExist( + `libs/${libName}/build.gradle.kts`, + `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 build.gradle.kts file contains the good information + const buildGradle = readFile(`libs/${libName}/build.gradle.kts`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'libs', libName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`libs/${libName}/build`)).toThrow(); + await runNxCommandAsync(`build ${libName}`); + expect(() => checkFilesExist(`libs/${libName}/build`)).not.toThrow(); + + 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: rootProjectName, + }); + }, 120000); + + it('should create a kotlin library', async () => { + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --language kotlin` + ); + + expect(() => + checkFilesExist( + `libs/${libName}/build.gradle.kts`, + `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 build.gradle.kts file contains the good information + const buildGradle = readFile(`libs/${libName}/build.gradle.kts`); + expect(buildGradle.includes('com.example')).toBeTruthy(); + expect(buildGradle.includes('0.0.1-SNAPSHOT')).toBeTruthy(); + + const testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + //should recreate build folder + const localTmpDir = path.dirname(tmpProjPath()); + const targetDir = path.join(localTmpDir, 'proj', 'libs', libName, 'build'); + fse.removeSync(targetDir); + expect(() => checkFilesExist(`libs/${libName}/build`)).toThrow(); + await runNxCommandAsync(`build ${libName}`); + expect(() => checkFilesExist(`libs/${libName}/build`)).not.toThrow(); + + 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: rootProjectName, + }); + }, 120000); + + it('should create a library with the specified properties', async () => { + const randomName = uniq('micronaut-gradle-lib-'); + const libDir = 'deep/subdir'; + const libName = `${normalizeName(libDir)}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${randomName} --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/build.gradle.kts`, + `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 build.gradle.kts file contains the good information + const buildGradle = readFile( + `libs/${libDir}/${randomName}/build.gradle.kts` + ); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('should generare a lib with a simple package name', async () => { + const randomName = uniq('micronaut-gradle-lib-'); + const libDir = 'deep/subdir'; + const libName = `${normalizeName(libDir)}-${randomName}`; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${randomName} --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --simplePackageName --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/build.gradle.kts`, + `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 build.gradle.kts file contains the good informations + const buildGradle = readFile( + `libs/${libDir}/${randomName}/build.gradle.kts` + ); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('--a lib with aliases', async () => { + const randomName = uniq('micronaut-gradle-lib-'); + const libDir = 'subdir'; + const libName = `${libDir}-${randomName}`; + + await runNxCommandAsync( + `g @jnxplus/nx-micronaut-gradle:lib ${randomName} --dir ${libDir} --t e2etag,e2ePackage --groupId com.jnxplus --v 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${randomName}/build.gradle.kts`, + `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 build.gradle.kts file contains the good information + const buildGradle = readFile( + `libs/${libDir}/${randomName}/build.gradle.kts` + ); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('should add a lib to an app dependencies', async () => { + const appName = uniq('micronaut-gradle-app-'); + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName}` + ); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --projects ${appName}` + ); + + // Making sure the app build.gradle.kts file contains the lib + const buildGradle = readFile(`apps/${appName}/build.gradle.kts`); + expect(buildGradle.includes(`:libs:${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 testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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[rootProjectName]).toBeDefined(); + expect(depGraphJson.graph.nodes[appName]).toBeDefined(); + expect(depGraphJson.graph.nodes[libName]).toBeDefined(); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: rootProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: rootProjectName, + }); + + 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-gradle-app-'); + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin --packaging war` + ); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --language kotlin --projects ${appName}` + ); + + // Making sure the app build.gradle.kts file contains the lib + const buildGradle = readFile(`apps/${appName}/build.gradle.kts`); + expect(buildGradle.includes(`:libs:${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 testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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[rootProjectName]).toBeDefined(); + expect(depGraphJson.graph.nodes[appName]).toBeDefined(); + expect(depGraphJson.graph.nodes[libName]).toBeDefined(); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: rootProjectName, + }); + + expect(depGraphJson.graph.dependencies[libName]).toContainEqual({ + type: 'static', + source: libName, + target: rootProjectName, + }); + + expect(depGraphJson.graph.dependencies[appName]).toContainEqual({ + type: 'static', + source: appName, + target: libName, + }); + }, 120000); + + it('should create an application with a simple name', async () => { + const appName = uniq('micronaut-gradle-app-'); + const appDir = 'deep/subdir'; + const port = 8686; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle: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}/build.gradle.kts`, + `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/resources/application.yml`, + `apps/${appDir}/${appName}/src/test/java/com/jnxplus/deep/subdir/${names( + appName + ).className.toLocaleLowerCase()}/HelloControllerTest.java` + ) + ).not.toThrow(); + + // Making sure the build.gradle.kts file contains the good information + const buildGradle = readFile(`apps/${appDir}/${appName}/build.gradle.kts`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.includes('1.2.3')).toBeTruthy(); + // expect(buildGradle.includes('war')).toBeTruthy(); + // expect( + // buildGradle.includes( + // 'org.springframework.boot:spring-boot-starter-tomcat' + // ) + // ).toBeTruthy(); + + //should add tags to project.json + const projectJson = readJson(`apps/${appDir}/${appName}/project.json`); + expect(projectJson.tags).toEqual(['e2etag', 'e2ePackage']); + + const testResult = await runNxCommandAsync(`test ${appName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${appName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + + const process = await runNxCommandUntil( + `serve ${appName} --args="--spring.profiles.active=test"`, + (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 with a simple name', async () => { + const libName = uniq('micronaut-gradle-lib-'); + const libDir = 'deep/subdir'; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --simpleName --directory ${libDir} --tags e2etag,e2ePackage --groupId com.jnxplus --projectVersion 1.2.3` + ); + + expect(() => + checkFilesExist( + `libs/${libDir}/${libName}/build.gradle.kts`, + `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 build.gradle.kts file contains the good information + const buildGradle = readFile(`libs/${libDir}/${libName}/build.gradle.kts`); + expect(buildGradle.includes('com.jnxplus')).toBeTruthy(); + expect(buildGradle.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 testResult = await runNxCommandAsync(`test ${libName}`); + expect(testResult.stdout).toContain('Executor ran for Test'); + + const buildResult = await runNxCommandAsync(`build ${libName}`); + expect(buildResult.stdout).toContain('Executor ran for Build'); + + 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: rootProjectName, + }); + }, 120000); + + it('should create a minimal java application', async () => { + const appName = uniq('micronaut-gradle-app-'); + const port = 8787; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --minimal --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle.kts`, + `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}Test.java` + ) + ).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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(); + + 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-gradle-app-'); + const port = 8888; + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:application ${appName} --language kotlin --minimal --port ${port}` + ); + + expect(() => + checkFilesExist( + `apps/${appName}/build.gradle.kts`, + `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}Test.kt` + ) + ).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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(); + + 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-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --skipStarterCode` + ); + + expect(() => + checkFilesExist(`libs/${libName}/build.gradle.kts`) + ).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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(); + }, 120000); + + it('should skip starter code when generating a kotlin library with skipStarterCode option', async () => { + const libName = uniq('micronaut-gradle-lib-'); + + await runNxCommandAsync( + `generate @jnxplus/nx-micronaut-gradle:library ${libName} --language kotlin --skipStarterCode` + ); + + expect(() => + checkFilesExist(`libs/${libName}/build.gradle.kts`) + ).not.toThrow(); + + expect(() => + checkFilesDoNotExist( + `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` + ) + ).not.toThrow(); + }, 120000); +}); diff --git a/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/tsconfig.json b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/tsconfig.json new file mode 100644 index 000000000..b36041a2a --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-kt-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-gradle-kt-e2e/tsconfig.spec.json b/testing-projects/e2e/nx-micronaut-gradle-kt-e2e/tsconfig.spec.json new file mode 100644 index 000000000..5936dfcb1 --- /dev/null +++ b/testing-projects/e2e/nx-micronaut-gradle-kt-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 3ec3e9d41..95a44f0f2 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -23,7 +23,10 @@ "@jnxplus/nx-boot-maven": ["packages/nx-boot-maven/src/index.ts"], "@jnxplus/nx-maven": ["packages/nx-maven/src/index.ts"], "@jnxplus/nx-quarkus-gradle": ["packages/nx-quarkus-gradle/src/index.ts"], - "@jnxplus/nx-quarkus-maven": ["packages/nx-quarkus-maven/src/index.ts"] + "@jnxplus/nx-quarkus-maven": ["packages/nx-quarkus-maven/src/index.ts"], + "@jnxplus/nx-micronaut-gradle": [ + "packages/nx-micronaut-gradle/src/index.ts" + ] } }, "exclude": ["node_modules", "tmp"]