@codyswann/lisa 1.9.5 → 1.11.0

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 (44) hide show
  1. package/README.md +71 -0
  2. package/all/copy-overwrite/.claude/agents/skill-evaluator.md +4 -4
  3. package/all/copy-overwrite/CLAUDE.md +1 -1
  4. package/cdk/tagged-merge/package.lisa.json +31 -0
  5. package/dist/core/config.d.ts +1 -1
  6. package/dist/core/config.d.ts.map +1 -1
  7. package/dist/core/config.js +1 -0
  8. package/dist/core/config.js.map +1 -1
  9. package/dist/core/lisa.d.ts.map +1 -1
  10. package/dist/core/lisa.js +2 -0
  11. package/dist/core/lisa.js.map +1 -1
  12. package/dist/strategies/index.d.ts +1 -0
  13. package/dist/strategies/index.d.ts.map +1 -1
  14. package/dist/strategies/index.js +3 -0
  15. package/dist/strategies/index.js.map +1 -1
  16. package/dist/strategies/package-lisa-types.d.ts +83 -0
  17. package/dist/strategies/package-lisa-types.d.ts.map +1 -0
  18. package/dist/strategies/package-lisa-types.js +10 -0
  19. package/dist/strategies/package-lisa-types.js.map +1 -0
  20. package/dist/strategies/package-lisa.d.ts +183 -0
  21. package/dist/strategies/package-lisa.d.ts.map +1 -0
  22. package/dist/strategies/package-lisa.js +385 -0
  23. package/dist/strategies/package-lisa.js.map +1 -0
  24. package/dist/strategies/tagged-merge.d.ts +41 -4
  25. package/dist/strategies/tagged-merge.d.ts.map +1 -1
  26. package/dist/strategies/tagged-merge.js +91 -4
  27. package/dist/strategies/tagged-merge.js.map +1 -1
  28. package/expo/copy-overwrite/knip.json +0 -1
  29. package/expo/tagged-merge/package.lisa.json +131 -0
  30. package/nestjs/tagged-merge/package.lisa.json +73 -0
  31. package/package.json +32 -31
  32. package/typescript/copy-overwrite/knip.json +3 -4
  33. package/typescript/tagged-merge/package.lisa.json +73 -0
  34. package/cdk/tagged-merge/package.json +0 -37
  35. package/expo/tagged-merge/package.json +0 -145
  36. package/nestjs/tagged-merge/package.json +0 -87
  37. package/typescript/tagged-merge/package.json +0 -75
  38. /package/cdk/{copy-overwrite → create-only}/.github/workflows/ci.yml +0 -0
  39. /package/cdk/{copy-overwrite → create-only}/.github/workflows/deploy.yml +0 -0
  40. /package/expo/{copy-overwrite → create-only}/.github/workflows/ci.yml +0 -0
  41. /package/expo/{copy-overwrite → create-only}/.github/workflows/deploy.yml +0 -0
  42. /package/nestjs/{copy-overwrite → create-only}/.github/workflows/ci.yml +0 -0
  43. /package/nestjs/{copy-overwrite → create-only}/.github/workflows/deploy.yml +0 -0
  44. /package/typescript/{copy-overwrite → create-only}/.github/workflows/ci.yml +0 -0
