poe-code 2.0.19 → 2.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +21 -19
  2. package/dist/bin/poe-claude.js +16 -0
  3. package/dist/bin/poe-codex.js +16 -0
  4. package/dist/bin/poe-opencode.js +16 -0
  5. package/dist/cli/binary-aliases.d.ts +7 -0
  6. package/dist/cli/binary-aliases.js +26 -0
  7. package/dist/cli/binary-aliases.js.map +1 -0
  8. package/dist/cli/command-runner.js +7 -1
  9. package/dist/cli/command-runner.js.map +1 -1
  10. package/dist/cli/commands/configure-payload.d.ts +13 -0
  11. package/dist/cli/commands/configure-payload.js +33 -0
  12. package/dist/cli/commands/configure-payload.js.map +1 -0
  13. package/dist/cli/commands/configure.js +16 -107
  14. package/dist/cli/commands/configure.js.map +1 -1
  15. package/dist/cli/commands/doctor.js +8 -1
  16. package/dist/cli/commands/doctor.js.map +1 -1
  17. package/dist/cli/commands/ensure-isolated-config.d.ts +11 -0
  18. package/dist/cli/commands/ensure-isolated-config.js +48 -0
  19. package/dist/cli/commands/ensure-isolated-config.js.map +1 -0
  20. package/dist/cli/commands/remove.js +20 -1
  21. package/dist/cli/commands/remove.js.map +1 -1
  22. package/dist/cli/commands/shared.d.ts +11 -1
  23. package/dist/cli/commands/shared.js +23 -4
  24. package/dist/cli/commands/shared.js.map +1 -1
  25. package/dist/cli/commands/test.d.ts +4 -1
  26. package/dist/cli/commands/test.js +37 -6
  27. package/dist/cli/commands/test.js.map +1 -1
  28. package/dist/cli/commands/wrap.d.ts +3 -0
  29. package/dist/cli/commands/wrap.js +54 -0
  30. package/dist/cli/commands/wrap.js.map +1 -0
  31. package/dist/cli/container.js +9 -2
  32. package/dist/cli/container.js.map +1 -1
  33. package/dist/cli/context.d.ts +5 -1
  34. package/dist/cli/context.js +12 -0
  35. package/dist/cli/context.js.map +1 -1
  36. package/dist/cli/isolated-env-runner.d.ts +10 -0
  37. package/dist/cli/isolated-env-runner.js +44 -0
  38. package/dist/cli/isolated-env-runner.js.map +1 -0
  39. package/dist/cli/isolated-env.d.ts +22 -0
  40. package/dist/cli/isolated-env.js +128 -0
  41. package/dist/cli/isolated-env.js.map +1 -0
  42. package/dist/cli/poe-code-command-runner.d.ts +6 -0
  43. package/dist/cli/poe-code-command-runner.js +54 -0
  44. package/dist/cli/poe-code-command-runner.js.map +1 -0
  45. package/dist/cli/program.js +2 -0
  46. package/dist/cli/program.js.map +1 -1
  47. package/dist/cli/service-registry.d.ts +30 -11
  48. package/dist/cli/service-registry.js.map +1 -1
  49. package/dist/providers/claude-code.d.ts +2 -2
  50. package/dist/providers/claude-code.js +70 -22
  51. package/dist/providers/claude-code.js.map +1 -1
  52. package/dist/providers/codex.d.ts +1 -1
  53. package/dist/providers/codex.js +21 -8
  54. package/dist/providers/codex.js.map +1 -1
  55. package/dist/providers/create-provider.d.ts +7 -8
  56. package/dist/providers/create-provider.js +1 -2
  57. package/dist/providers/create-provider.js.map +1 -1
  58. package/dist/providers/kimi.d.ts +2 -2
  59. package/dist/providers/kimi.js +7 -5
  60. package/dist/providers/kimi.js.map +1 -1
  61. package/dist/providers/opencode.d.ts +1 -1
  62. package/dist/providers/opencode.js +23 -8
  63. package/dist/providers/opencode.js.map +1 -1
  64. package/dist/providers/provider-helpers.js +12 -1
  65. package/dist/providers/provider-helpers.js.map +1 -1
  66. package/dist/providers/spawn-options.d.ts +2 -2
  67. package/dist/providers/versioned-provider.d.ts +2 -2
  68. package/dist/services/service-manifest.d.ts +65 -16
  69. package/dist/services/service-manifest.js +163 -19
  70. package/dist/services/service-manifest.js.map +1 -1
  71. package/dist/templates/claude-code/anthropic_key.sh.hbs +1 -1
  72. package/dist/utils/command-checks.d.ts +1 -0
  73. package/dist/utils/command-checks.js.map +1 -1
  74. package/package.json +6 -3
