From 77dd1614e538e798764ad045a58214a1348e1caa Mon Sep 17 00:00:00 2001 From: mararok <5163714+Mararok@users.noreply.github.com> Date: Sun, 19 May 2024 21:58:21 +0100 Subject: [PATCH] feat: add library generator + refactor --- .prettierignore | 5 + .prettierrc.js | 10 + .verdaccio/config.yml | 2 +- package.json | 2 + packages/e2e/jest.config.ts | 4 +- packages/e2e/src/generators/library.test.ts | 33 +++ packages/e2e/src/generators/preset.test.ts | 14 ++ packages/e2e/src/helper/createTestProject.ts | 39 ++++ .../{jest => helper}/startLocalRegistry.ts | 0 .../src/{jest => helper}/stopLocalRegistry.ts | 0 packages/e2e/src/preset.test.ts | 49 ----- packages/plugin/generators.json | 5 + packages/plugin/project.json | 9 + .../src/generators/library/LibraryType.ts | 1 + .../files/common/.eslintrc.json__tmpl__ | 5 + .../library/files/common/README.md.template | 9 + .../files/common/jest.config.ts__tmpl__ | 5 + .../files/common/tsconfig.json.template | 33 +++ .../files/common/tsconfig.lib.json__tmpl__ | 9 + .../files/common/tsconfig.test.json__tmpl__ | 16 ++ .../library/files/test/sample.test.ts__tmpl__ | 8 + .../generators/library/libraryGenerator.ts | 34 +++ .../plugin/src/generators/library/schema.d.ts | 6 + .../plugin/src/generators/library/schema.json | 34 +++ .../preset/files/bin/util/MakeHelp__tmpl__ | 32 +++ .../preset/files/bin/util/util.sh__tmpl__ | 49 +++++ .../preset/files/workspace/.gitignore | 2 +- .../plugin/src/generators/preset/generator.ts | 17 +- .../preset/helper/PresetNxJsonGenerator.ts | 1 + .../helper/PresetPackageJsonGenerator.ts | 11 +- packages/plugin/src/util/HcNxHelper.ts | 170 +++++++++++++++ packages/plugin/src/util/NxHelper.ts | 45 ---- packages/plugin/src/util/ProjectMeta.ts | 10 + .../src/util/ProjectPackageJsonGenerator.ts | 47 +++++ packages/plugin/src/util/index.ts | 3 + .../libraryGenerator.test.ts.snap | 197 ++++++++++++++++++ .../library/libraryGenerator.test.ts | 56 +++++ .../__snapshots__/generator.test.ts.snap | 47 ++--- .../test/generators/preset/generator.test.ts | 11 +- packages/plugin/test/helper/functions.ts | 7 + packages/plugin/test/util/HcNxHelper.test.ts | 52 +++++ packages/plugin/tsconfig.lib.json | 8 +- packages/plugin/tsconfig.test.json | 2 +- pnpm-lock.yaml | 13 ++ 44 files changed, 962 insertions(+), 150 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.js create mode 100644 packages/e2e/src/generators/library.test.ts create mode 100644 packages/e2e/src/generators/preset.test.ts create mode 100644 packages/e2e/src/helper/createTestProject.ts rename packages/e2e/src/{jest => helper}/startLocalRegistry.ts (100%) rename packages/e2e/src/{jest => helper}/stopLocalRegistry.ts (100%) delete mode 100644 packages/e2e/src/preset.test.ts create mode 100644 packages/plugin/src/generators/library/LibraryType.ts create mode 100644 packages/plugin/src/generators/library/files/common/.eslintrc.json__tmpl__ create mode 100644 packages/plugin/src/generators/library/files/common/README.md.template create mode 100644 packages/plugin/src/generators/library/files/common/jest.config.ts__tmpl__ create mode 100644 packages/plugin/src/generators/library/files/common/tsconfig.json.template create mode 100644 packages/plugin/src/generators/library/files/common/tsconfig.lib.json__tmpl__ create mode 100644 packages/plugin/src/generators/library/files/common/tsconfig.test.json__tmpl__ create mode 100644 packages/plugin/src/generators/library/files/test/sample.test.ts__tmpl__ create mode 100644 packages/plugin/src/generators/library/libraryGenerator.ts create mode 100644 packages/plugin/src/generators/library/schema.d.ts create mode 100644 packages/plugin/src/generators/library/schema.json create mode 100644 packages/plugin/src/generators/preset/files/bin/util/MakeHelp__tmpl__ create mode 100644 packages/plugin/src/generators/preset/files/bin/util/util.sh__tmpl__ create mode 100644 packages/plugin/src/util/HcNxHelper.ts delete mode 100644 packages/plugin/src/util/NxHelper.ts create mode 100644 packages/plugin/src/util/ProjectMeta.ts create mode 100644 packages/plugin/src/util/ProjectPackageJsonGenerator.ts create mode 100644 packages/plugin/src/util/index.ts create mode 100644 packages/plugin/test/generators/library/__snapshots__/libraryGenerator.test.ts.snap create mode 100644 packages/plugin/test/generators/library/libraryGenerator.test.ts create mode 100644 packages/plugin/test/helper/functions.ts create mode 100644 packages/plugin/test/util/HcNxHelper.test.ts diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..0f89d13 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +node_modules +tmp +dist +coverage +.nx \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..4182006 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,10 @@ +module.exports = { + semi: true, + trailingComma: 'all', + singleQuote: true, + bracketSpacing: true, + arrowParens: 'always', + printWidth: 150, + tabWidth: 2, + useTabs: false, +}; diff --git a/.verdaccio/config.yml b/.verdaccio/config.yml index a007fe8..f74420f 100644 --- a/.verdaccio/config.yml +++ b/.verdaccio/config.yml @@ -19,7 +19,7 @@ packages: proxy: npmjs # log settings -logs: +log: type: stdout format: pretty level: warn diff --git a/package.json b/package.json index d88c317..45bb069 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@nx/eslint-plugin": "19.0.4", "@nx/jest": "19.0.4", "@nx/js": "19.0.4", + "@nx/linter": "^19.0.4", "@nx/plugin": "19.0.4", "@nx/workspace": "19.0.4", "@swc-node/register": "~1.8.0", @@ -34,6 +35,7 @@ "jest": "^29.4.1", "jest-environment-jsdom": "^29.7.0", "nx": "19.0.4", + "prettier": "^2.8.8", "ts-jest": "^29.1.0", "ts-node": "10.9.1", "tsx": "^4.10.5", diff --git a/packages/e2e/jest.config.ts b/packages/e2e/jest.config.ts index 5a0211c..ff1889b 100644 --- a/packages/e2e/jest.config.ts +++ b/packages/e2e/jest.config.ts @@ -9,6 +9,6 @@ export default { }, moduleFileExtensions: ['ts', 'js', 'html'], coverageDirectory: '../../coverage/packages/e2e', - globalSetup: '/src/jest/startLocalRegistry.ts', - globalTeardown: '/src/jest/stopLocalRegistry.ts', + globalSetup: '/src/helper/startLocalRegistry.ts', + globalTeardown: '/src/helper/stopLocalRegistry.ts', }; diff --git a/packages/e2e/src/generators/library.test.ts b/packages/e2e/src/generators/library.test.ts new file mode 100644 index 0000000..d50c064 --- /dev/null +++ b/packages/e2e/src/generators/library.test.ts @@ -0,0 +1,33 @@ + +import { execSync } from 'child_process'; +import { createTestWorkspace } from '../helper/createTestProject'; +import { existsSync } from 'fs'; +import { join } from 'path'; + +describe('Library', () => { + let workspaceRoot; + + beforeAll(() => { + workspaceRoot = createTestWorkspace('library-test'); + execSync('nx g @hexancore/nx:lib acme/backend --type backend', { + cwd: workspaceRoot, + stdio: 'inherit', + env: process.env, + }); + }); + + test('should be created', () => { + expect(existsSync(join(workspaceRoot, 'libs/acme/backend', 'package.json'))).toBeTruthy(); + }); + + test('build should pass', () => { + execSync('nx run acme-backend:build', { + cwd: workspaceRoot, + stdio: 'inherit', + env: process.env, + }); + + expect(existsSync(join(workspaceRoot, 'dist/libs/acme/backend/src/index.js'))).toBeTruthy(); + }); +}); + diff --git a/packages/e2e/src/generators/preset.test.ts b/packages/e2e/src/generators/preset.test.ts new file mode 100644 index 0000000..c6238ed --- /dev/null +++ b/packages/e2e/src/generators/preset.test.ts @@ -0,0 +1,14 @@ +import { existsSync } from 'fs'; +import { join } from 'path'; + +import { createTestWorkspace } from '../helper/createTestProject'; + +describe('Preset', () => { + let workspaceRoot: string; + + test('should be installed', () => { + workspaceRoot = createTestWorkspace('preset-test'); + expect(existsSync(join(workspaceRoot, 'package.json'))).toBeTruthy(); + }); +}); + diff --git a/packages/e2e/src/helper/createTestProject.ts b/packages/e2e/src/helper/createTestProject.ts new file mode 100644 index 0000000..5526c86 --- /dev/null +++ b/packages/e2e/src/helper/createTestProject.ts @@ -0,0 +1,39 @@ +import { execSync } from 'child_process'; +import { join, dirname } from 'path'; +import { mkdirSync, rmSync } from 'fs'; + +export function createTestWorkspace(name: string): string { + process.env['HUSKY'] = '0'; + + const cwd = process.cwd(); + const workspaceRoot = join(cwd, 'tmp', name); + + rmSync(workspaceRoot, { + recursive: true, + force: true, + }); + + mkdirSync(dirname(workspaceRoot), { + recursive: true, + }); + + process.env['PNPM_HOME'] = join(cwd, 'tmp', 'pnpm-store'); + rmSync(process.env['PNPM_HOME'], { + recursive: true, + force: true, + }); + + const createWorkspaceScript = join(cwd, 'tools', 'scripts', 'create-workspace.mjs'); + try { + execSync(`node ${createWorkspaceScript} ${name}`, { + cwd: dirname(workspaceRoot), + stdio: 'inherit', + env: process.env, + }); + } catch (e) { + console.error(e); + throw e; + } + + return workspaceRoot; +} \ No newline at end of file diff --git a/packages/e2e/src/jest/startLocalRegistry.ts b/packages/e2e/src/helper/startLocalRegistry.ts similarity index 100% rename from packages/e2e/src/jest/startLocalRegistry.ts rename to packages/e2e/src/helper/startLocalRegistry.ts diff --git a/packages/e2e/src/jest/stopLocalRegistry.ts b/packages/e2e/src/helper/stopLocalRegistry.ts similarity index 100% rename from packages/e2e/src/jest/stopLocalRegistry.ts rename to packages/e2e/src/helper/stopLocalRegistry.ts diff --git a/packages/e2e/src/preset.test.ts b/packages/e2e/src/preset.test.ts deleted file mode 100644 index aac6e4b..0000000 --- a/packages/e2e/src/preset.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { execSync } from 'child_process'; -import { join, dirname } from 'path'; -import { existsSync, mkdirSync, rmSync } from 'fs'; - -describe('Plugin', () => { - let projectDirectory: string; - - test('should be installed', () => { - projectDirectory = createTestProject(); - expect(existsSync(join(projectDirectory,'package.json'))).toBeTruthy(); - }); -}); - -/** - * Creates a test project with create-nx-workspace and installs the plugin - * @returns The directory where the test project was created - */ -function createTestProject(extraArgs = '') { - const projectName = 'test-project'; - const projectDirectory = join(process.cwd(), 'tmp', projectName); - - rmSync(projectDirectory, { - recursive: true, - force: true, - }); - mkdirSync(dirname(projectDirectory), { - recursive: true, - }); - - process.env['PNPM_HOME'] = join(process.cwd(), 'tmp', 'pnpm-store'); - rmSync(process.env['PNPM_HOME'], { - recursive: true, - force: true, - }); - - const createWorkspaceScript = join(process.cwd(), 'tools', 'scripts', 'create-workspace.mjs'); - try { - execSync(`node ${createWorkspaceScript} ${projectName} ${extraArgs}`, { - cwd: dirname(projectDirectory), - stdio: 'inherit', - env: process.env, - }); - } catch (e) { - console.error(e); - throw e; - } - - return projectDirectory; -} diff --git a/packages/plugin/generators.json b/packages/plugin/generators.json index d979326..5f7dec1 100644 --- a/packages/plugin/generators.json +++ b/packages/plugin/generators.json @@ -5,6 +5,11 @@ "schema": "./src/generators/preset/schema.json", "description": "preset generator", "x-use-standalone-layout": true + }, + "lib": { + "factory": "./src/generators/library/libraryGenerator", + "schema": "./src/generators/library/schema.json", + "description": "library generator" } } } diff --git a/packages/plugin/project.json b/packages/plugin/project.json index 725bf2c..a2225ff 100644 --- a/packages/plugin/project.json +++ b/packages/plugin/project.json @@ -89,6 +89,15 @@ "jestConfig": "{projectRoot}/jest.config.ts", "runInBand": true } + }, + "test-watch": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "{projectRoot}/jest.config.ts", + "runInBand": true, + "watch": true + } } } } diff --git a/packages/plugin/src/generators/library/LibraryType.ts b/packages/plugin/src/generators/library/LibraryType.ts new file mode 100644 index 0000000..d28ce10 --- /dev/null +++ b/packages/plugin/src/generators/library/LibraryType.ts @@ -0,0 +1 @@ +export type LibraryType = 'frontend' | 'backend' | 'shared'; \ No newline at end of file diff --git a/packages/plugin/src/generators/library/files/common/.eslintrc.json__tmpl__ b/packages/plugin/src/generators/library/files/common/.eslintrc.json__tmpl__ new file mode 100644 index 0000000..abf9cca --- /dev/null +++ b/packages/plugin/src/generators/library/files/common/.eslintrc.json__tmpl__ @@ -0,0 +1,5 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"] + +} diff --git a/packages/plugin/src/generators/library/files/common/README.md.template b/packages/plugin/src/generators/library/files/common/README.md.template new file mode 100644 index 0000000..355cc03 --- /dev/null +++ b/packages/plugin/src/generators/library/files/common/README.md.template @@ -0,0 +1,9 @@ +# <%= project.name %> + +## Building + +Run `nx build <%= project.name %>` to build the library. + +## Running tests + +Run `nx test <%= project.name %>` to execute the tests. diff --git a/packages/plugin/src/generators/library/files/common/jest.config.ts__tmpl__ b/packages/plugin/src/generators/library/files/common/jest.config.ts__tmpl__ new file mode 100644 index 0000000..c3ea11b --- /dev/null +++ b/packages/plugin/src/generators/library/files/common/jest.config.ts__tmpl__ @@ -0,0 +1,5 @@ +import createJestConfig from "../../../jest.preset"; + +const jestConfig = createJestConfig(__dirname); + +export default jestConfig \ No newline at end of file diff --git a/packages/plugin/src/generators/library/files/common/tsconfig.json.template b/packages/plugin/src/generators/library/files/common/tsconfig.json.template new file mode 100644 index 0000000..e4100ab --- /dev/null +++ b/packages/plugin/src/generators/library/files/common/tsconfig.json.template @@ -0,0 +1,33 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "moduleResolution": "Node16", + "module": "Node16", + "target": "es2022", + "esModuleInterop": true, + "paths": { + "<%= project.importName %>": [ + "<%= project.root %>/src/index.ts" + ], + "@": [ + "<%= project.root %>/src" + ], + "@/*": [ + "<%= project.root %>/src/*" + ], + "@test/*": [ + "<%= project.root %>/test/helper/*" + ] + } + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.test.json" + }, + { + "path": "./tsconfig.lib.json" + } + ] +} \ No newline at end of file diff --git a/packages/plugin/src/generators/library/files/common/tsconfig.lib.json__tmpl__ b/packages/plugin/src/generators/library/files/common/tsconfig.lib.json__tmpl__ new file mode 100644 index 0000000..b0c8c86 --- /dev/null +++ b/packages/plugin/src/generators/library/files/common/tsconfig.lib.json__tmpl__ @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true + }, + "include": ["src/**/*.ts"], + "exclude": ["test/**/*"] +} diff --git a/packages/plugin/src/generators/library/files/common/tsconfig.test.json__tmpl__ b/packages/plugin/src/generators/library/files/common/tsconfig.test.json__tmpl__ new file mode 100644 index 0000000..d18a57d --- /dev/null +++ b/packages/plugin/src/generators/library/files/common/tsconfig.test.json__tmpl__ @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": ["jest"] + }, + + "files": [ + "../../../node_modules/jest-expect-message/types/index.d.ts", + "../../../node_modules/@hexancore/common/lib/cjs/Test/Matchers.d.ts" + ], + "include": [ + "src/**/*.ts", + "test/**/*.test.ts" + ] +} diff --git a/packages/plugin/src/generators/library/files/test/sample.test.ts__tmpl__ b/packages/plugin/src/generators/library/files/test/sample.test.ts__tmpl__ new file mode 100644 index 0000000..28a7d72 --- /dev/null +++ b/packages/plugin/src/generators/library/files/test/sample.test.ts__tmpl__ @@ -0,0 +1,8 @@ +/** + * @group unit + */ +describe('unit sample test', () => { + test('sample', () => { + expect(1).toBe(1); + }); +}); \ No newline at end of file diff --git a/packages/plugin/src/generators/library/libraryGenerator.ts b/packages/plugin/src/generators/library/libraryGenerator.ts new file mode 100644 index 0000000..bbb0f9d --- /dev/null +++ b/packages/plugin/src/generators/library/libraryGenerator.ts @@ -0,0 +1,34 @@ +import { + Tree, + updateJson +} from '@nx/devkit'; +import * as path from 'path'; +import { HcNxHelper } from '../../util/HcNxHelper'; +import { ProjectMeta, ProjectPackageJsonGenerator } from '../../util'; +import { LibraryGeneratorSchema } from './schema'; + +export async function libraryGenerator(tree: Tree, options: LibraryGeneratorSchema): Promise { + + const helper = new HcNxHelper(tree); + const project: ProjectMeta = helper.createProjectMeta(options.directory, false); + + helper.addProjectConfiguration(project); + ProjectPackageJsonGenerator.run(tree, { project }); + + const filesPath = path.join(__dirname, 'files'); + helper.generateProjectFiles(project, path.join(filesPath, 'common'), ''); + + updateJson(helper.tree, 'tsconfig.base.json', (v) => { + v.compilerOptions.paths = v.paths ?? {}; + v.compilerOptions.paths[project.importName] = [`${project.root}/src/index.ts`]; + return v; + }); + + tree.write(path.join(project.root, 'src/index.ts'), 'export const INITIAL = 1;'); + tree.write(path.join(project.root, 'test/helper/.gitkeep'), ''); + tree.write(path.join(project.root, 'test/unit/.gitkeep'), ''); + tree.write(path.join(project.root, 'test/integration/.gitkeep'), ''); + helper.generateProjectFiles(project, path.join(filesPath, 'test'), 'test/unit'); +} + +export default libraryGenerator; diff --git a/packages/plugin/src/generators/library/schema.d.ts b/packages/plugin/src/generators/library/schema.d.ts new file mode 100644 index 0000000..f16801d --- /dev/null +++ b/packages/plugin/src/generators/library/schema.d.ts @@ -0,0 +1,6 @@ +import type { LibraryType } from "./LibraryType"; + +export interface LibraryGeneratorSchema { + directory: string; + type: LibraryType | 'backend' | 'frontend' | 'shared'; +} \ No newline at end of file diff --git a/packages/plugin/src/generators/library/schema.json b/packages/plugin/src/generators/library/schema.json new file mode 100644 index 0000000..d087961 --- /dev/null +++ b/packages/plugin/src/generators/library/schema.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://json-schema.org/schema", + "$id": "Library", + "title": "", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "What name would you like to use?" + }, + "directory": { + "type": "string", + "description": "A directory where the lib is placed.", + "x-priority": "important", + "$default": { + "$source": "argv", + "index": 0 + }, + }, + "type": { + "description": "The library type.", + "type": "string", + "enum": ["frontend", "backend", "shared"], + "x-prompt": "Which library type would you like to use ? Choose 'none' to skip build setup.", + "x-priority": "important" + } + }, + "required": ["name", "type"] +} diff --git a/packages/plugin/src/generators/preset/files/bin/util/MakeHelp__tmpl__ b/packages/plugin/src/generators/preset/files/bin/util/MakeHelp__tmpl__ new file mode 100644 index 0000000..6858367 --- /dev/null +++ b/packages/plugin/src/generators/preset/files/bin/util/MakeHelp__tmpl__ @@ -0,0 +1,32 @@ +.DEFAULT_GOAL := help +.PHONY: help + +HELP_TARGET_MAX_CHAR_NUM ?= 30 +BOLD := $(shell tput -Txterm bold) +GREEN := $(shell tput -Txterm setaf 2) +YELLOW := $(shell tput -Txterm setaf 3) +WHITE := $(shell tput -Txterm setaf 7) +RESET := $(shell tput -Txterm sgr0) + +.ONESHELL: +## Shows this help +help: + @echo '${BOLD}Info${RESET}' + @echo ' ${YELLOW}${INFO}${RESET}' + @echo '${BOLD}Usage:${RESET}' + @echo ' ${YELLOW}make${RESET} ${GREEN}${EXTRA_MAKE_ARGS} ${RESET}' + @echo '${BOLD}Targets:${RESET}' + @awk '/^(.+):/ { \ + helpMessage = match(lastLine, /^## (.*)/); \ + if (helpMessage) { \ + helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ + is_subproject_target = match($$1, /^.+_subproject(_.+):/); \ + if (is_subproject_target) { \ + helpCommand = substr($$2, 0, index($$2, ":")-2)""; \ + } else { \ + helpCommand = substr($$1, 0, index($$1, ":")-1); \ + } \ + printf " ${YELLOW}%-$(HELP_TARGET_MAX_CHAR_NUM)s${RESET} ${BOLD}${GREEN}%s${RESET}\n", helpCommand, helpMessage; \ + } \ + } \ + { lastLine = $$0 }' $(MAKEFILE_LIST) diff --git a/packages/plugin/src/generators/preset/files/bin/util/util.sh__tmpl__ b/packages/plugin/src/generators/preset/files/bin/util/util.sh__tmpl__ new file mode 100644 index 0000000..2c61093 --- /dev/null +++ b/packages/plugin/src/generators/preset/files/bin/util/util.sh__tmpl__ @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# CONSTANTS: +readonly UTIL_BOLD=$(tput bold) +readonly UTIL_UNDERLINE=$(tput sgr 0 1) +readonly UTIL_RESET=$(tput sgr0) + +readonly UTIL_PURPLE=$(tput setaf 171) +readonly UTIL_RED=$(tput setaf 1) +readonly UTIL_GREEN=$(tput setaf 76) +readonly UTIL_TAN=$(tput setaf 3) +readonly UTIL_BLUE=$(tput setaf 38) + +# LOGGING: +function utils::print_header() { + printf "\n${UTIL_BOLD}${UTIL_PURPLE}========== %s ==========${UTIL_RESET}\n" "$@" 1>&2 +} + +function utils::print_arrow() { + printf "➜ $@\n" 1>&2 +} + +function utils::print_success() { + printf "${UTIL_GREEN}✔ %s${UTIL_RESET}\n" "$@" 1>&2 +} + +function util::print_error() { + printf "${UTIL_RED}✖ %s${UTIL_RESET}\n" "$@" 1>&2 +} + +function util::print_warning() { + printf "${UTIL_TAN}➜ %s${UTIL_RESET}\n" "$@" 1>&2 +} + +function util::print_underline() { + printf "${UTIL_UNDERLINE}${UTIL_BOLD}%s${UTIL_RESET}\n" "$@" 1>&2 +} +function util::print_bold() { + printf "${UTIL_BOLD}%s${UTIL_RESET}\n" "$@" +} + +function util::print_note() { + printf "${UTIL_UNDERLINE}${UTIL_BOLD}${UTIL_BLUE}Note:${UTIL_RESET} ${UTIL_BLUE}%s${UTIL_RESET}\n" "$@" 1>&2 +} + +function util::is_cygwin_env() { + [[ $(uname -s) == 'CYGWIN'* ]] +} + diff --git a/packages/plugin/src/generators/preset/files/workspace/.gitignore b/packages/plugin/src/generators/preset/files/workspace/.gitignore index 79fb253..0406082 100644 --- a/packages/plugin/src/generators/preset/files/workspace/.gitignore +++ b/packages/plugin/src/generators/preset/files/workspace/.gitignore @@ -29,7 +29,7 @@ node_modules # IDE - VSCode .vscode/* -!.vscode/settings.json.sample +!.vscode/settings.json.template !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json diff --git a/packages/plugin/src/generators/preset/generator.ts b/packages/plugin/src/generators/preset/generator.ts index a6b581f..8bb3ae5 100644 --- a/packages/plugin/src/generators/preset/generator.ts +++ b/packages/plugin/src/generators/preset/generator.ts @@ -1,10 +1,11 @@ import { Tree, formatFiles, - generateFiles + generateFiles, + installPackagesTask } from '@nx/devkit'; import * as path from 'path'; -import { HcNxHelper } from '../../util/NxHelper'; +import { HcNxHelper } from '../../util/HcNxHelper'; import { PresetNxJsonGenerator } from './helper/PresetNxJsonGenerator'; import { PresetPackageJsonGenerator } from './helper/PresetPackageJsonGenerator'; import { PresetGeneratorSchema } from './schema'; @@ -15,26 +16,32 @@ export async function presetGenerator( options: PresetGeneratorSchema ) { - const nxVersion = HcNxHelper.getPluginNxVersion(); - const hcNxPluginVersion = HcNxHelper.getVersion(); + const nxVersion = HcNxHelper.pluginNxVersion; + const hcNxPluginVersion = HcNxHelper.pluginVersion; PresetPackageJsonGenerator.run(tree, { nxVersion, hcNxPluginVersion }); PresetNxJsonGenerator.run(tree); - tree.delete('.prettierrc'); const templateContext = { + tmpl: '', workspace: { name: options.name, nxVersion } }; const filesPath = path.join(__dirname, 'files'); + tree.write('.vscode/extensions.json', readFileSync(path.join(filesPath, 'vscode/extensions.json'))); tree.write('.vscode/settings.json.template', readFileSync(path.join(filesPath, 'vscode/settings.json'))); generateFiles(tree, path.join(filesPath, './.husky'), './.husky', templateContext); generateFiles(tree, path.join(filesPath, 'workspace'), './', templateContext); + generateFiles(tree, path.join(filesPath, 'bin'), './bin', templateContext); await formatFiles(tree); + + return () => { + installPackagesTask(tree, true, undefined, 'pnpm'); + }; } export default presetGenerator; diff --git a/packages/plugin/src/generators/preset/helper/PresetNxJsonGenerator.ts b/packages/plugin/src/generators/preset/helper/PresetNxJsonGenerator.ts index 393a633..8e32c74 100644 --- a/packages/plugin/src/generators/preset/helper/PresetNxJsonGenerator.ts +++ b/packages/plugin/src/generators/preset/helper/PresetNxJsonGenerator.ts @@ -25,6 +25,7 @@ export class PresetNxJsonGenerator { "{projectRoot}/**/*", "sharedGlobals" ], + "sharedGlobals": [], }; o.namedInputs.production = [ "default", diff --git a/packages/plugin/src/generators/preset/helper/PresetPackageJsonGenerator.ts b/packages/plugin/src/generators/preset/helper/PresetPackageJsonGenerator.ts index 0d78d99..66c2a56 100644 --- a/packages/plugin/src/generators/preset/helper/PresetPackageJsonGenerator.ts +++ b/packages/plugin/src/generators/preset/helper/PresetPackageJsonGenerator.ts @@ -111,23 +111,19 @@ export class PresetPackageJsonGenerator { const vite = { "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-vue": "^5.0.4", - "@vitest/coverage-c8": "~0.32.4", - "@vitest/ui": "1.3.1", + "@vitest/coverage-v8": "1.6.*", + "@vitest/ui": "1.6.*", + "vitest": "1.6.*", "@rollup/plugin-node-resolve": "^15.2.3", "rollup": "^4.17.0", "vite": "^5.2.10", "vite-tsconfig-paths": "^4.3.2", - "vitest": "1.3.1", "autoprefixer": "^10.4.19", "@babel/core": "^7.24.4", "@babel/plugin-transform-modules-commonjs": "^7.24.1", "@babel/preset-env": "^7.24.4", }; - const nx = { - "nx-vue3-vite": "^0.27.0", - }; - const primevue = { "primeflex": "^3.3.1", "primeicons": "^6.0.1", @@ -147,7 +143,6 @@ export class PresetPackageJsonGenerator { ...vueI18n, ...vite, ...primevue, - ...nx, ...style }; } diff --git a/packages/plugin/src/util/HcNxHelper.ts b/packages/plugin/src/util/HcNxHelper.ts new file mode 100644 index 0000000..82c456a --- /dev/null +++ b/packages/plugin/src/util/HcNxHelper.ts @@ -0,0 +1,170 @@ +import { + readJsonFile, + Tree, + addProjectConfiguration, + generateFiles +} from '@nx/devkit'; +import { execSync } from 'child_process'; +import * as path from 'path'; + +import { ProjectMeta } from './ProjectMeta'; + +export class HcNxHelper { + + private static cachedPluginPackageJson: Record; + private _workspacePackageNamespace!: string; + + public constructor(public readonly tree: Tree) { + + } + + public createProjectMeta(directory: string, isApp: boolean): ProjectMeta { + const name = HcNxHelper.getProjectNameFromDirectory(directory, isApp); + return { + name, + root: HcNxHelper.getProjectRoot(directory, isApp), + importName: this.getProjectImportName(name), + type: isApp ? 'application' : 'library', + }; + } + + public static getProjectNameFromDirectory(directory: string, isApp: boolean): string { + const name = directory.replaceAll('/', '-'); + return isApp ? `app-${name}` : name; + } + + public static getProjectRoot(directory: string, isApp: boolean): string { + return isApp ? this.getApplicationProjectRoot(directory) : this.getLibraryProjectRoot(directory); + } + + public static getLibraryProjectRoot(directory: string): string { + return `libs/${directory}`; + } + + public static getApplicationProjectRoot(directory: string): string { + return `apps/${directory}`; + } + + public getProjectImportName(name: string): string { + return this.workspacePackageNamespace + '/' + name; + } + + public get workspacePackageNamespace(): string { + if (!this._workspacePackageNamespace) { + this._workspacePackageNamespace = this.getWorkspacePackageJson().name.split('/')[0]; + } + return this._workspacePackageNamespace; + } + + public get workspaceNxVersion(): string { + return this.getWorkspacePackageJson().devDependencies['@nrwl/workspace']; + } + + private getWorkspacePackageJson(): Record { + if (this.tree.exists('package.json')) { + return JSON.parse(this.tree.read('package.json')?.toString() ?? ""); + } + + throw new Error('Not found workspace package.json'); + } + + public static getGlobalNxVersion(): string { + const output = execSync('nx --version').toString(); + const regex = /- Global: v(\d+\.\d+\.\d+)/; + const match = output.match(regex); + + if (match) { + return match[1]; + } + + throw new Error('Not found Nx global version, install with `pnpm add --global nx`'); + } + + public generateProjectFiles>(project: ProjectMeta, srcDir: string, target: string, context?: T) { + const templateContext = { + tmpl: '', + project: project, + ...context, + }; + + generateFiles(this.tree, srcDir, path.join(project.root, target), templateContext); + } + + public addProjectConfiguration(options: ProjectMeta): void { + addProjectConfiguration(this.tree, options.name, { + root: options.root, + projectType: options.type, + sourceRoot: '{projectRoot}/src', + targets: { + "build": { + "executor": "@nx/js:tsc", + "outputs": [ + "{options.outputPath}" + ], + "options": { + "outputPath": "dist/{projectRoot}", + "main": "{projectRoot}/src/index.ts", + "tsConfig": "{projectRoot}/tsconfig.lib.json" + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "{projectRoot}/**/*.ts", + "{projectRoot}/package.json" + ] + } + }, + "lint-fix": { + "executor": "@nx/eslint:lint", + "options": { + "fix": true, + "lintFilePatterns": [ + "{projectRoot}/**/*.ts", + "{projectRoot}/package.json" + ] + } + }, + "test": { + "executor": "@nx/jest:jest", + "defaultConfiguration": "test", + "options": { + "jestConfig": "{projectRoot}/jest.config.ts", + "runInBand": true, + "passWithNoTests": true + } + }, + "test-watch": { + "executor": "@nx/jest:jest", + "defaultConfiguration": "test", + "options": { + "jestConfig": "{projectRoot}/jest.config.ts", + "runInBand": true, + "passWithNoTests": true, + "watch": true + } + } + } + }); + } + + public static get pluginVersion(): string { + const packageJson = this.getPluginPackageJson(); + return packageJson['version']; + } + + public static get pluginNxVersion(): string { + const packageJson = this.getPluginPackageJson(); + return packageJson['dependencies']['@nx/devkit']; + } + + private static getPluginPackageJson(): Record { + if (!this.cachedPluginPackageJson) { + const packageJsonPath = path.join(path.dirname(path.dirname(__dirname)), 'package.json'); + this.cachedPluginPackageJson = readJsonFile(packageJsonPath); + } + + return this.cachedPluginPackageJson; + } +} \ No newline at end of file diff --git a/packages/plugin/src/util/NxHelper.ts b/packages/plugin/src/util/NxHelper.ts deleted file mode 100644 index 24c4e0f..0000000 --- a/packages/plugin/src/util/NxHelper.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { - readJsonFile, - Tree -} from '@nx/devkit'; -import { execSync } from 'child_process'; -import * as path from 'path'; - -export class HcNxHelper { - - public static getVersion(): string { - const packageJson = this.getPluginPackageJson(); - return packageJson['version']; - } - - public static getPluginNxVersion(): string { - const packageJson = this.getPluginPackageJson(); - return packageJson['dependencies']['@nx/devkit']; - } - - public static getWorkspaceNxVersion(tree: Tree): string { - if (tree.exists('package.json')) { - const packageJson = readJsonFile(path.join(tree.root, 'package.json')); - return packageJson.devDependencies['@nrwl/workspace']; - } - - throw new Error('Not found workspace package.json'); - } - - public static getGlobalNxVersion(): string { - const output = execSync('nx --version').toString(); - const regex = /- Global: v(\d+\.\d+\.\d+)/; - const match = output.match(regex); - - if (match) { - return match[1]; - } - - throw new Error('Not found Nx global version, install with `pnpm add --global nx`'); - } - - private static getPluginPackageJson(): Record { - const packageJsonPath = path.join(path.dirname(path.dirname(__dirname)), 'package.json'); - return readJsonFile(packageJsonPath); - } -} \ No newline at end of file diff --git a/packages/plugin/src/util/ProjectMeta.ts b/packages/plugin/src/util/ProjectMeta.ts new file mode 100644 index 0000000..fadc6c8 --- /dev/null +++ b/packages/plugin/src/util/ProjectMeta.ts @@ -0,0 +1,10 @@ +import type { ProjectType } from "@nx/devkit"; +import type { LibraryType } from "../generators/library/LibraryType"; + +export interface ProjectMeta { + name: string; + root: string; + importName: string; + type: ProjectType; + libraryType?: LibraryType; +} \ No newline at end of file diff --git a/packages/plugin/src/util/ProjectPackageJsonGenerator.ts b/packages/plugin/src/util/ProjectPackageJsonGenerator.ts new file mode 100644 index 0000000..fd455fc --- /dev/null +++ b/packages/plugin/src/util/ProjectPackageJsonGenerator.ts @@ -0,0 +1,47 @@ +import { + Tree, + writeJson +} from '@nx/devkit'; +import type { ProjectMeta } from './ProjectMeta'; + +export interface ProjectPackageJsonGeneratorOptions { + project: ProjectMeta; +} + +export class ProjectPackageJsonGenerator { + protected packageJsonPath: string; + + public constructor(protected options: Opts) { + this.packageJsonPath = `${this.options.project.root}/package.json`; + } + + public static run(tree: Tree, options: Opts) { + const g = new this(options); + g.apply(tree); + } + + public apply(tree: Tree): void { + writeJson(tree, this.packageJsonPath, { + name: this.options.project.importName, + type: "commonjs", + private: true, + ...this.generateDeps(), + ...this.generateExports() + }); + } + + private generateExports(): Record { + return { + "main": "./src/index.js", + "types": "./src/index.d.ts", + }; + } + + private generateDeps(): Record { + return { + dependencies: { + 'tslib': '2.6.2' + } + }; + } +} \ No newline at end of file diff --git a/packages/plugin/src/util/index.ts b/packages/plugin/src/util/index.ts new file mode 100644 index 0000000..31449c4 --- /dev/null +++ b/packages/plugin/src/util/index.ts @@ -0,0 +1,3 @@ +export * from './HcNxHelper'; +export * from './ProjectPackageJsonGenerator'; +export * from './ProjectMeta'; \ No newline at end of file diff --git a/packages/plugin/test/generators/library/__snapshots__/libraryGenerator.test.ts.snap b/packages/plugin/test/generators/library/__snapshots__/libraryGenerator.test.ts.snap new file mode 100644 index 0000000..4ac165e --- /dev/null +++ b/packages/plugin/test/generators/library/__snapshots__/libraryGenerator.test.ts.snap @@ -0,0 +1,197 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`library generator configuration libs/task-manager/backend/.eslintrc.json should match snapshot 1`] = ` +"{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"] + +} +" +`; + +exports[`library generator configuration libs/task-manager/backend/README.md should match snapshot 1`] = ` +"# task-manager-backend + +## Building + +Run \`nx build task-manager-backend\` to build the library. + +## Running tests + +Run \`nx test task-manager-backend\` to execute the tests. +" +`; + +exports[`library generator configuration libs/task-manager/backend/jest.config.ts should match snapshot 1`] = ` +"import createJestConfig from "../../../jest.preset"; + +const jestConfig = createJestConfig(__dirname); + +export default jestConfig" +`; + +exports[`library generator configuration libs/task-manager/backend/package.json should match snapshot 1`] = ` +"{ + "name": "@testcompany/task-manager-backend", + "type": "commonjs", + "private": true, + "dependencies": { + "tslib": "2.6.2" + }, + "main": "./src/index.js", + "types": "./src/index.d.ts" +} +" +`; + +exports[`library generator configuration libs/task-manager/backend/project.json should match snapshot 1`] = ` +"{ + "name": "task-manager-backend", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "{projectRoot}/src", + "targets": { + "build": { + "executor": "@nx/js:tsc", + "outputs": [ + "{options.outputPath}" + ], + "options": { + "outputPath": "dist/{projectRoot}", + "main": "{projectRoot}/src/index.ts", + "tsConfig": "{projectRoot}/tsconfig.lib.json" + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "{projectRoot}/**/*.ts", + "{projectRoot}/package.json" + ] + } + }, + "lint-fix": { + "executor": "@nx/eslint:lint", + "options": { + "fix": true, + "lintFilePatterns": [ + "{projectRoot}/**/*.ts", + "{projectRoot}/package.json" + ] + } + }, + "test": { + "executor": "@nx/jest:jest", + "defaultConfiguration": "test", + "options": { + "jestConfig": "{projectRoot}/jest.config.ts", + "runInBand": true, + "passWithNoTests": true + } + }, + "test-watch": { + "executor": "@nx/jest:jest", + "defaultConfiguration": "test", + "options": { + "jestConfig": "{projectRoot}/jest.config.ts", + "runInBand": true, + "passWithNoTests": true, + "watch": true + } + } + } +} +" +`; + +exports[`library generator configuration libs/task-manager/backend/tsconfig.json should match snapshot 1`] = ` +"{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "moduleResolution": "Node16", + "module": "Node16", + "target": "es2022", + "esModuleInterop": true, + "paths": { + "@testcompany/task-manager-backend": [ + "libs/task-manager/backend/src/index.ts" + ], + "@": [ + "libs/task-manager/backend/src" + ], + "@/*": [ + "libs/task-manager/backend/src/*" + ], + "@test/*": [ + "libs/task-manager/backend/test/helper/*" + ] + } + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.test.json" + }, + { + "path": "./tsconfig.lib.json" + } + ] +}" +`; + +exports[`library generator configuration libs/task-manager/backend/tsconfig.lib.json should match snapshot 1`] = ` +"{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true + }, + "include": ["src/**/*.ts"], + "exclude": ["test/**/*"] +} +" +`; + +exports[`library generator configuration libs/task-manager/backend/tsconfig.test.json should match snapshot 1`] = ` +"{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": ["jest"] + }, + + "files": [ + "../../../node_modules/jest-expect-message/types/index.d.ts", + "../../../node_modules/@hexancore/common/lib/cjs/Test/Matchers.d.ts" + ], + "include": [ + "src/**/*.ts", + "test/**/*.test.ts" + ] +} +" +`; + +exports[`library generator configuration nx.json should match snapshot 1`] = `"{"affected":{"defaultBase":"main"},"targetDefaults":{"build":{"cache":true},"lint":{"cache":true}}}"`; + +exports[`library generator configuration package.json should match snapshot 1`] = ` +"{ + "name": "@testcompany/source" +} +" +`; + +exports[`library generator configuration tsconfig.base.json should match snapshot 1`] = ` +"{ + "compilerOptions": { + "paths": { + "@testcompany/task-manager-backend": [ + "libs/task-manager/backend/src/index.ts" + ] + } + } +} +" +`; diff --git a/packages/plugin/test/generators/library/libraryGenerator.test.ts b/packages/plugin/test/generators/library/libraryGenerator.test.ts new file mode 100644 index 0000000..ae3d3cb --- /dev/null +++ b/packages/plugin/test/generators/library/libraryGenerator.test.ts @@ -0,0 +1,56 @@ +import { Tree, writeJson } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; + +import { libraryGenerator } from '../../../src/generators/library/libraryGenerator'; +import { LibraryGeneratorSchema } from '../../../src/generators/library/schema'; +import { exceptWorkspaceFileMatchSnapshot } from '../../helper/functions'; + +describe('library generator', () => { + describe('configuration', () => { + let tree: Tree; + beforeAll(async () => { + tree = createTreeWithEmptyWorkspace(); + writeJson(tree, 'package.json', { + name: '@testcompany/source' + }); + const options: LibraryGeneratorSchema = { directory: 'task-manager/backend', type: 'backend' }; + await libraryGenerator(tree, options); + }); + + const expectedProjectFilesToMatchSnapshots = [ + 'README.md', + 'project.json', + 'package.json', + '.eslintrc.json', + 'jest.config.ts', + 'tsconfig.json', + 'tsconfig.test.json', + 'tsconfig.lib.json', + ].map(f => 'libs/task-manager/backend/' + f); + + const expectedWorkspaceFilesToMatchSnapshots = [ + 'tsconfig.base.json', + 'nx.json', + 'package.json', + ...expectedProjectFilesToMatchSnapshots + ]; + + test.each(expectedWorkspaceFilesToMatchSnapshots.map(i => [i]))('%s should match snapshot', (filePath) => { + exceptWorkspaceFileMatchSnapshot(tree, filePath); + }); + + test('only file from list should exist', () => { + const expectedWorkspaceFilesToExists = [ + '.prettierrc', + 'libs/task-manager/backend/src/index.ts', + 'libs/task-manager/backend/test/unit/sample.test.ts', + 'libs/task-manager/backend/test/helper/.gitkeep', + 'libs/task-manager/backend/test/unit/.gitkeep', + 'libs/task-manager/backend/test/integration/.gitkeep', + ...expectedWorkspaceFilesToMatchSnapshots + ]; + const diff = tree.listChanges().map(c => c.path).filter(x => !expectedWorkspaceFilesToExists.includes(x)); + expect(diff).toEqual([]); + }); + }); +}); diff --git a/packages/plugin/test/generators/preset/__snapshots__/generator.test.ts.snap b/packages/plugin/test/generators/preset/__snapshots__/generator.test.ts.snap index 009e56a..c631532 100644 --- a/packages/plugin/test/generators/preset/__snapshots__/generator.test.ts.snap +++ b/packages/plugin/test/generators/preset/__snapshots__/generator.test.ts.snap @@ -33,7 +33,6 @@ First off, thanks for taking the time to contribute! 🎉 The following is a set of guidelines for contributing to test-workspace. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. - ## How Can I Contribute? ### Reporting Bugs @@ -102,7 +101,8 @@ This section lists the labels we use to help us track and manage issues and pull --- -Thank you for your contributions! Your help is greatly appreciated." +Thank you for your contributions! Your help is greatly appreciated. +" `; exports[`preset generator README.md should match snapshot 1`] = ` @@ -115,20 +115,23 @@ Replace with Yours project workspace description. To start contributing you need install some tools and init developer environment. ### Tools - - NodeJS - - pnpm - - Nx (\`pnpm add --global nx@19.0.4\`) - - Docker + Compose - - make + +- NodeJS +- pnpm +- Nx (\`pnpm add --global nx@19.0.4\`) +- Docker + Compose +- make To init developer environment run: + \`\`\`bash make init_devenv \`\`\` ## Contributing -Contributing Guide is in separate file [CONTRIBUTING.md](./CONTRIBUTING.md)" +Contributing Guide is in separate file [CONTRIBUTING.md](./CONTRIBUTING.md) +" `; exports[`preset generator nx.json should match snapshot 1`] = ` @@ -138,9 +141,7 @@ exports[`preset generator nx.json should match snapshot 1`] = ` }, "targetDefaults": { "build": { - "dependsOn": [ - "^build" - ], + "dependsOn": ["^build"], "cache": true }, "lint": { @@ -152,19 +153,12 @@ exports[`preset generator nx.json should match snapshot 1`] = ` "cache": true }, "test": { - "inputs": [ - "default", - "^default", - "{workspaceRoot}/jest.preset.js" - ], + "inputs": ["default", "^default", "{workspaceRoot}/jest.preset.js"], "cache": true }, "@nx/vite:test": { "cache": true, - "inputs": [ - "default", - "^default" - ] + "inputs": ["default", "^default"] }, "@nx/eslint:lint": { "inputs": [ @@ -182,10 +176,8 @@ exports[`preset generator nx.json should match snapshot 1`] = ` } }, "namedInputs": { - "default": [ - "{projectRoot}/**/*", - "sharedGlobals" - ], + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "sharedGlobals": [], "production": [ "default", "!{projectRoot}/jest.config.{js,ts,mjs,mts}", @@ -244,8 +236,8 @@ exports[`preset generator package.json should match snapshot 1`] = ` "@typescript-eslint/parser": "7.3.0", "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-vue": "^5.0.4", - "@vitest/coverage-c8": "~0.32.4", - "@vitest/ui": "1.3.1", + "@vitest/coverage-v8": "1.6.*", + "@vitest/ui": "1.6.*", "@vue/eslint-config-typescript": "^11.0.3", "@vue/test-utils": "^2.4.5", "@vue/tsconfig": "^0.4.0", @@ -265,7 +257,6 @@ exports[`preset generator package.json should match snapshot 1`] = ` "jest-runner": "^29.7.0", "jest-runner-groups": "^2.2.0", "jsdom": "~22.1.0", - "nx-vue3-vite": "^0.27.0", "pinia": "^2.1.7", "postcss": "^8.4.38", "primeflex": "^3.3.1", @@ -283,7 +274,7 @@ exports[`preset generator package.json should match snapshot 1`] = ` "vee-validate": "^4.12.6", "vite": "^5.2.10", "vite-tsconfig-paths": "^4.3.2", - "vitest": "1.3.1", + "vitest": "1.6.*", "vue": "^3.4.25", "vue-eslint-parser": "^9.4.2", "vue-i18n": "^9.13.1", diff --git a/packages/plugin/test/generators/preset/generator.test.ts b/packages/plugin/test/generators/preset/generator.test.ts index 8a9d413..dfc7fb1 100644 --- a/packages/plugin/test/generators/preset/generator.test.ts +++ b/packages/plugin/test/generators/preset/generator.test.ts @@ -3,15 +3,11 @@ import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { presetGenerator } from '../../../src/generators/preset/generator'; import { PresetGeneratorSchema } from '../../../src/generators/preset/schema'; +import {exceptWorkspaceFileMatchSnapshot } from '../../helper/functions'; describe('preset generator', () => { let tree: Tree; - function exceptWorkspaceFileMatchSnapshot(filePath: string): void { - expect(tree.exists(filePath)).toBeTruthy(); - const contents = tree.read(filePath)?.toString(); - expect(contents).toMatchSnapshot(); - } const options: PresetGeneratorSchema = { name: 'test-workspace' }; beforeAll(async () => { tree = createTreeWithEmptyWorkspace(); @@ -29,7 +25,7 @@ describe('preset generator', () => { 'README.md', ]; test.each(expectedWorkespaceFilesToMatchSnapshots.map(i => [i]))('%s should match snapshot', (filePath) => { - exceptWorkspaceFileMatchSnapshot(filePath); + exceptWorkspaceFileMatchSnapshot(tree, filePath); }); test('only file from list should exist', () => { @@ -38,6 +34,7 @@ describe('preset generator', () => { 'tsconfig.base.json', '.eslintignore', '.eslintrc.json', + '.prettierrc', '.gitignore', '.gitattributes', '.editorconfig', @@ -48,6 +45,8 @@ describe('preset generator', () => { '.husky/pre-commit', 'jest.config.ts', 'jest.preset.ts', + 'bin/util/MakeHelp', + 'bin/util/util.sh', ...expectedWorkespaceFilesToMatchSnapshots ]; const diff = tree.listChanges().map(c => c.path).filter(x => !expectedWorkspaceFilesToExists.includes(x)); diff --git a/packages/plugin/test/helper/functions.ts b/packages/plugin/test/helper/functions.ts new file mode 100644 index 0000000..de00d8b --- /dev/null +++ b/packages/plugin/test/helper/functions.ts @@ -0,0 +1,7 @@ +import type { Tree } from "@nx/devkit"; + +export function exceptWorkspaceFileMatchSnapshot(tree: Tree, filePath: string): void { + expect(tree.exists(filePath)).toBeTruthy(); + const contents = tree.read(filePath)?.toString(); + expect(contents).toMatchSnapshot(); +} \ No newline at end of file diff --git a/packages/plugin/test/util/HcNxHelper.test.ts b/packages/plugin/test/util/HcNxHelper.test.ts new file mode 100644 index 0000000..73b4e46 --- /dev/null +++ b/packages/plugin/test/util/HcNxHelper.test.ts @@ -0,0 +1,52 @@ +import { Tree, writeJson } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { HcNxHelper } from '../../src/util'; + +describe(HcNxHelper.constructor.name, () => { + let tree: Tree; + let helper: HcNxHelper; + + beforeAll(async () => { + tree = createTreeWithEmptyWorkspace(); + writeJson(tree, 'package.json', { + name: '@acme/source', + devDependencies: { + '@nrwl/workspace': '10.10.10', + } + }); + helper = new HcNxHelper(tree); + }); + + test.each([ + {isApp: true, expected: 'app-acme-project'}, + {isApp: false, expected: 'acme-project'} + ])('getProjectNameFromDirectory() isApp: $isApp', ({isApp, expected}) => { + const current = HcNxHelper.getProjectNameFromDirectory('acme-project', isApp); + + expect(current).toEqual(expected); + }); + + test('getLibraryProjectRoot()', () => { + const current = HcNxHelper.getLibraryProjectRoot('acme-project'); + + expect(current).toEqual('libs/acme-project'); + }); + + test('getApplicationProjectRoot()', () => { + const current = HcNxHelper.getApplicationProjectRoot('acme-project'); + + expect(current).toEqual('apps/acme-project'); + }); + + test('getProjectImportName()', () => { + const current = helper.getProjectImportName('acme-project'); + + expect(current).toEqual('@acme/acme-project'); + }); + + test('workspaceNxVersion', () => { + const current = helper.workspaceNxVersion; + + expect(current).toEqual('10.10.10'); + }); +}); diff --git a/packages/plugin/tsconfig.lib.json b/packages/plugin/tsconfig.lib.json index d9821f6..22ba0bc 100644 --- a/packages/plugin/tsconfig.lib.json +++ b/packages/plugin/tsconfig.lib.json @@ -8,11 +8,11 @@ ] }, "include": [ - "src/**/*.ts", - "test/generators/preset/generator.test.ts" -, "src/generators/preset/files/workspace/jest.config.ts.template", "src/generators/preset/files/workspace/jest.preset.ts.template" ], + "src/**/*.ts" +, "src/generators/library/files/test/sample.test.ts__tmpl__" ], "exclude": [ "jest.config.ts", - "test/**/*.test.ts" + "test/**/*.test.ts", + "src/**/files/*" ] } \ No newline at end of file diff --git a/packages/plugin/tsconfig.test.json b/packages/plugin/tsconfig.test.json index 045def9..9abe118 100644 --- a/packages/plugin/tsconfig.test.json +++ b/packages/plugin/tsconfig.test.json @@ -9,7 +9,7 @@ }, "include": [ "jest.config.ts", - "test/**/*.test.ts", + "test/**/*.ts", "src/**/*.d.ts" ] } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c66470a..7c1e2b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,6 +30,9 @@ importers: '@nx/js': specifier: 19.0.4 version: 19.0.4(@babel/traverse@7.24.5)(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.4.5))(@swc/core@1.3.107(@swc/helpers@0.5.11))(@types/node@20.12.12)(nx@19.0.4(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.4.5))(@swc/core@1.3.107(@swc/helpers@0.5.11)))(typescript@5.4.5)(verdaccio@5.31.0(typanion@3.14.0)) + '@nx/linter': + specifier: ^19.0.4 + version: 19.0.4(@babel/traverse@7.24.5)(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.4.5))(@swc/core@1.3.107(@swc/helpers@0.5.11))(@types/node@20.12.12)(js-yaml@4.1.0)(nx@19.0.4(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.4.5))(@swc/core@1.3.107(@swc/helpers@0.5.11)))(verdaccio@5.31.0(typanion@3.14.0)) '@nx/plugin': specifier: 19.0.4 version: 19.0.4(@babel/traverse@7.24.5)(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.4.5))(@swc/core@1.3.107(@swc/helpers@0.5.11))(@types/node@20.12.12)(babel-plugin-macros@2.8.0)(js-yaml@4.1.0)(nx@19.0.4(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.4.5))(@swc/core@1.3.107(@swc/helpers@0.5.11)))(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.11))(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)(verdaccio@5.31.0(typanion@3.14.0)) @@ -78,6 +81,9 @@ importers: nx: specifier: 19.0.4 version: 19.0.4(@swc-node/register@1.8.0(@swc/core@1.3.107(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.4.5))(@swc/core@1.3.107(@swc/helpers@0.5.11)) + prettier: + specifier: ^2.8.8 + version: 2.8.8 ts-jest: specifier: ^29.1.0 version: 29.1.2(@babel/core@7.24.5)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(jest@29.7.0(@types/node@20.12.12)(babel-plugin-macros@2.8.0)(ts-node@10.9.1(@swc/core@1.3.107(@swc/helpers@0.5.11))(@types/node@20.12.12)(typescript@5.4.5)))(typescript@5.4.5) @@ -3380,6 +3386,11 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -8256,6 +8267,8 @@ snapshots: prelude-ls@1.2.1: {} + prettier@2.8.8: {} + pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3