@lsst/pik-plugin-select 0.7.0 → 0.8.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.
- package/README.md +41 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +341 -87
- package/dist/lib/commands/list.d.ts.map +1 -1
- package/dist/lib/commands/profile.d.ts +4 -0
- package/dist/lib/commands/profile.d.ts.map +1 -0
- package/dist/lib/commands/profiles.d.ts +4 -0
- package/dist/lib/commands/profiles.d.ts.map +1 -0
- package/dist/lib/commands/set.d.ts.map +1 -1
- package/dist/lib/commands/switch.d.ts.map +1 -1
- package/dist/lib/plugin.d.ts.map +1 -1
- package/dist/lib/profile/index.d.ts +2 -0
- package/dist/lib/profile/index.d.ts.map +1 -0
- package/dist/lib/profile/profile.d.ts +46 -0
- package/dist/lib/profile/profile.d.ts.map +1 -0
- package/dist/lib/scanner.d.ts +2 -2
- package/dist/lib/scanner.d.ts.map +1 -1
- package/dist/lib/types/profile-status.d.ts +35 -0
- package/dist/lib/types/profile-status.d.ts.map +1 -0
- package/dist/lib/types.d.ts +14 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/validation/requireSelectConfig.d.ts +12 -0
- package/dist/lib/validation/requireSelectConfig.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,6 +40,47 @@ pik select list # List all selectors
|
|
|
40
40
|
pik select set <name> <option> # Set directly
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
## Profiles
|
|
44
|
+
|
|
45
|
+
Switch multiple selectors at once using profiles. Configure them in `pik.config.ts`:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { defineConfig } from '@lsst/pik';
|
|
49
|
+
|
|
50
|
+
export default defineConfig({
|
|
51
|
+
select: {
|
|
52
|
+
include: ['src/**/*.ts', '.env'],
|
|
53
|
+
profiles: {
|
|
54
|
+
dev: {
|
|
55
|
+
Environment: 'Development',
|
|
56
|
+
Database: 'SQLite',
|
|
57
|
+
Theme: 'dark',
|
|
58
|
+
},
|
|
59
|
+
prod: {
|
|
60
|
+
Environment: 'Production',
|
|
61
|
+
Database: 'Postgres',
|
|
62
|
+
Theme: 'light',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Profile Commands
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pik select profiles # List all profiles with their status
|
|
73
|
+
pik select profile # Interactive profile picker
|
|
74
|
+
pik select profile dev # Apply a profile directly
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Profile Status
|
|
78
|
+
|
|
79
|
+
When listing profiles, each shows its status:
|
|
80
|
+
- **Green (●)** - Fully active: all selectors match
|
|
81
|
+
- **Yellow (●)** - Partially active: some selectors match
|
|
82
|
+
- **Gray (○)** - Inactive: no selectors match
|
|
83
|
+
|
|
43
84
|
## Marker Syntax
|
|
44
85
|
|
|
45
86
|
- `@pik:select <name>` - Defines a selector group
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { selectPlugin } from './lib/plugin.js';
|
|
2
|
-
export type { SelectConfig } from './lib/types.js';
|
|
2
|
+
export type { SelectConfig, ProfileMapping, ProfilesConfig } from './lib/types.js';
|
|
3
|
+
export type { ProfileStatus, SelectorMappingStatus } from './lib/types/profile-status.js';
|
|
3
4
|
export { Scanner, type FileResult } from './lib/scanner.js';
|
|
5
|
+
export { Profile, type FoundSelector } from './lib/profile/index.js';
|
|
4
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnF,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAG1F,OAAO,EAAE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG5D,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
import { Parser, loadConfig, BlockSelector } from "@lsst/pik-core";
|
|
2
3
|
import pc from "picocolors";
|
|
3
4
|
import { relative } from "path";
|
|
4
|
-
import { Parser, loadConfig, BlockSwitcher, SingleSwitcher } from "@lsst/pik-core";
|
|
5
5
|
import { readFile, writeFile } from "fs/promises";
|
|
6
6
|
import { glob } from "glob";
|
|
7
7
|
import { select, Separator } from "@inquirer/prompts";
|
|
@@ -27,32 +27,22 @@ class Scanner {
|
|
|
27
27
|
return results;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
function
|
|
31
|
-
return selector.blockOptions.length > 0;
|
|
32
|
-
}
|
|
33
|
-
function getActiveOptionName$1(selector) {
|
|
34
|
-
if (hasBlockOptions$2(selector)) {
|
|
35
|
-
return selector.blockOptions.find((b) => b.isActive)?.name ?? null;
|
|
36
|
-
}
|
|
37
|
-
return selector.options.find((o) => o.isActive)?.name ?? null;
|
|
38
|
-
}
|
|
39
|
-
function getAllOptions$1(selector) {
|
|
40
|
-
if (hasBlockOptions$2(selector)) {
|
|
41
|
-
return selector.blockOptions.map((b) => ({ name: b.name, isActive: b.isActive }));
|
|
42
|
-
}
|
|
43
|
-
return selector.options.map((o) => ({ name: o.name, isActive: o.isActive }));
|
|
44
|
-
}
|
|
45
|
-
const listCommand = new Command("list").alias("ls").description("List all selectors and their current state").option("--json", "Output in JSON format").action(async (options) => {
|
|
46
|
-
const config = await loadConfig();
|
|
30
|
+
function requireSelectConfig(config, options) {
|
|
47
31
|
if (!config?.select) {
|
|
48
|
-
|
|
49
|
-
|
|
32
|
+
const message = 'No pik config found or missing "select" section';
|
|
33
|
+
if (options?.json) {
|
|
34
|
+
console.log(JSON.stringify({ error: message }));
|
|
50
35
|
} else {
|
|
51
|
-
console.error(pc.red(
|
|
36
|
+
console.error(pc.red(message));
|
|
52
37
|
}
|
|
53
38
|
process.exit(1);
|
|
54
39
|
}
|
|
55
|
-
|
|
40
|
+
return config.select;
|
|
41
|
+
}
|
|
42
|
+
const listCommand = new Command("list").alias("ls").description("List all selectors and their current state").option("--json", "Output in JSON format").action(async (options) => {
|
|
43
|
+
const config = await loadConfig();
|
|
44
|
+
const selectConfig = requireSelectConfig(config, options);
|
|
45
|
+
const scanner = new Scanner(selectConfig);
|
|
56
46
|
const results = await scanner.scan();
|
|
57
47
|
if (options.json) {
|
|
58
48
|
const jsonOutput = results.flatMap(
|
|
@@ -60,9 +50,9 @@ const listCommand = new Command("list").alias("ls").description("List all select
|
|
|
60
50
|
name: selector.name,
|
|
61
51
|
file: relative(process.cwd(), file.path),
|
|
62
52
|
line: selector.line,
|
|
63
|
-
activeOption: getActiveOptionName
|
|
64
|
-
isBlock:
|
|
65
|
-
options:
|
|
53
|
+
activeOption: selector.getActiveOptionName(),
|
|
54
|
+
isBlock: selector instanceof BlockSelector,
|
|
55
|
+
options: selector.options.map((o) => ({ name: o.name, isActive: o.isActive }))
|
|
66
56
|
}))
|
|
67
57
|
);
|
|
68
58
|
console.log(JSON.stringify(jsonOutput, null, 2));
|
|
@@ -76,11 +66,11 @@ const listCommand = new Command("list").alias("ls").description("List all select
|
|
|
76
66
|
const relativePath = relative(process.cwd(), file.path);
|
|
77
67
|
console.log(pc.cyan(relativePath));
|
|
78
68
|
for (const selector of file.selectors) {
|
|
79
|
-
const activeOptionName = getActiveOptionName
|
|
69
|
+
const activeOptionName = selector.getActiveOptionName();
|
|
80
70
|
const activeLabel = activeOptionName ? pc.green(activeOptionName) : pc.yellow("none");
|
|
81
|
-
const blockIndicator =
|
|
71
|
+
const blockIndicator = selector instanceof BlockSelector ? pc.dim(" [block]") : "";
|
|
82
72
|
console.log(` ${pc.bold(selector.name)}${blockIndicator}: ${activeLabel}`);
|
|
83
|
-
for (const option of
|
|
73
|
+
for (const option of selector.options) {
|
|
84
74
|
const marker = option.isActive ? pc.green("●") : pc.dim("○");
|
|
85
75
|
console.log(` ${marker} ${option.name}`);
|
|
86
76
|
}
|
|
@@ -88,16 +78,10 @@ const listCommand = new Command("list").alias("ls").description("List all select
|
|
|
88
78
|
console.log();
|
|
89
79
|
}
|
|
90
80
|
});
|
|
91
|
-
function hasBlockOptions$1(selector) {
|
|
92
|
-
return selector.blockOptions.length > 0;
|
|
93
|
-
}
|
|
94
81
|
const setCommand = new Command("set").description("Set a specific option for a selector").argument("<selector>", "Selector name").argument("<option>", "Option to activate").action(async (selectorName, optionName) => {
|
|
95
82
|
const config = await loadConfig();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
const scanner = new Scanner(config.select);
|
|
83
|
+
const selectConfig = requireSelectConfig(config);
|
|
84
|
+
const scanner = new Scanner(selectConfig);
|
|
101
85
|
const results = await scanner.scan();
|
|
102
86
|
let found = false;
|
|
103
87
|
for (const file of results) {
|
|
@@ -105,14 +89,7 @@ const setCommand = new Command("set").description("Set a specific option for a s
|
|
|
105
89
|
if (selector) {
|
|
106
90
|
found = true;
|
|
107
91
|
try {
|
|
108
|
-
|
|
109
|
-
if (hasBlockOptions$1(selector)) {
|
|
110
|
-
const switcher = BlockSwitcher.forFilePath(file.path);
|
|
111
|
-
newContent = switcher.switch(file.content, selector, optionName);
|
|
112
|
-
} else {
|
|
113
|
-
const switcher = SingleSwitcher.forFilePath(file.path);
|
|
114
|
-
newContent = switcher.switch(file.content, selector, optionName);
|
|
115
|
-
}
|
|
92
|
+
const newContent = selector.switchTo(file.content, optionName, file.path);
|
|
116
93
|
await writeFile(file.path, newContent);
|
|
117
94
|
const relativePath = relative(process.cwd(), file.path);
|
|
118
95
|
console.log(
|
|
@@ -132,31 +109,13 @@ const setCommand = new Command("set").description("Set a specific option for a s
|
|
|
132
109
|
}
|
|
133
110
|
});
|
|
134
111
|
const BACK_VALUE = /* @__PURE__ */ Symbol("back");
|
|
135
|
-
function isExitPromptError(error) {
|
|
112
|
+
function isExitPromptError$1(error) {
|
|
136
113
|
return error instanceof Error && error.name === "ExitPromptError";
|
|
137
114
|
}
|
|
138
|
-
function hasBlockOptions(selector) {
|
|
139
|
-
return selector.blockOptions.length > 0;
|
|
140
|
-
}
|
|
141
|
-
function getActiveOptionName(selector) {
|
|
142
|
-
if (hasBlockOptions(selector)) {
|
|
143
|
-
return selector.blockOptions.find((b) => b.isActive)?.name ?? null;
|
|
144
|
-
}
|
|
145
|
-
return selector.options.find((o) => o.isActive)?.name ?? null;
|
|
146
|
-
}
|
|
147
|
-
function getAllOptions(selector) {
|
|
148
|
-
if (hasBlockOptions(selector)) {
|
|
149
|
-
return selector.blockOptions.map((b) => ({ name: b.name, isActive: b.isActive }));
|
|
150
|
-
}
|
|
151
|
-
return selector.options.map((o) => ({ name: o.name, isActive: o.isActive }));
|
|
152
|
-
}
|
|
153
115
|
const switchCommand = new Command("switch").alias("sw").description("Interactively switch options").action(async () => {
|
|
154
116
|
const config = await loadConfig();
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
process.exit(1);
|
|
158
|
-
}
|
|
159
|
-
const scanner = new Scanner(config.select);
|
|
117
|
+
const selectConfig = requireSelectConfig(config);
|
|
118
|
+
const scanner = new Scanner(selectConfig);
|
|
160
119
|
const results = await scanner.scan();
|
|
161
120
|
if (results.length === 0) {
|
|
162
121
|
console.log(pc.yellow("No selectors found"));
|
|
@@ -176,9 +135,9 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
|
|
|
176
135
|
choices: [
|
|
177
136
|
...choices.map((choice) => {
|
|
178
137
|
const relativePath2 = relative(process.cwd(), choice.file.path);
|
|
179
|
-
const activeOptionName =
|
|
138
|
+
const activeOptionName = choice.selector.getActiveOptionName();
|
|
180
139
|
const current = activeOptionName ? pc.dim(` (${activeOptionName})`) : "";
|
|
181
|
-
const blockIndicator =
|
|
140
|
+
const blockIndicator = choice.selector instanceof BlockSelector ? pc.dim(" [block]") : "";
|
|
182
141
|
return {
|
|
183
142
|
name: `${choice.selector.name}${blockIndicator}${current} ${pc.dim(`- ${relativePath2}`)}`,
|
|
184
143
|
value: choice
|
|
@@ -189,7 +148,7 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
|
|
|
189
148
|
]
|
|
190
149
|
});
|
|
191
150
|
} catch (error) {
|
|
192
|
-
if (isExitPromptError(error)) {
|
|
151
|
+
if (isExitPromptError$1(error)) {
|
|
193
152
|
process.exit(0);
|
|
194
153
|
}
|
|
195
154
|
throw error;
|
|
@@ -198,12 +157,11 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
|
|
|
198
157
|
return;
|
|
199
158
|
}
|
|
200
159
|
let selectedOption;
|
|
201
|
-
const allOptions = getAllOptions(selectedChoice.selector);
|
|
202
160
|
try {
|
|
203
161
|
selectedOption = await select({
|
|
204
162
|
message: `Select option for ${pc.bold(selectedChoice.selector.name)}`,
|
|
205
163
|
choices: [
|
|
206
|
-
...
|
|
164
|
+
...selectedChoice.selector.options.map((option) => ({
|
|
207
165
|
name: option.isActive ? `${option.name} ${pc.green("(current)")}` : option.name,
|
|
208
166
|
value: option.name
|
|
209
167
|
})),
|
|
@@ -212,7 +170,7 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
|
|
|
212
170
|
]
|
|
213
171
|
});
|
|
214
172
|
} catch (error) {
|
|
215
|
-
if (isExitPromptError(error)) {
|
|
173
|
+
if (isExitPromptError$1(error)) {
|
|
216
174
|
process.exit(0);
|
|
217
175
|
}
|
|
218
176
|
throw error;
|
|
@@ -220,22 +178,11 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
|
|
|
220
178
|
if (selectedOption === BACK_VALUE) {
|
|
221
179
|
continue;
|
|
222
180
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
selectedChoice.selector,
|
|
229
|
-
selectedOption
|
|
230
|
-
);
|
|
231
|
-
} else {
|
|
232
|
-
const switcher = SingleSwitcher.forFilePath(selectedChoice.file.path);
|
|
233
|
-
newContent = switcher.switch(
|
|
234
|
-
selectedChoice.file.content,
|
|
235
|
-
selectedChoice.selector,
|
|
236
|
-
selectedOption
|
|
237
|
-
);
|
|
238
|
-
}
|
|
181
|
+
const newContent = selectedChoice.selector.switchTo(
|
|
182
|
+
selectedChoice.file.content,
|
|
183
|
+
selectedOption,
|
|
184
|
+
selectedChoice.file.path
|
|
185
|
+
);
|
|
239
186
|
await writeFile(selectedChoice.file.path, newContent);
|
|
240
187
|
const relativePath = relative(process.cwd(), selectedChoice.file.path);
|
|
241
188
|
console.log(
|
|
@@ -246,6 +193,310 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
|
|
|
246
193
|
return;
|
|
247
194
|
}
|
|
248
195
|
});
|
|
196
|
+
class Profile {
|
|
197
|
+
constructor(name, mapping) {
|
|
198
|
+
this.name = name;
|
|
199
|
+
this.mapping = mapping;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Find a selector by name across scan results
|
|
203
|
+
*/
|
|
204
|
+
static findSelector(results, selectorName) {
|
|
205
|
+
for (const file of results) {
|
|
206
|
+
const selector = file.selectors.find((s) => s.name === selectorName);
|
|
207
|
+
if (selector) {
|
|
208
|
+
return { file, selector };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Compute the status of this profile against scan results
|
|
215
|
+
*/
|
|
216
|
+
computeStatus(results) {
|
|
217
|
+
const mappings = [];
|
|
218
|
+
for (const [selectorName, expectedOption] of Object.entries(this.mapping)) {
|
|
219
|
+
const found = Profile.findSelector(results, selectorName);
|
|
220
|
+
if (!found) {
|
|
221
|
+
mappings.push({
|
|
222
|
+
selectorName,
|
|
223
|
+
expectedOption,
|
|
224
|
+
currentOption: null,
|
|
225
|
+
filePath: "",
|
|
226
|
+
isMatched: false,
|
|
227
|
+
error: `Selector "${selectorName}" not found`
|
|
228
|
+
});
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const currentOption = found.selector.getActiveOptionName();
|
|
232
|
+
const optionExists = found.selector.optionExists(expectedOption);
|
|
233
|
+
if (!optionExists) {
|
|
234
|
+
mappings.push({
|
|
235
|
+
selectorName,
|
|
236
|
+
expectedOption,
|
|
237
|
+
currentOption,
|
|
238
|
+
filePath: found.file.path,
|
|
239
|
+
isMatched: false,
|
|
240
|
+
error: `Option "${expectedOption}" not found in selector "${selectorName}"`
|
|
241
|
+
});
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
mappings.push({
|
|
245
|
+
selectorName,
|
|
246
|
+
expectedOption,
|
|
247
|
+
currentOption,
|
|
248
|
+
filePath: found.file.path,
|
|
249
|
+
isMatched: currentOption === expectedOption
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
const matchedCount = mappings.filter((m) => m.isMatched).length;
|
|
253
|
+
const totalCount = mappings.length;
|
|
254
|
+
return {
|
|
255
|
+
name: this.name,
|
|
256
|
+
mappings,
|
|
257
|
+
isFullyActive: matchedCount === totalCount && totalCount > 0,
|
|
258
|
+
isPartiallyActive: matchedCount > 0 && matchedCount < totalCount,
|
|
259
|
+
matchedCount,
|
|
260
|
+
totalCount
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Apply this profile to the scanned files
|
|
265
|
+
*/
|
|
266
|
+
async apply(results) {
|
|
267
|
+
const applyResults = [];
|
|
268
|
+
const changesByFile = /* @__PURE__ */ new Map();
|
|
269
|
+
for (const [selectorName, optionName] of Object.entries(this.mapping)) {
|
|
270
|
+
const found = Profile.findSelector(results, selectorName);
|
|
271
|
+
if (!found) {
|
|
272
|
+
applyResults.push({
|
|
273
|
+
selectorName,
|
|
274
|
+
optionName,
|
|
275
|
+
filePath: "",
|
|
276
|
+
success: false,
|
|
277
|
+
error: `Selector "${selectorName}" not found`
|
|
278
|
+
});
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const optionExists = found.selector.optionExists(optionName);
|
|
282
|
+
if (!optionExists) {
|
|
283
|
+
const availableOptions = found.selector.options.map((o) => o.name).join(", ");
|
|
284
|
+
applyResults.push({
|
|
285
|
+
selectorName,
|
|
286
|
+
optionName,
|
|
287
|
+
filePath: found.file.path,
|
|
288
|
+
success: false,
|
|
289
|
+
error: `Option "${optionName}" not found. Available: ${availableOptions}`
|
|
290
|
+
});
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const existing = changesByFile.get(found.file.path);
|
|
294
|
+
if (existing) {
|
|
295
|
+
existing.push({
|
|
296
|
+
selectorName,
|
|
297
|
+
optionName,
|
|
298
|
+
selector: found.selector
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
changesByFile.set(found.file.path, [
|
|
302
|
+
{
|
|
303
|
+
selectorName,
|
|
304
|
+
optionName,
|
|
305
|
+
selector: found.selector
|
|
306
|
+
}
|
|
307
|
+
]);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
for (const [filePath, changes] of changesByFile) {
|
|
311
|
+
let content = await readFile(filePath, "utf-8");
|
|
312
|
+
for (const change of changes) {
|
|
313
|
+
try {
|
|
314
|
+
const parser = Parser.forFilePath(filePath);
|
|
315
|
+
const { selectors } = parser.parse(content);
|
|
316
|
+
const freshSelector = selectors.find((s) => s.name === change.selectorName);
|
|
317
|
+
if (!freshSelector) {
|
|
318
|
+
applyResults.push({
|
|
319
|
+
selectorName: change.selectorName,
|
|
320
|
+
optionName: change.optionName,
|
|
321
|
+
filePath,
|
|
322
|
+
success: false,
|
|
323
|
+
error: `Selector "${change.selectorName}" not found after previous changes`
|
|
324
|
+
});
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
content = freshSelector.switchTo(content, change.optionName, filePath);
|
|
328
|
+
applyResults.push({
|
|
329
|
+
selectorName: change.selectorName,
|
|
330
|
+
optionName: change.optionName,
|
|
331
|
+
filePath,
|
|
332
|
+
success: true
|
|
333
|
+
});
|
|
334
|
+
} catch (error) {
|
|
335
|
+
applyResults.push({
|
|
336
|
+
selectorName: change.selectorName,
|
|
337
|
+
optionName: change.optionName,
|
|
338
|
+
filePath,
|
|
339
|
+
success: false,
|
|
340
|
+
error: error instanceof Error ? error.message : String(error)
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
await writeFile(filePath, content);
|
|
345
|
+
}
|
|
346
|
+
return applyResults;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Compute statuses for multiple profiles
|
|
350
|
+
*/
|
|
351
|
+
static computeAllStatuses(profiles, results) {
|
|
352
|
+
return Object.entries(profiles).map(
|
|
353
|
+
([name, mapping]) => new Profile(name, mapping).computeStatus(results)
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
function isExitPromptError(error) {
|
|
358
|
+
return error instanceof Error && error.name === "ExitPromptError";
|
|
359
|
+
}
|
|
360
|
+
const profileCommand = new Command("profile").description("Apply a profile to switch multiple selectors at once").argument("[name]", "Profile name to apply").action(async (profileName) => {
|
|
361
|
+
const config = await loadConfig();
|
|
362
|
+
const selectConfig = requireSelectConfig(config);
|
|
363
|
+
const profiles = selectConfig.profiles;
|
|
364
|
+
if (!profiles || Object.keys(profiles).length === 0) {
|
|
365
|
+
console.error(pc.red("No profiles configured"));
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
368
|
+
const scanner = new Scanner(selectConfig);
|
|
369
|
+
const results = await scanner.scan();
|
|
370
|
+
if (!profileName) {
|
|
371
|
+
const statuses = Profile.computeAllStatuses(profiles, results);
|
|
372
|
+
try {
|
|
373
|
+
profileName = await select({
|
|
374
|
+
message: "Select a profile to apply",
|
|
375
|
+
choices: [
|
|
376
|
+
...statuses.map((status) => {
|
|
377
|
+
let statusIndicator;
|
|
378
|
+
if (status.isFullyActive) {
|
|
379
|
+
statusIndicator = pc.green("●");
|
|
380
|
+
} else if (status.isPartiallyActive) {
|
|
381
|
+
statusIndicator = pc.yellow("●");
|
|
382
|
+
} else {
|
|
383
|
+
statusIndicator = pc.dim("○");
|
|
384
|
+
}
|
|
385
|
+
const countInfo = pc.dim(`(${status.matchedCount}/${status.totalCount})`);
|
|
386
|
+
return {
|
|
387
|
+
name: `${statusIndicator} ${status.name} ${countInfo}`,
|
|
388
|
+
value: status.name
|
|
389
|
+
};
|
|
390
|
+
}),
|
|
391
|
+
new Separator(),
|
|
392
|
+
{ name: pc.dim("← Cancel"), value: "" }
|
|
393
|
+
]
|
|
394
|
+
});
|
|
395
|
+
} catch (error) {
|
|
396
|
+
if (isExitPromptError(error)) {
|
|
397
|
+
process.exit(0);
|
|
398
|
+
}
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
401
|
+
if (!profileName) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
const profileMapping = profiles[profileName];
|
|
406
|
+
if (!profileMapping) {
|
|
407
|
+
const availableProfiles = Object.keys(profiles).join(", ");
|
|
408
|
+
console.error(pc.red(`Profile "${profileName}" not found`));
|
|
409
|
+
console.error(pc.dim(`Available profiles: ${availableProfiles}`));
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
const profile = new Profile(profileName, profileMapping);
|
|
413
|
+
const applyResults = await profile.apply(results);
|
|
414
|
+
const successes = applyResults.filter((r) => r.success);
|
|
415
|
+
const failures = applyResults.filter((r) => !r.success);
|
|
416
|
+
for (const result of successes) {
|
|
417
|
+
const relativePath = relative(process.cwd(), result.filePath);
|
|
418
|
+
console.log(
|
|
419
|
+
pc.green(
|
|
420
|
+
`✓ Set ${pc.bold(result.selectorName)} to ${pc.bold(result.optionName)} in ${relativePath}`
|
|
421
|
+
)
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
for (const result of failures) {
|
|
425
|
+
console.error(pc.red(`✗ ${result.selectorName}: ${result.error}`));
|
|
426
|
+
}
|
|
427
|
+
if (failures.length > 0) {
|
|
428
|
+
console.log();
|
|
429
|
+
console.log(
|
|
430
|
+
pc.yellow(`Applied ${successes.length}/${applyResults.length} selector(s) from profile "${profileName}"`)
|
|
431
|
+
);
|
|
432
|
+
process.exit(1);
|
|
433
|
+
} else {
|
|
434
|
+
console.log();
|
|
435
|
+
console.log(pc.green(`✓ Applied profile "${profileName}" (${successes.length} selector(s))`));
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
const profilesCommand = new Command("profiles").description("List all profiles and their status").option("--json", "Output in JSON format").action(async (options) => {
|
|
439
|
+
const config = await loadConfig();
|
|
440
|
+
const selectConfig = requireSelectConfig(config, options);
|
|
441
|
+
const profiles = selectConfig.profiles;
|
|
442
|
+
if (!profiles || Object.keys(profiles).length === 0) {
|
|
443
|
+
if (options.json) {
|
|
444
|
+
console.log(JSON.stringify({ error: "No profiles configured" }));
|
|
445
|
+
} else {
|
|
446
|
+
console.log(pc.yellow("No profiles configured"));
|
|
447
|
+
}
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
const scanner = new Scanner(selectConfig);
|
|
451
|
+
const results = await scanner.scan();
|
|
452
|
+
const statuses = Profile.computeAllStatuses(profiles, results);
|
|
453
|
+
if (options.json) {
|
|
454
|
+
const jsonOutput = statuses.map((status) => ({
|
|
455
|
+
name: status.name,
|
|
456
|
+
isFullyActive: status.isFullyActive,
|
|
457
|
+
isPartiallyActive: status.isPartiallyActive,
|
|
458
|
+
matchedCount: status.matchedCount,
|
|
459
|
+
totalCount: status.totalCount,
|
|
460
|
+
mappings: status.mappings.map((m) => ({
|
|
461
|
+
selectorName: m.selectorName,
|
|
462
|
+
expectedOption: m.expectedOption,
|
|
463
|
+
currentOption: m.currentOption,
|
|
464
|
+
filePath: m.filePath ? relative(process.cwd(), m.filePath) : null,
|
|
465
|
+
isMatched: m.isMatched,
|
|
466
|
+
error: m.error
|
|
467
|
+
}))
|
|
468
|
+
}));
|
|
469
|
+
console.log(JSON.stringify(jsonOutput, null, 2));
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
for (const status of statuses) {
|
|
473
|
+
let statusIndicator;
|
|
474
|
+
if (status.isFullyActive) {
|
|
475
|
+
statusIndicator = pc.green("●");
|
|
476
|
+
} else if (status.isPartiallyActive) {
|
|
477
|
+
statusIndicator = pc.yellow("●");
|
|
478
|
+
} else {
|
|
479
|
+
statusIndicator = pc.dim("○");
|
|
480
|
+
}
|
|
481
|
+
const countInfo = pc.dim(`(${status.matchedCount}/${status.totalCount})`);
|
|
482
|
+
console.log(`${statusIndicator} ${pc.bold(status.name)} ${countInfo}`);
|
|
483
|
+
for (const mapping of status.mappings) {
|
|
484
|
+
const mappingIndicator = mapping.isMatched ? pc.green("✓") : pc.dim("○");
|
|
485
|
+
const currentValue = mapping.currentOption ?? pc.dim("none");
|
|
486
|
+
const expectedValue = mapping.expectedOption;
|
|
487
|
+
if (mapping.error) {
|
|
488
|
+
console.log(` ${pc.red("✗")} ${mapping.selectorName}: ${pc.red(mapping.error)}`);
|
|
489
|
+
} else if (mapping.isMatched) {
|
|
490
|
+
console.log(` ${mappingIndicator} ${mapping.selectorName}: ${pc.green(currentValue)}`);
|
|
491
|
+
} else {
|
|
492
|
+
console.log(
|
|
493
|
+
` ${mappingIndicator} ${mapping.selectorName}: ${currentValue} ${pc.dim(`→ ${expectedValue}`)}`
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
console.log();
|
|
498
|
+
}
|
|
499
|
+
});
|
|
249
500
|
const selectPlugin = {
|
|
250
501
|
name: "Select",
|
|
251
502
|
description: "Switch config options using @pik markers",
|
|
@@ -256,6 +507,8 @@ const selectPlugin = {
|
|
|
256
507
|
selectCmd.addCommand(listCommand);
|
|
257
508
|
selectCmd.addCommand(setCommand);
|
|
258
509
|
selectCmd.addCommand(switchCommand);
|
|
510
|
+
selectCmd.addCommand(profileCommand);
|
|
511
|
+
selectCmd.addCommand(profilesCommand);
|
|
259
512
|
selectCmd.action(async () => {
|
|
260
513
|
await switchCommand.parseAsync([], { from: "user" });
|
|
261
514
|
});
|
|
@@ -265,6 +518,7 @@ const selectPlugin = {
|
|
|
265
518
|
}
|
|
266
519
|
};
|
|
267
520
|
export {
|
|
521
|
+
Profile,
|
|
268
522
|
Scanner,
|
|
269
523
|
selectPlugin
|
|
270
524
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,aAAa,CAAC;AAMrB,eAAO,MAAM,WAAW,SAoDpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,aAAa,CAAC;AAMrB,eAAO,MAAM,cAAc,SAkGvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/profiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,aAAa,CAAC;AAMrB,eAAO,MAAM,eAAe,SA0ExB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,aAAa,CAAC;AAErB,eAAO,MAAM,UAAU,SAwCnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,aAAa,CAAC;AAarB,eAAO,MAAM,aAAa,SAqGtB,CAAC"}
|
package/dist/lib/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/lib/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/lib/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAOhD,eAAO,MAAM,YAAY,EAAE,SA8B1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/profile/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type BaseSelector } from '@lsst/pik-core';
|
|
2
|
+
import type { FileResult } from '../scanner.js';
|
|
3
|
+
import type { ProfileMapping } from '../types.js';
|
|
4
|
+
import type { ProfileStatus } from '../types/profile-status.js';
|
|
5
|
+
/**
|
|
6
|
+
* Result of finding a selector by name
|
|
7
|
+
*/
|
|
8
|
+
export interface FoundSelector {
|
|
9
|
+
file: FileResult;
|
|
10
|
+
selector: BaseSelector;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of applying a single selector change
|
|
14
|
+
*/
|
|
15
|
+
export interface ApplyResult {
|
|
16
|
+
selectorName: string;
|
|
17
|
+
optionName: string;
|
|
18
|
+
filePath: string;
|
|
19
|
+
success: boolean;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Represents a profile that maps selector names to option names
|
|
24
|
+
*/
|
|
25
|
+
export declare class Profile {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly mapping: ProfileMapping;
|
|
28
|
+
constructor(name: string, mapping: ProfileMapping);
|
|
29
|
+
/**
|
|
30
|
+
* Find a selector by name across scan results
|
|
31
|
+
*/
|
|
32
|
+
static findSelector(results: FileResult[], selectorName: string): FoundSelector | null;
|
|
33
|
+
/**
|
|
34
|
+
* Compute the status of this profile against scan results
|
|
35
|
+
*/
|
|
36
|
+
computeStatus(results: FileResult[]): ProfileStatus;
|
|
37
|
+
/**
|
|
38
|
+
* Apply this profile to the scanned files
|
|
39
|
+
*/
|
|
40
|
+
apply(results: FileResult[]): Promise<ApplyResult[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Compute statuses for multiple profiles
|
|
43
|
+
*/
|
|
44
|
+
static computeAllStatuses(profiles: Record<string, ProfileMapping>, results: FileResult[]): ProfileStatus[];
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../../src/lib/profile/profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAyB,MAAM,4BAA4B,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,OAAO;aAEA,IAAI,EAAE,MAAM;aACZ,OAAO,EAAE,cAAc;gBADvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc;IAGzC;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAUtF;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,aAAa;IAuDnD;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAsG1D;;OAEG;IACH,MAAM,CAAC,kBAAkB,CACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EACxC,OAAO,EAAE,UAAU,EAAE,GACpB,aAAa,EAAE;CAKnB"}
|
package/dist/lib/scanner.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type BaseSelector } from '@lsst/pik-core';
|
|
2
2
|
import type { SelectConfig } from './types.js';
|
|
3
3
|
export interface FileResult {
|
|
4
4
|
path: string;
|
|
5
|
-
selectors:
|
|
5
|
+
selectors: BaseSelector[];
|
|
6
6
|
content: string;
|
|
7
7
|
}
|
|
8
8
|
export declare class Scanner {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/lib/scanner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/lib/scanner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,OAAO;IACN,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,YAAY;IAE3C,IAAI,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;CAqB/D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status of a single selector mapping within a profile
|
|
3
|
+
*/
|
|
4
|
+
export interface SelectorMappingStatus {
|
|
5
|
+
/** Name of the selector */
|
|
6
|
+
selectorName: string;
|
|
7
|
+
/** Expected option from the profile */
|
|
8
|
+
expectedOption: string;
|
|
9
|
+
/** Current active option in the file */
|
|
10
|
+
currentOption: string | null;
|
|
11
|
+
/** Path to the file containing the selector */
|
|
12
|
+
filePath: string;
|
|
13
|
+
/** Whether the current option matches the expected option */
|
|
14
|
+
isMatched: boolean;
|
|
15
|
+
/** Error message if selector or option not found */
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Status of a profile
|
|
20
|
+
*/
|
|
21
|
+
export interface ProfileStatus {
|
|
22
|
+
/** Profile name */
|
|
23
|
+
name: string;
|
|
24
|
+
/** Status of each selector mapping */
|
|
25
|
+
mappings: SelectorMappingStatus[];
|
|
26
|
+
/** All mappings match their expected options */
|
|
27
|
+
isFullyActive: boolean;
|
|
28
|
+
/** Some mappings match their expected options */
|
|
29
|
+
isPartiallyActive: boolean;
|
|
30
|
+
/** Number of matched mappings */
|
|
31
|
+
matchedCount: number;
|
|
32
|
+
/** Total number of mappings in the profile */
|
|
33
|
+
totalCount: number;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=profile-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-status.d.ts","sourceRoot":"","sources":["../../../src/lib/types/profile-status.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,SAAS,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,gDAAgD;IAChD,aAAa,EAAE,OAAO,CAAC;IACvB,iDAAiD;IACjD,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps selector names to option names within a profile
|
|
3
|
+
*/
|
|
4
|
+
export interface ProfileMapping {
|
|
5
|
+
[selectorName: string]: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Collection of named profiles
|
|
9
|
+
*/
|
|
10
|
+
export interface ProfilesConfig {
|
|
11
|
+
[profileName: string]: ProfileMapping;
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* Configuration for the select plugin
|
|
3
15
|
*/
|
|
4
16
|
export interface SelectConfig {
|
|
5
17
|
/** File patterns to scan for @pik markers */
|
|
6
18
|
include: string[];
|
|
19
|
+
/** Named profiles that apply multiple selector options at once */
|
|
20
|
+
profiles?: ProfilesConfig;
|
|
7
21
|
}
|
|
8
22
|
/**
|
|
9
23
|
* Extend PikConfig to include select plugin config
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;GAEG;AACH,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,SAAS;QACjB,MAAM,CAAC,EAAE,YAAY,CAAC;KACvB;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PikConfig } from '@lsst/pik-core';
|
|
2
|
+
import type { SelectConfig } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validates that config has a select section.
|
|
5
|
+
* Exits with error if not found.
|
|
6
|
+
*
|
|
7
|
+
* @returns The select config (type-narrowed)
|
|
8
|
+
*/
|
|
9
|
+
export declare function requireSelectConfig(config: PikConfig | null, options?: {
|
|
10
|
+
json?: boolean;
|
|
11
|
+
}): SelectConfig;
|
|
12
|
+
//# sourceMappingURL=requireSelectConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requireSelectConfig.d.ts","sourceRoot":"","sources":["../../../src/lib/validation/requireSelectConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,GAAG,IAAI,EACxB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3B,YAAY,CAWd"}
|