@enactprotocol/shared 2.0.4 → 2.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/execution/command.d.ts +31 -0
- package/dist/execution/command.d.ts.map +1 -1
- package/dist/execution/command.js +86 -10
- package/dist/execution/command.js.map +1 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/types.d.ts +21 -0
- package/dist/execution/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/execution/command.ts +100 -10
- package/src/execution/index.ts +2 -0
- package/src/execution/types.ts +24 -1
- package/tests/execution/command.test.ts +155 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
prepareCommand,
|
|
12
12
|
shellEscape,
|
|
13
13
|
} from "../../src/execution/command";
|
|
14
|
+
import type { CommandWarning } from "../../src/execution/types";
|
|
14
15
|
|
|
15
16
|
describe("Command Interpolation", () => {
|
|
16
17
|
describe("parseCommand", () => {
|
|
@@ -69,6 +70,63 @@ describe("Command Interpolation", () => {
|
|
|
69
70
|
|
|
70
71
|
expect(result.parameters).toEqual(["name"]);
|
|
71
72
|
});
|
|
73
|
+
|
|
74
|
+
test("parses :raw modifier", () => {
|
|
75
|
+
const result = parseCommand("echo ${data:raw}");
|
|
76
|
+
|
|
77
|
+
expect(result.parameters).toEqual(["data"]);
|
|
78
|
+
expect(result.tokens).toHaveLength(2);
|
|
79
|
+
expect(result.tokens[1]).toEqual({ type: "parameter", name: "data", raw: true });
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("detects single-quoted parameter", () => {
|
|
83
|
+
const result = parseCommand("echo '${message}'");
|
|
84
|
+
|
|
85
|
+
expect(result.tokens).toHaveLength(2);
|
|
86
|
+
expect(result.tokens[0]).toEqual({ type: "literal", value: "echo " });
|
|
87
|
+
expect(result.tokens[1]).toEqual({
|
|
88
|
+
type: "parameter",
|
|
89
|
+
name: "message",
|
|
90
|
+
surroundingQuotes: "single",
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("detects double-quoted parameter", () => {
|
|
95
|
+
const result = parseCommand('echo "${message}"');
|
|
96
|
+
|
|
97
|
+
expect(result.tokens).toHaveLength(2);
|
|
98
|
+
expect(result.tokens[1]).toEqual({
|
|
99
|
+
type: "parameter",
|
|
100
|
+
name: "message",
|
|
101
|
+
surroundingQuotes: "double",
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("handles mix of quoted and unquoted parameters", () => {
|
|
106
|
+
const result = parseCommand("cmd '${a}' ${b} \"${c}\"");
|
|
107
|
+
|
|
108
|
+
expect(result.parameters).toEqual(["a", "b", "c"]);
|
|
109
|
+
expect(result.tokens[1]).toMatchObject({ name: "a", surroundingQuotes: "single" });
|
|
110
|
+
expect(result.tokens[3]).toMatchObject({ name: "b" });
|
|
111
|
+
expect(
|
|
112
|
+
(result.tokens[3] as { surroundingQuotes?: string }).surroundingQuotes
|
|
113
|
+
).toBeUndefined();
|
|
114
|
+
expect(result.tokens[5]).toMatchObject({ name: "c", surroundingQuotes: "double" });
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("does not detect quotes that don't surround the parameter", () => {
|
|
118
|
+
// Single quote before but not after
|
|
119
|
+
const result1 = parseCommand("echo '${a} foo");
|
|
120
|
+
expect(
|
|
121
|
+
(result1.tokens[1] as { surroundingQuotes?: string }).surroundingQuotes
|
|
122
|
+
).toBeUndefined();
|
|
123
|
+
|
|
124
|
+
// Mismatched quotes
|
|
125
|
+
const result2 = parseCommand("echo '${a}\"");
|
|
126
|
+
expect(
|
|
127
|
+
(result2.tokens[1] as { surroundingQuotes?: string }).surroundingQuotes
|
|
128
|
+
).toBeUndefined();
|
|
129
|
+
});
|
|
72
130
|
});
|
|
73
131
|
|
|
74
132
|
describe("interpolateCommand", () => {
|
|
@@ -154,6 +212,103 @@ describe("Command Interpolation", () => {
|
|
|
154
212
|
|
|
155
213
|
expect(result).toBe("echo [1,2,3]");
|
|
156
214
|
});
|
|
215
|
+
|
|
216
|
+
test("handles :raw modifier - no escaping", () => {
|
|
217
|
+
const result = interpolateCommand("echo ${data:raw}", {
|
|
218
|
+
data: "hello world",
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// Without :raw, "hello world" would become 'hello world' (quoted)
|
|
222
|
+
// With :raw, it stays as-is
|
|
223
|
+
expect(result).toBe("echo hello world");
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("handles :raw modifier with JSON", () => {
|
|
227
|
+
const result = interpolateCommand("echo ${json:raw}", {
|
|
228
|
+
json: { key: "value" },
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// JSON is stringified but not quoted
|
|
232
|
+
expect(result).toBe('echo {"key":"value"}');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("strips surrounding single quotes and applies proper escaping", () => {
|
|
236
|
+
// This is the key fix for the double-quoting issue
|
|
237
|
+
const result = interpolateCommand("node script.js '${input}'", {
|
|
238
|
+
input: '[{"name":"Alice"}]',
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// The surrounding quotes are stripped, and the value is properly escaped
|
|
242
|
+
// JSON with special chars gets single-quoted by shellEscape
|
|
243
|
+
expect(result).toBe('node script.js \'[{"name":"Alice"}]\'');
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("strips surrounding double quotes and applies proper escaping", () => {
|
|
247
|
+
const result = interpolateCommand('node script.js "${input}"', {
|
|
248
|
+
input: "hello world",
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// The surrounding quotes are stripped, value gets quoted by shellEscape
|
|
252
|
+
expect(result).toBe("node script.js 'hello world'");
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test("emits warning when stripping surrounding quotes", () => {
|
|
256
|
+
const warnings: CommandWarning[] = [];
|
|
257
|
+
|
|
258
|
+
interpolateCommand(
|
|
259
|
+
"echo '${message}'",
|
|
260
|
+
{ message: "test" },
|
|
261
|
+
{
|
|
262
|
+
onWarning: (w) => warnings.push(w),
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
expect(warnings).toHaveLength(1);
|
|
267
|
+
expect(warnings[0]?.code).toBe("DOUBLE_QUOTING");
|
|
268
|
+
expect(warnings[0]?.parameter).toBe("message");
|
|
269
|
+
expect(warnings[0]?.suggestion).toContain("${message}");
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("no warning for unquoted parameters", () => {
|
|
273
|
+
const warnings: CommandWarning[] = [];
|
|
274
|
+
|
|
275
|
+
interpolateCommand(
|
|
276
|
+
"echo ${message}",
|
|
277
|
+
{ message: "test" },
|
|
278
|
+
{
|
|
279
|
+
onWarning: (w) => warnings.push(w),
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
expect(warnings).toHaveLength(0);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("handles complex JSON input without double-quoting", () => {
|
|
287
|
+
// This is the exact case from the user's feedback
|
|
288
|
+
const result = interpolateCommand(
|
|
289
|
+
"node dist/index.js ${input} ${input_format} ${output_format}",
|
|
290
|
+
{
|
|
291
|
+
input: '[{"name":"Alice"}]',
|
|
292
|
+
input_format: "json",
|
|
293
|
+
output_format: "csv",
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
// JSON gets quoted, simple strings don't
|
|
298
|
+
expect(result).toBe('node dist/index.js \'[{"name":"Alice"}]\' json csv');
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
test("handles quoted parameter template that would have caused double-quoting", () => {
|
|
302
|
+
// Without the fix, this would produce: node dist/index.js ''[{"name":"Alice"}]''
|
|
303
|
+
// With the fix, surrounding quotes are stripped first
|
|
304
|
+
const result = interpolateCommand("node dist/index.js '${input}'", {
|
|
305
|
+
input: '[{"name":"Alice"}]',
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Should NOT have double quotes
|
|
309
|
+
expect(result).not.toContain("''");
|
|
310
|
+
expect(result).toBe('node dist/index.js \'[{"name":"Alice"}]\'');
|
|
311
|
+
});
|
|
157
312
|
});
|
|
158
313
|
|
|
159
314
|
describe("shellEscape", () => {
|