poe-code 3.0.4 → 3.0.6
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/dist/cli/commands/configure.js.map +1 -1
- package/dist/cli/commands/shared.d.ts +2 -2
- package/dist/cli/service-registry.d.ts +10 -1
- package/dist/cli/service-registry.js.map +1 -1
- package/dist/providers/claude-code.js +18 -17
- package/dist/providers/claude-code.js.map +1 -1
- package/dist/providers/codex.js +21 -23
- package/dist/providers/codex.js.map +1 -1
- package/dist/providers/create-provider.d.ts +9 -6
- package/dist/providers/create-provider.js +44 -31
- package/dist/providers/create-provider.js.map +1 -1
- package/dist/providers/kimi.js +13 -17
- package/dist/providers/kimi.js.map +1 -1
- package/dist/providers/mcp-config.d.ts +5 -9
- package/dist/providers/mcp-config.js +16 -32
- package/dist/providers/mcp-config.js.map +1 -1
- package/dist/providers/opencode.d.ts +1 -1
- package/dist/providers/opencode.js +17 -29
- package/dist/providers/opencode.js.map +1 -1
- package/dist/services/mutation-events.d.ts +3 -3
- package/dist/services/mutation-events.js.map +1 -1
- package/dist/utils/templates.d.ts +1 -0
- package/dist/utils/templates.js +1 -1
- package/dist/utils/templates.js.map +1 -1
- package/package.json +1 -1
- package/dist/providers/provider-helpers.d.ts +0 -10
- package/dist/providers/provider-helpers.js +0 -73
- package/dist/providers/provider-helpers.js.map +0 -1
- package/dist/services/service-manifest.d.ts +0 -200
- package/dist/services/service-manifest.js +0 -717
- package/dist/services/service-manifest.js.map +0 -1
|
@@ -1,717 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { createBackup } from "../utils/backup.js";
|
|
3
|
-
import { renderTemplate } from "../utils/templates.js";
|
|
4
|
-
import { deepMergeJson, isJsonObject, pruneJsonByShape } from "../utils/json.js";
|
|
5
|
-
import { parseTomlDocument, serializeTomlDocument, mergeTomlTables } from "../utils/toml.js";
|
|
6
|
-
export function ensureDirectory(config) {
|
|
7
|
-
const targetDirectory = config.targetDirectory ?? config.path;
|
|
8
|
-
if (!targetDirectory) {
|
|
9
|
-
throw new Error("ensureDirectory requires a path or targetDirectory.");
|
|
10
|
-
}
|
|
11
|
-
return {
|
|
12
|
-
kind: "ensureDirectory",
|
|
13
|
-
targetDirectory,
|
|
14
|
-
label: config.label
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export function createBackupMutation(config) {
|
|
18
|
-
return {
|
|
19
|
-
kind: "createBackup",
|
|
20
|
-
target: normalizeTargetLocation(config),
|
|
21
|
-
timestamp: config.timestamp,
|
|
22
|
-
label: config.label
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export function writeTemplateMutation(config) {
|
|
26
|
-
return {
|
|
27
|
-
kind: "writeTemplate",
|
|
28
|
-
target: normalizeTargetLocation(config),
|
|
29
|
-
templateId: config.templateId,
|
|
30
|
-
context: config.context,
|
|
31
|
-
label: config.label
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
export function chmodMutation(config) {
|
|
35
|
-
return {
|
|
36
|
-
kind: "chmod",
|
|
37
|
-
target: normalizeTargetLocation(config),
|
|
38
|
-
mode: config.mode,
|
|
39
|
-
label: config.label
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
export function jsonMergeMutation(config) {
|
|
43
|
-
return {
|
|
44
|
-
kind: "transformFile",
|
|
45
|
-
target: normalizeTargetLocation(config),
|
|
46
|
-
label: config.label,
|
|
47
|
-
async transform({ content, context }) {
|
|
48
|
-
const targetPath = resolveTargetPath(config, context);
|
|
49
|
-
const current = await parseJsonWithRecovery({
|
|
50
|
-
content,
|
|
51
|
-
fs: context.fs,
|
|
52
|
-
targetPath
|
|
53
|
-
});
|
|
54
|
-
const desired = resolveValue(config.value, context);
|
|
55
|
-
const merged = deepMergeJson(current, desired);
|
|
56
|
-
const serialized = serializeJson(merged);
|
|
57
|
-
return {
|
|
58
|
-
content: serialized,
|
|
59
|
-
changed: serialized !== content
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
export function jsonPruneMutation(config) {
|
|
65
|
-
return {
|
|
66
|
-
kind: "transformFile",
|
|
67
|
-
target: normalizeTargetLocation(config),
|
|
68
|
-
label: config.label,
|
|
69
|
-
async transform({ content, context }) {
|
|
70
|
-
if (content == null) {
|
|
71
|
-
return { content: null, changed: false };
|
|
72
|
-
}
|
|
73
|
-
const targetPath = resolveTargetPath(config, context);
|
|
74
|
-
const current = await parseJsonWithRecovery({
|
|
75
|
-
content,
|
|
76
|
-
fs: context.fs,
|
|
77
|
-
targetPath
|
|
78
|
-
});
|
|
79
|
-
const shape = resolveValue(config.shape, context);
|
|
80
|
-
const { changed, result } = pruneJsonByShape(current, shape);
|
|
81
|
-
if (!changed) {
|
|
82
|
-
return { content, changed: false };
|
|
83
|
-
}
|
|
84
|
-
if (Object.keys(result).length === 0) {
|
|
85
|
-
return { content: null, changed: true };
|
|
86
|
-
}
|
|
87
|
-
const serialized = serializeJson(result);
|
|
88
|
-
return {
|
|
89
|
-
content: serialized,
|
|
90
|
-
changed: serialized !== content
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
export function tomlMergeMutation(config) {
|
|
96
|
-
return {
|
|
97
|
-
kind: "transformFile",
|
|
98
|
-
target: normalizeTargetLocation(config),
|
|
99
|
-
label: config.label,
|
|
100
|
-
async transform({ content, context }) {
|
|
101
|
-
const targetPath = resolveTargetPath(config, context);
|
|
102
|
-
const current = await parseTomlWithRecovery({
|
|
103
|
-
content,
|
|
104
|
-
fs: context.fs,
|
|
105
|
-
targetPath
|
|
106
|
-
});
|
|
107
|
-
const desired = resolveValue(config.value, context);
|
|
108
|
-
const mergeOptions = config.pruneByPrefix
|
|
109
|
-
? { pruneByPrefix: config.pruneByPrefix }
|
|
110
|
-
: {};
|
|
111
|
-
const merged = mergeTomlTables(current, desired, mergeOptions);
|
|
112
|
-
const serialized = serializeTomlDocument(merged);
|
|
113
|
-
const previous = content ?? "";
|
|
114
|
-
return {
|
|
115
|
-
content: serialized,
|
|
116
|
-
changed: serialized !== previous
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
export function tomlPruneMutation(config) {
|
|
122
|
-
return {
|
|
123
|
-
kind: "transformFile",
|
|
124
|
-
target: normalizeTargetLocation(config),
|
|
125
|
-
label: config.label,
|
|
126
|
-
async transform({ content, context }) {
|
|
127
|
-
if (content == null) {
|
|
128
|
-
return { content: null, changed: false };
|
|
129
|
-
}
|
|
130
|
-
let document;
|
|
131
|
-
try {
|
|
132
|
-
document = parseTomlDocument(content);
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
return { content, changed: false };
|
|
136
|
-
}
|
|
137
|
-
const outcome = config.prune(document, context);
|
|
138
|
-
if (!outcome.changed) {
|
|
139
|
-
return { content, changed: false };
|
|
140
|
-
}
|
|
141
|
-
if (!outcome.result || Object.keys(outcome.result).length === 0) {
|
|
142
|
-
return { content: null, changed: true };
|
|
143
|
-
}
|
|
144
|
-
const serialized = serializeTomlDocument(outcome.result);
|
|
145
|
-
return {
|
|
146
|
-
content: serialized,
|
|
147
|
-
changed: serialized !== content
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
export function tomlTemplateMergeMutation(config) {
|
|
153
|
-
return {
|
|
154
|
-
kind: "transformFile",
|
|
155
|
-
target: normalizeTargetLocation(config),
|
|
156
|
-
label: config.label,
|
|
157
|
-
async transform({ content, context }) {
|
|
158
|
-
const targetPath = resolveTargetPath(config, context);
|
|
159
|
-
const current = await parseTomlWithRecovery({
|
|
160
|
-
content,
|
|
161
|
-
fs: context.fs,
|
|
162
|
-
targetPath
|
|
163
|
-
});
|
|
164
|
-
const templateContext = config.context
|
|
165
|
-
? resolveValue(config.context, context)
|
|
166
|
-
: undefined;
|
|
167
|
-
const rendered = await renderTemplate(config.templateId, templateContext ?? {});
|
|
168
|
-
const templateDocument = parseTomlDocument(rendered);
|
|
169
|
-
const merged = mergeTomlTables(current, templateDocument);
|
|
170
|
-
const serialized = serializeTomlDocument(merged);
|
|
171
|
-
const previous = content ?? "";
|
|
172
|
-
return {
|
|
173
|
-
content: serialized,
|
|
174
|
-
changed: serialized !== previous
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
export function removePatternMutation(config) {
|
|
180
|
-
return {
|
|
181
|
-
kind: "transformFile",
|
|
182
|
-
target: { target: config.target },
|
|
183
|
-
label: config.label,
|
|
184
|
-
transform({ content, context }) {
|
|
185
|
-
if (content == null) {
|
|
186
|
-
return { content: null, changed: false };
|
|
187
|
-
}
|
|
188
|
-
let next;
|
|
189
|
-
if (typeof config.replacement === "function") {
|
|
190
|
-
const replacementFn = config.replacement;
|
|
191
|
-
const replacer = (match, ..._args) => replacementFn(match, context);
|
|
192
|
-
next = content.replace(config.pattern, replacer);
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
next = content.replace(config.pattern, config.replacement ?? "");
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
content: next,
|
|
199
|
-
changed: next !== content
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
export function removeFileMutation(config) {
|
|
205
|
-
return {
|
|
206
|
-
kind: "removeFile",
|
|
207
|
-
target: normalizeTargetLocation(config),
|
|
208
|
-
whenEmpty: config.whenEmpty,
|
|
209
|
-
whenContentMatches: config.whenContentMatches,
|
|
210
|
-
label: config.label
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
export function createServiceManifest(definition) {
|
|
214
|
-
const configureMutations = definition.configure;
|
|
215
|
-
const unconfigureMutations = definition.unconfigure;
|
|
216
|
-
return {
|
|
217
|
-
id: definition.id,
|
|
218
|
-
summary: definition.summary,
|
|
219
|
-
configureMutations,
|
|
220
|
-
unconfigureMutations,
|
|
221
|
-
async configure(context, runOptions) {
|
|
222
|
-
await runMutations(configureMutations, context, {
|
|
223
|
-
trackChanges: false,
|
|
224
|
-
observers: runOptions?.observers,
|
|
225
|
-
manifestId: definition.id
|
|
226
|
-
});
|
|
227
|
-
},
|
|
228
|
-
async unconfigure(context, runOptions) {
|
|
229
|
-
if (!unconfigureMutations) {
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
232
|
-
return runMutations(unconfigureMutations, context, {
|
|
233
|
-
trackChanges: true,
|
|
234
|
-
observers: runOptions?.observers,
|
|
235
|
-
manifestId: definition.id
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
async function runMutations(mutations, context, options) {
|
|
241
|
-
let touched = false;
|
|
242
|
-
for (const mutation of mutations) {
|
|
243
|
-
const changed = await applyMutation(mutation, context, options.manifestId, options.observers);
|
|
244
|
-
if (options.trackChanges && changed) {
|
|
245
|
-
touched = true;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return touched;
|
|
249
|
-
}
|
|
250
|
-
async function applyMutation(mutation, context, manifestId, observers) {
|
|
251
|
-
switch (mutation.kind) {
|
|
252
|
-
case "ensureDirectory": {
|
|
253
|
-
validateHomeRelativePath(mutation.targetDirectory, context);
|
|
254
|
-
const targetPath = resolvePath({ targetDirectory: mutation.targetDirectory }, context);
|
|
255
|
-
const details = createMutationDetails(mutation, manifestId, targetPath, context);
|
|
256
|
-
observers?.onStart?.(details);
|
|
257
|
-
try {
|
|
258
|
-
const existed = await pathExists(context.fs, targetPath);
|
|
259
|
-
await context.fs.mkdir(targetPath, { recursive: true });
|
|
260
|
-
observers?.onComplete?.(details, {
|
|
261
|
-
changed: !existed,
|
|
262
|
-
effect: "mkdir",
|
|
263
|
-
detail: existed ? "noop" : "create"
|
|
264
|
-
});
|
|
265
|
-
flushCommandDryRun(context);
|
|
266
|
-
return !existed;
|
|
267
|
-
}
|
|
268
|
-
catch (error) {
|
|
269
|
-
observers?.onError?.(details, error);
|
|
270
|
-
throw error;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
case "createBackup": {
|
|
274
|
-
validateHomeRelativePath(mutation.target, context);
|
|
275
|
-
const targetPath = resolvePath(mutation.target, context);
|
|
276
|
-
const timestamp = mutation.timestamp
|
|
277
|
-
? resolveValue(mutation.timestamp, mutationContext(context))
|
|
278
|
-
: undefined;
|
|
279
|
-
const details = createMutationDetails(mutation, manifestId, targetPath, context);
|
|
280
|
-
observers?.onStart?.(details);
|
|
281
|
-
try {
|
|
282
|
-
const backupPath = await createBackup(context.fs, targetPath, timestamp);
|
|
283
|
-
observers?.onComplete?.(details, {
|
|
284
|
-
changed: backupPath != null,
|
|
285
|
-
effect: backupPath ? "copy" : "none",
|
|
286
|
-
detail: backupPath ? "backup" : "noop"
|
|
287
|
-
});
|
|
288
|
-
flushCommandDryRun(context);
|
|
289
|
-
}
|
|
290
|
-
catch (error) {
|
|
291
|
-
observers?.onError?.(details, error);
|
|
292
|
-
throw error;
|
|
293
|
-
}
|
|
294
|
-
return false;
|
|
295
|
-
}
|
|
296
|
-
case "writeTemplate": {
|
|
297
|
-
validateHomeRelativePath(mutation.target, context);
|
|
298
|
-
const targetPath = resolvePath(mutation.target, context);
|
|
299
|
-
const renderContext = mutation.context
|
|
300
|
-
? resolveValue(mutation.context, mutationContext(context))
|
|
301
|
-
: undefined;
|
|
302
|
-
const rendered = await renderTemplate(mutation.templateId, renderContext ?? {});
|
|
303
|
-
const details = createMutationDetails(mutation, manifestId, targetPath, context);
|
|
304
|
-
observers?.onStart?.(details);
|
|
305
|
-
try {
|
|
306
|
-
const existed = await pathExists(context.fs, targetPath);
|
|
307
|
-
await context.fs.writeFile(targetPath, rendered, { encoding: "utf8" });
|
|
308
|
-
observers?.onComplete?.(details, {
|
|
309
|
-
changed: true,
|
|
310
|
-
effect: "write",
|
|
311
|
-
detail: existed ? "update" : "create"
|
|
312
|
-
});
|
|
313
|
-
flushCommandDryRun(context);
|
|
314
|
-
}
|
|
315
|
-
catch (error) {
|
|
316
|
-
observers?.onError?.(details, error);
|
|
317
|
-
throw error;
|
|
318
|
-
}
|
|
319
|
-
return true;
|
|
320
|
-
}
|
|
321
|
-
case "chmod": {
|
|
322
|
-
validateHomeRelativePath(mutation.target, context);
|
|
323
|
-
const targetPath = resolvePath(mutation.target, context);
|
|
324
|
-
const details = createMutationDetails(mutation, manifestId, targetPath, context);
|
|
325
|
-
observers?.onStart?.(details);
|
|
326
|
-
try {
|
|
327
|
-
if (typeof context.fs.chmod !== "function") {
|
|
328
|
-
observers?.onComplete?.(details, {
|
|
329
|
-
changed: false,
|
|
330
|
-
effect: "none",
|
|
331
|
-
detail: "noop"
|
|
332
|
-
});
|
|
333
|
-
flushCommandDryRun(context);
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
const stat = await context.fs.stat(targetPath);
|
|
337
|
-
const currentMode = typeof stat.mode === "number" ? stat.mode & 0o777 : null;
|
|
338
|
-
if (currentMode === mutation.mode) {
|
|
339
|
-
observers?.onComplete?.(details, {
|
|
340
|
-
changed: false,
|
|
341
|
-
effect: "none",
|
|
342
|
-
detail: "noop"
|
|
343
|
-
});
|
|
344
|
-
flushCommandDryRun(context);
|
|
345
|
-
return false;
|
|
346
|
-
}
|
|
347
|
-
await context.fs.chmod(targetPath, mutation.mode);
|
|
348
|
-
observers?.onComplete?.(details, {
|
|
349
|
-
changed: true,
|
|
350
|
-
effect: "chmod",
|
|
351
|
-
detail: "update"
|
|
352
|
-
});
|
|
353
|
-
flushCommandDryRun(context);
|
|
354
|
-
return true;
|
|
355
|
-
}
|
|
356
|
-
catch (error) {
|
|
357
|
-
if (isNotFound(error)) {
|
|
358
|
-
observers?.onComplete?.(details, {
|
|
359
|
-
changed: false,
|
|
360
|
-
effect: "none",
|
|
361
|
-
detail: "noop"
|
|
362
|
-
});
|
|
363
|
-
flushCommandDryRun(context);
|
|
364
|
-
return false;
|
|
365
|
-
}
|
|
366
|
-
observers?.onError?.(details, error);
|
|
367
|
-
throw error;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
case "removeFile": {
|
|
371
|
-
validateHomeRelativePath(mutation.target, context);
|
|
372
|
-
const targetPath = resolvePath(mutation.target, context);
|
|
373
|
-
const details = createMutationDetails(mutation, manifestId, targetPath, context);
|
|
374
|
-
observers?.onStart?.(details);
|
|
375
|
-
try {
|
|
376
|
-
const raw = await context.fs.readFile(targetPath, "utf8");
|
|
377
|
-
const trimmed = raw.trim();
|
|
378
|
-
if (mutation.whenContentMatches &&
|
|
379
|
-
!mutation.whenContentMatches.test(trimmed)) {
|
|
380
|
-
observers?.onComplete?.(details, {
|
|
381
|
-
changed: false,
|
|
382
|
-
effect: "none",
|
|
383
|
-
detail: "noop"
|
|
384
|
-
});
|
|
385
|
-
flushCommandDryRun(context);
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
|
-
if (mutation.whenEmpty && trimmed.length > 0) {
|
|
389
|
-
observers?.onComplete?.(details, {
|
|
390
|
-
changed: false,
|
|
391
|
-
effect: "none",
|
|
392
|
-
detail: "noop"
|
|
393
|
-
});
|
|
394
|
-
flushCommandDryRun(context);
|
|
395
|
-
return false;
|
|
396
|
-
}
|
|
397
|
-
await context.fs.unlink(targetPath);
|
|
398
|
-
observers?.onComplete?.(details, {
|
|
399
|
-
changed: true,
|
|
400
|
-
effect: "delete",
|
|
401
|
-
detail: "delete"
|
|
402
|
-
});
|
|
403
|
-
flushCommandDryRun(context);
|
|
404
|
-
return true;
|
|
405
|
-
}
|
|
406
|
-
catch (error) {
|
|
407
|
-
if (isNotFound(error)) {
|
|
408
|
-
observers?.onComplete?.(details, {
|
|
409
|
-
changed: false,
|
|
410
|
-
effect: "none",
|
|
411
|
-
detail: "noop"
|
|
412
|
-
});
|
|
413
|
-
flushCommandDryRun(context);
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
observers?.onError?.(details, error);
|
|
417
|
-
throw error;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
case "transformFile": {
|
|
421
|
-
validateHomeRelativePath(mutation.target, context);
|
|
422
|
-
const targetPath = resolvePath(mutation.target, context);
|
|
423
|
-
const current = await readFileIfExists(context.fs, targetPath);
|
|
424
|
-
const details = createMutationDetails(mutation, manifestId, targetPath, context);
|
|
425
|
-
observers?.onStart?.(details);
|
|
426
|
-
try {
|
|
427
|
-
const result = await mutation.transform({
|
|
428
|
-
content: current,
|
|
429
|
-
context: mutationContext(context)
|
|
430
|
-
});
|
|
431
|
-
const transformOutcome = await persistTransformResult({
|
|
432
|
-
fs: context.fs,
|
|
433
|
-
targetPath,
|
|
434
|
-
previousContent: current,
|
|
435
|
-
result
|
|
436
|
-
});
|
|
437
|
-
observers?.onComplete?.(details, transformOutcome);
|
|
438
|
-
flushCommandDryRun(context);
|
|
439
|
-
return transformOutcome.changed;
|
|
440
|
-
}
|
|
441
|
-
catch (error) {
|
|
442
|
-
observers?.onError?.(details, error);
|
|
443
|
-
throw error;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
default: {
|
|
447
|
-
const neverMutation = mutation;
|
|
448
|
-
throw new Error(`Unsupported mutation kind: ${neverMutation.kind}`);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
function validateHomeRelativePath(resolver, context) {
|
|
453
|
-
const raw = resolveRawPathResolver(resolver, context);
|
|
454
|
-
if (typeof raw !== "string" || raw.length === 0) {
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
if (raw.startsWith("~")) {
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
throw new Error(`Service manifest targets must live under home (~): received "${raw}".`);
|
|
461
|
-
}
|
|
462
|
-
function resolveRawPathResolver(resolver, context) {
|
|
463
|
-
const location = normalizeResolverToLocation(resolver);
|
|
464
|
-
if ("target" in location && location.target !== undefined) {
|
|
465
|
-
return resolveValue(location.target, mutationContext(context));
|
|
466
|
-
}
|
|
467
|
-
return resolveValue(location.targetDirectory, mutationContext(context));
|
|
468
|
-
}
|
|
469
|
-
function mutationContext(context) {
|
|
470
|
-
return {
|
|
471
|
-
fs: context.fs,
|
|
472
|
-
options: context.options,
|
|
473
|
-
env: context.env
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
function createMutationDetails(mutation, manifestId, targetPath, context) {
|
|
477
|
-
const customLabel = mutation.label != null
|
|
478
|
-
? resolveValue(mutation.label, mutationContext(context))
|
|
479
|
-
: undefined;
|
|
480
|
-
const label = customLabel ?? describeMutationOperation(mutation.kind, targetPath);
|
|
481
|
-
return {
|
|
482
|
-
manifestId,
|
|
483
|
-
kind: mutation.kind,
|
|
484
|
-
label,
|
|
485
|
-
targetPath
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
function describeMutationOperation(kind, targetPath) {
|
|
489
|
-
const displayPath = targetPath ?? "target";
|
|
490
|
-
switch (kind) {
|
|
491
|
-
case "ensureDirectory":
|
|
492
|
-
return `Create ${displayPath}`;
|
|
493
|
-
case "createBackup":
|
|
494
|
-
return `Backup ${displayPath}`;
|
|
495
|
-
case "writeTemplate":
|
|
496
|
-
return `Write ${displayPath}`;
|
|
497
|
-
case "chmod":
|
|
498
|
-
return `Set permissions on ${displayPath}`;
|
|
499
|
-
case "removeFile":
|
|
500
|
-
return `Remove ${displayPath}`;
|
|
501
|
-
case "transformFile":
|
|
502
|
-
return `Update ${displayPath}`;
|
|
503
|
-
default:
|
|
504
|
-
return "Operation";
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
function resolveValue(resolver, context) {
|
|
508
|
-
if (typeof resolver === "function") {
|
|
509
|
-
return resolver(context);
|
|
510
|
-
}
|
|
511
|
-
return resolver;
|
|
512
|
-
}
|
|
513
|
-
function resolvePath(resolver, context) {
|
|
514
|
-
const location = normalizeResolverToLocation(resolver);
|
|
515
|
-
if ("target" in location && location.target !== undefined) {
|
|
516
|
-
const raw = resolveValue(location.target, mutationContext(context));
|
|
517
|
-
const expanded = expandHomeShortcut(raw, context.env);
|
|
518
|
-
if (!context.pathMapper) {
|
|
519
|
-
return expanded;
|
|
520
|
-
}
|
|
521
|
-
const rawDirectory = path.dirname(expanded);
|
|
522
|
-
const mappedDirectory = context.pathMapper.mapTargetDirectory({
|
|
523
|
-
targetDirectory: rawDirectory,
|
|
524
|
-
env: context.env
|
|
525
|
-
});
|
|
526
|
-
const rawFile = path.basename(expanded);
|
|
527
|
-
return rawFile.length === 0 ? mappedDirectory : path.join(mappedDirectory, rawFile);
|
|
528
|
-
}
|
|
529
|
-
const rawDirectory = resolveValue(location.targetDirectory, mutationContext(context));
|
|
530
|
-
const expandedDirectory = expandHomeShortcut(rawDirectory, context.env);
|
|
531
|
-
const mappedDirectory = context.pathMapper
|
|
532
|
-
? context.pathMapper.mapTargetDirectory({
|
|
533
|
-
targetDirectory: expandedDirectory,
|
|
534
|
-
env: context.env
|
|
535
|
-
})
|
|
536
|
-
: expandedDirectory;
|
|
537
|
-
if (location.targetFile === undefined) {
|
|
538
|
-
return mappedDirectory;
|
|
539
|
-
}
|
|
540
|
-
const rawFile = resolveValue(location.targetFile, mutationContext(context));
|
|
541
|
-
return rawFile.length === 0 ? mappedDirectory : path.join(mappedDirectory, rawFile);
|
|
542
|
-
}
|
|
543
|
-
function normalizeResolverToLocation(resolver) {
|
|
544
|
-
if (typeof resolver === "object" && resolver != null) {
|
|
545
|
-
if ("target" in resolver || "targetDirectory" in resolver) {
|
|
546
|
-
return resolver;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
return {
|
|
550
|
-
target: resolver
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
function normalizeTargetLocation(config) {
|
|
554
|
-
if (config.target) {
|
|
555
|
-
return { target: config.target };
|
|
556
|
-
}
|
|
557
|
-
if (config.targetDirectory) {
|
|
558
|
-
return {
|
|
559
|
-
targetDirectory: config.targetDirectory,
|
|
560
|
-
targetFile: config.targetFile
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
throw new Error("Missing target for service manifest mutation.");
|
|
564
|
-
}
|
|
565
|
-
function resolveTargetPath(config, context) {
|
|
566
|
-
if (config.target) {
|
|
567
|
-
return expandHomeShortcut(resolveValue(config.target, context), context.env);
|
|
568
|
-
}
|
|
569
|
-
if (!config.targetDirectory) {
|
|
570
|
-
throw new Error("Missing targetDirectory.");
|
|
571
|
-
}
|
|
572
|
-
const directory = expandHomeShortcut(resolveValue(config.targetDirectory, context), context.env);
|
|
573
|
-
if (!config.targetFile) {
|
|
574
|
-
return directory;
|
|
575
|
-
}
|
|
576
|
-
const file = resolveValue(config.targetFile, context);
|
|
577
|
-
return file.length === 0 ? directory : path.join(directory, file);
|
|
578
|
-
}
|
|
579
|
-
function flushCommandDryRun(context) {
|
|
580
|
-
context.command.flushDryRun({ emitIfEmpty: false });
|
|
581
|
-
}
|
|
582
|
-
function expandHomeShortcut(targetPath, env) {
|
|
583
|
-
if (!targetPath?.startsWith("~")) {
|
|
584
|
-
return targetPath;
|
|
585
|
-
}
|
|
586
|
-
if (targetPath.startsWith("~./")) {
|
|
587
|
-
targetPath = `~/.${targetPath.slice(3)}`;
|
|
588
|
-
}
|
|
589
|
-
const homeDir = env?.homeDir ?? process.env.HOME ?? process.env.USERPROFILE;
|
|
590
|
-
if (!homeDir) {
|
|
591
|
-
return targetPath;
|
|
592
|
-
}
|
|
593
|
-
let remainder = targetPath.slice(1);
|
|
594
|
-
if (remainder.startsWith("/")) {
|
|
595
|
-
remainder = remainder.slice(1);
|
|
596
|
-
}
|
|
597
|
-
else if (remainder.startsWith("\\")) {
|
|
598
|
-
remainder = remainder.slice(1);
|
|
599
|
-
}
|
|
600
|
-
else if (remainder.startsWith(".")) {
|
|
601
|
-
remainder = remainder.slice(1);
|
|
602
|
-
if (remainder.startsWith("/")) {
|
|
603
|
-
remainder = remainder.slice(1);
|
|
604
|
-
}
|
|
605
|
-
else if (remainder.startsWith("\\")) {
|
|
606
|
-
remainder = remainder.slice(1);
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
return remainder.length === 0 ? homeDir : path.join(homeDir, remainder);
|
|
610
|
-
}
|
|
611
|
-
function parseJson(content) {
|
|
612
|
-
if (content == null) {
|
|
613
|
-
return {};
|
|
614
|
-
}
|
|
615
|
-
const parsed = JSON.parse(content);
|
|
616
|
-
if (!isJsonObject(parsed)) {
|
|
617
|
-
throw new Error("Expected JSON object for manifest-managed file.");
|
|
618
|
-
}
|
|
619
|
-
return parsed;
|
|
620
|
-
}
|
|
621
|
-
async function parseJsonWithRecovery(input) {
|
|
622
|
-
try {
|
|
623
|
-
return parseJson(input.content);
|
|
624
|
-
}
|
|
625
|
-
catch {
|
|
626
|
-
await backupInvalidJsonDocument(input);
|
|
627
|
-
return {};
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
async function parseTomlWithRecovery(input) {
|
|
631
|
-
if (input.content == null) {
|
|
632
|
-
return {};
|
|
633
|
-
}
|
|
634
|
-
try {
|
|
635
|
-
return parseTomlDocument(input.content);
|
|
636
|
-
}
|
|
637
|
-
catch {
|
|
638
|
-
await backupInvalidTomlDocument(input);
|
|
639
|
-
return {};
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
async function backupInvalidJsonDocument(input) {
|
|
643
|
-
if (input.content == null) {
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
646
|
-
const backupPath = createInvalidDocumentBackupPath(input.targetPath);
|
|
647
|
-
await input.fs.writeFile(backupPath, input.content, { encoding: "utf8" });
|
|
648
|
-
}
|
|
649
|
-
async function backupInvalidTomlDocument(input) {
|
|
650
|
-
if (input.content == null) {
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
const backupPath = createInvalidDocumentBackupPath(input.targetPath);
|
|
654
|
-
await input.fs.writeFile(backupPath, input.content, { encoding: "utf8" });
|
|
655
|
-
}
|
|
656
|
-
function createInvalidDocumentBackupPath(targetPath) {
|
|
657
|
-
return `${targetPath}.invalid-${createTimestamp()}.json`;
|
|
658
|
-
}
|
|
659
|
-
function createTimestamp() {
|
|
660
|
-
return new Date()
|
|
661
|
-
.toISOString()
|
|
662
|
-
.replaceAll(":", "-")
|
|
663
|
-
.replaceAll(".", "-");
|
|
664
|
-
}
|
|
665
|
-
function serializeJson(value) {
|
|
666
|
-
return `${JSON.stringify(value, null, 2)}\n`;
|
|
667
|
-
}
|
|
668
|
-
async function persistTransformResult(input) {
|
|
669
|
-
if (!input.result.changed) {
|
|
670
|
-
return { changed: false, effect: "none", detail: "noop" };
|
|
671
|
-
}
|
|
672
|
-
if (input.result.content == null) {
|
|
673
|
-
if (input.previousContent == null) {
|
|
674
|
-
return { changed: false, effect: "none", detail: "noop" };
|
|
675
|
-
}
|
|
676
|
-
await input.fs.unlink(input.targetPath);
|
|
677
|
-
return { changed: true, effect: "delete", detail: "delete" };
|
|
678
|
-
}
|
|
679
|
-
await input.fs.writeFile(input.targetPath, input.result.content, {
|
|
680
|
-
encoding: "utf8"
|
|
681
|
-
});
|
|
682
|
-
return {
|
|
683
|
-
changed: true,
|
|
684
|
-
effect: "write",
|
|
685
|
-
detail: input.previousContent == null ? "create" : "update"
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
async function readFileIfExists(fs, target) {
|
|
689
|
-
try {
|
|
690
|
-
return await fs.readFile(target, "utf8");
|
|
691
|
-
}
|
|
692
|
-
catch (error) {
|
|
693
|
-
if (isNotFound(error)) {
|
|
694
|
-
return null;
|
|
695
|
-
}
|
|
696
|
-
throw error;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
async function pathExists(fs, target) {
|
|
700
|
-
try {
|
|
701
|
-
await fs.stat(target);
|
|
702
|
-
return true;
|
|
703
|
-
}
|
|
704
|
-
catch (error) {
|
|
705
|
-
if (isNotFound(error)) {
|
|
706
|
-
return false;
|
|
707
|
-
}
|
|
708
|
-
throw error;
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
function isNotFound(error) {
|
|
712
|
-
return (typeof error === "object" &&
|
|
713
|
-
error !== null &&
|
|
714
|
-
"code" in error &&
|
|
715
|
-
error.code === "ENOENT");
|
|
716
|
-
}
|
|
717
|
-
//# sourceMappingURL=service-manifest.js.map
|