@tactical-ddd/nx 0.0.2-alpha.1 → 0.0.2-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/generators/domain/domain.d.ts.map +1 -1
- package/generators/domain/domain.js +0 -4
- package/generators/domain/domain.js.map +1 -1
- package/generators/domain/schema.d.ts +1 -1
- package/generators/init/init.d.ts.map +1 -1
- package/generators/init/init.js +35 -9
- package/generators/init/init.js.map +1 -1
- package/generators/shared-kernel/files/contracts/README.md +24 -0
- package/generators/shared-kernel/files/infrastructure/README.md +26 -0
- package/generators/shared-kernel/files/utils/README.md +26 -0
- package/generators/shared-kernel/schema.d.ts +1 -1
- package/generators/shared-kernel/shared-kernel.d.ts.map +1 -1
- package/generators/shared-kernel/shared-kernel.js +18 -10
- package/generators/shared-kernel/shared-kernel.js.map +1 -1
- package/package.json +1 -1
- package/utils/eslint-module-boundaries.d.ts.map +1 -1
- package/utils/eslint-module-boundaries.js +22 -8
- package/utils/eslint-module-boundaries.js.map +1 -1
- package/utils/library-exist.d.ts +10 -3
- package/utils/library-exist.d.ts.map +1 -1
- package/utils/library-exist.js +1 -1
- package/utils/library-exist.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/generators/domain/domain.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,iBAAiB,EACtB,KAAK,IAAI,EAEV,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAatD,wBAAsB,eAAe,CACnC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/generators/domain/domain.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,iBAAiB,EACtB,KAAK,IAAI,EAEV,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAatD,wBAAsB,eAAe,CACnC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CAiK5B;AAmED,eAAe,eAAe,CAAC"}
|
|
@@ -48,7 +48,6 @@ async function domainGenerator(tree, options) {
|
|
|
48
48
|
tasks.push(await (0, _js.libraryGenerator)(tree, {
|
|
49
49
|
name: layerName(options, 'contracts'),
|
|
50
50
|
directory: contractsRoot,
|
|
51
|
-
useProjectJson: false,
|
|
52
51
|
addPlugin: true,
|
|
53
52
|
unitTestRunner: 'none',
|
|
54
53
|
bundler: options.bundler,
|
|
@@ -70,7 +69,6 @@ async function domainGenerator(tree, options) {
|
|
|
70
69
|
tasks.push(await (0, _js.libraryGenerator)(tree, {
|
|
71
70
|
name: layerName(options, 'core'),
|
|
72
71
|
directory: coreRoot,
|
|
73
|
-
useProjectJson: false,
|
|
74
72
|
addPlugin: true,
|
|
75
73
|
unitTestRunner: options.unitTestRunner,
|
|
76
74
|
bundler: options.bundler,
|
|
@@ -169,7 +167,6 @@ async function domainGenerator(tree, options) {
|
|
|
169
167
|
return await reactLibraryGenerator(tree, {
|
|
170
168
|
name: layer.name,
|
|
171
169
|
directory: layer.root,
|
|
172
|
-
useProjectJson: false,
|
|
173
170
|
addPlugin: true,
|
|
174
171
|
unitTestRunner: options.unitTestRunner,
|
|
175
172
|
bundler: options.bundler,
|
|
@@ -181,7 +178,6 @@ async function domainGenerator(tree, options) {
|
|
|
181
178
|
const task = await (0, _js.libraryGenerator)(tree, {
|
|
182
179
|
name: layer.name,
|
|
183
180
|
directory: layer.root,
|
|
184
|
-
useProjectJson: false,
|
|
185
181
|
addPlugin: true,
|
|
186
182
|
unitTestRunner: options.unitTestRunner,
|
|
187
183
|
bundler: options.bundler,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx/src/generators/domain/domain.ts"],"sourcesContent":["import {\n ensurePackage,\n formatFiles,\n generateFiles,\n names,\n NX_VERSION,\n OverwriteStrategy,\n readJson,\n runTasksInSerial,\n type GeneratorCallback,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { libraryGenerator as jsLibraryGenerator } from '@nx/js';\nimport { resolve } from 'path';\n\nimport type { DomainGeneratorSchema } from './schema';\nimport { libraryExists } from '../../utils/library-exist';\nimport {\n applyCleanArchitectureBoundaries,\n applyDepConstraints,\n} from '../../utils/eslint-module-boundaries';\nimport { warning } from '../../utils/logger';\nimport { LibraryScope, LibraryType, ModuleFormat } from '../../types';\nimport { resolveLibraryModuleFormat } from '../../utils/resolve-module-format';\n\n/** Conventional location of the shared kernel's contracts library. */\nconst SHARED_CONTRACTS_ROOT = 'libs/shared/contracts';\n\nexport async function domainGenerator(\n tree: Tree,\n options: DomainGeneratorSchema,\n): Promise<GeneratorCallback> {\n // Implicit existence check (CLAUDE.md 7.3.1): domain libraries depend on the\n // shared kernel, so warn if it has not been generated yet rather than\n // producing libraries whose boundary constraints reference tags nothing\n // carries.\n if (!libraryExists(tree, SHARED_CONTRACTS_ROOT)) {\n warning(\n `Shared kernel not found at ${SHARED_CONTRACTS_ROOT}. Run \\`nx g @tactical-ddd/nx:init\\` (or the \\`shared-kernel\\` generator) first so domain libraries can depend on the shared contracts.`,\n );\n }\n\n const contractsRoot = `${options.directory}/contracts`;\n const coreRoot = `${options.directory}/core`;\n const uiRoot = `${options.directory}/ui`;\n const featuresRoot = `${options.directory}/features`;\n const domainTag = `domain:${options.name}`;\n const facadeDomainInterfaceVariants = names(`${options.name}Facade`);\n\n // Install callbacks from the delegated library generators — returned to Nx so\n // the packages backing the inferred plugins (`@nx/eslint`, `@nx/jest`) the\n // libraries register via `addPlugin` get installed.\n const tasks: GeneratorCallback[] = [];\n\n if (\n !libraryExists(tree, contractsRoot) &&\n options.layers.includes('contracts')\n ) {\n tasks.push(\n await jsLibraryGenerator(tree, {\n name: layerName(options, 'contracts'),\n directory: contractsRoot,\n useProjectJson: false,\n addPlugin: true,\n unitTestRunner: 'none',\n bundler: options.bundler,\n linter: options.linter,\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Contracts}`,\n }),\n );\n\n const type = resolveLibraryModuleFormat(tree, contractsRoot);\n\n tree.delete(`${contractsRoot}/src/lib/${options.name}-contracts.ts`);\n tree.write(`${contractsRoot}/src/index.ts`, '');\n generateFiles(\n tree,\n resolve(__dirname, 'files/contracts'),\n contractsRoot,\n {\n name: options.name,\n interfaceName: facadeDomainInterfaceVariants.className,\n esm: type === ModuleFormat.EsModule,\n },\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n }\n\n if (!libraryExists(tree, coreRoot) && options.layers.includes('core')) {\n tasks.push(\n await jsLibraryGenerator(tree, {\n name: layerName(options, 'core'),\n directory: coreRoot,\n useProjectJson: false,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Core}`,\n }),\n );\n\n const type = resolveLibraryModuleFormat(tree, coreRoot);\n const contractsPackage = layerName(options, 'contracts');\n\n tree.delete(`${coreRoot}/src/lib/${options.name}-core.ts`);\n tree.delete(`${coreRoot}/src/lib/${options.name}-core.spec.ts`);\n tree.write(`${coreRoot}/src/index.ts`, '');\n\n // Scaffold the default Clean Architecture layer folders (domain,\n // application, infrastructure — each kept in git via a `.gitkeep`) and lock\n // down imports between them: domain ⊀ application/infrastructure, and\n // application ⊀ infrastructure (the implementation is wired via DI at the\n // composition root, not imported across layers).\n generateFiles(\n tree,\n resolve(__dirname, 'files/core'),\n coreRoot,\n {\n name: options.name,\n interfaceName: facadeDomainInterfaceVariants.className,\n // Full package name of this domain's contracts library, so the facade's\n // import resolves with or without an organization prefix.\n contractsPackage,\n esm: type === ModuleFormat.EsModule,\n },\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n\n // The generated facade imports the domain's contracts package, so declare it\n // as a dependency — otherwise `@nx/dependency-checks` flags the core library\n // for using a package missing from its `package.json`.\n if (tree.exists(`${contractsRoot}/package.json`)) {\n const contractsVersion =\n readJson(tree, `${contractsRoot}/package.json`).version ?? '*';\n updateJson(tree, `${coreRoot}/package.json`, (pkg) => {\n pkg.dependencies = {\n ...pkg.dependencies,\n [contractsPackage]: contractsVersion,\n };\n return pkg;\n });\n }\n\n applyCleanArchitectureBoundaries(tree, coreRoot, options.prefix);\n }\n\n if (!libraryExists(tree, uiRoot) && options.layers.includes('ui')) {\n tasks.push(\n await generateLayerLibrary(tree, options, {\n root: uiRoot,\n name: layerName(options, 'ui'),\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Ui}`,\n }),\n );\n }\n\n if (\n !libraryExists(tree, featuresRoot) &&\n options.layers.includes('features')\n ) {\n tasks.push(\n await generateLayerLibrary(tree, options, {\n root: featuresRoot,\n name: layerName(options, 'features'),\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Features}`,\n }),\n );\n }\n\n // Silo this domain: per-domain constraints are what actually prevent\n // cross-domain imports (a static `domain:*` rule cannot — Nx glob-matches the\n // target tags, so it would let `domain:auth` import `domain:payments`).\n //\n // A `domain:<name>` library may depend on its own domain, the shared kernel,\n // and the *public contracts* of any other domain (`type:contracts`) — the\n // published-language pattern: a domain depends on another domain's\n // abstraction, never its implementation (`core`/`ui`/`features`/\n // `infrastructure`), which stays hidden behind DI wired up in the composition\n // root. No-op (with a warning) when there is no ESLint config.\n applyDepConstraints(tree, [\n {\n sourceTag: domainTag,\n onlyDependOnLibsWithTags: [\n domainTag,\n LibraryScope.Shared,\n LibraryType.Contracts,\n ],\n },\n ]);\n\n await formatFiles(tree);\n\n return runTasksInSerial(...tasks);\n}\n\n/** Composes a layer library name, applying the optional organization prefix. */\nfunction layerName(options: DomainGeneratorSchema, layer: string): string {\n const base = `${options.name}-${layer}`;\n return options.prefix ? `${options.prefix}/${base}` : base;\n}\n\n/**\n * Generates a presentational/feature layer library and returns its install\n * callback. Under the `react` preset it uses `@nx/react`'s generator (loaded\n * lazily via `ensurePackage` so the domain generator never hard-depends on\n * `@nx/react` in non-React workspaces); under `none` it uses `@nx/js` and adds\n * the DOM lib to the library `tsconfig` so browser globals type-check.\n *\n * Both pass `addPlugin: true` so the library gets inferred tasks (Project\n * Crystal) rather than the deprecated executor targets the generators' public\n * wrappers default to.\n */\nasync function generateLayerLibrary(\n tree: Tree,\n options: DomainGeneratorSchema,\n layer: { root: string; name: string; tags: string },\n): Promise<GeneratorCallback> {\n if (options.preset === 'react') {\n const { libraryGenerator: reactLibraryGenerator } = ensurePackage<\n typeof import('@nx/react')\n >('@nx/react', NX_VERSION);\n\n return await reactLibraryGenerator(tree, {\n name: layer.name,\n directory: layer.root,\n useProjectJson: false,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n style: 'none',\n tags: layer.tags,\n });\n }\n\n const task = await jsLibraryGenerator(tree, {\n name: layer.name,\n directory: layer.root,\n useProjectJson: false,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n tags: layer.tags,\n });\n addDomLibToTsConfig(tree, layer.root);\n return task;\n}\n\n/** Adds the `DOM` lib to a library's `tsconfig.lib.json` (idempotent). */\nfunction addDomLibToTsConfig(tree: Tree, root: string) {\n updateJson(tree, `${root}/tsconfig.lib.json`, (json) => {\n json.compilerOptions ??= {};\n if (!json.compilerOptions.lib) {\n json.compilerOptions.lib = ['ESNext', 'DOM'];\n } else if (!json.compilerOptions.lib.includes('DOM')) {\n json.compilerOptions.lib.push('DOM');\n }\n return json;\n });\n}\n\nexport default domainGenerator;\n"],"names":["domainGenerator","SHARED_CONTRACTS_ROOT","tree","options","libraryExists","warning","contractsRoot","directory","coreRoot","uiRoot","featuresRoot","domainTag","name","facadeDomainInterfaceVariants","names","tasks","layers","includes","push","jsLibraryGenerator","layerName","useProjectJson","addPlugin","unitTestRunner","bundler","linter","tags","LibraryScope","Domain","LibraryType","Contracts","type","resolveLibraryModuleFormat","delete","write","generateFiles","resolve","__dirname","interfaceName","className","esm","ModuleFormat","EsModule","overwriteStrategy","OverwriteStrategy","Overwrite","Core","contractsPackage","exists","readJson","contractsVersion","version","updateJson","pkg","dependencies","applyCleanArchitectureBoundaries","prefix","generateLayerLibrary","root","Ui","Features","applyDepConstraints","sourceTag","onlyDependOnLibsWithTags","Shared","formatFiles","runTasksInSerial","layer","base","preset","libraryGenerator","reactLibraryGenerator","ensurePackage","NX_VERSION","style","task","addDomLibToTsConfig","json","compilerOptions","lib"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx/src/generators/domain/domain.ts"],"sourcesContent":["import {\n ensurePackage,\n formatFiles,\n generateFiles,\n names,\n NX_VERSION,\n OverwriteStrategy,\n readJson,\n runTasksInSerial,\n type GeneratorCallback,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { libraryGenerator as jsLibraryGenerator } from '@nx/js';\nimport { resolve } from 'path';\n\nimport type { DomainGeneratorSchema } from './schema';\nimport { libraryExists } from '../../utils/library-exist';\nimport {\n applyCleanArchitectureBoundaries,\n applyDepConstraints,\n} from '../../utils/eslint-module-boundaries';\nimport { warning } from '../../utils/logger';\nimport { LibraryScope, LibraryType, ModuleFormat } from '../../types';\nimport { resolveLibraryModuleFormat } from '../../utils/resolve-module-format';\n\n/** Conventional location of the shared kernel's contracts library. */\nconst SHARED_CONTRACTS_ROOT = 'libs/shared/contracts';\n\nexport async function domainGenerator(\n tree: Tree,\n options: DomainGeneratorSchema,\n): Promise<GeneratorCallback> {\n // Implicit existence check (CLAUDE.md 7.3.1): domain libraries depend on the\n // shared kernel, so warn if it has not been generated yet rather than\n // producing libraries whose boundary constraints reference tags nothing\n // carries.\n if (!libraryExists(tree, SHARED_CONTRACTS_ROOT)) {\n warning(\n `Shared kernel not found at ${SHARED_CONTRACTS_ROOT}. Run \\`nx g @tactical-ddd/nx:init\\` (or the \\`shared-kernel\\` generator) first so domain libraries can depend on the shared contracts.`,\n );\n }\n\n const contractsRoot = `${options.directory}/contracts`;\n const coreRoot = `${options.directory}/core`;\n const uiRoot = `${options.directory}/ui`;\n const featuresRoot = `${options.directory}/features`;\n const domainTag = `domain:${options.name}`;\n const facadeDomainInterfaceVariants = names(`${options.name}Facade`);\n\n // Install callbacks from the delegated library generators — returned to Nx so\n // the packages backing the inferred plugins (`@nx/eslint`, `@nx/jest`) the\n // libraries register via `addPlugin` get installed.\n const tasks: GeneratorCallback[] = [];\n\n if (\n !libraryExists(tree, contractsRoot) &&\n options.layers.includes('contracts')\n ) {\n tasks.push(\n await jsLibraryGenerator(tree, {\n name: layerName(options, 'contracts'),\n directory: contractsRoot,\n addPlugin: true,\n unitTestRunner: 'none',\n bundler: options.bundler,\n linter: options.linter,\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Contracts}`,\n }),\n );\n\n const type = resolveLibraryModuleFormat(tree, contractsRoot);\n\n tree.delete(`${contractsRoot}/src/lib/${options.name}-contracts.ts`);\n tree.write(`${contractsRoot}/src/index.ts`, '');\n generateFiles(\n tree,\n resolve(__dirname, 'files/contracts'),\n contractsRoot,\n {\n name: options.name,\n interfaceName: facadeDomainInterfaceVariants.className,\n esm: type === ModuleFormat.EsModule,\n },\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n }\n\n if (!libraryExists(tree, coreRoot) && options.layers.includes('core')) {\n tasks.push(\n await jsLibraryGenerator(tree, {\n name: layerName(options, 'core'),\n directory: coreRoot,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Core}`,\n }),\n );\n\n const type = resolveLibraryModuleFormat(tree, coreRoot);\n const contractsPackage = layerName(options, 'contracts');\n\n tree.delete(`${coreRoot}/src/lib/${options.name}-core.ts`);\n tree.delete(`${coreRoot}/src/lib/${options.name}-core.spec.ts`);\n tree.write(`${coreRoot}/src/index.ts`, '');\n\n // Scaffold the default Clean Architecture layer folders (domain,\n // application, infrastructure — each kept in git via a `.gitkeep`) and lock\n // down imports between them: domain ⊀ application/infrastructure, and\n // application ⊀ infrastructure (the implementation is wired via DI at the\n // composition root, not imported across layers).\n generateFiles(\n tree,\n resolve(__dirname, 'files/core'),\n coreRoot,\n {\n name: options.name,\n interfaceName: facadeDomainInterfaceVariants.className,\n // Full package name of this domain's contracts library, so the facade's\n // import resolves with or without an organization prefix.\n contractsPackage,\n esm: type === ModuleFormat.EsModule,\n },\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n\n // The generated facade imports the domain's contracts package, so declare it\n // as a dependency — otherwise `@nx/dependency-checks` flags the core library\n // for using a package missing from its `package.json`.\n if (tree.exists(`${contractsRoot}/package.json`)) {\n const contractsVersion =\n readJson(tree, `${contractsRoot}/package.json`).version ?? '*';\n updateJson(tree, `${coreRoot}/package.json`, (pkg) => {\n pkg.dependencies = {\n ...pkg.dependencies,\n [contractsPackage]: contractsVersion,\n };\n return pkg;\n });\n }\n\n applyCleanArchitectureBoundaries(tree, coreRoot, options.prefix);\n }\n\n if (!libraryExists(tree, uiRoot) && options.layers.includes('ui')) {\n tasks.push(\n await generateLayerLibrary(tree, options, {\n root: uiRoot,\n name: layerName(options, 'ui'),\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Ui}`,\n }),\n );\n }\n\n if (\n !libraryExists(tree, featuresRoot) &&\n options.layers.includes('features')\n ) {\n tasks.push(\n await generateLayerLibrary(tree, options, {\n root: featuresRoot,\n name: layerName(options, 'features'),\n tags: `${LibraryScope.Domain},${domainTag},${LibraryType.Features}`,\n }),\n );\n }\n\n // Silo this domain: per-domain constraints are what actually prevent\n // cross-domain imports (a static `domain:*` rule cannot — Nx glob-matches the\n // target tags, so it would let `domain:auth` import `domain:payments`).\n //\n // A `domain:<name>` library may depend on its own domain, the shared kernel,\n // and the *public contracts* of any other domain (`type:contracts`) — the\n // published-language pattern: a domain depends on another domain's\n // abstraction, never its implementation (`core`/`ui`/`features`/\n // `infrastructure`), which stays hidden behind DI wired up in the composition\n // root. No-op (with a warning) when there is no ESLint config.\n applyDepConstraints(tree, [\n {\n sourceTag: domainTag,\n onlyDependOnLibsWithTags: [\n domainTag,\n LibraryScope.Shared,\n LibraryType.Contracts,\n ],\n },\n ]);\n\n await formatFiles(tree);\n\n return runTasksInSerial(...tasks);\n}\n\n/** Composes a layer library name, applying the optional organization prefix. */\nfunction layerName(options: DomainGeneratorSchema, layer: string): string {\n const base = `${options.name}-${layer}`;\n return options.prefix ? `${options.prefix}/${base}` : base;\n}\n\n/**\n * Generates a presentational/feature layer library and returns its install\n * callback. Under the `react` preset it uses `@nx/react`'s generator (loaded\n * lazily via `ensurePackage` so the domain generator never hard-depends on\n * `@nx/react` in non-React workspaces); under `none` it uses `@nx/js` and adds\n * the DOM lib to the library `tsconfig` so browser globals type-check.\n *\n * Both pass `addPlugin: true` so the library gets inferred tasks (Project\n * Crystal) rather than the deprecated executor targets the generators' public\n * wrappers default to.\n */\nasync function generateLayerLibrary(\n tree: Tree,\n options: DomainGeneratorSchema,\n layer: { root: string; name: string; tags: string },\n): Promise<GeneratorCallback> {\n if (options.preset === 'react') {\n const { libraryGenerator: reactLibraryGenerator } = ensurePackage<\n typeof import('@nx/react')\n >('@nx/react', NX_VERSION);\n\n return await reactLibraryGenerator(tree, {\n name: layer.name,\n directory: layer.root,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n style: 'none',\n tags: layer.tags,\n });\n }\n\n const task = await jsLibraryGenerator(tree, {\n name: layer.name,\n directory: layer.root,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n tags: layer.tags,\n });\n addDomLibToTsConfig(tree, layer.root);\n return task;\n}\n\n/** Adds the `DOM` lib to a library's `tsconfig.lib.json` (idempotent). */\nfunction addDomLibToTsConfig(tree: Tree, root: string) {\n updateJson(tree, `${root}/tsconfig.lib.json`, (json) => {\n json.compilerOptions ??= {};\n if (!json.compilerOptions.lib) {\n json.compilerOptions.lib = ['ESNext', 'DOM'];\n } else if (!json.compilerOptions.lib.includes('DOM')) {\n json.compilerOptions.lib.push('DOM');\n }\n return json;\n });\n}\n\nexport default domainGenerator;\n"],"names":["domainGenerator","SHARED_CONTRACTS_ROOT","tree","options","libraryExists","warning","contractsRoot","directory","coreRoot","uiRoot","featuresRoot","domainTag","name","facadeDomainInterfaceVariants","names","tasks","layers","includes","push","jsLibraryGenerator","layerName","addPlugin","unitTestRunner","bundler","linter","tags","LibraryScope","Domain","LibraryType","Contracts","type","resolveLibraryModuleFormat","delete","write","generateFiles","resolve","__dirname","interfaceName","className","esm","ModuleFormat","EsModule","overwriteStrategy","OverwriteStrategy","Overwrite","Core","contractsPackage","exists","readJson","contractsVersion","version","updateJson","pkg","dependencies","applyCleanArchitectureBoundaries","prefix","generateLayerLibrary","root","Ui","Features","applyDepConstraints","sourceTag","onlyDependOnLibsWithTags","Shared","formatFiles","runTasksInSerial","layer","base","preset","libraryGenerator","reactLibraryGenerator","ensurePackage","NX_VERSION","style","task","addDomLibToTsConfig","json","compilerOptions","lib"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/generators/init/init.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/generators/init/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,iBAAiB,EAEtB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAyDpD,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CA8B5B;AA+JD,eAAe,aAAa,CAAC"}
|
package/generators/init/init.js
CHANGED
|
@@ -47,11 +47,13 @@ const REACT_LIBRARY_GENERATORS = [
|
|
|
47
47
|
];
|
|
48
48
|
/** The Tactical DDD React runtime bindings package. */ const TACTICAL_DDD_REACT = '@tactical-ddd/react';
|
|
49
49
|
/**
|
|
50
|
-
* React runtime
|
|
51
|
-
* preset.
|
|
52
|
-
*
|
|
50
|
+
* React runtime version added to the *user's* workspace under the `react`
|
|
51
|
+
* preset. `react` and `react-dom` are pinned to the *same* specifier and only
|
|
52
|
+
* ever added together (see {@link ensureGeneratorDependencies}) so we never
|
|
53
|
+
* introduce a `react` vs `react-dom` version skew of our own. Kept in step with
|
|
54
|
+
* the React version `@nx/react`'s own generators install so the two never
|
|
55
|
+
* disagree.
|
|
53
56
|
*/ const REACT_VERSION = '^19.0.0';
|
|
54
|
-
const REACT_DOM_VERSION = '^19.0.0';
|
|
55
57
|
/**
|
|
56
58
|
* Version specifier to install `@tactical-ddd/react` at. The React bindings are
|
|
57
59
|
* released in lockstep with this plugin, so we mirror the running plugin's own
|
|
@@ -106,8 +108,17 @@ async function initGenerator(tree, options) {
|
|
|
106
108
|
* Dependencies are scoped to the chosen options: the ESLint tooling is only
|
|
107
109
|
* required when `linter: 'eslint'`, and the test-runner plugin follows
|
|
108
110
|
* `unitTestRunner`. The `react` preset additionally pulls in the `@nx/react`
|
|
109
|
-
* generator plugin (dev-time) plus the
|
|
110
|
-
*
|
|
111
|
+
* generator plugin (dev-time) plus the `@tactical-ddd/react` bindings as a
|
|
112
|
+
* production dependency.
|
|
113
|
+
*
|
|
114
|
+
* The `react`/`react-dom` runtime is treated carefully: a React workspace
|
|
115
|
+
* already ships its own React, and declaring our own range on top adds nothing
|
|
116
|
+
* but forces the package manager to re-resolve — which can surface a latent
|
|
117
|
+
* peer-dependency conflict already present in the workspace (e.g. an exactly
|
|
118
|
+
* pinned `react` that a newer `react-dom` patch no longer satisfies) and abort
|
|
119
|
+
* the install. So we only add `react` and `react-dom` when *neither* is already
|
|
120
|
+
* present, and add them together at the same {@link REACT_VERSION} specifier —
|
|
121
|
+
* never introducing a skew of our own.
|
|
111
122
|
*/ function ensureGeneratorDependencies(tree, options) {
|
|
112
123
|
const dependencies = {};
|
|
113
124
|
const devDependencies = {
|
|
@@ -129,13 +140,28 @@ async function initGenerator(tree, options) {
|
|
|
129
140
|
if (options.preset === 'react') {
|
|
130
141
|
// Dev-time: powers the `@nx/react:library` defaults and React generators.
|
|
131
142
|
devDependencies['@nx/react'] = _devkit.NX_VERSION;
|
|
132
|
-
// Run-time:
|
|
133
|
-
dependencies['react'] = REACT_VERSION;
|
|
134
|
-
dependencies['react-dom'] = REACT_DOM_VERSION;
|
|
143
|
+
// Run-time: our React bindings always ship in the app.
|
|
135
144
|
dependencies[TACTICAL_DDD_REACT] = tacticalDddReactVersion();
|
|
145
|
+
// Only provide the React runtime when the workspace manages neither half of
|
|
146
|
+
// it yet; if it already has `react` (or `react-dom`), defer to whatever
|
|
147
|
+
// versions it pinned rather than re-resolving and risking a peer conflict.
|
|
148
|
+
if (!workspaceHasReactRuntime(tree)) {
|
|
149
|
+
dependencies['react'] = REACT_VERSION;
|
|
150
|
+
dependencies['react-dom'] = REACT_VERSION;
|
|
151
|
+
}
|
|
136
152
|
}
|
|
137
153
|
return (0, _devkit.addDependenciesToPackageJson)(tree, dependencies, devDependencies);
|
|
138
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Whether the workspace `package.json` already declares `react` or `react-dom`
|
|
157
|
+
* (in either `dependencies` or `devDependencies`). When it does, `init` leaves
|
|
158
|
+
* the React runtime untouched so it can't introduce a version skew or trigger a
|
|
159
|
+
* conflicting re-resolve.
|
|
160
|
+
*/ function workspaceHasReactRuntime(tree) {
|
|
161
|
+
const packageJson = (0, _devkit.readJson)(tree, 'package.json');
|
|
162
|
+
const declared = _extends._({}, packageJson.devDependencies, packageJson.dependencies);
|
|
163
|
+
return 'react' in declared || 'react-dom' in declared;
|
|
164
|
+
}
|
|
139
165
|
/**
|
|
140
166
|
* Persists workspace-wide generator defaults into `nx.json` so choices like the
|
|
141
167
|
* organization `prefix`, linter and test runner are configured once during
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx/src/generators/init/init.ts"],"sourcesContent":["import {\n addDependenciesToPackageJson,\n formatFiles,\n NX_VERSION,\n readNxJson,\n runTasksInSerial,\n updateNxJson,\n type GeneratorCallback,\n type NxJsonConfiguration,\n type Tree,\n} from '@nx/devkit';\n\nimport type { InitGeneratorSchema } from './schema';\nimport { DEP_CONSTRAINTS } from './module-boundaries';\nimport { applyDepConstraints } from '../../utils/eslint-module-boundaries';\nimport sharedKernelGenerator from '../shared-kernel/shared-kernel';\n\n/**\n * Collection name this plugin publishes its generators under. Used as the key\n * in `nx.json`'s `generators` map so defaults apply to every generator we ship.\n */\nconst COLLECTION = '@tactical-ddd/nx';\n\n/**\n * Generators that accept (and should inherit) the workspace-wide `prefix`.\n * Extend this list as new generators are added — for now only `shared-kernel`\n * consumes the prefix.\n */\nconst PREFIXED_GENERATORS = ['shared-kernel', 'domain'] as const;\n\n/**\n * Built-in Nx library generators that should inherit the workspace-wide\n * build/lint/test defaults so hand-rolled libraries match the conventions.\n * `@nx/js:library` always applies; `@nx/react:library` is layered on only for\n * the `react` preset (see {@link setGeneratorDefaults}).\n */\nconst BASE_LIBRARY_GENERATORS = ['@nx/js:library'] as const;\nconst REACT_LIBRARY_GENERATORS = ['@nx/react:library'] as const;\n\n/** The Tactical DDD React runtime bindings package. */\nconst TACTICAL_DDD_REACT = '@tactical-ddd/react';\n\n/**\n * React runtime versions added to the *user's* workspace under the `react`\n * preset. Kept in step with the React version `@nx/react`'s own generators\n * install so the two never disagree.\n */\nconst REACT_VERSION = '^19.0.0';\nconst REACT_DOM_VERSION = '^19.0.0';\n\n/**\n * Version specifier to install `@tactical-ddd/react` at. The React bindings are\n * released in lockstep with this plugin, so we mirror the running plugin's own\n * version. This also makes the e2e suite resolve the locally-published build:\n * both packages are published to the local registry under the same e2e version.\n */\nfunction tacticalDddReactVersion(): string {\n try {\n // Resolves from the workspace the generator runs in, where the plugin is\n // installed (real usage and e2e).\n return require('@tactical-ddd/nx/package.json').version as string;\n } catch {\n // Source / unit-test fallback: this package's own manifest.\n return require('../../../package.json').version as string;\n }\n}\n\nexport async function initGenerator(\n tree: Tree,\n options: InitGeneratorSchema,\n): Promise<GeneratorCallback> {\n setGeneratorDefaults(tree, options);\n\n // Make sure every Nx plugin the configured/invoked generators rely on is\n // present; the returned task installs whatever was missing once the generator\n // finishes writing to the tree.\n const installDependencies = ensureGeneratorDependencies(tree, options);\n\n // Generate the shared kernel first: in a fresh workspace the root ESLint\n // config does not exist until the first library is generated, so this is what\n // establishes the config that `applyDepConstraints` then tunes.\n const installKernel = await sharedKernelGenerator(tree, {\n directory: options.sharedDirectory,\n prefix: options.prefix,\n linter: options.linter,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n });\n\n // Populate the root ESLint config with the Tactical DDD dependency graph so\n // the architecture is enforced at lint time. Skipped (with a warning) when\n // the workspace has no ESLint config — e.g. `linter: none`.\n applyDepConstraints(tree, DEP_CONSTRAINTS);\n\n await formatFiles(tree);\n\n // Run both the plugin-dependency install and the shared kernel's own install\n // callbacks (the latter installs the packages backing the inferred ESLint/Jest\n // plugins the generated libraries registered).\n return runTasksInSerial(installDependencies, installKernel);\n}\n\n/**\n * Ensures the Nx plugin packages the configured/invoked generators depend on are\n * declared in the workspace `package.json`, installing any that are missing.\n *\n * `addDependenciesToPackageJson` is itself the presence check: it only adds (or\n * bumps) entries that are absent or older, leaving existing versions untouched,\n * and returns a task that runs the package manager install for whatever changed.\n * All versions are pinned to `NX_VERSION` — the Nx version this plugin runs\n * against — so the added plugins stay in lockstep with the workspace's Nx core.\n *\n * Dependencies are scoped to the chosen options: the ESLint tooling is only\n * required when `linter: 'eslint'`, and the test-runner plugin follows\n * `unitTestRunner`. The `react` preset additionally pulls in the `@nx/react`\n * generator plugin (dev-time) plus the React runtime — `react`, `react-dom`\n * and the `@tactical-ddd/react` bindings — as production dependencies.\n */\nfunction ensureGeneratorDependencies(\n tree: Tree,\n options: InitGeneratorSchema,\n): GeneratorCallback {\n const dependencies: Record<string, string> = {};\n const devDependencies: Record<string, string> = {\n // Powers the shared-kernel generator (`@nx/js:library`) and the\n // `@nx/js:library` defaults written above.\n '@nx/js': NX_VERSION,\n };\n\n if (options.linter === 'eslint') {\n // `@nx/eslint` provides the flat-config AST utilities and lint target;\n // `@nx/eslint-plugin` provides the `@nx/enforce-module-boundaries` rule.\n devDependencies['@nx/eslint'] = NX_VERSION;\n devDependencies['@nx/eslint-plugin'] = NX_VERSION;\n }\n\n if (options.unitTestRunner === 'jest') {\n devDependencies['@nx/jest'] = NX_VERSION;\n } else if (options.unitTestRunner === 'vitest') {\n devDependencies['@nx/vite'] = NX_VERSION;\n }\n\n if (options.preset === 'react') {\n // Dev-time: powers the `@nx/react:library` defaults and React generators.\n devDependencies['@nx/react'] = NX_VERSION;\n // Run-time: the React framework and our React bindings ship in the app.\n dependencies['react'] = REACT_VERSION;\n dependencies['react-dom'] = REACT_DOM_VERSION;\n dependencies[TACTICAL_DDD_REACT] = tacticalDddReactVersion();\n }\n\n return addDependenciesToPackageJson(tree, dependencies, devDependencies);\n}\n\n/**\n * Persists workspace-wide generator defaults into `nx.json` so choices like the\n * organization `prefix`, linter and test runner are configured once during\n * `init` and then transparently injected by Nx into every subsequent generator\n * invocation (e.g. `nx g @tactical-ddd/nx:shared-kernel`, or even the built-in\n * `nx g @nx/js:library`) without the user re-typing them.\n *\n * Two groups of defaults are written:\n *\n * \"generators\": {\n * // 1. Our own collection — inherit the prefix and linting/testing choices.\n * \"@tactical-ddd/nx\": {\n * \"shared-kernel\": { \"prefix\": \"@my-org\", \"linter\": \"eslint\", \"unitTestRunner\": \"jest\" }\n * },\n * // 2. The built-in library generators — so hand-rolled libs match conventions.\n * \"@nx/js:library\": { \"bundler\": \"none\", \"linter\": \"eslint\", \"unitTestRunner\": \"jest\" },\n * // `@nx/react:library` is added only under the `react` preset.\n * \"@nx/react:library\": { \"bundler\": \"none\", \"linter\": \"eslint\", \"unitTestRunner\": \"jest\" }\n * }\n */\nfunction setGeneratorDefaults(tree: Tree, options: InitGeneratorSchema) {\n const nxJson = readNxJson(tree) ?? ({} as NxJsonConfiguration);\n\n const generators = (nxJson.generators ??= {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n // 1. Our own collection's generators inherit the prefix + linting/testing.\n const collectionDefaults = (generators[COLLECTION] ??= {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n for (const generator of PREFIXED_GENERATORS) {\n collectionDefaults[generator] = {\n ...collectionDefaults[generator],\n prefix: options.prefix,\n linter: options.linter,\n unitTestRunner: options.unitTestRunner,\n preset: options.preset,\n };\n }\n\n // 2. The built-in library generators get the same workspace-wide build/lint/\n // test defaults, so a plain `nx g @nx/js:library` (or `@nx/react:library`)\n // produces a library that already matches the Tactical DDD conventions.\n // `@nx/react:library` defaults are written only under the `react` preset, so\n // we don't advertise React tooling a non-React workspace never installed.\n const libraryDefaults: Record<string, unknown> = {\n bundler: options.bundler ?? 'none',\n linter: options.linter,\n unitTestRunner: options.unitTestRunner,\n };\n\n const libraryGenerators =\n options.preset === 'react'\n ? [...BASE_LIBRARY_GENERATORS, ...REACT_LIBRARY_GENERATORS]\n : BASE_LIBRARY_GENERATORS;\n\n for (const generator of libraryGenerators) {\n generators[generator] = {\n ...generators[generator],\n ...libraryDefaults,\n };\n }\n\n updateNxJson(tree, nxJson);\n}\n\nexport default initGenerator;\n"],"names":["initGenerator","COLLECTION","PREFIXED_GENERATORS","BASE_LIBRARY_GENERATORS","REACT_LIBRARY_GENERATORS","TACTICAL_DDD_REACT","REACT_VERSION","REACT_DOM_VERSION","tacticalDddReactVersion","require","version","tree","options","setGeneratorDefaults","installDependencies","ensureGeneratorDependencies","installKernel","sharedKernelGenerator","directory","sharedDirectory","prefix","linter","unitTestRunner","bundler","applyDepConstraints","DEP_CONSTRAINTS","formatFiles","runTasksInSerial","dependencies","devDependencies","NX_VERSION","preset","addDependenciesToPackageJson","readNxJson","nxJson","generators","collectionDefaults","generator","libraryDefaults","libraryGenerators","updateNxJson"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx/src/generators/init/init.ts"],"sourcesContent":["import {\n addDependenciesToPackageJson,\n formatFiles,\n NX_VERSION,\n readJson,\n readNxJson,\n runTasksInSerial,\n updateNxJson,\n type GeneratorCallback,\n type NxJsonConfiguration,\n type Tree,\n} from '@nx/devkit';\n\nimport type { InitGeneratorSchema } from './schema';\nimport { DEP_CONSTRAINTS } from './module-boundaries';\nimport { applyDepConstraints } from '../../utils/eslint-module-boundaries';\nimport sharedKernelGenerator from '../shared-kernel/shared-kernel';\n\n/**\n * Collection name this plugin publishes its generators under. Used as the key\n * in `nx.json`'s `generators` map so defaults apply to every generator we ship.\n */\nconst COLLECTION = '@tactical-ddd/nx';\n\n/**\n * Generators that accept (and should inherit) the workspace-wide `prefix`.\n * Extend this list as new generators are added — for now only `shared-kernel`\n * consumes the prefix.\n */\nconst PREFIXED_GENERATORS = ['shared-kernel', 'domain'] as const;\n\n/**\n * Built-in Nx library generators that should inherit the workspace-wide\n * build/lint/test defaults so hand-rolled libraries match the conventions.\n * `@nx/js:library` always applies; `@nx/react:library` is layered on only for\n * the `react` preset (see {@link setGeneratorDefaults}).\n */\nconst BASE_LIBRARY_GENERATORS = ['@nx/js:library'] as const;\nconst REACT_LIBRARY_GENERATORS = ['@nx/react:library'] as const;\n\n/** The Tactical DDD React runtime bindings package. */\nconst TACTICAL_DDD_REACT = '@tactical-ddd/react';\n\n/**\n * React runtime version added to the *user's* workspace under the `react`\n * preset. `react` and `react-dom` are pinned to the *same* specifier and only\n * ever added together (see {@link ensureGeneratorDependencies}) so we never\n * introduce a `react` vs `react-dom` version skew of our own. Kept in step with\n * the React version `@nx/react`'s own generators install so the two never\n * disagree.\n */\nconst REACT_VERSION = '^19.0.0';\n\n/**\n * Version specifier to install `@tactical-ddd/react` at. The React bindings are\n * released in lockstep with this plugin, so we mirror the running plugin's own\n * version. This also makes the e2e suite resolve the locally-published build:\n * both packages are published to the local registry under the same e2e version.\n */\nfunction tacticalDddReactVersion(): string {\n try {\n // Resolves from the workspace the generator runs in, where the plugin is\n // installed (real usage and e2e).\n return require('@tactical-ddd/nx/package.json').version as string;\n } catch {\n // Source / unit-test fallback: this package's own manifest.\n return require('../../../package.json').version as string;\n }\n}\n\nexport async function initGenerator(\n tree: Tree,\n options: InitGeneratorSchema,\n): Promise<GeneratorCallback> {\n setGeneratorDefaults(tree, options);\n\n // Make sure every Nx plugin the configured/invoked generators rely on is\n // present; the returned task installs whatever was missing once the generator\n // finishes writing to the tree.\n const installDependencies = ensureGeneratorDependencies(tree, options);\n\n // Generate the shared kernel first: in a fresh workspace the root ESLint\n // config does not exist until the first library is generated, so this is what\n // establishes the config that `applyDepConstraints` then tunes.\n const installKernel = await sharedKernelGenerator(tree, {\n directory: options.sharedDirectory,\n prefix: options.prefix,\n linter: options.linter,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n });\n\n // Populate the root ESLint config with the Tactical DDD dependency graph so\n // the architecture is enforced at lint time. Skipped (with a warning) when\n // the workspace has no ESLint config — e.g. `linter: none`.\n applyDepConstraints(tree, DEP_CONSTRAINTS);\n\n await formatFiles(tree);\n\n // Run both the plugin-dependency install and the shared kernel's own install\n // callbacks (the latter installs the packages backing the inferred ESLint/Jest\n // plugins the generated libraries registered).\n return runTasksInSerial(installDependencies, installKernel);\n}\n\n/**\n * Ensures the Nx plugin packages the configured/invoked generators depend on are\n * declared in the workspace `package.json`, installing any that are missing.\n *\n * `addDependenciesToPackageJson` is itself the presence check: it only adds (or\n * bumps) entries that are absent or older, leaving existing versions untouched,\n * and returns a task that runs the package manager install for whatever changed.\n * All versions are pinned to `NX_VERSION` — the Nx version this plugin runs\n * against — so the added plugins stay in lockstep with the workspace's Nx core.\n *\n * Dependencies are scoped to the chosen options: the ESLint tooling is only\n * required when `linter: 'eslint'`, and the test-runner plugin follows\n * `unitTestRunner`. The `react` preset additionally pulls in the `@nx/react`\n * generator plugin (dev-time) plus the `@tactical-ddd/react` bindings as a\n * production dependency.\n *\n * The `react`/`react-dom` runtime is treated carefully: a React workspace\n * already ships its own React, and declaring our own range on top adds nothing\n * but forces the package manager to re-resolve — which can surface a latent\n * peer-dependency conflict already present in the workspace (e.g. an exactly\n * pinned `react` that a newer `react-dom` patch no longer satisfies) and abort\n * the install. So we only add `react` and `react-dom` when *neither* is already\n * present, and add them together at the same {@link REACT_VERSION} specifier —\n * never introducing a skew of our own.\n */\nfunction ensureGeneratorDependencies(\n tree: Tree,\n options: InitGeneratorSchema,\n): GeneratorCallback {\n const dependencies: Record<string, string> = {};\n const devDependencies: Record<string, string> = {\n // Powers the shared-kernel generator (`@nx/js:library`) and the\n // `@nx/js:library` defaults written above.\n '@nx/js': NX_VERSION,\n };\n\n if (options.linter === 'eslint') {\n // `@nx/eslint` provides the flat-config AST utilities and lint target;\n // `@nx/eslint-plugin` provides the `@nx/enforce-module-boundaries` rule.\n devDependencies['@nx/eslint'] = NX_VERSION;\n devDependencies['@nx/eslint-plugin'] = NX_VERSION;\n }\n\n if (options.unitTestRunner === 'jest') {\n devDependencies['@nx/jest'] = NX_VERSION;\n } else if (options.unitTestRunner === 'vitest') {\n devDependencies['@nx/vite'] = NX_VERSION;\n }\n\n if (options.preset === 'react') {\n // Dev-time: powers the `@nx/react:library` defaults and React generators.\n devDependencies['@nx/react'] = NX_VERSION;\n // Run-time: our React bindings always ship in the app.\n dependencies[TACTICAL_DDD_REACT] = tacticalDddReactVersion();\n\n // Only provide the React runtime when the workspace manages neither half of\n // it yet; if it already has `react` (or `react-dom`), defer to whatever\n // versions it pinned rather than re-resolving and risking a peer conflict.\n if (!workspaceHasReactRuntime(tree)) {\n dependencies['react'] = REACT_VERSION;\n dependencies['react-dom'] = REACT_VERSION;\n }\n }\n\n return addDependenciesToPackageJson(tree, dependencies, devDependencies);\n}\n\n/**\n * Whether the workspace `package.json` already declares `react` or `react-dom`\n * (in either `dependencies` or `devDependencies`). When it does, `init` leaves\n * the React runtime untouched so it can't introduce a version skew or trigger a\n * conflicting re-resolve.\n */\nfunction workspaceHasReactRuntime(tree: Tree): boolean {\n const packageJson = readJson<{\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n }>(tree, 'package.json');\n\n const declared = {\n ...packageJson.devDependencies,\n ...packageJson.dependencies,\n };\n\n return 'react' in declared || 'react-dom' in declared;\n}\n\n/**\n * Persists workspace-wide generator defaults into `nx.json` so choices like the\n * organization `prefix`, linter and test runner are configured once during\n * `init` and then transparently injected by Nx into every subsequent generator\n * invocation (e.g. `nx g @tactical-ddd/nx:shared-kernel`, or even the built-in\n * `nx g @nx/js:library`) without the user re-typing them.\n *\n * Two groups of defaults are written:\n *\n * \"generators\": {\n * // 1. Our own collection — inherit the prefix and linting/testing choices.\n * \"@tactical-ddd/nx\": {\n * \"shared-kernel\": { \"prefix\": \"@my-org\", \"linter\": \"eslint\", \"unitTestRunner\": \"jest\" }\n * },\n * // 2. The built-in library generators — so hand-rolled libs match conventions.\n * \"@nx/js:library\": { \"bundler\": \"none\", \"linter\": \"eslint\", \"unitTestRunner\": \"jest\" },\n * // `@nx/react:library` is added only under the `react` preset.\n * \"@nx/react:library\": { \"bundler\": \"none\", \"linter\": \"eslint\", \"unitTestRunner\": \"jest\" }\n * }\n */\nfunction setGeneratorDefaults(tree: Tree, options: InitGeneratorSchema) {\n const nxJson = readNxJson(tree) ?? ({} as NxJsonConfiguration);\n\n const generators = (nxJson.generators ??= {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n // 1. Our own collection's generators inherit the prefix + linting/testing.\n const collectionDefaults = (generators[COLLECTION] ??= {}) as Record<\n string,\n Record<string, unknown>\n >;\n\n for (const generator of PREFIXED_GENERATORS) {\n collectionDefaults[generator] = {\n ...collectionDefaults[generator],\n prefix: options.prefix,\n linter: options.linter,\n unitTestRunner: options.unitTestRunner,\n preset: options.preset,\n };\n }\n\n // 2. The built-in library generators get the same workspace-wide build/lint/\n // test defaults, so a plain `nx g @nx/js:library` (or `@nx/react:library`)\n // produces a library that already matches the Tactical DDD conventions.\n // `@nx/react:library` defaults are written only under the `react` preset, so\n // we don't advertise React tooling a non-React workspace never installed.\n const libraryDefaults: Record<string, unknown> = {\n bundler: options.bundler ?? 'none',\n linter: options.linter,\n unitTestRunner: options.unitTestRunner,\n };\n\n const libraryGenerators =\n options.preset === 'react'\n ? [...BASE_LIBRARY_GENERATORS, ...REACT_LIBRARY_GENERATORS]\n : BASE_LIBRARY_GENERATORS;\n\n for (const generator of libraryGenerators) {\n generators[generator] = {\n ...generators[generator],\n ...libraryDefaults,\n };\n }\n\n updateNxJson(tree, nxJson);\n}\n\nexport default initGenerator;\n"],"names":["initGenerator","COLLECTION","PREFIXED_GENERATORS","BASE_LIBRARY_GENERATORS","REACT_LIBRARY_GENERATORS","TACTICAL_DDD_REACT","REACT_VERSION","tacticalDddReactVersion","require","version","tree","options","setGeneratorDefaults","installDependencies","ensureGeneratorDependencies","installKernel","sharedKernelGenerator","directory","sharedDirectory","prefix","linter","unitTestRunner","bundler","applyDepConstraints","DEP_CONSTRAINTS","formatFiles","runTasksInSerial","dependencies","devDependencies","NX_VERSION","preset","workspaceHasReactRuntime","addDependenciesToPackageJson","packageJson","readJson","declared","readNxJson","nxJson","generators","collectionDefaults","generator","libraryDefaults","libraryGenerators","updateNxJson"],"mappings":";;;;;;;;;;;QAsQA;eAAA;;QAhMsBA;eAAAA;;;;;wBA3Df;kCAGyB;wCACI;uEACF;AAElC;;;CAGC,GACD,MAAMC,aAAa;AAEnB;;;;CAIC,GACD,MAAMC,sBAAsB;IAAC;IAAiB;CAAS;AAEvD;;;;;CAKC,GACD,MAAMC,0BAA0B;IAAC;CAAiB;AAClD,MAAMC,2BAA2B;IAAC;CAAoB;AAEtD,qDAAqD,GACrD,MAAMC,qBAAqB;AAE3B;;;;;;;CAOC,GACD,MAAMC,gBAAgB;AAEtB;;;;;CAKC,GACD,SAASC;IACP,IAAI;QACF,yEAAyE;QACzE,kCAAkC;QAClC,OAAOC,QAAQ,iCAAiCC,OAAO;IACzD,EAAE,eAAM;QACN,4DAA4D;QAC5D,OAAOD,QAAQ,yBAAyBC,OAAO;IACjD;AACF;AAEO,eAAeT,cACpBU,IAAU,EACVC,OAA4B;IAE5BC,qBAAqBF,MAAMC;IAE3B,yEAAyE;IACzE,8EAA8E;IAC9E,gCAAgC;IAChC,MAAME,sBAAsBC,4BAA4BJ,MAAMC;IAE9D,yEAAyE;IACzE,8EAA8E;IAC9E,gEAAgE;IAChE,MAAMI,gBAAgB,MAAMC,IAAAA,qBAAqB,EAACN,MAAM;QACtDO,WAAWN,QAAQO,eAAe;QAClCC,QAAQR,QAAQQ,MAAM;QACtBC,QAAQT,QAAQS,MAAM;QACtBC,gBAAgBV,QAAQU,cAAc;QACtCC,SAASX,QAAQW,OAAO;IAC1B;IAEA,4EAA4E;IAC5E,2EAA2E;IAC3E,4DAA4D;IAC5DC,IAAAA,2CAAmB,EAACb,MAAMc,iCAAe;IAEzC,MAAMC,IAAAA,mBAAW,EAACf;IAElB,6EAA6E;IAC7E,+EAA+E;IAC/E,+CAA+C;IAC/C,OAAOgB,IAAAA,wBAAgB,EAACb,qBAAqBE;AAC/C;AAEA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,SAASD,4BACPJ,IAAU,EACVC,OAA4B;IAE5B,MAAMgB,eAAuC,CAAC;IAC9C,MAAMC,kBAA0C;QAC9C,gEAAgE;QAChE,2CAA2C;QAC3C,UAAUC,kBAAU;IACtB;IAEA,IAAIlB,QAAQS,MAAM,KAAK,UAAU;QAC/B,uEAAuE;QACvE,yEAAyE;QACzEQ,eAAe,CAAC,aAAa,GAAGC,kBAAU;QAC1CD,eAAe,CAAC,oBAAoB,GAAGC,kBAAU;IACnD;IAEA,IAAIlB,QAAQU,cAAc,KAAK,QAAQ;QACrCO,eAAe,CAAC,WAAW,GAAGC,kBAAU;IAC1C,OAAO,IAAIlB,QAAQU,cAAc,KAAK,UAAU;QAC9CO,eAAe,CAAC,WAAW,GAAGC,kBAAU;IAC1C;IAEA,IAAIlB,QAAQmB,MAAM,KAAK,SAAS;QAC9B,0EAA0E;QAC1EF,eAAe,CAAC,YAAY,GAAGC,kBAAU;QACzC,uDAAuD;QACvDF,YAAY,CAACtB,mBAAmB,GAAGE;QAEnC,4EAA4E;QAC5E,wEAAwE;QACxE,2EAA2E;QAC3E,IAAI,CAACwB,yBAAyBrB,OAAO;YACnCiB,YAAY,CAAC,QAAQ,GAAGrB;YACxBqB,YAAY,CAAC,YAAY,GAAGrB;QAC9B;IACF;IAEA,OAAO0B,IAAAA,oCAA4B,EAACtB,MAAMiB,cAAcC;AAC1D;AAEA;;;;;CAKC,GACD,SAASG,yBAAyBrB,IAAU;IAC1C,MAAMuB,cAAcC,IAAAA,gBAAQ,EAGzBxB,MAAM;IAET,MAAMyB,WAAW,eACZF,YAAYL,eAAe,EAC3BK,YAAYN,YAAY;IAG7B,OAAO,WAAWQ,YAAY,eAAeA;AAC/C;AAEA;;;;;;;;;;;;;;;;;;;CAmBC,GACD,SAASvB,qBAAqBF,IAAU,EAAEC,OAA4B;QACrDyB,aAEKC,SAAAA,aAMQC,cAAWrC,aAAXqC,GAqBjB3B;IA7BX,MAAM0B,UAASD,cAAAA,IAAAA,kBAAU,EAAC1B,iBAAX0B,cAAqB,CAAC;IAErC,MAAME,cAAcD,cAAAA,CAAAA,UAAAA,QAAOC,UAAU,YAAjBD,cAAAA,QAAOC,UAAU,GAAK,CAAC;IAK3C,2EAA2E;IAC3E,MAAMC,sBAAsBD,IAAAA,CAAAA,eAAAA,WAAU,CAACrC,cAAAA,WAAW,YAAtBqC,IAAAA,YAAU,CAACrC,YAAW,GAAK,CAAC;IAKxD,KAAK,MAAMuC,aAAatC,oBAAqB;QAC3CqC,kBAAkB,CAACC,UAAU,GAAG,eAC3BD,kBAAkB,CAACC,UAAU;YAChCrB,QAAQR,QAAQQ,MAAM;YACtBC,QAAQT,QAAQS,MAAM;YACtBC,gBAAgBV,QAAQU,cAAc;YACtCS,QAAQnB,QAAQmB,MAAM;;IAE1B;IAEA,6EAA6E;IAC7E,2EAA2E;IAC3E,wEAAwE;IACxE,6EAA6E;IAC7E,0EAA0E;IAC1E,MAAMW,kBAA2C;QAC/CnB,OAAO,GAAEX,mBAAAA,QAAQW,OAAO,YAAfX,mBAAmB;QAC5BS,QAAQT,QAAQS,MAAM;QACtBC,gBAAgBV,QAAQU,cAAc;IACxC;IAEA,MAAMqB,oBACJ/B,QAAQmB,MAAM,KAAK,UACf;WAAI3B;WAA4BC;KAAyB,GACzDD;IAEN,KAAK,MAAMqC,aAAaE,kBAAmB;QACzCJ,UAAU,CAACE,UAAU,GAAG,eACnBF,UAAU,CAACE,UAAU,EACrBC;IAEP;IAEAE,IAAAA,oBAAY,EAACjC,MAAM2B;AACrB;MAEA,WAAerC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# <%= prefix ? prefix + '/' : '' %>shared-contracts
|
|
2
|
+
|
|
3
|
+
Global, framework-agnostic **contracts** for the whole workspace — the published
|
|
4
|
+
language every layer is allowed to depend on.
|
|
5
|
+
|
|
6
|
+
- **Tags:** `scope:shared`, `type:contracts`
|
|
7
|
+
- **May import:** nothing. This is the root of the dependency graph.
|
|
8
|
+
- **Contains:** type-level declarations only — no runtime logic, no framework code.
|
|
9
|
+
|
|
10
|
+
## What goes here
|
|
11
|
+
|
|
12
|
+
- Cross-cutting interfaces and their DI tokens (e.g. `HttpClient`, `Store`).
|
|
13
|
+
- Shared DTOs and API request/response shapes.
|
|
14
|
+
- Global type aliases, enums and union types reused across domains.
|
|
15
|
+
|
|
16
|
+
Anything here can be imported by `shared/*` and by every domain's `contracts`
|
|
17
|
+
and `core`, so keep it stable and intentionally small.
|
|
18
|
+
|
|
19
|
+
## What does NOT go here
|
|
20
|
+
|
|
21
|
+
- Implementations of these interfaces — those live in `shared/infrastructure`
|
|
22
|
+
(or a domain's `core`), wired up via DI.
|
|
23
|
+
- Domain-specific contracts — those belong in `libs/<domain>/contracts`.
|
|
24
|
+
- Anything that imports another library.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# <%= prefix ? prefix + '/' : '' %>shared-infrastructure
|
|
2
|
+
|
|
3
|
+
Global, workspace-wide **infrastructure** — the concrete adapters that implement
|
|
4
|
+
the abstractions declared in `shared-contracts`.
|
|
5
|
+
|
|
6
|
+
- **Tags:** `scope:shared`, `type:infrastructure`
|
|
7
|
+
- **May import:** `shared-contracts` only.
|
|
8
|
+
- **Contains:** runtime implementations of cross-cutting technical concerns.
|
|
9
|
+
|
|
10
|
+
## What goes here
|
|
11
|
+
|
|
12
|
+
- HTTP/WS clients and `fetch`/`axios` wrappers implementing `HttpClient`.
|
|
13
|
+
- Storage adapters implementing `Store` (localStorage, cookies, in-memory…).
|
|
14
|
+
- Core data-layer setup shared across domains (e.g. `@tanstack/query-core`
|
|
15
|
+
query client configuration).
|
|
16
|
+
|
|
17
|
+
These implementations are wired into consumers via DI tokens from
|
|
18
|
+
`shared-contracts`, so application and domain code depends on the interface,
|
|
19
|
+
never on this library directly.
|
|
20
|
+
|
|
21
|
+
## What does NOT go here
|
|
22
|
+
|
|
23
|
+
- Type/interface declarations — those belong in `shared-contracts`.
|
|
24
|
+
- Pure, dependency-free helpers — those belong in `shared-utils`.
|
|
25
|
+
- Domain or business logic — that belongs in `libs/<domain>/core`.
|
|
26
|
+
- Imports from any domain library or `shared-utils`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# <%= prefix ? prefix + '/' : '' %>shared-utils
|
|
2
|
+
|
|
3
|
+
Global, framework-agnostic **utilities** — pure helper functions reused across
|
|
4
|
+
the whole workspace.
|
|
5
|
+
|
|
6
|
+
- **Tags:** `scope:shared`, `type:utils`
|
|
7
|
+
- **May import:** `shared-contracts` only.
|
|
8
|
+
- **Contains:** small, side-effect-free functions with no framework or I/O
|
|
9
|
+
dependencies.
|
|
10
|
+
|
|
11
|
+
## What goes here
|
|
12
|
+
|
|
13
|
+
- Date/time formatters and parsers.
|
|
14
|
+
- String, number and math helpers.
|
|
15
|
+
- Array/object transformation utilities, type guards and predicates.
|
|
16
|
+
|
|
17
|
+
Functions here should be deterministic and dependency-light, so they are safe to
|
|
18
|
+
import from anywhere (`shared/*` and every domain's `contracts`/`core`).
|
|
19
|
+
|
|
20
|
+
## What does NOT go here
|
|
21
|
+
|
|
22
|
+
- Interfaces/types — those belong in `shared-contracts`.
|
|
23
|
+
- Anything doing I/O, network or storage — that belongs in
|
|
24
|
+
`shared-infrastructure`.
|
|
25
|
+
- Domain or business logic — that belongs in `libs/<domain>/core`.
|
|
26
|
+
- Imports from any domain library or `shared-infrastructure`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-kernel.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/generators/shared-kernel/shared-kernel.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAM5D,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"shared-kernel.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/generators/shared-kernel/shared-kernel.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAIpB,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAM5D,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,iBAAiB,CAAC,CA+G5B;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -37,22 +37,22 @@ async function sharedKernelGenerator(tree, options) {
|
|
|
37
37
|
// deprecated executor targets instead of inferred tasks (Project Crystal).
|
|
38
38
|
const tasks = [];
|
|
39
39
|
if (!(0, _libraryexist.libraryExists)(tree, contractsRoot)) {
|
|
40
|
+
var _options_prefix;
|
|
40
41
|
(0, _logger.info)(`Creating contracts library at ${contractsRoot}...`);
|
|
41
42
|
tasks.push(await (0, _js.libraryGenerator)(tree, {
|
|
42
43
|
name: options.prefix ? `${options.prefix}/shared-contracts` : 'shared-contracts',
|
|
43
44
|
directory: contractsRoot,
|
|
44
|
-
useProjectJson: false,
|
|
45
45
|
addPlugin: true,
|
|
46
46
|
unitTestRunner: 'none',
|
|
47
47
|
bundler: options.bundler,
|
|
48
48
|
linter: options.linter,
|
|
49
|
-
tags: `${_types.LibraryScope.Shared},${_types.LibraryType.Contracts}
|
|
50
|
-
minimal: true
|
|
49
|
+
tags: `${_types.LibraryScope.Shared},${_types.LibraryType.Contracts}`
|
|
51
50
|
}));
|
|
52
51
|
const type = (0, _resolvemoduleformat.resolveLibraryModuleFormat)(tree, contractsRoot);
|
|
53
52
|
tree.delete(`${contractsRoot}/src/lib/shared-contracts.ts`);
|
|
54
53
|
(0, _devkit.generateFiles)(tree, (0, _path.resolve)(__dirname, 'files/contracts'), contractsRoot, {
|
|
55
|
-
esm: type === _types.ModuleFormat.EsModule
|
|
54
|
+
esm: type === _types.ModuleFormat.EsModule,
|
|
55
|
+
prefix: (_options_prefix = options.prefix) != null ? _options_prefix : ''
|
|
56
56
|
}, {
|
|
57
57
|
overwriteStrategy: _devkit.OverwriteStrategy.Overwrite
|
|
58
58
|
});
|
|
@@ -60,40 +60,48 @@ async function sharedKernelGenerator(tree, options) {
|
|
|
60
60
|
(0, _logger.info)(`Contracts library already exists at ${contractsRoot}`);
|
|
61
61
|
}
|
|
62
62
|
if (!(0, _libraryexist.libraryExists)(tree, utilsRoot)) {
|
|
63
|
+
var _options_prefix1;
|
|
63
64
|
(0, _logger.info)(`Creating utils library at ${utilsRoot}...`);
|
|
64
65
|
tasks.push(await (0, _js.libraryGenerator)(tree, {
|
|
65
66
|
name: options.prefix ? `${options.prefix}/shared-utils` : 'shared-utils',
|
|
66
67
|
directory: utilsRoot,
|
|
67
|
-
useProjectJson: false,
|
|
68
68
|
addPlugin: true,
|
|
69
69
|
unitTestRunner: options.unitTestRunner,
|
|
70
70
|
bundler: options.bundler,
|
|
71
71
|
linter: options.linter,
|
|
72
|
-
tags: `${_types.LibraryScope.Shared},${_types.LibraryType.Utils}
|
|
73
|
-
minimal: true
|
|
72
|
+
tags: `${_types.LibraryScope.Shared},${_types.LibraryType.Utils}`
|
|
74
73
|
}));
|
|
75
74
|
tree.delete(`${utilsRoot}/src/lib/shared-utils.ts`);
|
|
76
75
|
tree.delete(`${utilsRoot}/src/lib/shared-utils.spec.ts`);
|
|
77
76
|
tree.write(`${utilsRoot}/src/index.ts`, '');
|
|
77
|
+
(0, _devkit.generateFiles)(tree, (0, _path.resolve)(__dirname, 'files/utils'), utilsRoot, {
|
|
78
|
+
prefix: (_options_prefix1 = options.prefix) != null ? _options_prefix1 : ''
|
|
79
|
+
}, {
|
|
80
|
+
overwriteStrategy: _devkit.OverwriteStrategy.Overwrite
|
|
81
|
+
});
|
|
78
82
|
} else {
|
|
79
83
|
(0, _logger.info)(`Utils library already exists at ${utilsRoot}`);
|
|
80
84
|
}
|
|
81
85
|
if (!(0, _libraryexist.libraryExists)(tree, infrastructureRoot)) {
|
|
86
|
+
var _options_prefix2;
|
|
82
87
|
(0, _logger.info)(`Creating infrastructure library at ${infrastructureRoot}...`);
|
|
83
88
|
tasks.push(await (0, _js.libraryGenerator)(tree, {
|
|
84
89
|
name: options.prefix ? `${options.prefix}/shared-infrastructure` : 'shared-infrastructure',
|
|
85
90
|
directory: infrastructureRoot,
|
|
86
|
-
useProjectJson: false,
|
|
87
91
|
addPlugin: true,
|
|
88
92
|
unitTestRunner: options.unitTestRunner,
|
|
89
93
|
bundler: options.bundler,
|
|
90
94
|
linter: options.linter,
|
|
91
|
-
tags: `${_types.LibraryScope.Shared},${_types.LibraryType.Infrastructure}
|
|
92
|
-
minimal: true
|
|
95
|
+
tags: `${_types.LibraryScope.Shared},${_types.LibraryType.Infrastructure}`
|
|
93
96
|
}));
|
|
94
97
|
tree.delete(`${infrastructureRoot}/src/lib/shared-infrastructure.ts`);
|
|
95
98
|
tree.delete(`${infrastructureRoot}/src/lib/shared-infrastructure.spec.ts`);
|
|
96
99
|
tree.write(`${infrastructureRoot}/src/index.ts`, '');
|
|
100
|
+
(0, _devkit.generateFiles)(tree, (0, _path.resolve)(__dirname, 'files/infrastructure'), infrastructureRoot, {
|
|
101
|
+
prefix: (_options_prefix2 = options.prefix) != null ? _options_prefix2 : ''
|
|
102
|
+
}, {
|
|
103
|
+
overwriteStrategy: _devkit.OverwriteStrategy.Overwrite
|
|
104
|
+
});
|
|
97
105
|
} else {
|
|
98
106
|
(0, _logger.info)(`Infrastructure library already exists at ${infrastructureRoot}`);
|
|
99
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx/src/generators/shared-kernel/shared-kernel.ts"],"sourcesContent":["import {\n formatFiles,\n generateFiles,\n OverwriteStrategy,\n runTasksInSerial,\n type GeneratorCallback,\n type Tree,\n} from '@nx/devkit';\nimport { libraryGenerator } from '@nx/js';\nimport { resolve } from 'path';\n\nimport type { SharedKernelGeneratorSchema } from './schema';\nimport { LibraryScope, LibraryType, ModuleFormat } from '../../types';\nimport { resolveLibraryModuleFormat } from '../../utils/resolve-module-format';\nimport { libraryExists } from '../../utils/library-exist';\nimport { info } from '../../utils/logger';\n\nexport async function sharedKernelGenerator(\n tree: Tree,\n options: SharedKernelGeneratorSchema,\n): Promise<GeneratorCallback> {\n const sharedDirectory = options.directory;\n const contractsRoot = `${sharedDirectory}/contracts`;\n const utilsRoot = `${sharedDirectory}/utils`;\n const infrastructureRoot = `${sharedDirectory}/infrastructure`;\n\n // Install callbacks returned by the delegated `@nx/js:library` generator.\n // They must be returned to Nx so the packages backing the inferred plugins\n // registered via `addPlugin` — `@nx/eslint`, `@nx/jest` — actually get\n // installed; otherwise nx.json references plugins Nx cannot load on the next\n // command. Every library also passes `addPlugin: true`: the `@nx/js` public\n // wrapper defaults it to `false`, which makes the delegated generators emit\n // deprecated executor targets instead of inferred tasks (Project Crystal).\n const tasks: GeneratorCallback[] = [];\n\n if (!libraryExists(tree, contractsRoot)) {\n info(`Creating contracts library at ${contractsRoot}...`);\n\n tasks.push(\n await libraryGenerator(tree, {\n name: options.prefix\n ? `${options.prefix}/shared-contracts`\n : 'shared-contracts',\n directory: contractsRoot,\n
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx/src/generators/shared-kernel/shared-kernel.ts"],"sourcesContent":["import {\n formatFiles,\n generateFiles,\n OverwriteStrategy,\n runTasksInSerial,\n type GeneratorCallback,\n type Tree,\n} from '@nx/devkit';\nimport { libraryGenerator } from '@nx/js';\nimport { resolve } from 'path';\n\nimport type { SharedKernelGeneratorSchema } from './schema';\nimport { LibraryScope, LibraryType, ModuleFormat } from '../../types';\nimport { resolveLibraryModuleFormat } from '../../utils/resolve-module-format';\nimport { libraryExists } from '../../utils/library-exist';\nimport { info } from '../../utils/logger';\n\nexport async function sharedKernelGenerator(\n tree: Tree,\n options: SharedKernelGeneratorSchema,\n): Promise<GeneratorCallback> {\n const sharedDirectory = options.directory;\n const contractsRoot = `${sharedDirectory}/contracts`;\n const utilsRoot = `${sharedDirectory}/utils`;\n const infrastructureRoot = `${sharedDirectory}/infrastructure`;\n\n // Install callbacks returned by the delegated `@nx/js:library` generator.\n // They must be returned to Nx so the packages backing the inferred plugins\n // registered via `addPlugin` — `@nx/eslint`, `@nx/jest` — actually get\n // installed; otherwise nx.json references plugins Nx cannot load on the next\n // command. Every library also passes `addPlugin: true`: the `@nx/js` public\n // wrapper defaults it to `false`, which makes the delegated generators emit\n // deprecated executor targets instead of inferred tasks (Project Crystal).\n const tasks: GeneratorCallback[] = [];\n\n if (!libraryExists(tree, contractsRoot)) {\n info(`Creating contracts library at ${contractsRoot}...`);\n\n tasks.push(\n await libraryGenerator(tree, {\n name: options.prefix\n ? `${options.prefix}/shared-contracts`\n : 'shared-contracts',\n directory: contractsRoot,\n addPlugin: true,\n unitTestRunner: 'none',\n bundler: options.bundler,\n linter: options.linter,\n tags: `${LibraryScope.Shared},${LibraryType.Contracts}`,\n }),\n );\n\n const type = resolveLibraryModuleFormat(tree, contractsRoot);\n\n tree.delete(`${contractsRoot}/src/lib/shared-contracts.ts`);\n generateFiles(\n tree,\n resolve(__dirname, 'files/contracts'),\n contractsRoot,\n { esm: type === ModuleFormat.EsModule, prefix: options.prefix ?? '' },\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n } else {\n info(`Contracts library already exists at ${contractsRoot}`);\n }\n\n if (!libraryExists(tree, utilsRoot)) {\n info(`Creating utils library at ${utilsRoot}...`);\n\n tasks.push(\n await libraryGenerator(tree, {\n name: options.prefix\n ? `${options.prefix}/shared-utils`\n : 'shared-utils',\n directory: utilsRoot,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n tags: `${LibraryScope.Shared},${LibraryType.Utils}`,\n }),\n );\n\n tree.delete(`${utilsRoot}/src/lib/shared-utils.ts`);\n tree.delete(`${utilsRoot}/src/lib/shared-utils.spec.ts`);\n tree.write(`${utilsRoot}/src/index.ts`, '');\n generateFiles(\n tree,\n resolve(__dirname, 'files/utils'),\n utilsRoot,\n { prefix: options.prefix ?? '' },\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n } else {\n info(`Utils library already exists at ${utilsRoot}`);\n }\n\n if (!libraryExists(tree, infrastructureRoot)) {\n info(`Creating infrastructure library at ${infrastructureRoot}...`);\n\n tasks.push(\n await libraryGenerator(tree, {\n name: options.prefix\n ? `${options.prefix}/shared-infrastructure`\n : 'shared-infrastructure',\n directory: infrastructureRoot,\n addPlugin: true,\n unitTestRunner: options.unitTestRunner,\n bundler: options.bundler,\n linter: options.linter,\n tags: `${LibraryScope.Shared},${LibraryType.Infrastructure}`,\n }),\n );\n\n tree.delete(`${infrastructureRoot}/src/lib/shared-infrastructure.ts`);\n tree.delete(`${infrastructureRoot}/src/lib/shared-infrastructure.spec.ts`);\n tree.write(`${infrastructureRoot}/src/index.ts`, '');\n generateFiles(\n tree,\n resolve(__dirname, 'files/infrastructure'),\n infrastructureRoot,\n { prefix: options.prefix ?? '' },\n { overwriteStrategy: OverwriteStrategy.Overwrite },\n );\n } else {\n info(`Infrastructure library already exists at ${infrastructureRoot}`);\n }\n\n await formatFiles(tree);\n\n return runTasksInSerial(...tasks);\n}\n\nexport default sharedKernelGenerator;\n"],"names":["sharedKernelGenerator","tree","options","sharedDirectory","directory","contractsRoot","utilsRoot","infrastructureRoot","tasks","libraryExists","info","push","libraryGenerator","name","prefix","addPlugin","unitTestRunner","bundler","linter","tags","LibraryScope","Shared","LibraryType","Contracts","type","resolveLibraryModuleFormat","delete","generateFiles","resolve","__dirname","esm","ModuleFormat","EsModule","overwriteStrategy","OverwriteStrategy","Overwrite","Utils","write","Infrastructure","formatFiles","runTasksInSerial"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-module-boundaries.d.ts","sourceRoot":"","sources":["../../../../packages/nx/src/utils/eslint-module-boundaries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"eslint-module-boundaries.d.ts","sourceRoot":"","sources":["../../../../packages/nx/src/utils/eslint-module-boundaries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAwCvC,qFAAqF;AACrF,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AAEtE,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,wBAAwB,EAAE,MAAM,EAAE,CAAC;CACpC;AAoCD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,aAAa,EAAE,GAC3B,OAAO,CA+DT;AA2DD;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CA0BT"}
|
|
@@ -20,8 +20,22 @@ _export(exports, {
|
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
const _extends = require("@swc/helpers/_/_extends");
|
|
23
|
-
const _internal = require("@nx/eslint/internal");
|
|
24
23
|
const _logger = require("./logger");
|
|
24
|
+
/**
|
|
25
|
+
* Loads `@nx/eslint`'s ESLint-config AST utilities across Nx major versions.
|
|
26
|
+
*
|
|
27
|
+
* Nx >= 23 exposes them through the curated `@nx/eslint/internal` subpath. Nx 22
|
|
28
|
+
* has no such subpath (requiring it throws "Cannot find module
|
|
29
|
+
* '@nx/eslint/internal'"), but ships no `package.json` `exports` map either, so
|
|
30
|
+
* the utilities can be required directly from their module path instead.
|
|
31
|
+
*/ function loadEslintConfigUtils() {
|
|
32
|
+
try {
|
|
33
|
+
return require('@nx/eslint/internal');
|
|
34
|
+
} catch (unused) {
|
|
35
|
+
return require('@nx/eslint/src/generators/utils/eslint-file');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const { addOverrideToLintConfig, isEslintConfigSupported, lintConfigHasOverride, updateOverrideInLintConfig } = loadEslintConfigUtils();
|
|
25
39
|
const MODULE_BOUNDARIES_RULE = '@nx/enforce-module-boundaries';
|
|
26
40
|
/**
|
|
27
41
|
* Baseline options every `@nx/enforce-module-boundaries` rule we write carries.
|
|
@@ -52,16 +66,16 @@ const MODULE_BOUNDARIES_RULE = '@nx/enforce-module-boundaries';
|
|
|
52
66
|
];
|
|
53
67
|
}
|
|
54
68
|
function applyDepConstraints(tree, constraints) {
|
|
55
|
-
if (!
|
|
69
|
+
if (!isEslintConfigSupported(tree)) {
|
|
56
70
|
(0, _logger.warning)('No supported ESLint config found at the workspace root — skipping module boundary rules.');
|
|
57
71
|
return false;
|
|
58
72
|
}
|
|
59
|
-
const hasRule =
|
|
73
|
+
const hasRule = lintConfigHasOverride(tree, '', (override)=>{
|
|
60
74
|
var _override_rules;
|
|
61
75
|
return Boolean((_override_rules = override.rules) == null ? void 0 : _override_rules[MODULE_BOUNDARIES_RULE]);
|
|
62
76
|
});
|
|
63
77
|
if (!hasRule) {
|
|
64
|
-
|
|
78
|
+
addOverrideToLintConfig(tree, '', {
|
|
65
79
|
files: [
|
|
66
80
|
'**/*.ts',
|
|
67
81
|
'**/*.js'
|
|
@@ -77,7 +91,7 @@ function applyDepConstraints(tree, constraints) {
|
|
|
77
91
|
});
|
|
78
92
|
return true;
|
|
79
93
|
}
|
|
80
|
-
|
|
94
|
+
updateOverrideInLintConfig(tree, '', (override)=>{
|
|
81
95
|
var _override_rules;
|
|
82
96
|
return Boolean((_override_rules = override.rules) == null ? void 0 : _override_rules[MODULE_BOUNDARIES_RULE]);
|
|
83
97
|
}, (override)=>{
|
|
@@ -157,10 +171,10 @@ function applicationLayerPatterns(prefix) {
|
|
|
157
171
|
return patterns;
|
|
158
172
|
}
|
|
159
173
|
function applyCleanArchitectureBoundaries(tree, libraryRoot, prefix) {
|
|
160
|
-
if (!
|
|
174
|
+
if (!isEslintConfigSupported(tree, libraryRoot)) {
|
|
161
175
|
return false;
|
|
162
176
|
}
|
|
163
|
-
|
|
177
|
+
addOverrideToLintConfig(tree, libraryRoot, {
|
|
164
178
|
files: [
|
|
165
179
|
'src/lib/domain/**/*.ts'
|
|
166
180
|
],
|
|
@@ -173,7 +187,7 @@ function applyCleanArchitectureBoundaries(tree, libraryRoot, prefix) {
|
|
|
173
187
|
]
|
|
174
188
|
}
|
|
175
189
|
});
|
|
176
|
-
|
|
190
|
+
addOverrideToLintConfig(tree, libraryRoot, {
|
|
177
191
|
files: [
|
|
178
192
|
'src/lib/application/**/*.ts'
|
|
179
193
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../packages/nx/src/utils/eslint-module-boundaries.ts"],"sourcesContent":["import { type Tree } from '@nx/devkit';\nimport {\n addOverrideToLintConfig,\n isEslintConfigSupported,\n lintConfigHasOverride,\n updateOverrideInLintConfig,\n} from '@nx/eslint/internal';\n\nimport type { Linter } from 'eslint';\n\nimport { warning } from './logger';\n\n/** The module-boundaries rule whose `depConstraints` encode the dependency graph. */\nexport const MODULE_BOUNDARIES_RULE = '@nx/enforce-module-boundaries';\n\n/** A single `@nx/enforce-module-boundaries` dependency constraint. */\nexport interface DepConstraint {\n sourceTag: string;\n onlyDependOnLibsWithTags: string[];\n}\n\n/** A single `no-restricted-imports` pattern group with its violation message. */\ninterface RestrictedImportPattern {\n group: string[];\n message: string;\n}\n\n/**\n * Baseline options every `@nx/enforce-module-boundaries` rule we write carries.\n * The `allow` glob keeps libraries free to import the workspace's flat ESLint\n * config files (which live outside any project's source) without tripping the\n * boundary check.\n */\nconst DEFAULT_RULE_OPTIONS = {\n enforceBuildableLibDependency: true,\n allow: ['^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?[jt]s$'],\n};\n\n/**\n * Merges `incoming` constraints into `existing`, keyed by `sourceTag`: an\n * incoming constraint replaces any existing one with the same `sourceTag`,\n * otherwise it is appended. Order of first appearance is preserved so the\n * config stays stable across re-runs (idempotent).\n */\nfunction mergeConstraints(\n existing: DepConstraint[],\n incoming: DepConstraint[],\n): DepConstraint[] {\n const bySource = new Map<string, DepConstraint>();\n for (const constraint of [...existing, ...incoming]) {\n bySource.set(constraint.sourceTag, constraint);\n }\n return [...bySource.values()];\n}\n\n/**\n * Ensures the root `@nx/enforce-module-boundaries` rule exists and that every\n * constraint in `constraints` is present in its `depConstraints` (merged by\n * `sourceTag`). Existing rule options are preserved; the baseline options are\n * filled in for any that are missing.\n *\n * Returns `false` (and warns) when there is no ESLint config to update — e.g.\n * the workspace was set up with `linter: none`.\n */\nexport function applyDepConstraints(\n tree: Tree,\n constraints: DepConstraint[],\n): boolean {\n if (!isEslintConfigSupported(tree)) {\n warning(\n 'No supported ESLint config found at the workspace root — skipping module boundary rules.',\n );\n return false;\n }\n\n const hasRule = lintConfigHasOverride(tree, '', (override) =>\n Boolean(override.rules?.[MODULE_BOUNDARIES_RULE]),\n );\n\n if (!hasRule) {\n addOverrideToLintConfig(tree, '', {\n files: ['**/*.ts', '**/*.js'],\n rules: {\n [MODULE_BOUNDARIES_RULE]: [\n 'error',\n { ...DEFAULT_RULE_OPTIONS, depConstraints: constraints },\n ],\n },\n });\n return true;\n }\n\n updateOverrideInLintConfig(\n tree,\n '',\n (override) => Boolean(override.rules?.[MODULE_BOUNDARIES_RULE]),\n (override) => {\n const rules = override.rules ?? {};\n const rule = rules[MODULE_BOUNDARIES_RULE];\n\n // The rule may be a bare severity string (`'error'`) or the usual\n // `[severity, options]` tuple. Falling back to `{}` for the non-tuple\n // form would silently drop `enforceBuildableLibDependency`/`allow`, so we\n // start from the baseline options and layer any existing ones on top.\n const severity: Linter.RuleSeverity = Array.isArray(rule)\n ? (rule[0] as Linter.RuleSeverity)\n : ((rule as Linter.RuleSeverity) ?? 'error');\n const existingOptions = (\n Array.isArray(rule) ? (rule[1] ?? {}) : {}\n ) as Record<string, unknown>;\n const existingConstraints = Array.isArray(existingOptions.depConstraints)\n ? (existingOptions.depConstraints as DepConstraint[])\n : [];\n\n const updatedRule: Linter.RuleEntry = [\n severity,\n {\n ...DEFAULT_RULE_OPTIONS,\n ...existingOptions,\n depConstraints: mergeConstraints(existingConstraints, constraints),\n },\n ];\n\n return {\n ...override,\n rules: { ...rules, [MODULE_BOUNDARIES_RULE]: updatedRule },\n };\n },\n );\n return true;\n}\n\n/**\n * The `no-restricted-imports` patterns enforcing Clean Architecture layering\n * *inside* a domain's `core` library: `domain` may not reach into `application`\n * or `infrastructure`, and `application` may not reach into `infrastructure`.\n *\n * Each layer gets a relative-path rule (sibling folders under `src/lib`) and,\n * when an organization `prefix` is known, an absolute-path rule that closes the\n * loophole of bypassing the relative rule through a workspace alias.\n */\nfunction domainLayerPatterns(prefix?: string): RestrictedImportPattern[] {\n const patterns: RestrictedImportPattern[] = [\n {\n group: [\n '../application/*',\n '../application',\n '../infrastructure/*',\n '../infrastructure',\n ],\n message:\n 'Clean Architecture violation: Domain layer must be independent and cannot import from Application or Infrastructure layers.',\n },\n ];\n\n if (prefix) {\n patterns.push({\n group: [\n `${prefix}/*/core/infrastructure/*`,\n `${prefix}/*/core/application/*`,\n ],\n message:\n 'Clean Architecture violation: Domain layer cannot import upper layers via absolute paths.',\n });\n }\n\n return patterns;\n}\n\nfunction applicationLayerPatterns(prefix?: string): RestrictedImportPattern[] {\n const patterns: RestrictedImportPattern[] = [\n {\n group: ['../infrastructure/*', '../infrastructure'],\n message:\n 'Clean Architecture violation: Application layer cannot import from Infrastructure layer.',\n },\n ];\n\n if (prefix) {\n patterns.push({\n group: [`${prefix}/*/core/infrastructure/*`],\n message:\n 'Clean Architecture violation: Application layer cannot import Infrastructure via absolute paths.',\n });\n }\n\n return patterns;\n}\n\n/**\n * Adds Clean Architecture import boundaries to a `core` library's own ESLint\n * config (`<libraryRoot>/eslint.config.*`) via `no-restricted-imports` overrides\n * scoped to the `domain` and `application` layer folders. `@nx/enforce-module-\n * boundaries` guards dependencies *between* projects; these rules guard the\n * layering *within* the core library.\n *\n * No-op (returning `false`) when the library has no ESLint config — e.g. it was\n * generated with `linter: none`.\n */\nexport function applyCleanArchitectureBoundaries(\n tree: Tree,\n libraryRoot: string,\n prefix?: string,\n): boolean {\n if (!isEslintConfigSupported(tree, libraryRoot)) {\n return false;\n }\n\n addOverrideToLintConfig(tree, libraryRoot, {\n files: ['src/lib/domain/**/*.ts'],\n rules: {\n 'no-restricted-imports': [\n 'error',\n { patterns: domainLayerPatterns(prefix) },\n ],\n },\n });\n\n addOverrideToLintConfig(tree, libraryRoot, {\n files: ['src/lib/application/**/*.ts'],\n rules: {\n 'no-restricted-imports': [\n 'error',\n { patterns: applicationLayerPatterns(prefix) },\n ],\n },\n });\n\n return true;\n}\n"],"names":["MODULE_BOUNDARIES_RULE","applyCleanArchitectureBoundaries","applyDepConstraints","DEFAULT_RULE_OPTIONS","enforceBuildableLibDependency","allow","mergeConstraints","existing","incoming","bySource","Map","constraint","set","sourceTag","values","tree","constraints","isEslintConfigSupported","warning","hasRule","lintConfigHasOverride","override","Boolean","rules","addOverrideToLintConfig","files","depConstraints","updateOverrideInLintConfig","rule","severity","Array","isArray","existingOptions","existingConstraints","updatedRule","domainLayerPatterns","prefix","patterns","group","message","push","applicationLayerPatterns","libraryRoot"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../packages/nx/src/utils/eslint-module-boundaries.ts"],"sourcesContent":["import { type Tree } from '@nx/devkit';\n\nimport type { Linter } from 'eslint';\n\nimport { warning } from './logger';\n\n/**\n * The slice of `@nx/eslint`'s flat-config AST utilities this module relies on.\n */\ntype EslintConfigUtils = Pick<\n typeof import('@nx/eslint/internal'),\n | 'addOverrideToLintConfig'\n | 'isEslintConfigSupported'\n | 'lintConfigHasOverride'\n | 'updateOverrideInLintConfig'\n>;\n\n/**\n * Loads `@nx/eslint`'s ESLint-config AST utilities across Nx major versions.\n *\n * Nx >= 23 exposes them through the curated `@nx/eslint/internal` subpath. Nx 22\n * has no such subpath (requiring it throws \"Cannot find module\n * '@nx/eslint/internal'\"), but ships no `package.json` `exports` map either, so\n * the utilities can be required directly from their module path instead.\n */\nfunction loadEslintConfigUtils(): EslintConfigUtils {\n try {\n return require('@nx/eslint/internal');\n } catch {\n return require('@nx/eslint/src/generators/utils/eslint-file');\n }\n}\n\nconst {\n addOverrideToLintConfig,\n isEslintConfigSupported,\n lintConfigHasOverride,\n updateOverrideInLintConfig,\n} = loadEslintConfigUtils();\n\n/** The module-boundaries rule whose `depConstraints` encode the dependency graph. */\nexport const MODULE_BOUNDARIES_RULE = '@nx/enforce-module-boundaries';\n\n/** A single `@nx/enforce-module-boundaries` dependency constraint. */\nexport interface DepConstraint {\n sourceTag: string;\n onlyDependOnLibsWithTags: string[];\n}\n\n/** A single `no-restricted-imports` pattern group with its violation message. */\ninterface RestrictedImportPattern {\n group: string[];\n message: string;\n}\n\n/**\n * Baseline options every `@nx/enforce-module-boundaries` rule we write carries.\n * The `allow` glob keeps libraries free to import the workspace's flat ESLint\n * config files (which live outside any project's source) without tripping the\n * boundary check.\n */\nconst DEFAULT_RULE_OPTIONS = {\n enforceBuildableLibDependency: true,\n allow: ['^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?[jt]s$'],\n};\n\n/**\n * Merges `incoming` constraints into `existing`, keyed by `sourceTag`: an\n * incoming constraint replaces any existing one with the same `sourceTag`,\n * otherwise it is appended. Order of first appearance is preserved so the\n * config stays stable across re-runs (idempotent).\n */\nfunction mergeConstraints(\n existing: DepConstraint[],\n incoming: DepConstraint[],\n): DepConstraint[] {\n const bySource = new Map<string, DepConstraint>();\n for (const constraint of [...existing, ...incoming]) {\n bySource.set(constraint.sourceTag, constraint);\n }\n return [...bySource.values()];\n}\n\n/**\n * Ensures the root `@nx/enforce-module-boundaries` rule exists and that every\n * constraint in `constraints` is present in its `depConstraints` (merged by\n * `sourceTag`). Existing rule options are preserved; the baseline options are\n * filled in for any that are missing.\n *\n * Returns `false` (and warns) when there is no ESLint config to update — e.g.\n * the workspace was set up with `linter: none`.\n */\nexport function applyDepConstraints(\n tree: Tree,\n constraints: DepConstraint[],\n): boolean {\n if (!isEslintConfigSupported(tree)) {\n warning(\n 'No supported ESLint config found at the workspace root — skipping module boundary rules.',\n );\n return false;\n }\n\n const hasRule = lintConfigHasOverride(tree, '', (override) =>\n Boolean(override.rules?.[MODULE_BOUNDARIES_RULE]),\n );\n\n if (!hasRule) {\n addOverrideToLintConfig(tree, '', {\n files: ['**/*.ts', '**/*.js'],\n rules: {\n [MODULE_BOUNDARIES_RULE]: [\n 'error',\n { ...DEFAULT_RULE_OPTIONS, depConstraints: constraints },\n ],\n },\n });\n return true;\n }\n\n updateOverrideInLintConfig(\n tree,\n '',\n (override) => Boolean(override.rules?.[MODULE_BOUNDARIES_RULE]),\n (override) => {\n const rules = override.rules ?? {};\n const rule = rules[MODULE_BOUNDARIES_RULE];\n\n // The rule may be a bare severity string (`'error'`) or the usual\n // `[severity, options]` tuple. Falling back to `{}` for the non-tuple\n // form would silently drop `enforceBuildableLibDependency`/`allow`, so we\n // start from the baseline options and layer any existing ones on top.\n const severity: Linter.RuleSeverity = Array.isArray(rule)\n ? (rule[0] as Linter.RuleSeverity)\n : ((rule as Linter.RuleSeverity) ?? 'error');\n const existingOptions = (\n Array.isArray(rule) ? (rule[1] ?? {}) : {}\n ) as Record<string, unknown>;\n const existingConstraints = Array.isArray(existingOptions.depConstraints)\n ? (existingOptions.depConstraints as DepConstraint[])\n : [];\n\n const updatedRule: Linter.RuleEntry = [\n severity,\n {\n ...DEFAULT_RULE_OPTIONS,\n ...existingOptions,\n depConstraints: mergeConstraints(existingConstraints, constraints),\n },\n ];\n\n return {\n ...override,\n rules: { ...rules, [MODULE_BOUNDARIES_RULE]: updatedRule },\n };\n },\n );\n return true;\n}\n\n/**\n * The `no-restricted-imports` patterns enforcing Clean Architecture layering\n * *inside* a domain's `core` library: `domain` may not reach into `application`\n * or `infrastructure`, and `application` may not reach into `infrastructure`.\n *\n * Each layer gets a relative-path rule (sibling folders under `src/lib`) and,\n * when an organization `prefix` is known, an absolute-path rule that closes the\n * loophole of bypassing the relative rule through a workspace alias.\n */\nfunction domainLayerPatterns(prefix?: string): RestrictedImportPattern[] {\n const patterns: RestrictedImportPattern[] = [\n {\n group: [\n '../application/*',\n '../application',\n '../infrastructure/*',\n '../infrastructure',\n ],\n message:\n 'Clean Architecture violation: Domain layer must be independent and cannot import from Application or Infrastructure layers.',\n },\n ];\n\n if (prefix) {\n patterns.push({\n group: [\n `${prefix}/*/core/infrastructure/*`,\n `${prefix}/*/core/application/*`,\n ],\n message:\n 'Clean Architecture violation: Domain layer cannot import upper layers via absolute paths.',\n });\n }\n\n return patterns;\n}\n\nfunction applicationLayerPatterns(prefix?: string): RestrictedImportPattern[] {\n const patterns: RestrictedImportPattern[] = [\n {\n group: ['../infrastructure/*', '../infrastructure'],\n message:\n 'Clean Architecture violation: Application layer cannot import from Infrastructure layer.',\n },\n ];\n\n if (prefix) {\n patterns.push({\n group: [`${prefix}/*/core/infrastructure/*`],\n message:\n 'Clean Architecture violation: Application layer cannot import Infrastructure via absolute paths.',\n });\n }\n\n return patterns;\n}\n\n/**\n * Adds Clean Architecture import boundaries to a `core` library's own ESLint\n * config (`<libraryRoot>/eslint.config.*`) via `no-restricted-imports` overrides\n * scoped to the `domain` and `application` layer folders. `@nx/enforce-module-\n * boundaries` guards dependencies *between* projects; these rules guard the\n * layering *within* the core library.\n *\n * No-op (returning `false`) when the library has no ESLint config — e.g. it was\n * generated with `linter: none`.\n */\nexport function applyCleanArchitectureBoundaries(\n tree: Tree,\n libraryRoot: string,\n prefix?: string,\n): boolean {\n if (!isEslintConfigSupported(tree, libraryRoot)) {\n return false;\n }\n\n addOverrideToLintConfig(tree, libraryRoot, {\n files: ['src/lib/domain/**/*.ts'],\n rules: {\n 'no-restricted-imports': [\n 'error',\n { patterns: domainLayerPatterns(prefix) },\n ],\n },\n });\n\n addOverrideToLintConfig(tree, libraryRoot, {\n files: ['src/lib/application/**/*.ts'],\n rules: {\n 'no-restricted-imports': [\n 'error',\n { patterns: applicationLayerPatterns(prefix) },\n ],\n },\n });\n\n return true;\n}\n"],"names":["MODULE_BOUNDARIES_RULE","applyCleanArchitectureBoundaries","applyDepConstraints","loadEslintConfigUtils","require","addOverrideToLintConfig","isEslintConfigSupported","lintConfigHasOverride","updateOverrideInLintConfig","DEFAULT_RULE_OPTIONS","enforceBuildableLibDependency","allow","mergeConstraints","existing","incoming","bySource","Map","constraint","set","sourceTag","values","tree","constraints","warning","hasRule","override","Boolean","rules","files","depConstraints","rule","severity","Array","isArray","existingOptions","existingConstraints","updatedRule","domainLayerPatterns","prefix","patterns","group","message","push","applicationLayerPatterns","libraryRoot"],"mappings":"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"}
|
package/utils/library-exist.d.ts
CHANGED
|
@@ -2,11 +2,18 @@ import { Tree } from '@nx/devkit';
|
|
|
2
2
|
/**
|
|
3
3
|
* Whether a kernel library has actually been generated at `root`.
|
|
4
4
|
*
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
* We key off the library's project manifest rather than the directory:
|
|
6
8
|
* `tree.exists(root)` is `true` for *any* existing directory — including an
|
|
7
9
|
* empty leftover from an aborted run — which would make the generator wrongly
|
|
8
|
-
* skip a layer that has no files in it.
|
|
9
|
-
*
|
|
10
|
+
* skip a layer that has no files in it.
|
|
11
|
+
*
|
|
12
|
+
* `@nx/js:library` writes its configuration to whichever manifest suits the
|
|
13
|
+
* workspace: `project.json` in an integrated (tsconfig-paths) workspace, or the
|
|
14
|
+
* `package.json` `nx` block in a package-manager-workspaces (TS solution) one —
|
|
15
|
+
* and in the latter the bundler-less case may leave only `project.json`. Either
|
|
16
|
+
* manifest existing is a reliable marker that the library was scaffolded.
|
|
10
17
|
*/
|
|
11
18
|
export declare function libraryExists(tree: Tree, root: string): boolean;
|
|
12
19
|
//# sourceMappingURL=library-exist.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"library-exist.d.ts","sourceRoot":"","sources":["../../../../packages/nx/src/utils/library-exist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC
|
|
1
|
+
{"version":3,"file":"library-exist.d.ts","sourceRoot":"","sources":["../../../../packages/nx/src/utils/library-exist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAI/D"}
|
package/utils/library-exist.js
CHANGED
|
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "libraryExists", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
function libraryExists(tree, root) {
|
|
12
|
-
return tree.exists(`${root}/package.json`);
|
|
12
|
+
return tree.exists(`${root}/package.json`) || tree.exists(`${root}/project.json`);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
//# sourceMappingURL=library-exist.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../packages/nx/src/utils/library-exist.ts"],"sourcesContent":["import { Tree } from '@nx/devkit';\n\n/**\n * Whether a kernel library has actually been generated at `root`.\n *\n * We key off the library manifest
|
|
1
|
+
{"version":3,"sources":["../../../../packages/nx/src/utils/library-exist.ts"],"sourcesContent":["import { Tree } from '@nx/devkit';\n\n/**\n * Whether a kernel library has actually been generated at `root`.\n *\n\n\n * We key off the library's project manifest rather than the directory:\n * `tree.exists(root)` is `true` for *any* existing directory — including an\n * empty leftover from an aborted run — which would make the generator wrongly\n * skip a layer that has no files in it.\n *\n * `@nx/js:library` writes its configuration to whichever manifest suits the\n * workspace: `project.json` in an integrated (tsconfig-paths) workspace, or the\n * `package.json` `nx` block in a package-manager-workspaces (TS solution) one —\n * and in the latter the bundler-less case may leave only `project.json`. Either\n * manifest existing is a reliable marker that the library was scaffolded.\n */\nexport function libraryExists(tree: Tree, root: string): boolean {\n return (\n tree.exists(`${root}/package.json`) || tree.exists(`${root}/project.json`)\n );\n}\n"],"names":["libraryExists","tree","root","exists"],"mappings":";;;;+BAkBgBA;;;eAAAA;;;AAAT,SAASA,cAAcC,IAAU,EAAEC,IAAY;IACpD,OACED,KAAKE,MAAM,CAAC,GAAGD,KAAK,aAAa,CAAC,KAAKD,KAAKE,MAAM,CAAC,GAAGD,KAAK,aAAa,CAAC;AAE7E"}
|