@codyswann/lisa 1.9.3 → 1.9.4
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/README.md +59 -2
- package/all/copy-overwrite/CLAUDE.md +2 -3
- package/cdk/copy-overwrite/eslint.slow.config.ts +5 -0
- package/cdk/copy-overwrite/knip.json +0 -1
- package/cdk/tagged-merge/bin/infrastructure.js +16 -0
- package/cdk/tagged-merge/package.json +37 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +1 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +2 -1
- package/dist/core/lisa.js.map +1 -1
- package/dist/strategies/index.d.ts +1 -0
- package/dist/strategies/index.d.ts.map +1 -1
- package/dist/strategies/index.js +3 -0
- package/dist/strategies/index.js.map +1 -1
- package/dist/strategies/tagged-merge-types.d.ts +30 -0
- package/dist/strategies/tagged-merge-types.d.ts.map +1 -0
- package/dist/strategies/tagged-merge-types.js +7 -0
- package/dist/strategies/tagged-merge-types.js.map +1 -0
- package/dist/strategies/tagged-merge.d.ts +206 -0
- package/dist/strategies/tagged-merge.d.ts.map +1 -0
- package/dist/strategies/tagged-merge.js +421 -0
- package/dist/strategies/tagged-merge.js.map +1 -0
- package/expo/copy-overwrite/eslint.slow.config.ts +5 -0
- package/expo/copy-overwrite/knip.json +0 -1
- package/expo/{merge → tagged-merge}/package.json +28 -28
- package/nestjs/{merge → tagged-merge}/package.json +28 -24
- package/package.json +1 -8
- package/typescript/copy-overwrite/eslint.slow.config.ts +6 -0
- package/typescript/copy-overwrite/knip.json +0 -1
- package/typescript/{merge → tagged-merge}/package.json +23 -21
- package/cdk/merge/package.json +0 -36
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import type { FileOperationResult } from "../core/config.js";
|
|
2
|
+
import type { ICopyStrategy, StrategyContext } from "./strategy.interface.js";
|
|
3
|
+
/**
|
|
4
|
+
* Implements tagged merge strategy for JSON files with comment-based section control
|
|
5
|
+
* @remarks
|
|
6
|
+
* Supports three tag behaviors:
|
|
7
|
+
* - `//lisa-force-*`: Lisa replaces entire section, project changes ignored (for governance)
|
|
8
|
+
* - `//lisa-defaults-*`: Lisa provides values, project can override (for sensible defaults)
|
|
9
|
+
* - `//lisa-merge-*`: For arrays - combine Lisa's + project's items deduplicated (for shared lists)
|
|
10
|
+
*
|
|
11
|
+
* Tag format: `//lisa-<behavior>-<category>` with matching `//end-lisa-<behavior>-<category>`
|
|
12
|
+
*
|
|
13
|
+
* Order preservation: JSON key ordering is maintained throughout the merge process,
|
|
14
|
+
* ensuring deterministic output and minimal diff noise when configs change.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TaggedMergeStrategy implements ICopyStrategy {
|
|
17
|
+
readonly name: "tagged-merge";
|
|
18
|
+
/**
|
|
19
|
+
* Regex pattern for parsing opening tags
|
|
20
|
+
* @remarks Captures behavior (force|defaults|merge) and category name for routing to appropriate merge logic
|
|
21
|
+
*/
|
|
22
|
+
private readonly tagPattern;
|
|
23
|
+
/**
|
|
24
|
+
* Apply tagged merge strategy to a JSON file
|
|
25
|
+
* @param sourcePath - Absolute path to Lisa template JSON file with tags
|
|
26
|
+
* @param destPath - Absolute path to project JSON file to merge into
|
|
27
|
+
* @param relativePath - Project-relative path for manifest recording and logging
|
|
28
|
+
* @param context - Strategy context with config, manifest recording, and backup functions
|
|
29
|
+
* @returns Operation result indicating copied, skipped, or merged action
|
|
30
|
+
* @throws JsonMergeError if source or destination JSON cannot be parsed
|
|
31
|
+
* @remarks
|
|
32
|
+
* When destination doesn't exist, copies source directly. When destination exists,
|
|
33
|
+
* performs tagged merge preserving project customizations outside tagged sections.
|
|
34
|
+
*/
|
|
35
|
+
apply(sourcePath: string, destPath: string, relativePath: string, context: StrategyContext): Promise<FileOperationResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Merge source and destination JSON using tagged sections
|
|
38
|
+
* @param source - Lisa template JSON containing tag markers and governed content
|
|
39
|
+
* @param dest - Project JSON with potential customizations to preserve
|
|
40
|
+
* @returns Merged JSON with tagged sections applied according to their behavior types
|
|
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.
|
|
46
|
+
*/
|
|
47
|
+
private mergeWithTags;
|
|
48
|
+
/**
|
|
49
|
+
* Preserve project customizations by adding untagged destination content to result
|
|
50
|
+
* @param result - Result object being built
|
|
51
|
+
* @param dest - Project JSON containing potential customizations
|
|
52
|
+
* @param processed - Keys already processed via tagged sections (to avoid duplicates)
|
|
53
|
+
* @param processedTags - Tag keys already processed (to avoid duplicates)
|
|
54
|
+
* @remarks
|
|
55
|
+
* This is the key step that preserves project freedom: any content outside tagged
|
|
56
|
+
* regions is copied from the project's file unchanged, allowing custom scripts,
|
|
57
|
+
* dependencies, or configs that Lisa doesn't govern.
|
|
58
|
+
*/
|
|
59
|
+
private addUnprocessedContent;
|
|
60
|
+
/**
|
|
61
|
+
* Add any remaining tag keys from source that weren't part of complete tag pairs
|
|
62
|
+
* @param result - Result object being built
|
|
63
|
+
* @param source - Lisa template JSON
|
|
64
|
+
* @param processedTags - Tag keys already processed as part of complete sections
|
|
65
|
+
* @param processed - Content keys already processed
|
|
66
|
+
* @remarks
|
|
67
|
+
* Handles edge case of orphaned tags (e.g., opening tag without closing tag)
|
|
68
|
+
* by preserving them in output rather than silently dropping them.
|
|
69
|
+
*/
|
|
70
|
+
private addUnprocessedTags;
|
|
71
|
+
/**
|
|
72
|
+
* Process a single tagged section, routing to appropriate behavior handler
|
|
73
|
+
* @param key - Opening tag key (e.g., `//lisa-force-scripts`)
|
|
74
|
+
* @param source - Lisa template JSON
|
|
75
|
+
* @param dest - Project JSON
|
|
76
|
+
* @param sourceTags - Map of all parsed tag sections from source
|
|
77
|
+
* @param result - Result object being built
|
|
78
|
+
* @param processed - Set tracking processed content keys
|
|
79
|
+
* @param processedTags - Set tracking processed tag keys
|
|
80
|
+
* @remarks
|
|
81
|
+
* Routes to applyForceSection, applyDefaultsSection, or applyMergeSection
|
|
82
|
+
* based on the behavior extracted from the tag. All keys within the section
|
|
83
|
+
* (including opening/closing tags) are marked as processed to prevent
|
|
84
|
+
* duplicate handling in subsequent steps.
|
|
85
|
+
*/
|
|
86
|
+
private processTaggedSection;
|
|
87
|
+
/**
|
|
88
|
+
* Parse JSON object to extract all tagged sections with their boundaries
|
|
89
|
+
* @param obj - JSON object to parse for tag markers
|
|
90
|
+
* @returns Map of opening tag keys to section info (behavior, category, content keys, close key)
|
|
91
|
+
* @remarks
|
|
92
|
+
* Relies on JSON key ordering being preserved (standard in modern JS engines).
|
|
93
|
+
* Skips sections without matching closing tags to handle malformed input gracefully.
|
|
94
|
+
*/
|
|
95
|
+
private parseTaggedSections;
|
|
96
|
+
/**
|
|
97
|
+
* Apply force behavior: Lisa's section replaces project's entirely
|
|
98
|
+
* @param result - Result object being built
|
|
99
|
+
* @param source - Lisa template containing the authoritative values
|
|
100
|
+
* @param section - Section info with content keys to copy
|
|
101
|
+
* @remarks
|
|
102
|
+
* Use force for governance-critical configs that projects must not override,
|
|
103
|
+
* such as CI/CD scripts, required linting commands, or mandatory dev dependencies.
|
|
104
|
+
* Project changes within force-tagged sections are discarded during merge.
|
|
105
|
+
*/
|
|
106
|
+
private applyForceSection;
|
|
107
|
+
/**
|
|
108
|
+
* Apply defaults behavior: project's values take precedence if they exist
|
|
109
|
+
* @param result - Result object being built
|
|
110
|
+
* @param source - Lisa template with default values
|
|
111
|
+
* @param dest - Project JSON with potential overrides
|
|
112
|
+
* @param section - Section info from source
|
|
113
|
+
* @param category - Tag category name for looking up destination section
|
|
114
|
+
* @remarks
|
|
115
|
+
* Use defaults for sensible starting values that projects may legitimately need
|
|
116
|
+
* to customize, such as engine versions or optional configurations. If project
|
|
117
|
+
* has the same tagged section, its content is used; otherwise Lisa's defaults apply.
|
|
118
|
+
*/
|
|
119
|
+
private applyDefaultsSection;
|
|
120
|
+
/**
|
|
121
|
+
* Add defaults section content, preferring project's version if it has content
|
|
122
|
+
* @param result - Result object being built
|
|
123
|
+
* @param source - Lisa template with fallback values
|
|
124
|
+
* @param dest - Project JSON with potential overrides
|
|
125
|
+
* @param section - Section info from source
|
|
126
|
+
* @param category - Tag category name
|
|
127
|
+
*/
|
|
128
|
+
private addDefaultsContent;
|
|
129
|
+
/**
|
|
130
|
+
* Locate and extract the matching tagged section from destination JSON
|
|
131
|
+
* @param dest - Project JSON to search for matching tags
|
|
132
|
+
* @param section - Source section info containing behavior type
|
|
133
|
+
* @param category - Tag category name to match
|
|
134
|
+
* @returns Extracted section info if found, undefined if project lacks the section
|
|
135
|
+
*/
|
|
136
|
+
private findAndExtractDestinationSection;
|
|
137
|
+
/**
|
|
138
|
+
* Copy content keys from source template to result
|
|
139
|
+
* @param result - Result object being built
|
|
140
|
+
* @param source - Lisa template containing values to copy
|
|
141
|
+
* @param contentKeys - Keys to copy from source
|
|
142
|
+
*/
|
|
143
|
+
private addSourceContent;
|
|
144
|
+
/**
|
|
145
|
+
* Apply merge behavior: combine arrays from source and dest without duplicates
|
|
146
|
+
* @param result - Result object being built
|
|
147
|
+
* @param source - Lisa template with base array items
|
|
148
|
+
* @param dest - Project JSON with additional array items
|
|
149
|
+
* @param section - Section info with content keys
|
|
150
|
+
* @param category - Tag category name
|
|
151
|
+
* @remarks
|
|
152
|
+
* Use merge for shared lists where both Lisa and projects contribute items,
|
|
153
|
+
* such as trustedDependencies. Lisa's items come first, then project's unique
|
|
154
|
+
* additions. Deduplication uses JSON.stringify for value equality comparison.
|
|
155
|
+
*/
|
|
156
|
+
private applyMergeSection;
|
|
157
|
+
/**
|
|
158
|
+
* Combine two arrays, removing duplicates while preserving order
|
|
159
|
+
* @param sourceArray - Lisa template array (items added first)
|
|
160
|
+
* @param destArray - Project array (unique items added after)
|
|
161
|
+
* @returns Combined array with source items first, then project's unique additions
|
|
162
|
+
* @remarks
|
|
163
|
+
* Uses JSON.stringify for value equality, so objects/arrays with same content
|
|
164
|
+
* are considered duplicates. This allows deduplicating complex items like
|
|
165
|
+
* package names with version specifiers.
|
|
166
|
+
*/
|
|
167
|
+
private deduplicateArrays;
|
|
168
|
+
/**
|
|
169
|
+
* Test if a key is an opening tag (matches `//lisa-<behavior>-<category>` format)
|
|
170
|
+
* @param key - JSON key to test
|
|
171
|
+
* @returns True if key matches the opening tag pattern
|
|
172
|
+
*/
|
|
173
|
+
private isOpeningTag;
|
|
174
|
+
/**
|
|
175
|
+
* Test if a key is any tag-like comment key (starts with `//`)
|
|
176
|
+
* @param key - JSON key to test
|
|
177
|
+
* @returns True if key is a JSON comment (convention used for documentation/tags)
|
|
178
|
+
*/
|
|
179
|
+
private isTagKey;
|
|
180
|
+
/**
|
|
181
|
+
* Find opening tag key for a given behavior and category in an object
|
|
182
|
+
* @param obj - Object to search for the tag
|
|
183
|
+
* @param behavior - Tag behavior type (force, defaults, merge)
|
|
184
|
+
* @param category - Tag category name
|
|
185
|
+
* @returns Tag key string if found, undefined if object lacks this tag
|
|
186
|
+
*/
|
|
187
|
+
private findSectionStart;
|
|
188
|
+
/**
|
|
189
|
+
* Extract section boundaries and content keys between opening and closing tags
|
|
190
|
+
* @param obj - Object containing the tagged section
|
|
191
|
+
* @param startKey - Opening tag key that marks section start
|
|
192
|
+
* @param behavior - Tag behavior type (for constructing close key)
|
|
193
|
+
* @param category - Tag category name (for constructing close key)
|
|
194
|
+
* @returns Complete section info including content keys between tags
|
|
195
|
+
*/
|
|
196
|
+
private extractSectionContent;
|
|
197
|
+
/**
|
|
198
|
+
* Extract keys between opening and closing tag indices
|
|
199
|
+
* @param startIndex - Index of opening tag in keys array
|
|
200
|
+
* @param closeIndex - Index of closing tag in keys array
|
|
201
|
+
* @param keys - Ordered array of all keys in the object
|
|
202
|
+
* @returns Array of content keys between the tags, empty if indices invalid
|
|
203
|
+
*/
|
|
204
|
+
private extractContentKeysFromRange;
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=tagged-merge.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file tagged-merge.ts
|
|
3
|
+
* @description Copy strategy for JSON files using comment-based tags for section-level control
|
|
4
|
+
* @module strategies
|
|
5
|
+
* @remarks
|
|
6
|
+
* This strategy solves a limitation of the regular merge strategy: the inability to
|
|
7
|
+
* force certain values while allowing project overrides in other sections of the same file.
|
|
8
|
+
* By using comment tags as section markers, Lisa can govern critical configs (CI/CD scripts,
|
|
9
|
+
* required dependencies) while projects retain freedom to customize other areas.
|
|
10
|
+
*/
|
|
11
|
+
/* eslint-disable max-lines -- Large complex strategy with many helper methods */
|
|
12
|
+
import * as fse from "fs-extra";
|
|
13
|
+
import { copyFile } from "node:fs/promises";
|
|
14
|
+
import { ensureParentDir } from "../utils/file-operations.js";
|
|
15
|
+
import { readJson, writeJson } from "../utils/json-utils.js";
|
|
16
|
+
import { JsonMergeError } from "../errors/index.js";
|
|
17
|
+
/**
|
|
18
|
+
* Implements tagged merge strategy for JSON files with comment-based section control
|
|
19
|
+
* @remarks
|
|
20
|
+
* Supports three tag behaviors:
|
|
21
|
+
* - `//lisa-force-*`: Lisa replaces entire section, project changes ignored (for governance)
|
|
22
|
+
* - `//lisa-defaults-*`: Lisa provides values, project can override (for sensible defaults)
|
|
23
|
+
* - `//lisa-merge-*`: For arrays - combine Lisa's + project's items deduplicated (for shared lists)
|
|
24
|
+
*
|
|
25
|
+
* Tag format: `//lisa-<behavior>-<category>` with matching `//end-lisa-<behavior>-<category>`
|
|
26
|
+
*
|
|
27
|
+
* Order preservation: JSON key ordering is maintained throughout the merge process,
|
|
28
|
+
* ensuring deterministic output and minimal diff noise when configs change.
|
|
29
|
+
*/
|
|
30
|
+
export class TaggedMergeStrategy {
|
|
31
|
+
name = "tagged-merge";
|
|
32
|
+
/**
|
|
33
|
+
* Regex pattern for parsing opening tags
|
|
34
|
+
* @remarks Captures behavior (force|defaults|merge) and category name for routing to appropriate merge logic
|
|
35
|
+
*/
|
|
36
|
+
tagPattern = /^\/\/lisa-(force|defaults|merge)-(.+)$/;
|
|
37
|
+
/**
|
|
38
|
+
* Apply tagged merge strategy to a JSON file
|
|
39
|
+
* @param sourcePath - Absolute path to Lisa template JSON file with tags
|
|
40
|
+
* @param destPath - Absolute path to project JSON file to merge into
|
|
41
|
+
* @param relativePath - Project-relative path for manifest recording and logging
|
|
42
|
+
* @param context - Strategy context with config, manifest recording, and backup functions
|
|
43
|
+
* @returns Operation result indicating copied, skipped, or merged action
|
|
44
|
+
* @throws JsonMergeError if source or destination JSON cannot be parsed
|
|
45
|
+
* @remarks
|
|
46
|
+
* When destination doesn't exist, copies source directly. When destination exists,
|
|
47
|
+
* performs tagged merge preserving project customizations outside tagged sections.
|
|
48
|
+
*/
|
|
49
|
+
async apply(sourcePath, destPath, relativePath, context) {
|
|
50
|
+
const { config, recordFile, backupFile } = context;
|
|
51
|
+
const destExists = await fse.pathExists(destPath);
|
|
52
|
+
if (!destExists) {
|
|
53
|
+
if (!config.dryRun) {
|
|
54
|
+
await ensureParentDir(destPath);
|
|
55
|
+
await copyFile(sourcePath, destPath);
|
|
56
|
+
recordFile(relativePath, this.name);
|
|
57
|
+
}
|
|
58
|
+
return { relativePath, strategy: this.name, action: "copied" };
|
|
59
|
+
}
|
|
60
|
+
const sourceJson = await readJson(sourcePath).catch(() => {
|
|
61
|
+
throw new JsonMergeError(relativePath, `Failed to parse source: ${sourcePath}`);
|
|
62
|
+
});
|
|
63
|
+
const destJson = await readJson(destPath).catch(() => {
|
|
64
|
+
throw new JsonMergeError(relativePath, `Failed to parse destination: ${destPath}`);
|
|
65
|
+
});
|
|
66
|
+
const merged = this.mergeWithTags(sourceJson, destJson);
|
|
67
|
+
const normalizedDest = JSON.stringify(destJson, null, 2);
|
|
68
|
+
const normalizedMerged = JSON.stringify(merged, null, 2);
|
|
69
|
+
if (normalizedDest === normalizedMerged) {
|
|
70
|
+
if (!config.dryRun) {
|
|
71
|
+
recordFile(relativePath, this.name);
|
|
72
|
+
}
|
|
73
|
+
return { relativePath, strategy: this.name, action: "skipped" };
|
|
74
|
+
}
|
|
75
|
+
if (!config.dryRun) {
|
|
76
|
+
await backupFile(destPath);
|
|
77
|
+
await writeJson(destPath, merged);
|
|
78
|
+
recordFile(relativePath, this.name);
|
|
79
|
+
}
|
|
80
|
+
return { relativePath, strategy: this.name, action: "merged" };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Merge source and destination JSON using tagged sections
|
|
84
|
+
* @param source - Lisa template JSON containing tag markers and governed content
|
|
85
|
+
* @param dest - Project JSON with potential customizations to preserve
|
|
86
|
+
* @returns Merged JSON with tagged sections applied according to their behavior types
|
|
87
|
+
* @remarks
|
|
88
|
+
* Processing order: 1) Process all tagged sections from source applying their behaviors,
|
|
89
|
+
* 2) Add unprocessed content from destination (preserves project customizations),
|
|
90
|
+
* 3) Add any remaining unprocessed tags from source. This ensures governance while
|
|
91
|
+
* preserving project-specific additions outside tagged regions.
|
|
92
|
+
*/
|
|
93
|
+
mergeWithTags(source, dest) {
|
|
94
|
+
const sourceTags = this.parseTaggedSections(source);
|
|
95
|
+
const result = {};
|
|
96
|
+
const processed = new Set();
|
|
97
|
+
const processedTags = new Set();
|
|
98
|
+
for (const key in source) {
|
|
99
|
+
if (this.isOpeningTag(key)) {
|
|
100
|
+
this.processTaggedSection(key, source, dest, sourceTags, result, processed, processedTags);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
this.addUnprocessedContent(result, dest, processed, processedTags);
|
|
104
|
+
this.addUnprocessedTags(result, source, processedTags, processed);
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Preserve project customizations by adding untagged destination content to result
|
|
109
|
+
* @param result - Result object being built
|
|
110
|
+
* @param dest - Project JSON containing potential customizations
|
|
111
|
+
* @param processed - Keys already processed via tagged sections (to avoid duplicates)
|
|
112
|
+
* @param processedTags - Tag keys already processed (to avoid duplicates)
|
|
113
|
+
* @remarks
|
|
114
|
+
* This is the key step that preserves project freedom: any content outside tagged
|
|
115
|
+
* regions is copied from the project's file unchanged, allowing custom scripts,
|
|
116
|
+
* dependencies, or configs that Lisa doesn't govern.
|
|
117
|
+
*/
|
|
118
|
+
addUnprocessedContent(result, dest, processed, processedTags) {
|
|
119
|
+
for (const key in dest) {
|
|
120
|
+
if (!processed.has(key) &&
|
|
121
|
+
!processedTags.has(key) &&
|
|
122
|
+
!this.isTagKey(key)) {
|
|
123
|
+
result[key] = dest[key];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Add any remaining tag keys from source that weren't part of complete tag pairs
|
|
129
|
+
* @param result - Result object being built
|
|
130
|
+
* @param source - Lisa template JSON
|
|
131
|
+
* @param processedTags - Tag keys already processed as part of complete sections
|
|
132
|
+
* @param processed - Content keys already processed
|
|
133
|
+
* @remarks
|
|
134
|
+
* Handles edge case of orphaned tags (e.g., opening tag without closing tag)
|
|
135
|
+
* by preserving them in output rather than silently dropping them.
|
|
136
|
+
*/
|
|
137
|
+
addUnprocessedTags(result, source, processedTags, processed) {
|
|
138
|
+
for (const key in source) {
|
|
139
|
+
if (this.isTagKey(key) &&
|
|
140
|
+
!processedTags.has(key) &&
|
|
141
|
+
!processed.has(key)) {
|
|
142
|
+
result[key] = source[key];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Process a single tagged section, routing to appropriate behavior handler
|
|
148
|
+
* @param key - Opening tag key (e.g., `//lisa-force-scripts`)
|
|
149
|
+
* @param source - Lisa template JSON
|
|
150
|
+
* @param dest - Project JSON
|
|
151
|
+
* @param sourceTags - Map of all parsed tag sections from source
|
|
152
|
+
* @param result - Result object being built
|
|
153
|
+
* @param processed - Set tracking processed content keys
|
|
154
|
+
* @param processedTags - Set tracking processed tag keys
|
|
155
|
+
* @remarks
|
|
156
|
+
* Routes to applyForceSection, applyDefaultsSection, or applyMergeSection
|
|
157
|
+
* based on the behavior extracted from the tag. All keys within the section
|
|
158
|
+
* (including opening/closing tags) are marked as processed to prevent
|
|
159
|
+
* duplicate handling in subsequent steps.
|
|
160
|
+
*/
|
|
161
|
+
processTaggedSection(key, source, dest, sourceTags, result, processed, processedTags) {
|
|
162
|
+
const tagMatch = this.tagPattern.exec(key);
|
|
163
|
+
if (!tagMatch || !tagMatch[2])
|
|
164
|
+
return;
|
|
165
|
+
const behavior = tagMatch[1];
|
|
166
|
+
const category = tagMatch[2];
|
|
167
|
+
const section = sourceTags.get(key);
|
|
168
|
+
if (!section)
|
|
169
|
+
return;
|
|
170
|
+
processedTags.add(key);
|
|
171
|
+
processedTags.add(section.closeKey);
|
|
172
|
+
for (const contentKey of section.contentKeys) {
|
|
173
|
+
processedTags.add(contentKey);
|
|
174
|
+
}
|
|
175
|
+
if (behavior === "force") {
|
|
176
|
+
this.applyForceSection(result, source, section);
|
|
177
|
+
}
|
|
178
|
+
else if (behavior === "defaults") {
|
|
179
|
+
this.applyDefaultsSection(result, source, dest, section, category);
|
|
180
|
+
}
|
|
181
|
+
else if (behavior === "merge") {
|
|
182
|
+
this.applyMergeSection(result, source, dest, section, category);
|
|
183
|
+
}
|
|
184
|
+
for (const contentKey of section.contentKeys) {
|
|
185
|
+
processed.add(contentKey);
|
|
186
|
+
}
|
|
187
|
+
processed.add(key);
|
|
188
|
+
processed.add(section.closeKey);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Parse JSON object to extract all tagged sections with their boundaries
|
|
192
|
+
* @param obj - JSON object to parse for tag markers
|
|
193
|
+
* @returns Map of opening tag keys to section info (behavior, category, content keys, close key)
|
|
194
|
+
* @remarks
|
|
195
|
+
* Relies on JSON key ordering being preserved (standard in modern JS engines).
|
|
196
|
+
* Skips sections without matching closing tags to handle malformed input gracefully.
|
|
197
|
+
*/
|
|
198
|
+
parseTaggedSections(obj) {
|
|
199
|
+
const sections = new Map();
|
|
200
|
+
const keys = Object.keys(obj);
|
|
201
|
+
keys.forEach((key, i) => {
|
|
202
|
+
if (!this.isOpeningTag(key))
|
|
203
|
+
return;
|
|
204
|
+
const match = this.tagPattern.exec(key);
|
|
205
|
+
if (!match || !match[2])
|
|
206
|
+
return;
|
|
207
|
+
const behavior = match[1];
|
|
208
|
+
const category = match[2];
|
|
209
|
+
const closeKey = `//end-lisa-${behavior}-${category}`;
|
|
210
|
+
const closeIndex = keys.indexOf(closeKey);
|
|
211
|
+
if (closeIndex === -1)
|
|
212
|
+
return;
|
|
213
|
+
const contentKeys = keys.slice(i + 1, closeIndex);
|
|
214
|
+
sections.set(key, { behavior, category, contentKeys, closeKey });
|
|
215
|
+
});
|
|
216
|
+
return sections;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Apply force behavior: Lisa's section replaces project's entirely
|
|
220
|
+
* @param result - Result object being built
|
|
221
|
+
* @param source - Lisa template containing the authoritative values
|
|
222
|
+
* @param section - Section info with content keys to copy
|
|
223
|
+
* @remarks
|
|
224
|
+
* Use force for governance-critical configs that projects must not override,
|
|
225
|
+
* such as CI/CD scripts, required linting commands, or mandatory dev dependencies.
|
|
226
|
+
* Project changes within force-tagged sections are discarded during merge.
|
|
227
|
+
*/
|
|
228
|
+
applyForceSection(result, source, section) {
|
|
229
|
+
const openKey = `//lisa-${section.behavior}-${section.category}`;
|
|
230
|
+
result[openKey] = source[openKey];
|
|
231
|
+
for (const key of section.contentKeys) {
|
|
232
|
+
result[key] = source[key];
|
|
233
|
+
}
|
|
234
|
+
result[section.closeKey] = source[section.closeKey];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Apply defaults behavior: project's values take precedence if they exist
|
|
238
|
+
* @param result - Result object being built
|
|
239
|
+
* @param source - Lisa template with default values
|
|
240
|
+
* @param dest - Project JSON with potential overrides
|
|
241
|
+
* @param section - Section info from source
|
|
242
|
+
* @param category - Tag category name for looking up destination section
|
|
243
|
+
* @remarks
|
|
244
|
+
* Use defaults for sensible starting values that projects may legitimately need
|
|
245
|
+
* to customize, such as engine versions or optional configurations. If project
|
|
246
|
+
* has the same tagged section, its content is used; otherwise Lisa's defaults apply.
|
|
247
|
+
*/
|
|
248
|
+
applyDefaultsSection(result, source, dest, section, category) {
|
|
249
|
+
const openKey = `//lisa-${section.behavior}-${category}`;
|
|
250
|
+
result[openKey] = source[openKey];
|
|
251
|
+
this.addDefaultsContent(result, source, dest, section, category);
|
|
252
|
+
result[section.closeKey] = source[section.closeKey];
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Add defaults section content, preferring project's version if it has content
|
|
256
|
+
* @param result - Result object being built
|
|
257
|
+
* @param source - Lisa template with fallback values
|
|
258
|
+
* @param dest - Project JSON with potential overrides
|
|
259
|
+
* @param section - Section info from source
|
|
260
|
+
* @param category - Tag category name
|
|
261
|
+
*/
|
|
262
|
+
addDefaultsContent(result, source, dest, section, category) {
|
|
263
|
+
const destSection = this.findAndExtractDestinationSection(dest, section, category);
|
|
264
|
+
if (destSection && destSection.contentKeys.length > 0) {
|
|
265
|
+
for (const key of destSection.contentKeys) {
|
|
266
|
+
if (key in dest) {
|
|
267
|
+
result[key] = dest[key];
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
this.addSourceContent(result, source, section.contentKeys);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Locate and extract the matching tagged section from destination JSON
|
|
277
|
+
* @param dest - Project JSON to search for matching tags
|
|
278
|
+
* @param section - Source section info containing behavior type
|
|
279
|
+
* @param category - Tag category name to match
|
|
280
|
+
* @returns Extracted section info if found, undefined if project lacks the section
|
|
281
|
+
*/
|
|
282
|
+
findAndExtractDestinationSection(dest, section, category) {
|
|
283
|
+
const destSectionStart = this.findSectionStart(dest, section.behavior, category);
|
|
284
|
+
return destSectionStart
|
|
285
|
+
? this.extractSectionContent(dest, destSectionStart, section.behavior, category)
|
|
286
|
+
: undefined;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Copy content keys from source template to result
|
|
290
|
+
* @param result - Result object being built
|
|
291
|
+
* @param source - Lisa template containing values to copy
|
|
292
|
+
* @param contentKeys - Keys to copy from source
|
|
293
|
+
*/
|
|
294
|
+
addSourceContent(result, source, contentKeys) {
|
|
295
|
+
for (const key of contentKeys) {
|
|
296
|
+
result[key] = source[key];
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Apply merge behavior: combine arrays from source and dest without duplicates
|
|
301
|
+
* @param result - Result object being built
|
|
302
|
+
* @param source - Lisa template with base array items
|
|
303
|
+
* @param dest - Project JSON with additional array items
|
|
304
|
+
* @param section - Section info with content keys
|
|
305
|
+
* @param category - Tag category name
|
|
306
|
+
* @remarks
|
|
307
|
+
* Use merge for shared lists where both Lisa and projects contribute items,
|
|
308
|
+
* such as trustedDependencies. Lisa's items come first, then project's unique
|
|
309
|
+
* additions. Deduplication uses JSON.stringify for value equality comparison.
|
|
310
|
+
*/
|
|
311
|
+
applyMergeSection(result, source, dest, section, category) {
|
|
312
|
+
const openKey = `//lisa-${section.behavior}-${category}`;
|
|
313
|
+
result[openKey] = source[openKey];
|
|
314
|
+
for (const key of section.contentKeys) {
|
|
315
|
+
const sourceValue = source[key];
|
|
316
|
+
const destValue = dest[key];
|
|
317
|
+
if (Array.isArray(sourceValue) && Array.isArray(destValue)) {
|
|
318
|
+
result[key] = this.deduplicateArrays(sourceValue, destValue);
|
|
319
|
+
}
|
|
320
|
+
else if (sourceValue !== undefined) {
|
|
321
|
+
result[key] = sourceValue;
|
|
322
|
+
}
|
|
323
|
+
else if (destValue !== undefined) {
|
|
324
|
+
result[key] = destValue;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
result[section.closeKey] = source[section.closeKey];
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Combine two arrays, removing duplicates while preserving order
|
|
331
|
+
* @param sourceArray - Lisa template array (items added first)
|
|
332
|
+
* @param destArray - Project array (unique items added after)
|
|
333
|
+
* @returns Combined array with source items first, then project's unique additions
|
|
334
|
+
* @remarks
|
|
335
|
+
* Uses JSON.stringify for value equality, so objects/arrays with same content
|
|
336
|
+
* are considered duplicates. This allows deduplicating complex items like
|
|
337
|
+
* package names with version specifiers.
|
|
338
|
+
*/
|
|
339
|
+
deduplicateArrays(sourceArray, destArray) {
|
|
340
|
+
const seen = new Set();
|
|
341
|
+
const result = [];
|
|
342
|
+
for (const item of sourceArray) {
|
|
343
|
+
const key = JSON.stringify(item);
|
|
344
|
+
if (!seen.has(key)) {
|
|
345
|
+
seen.add(key);
|
|
346
|
+
result.push(item);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
for (const item of destArray) {
|
|
350
|
+
const key = JSON.stringify(item);
|
|
351
|
+
if (!seen.has(key)) {
|
|
352
|
+
seen.add(key);
|
|
353
|
+
result.push(item);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return result;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Test if a key is an opening tag (matches `//lisa-<behavior>-<category>` format)
|
|
360
|
+
* @param key - JSON key to test
|
|
361
|
+
* @returns True if key matches the opening tag pattern
|
|
362
|
+
*/
|
|
363
|
+
isOpeningTag(key) {
|
|
364
|
+
return this.tagPattern.test(key);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Test if a key is any tag-like comment key (starts with `//`)
|
|
368
|
+
* @param key - JSON key to test
|
|
369
|
+
* @returns True if key is a JSON comment (convention used for documentation/tags)
|
|
370
|
+
*/
|
|
371
|
+
isTagKey(key) {
|
|
372
|
+
return key.startsWith("//");
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Find opening tag key for a given behavior and category in an object
|
|
376
|
+
* @param obj - Object to search for the tag
|
|
377
|
+
* @param behavior - Tag behavior type (force, defaults, merge)
|
|
378
|
+
* @param category - Tag category name
|
|
379
|
+
* @returns Tag key string if found, undefined if object lacks this tag
|
|
380
|
+
*/
|
|
381
|
+
findSectionStart(obj, behavior, category) {
|
|
382
|
+
const tagKey = `//lisa-${behavior}-${category}`;
|
|
383
|
+
return tagKey in obj ? tagKey : undefined;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Extract section boundaries and content keys between opening and closing tags
|
|
387
|
+
* @param obj - Object containing the tagged section
|
|
388
|
+
* @param startKey - Opening tag key that marks section start
|
|
389
|
+
* @param behavior - Tag behavior type (for constructing close key)
|
|
390
|
+
* @param category - Tag category name (for constructing close key)
|
|
391
|
+
* @returns Complete section info including content keys between tags
|
|
392
|
+
*/
|
|
393
|
+
extractSectionContent(obj, startKey, behavior, category) {
|
|
394
|
+
const closeKey = `//end-lisa-${behavior}-${category}`;
|
|
395
|
+
const keys = Object.keys(obj);
|
|
396
|
+
const startIndex = keys.indexOf(startKey);
|
|
397
|
+
const closeIndex = keys.indexOf(closeKey);
|
|
398
|
+
const contentKeys = this.extractContentKeysFromRange(startIndex, closeIndex, keys);
|
|
399
|
+
return {
|
|
400
|
+
behavior,
|
|
401
|
+
category,
|
|
402
|
+
contentKeys,
|
|
403
|
+
closeKey,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Extract keys between opening and closing tag indices
|
|
408
|
+
* @param startIndex - Index of opening tag in keys array
|
|
409
|
+
* @param closeIndex - Index of closing tag in keys array
|
|
410
|
+
* @param keys - Ordered array of all keys in the object
|
|
411
|
+
* @returns Array of content keys between the tags, empty if indices invalid
|
|
412
|
+
*/
|
|
413
|
+
extractContentKeysFromRange(startIndex, closeIndex, keys) {
|
|
414
|
+
if (startIndex === -1 || closeIndex === -1 || startIndex >= closeIndex) {
|
|
415
|
+
return [];
|
|
416
|
+
}
|
|
417
|
+
return keys.slice(startIndex + 1, closeIndex);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
/* eslint-enable max-lines -- End of TaggedMergeStrategy */
|
|
421
|
+
//# sourceMappingURL=tagged-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagged-merge.js","sourceRoot":"","sources":["../../src/strategies/tagged-merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -55,6 +55,11 @@ export default [
|
|
|
55
55
|
// TypeScript/TSX files - slow import and React rules only
|
|
56
56
|
{
|
|
57
57
|
files: ["**/*.ts", "**/*.tsx"],
|
|
58
|
+
linterOptions: {
|
|
59
|
+
// Ignore inline eslint-disable comments since they reference rules
|
|
60
|
+
// from the main config that aren't loaded in this minimal config
|
|
61
|
+
noInlineConfig: true,
|
|
62
|
+
},
|
|
58
63
|
languageOptions: {
|
|
59
64
|
parser: tseslint.parser,
|
|
60
65
|
parserOptions: {
|