@@ -0,0 +1,183 @@
1
+ import type { FileOperationResult } from "../core/config.js";
2
+ import type { ICopyStrategy, StrategyContext } from "./strategy.interface.js";
3
+ /**
4
+ * @file package-lisa.ts
5
+ * @description Package.lisa.json strategy for governance-driven package.json management
6
+ *
7
+ * Implements a two-file approach to package.json governance:
8
+ * - Source: package.lisa.json files in type directories (all/, typescript/, expo/, etc.)
9
+ * - Destination: project's package.json
10
+ *
11
+ * Behavior is defined in package.lisa.json:
12
+ * - force: Lisa's values completely replace project's values
13
+ * - defaults: Project's values preserved; Lisa's used only if missing
14
+ * - merge: Arrays concatenated and deduplicated
15
+ *
16
+ * Inheritance chain: all → typescript → specific types (expo, nestjs, cdk, npm-package)
17
+ * Child types override parent values in each section.
18
+ * @module strategies
19
+ */
20
+ /**
21
+ * Package.lisa.json strategy: Manage package.json via separate template files
22
+ * - Loads templates from all applicable types in inheritance chain
23
+ * - Merges templates (child overrides parent)
24
+ * - Applies force/defaults/merge logic to project's package.json
25
+ * - Keeps project's package.json 100% clean (no Lisa artifacts)
26
+ */
27
+ export declare class PackageLisaStrategy implements ICopyStrategy {
28
+ readonly name: "package-lisa";
29
+ private readonly PACKAGE_JSON;
30
+ private readonly TSCONFIG_JSON;
31
+ private readonly APP_JSON;
32
+ private readonly EAS_JSON;
33
+ private readonly NEST_CLI_JSON;
34
+ private readonly CDK_JSON;
35
+ /**
36
+ * Apply package-lisa strategy: Load templates from inheritance chain, apply to package.json
37
+ * @remarks
38
+ * This strategy is unique because:
39
+ * 1. It loads multiple source files from type hierarchy, not just one
40
+ * 2. It applies structured merge logic (force/defaults/merge) instead of simple JSON merge
41
+ * 3. It never applies changes if source file doesn't exist in ANY type directory
42
+ * @param sourcePath - Path to source package.lisa.json (only used for detecting when to apply)
43
+ * @param destPath - Destination package.json path
44
+ * @param relativePath - Relative path for recording ("package.json")
45
+ * @param context - Strategy context with config and callbacks
46
+ * @returns Result with action "copied", "merged", or "skipped"
47
+ */
48
+ apply(sourcePath: string, destPath: string, relativePath: string, context: StrategyContext): Promise<FileOperationResult>;
49
+ /**
50
+ * Create destination file when it doesn't exist
51
+ * @param destPath - Path to destination package.json
52
+ * @param merged - Merged package.json object
53
+ * @param relativePath - Relative path for recording
54
+ * @param context - Strategy context with config and callbacks
55
+ * @returns Result with action "copied"
56
+ * @private
57
+ */
58
+ private createDestination;
59
+ /**
60
+ * Update destination file when it exists
61
+ * @param destPath - Path to destination package.json
62
+ * @param merged - Merged package.json object
63
+ * @param relativePath - Relative path for recording
64
+ * @param context - Strategy context with config and callbacks
65
+ * @returns Result with action "merged" or "skipped"
66
+ * @private
67
+ */
68
+ private updateDestination;
69
+ /**
70
+ * Merge package.json using force/defaults/merge logic from package.lisa.json templates
71
+ * @param packageJsonPath - Absolute path to destination package.json
72
+ * @param context - Strategy context with Lisa config
73
+ * @returns Merged package.json object
74
+ * @private
75
+ */
76
+ private mergePackageJson;
77
+ /**
78
+ * Detect which project types apply to this project
79
+ * (TypeScript, Expo, NestJS, CDK, npm-package)
80
+ * @param projectDir - Root directory of the project
81
+ * @returns Array of detected project types
82
+ * @private
83
+ */
84
+ private detectProjectTypes;
85
+ /**
86
+ * Check if package.json contains a key
87
+ * @param projectDir - The project directory to check
88
+ * @param key - The key to check for in package.json
89
+ * @returns True if the key exists in package.json, false otherwise
90
+ * @private
91
+ */
92
+ private packageJsonHasKey;
93
+ /**
94
+ * Check if package.json contains a key that starts with a prefix (for scoped packages)
95
+ * @param projectDir - The project directory to check
96
+ * @param prefix - The prefix to check for (e.g., "@nestjs" or "@aws-sdk")
97
+ * @returns True if any key in package.json starts with the given prefix, false otherwise
98
+ * @private
99
+ */
100
+ private packageJsonHasKeyPrefix;
101
+ /**
102
+ * Get a field value from package.json
103
+ * @param projectDir - The project directory containing the package.json
104
+ * @param fieldName - The field name to retrieve from package.json
105
+ * @returns The field value if found, undefined if not found or if package.json doesn't exist
106
+ * @private
107
+ */
108
+ private packageJsonField;
109
+ /**
110
+ * Load and merge all package.lisa.json templates from type hierarchy
111
+ * @remarks
112
+ * Inheritance chain: all → typescript → specific types (expo, nestjs, cdk, npm-package)
113
+ * Child types override parent types in force, defaults, and merge sections.
114
+ * @param lisaDir - Root Lisa directory path
115
+ * @param detectedTypes - Project types to load templates for
116
+ * @returns Merged template with force, defaults, merge sections
117
+ * @private
118
+ */
119
+ private loadAndMergeTemplates;
120
+ /**
121
+ * Expand project types to include parent types
122
+ * @remarks
123
+ * Type hierarchy: expo/nestjs/cdk/npm-package inherit from typescript
124
+ * This expands a list to include parents.
125
+ * Example: [expo] → [typescript, expo]
126
+ * @param types - Project types detected
127
+ * @returns Expanded types including parents
128
+ * @private
129
+ */
130
+ private expandTypeHierarchy;
131
+ /**
132
+ * Merge two template objects
133
+ * Child template (override) values win in force and defaults.
134
+ * Merge arrays are concatenated without deduplication at merge time.
135
+ * @param parent - Parent template (e.g., "all" or "typescript")
136
+ * @param child - Child template (e.g., "expo") that overrides parent
137
+ * @returns Merged template
138
+ * @private
139
+ */
140
+ private mergeTemplates;
141
+ /**
142
+ * Merge two merge-section objects
143
+ * Arrays are concatenated (deduplication happens later when applied to package.json)
144
+ * @param parent - Parent merge sections
145
+ * @param child - Child merge sections
146
+ * @returns Merged sections
147
+ * @private
148
+ */
149
+ private mergeMergeSections;
150
+ /**
151
+ * Apply force/defaults/merge logic to project's package.json
152
+ * @remarks
153
+ * Processing order:
154
+ * 1. Apply force: Deep merge with Lisa values winning (entire section replaced)
155
+ * 2. Apply defaults: Deep merge with project values winning (only set if missing)
156
+ * 3. Apply merge: Concatenate arrays and deduplicate
157
+ * @param projectJson - Current project's package.json
158
+ * @param template - Merged package.lisa.json template
159
+ * @returns Modified package.json
160
+ * @private
161
+ */
162
+ private applyTemplate;
163
+ /**
164
+ * Apply merge-section arrays to package.json
165
+ * Concatenates Lisa's items and project's items, deduplicated by JSON.stringify equality.
166
+ * @param packageJson - Current package.json after force/defaults applied
167
+ * @param mergeSections - Merge sections from template
168
+ * @returns Package.json with merge sections applied
169
+ * @private
170
+ */
171
+ private applyMergeSections;
172
+ /**
173
+ * Concatenate two arrays and remove duplicates
174
+ * Uses JSON.stringify for value equality comparison.
175
+ * Lisa items come first, then project's unique items.
176
+ * @param lisaItems - Lisa's items (come first)
177
+ * @param projectItems - Project's items (added if not already present)
178
+ * @returns Deduplicated array
179
+ * @private
180
+ */
181
+ private deduplicateArrays;
182
+ }
183
+ //# sourceMappingURL=package-lisa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-lisa.d.ts","sourceRoot":"","sources":["../../src/strategies/package-lisa.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,mBAAmB,CAAC;AAE1E,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAc9E;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IAExC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IAEvC;;;;;;;;;;;;OAYG;IACG,KAAK,CACT,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;IA8B/B;;;;;;;;OAQG;YACW,iBAAiB;IAc/B;;;;;;;;OAQG;YACW,iBAAiB;IA4B/B;;;;;;OAMG;YACW,gBAAgB;IAsB9B;;;;;;OAMG;YACW,kBAAkB;IA8ChC;;;;;;OAMG;YACW,iBAAiB;IAW/B;;;;;;OAMG;YACW,uBAAuB;IAWrC;;;;;;OAMG;YACW,gBAAgB;IAW9B;;;;;;;;;OASG;YACW,qBAAqB;IAwCnC;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;;;;;;;OAQG;IACH,OAAO,CAAC,cAAc;IAWtB;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IAoBrB;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;CA2B1B"}
@@ -0,0 +1,385 @@
1
+ import * as fse from "fs-extra";
2
+ import path from "node:path";
3
+ import { PROJECT_TYPE_HIERARCHY } from "../core/config.js";
4
+ import { ensureParentDir } from "../utils/file-operations.js";
5
+ import { readJson, writeJson, deepMerge, readJsonOrNull, } from "../utils/json-utils.js";
6
+ import { JsonMergeError } from "../errors/index.js";
7
+ /**
8
+ * @file package-lisa.ts
9
+ * @description Package.lisa.json strategy for governance-driven package.json management
10
+ *
11
+ * Implements a two-file approach to package.json governance:
12
+ * - Source: package.lisa.json files in type directories (all/, typescript/, expo/, etc.)
13
+ * - Destination: project's package.json
14
+ *
15
+ * Behavior is defined in package.lisa.json:
16
+ * - force: Lisa's values completely replace project's values
17
+ * - defaults: Project's values preserved; Lisa's used only if missing
18
+ * - merge: Arrays concatenated and deduplicated
19
+ *
20
+ * Inheritance chain: all → typescript → specific types (expo, nestjs, cdk, npm-package)
21
+ * Child types override parent values in each section.
22
+ * @module strategies
23
+ */
24
+ /**
25
+ * Package.lisa.json strategy: Manage package.json via separate template files
26
+ * - Loads templates from all applicable types in inheritance chain
27
+ * - Merges templates (child overrides parent)
28
+ * - Applies force/defaults/merge logic to project's package.json
29
+ * - Keeps project's package.json 100% clean (no Lisa artifacts)
30
+ */
31
+ export class PackageLisaStrategy {
32
+ name = "package-lisa";
33
+ PACKAGE_JSON = "package.json";
34
+ TSCONFIG_JSON = "tsconfig.json";
35
+ APP_JSON = "app.json";
36
+ EAS_JSON = "eas.json";
37
+ NEST_CLI_JSON = "nest-cli.json";
38
+ CDK_JSON = "cdk.json";
39
+ /**
40
+ * Apply package-lisa strategy: Load templates from inheritance chain, apply to package.json
41
+ * @remarks
42
+ * This strategy is unique because:
43
+ * 1. It loads multiple source files from type hierarchy, not just one
44
+ * 2. It applies structured merge logic (force/defaults/merge) instead of simple JSON merge
45
+ * 3. It never applies changes if source file doesn't exist in ANY type directory
46
+ * @param sourcePath - Path to source package.lisa.json (only used for detecting when to apply)
47
+ * @param destPath - Destination package.json path
48
+ * @param relativePath - Relative path for recording ("package.json")
49
+ * @param context - Strategy context with config and callbacks
50
+ * @returns Result with action "copied", "merged", or "skipped"
51
+ */
52
+ async apply(sourcePath, destPath, relativePath, context) {
53
+ // Check if any package.lisa.json exists in the Lisa directory
54
+ const packageLisaExists = await fse.pathExists(sourcePath);
55
+ if (!packageLisaExists) {
56
+ // No package.lisa.json found; skip this strategy
57
+ return { relativePath, strategy: this.name, action: "skipped" };
58
+ }
59
+ const destExists = await fse.pathExists(destPath);
60
+ try {
61
+ // Load templates and apply regardless of whether destination exists
62
+ const merged = await this.mergePackageJson(destPath, context);
63
+ if (!destExists) {
64
+ return this.createDestination(destPath, merged, relativePath, context);
65
+ }
66
+ return this.updateDestination(destPath, merged, relativePath, context);
67
+ }
68
+ catch (error) {
69
+ if (error instanceof JsonMergeError) {
70
+ throw error;
71
+ }
72
+ throw new JsonMergeError(relativePath, `Failed to apply package-lisa strategy: ${error instanceof Error ? error.message : String(error)}`);
73
+ }
74
+ }
75
+ /**
76
+ * Create destination file when it doesn't exist
77
+ * @param destPath - Path to destination package.json
78
+ * @param merged - Merged package.json object
79
+ * @param relativePath - Relative path for recording
80
+ * @param context - Strategy context with config and callbacks
81
+ * @returns Result with action "copied"
82
+ * @private
83
+ */
84
+ async createDestination(destPath, merged, relativePath, context) {
85
+ if (!context.config.dryRun) {
86
+ await ensureParentDir(destPath);
87
+ await writeJson(destPath, merged);
88
+ context.recordFile(relativePath, this.name);
89
+ }
90
+ return { relativePath, strategy: this.name, action: "copied" };
91
+ }
92
+ /**
93
+ * Update destination file when it exists
94
+ * @param destPath - Path to destination package.json
95
+ * @param merged - Merged package.json object
96
+ * @param relativePath - Relative path for recording
97
+ * @param context - Strategy context with config and callbacks
98
+ * @returns Result with action "merged" or "skipped"
99
+ * @private
100
+ */
101
+ async updateDestination(destPath, merged, relativePath, context) {
102
+ const originalJson = await readJson(destPath);
103
+ // Normalize for comparison
104
+ const normalizedDest = JSON.stringify(originalJson, null, 2);
105
+ const normalizedMerged = JSON.stringify(merged, null, 2);
106
+ if (normalizedDest === normalizedMerged) {
107
+ if (!context.config.dryRun) {
108
+ context.recordFile(relativePath, this.name);
109
+ }
110
+ return { relativePath, strategy: this.name, action: "skipped" };
111
+ }
112
+ if (!context.config.dryRun) {
113
+ await context.backupFile(destPath);
114
+ await writeJson(destPath, merged);
115
+ context.recordFile(relativePath, this.name);
116
+ }
117
+ return { relativePath, strategy: this.name, action: "merged" };
118
+ }
119
+ /**
120
+ * Merge package.json using force/defaults/merge logic from package.lisa.json templates
121
+ * @param packageJsonPath - Absolute path to destination package.json
122
+ * @param context - Strategy context with Lisa config
123
+ * @returns Merged package.json object
124
+ * @private
125
+ */
126
+ async mergePackageJson(packageJsonPath, context) {
127
+ // Try to read existing package.json, or start with empty object
128
+ const projectJson = (await readJsonOrNull(packageJsonPath)) || {};
129
+ // Extract the Lisa directory from config
130
+ const lisaDir = context.config.lisaDir;
131
+ const projectDir = path.dirname(packageJsonPath);
132
+ // Get detected project types by analyzing the project structure
133
+ const detectedTypes = await this.detectProjectTypes(projectDir);
134
+ // Load and merge all package.lisa.json templates from type hierarchy
135
+ const merged = await this.loadAndMergeTemplates(lisaDir, detectedTypes);
136
+ // Apply force/defaults/merge logic to project's package.json
137
+ return this.applyTemplate(projectJson, merged);
138
+ }
139
+ /**
140
+ * Detect which project types apply to this project
141
+ * (TypeScript, Expo, NestJS, CDK, npm-package)
142
+ * @param projectDir - Root directory of the project
143
+ * @returns Array of detected project types
144
+ * @private
145
+ */
146
+ async detectProjectTypes(projectDir) {
147
+ const types = [];
148
+ // TypeScript detection
149
+ const hasTypeScript = (await fse.pathExists(path.join(projectDir, this.TSCONFIG_JSON))) ||
150
+ (await this.packageJsonHasKey(projectDir, "typescript"));
151
+ if (hasTypeScript)
152
+ types.push("typescript");
153
+ // Expo detection
154
+ const hasExpo = (await fse.pathExists(path.join(projectDir, this.APP_JSON))) ||
155
+ (await fse.pathExists(path.join(projectDir, this.EAS_JSON))) ||
156
+ (await this.packageJsonHasKey(projectDir, "expo"));
157
+ if (hasExpo)
158
+ types.push("expo");
159
+ // NestJS detection
160
+ const hasNestJS = (await fse.pathExists(path.join(projectDir, this.NEST_CLI_JSON))) ||
161
+ (await this.packageJsonHasKeyPrefix(projectDir, "@nestjs"));
162
+ if (hasNestJS)
163
+ types.push("nestjs");
164
+ // CDK detection
165
+ const hasCDK = (await fse.pathExists(path.join(projectDir, this.CDK_JSON))) ||
166
+ (await this.packageJsonHasKey(projectDir, "aws-cdk"));
167
+ if (hasCDK)
168
+ types.push("cdk");
169
+ // npm-package detection
170
+ const isPrivate = await this.packageJsonField(projectDir, "private");
171
+ const hasPublishField = (await this.packageJsonField(projectDir, "main")) !== undefined ||
172
+ (await this.packageJsonField(projectDir, "bin")) !== undefined ||
173
+ (await this.packageJsonField(projectDir, "exports")) !== undefined ||
174
+ (await this.packageJsonField(projectDir, "files")) !== undefined;
175
+ if (!isPrivate && hasPublishField) {
176
+ types.push("npm-package");
177
+ }
178
+ return types;
179
+ }
180
+ /**
181
+ * Check if package.json contains a key
182
+ * @param projectDir - The project directory to check
183
+ * @param key - The key to check for in package.json
184
+ * @returns True if the key exists in package.json, false otherwise
185
+ * @private
186
+ */
187
+ async packageJsonHasKey(projectDir, key) {
188
+ const packageJson = await readJsonOrNull(path.join(projectDir, this.PACKAGE_JSON));
189
+ if (!packageJson)
190
+ return false;
191
+ return key in packageJson;
192
+ }
193
+ /**
194
+ * Check if package.json contains a key that starts with a prefix (for scoped packages)
195
+ * @param projectDir - The project directory to check
196
+ * @param prefix - The prefix to check for (e.g., "@nestjs" or "@aws-sdk")
197
+ * @returns True if any key in package.json starts with the given prefix, false otherwise
198
+ * @private
199
+ */
200
+ async packageJsonHasKeyPrefix(projectDir, prefix) {
201
+ const packageJson = await readJsonOrNull(path.join(projectDir, this.PACKAGE_JSON));
202
+ if (!packageJson)
203
+ return false;
204
+ return Object.keys(packageJson).some(key => key.startsWith(prefix));
205
+ }
206
+ /**
207
+ * Get a field value from package.json
208
+ * @param projectDir - The project directory containing the package.json
209
+ * @param fieldName - The field name to retrieve from package.json
210
+ * @returns The field value if found, undefined if not found or if package.json doesn't exist
211
+ * @private
212
+ */
213
+ async packageJsonField(projectDir, fieldName) {
214
+ const packageJson = await readJsonOrNull(path.join(projectDir, this.PACKAGE_JSON));
215
+ if (!packageJson)
216
+ return undefined;
217
+ return packageJson[fieldName];
218
+ }
219
+ /**
220
+ * Load and merge all package.lisa.json templates from type hierarchy
221
+ * @remarks
222
+ * Inheritance chain: all → typescript → specific types (expo, nestjs, cdk, npm-package)
223
+ * Child types override parent types in force, defaults, and merge sections.
224
+ * @param lisaDir - Root Lisa directory path
225
+ * @param detectedTypes - Project types to load templates for
226
+ * @returns Merged template with force, defaults, merge sections
227
+ * @private
228
+ */
229
+ async loadAndMergeTemplates(lisaDir, detectedTypes) {
230
+ const initial = {
231
+ force: {},
232
+ defaults: {},
233
+ merge: {},
234
+ };
235
+ // Expand types to include parents (e.g., expo includes typescript)
236
+ const allTypes = this.expandTypeHierarchy(detectedTypes);
237
+ // Process types in order: all, then typescript, then specific types
238
+ const typesToProcess = ["all", ...allTypes];
239
+ // Load and merge all templates using reduce
240
+ // eslint-disable-next-line functional/no-let -- Reassignment needed for async loop
241
+ let accumulator = initial;
242
+ for (const type of typesToProcess) {
243
+ const templatePath = path.join(lisaDir, type, "tagged-merge", "package.lisa.json");
244
+ const template = await readJsonOrNull(templatePath);
245
+ if (!template) {
246
+ // Template doesn't exist for this type; skip
247
+ continue;
248
+ }
249
+ // Merge template into accumulated template (child overrides parent)
250
+ accumulator = this.mergeTemplates(accumulator, template);
251
+ }
252
+ return accumulator;
253
+ }
254
+ /**
255
+ * Expand project types to include parent types
256
+ * @remarks
257
+ * Type hierarchy: expo/nestjs/cdk/npm-package inherit from typescript
258
+ * This expands a list to include parents.
259
+ * Example: [expo] → [typescript, expo]
260
+ * @param types - Project types detected
261
+ * @returns Expanded types including parents
262
+ * @private
263
+ */
264
+ expandTypeHierarchy(types) {
265
+ const allTypes = new Set(types);
266
+ for (const type of types) {
267
+ const parent = PROJECT_TYPE_HIERARCHY[type];
268
+ if (parent) {
269
+ allTypes.add(parent);
270
+ }
271
+ }
272
+ return Array.from(allTypes);
273
+ }
274
+ /**
275
+ * Merge two template objects
276
+ * Child template (override) values win in force and defaults.
277
+ * Merge arrays are concatenated without deduplication at merge time.
278
+ * @param parent - Parent template (e.g., "all" or "typescript")
279
+ * @param child - Child template (e.g., "expo") that overrides parent
280
+ * @returns Merged template
281
+ * @private
282
+ */
283
+ mergeTemplates(parent, child) {
284
+ return {
285
+ force: deepMerge(parent.force, child.force || {}),
286
+ defaults: deepMerge(parent.defaults, child.defaults || {}),
287
+ merge: this.mergeMergeSections(parent.merge, child.merge || {}),
288
+ };
289
+ }
290
+ /**
291
+ * Merge two merge-section objects
292
+ * Arrays are concatenated (deduplication happens later when applied to package.json)
293
+ * @param parent - Parent merge sections
294
+ * @param child - Child merge sections
295
+ * @returns Merged sections
296
+ * @private
297
+ */
298
+ mergeMergeSections(parent, child) {
299
+ const result = { ...parent };
300
+ for (const [key, value] of Object.entries(child)) {
301
+ if (key in result) {
302
+ // Concatenate arrays
303
+ const existing = result[key];
304
+ result[key] = [...existing, ...value];
305
+ }
306
+ else {
307
+ result[key] = value;
308
+ }
309
+ }
310
+ return result;
311
+ }
312
+ /**
313
+ * Apply force/defaults/merge logic to project's package.json
314
+ * @remarks
315
+ * Processing order:
316
+ * 1. Apply force: Deep merge with Lisa values winning (entire section replaced)
317
+ * 2. Apply defaults: Deep merge with project values winning (only set if missing)
318
+ * 3. Apply merge: Concatenate arrays and deduplicate
319
+ * @param projectJson - Current project's package.json
320
+ * @param template - Merged package.lisa.json template
321
+ * @returns Modified package.json
322
+ * @private
323
+ */
324
+ applyTemplate(projectJson, template) {
325
+ // Phase 1: Apply force (Lisa's values completely replace project's)
326
+ const afterForce = deepMerge(projectJson, template.force);
327
+ // Phase 2: Apply defaults (project's values preserved, Lisa provides fallback)
328
+ const afterDefaults = deepMerge(template.defaults, afterForce);
329
+ // Phase 3: Apply merge (concatenate and deduplicate arrays)
330
+ return this.applyMergeSections(afterDefaults, template.merge);
331
+ }
332
+ /**
333
+ * Apply merge-section arrays to package.json
334
+ * Concatenates Lisa's items and project's items, deduplicated by JSON.stringify equality.
335
+ * @param packageJson - Current package.json after force/defaults applied
336
+ * @param mergeSections - Merge sections from template
337
+ * @returns Package.json with merge sections applied
338
+ * @private
339
+ */
340
+ applyMergeSections(packageJson, mergeSections) {
341
+ const result = { ...packageJson };
342
+ for (const [key, lisaItems] of Object.entries(mergeSections)) {
343
+ const projectItems = result[key] || [];
344
+ if (!Array.isArray(projectItems)) {
345
+ // If the field exists but isn't an array, replace it with Lisa's items
346
+ result[key] = lisaItems;
347
+ continue;
348
+ }
349
+ // Concatenate and deduplicate: Lisa items first, then project's unique items
350
+ result[key] = this.deduplicateArrays(lisaItems, projectItems);
351
+ }
352
+ return result;
353
+ }
354
+ /**
355
+ * Concatenate two arrays and remove duplicates
356
+ * Uses JSON.stringify for value equality comparison.
357
+ * Lisa items come first, then project's unique items.
358
+ * @param lisaItems - Lisa's items (come first)
359
+ * @param projectItems - Project's items (added if not already present)
360
+ * @returns Deduplicated array
361
+ * @private
362
+ */
363
+ deduplicateArrays(lisaItems, projectItems) {
364
+ const seen = new Set();
365
+ const result = [];
366
+ // Add Lisa items first
367
+ for (const item of lisaItems) {
368
+ const key = JSON.stringify(item);
369
+ if (!seen.has(key)) {
370
+ seen.add(key);
371
+ result.push(item);
372
+ }
373
+ }
374
+ // Add project's unique items
375
+ for (const item of projectItems) {
376
+ const key = JSON.stringify(item);
377
+ if (!seen.has(key)) {
378
+ seen.add(key);
379
+ result.push(item);
380
+ }
381
+ }
382
+ return result;
383
+ }
384
+ }
385
+ //# sourceMappingURL=package-lisa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-lisa.js","sourceRoot":"","sources":["../../src/strategies/package-lisa.ts"],"names":[],"mappings":"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"}
@@ -39,12 +39,49 @@ export declare class TaggedMergeStrategy implements ICopyStrategy {
39
39
  * @param dest - Project JSON with potential customizations to preserve
40
40
  * @returns Merged JSON with tagged sections applied according to their behavior types
41
41
  * @remarks
42
- * Processing order: 1) Process all tagged sections from source applying their behaviors,
43
- * 2) Add unprocessed content from destination (preserves project customizations),
44
- * 3) Add any remaining unprocessed tags from source. This ensures governance while
45
- * preserving project-specific additions outside tagged regions.
42
+ * Processing supports tags at any nesting level. For each tagged section (whether at
43
+ * top level or nested in an object), applies its behavior rules. Order of processing:
44
+ * 1) Process all tagged sections from source recursively, applying their behaviors
45
+ * 2) Add unprocessed content from destination (preserves project customizations)
46
+ * 3) Add any remaining unprocessed tags from source
47
+ * This ensures governance while preserving project-specific additions outside tagged regions.
46
48
  */
