@tactical-ddd/nx 0.0.2-alpha.0 → 0.0.2-alpha.1

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.
Files changed (54) hide show
  1. package/README.md +137 -1
  2. package/generators/domain/domain.d.ts +5 -0
  3. package/generators/domain/domain.d.ts.map +1 -0
  4. package/generators/domain/domain.js +211 -0
  5. package/generators/domain/domain.js.map +1 -0
  6. package/generators/domain/files/contracts/src/index.ts +1 -0
  7. package/generators/domain/files/contracts/src/lib/interfaces/__name__-facade.interface.ts +7 -0
  8. package/generators/domain/files/core/src/index.ts +1 -0
  9. package/generators/domain/files/core/src/lib/application/__name__.facade.ts +7 -0
  10. package/generators/domain/files/core/src/lib/domain/.gitkeep +0 -0
  11. package/generators/domain/files/core/src/lib/infrastructure/.gitkeep +0 -0
  12. package/generators/domain/schema.d.js +6 -0
  13. package/generators/domain/schema.d.js.map +1 -0
  14. package/generators/domain/schema.d.ts +12 -0
  15. package/generators/domain/schema.json +73 -0
  16. package/generators/init/init.d.ts +5 -0
  17. package/generators/init/init.d.ts.map +1 -0
  18. package/generators/init/init.js +193 -0
  19. package/generators/init/init.js.map +1 -0
  20. package/generators/init/module-boundaries.d.ts +14 -0
  21. package/generators/init/module-boundaries.d.ts.map +1 -0
  22. package/generators/init/module-boundaries.js +140 -0
  23. package/generators/init/module-boundaries.js.map +1 -0
  24. package/generators/init/schema.d.js +6 -0
  25. package/generators/init/schema.d.js.map +1 -0
  26. package/generators/init/schema.d.ts +10 -0
  27. package/generators/init/schema.json +55 -0
  28. package/generators/shared-kernel/schema.json +1 -1
  29. package/generators/shared-kernel/shared-kernel.d.ts +2 -2
  30. package/generators/shared-kernel/shared-kernel.d.ts.map +1 -1
  31. package/generators/shared-kernel/shared-kernel.js +29 -15
  32. package/generators/shared-kernel/shared-kernel.js.map +1 -1
  33. package/generators.json +10 -0
  34. package/index.d.ts +5 -0
  35. package/index.d.ts.map +1 -1
  36. package/index.js +5 -0
  37. package/index.js.map +1 -1
  38. package/package.json +19 -1
  39. package/types.d.ts +3 -1
  40. package/types.d.ts.map +1 -1
  41. package/types.js +2 -0
  42. package/types.js.map +1 -1
  43. package/utils/eslint-module-boundaries.d.ts +30 -0
  44. package/utils/eslint-module-boundaries.d.ts.map +1 -0
  45. package/utils/eslint-module-boundaries.js +192 -0
  46. package/utils/eslint-module-boundaries.js.map +1 -0
  47. package/utils/library-exist.d.ts +12 -0
  48. package/utils/library-exist.d.ts.map +1 -0
  49. package/utils/library-exist.js +15 -0
  50. package/utils/library-exist.js.map +1 -0
  51. package/utils/logger.d.ts +13 -0
  52. package/utils/logger.d.ts.map +1 -0
  53. package/utils/logger.js +48 -0
  54. package/utils/logger.js.map +1 -0
package/README.md CHANGED
@@ -4,9 +4,80 @@
4
4
 
5
5
  The suite is being built out incrementally. Generators currently available:
6
6
 