@@ -1 +1 @@
1
- {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/providers/opencode.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/providers/opencode.ts"],"names":[],"mappings":"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"}
@@ -2,9 +2,10 @@ import path from "node:path";
2
2
  export function makeExecutableMutation(config) {
3
3
  const mode = config.mode ?? 0o700;
4
4
  const resolver = toResolver(config.target);
5
+ const target = toManifestTarget(config.target);
5
6
  return {
6
7
  kind: "transformFile",
7
- target: resolver,
8
+ target,
8
9
  label: (context) => `Make file executable ${resolveTargetPath(resolver, context)}`,
9
10
  async transform({ content, context }) {
10
11
  if (typeof context.fs.chmod === "function" && content != null) {
@@ -25,6 +26,16 @@ function toResolver(input) {
25
26
  }
26
27
  return () => input;
27
28
  }
29
+ function toManifestTarget(input) {
30
+ if (typeof input === "function") {
31
+ return {
32
+ target: (context) => input({ options: context.options })
33
+ };
34
+ }
35
+ return {
36
+ target: input
37
+ };
38
+ }
28
39
  function resolveTargetPath(resolver, context) {
29
40
  const raw = resolver(context);
30
41
  if (!raw.startsWith("~")) {
@@ -1 +1 @@
1
- {"version":3,"file":"provider-helpers.js","sourceRoot":"","sources":["../../src/providers/provider-helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider-helpers.js","sourceRoot":"","sources":["../../src/providers/provider-helpers.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ export interface SpawnCommandOptions {
6
6
  useStdin?: boolean;
7
7
  }
8
8
  export type ProviderSpawnOptions<Extra extends Record<string, unknown> = Record<string, never>> = SpawnCommandOptions & Extra;
9
- export interface DefaultModelConfigureOptions {
10
- defaultModel: string;
9
+ export interface ModelConfigureOptions {
10
+ model: string;
11
11
  }
12
12
  export type EmptyProviderOptions = Record<string, never>;
@@ -1,3 +1,3 @@
1
1
  import type { ProviderContext } from "../cli/service-registry.js";
2
- export type ProviderVersionResolver<TPaths extends Record<string, unknown>> = (context: ProviderContext<TPaths>) => Promise<string | null>;
3
- export declare function createBinaryVersionResolver(binaryName: string): ProviderVersionResolver<Record<string, string>>;
2
+ export type ProviderVersionResolver = (context: ProviderContext) => Promise<string | null>;
3
+ export declare function createBinaryVersionResolver(binaryName: string): ProviderVersionResolver;
@@ -4,11 +4,29 @@ import type { FileSystem } from "../utils/file-system.js";
4
4
  import { type JsonObject } from "../utils/json.js";
5
5
  import { type TomlTable } from "../utils/toml.js";
6
6
  type ValueResolver<Options, Value> = Value | ((context: MutationContext<Options>) => Value);
7
+ type TargetPathResolver<Options> = ValueResolver<Options, string>;
8
+ type TargetDirectoryResolver<Options> = ValueResolver<Options, string>;
9
+ type TargetFileResolver<Options> = ValueResolver<Options, string>;
10
+ export type TargetLocation<Options> = {
11
+ target: TargetPathResolver<Options>;
12
+ targetDirectory?: never;
13
+ targetFile?: never;
14
+ } | {
15
+ target?: never;
16
+ targetDirectory: TargetDirectoryResolver<Options>;
17
+ targetFile?: TargetFileResolver<Options>;
18
+ };
7
19
  interface MutationContext<Options> {
8
20
  options: Options;
9
21
  fs: FileSystem;
10
22
  env: CliEnvironment;
11
23
  }
24
+ export interface ServiceManifestPathMapper {
25
+ mapTargetDirectory: (input: {
26
+ targetDirectory: string;
27
+ env: CliEnvironment;
28
+ }) => string;
29
+ }
12
30
  interface TransformResult {
13
31
  content: string | null;
14
32
  changed: boolean;
@@ -16,7 +34,7 @@ interface TransformResult {
16
34
  interface TransformFileMutation<Options> {
17
35
  kind: "transformFile";
18
36
  label?: ValueResolver<Options, string | undefined>;
19
- target: ValueResolver<Options, string>;
37
+ target: TargetLocation<Options>;
20
38
  transform(input: {
21
39
  content: string | null;
22
40
  context: MutationContext<Options>;
@@ -25,29 +43,35 @@ interface TransformFileMutation<Options> {
25
43
  interface EnsureDirectoryMutation<Options> {
26
44
  kind: "ensureDirectory";
27
45
  label?: ValueResolver<Options, string | undefined>;
28
- path: ValueResolver<Options, string>;
46
+ targetDirectory: TargetDirectoryResolver<Options>;
29
47
  }
30
48
  interface CreateBackupMutation<Options> {
31
49
  kind: "createBackup";
32
50
  label?: ValueResolver<Options, string | undefined>;
33
- target: ValueResolver<Options, string>;
51
+ target: TargetLocation<Options>;
34
52
  timestamp?: ValueResolver<Options, (() => string) | undefined>;
35
53
  }
36
54
  interface WriteTemplateMutation<Options> {
37
55
  kind: "writeTemplate";
38
56
  label?: ValueResolver<Options, string | undefined>;
39
- target: ValueResolver<Options, string>;
57
+ target: TargetLocation<Options>;
40
58
  templateId: string;
41
59
  context?: ValueResolver<Options, JsonObject | undefined>;
42
60
  }
43
61
  interface RemoveFileMutation<Options> {
44
62
  kind: "removeFile";
45
63
  label?: ValueResolver<Options, string | undefined>;
46
- target: ValueResolver<Options, string>;
64
+ target: TargetLocation<Options>;
47
65
  whenEmpty?: boolean;
48
66
  whenContentMatches?: RegExp;
49
67
  }
50
- export type ServiceMutation<Options> = TransformFileMutation<Options> | EnsureDirectoryMutation<Options> | CreateBackupMutation<Options> | WriteTemplateMutation<Options> | RemoveFileMutation<Options>;
68
+ interface ChmodMutation<Options> {
69
+ kind: "chmod";
70
+ label?: ValueResolver<Options, string | undefined>;
71
+ target: TargetLocation<Options>;
72
+ mode: number;
73
+ }
74
+ export type ServiceMutation<Options> = TransformFileMutation<Options> | EnsureDirectoryMutation<Options> | CreateBackupMutation<Options> | WriteTemplateMutation<Options> | RemoveFileMutation<Options> | ChmodMutation<Options>;
51
75
  export interface ServiceManifestDefinition<ConfigureOptions, RemoveOptions = ConfigureOptions> {
52
76
  id: string;
53
77
  summary: string;
@@ -67,6 +91,7 @@ export interface ServiceExecutionContext<Options> {
67
91
  env: CliEnvironment;
68
92
  command: CommandContext;
69
93
  options: Options;
94
+ pathMapper?: ServiceManifestPathMapper;
70
95
  }
71
96
  export interface MutationLogDetails {
72
97
  manifestId: string;
@@ -80,44 +105,64 @@ export interface ServiceMutationOutcome {
80
105
  effect: MutationEffect;
81
106
  detail?: MutationDetail;
82
107
  }
83
- export type MutationEffect = "none" | "mkdir" | "copy" | "write" | "delete";
108
+ export type MutationEffect = "none" | "mkdir" | "copy" | "write" | "delete" | "chmod";
84
109
  export interface ServiceMutationObservers {
85
110
  onStart?(details: MutationLogDetails): void;
86
111
  onComplete?(details: MutationLogDetails, outcome: ServiceMutationOutcome): void;
87
112
  onError?(details: MutationLogDetails, error: unknown): void;
88
113
  }
89
114
  export declare function ensureDirectory<Options>(config: {
90
- path: ValueResolver<Options, string>;
115
+ path?: ValueResolver<Options, string>;
116
+ targetDirectory?: ValueResolver<Options, string>;
91
117
  label?: ValueResolver<Options, string | undefined>;
92
118
  }): ServiceMutation<Options>;
93
119
  export declare function createBackupMutation<Options>(config: {
94
- target: ValueResolver<Options, string>;
120
+ target?: ValueResolver<Options, string>;
121
+ targetDirectory?: ValueResolver<Options, string>;
122
+ targetFile?: ValueResolver<Options, string>;
95
123
  timestamp?: ValueResolver<Options, (() => string) | undefined>;
96
124
  label?: ValueResolver<Options, string | undefined>;
97
125
  }): ServiceMutation<Options>;
98
126
  export declare function writeTemplateMutation<Options>(config: {
99
- target: ValueResolver<Options, string>;
127
+ target?: ValueResolver<Options, string>;
128
+ targetDirectory?: ValueResolver<Options, string>;
129
+ targetFile?: ValueResolver<Options, string>;
100
130
  templateId: string;
101
131
  context?: ValueResolver<Options, JsonObject | undefined>;
102
132
  label?: ValueResolver<Options, string | undefined>;
103
133
  }): ServiceMutation<Options>;
134
+ export declare function chmodMutation<Options>(config: {
135
+ target?: ValueResolver<Options, string>;
136
+ targetDirectory?: ValueResolver<Options, string>;
137
+ targetFile?: ValueResolver<Options, string>;
138
+ mode: number;
139
+ label?: ValueResolver<Options, string | undefined>;
140
+ }): ServiceMutation<Options>;
104
141
  export declare function jsonMergeMutation<Options>(config: {
105
- target: ValueResolver<Options, string>;
142
+ target?: ValueResolver<Options, string>;
143
+ targetDirectory?: ValueResolver<Options, string>;
144
+ targetFile?: ValueResolver<Options, string>;
106
145
  value: ValueResolver<Options, JsonObject>;
107
146
  label?: ValueResolver<Options, string | undefined>;
108
147
  }): ServiceMutation<Options>;
109
148
  export declare function jsonPruneMutation<Options>(config: {
110
- target: ValueResolver<Options, string>;
149
+ target?: ValueResolver<Options, string>;
150
+ targetDirectory?: ValueResolver<Options, string>;
151
+ targetFile?: ValueResolver<Options, string>;
111
152
  shape: ValueResolver<Options, JsonObject>;
112
153
  label?: ValueResolver<Options, string | undefined>;
113
154
  }): ServiceMutation<Options>;
114
155
  export declare function tomlMergeMutation<Options>(config: {
115
- target: ValueResolver<Options, string>;
156
+ target?: ValueResolver<Options, string>;
157
+ targetDirectory?: ValueResolver<Options, string>;
158
+ targetFile?: ValueResolver<Options, string>;
116
159
  value: ValueResolver<Options, TomlTable>;
117
160
  label?: ValueResolver<Options, string | undefined>;
118
161
  }): ServiceMutation<Options>;
119
162
  export declare function tomlPruneMutation<Options>(config: {
120
- target: ValueResolver<Options, string>;
163
+ target?: ValueResolver<Options, string>;
164
+ targetDirectory?: ValueResolver<Options, string>;
165
+ targetFile?: ValueResolver<Options, string>;
121
166
  prune: (document: TomlTable, context: MutationContext<Options>) => {
122
167
  changed: boolean;
123
168
  result: TomlTable | null;
@@ -125,7 +170,9 @@ export declare function tomlPruneMutation<Options>(config: {
125
170
  label?: ValueResolver<Options, string | undefined>;
126
171
  }): ServiceMutation<Options>;
127
172
  export declare function tomlTemplateMergeMutation<Options>(config: {
128
- target: ValueResolver<Options, string>;
173
+ target?: ValueResolver<Options, string>;
174
+ targetDirectory?: ValueResolver<Options, string>;
175
+ targetFile?: ValueResolver<Options, string>;
129
176
  templateId: string;
130
177
  context?: ValueResolver<Options, JsonObject | undefined>;
131
178
  label?: ValueResolver<Options, string | undefined>;
@@ -137,7 +184,9 @@ export declare function removePatternMutation<Options>(config: {
137
184
  label?: ValueResolver<Options, string | undefined>;
138
185
  }): ServiceMutation<Options>;
139
186
  export declare function removeFileMutation<Options>(config: {
140
- target: ValueResolver<Options, string>;
187
+ target?: ValueResolver<Options, string>;
188
+ targetDirectory?: ValueResolver<Options, string>;
189
+ targetFile?: ValueResolver<Options, string>;
141
190
  whenEmpty?: boolean;
142
191
  whenContentMatches?: RegExp;
143
192
  label?: ValueResolver<Options, string | undefined>;
@@ -4,16 +4,20 @@ import { renderTemplate } from "../utils/templates.js";
4
4
  import { deepMergeJson, isJsonObject, pruneJsonByShape } from "../utils/json.js";
5
5
  import { parseTomlDocument, serializeTomlDocument, mergeTomlTables } from "../utils/toml.js";
6
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
+ }
7
11
  return {
8
12
  kind: "ensureDirectory",
9
- path: config.path,
13
+ targetDirectory,
10
14
  label: config.label
11
15
  };
12
16
  }
13
17
  export function createBackupMutation(config) {
14
18
  return {
15
19
  kind: "createBackup",
16
- target: config.target,
20
+ target: normalizeTargetLocation(config),
17
21
  timestamp: config.timestamp,
18
22
  label: config.label
19
23
  };
@@ -21,20 +25,27 @@ export function createBackupMutation(config) {
21
25
  export function writeTemplateMutation(config) {
22
26
  return {
23
27
  kind: "writeTemplate",
24
- target: config.target,
28
+ target: normalizeTargetLocation(config),
25
29
  templateId: config.templateId,
26
30
  context: config.context,
27
31
  label: config.label
28
32
  };
29
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
+ }
30
42
  export function jsonMergeMutation(config) {
31
43
  return {
32
44
  kind: "transformFile",
33
- target: config.target,
45
+ target: normalizeTargetLocation(config),
34
46
  label: config.label,
35
47
  async transform({ content, context }) {
36
- const rawTarget = resolveValue(config.target, context);
37
- const targetPath = expandHomeShortcut(rawTarget, context.env);
48
+ const targetPath = resolveTargetPath(config, context);
38
49
  const current = await parseJsonWithRecovery({
39
50
  content,
40
51
  fs: context.fs,
@@ -53,7 +64,7 @@ export function jsonMergeMutation(config) {
53
64
  export function jsonPruneMutation(config) {
54
65
  return {
55
66
  kind: "transformFile",
56
- target: config.target,
67
+ target: normalizeTargetLocation(config),
57
68
  label: config.label,
58
69
  async transform({ content, context }) {
59
70
  if (content == null) {
@@ -79,11 +90,10 @@ export function jsonPruneMutation(config) {
79
90
  export function tomlMergeMutation(config) {
80
91
  return {
81
92
  kind: "transformFile",
82
- target: config.target,
93
+ target: normalizeTargetLocation(config),
83
94
  label: config.label,
84
95
  async transform({ content, context }) {
85
- const rawTarget = resolveValue(config.target, context);
86
- const targetPath = expandHomeShortcut(rawTarget, context.env);
96
+ const targetPath = resolveTargetPath(config, context);
87
97
  const current = await parseTomlWithRecovery({
88
98
  content,
89
99
  fs: context.fs,
@@ -103,7 +113,7 @@ export function tomlMergeMutation(config) {
103
113
  export function tomlPruneMutation(config) {
104
114
  return {
105
115
  kind: "transformFile",
106
- target: config.target,
116
+ target: normalizeTargetLocation(config),
107
117
  label: config.label,
108
118
  async transform({ content, context }) {
109
119
  if (content == null) {
@@ -134,11 +144,10 @@ export function tomlPruneMutation(config) {
134
144
  export function tomlTemplateMergeMutation(config) {
135
145
  return {
136
146
  kind: "transformFile",
137
- target: config.target,
147
+ target: normalizeTargetLocation(config),
138
148
  label: config.label,
139
149
  async transform({ content, context }) {
140
- const rawTarget = resolveValue(config.target, context);
141
- const targetPath = expandHomeShortcut(rawTarget, context.env);
150
+ const targetPath = resolveTargetPath(config, context);
142
151
  const current = await parseTomlWithRecovery({
143
152
  content,
144
153
  fs: context.fs,
@@ -162,7 +171,7 @@ export function tomlTemplateMergeMutation(config) {
162
171
  export function removePatternMutation(config) {
163
172
  return {
164
173
  kind: "transformFile",
165
- target: config.target,
174
+ target: { target: config.target },
166
175
  label: config.label,
167
176
  transform({ content, context }) {
168
177
  if (content == null) {
@@ -187,7 +196,7 @@ export function removePatternMutation(config) {
187
196
  export function removeFileMutation(config) {
188
197
  return {
189
198
  kind: "removeFile",
190
- target: config.target,
199
+ target: normalizeTargetLocation(config),
191
200
  whenEmpty: config.whenEmpty,
192
201
  whenContentMatches: config.whenContentMatches,
193
202
  label: config.label
@@ -233,7 +242,8 @@ async function runMutations(mutations, context, options) {
233
242
  async function applyMutation(mutation, context, manifestId, observers) {
234
243
  switch (mutation.kind) {
235
244
  case "ensureDirectory": {
236
- const targetPath = resolvePath(mutation.path, context);
245
+ validateHomeRelativePath(mutation.targetDirectory, context);
246
+ const targetPath = resolvePath({ targetDirectory: mutation.targetDirectory }, context);
237
247
  const details = createMutationDetails(mutation, manifestId, targetPath, context);
238
248
  observers?.onStart?.(details);
239
249
  try {
@@ -253,6 +263,7 @@ async function applyMutation(mutation, context, manifestId, observers) {
253
263
  }
254
264
  }
255
265
  case "createBackup": {
266
+ validateHomeRelativePath(mutation.target, context);
256
267
  const targetPath = resolvePath(mutation.target, context);
257
268
  const timestamp = mutation.timestamp
258
269
  ? resolveValue(mutation.timestamp, mutationContext(context))
@@ -275,6 +286,7 @@ async function applyMutation(mutation, context, manifestId, observers) {
275
286
  return false;
276
287
  }
277
288
  case "writeTemplate": {
289
+ validateHomeRelativePath(mutation.target, context);
278
290
  const targetPath = resolvePath(mutation.target, context);
279
291
  const renderContext = mutation.context
280
292
  ? resolveValue(mutation.context, mutationContext(context))
@@ -298,7 +310,57 @@ async function applyMutation(mutation, context, manifestId, observers) {
298
310
  }
299
311
  return true;
300
312
  }
313
+ case "chmod": {
314
+ validateHomeRelativePath(mutation.target, context);
315
+ const targetPath = resolvePath(mutation.target, context);
316
+ const details = createMutationDetails(mutation, manifestId, targetPath, context);
317
+ observers?.onStart?.(details);
318
+ try {
319
+ if (typeof context.fs.chmod !== "function") {
320
+ observers?.onComplete?.(details, {
321
+ changed: false,
322
+ effect: "none",
323
+ detail: "noop"
324
+ });
325
+ flushCommandDryRun(context);
326
+ return false;
327
+ }
328
+ const stat = await context.fs.stat(targetPath);
329
+ const currentMode = typeof stat.mode === "number" ? stat.mode & 0o777 : null;
330
+ if (currentMode === mutation.mode) {
331
+ observers?.onComplete?.(details, {
332
+ changed: false,
333
+ effect: "none",
334
+ detail: "noop"
335
+ });
336
+ flushCommandDryRun(context);
337
+ return false;
338
+ }
339
+ await context.fs.chmod(targetPath, mutation.mode);
340
+ observers?.onComplete?.(details, {
341
+ changed: true,
342
+ effect: "chmod",
343
+ detail: "update"
344
+ });
345
+ flushCommandDryRun(context);
346
+ return true;
347
+ }
348
+ catch (error) {
349
+ if (isNotFound(error)) {
350
+ observers?.onComplete?.(details, {
351
+ changed: false,
352
+ effect: "none",
353
+ detail: "noop"
354
+ });
355
+ flushCommandDryRun(context);
356
+ return false;
357
+ }
358
+ observers?.onError?.(details, error);
359
+ throw error;
360
+ }
361
+ }
301
362
  case "removeFile": {
363
+ validateHomeRelativePath(mutation.target, context);
302
364
  const targetPath = resolvePath(mutation.target, context);
303
365
  const details = createMutationDetails(mutation, manifestId, targetPath, context);
304
366
  observers?.onStart?.(details);
@@ -348,6 +410,7 @@ async function applyMutation(mutation, context, manifestId, observers) {
348
410
  }
349
411
  }
350
412
  case "transformFile": {
413
+ validateHomeRelativePath(mutation.target, context);
351
414
  const targetPath = resolvePath(mutation.target, context);
352
415
  const current = await readFileIfExists(context.fs, targetPath);
353
416
  const details = createMutationDetails(mutation, manifestId, targetPath, context);
@@ -378,6 +441,23 @@ async function applyMutation(mutation, context, manifestId, observers) {
378
441
  }
379
442
  }
380
443
  }
444
+ function validateHomeRelativePath(resolver, context) {
445
+ const raw = resolveRawPathResolver(resolver, context);
446
+ if (typeof raw !== "string" || raw.length === 0) {
447
+ return;
448
+ }
449
+ if (raw.startsWith("~")) {
450
+ return;
451
+ }
452
+ throw new Error(`Service manifest targets must live under home (~): received "${raw}".`);
453
+ }
454
+ function resolveRawPathResolver(resolver, context) {
455
+ const location = normalizeResolverToLocation(resolver);
456
+ if ("target" in location && location.target !== undefined) {
457
+ return resolveValue(location.target, mutationContext(context));
458
+ }
459
+ return resolveValue(location.targetDirectory, mutationContext(context));
460
+ }
381
461
  function mutationContext(context) {
382
462
  return {
383
463
  fs: context.fs,
@@ -406,6 +486,8 @@ function describeMutationOperation(kind, targetPath) {
406
486
  return `Create backup ${displayPath}`;
407
487
  case "writeTemplate":
408
488
  return `Write file ${displayPath}`;
489
+ case "chmod":
490
+ return `Set permissions ${displayPath}`;
409
491
  case "removeFile":
410
492
  return `Remove file ${displayPath}`;
411
493
  case "transformFile":
@@ -421,8 +503,70 @@ function resolveValue(resolver, context) {
421
503
  return resolver;
422
504
  }
423
505
  function resolvePath(resolver, context) {
424
- const raw = resolveValue(resolver, mutationContext(context));
425
- return expandHomeShortcut(raw, context.env);
506
+ const location = normalizeResolverToLocation(resolver);
507
+ if ("target" in location && location.target !== undefined) {
508
+ const raw = resolveValue(location.target, mutationContext(context));
509
+ const expanded = expandHomeShortcut(raw, context.env);
510
+ if (!context.pathMapper) {
511
+ return expanded;
512
+ }
513
+ const rawDirectory = path.dirname(expanded);
514
+ const mappedDirectory = context.pathMapper.mapTargetDirectory({
515
+ targetDirectory: rawDirectory,
516
+ env: context.env
517
+ });
518
+ const rawFile = path.basename(expanded);
519
+ return rawFile.length === 0 ? mappedDirectory : path.join(mappedDirectory, rawFile);
520
+ }
521
+ const rawDirectory = resolveValue(location.targetDirectory, mutationContext(context));
522
+ const expandedDirectory = expandHomeShortcut(rawDirectory, context.env);
523
+ const mappedDirectory = context.pathMapper
524
+ ? context.pathMapper.mapTargetDirectory({
525
+ targetDirectory: expandedDirectory,
526
+ env: context.env
527
+ })
528
+ : expandedDirectory;
529
+ if (location.targetFile === undefined) {
530
+ return mappedDirectory;
531
+ }
532
+ const rawFile = resolveValue(location.targetFile, mutationContext(context));
533
+ return rawFile.length === 0 ? mappedDirectory : path.join(mappedDirectory, rawFile);
534
+ }
535
+ function normalizeResolverToLocation(resolver) {
536
+ if (typeof resolver === "object" && resolver != null) {
537
+ if ("target" in resolver || "targetDirectory" in resolver) {
538
+ return resolver;
539
+ }
540
+ }
541
+ return {
542
+ target: resolver
543
+ };
544
+ }
545
+ function normalizeTargetLocation(config) {
546
+ if (config.target) {
547
+ return { target: config.target };
548
+ }
549
+ if (config.targetDirectory) {
550
+ return {
551
+ targetDirectory: config.targetDirectory,
552
+ targetFile: config.targetFile
553
+ };
554
+ }
555
+ throw new Error("Missing target for service manifest mutation.");
556
+ }
557
+ function resolveTargetPath(config, context) {
558
+ if (config.target) {
559
+ return expandHomeShortcut(resolveValue(config.target, context), context.env);
560
+ }
561
+ if (!config.targetDirectory) {
562
+ throw new Error("Missing targetDirectory.");
563
+ }
564
+ const directory = expandHomeShortcut(resolveValue(config.targetDirectory, context), context.env);
565
+ if (!config.targetFile) {
566
+ return directory;
567
+ }
568
+ const file = resolveValue(config.targetFile, context);
569
+ return file.length === 0 ? directory : path.join(directory, file);
426
570
  }
427
571
  function flushCommandDryRun(context) {
428
572
  context.command.flushDryRun({ emitIfEmpty: false });