47
49
  private mergeWithTags;
50
+ /**
51
+ * Process an object that might contain nested tags
52
+ * @param key - The key of the object to process
53
+ * @param source - Source object containing the nested object
54
+ * @param dest - Destination object containing potential counterpart
55
+ * @param result - Result object being built
56
+ * @param processed - Set of processed keys
57
+ */
58
+ private processNestedTaggedObject;
59
+ /**
60
+ * Check if a value is a plain object (not array, null, or primitive)
61
+ * @param value - Value to check
62
+ * @returns True if value is a plain object
63
+ */
64
+ private isPlainObject;
65
+ /**
66
+ * Check if an object contains any nested tags
67
+ * @param obj - Object to check
68
+ * @returns True if object has opening tags as properties
69
+ */
70
+ private hasNestedTags;
71
+ /**
72
+ * Get the destination object for a key, or empty object if not found
73
+ * @param dest - Destination object
74
+ * @param key - Key to look for
75
+ * @returns Destination object or empty object
76
+ */
77
+ private getDestinationObject;
78
+ /**
79
+ * Merge an object that may contain nested tags
80
+ * @param source - Source object potentially containing tags
81
+ * @param dest - Destination object to merge with
82
+ * @returns Merged object with tags applied appropriately
83
+ */
84
+ private mergeObjectWithNestedTags;
48
85
  /**
49
86
  * Preserve project customizations by adding untagged destination content to result
50
87
  * @param result - Result object being built
@@ -1 +1 @@
1
- {"version":3,"file":"tagged-merge.d.ts","sourceRoot":"","sources":["../../src/strategies/tagged-merge.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAM9E;;;;;;;;;;;;GAYG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IAExC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4C;IAEvE;;;;;;;;;;;OAWG;IACG,KAAK,CACT,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;IAmD/B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,aAAa;IA4BrB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,qBAAqB;IAiB7B;;;;;;;;;OASG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,oBAAoB;IAsC5B;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAa5B;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAwB1B;;;;;;OAMG;IACH,OAAO,CAAC,gCAAgC;IAqBxC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAIhB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IASxB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAwB7B;;;;;;OAMG;IACH,OAAO,CAAC,2BAA2B;CAUpC"}
1
+ {"version":3,"file":"tagged-merge.d.ts","sourceRoot":"","sources":["../../src/strategies/tagged-merge.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAM9E;;;;;;;;;;;;GAYG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAG,cAAc,CAAU;IAExC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4C;IAEvE;;;;;;;;;;;OAWG;IACG,KAAK,CACT,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;IAmD/B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,aAAa;IAoCrB;;;;;;;OAOG;IACH,OAAO,CAAC,yBAAyB;IAyBjC;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAU5B;;;;;OAKG;IACH,OAAO,CAAC,yBAAyB;IAwCjC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,qBAAqB;IAiB7B;;;;;;;;;OASG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,oBAAoB;IAsC5B;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,oBAAoB;IAa5B;;;;;;;OAOG;IACH,OAAO,CAAC,kBAAkB;IAwB1B;;;;;;OAMG;IACH,OAAO,CAAC,gCAAgC;IAqBxC;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAIhB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IASxB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAwB7B;;;;;;OAMG;IACH,OAAO,CAAC,2BAA2B;CAUpC"}