7
+ - [`init`](#init-generator) — the recommended starting point: bootstraps the whole workspace (generator defaults, module-boundary lint rules, the Shared Kernel, and an optional framework preset such as React) in one step.
7
8
  - [`shared-kernel`](#shared-kernel-generator) — scaffolds the Shared Kernel, the agnostic foundation reused by every other module.
9
+ - [`domain`](#domain-generator) — scaffolds a bounded business domain (its `contracts`/`core`/`ui`/`features` layers) and wires up cross-domain isolation.
8
10
 
9
- > More generators (e.g. `domain`) are planned. This document covers the generators shipped today.
11
+ ## Init Generator
12
+
13
+ The `init` generator is the **one-shot bootstrap** for a Tactical DDD workspace. Run it once, right after creating your Nx workspace, and it wires up everything the rest of the ecosystem relies on. It is a composing generator — it does not duplicate logic, but orchestrates the lower-level pieces:
14
+
15
+ 1. **Workspace generator defaults** — persists shared options into `nx.json` so they are configured **once** and Nx injects them automatically into later generator invocations, so you never have to retype them. Two groups are written: the organization `prefix` plus `linter`/`unitTestRunner` for our own `@tactical-ddd/nx` generators, and the same `bundler`/`linter`/`unitTestRunner` choices for the built-in `@nx/js:library` generator — so even a hand-rolled `nx g @nx/js:library` already matches the conventions. The matching `@nx/react:library` defaults are added only under the `react` preset:
16
+
17
+ ```jsonc
18
+ // nx.json
19
+ {
20
+ "generators": {
21
+ "@tactical-ddd/nx": {
22
+ "shared-kernel": {
23
+ "prefix": "@my-org",
24
+ "linter": "eslint",
25
+ "unitTestRunner": "jest",
26
+ },
27
+ },
28
+ "@nx/js:library": {
29
+ "bundler": "none",
30
+ "linter": "eslint",
31
+ "unitTestRunner": "jest",
32
+ },
33
+ // Added only with `--preset=react`:
34
+ "@nx/react:library": {
35
+ "bundler": "none",
36
+ "linter": "eslint",
37
+ "unitTestRunner": "jest",
38
+ },
39
+ },
40
+ }
41
+ ```
42
+
43
+ 2. **Module-boundary lint rules** — populates `@nx/enforce-module-boundaries` in the root ESLint config with the full Tactical DDD dependency graph (`depConstraints`). This enforces the allowed dependency directions between scopes/layers _and_ the absence of circular dependencies. Both flat config (`eslint.config.*`) and legacy `.eslintrc.*` are detected and updated via AST manipulation. See [Module Boundaries & Isolation Rules](#module-boundaries--isolation-rules).
44
+
45
+ 3. **Shared Kernel** — invokes the [`shared-kernel`](#shared-kernel-generator) generator to scaffold `libs/shared/{contracts,utils,infrastructure}`.
46
+
47
+ 4. **Framework preset** _(optional)_ — with `--preset=react`, the workspace is additionally set up for React: the `@nx/react:library` generator defaults above are written, the `@nx/react` generator plugin is added, and the React runtime — `react`, `react-dom` and the [`@tactical-ddd/react`](https://www.npmjs.com/package/@tactical-ddd/react) bindings — is installed as a production dependency. With the default `--preset=none` the workspace stays framework-agnostic and none of the React tooling is pulled in.
48
+
49
+ 5. **Dependency check & install** — ensures the packages the configured and invoked generators rely on are present in the workspace `package.json`, installing any that are missing (via `addDependenciesToPackageJson`). Nx plugin versions are pinned to the workspace's Nx version. The set is scoped to your choices: `@nx/js` always; `@nx/eslint` + `@nx/eslint-plugin` when `linter: eslint`; `@nx/jest` or `@nx/vite` to match `unitTestRunner`; and the React packages above when `preset: react`. Already-installed packages are left untouched (never downgraded).
50
+
51
+ > Order matters and is handled for you: the Shared Kernel is generated first (in a fresh workspace the root ESLint config only exists after the first library is created), then the module-boundary rules are applied to it.
52
+
53
+ ### Usage
54
+
55
+ ```bash
56
+ nx g @tactical-ddd/nx:init --prefix=@my-org --linter=eslint --unitTestRunner=jest
57
+ ```
58
+
59
+ For a React workspace, add the preset to also install `@tactical-ddd/react` and the React tooling:
60
+
61
+ ```bash
62
+ nx g @tactical-ddd/nx:init --prefix=@my-org --linter=eslint --unitTestRunner=jest --preset=react
63
+ ```
64
+
65
+ When run interactively (or via Nx Console), the generator prompts for any required option that is not passed on the command line.
66
+
67
+ ### Options
68
+
69
+ | Option | Type | Default | Required | Description |
70
+ | ----------------- | -------- | ------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
71
+ | `prefix` | `string` | — | Yes | Organization prefix used for the generated library names, e.g. `@my-org`. Set once, reused by all generators. |
72
+ | `sharedDirectory` | `string` | `libs/shared` | No | Root folder the Shared Kernel libraries are generated into. |
73
+ | `linter` | `string` | — | Yes | Linter to configure for the generated libraries. One of `eslint`, `none`. |
74
+ | `unitTestRunner` | `string` | — | Yes | Unit test runner to set up. One of `jest`, `vitest`, `none`. |
75
+ | `bundler` | `string` | `none` | No | Bundler used to build the libraries. One of `none`, `swc`, `tsc`, `rollup`, `vite`, `esbuild`. |
76
+ | `preset` | `string` | `none` | No | Framework preset. `react` also installs `@tactical-ddd/react`, the React runtime, and React generator defaults. One of `none`, `react`. |
77
+
78
+ > The generator is idempotent: re-running it refreshes the `nx.json` defaults and module-boundary rules and safely skips Shared Kernel libraries that already exist.
79
+ >
80
+ > If the linter is set to `none` (no ESLint config in the workspace), the module-boundary step is skipped with a warning — there is no linter to enforce the graph.
10
81
 
11
82
  ## Shared Kernel Generator
12
83
 
@@ -164,3 +235,68 @@ The generator automatically tags these projects with `scope:shared`. In your roo
164
235
  - `contracts` knows about no one.
165
236
  - `utils` only knows about `contracts`.
166
237
  - `infrastructure` knows about both `contracts` and `utils`.
238
+
239
+ ## Domain Generator
240
+
241
+ The `domain` generator scaffolds a single **bounded business domain** (e.g. `auth`, `payments`, `beneficiaries`) under `libs/[domain-name]/`. Each domain is isolated from every other domain and depends only on the Shared Kernel and — for collaboration — the **public contracts** of other domains.
242
+
243
+ It generates one library per selected layer, tags each with `scope:domain` plus its layer type and a domain tag (`domain:<name>`), and registers a per-domain module-boundary constraint that enforces the isolation described below.
244
+
245
+ ### Layers
246
+
247
+ The `--layers` option selects which layers to generate (default: `contracts,core`):
248
+
249
+ | Layer | Tags | Purpose |
250
+ | ----------- | -------------------------------- | ----------------------------------------------------------------------------------------- |
251
+ | `contracts` | `scope:domain`, `type:contracts` | Domain-specific types, events, and ports/API boundaries. The domain's **public surface**. |
252
+ | `core` | `scope:domain`, `type:core` | Pure business logic — entities, value objects, use cases, repository interfaces. |
253
+ | `ui` | `scope:domain`, `type:ui` | Presentational components (a DOM lib is added to `tsconfig` for browser globals). |
254
+ | `features` | `scope:domain`, `type:features` | UI + state, framework bindings, DI containers — the topmost layer. |
255
+
256
+ > Under `--preset=react`, the `ui` and `features` layers are generated as React libraries (via `@nx/react`, loaded only when the preset is set); otherwise they are framework-agnostic `@nx/js` libraries.
257
+
258
+ ### Cross-domain isolation (published-language)
259
+
260
+ The generator injects a per-domain `@nx/enforce-module-boundaries` constraint so that a `domain:<name>` library may depend only on:
261
+
262
+ - its **own** domain (`domain:<name>`),
263
+ - the **Shared Kernel** (`scope:shared`),
264
+ - and the **public contracts of any other domain** (`type:contracts`).
265
+
266
+ This is the **published-language** pattern: a domain may depend on another domain's _abstraction_ (its contracts), but never on its _implementation_ (`core`/`ui`/`features`/`infrastructure`). The implementation stays hidden inside the domain and is provided across boundaries via dependency injection wired up in the composition root. Importing another domain's `core` fails the lint boundary check.
267
+
268
+ ### Usage
269
+
270
+ ```bash
271
+ nx g @tactical-ddd/nx:domain payments --directory=libs/payments
272
+ ```
273
+
274
+ `prefix`, `linter`, `unitTestRunner` and `preset` are inherited from the `nx.json` defaults written by [`init`](#init-generator), so in a bootstrapped workspace only the domain name (and directory) are needed. Example with explicit flags:
275
+
276
+ ```bash
277
+ nx g @tactical-ddd/nx:domain payments \
278
+ --directory=libs/payments \
279
+ --prefix=@my-org \
280
+ --layers=contracts,core,features \
281
+ --preset=react \
282
+ --linter=eslint \
283
+ --unitTestRunner=jest \
284
+ --bundler=tsc
285
+ ```
286
+
287
+ ### Options
288
+
289
+ | Option | Type | Default | Required | Description |
290
+ | ---------------- | ---------- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
291
+ | `name` | `string` | — | Yes | Domain name, also the `domain:<name>` tag. Passed as the first positional argument. |
292
+ | `directory` | `string` | — | Yes | Root folder the domain libraries are generated into, e.g. `libs/payments`. |
293
+ | `layers` | `string[]` | `contracts,core` | Yes | Architectural layers to generate. Any of `contracts`, `core`, `ui`, `features`. |
294
+ | `prefix` | `string` | — | No | Organization prefix used for the generated library names, e.g. `@my-org`. |
295
+ | `preset` | `string` | `none` | No | Framework preset for the `ui`/`features` layers. One of `none`, `react`. |
296
+ | `linter` | `string` | — | Yes | Linter to configure for the generated libraries. One of `eslint`, `none`. |
297
+ | `unitTestRunner` | `string` | — | No | Unit test runner to set up. One of `jest`, `vitest`, `none`. (`contracts` is always generated without one.) |
298
+ | `bundler` | `string` | `tsc` | No | Bundler used to build the libraries. One of `none`, `swc`, `tsc`, `rollup`, `vite`, `esbuild`. |
299
+
300
+ > The generator is idempotent: it checks for each layer's library before creating it, so re-running it safely fills in only the layers that are missing.
301
+ >
302
+ > If `libs/shared/contracts` does not exist yet, the generator warns you to run [`init`](#init-generator) (or [`shared-kernel`](#shared-kernel-generator)) first, since domain libraries depend on the Shared Kernel.
@@ -0,0 +1,5 @@
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
+ import type { DomainGeneratorSchema } from './schema';
3
+ export declare function domainGenerator(tree: Tree, options: DomainGeneratorSchema): Promise<GeneratorCallback>;
4
+ export default domainGenerator;
5
+ //# sourceMappingURL=domain.d.ts.map
@@ -0,0 +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,CAmK5B;AAqED,eAAe,eAAe,CAAC"}
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get default () {
13
+ return _default;
14
+ },
15
+ get domainGenerator () {
16
+ return domainGenerator;
17
+ }
18
+ });
19
+ const _extends = require("@swc/helpers/_/_extends");
20
+ const _devkit = require("@nx/devkit");
21
+ const _js = require("@nx/js");
22
+ const _path = require("path");
23
+ const _libraryexist = require("../../utils/library-exist");
24
+ const _eslintmoduleboundaries = require("../../utils/eslint-module-boundaries");
25
+ const _logger = require("../../utils/logger");
26
+ const _types = require("../../types");
27
+ const _resolvemoduleformat = require("../../utils/resolve-module-format");
28
+ /** Conventional location of the shared kernel's contracts library. */ const SHARED_CONTRACTS_ROOT = 'libs/shared/contracts';
29
+ async function domainGenerator(tree, options) {
30
+ // Implicit existence check (CLAUDE.md 7.3.1): domain libraries depend on the
31
+ // shared kernel, so warn if it has not been generated yet rather than
32
+ // producing libraries whose boundary constraints reference tags nothing
33
+ // carries.
34
+ if (!(0, _libraryexist.libraryExists)(tree, SHARED_CONTRACTS_ROOT)) {
35
+ (0, _logger.warning)(`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.`);
36
+ }
37
+ const contractsRoot = `${options.directory}/contracts`;
38
+ const coreRoot = `${options.directory}/core`;
39
+ const uiRoot = `${options.directory}/ui`;
40
+ const featuresRoot = `${options.directory}/features`;
41
+ const domainTag = `domain:${options.name}`;
42
+ const facadeDomainInterfaceVariants = (0, _devkit.names)(`${options.name}Facade`);
43
+ // Install callbacks from the delegated library generators — returned to Nx so
44
+ // the packages backing the inferred plugins (`@nx/eslint`, `@nx/jest`) the
45
+ // libraries register via `addPlugin` get installed.
46
+ const tasks = [];
47
+ if (!(0, _libraryexist.libraryExists)(tree, contractsRoot) && options.layers.includes('contracts')) {
48
+ tasks.push(await (0, _js.libraryGenerator)(tree, {
49
+ name: layerName(options, 'contracts'),
50
+ directory: contractsRoot,
51
+ useProjectJson: false,
52
+ addPlugin: true,
53
+ unitTestRunner: 'none',
54
+ bundler: options.bundler,
55
+ linter: options.linter,
56
+ tags: `${_types.LibraryScope.Domain},${domainTag},${_types.LibraryType.Contracts}`
57
+ }));
58
+ const type = (0, _resolvemoduleformat.resolveLibraryModuleFormat)(tree, contractsRoot);
59
+ tree.delete(`${contractsRoot}/src/lib/${options.name}-contracts.ts`);
60
+ tree.write(`${contractsRoot}/src/index.ts`, '');
61
+ (0, _devkit.generateFiles)(tree, (0, _path.resolve)(__dirname, 'files/contracts'), contractsRoot, {
62
+ name: options.name,
63
+ interfaceName: facadeDomainInterfaceVariants.className,
64
+ esm: type === _types.ModuleFormat.EsModule
65
+ }, {
66
+ overwriteStrategy: _devkit.OverwriteStrategy.Overwrite
67
+ });
68
+ }
69
+ if (!(0, _libraryexist.libraryExists)(tree, coreRoot) && options.layers.includes('core')) {
70
+ tasks.push(await (0, _js.libraryGenerator)(tree, {
71
+ name: layerName(options, 'core'),
72
+ directory: coreRoot,
73
+ useProjectJson: false,
74
+ addPlugin: true,
75
+ unitTestRunner: options.unitTestRunner,
76
+ bundler: options.bundler,
77
+ linter: options.linter,
78
+ tags: `${_types.LibraryScope.Domain},${domainTag},${_types.LibraryType.Core}`
79
+ }));
80
+ const type = (0, _resolvemoduleformat.resolveLibraryModuleFormat)(tree, coreRoot);
81
+ const contractsPackage = layerName(options, 'contracts');
82
+ tree.delete(`${coreRoot}/src/lib/${options.name}-core.ts`);
83
+ tree.delete(`${coreRoot}/src/lib/${options.name}-core.spec.ts`);
84
+ tree.write(`${coreRoot}/src/index.ts`, '');
85
+ // Scaffold the default Clean Architecture layer folders (domain,
86
+ // application, infrastructure — each kept in git via a `.gitkeep`) and lock
87
+ // down imports between them: domain ⊀ application/infrastructure, and
88
+ // application ⊀ infrastructure (the implementation is wired via DI at the
89
+ // composition root, not imported across layers).
90
+ (0, _devkit.generateFiles)(tree, (0, _path.resolve)(__dirname, 'files/core'), coreRoot, {
91
+ name: options.name,
92
+ interfaceName: facadeDomainInterfaceVariants.className,
93
+ // Full package name of this domain's contracts library, so the facade's
94
+ // import resolves with or without an organization prefix.
95
+ contractsPackage,
96
+ esm: type === _types.ModuleFormat.EsModule
97
+ }, {
98
+ overwriteStrategy: _devkit.OverwriteStrategy.Overwrite
99
+ });
100
+ // The generated facade imports the domain's contracts package, so declare it
101
+ // as a dependency — otherwise `@nx/dependency-checks` flags the core library
102
+ // for using a package missing from its `package.json`.
103
+ if (tree.exists(`${contractsRoot}/package.json`)) {
104
+ var _readJson_version;
105
+ const contractsVersion = (_readJson_version = (0, _devkit.readJson)(tree, `${contractsRoot}/package.json`).version) != null ? _readJson_version : '*';
106
+ (0, _devkit.updateJson)(tree, `${coreRoot}/package.json`, (pkg)=>{
107
+ pkg.dependencies = _extends._({}, pkg.dependencies, {
108
+ [contractsPackage]: contractsVersion
109
+ });
110
+ return pkg;
111
+ });
112
+ }
113
+ (0, _eslintmoduleboundaries.applyCleanArchitectureBoundaries)(tree, coreRoot, options.prefix);
114
+ }
115
+ if (!(0, _libraryexist.libraryExists)(tree, uiRoot) && options.layers.includes('ui')) {
116
+ tasks.push(await generateLayerLibrary(tree, options, {
117
+ root: uiRoot,
118
+ name: layerName(options, 'ui'),
119
+ tags: `${_types.LibraryScope.Domain},${domainTag},${_types.LibraryType.Ui}`
120
+ }));
121
+ }
122
+ if (!(0, _libraryexist.libraryExists)(tree, featuresRoot) && options.layers.includes('features')) {
123
+ tasks.push(await generateLayerLibrary(tree, options, {
124
+ root: featuresRoot,
125
+ name: layerName(options, 'features'),
126
+ tags: `${_types.LibraryScope.Domain},${domainTag},${_types.LibraryType.Features}`
127
+ }));
128
+ }
129
+ // Silo this domain: per-domain constraints are what actually prevent
130
+ // cross-domain imports (a static `domain:*` rule cannot — Nx glob-matches the
131
+ // target tags, so it would let `domain:auth` import `domain:payments`).
132
+ //
133
+ // A `domain:<name>` library may depend on its own domain, the shared kernel,
134
+ // and the *public contracts* of any other domain (`type:contracts`) — the
135
+ // published-language pattern: a domain depends on another domain's
136
+ // abstraction, never its implementation (`core`/`ui`/`features`/
137
+ // `infrastructure`), which stays hidden behind DI wired up in the composition
138
+ // root. No-op (with a warning) when there is no ESLint config.
139
+ (0, _eslintmoduleboundaries.applyDepConstraints)(tree, [
140
+ {
141
+ sourceTag: domainTag,
142
+ onlyDependOnLibsWithTags: [
143
+ domainTag,
144
+ _types.LibraryScope.Shared,
145
+ _types.LibraryType.Contracts
146
+ ]
147
+ }
148
+ ]);
149
+ await (0, _devkit.formatFiles)(tree);
150
+ return (0, _devkit.runTasksInSerial)(...tasks);
151
+ }
152
+ /** Composes a layer library name, applying the optional organization prefix. */ function layerName(options, layer) {
153
+ const base = `${options.name}-${layer}`;
154
+ return options.prefix ? `${options.prefix}/${base}` : base;
155
+ }
156
+ /**
157
+ * Generates a presentational/feature layer library and returns its install
158
+ * callback. Under the `react` preset it uses `@nx/react`'s generator (loaded
159
+ * lazily via `ensurePackage` so the domain generator never hard-depends on
160
+ * `@nx/react` in non-React workspaces); under `none` it uses `@nx/js` and adds
161
+ * the DOM lib to the library `tsconfig` so browser globals type-check.
162
+ *
163
+ * Both pass `addPlugin: true` so the library gets inferred tasks (Project
164
+ * Crystal) rather than the deprecated executor targets the generators' public
165
+ * wrappers default to.
166
+ */ async function generateLayerLibrary(tree, options, layer) {
167
+ if (options.preset === 'react') {
168
+ const { libraryGenerator: reactLibraryGenerator } = (0, _devkit.ensurePackage)('@nx/react', _devkit.NX_VERSION);
169
+ return await reactLibraryGenerator(tree, {
170
+ name: layer.name,
171
+ directory: layer.root,
172
+ useProjectJson: false,
173
+ addPlugin: true,
174
+ unitTestRunner: options.unitTestRunner,
175
+ bundler: options.bundler,
176
+ linter: options.linter,
177
+ style: 'none',
178
+ tags: layer.tags
179
+ });
180
+ }
181
+ const task = await (0, _js.libraryGenerator)(tree, {
182
+ name: layer.name,
183
+ directory: layer.root,
184
+ useProjectJson: false,
185
+ addPlugin: true,
186
+ unitTestRunner: options.unitTestRunner,
187
+ bundler: options.bundler,
188
+ linter: options.linter,
189
+ tags: layer.tags
190
+ });
191
+ addDomLibToTsConfig(tree, layer.root);
192
+ return task;
193
+ }
194
+ /** Adds the `DOM` lib to a library's `tsconfig.lib.json` (idempotent). */ function addDomLibToTsConfig(tree, root) {
195
+ (0, _devkit.updateJson)(tree, `${root}/tsconfig.lib.json`, (json)=>{
196
+ var _json, _compilerOptions;
197
+ (_compilerOptions = (_json = json).compilerOptions) != null ? _compilerOptions : _json.compilerOptions = {};
198
+ if (!json.compilerOptions.lib) {
199
+ json.compilerOptions.lib = [
200
+ 'ESNext',
201
+ 'DOM'
202
+ ];
203
+ } else if (!json.compilerOptions.lib.includes('DOM')) {
204
+ json.compilerOptions.lib.push('DOM');
205
+ }
206
+ return json;
207
+ });
208
+ }
209
+ const _default = domainGenerator;
210
+
211
+ //# sourceMappingURL=domain.js.map
@@ -0,0 +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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"}
@@ -0,0 +1 @@
1
+ export * from './lib/interfaces/<%= name %>-facade.interface<% if (esm) { %>.js<% } %>';
@@ -0,0 +1,7 @@
1
+ export interface <%= interfaceName %> {
2
+ method(): void
3
+ }
4
+
5
+ export const <%= interfaceName %> = {
6
+ $: Symbol.for('<%= interfaceName %>')
7
+ }
@@ -0,0 +1 @@
1
+ export * from './lib/application/<%= name %>.facade<% if (esm) { %>.js<% } %>';
@@ -0,0 +1,7 @@
1
+ import { <%= interfaceName %> } from '<%= contractsPackage %>';
2
+
3
+ export class Core<%= interfaceName %> implements <%= interfaceName %> {
4
+ method(): void {
5
+ throw new Error('Method not implemented.');
6
+ }
7
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+
6
+ //# sourceMappingURL=schema.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../packages/nx/src/generators/domain/schema.d.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import type { Bundler } from '@nx/devkit';
2
+
3
+ export interface DomainGeneratorSchema {
4
+ directory: string;
5
+ name: string;
6
+ layers: string[];
7
+ prefix?: string;
8
+ preset?: string;
9
+ linter: 'eslint' | 'none';
10
+ unitTestRunner?: 'jest' | 'vitest' | 'none';
11
+ bundler?: Bundler;
12
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "DomainGenerator",
4
+ "title": "Tactical DDD: Domain Generator",
5
+ "type": "object",
6
+ "properties": {
7
+ "name": {
8
+ "type": "string",
9
+ "description": "Domain ",
10
+ "$default": {
11
+ "$source": "argv",
12
+ "index": 0
13
+ },
14
+ "x-prompt": "What name would you like to use?"
15
+ },
16
+ "directory": {
17
+ "type": "string",
18
+ "description": "Root folder for domain libraries",
19
+ "x-prompt": "Which directory should the domain be generated into?"
20
+ },
21
+ "prefix": {
22
+ "type": "string",
23
+ "description": "Organization prefix for the generated libraries, e.g. '@my-org'",
24
+ "x-prompt": "Which organization prefix should be used (e.g. @my-org)?"
25
+ },
26
+ "layers": {
27
+ "type": "array",
28
+ "description": "Select the architectural layers to generate for this domain",
29
+ "items": {
30
+ "type": "string",
31
+ "enum": ["contracts", "core", "ui", "features"]
32
+ },
33
+ "default": ["contracts", "core"],
34
+ "x-prompt": "Select the architectural layers to generate for this domain"
35
+ },
36
+ "preset": {
37
+ "type": "string",
38
+ "enum": ["none", "react"],
39
+ "default": "none",
40
+ "description": "Framework preset. 'react' also installs @tactical-ddd/react, the React runtime and React generator defaults.",
41
+ "x-prompt": {
42
+ "message": "Which framework preset should be configured?",
43
+ "type": "list",
44
+ "items": [
45
+ { "value": "none", "label": "None (framework-agnostic)" },
46
+ {
47
+ "value": "react",
48
+ "label": "React (@tactical-ddd/react + React tooling)"
49
+ }
50
+ ]
51
+ }
52
+ },
53
+ "linter": {
54
+ "type": "string",
55
+ "enum": ["eslint", "none"],
56
+ "description": "Which linter to use?",
57
+ "x-prompt": "Which linter should be configured?"
58
+ },
59
+ "unitTestRunner": {
60
+ "type": "string",
61
+ "enum": ["jest", "vitest", "none"],
62
+ "description": "Which test runner to use?",
63
+ "x-prompt": "Which unit test runner should be used?"
64
+ },
65
+ "bundler": {
66
+ "type": "string",
67
+ "enum": ["none", "swc", "tsc", "rollup", "vite", "esbuild"],
68
+ "default": "tsc",
69
+ "description": "Which bundler to use? Defaults to 'tsc' per the Tactical DDD standard (all generated libraries are tsc-built)."
70
+ }
71
+ },
72
+ "required": ["name", "directory", "layers", "linter", "prefix"]
73
+ }
@@ -0,0 +1,5 @@
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
+ import type { InitGeneratorSchema } from './schema';
3
+ export declare function initGenerator(tree: Tree, options: InitGeneratorSchema): Promise<GeneratorCallback>;
4
+ export default initGenerator;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../packages/nx/src/generators/init/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,iBAAiB,EAEtB,KAAK,IAAI,EACV,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAuDpD,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CA8B5B;AA4HD,eAAe,aAAa,CAAC"}