cligr 1.0.5 → 1.0.7

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.
@@ -11,15 +11,15 @@
11
11
  import { describe, it } from 'node:test';
12
12
  import assert from 'node:assert';
13
13
  import { TemplateExpander } from '../../src/process/template.js';
14
- import type { ProcessItem } from '../../src/config/types.js';
14
+ import type { ProcessItem, ItemEntry } from '../../src/config/types.js';
15
15
 
16
16
  describe('TemplateExpander Integration Tests', () => {
17
17
  describe('expand()', () => {
18
18
  it('should expand template with single argument', () => {
19
19
  const template = 'echo $1';
20
- const itemStr = 'hello';
20
+ const item: ItemEntry = { name: 'hello', value: 'hello' };
21
21
 
22
- const result = TemplateExpander.expand(template, itemStr, 0);
22
+ const result = TemplateExpander.expand(template, item, 0);
23
23
 
24
24
  assert.strictEqual(result.name, 'hello');
25
25
  assert.deepStrictEqual(result.args, ['hello']);
@@ -28,9 +28,9 @@ describe('TemplateExpander Integration Tests', () => {
28
28
 
29
29
  it('should expand template with multiple arguments', () => {
30
30
  const template = 'docker run -p $2:$3 $1';
31
- const itemStr = 'nginx,8080,80';
31
+ const item: ItemEntry = { name: 'nginx', value: 'nginx,8080,80' };
32
32
 
33
- const result = TemplateExpander.expand(template, itemStr, 0);
33
+ const result = TemplateExpander.expand(template, item, 0);
34
34
 
35
35
  assert.strictEqual(result.name, 'nginx');
36
36
  assert.deepStrictEqual(result.args, ['nginx', '8080', '80']);
@@ -39,27 +39,27 @@ describe('TemplateExpander Integration Tests', () => {
39
39
 
40
40
  it('should replace all occurrences of placeholder', () => {
41
41
  const template = 'echo $1 and $1 again';
42
- const itemStr = 'test';
42
+ const item: ItemEntry = { name: 'test', value: 'test' };
43
43
 
44
- const result = TemplateExpander.expand(template, itemStr, 0);
44
+ const result = TemplateExpander.expand(template, item, 0);
45
45
 
46
46
  assert.strictEqual(result.fullCmd, 'echo test and test again');
47
47
  });
48
48
 
49
49
  it('should handle placeholders with spaces around', () => {
50
50
  const template = 'cmd $1 opt $2 end';
51
- const itemStr = 'arg1,arg2';
51
+ const item: ItemEntry = { name: 'args', value: 'arg1,arg2' };
52
52
 
53
- const result = TemplateExpander.expand(template, itemStr, 0);
53
+ const result = TemplateExpander.expand(template, item, 0);
54
54
 
55
55
  assert.strictEqual(result.fullCmd, 'cmd arg1 opt arg2 end');
56
56
  });
57
57
 
58
- it('should use index as name when first argument is empty', () => {
58
+ it('should use ItemEntry name when first argument is empty', () => {
59
59
  const template = 'echo test';
60
- const itemStr = ',arg2,arg3';
60
+ const item: ItemEntry = { name: 'item-5', value: ',arg2,arg3' };
61
61
 
62
- const result = TemplateExpander.expand(template, itemStr, 5);
62
+ const result = TemplateExpander.expand(template, item, 5);
63
63
 
64
64
  assert.strictEqual(result.name, 'item-5');
65
65
  assert.deepStrictEqual(result.args, ['', 'arg2', 'arg3']);
@@ -67,29 +67,29 @@ describe('TemplateExpander Integration Tests', () => {
67
67
 
68
68
  it('should handle single argument with no commas', () => {
69
69
  const template = 'node $1';
70
- const itemStr = 'server.js';
70
+ const item: ItemEntry = { name: 'server', value: 'server.js' };
71
71
 
72
- const result = TemplateExpander.expand(template, itemStr, 0);
72
+ const result = TemplateExpander.expand(template, item, 0);
73
73
 
74
- assert.strictEqual(result.name, 'server.js');
74
+ assert.strictEqual(result.name, 'server');
75
75
  assert.deepStrictEqual(result.args, ['server.js']);
76
76
  assert.strictEqual(result.fullCmd, 'node server.js');
77
77
  });
78
78
 
79
79
  it('should handle more placeholders than arguments', () => {
80
80
  const template = 'cmd $1 $2 $3 $4';
81
- const itemStr = 'a,b';
81
+ const item: ItemEntry = { name: 'args', value: 'a,b' };
82
82
 
83
- const result = TemplateExpander.expand(template, itemStr, 0);
83
+ const result = TemplateExpander.expand(template, item, 0);
84
84
 
85
85
  assert.strictEqual(result.fullCmd, 'cmd a b $3 $4');
86
86
  });
87
87
 
88
88
  it('should trim whitespace from arguments', () => {
89
89
  const template = 'cmd $1 $2 $3';
90
- const itemStr = ' a , b , c ';
90
+ const item: ItemEntry = { name: 'args', value: ' a , b , c ' };
91
91
 
92
- const result = TemplateExpander.expand(template, itemStr, 0);
92
+ const result = TemplateExpander.expand(template, item, 0);
93
93
 
94
94
  assert.deepStrictEqual(result.args, ['a', 'b', 'c']);
95
95
  assert.strictEqual(result.fullCmd, 'cmd a b c');
@@ -97,9 +97,9 @@ describe('TemplateExpander Integration Tests', () => {
97
97
 
98
98
  it('should handle empty string argument', () => {
99
99
  const template = 'cmd $1 $2 $3';
100
- const itemStr = 'first,,third';
100
+ const item: ItemEntry = { name: 'args', value: 'first,,third' };
101
101
 
102
- const result = TemplateExpander.expand(template, itemStr, 0);
102
+ const result = TemplateExpander.expand(template, item, 0);
103
103
 
104
104
  assert.deepStrictEqual(result.args, ['first', '', 'third']);
105
105
  assert.strictEqual(result.fullCmd, 'cmd first third');
@@ -107,9 +107,9 @@ describe('TemplateExpander Integration Tests', () => {
107
107
 
108
108
  it('should handle quoted paths with spaces in template', () => {
109
109
  const template = '"C:\\Program Files\\app\\app.exe" $1';
110
- const itemStr = 'arg1';
110
+ const item: ItemEntry = { name: 'arg', value: 'arg1' };
111
111
 
112
- const result = TemplateExpander.expand(template, itemStr, 0);
112
+ const result = TemplateExpander.expand(template, item, 0);
113
113
 
114
114
  assert.strictEqual(result.fullCmd, '"C:\\Program Files\\app\\app.exe" arg1');
115
115
  });
@@ -120,9 +120,9 @@ describe('TemplateExpander Integration Tests', () => {
120
120
  it('should use tool template for expansion', () => {
121
121
  const tool = 'docker';
122
122
  const toolTemplate = 'docker run -it --rm $1';
123
- const itemStr = 'nginx,-p,80:80';
123
+ const item: ItemEntry = { name: 'nginx', value: 'nginx,-p,80:80' };
124
124
 
125
- const result = TemplateExpander.parseItem(tool, toolTemplate, itemStr, 0);
125
+ const result = TemplateExpander.parseItem(tool, toolTemplate, item, 0);
126
126
 
127
127
  assert.strictEqual(result.name, 'nginx');
128
128
  assert.strictEqual(result.fullCmd, 'docker run -it --rm nginx -p 80:80');
@@ -131,9 +131,9 @@ describe('TemplateExpander Integration Tests', () => {
131
131
  it('should handle complex docker compose templates', () => {
132
132
  const tool = 'compose';
133
133
  const toolTemplate = 'docker-compose run --service-ports $1';
134
- const itemStr = 'web';
134
+ const item: ItemEntry = { name: 'web', value: 'web' };
135
135
 
136
- const result = TemplateExpander.parseItem(tool, toolTemplate, itemStr, 0);
136
+ const result = TemplateExpander.parseItem(tool, toolTemplate, item, 0);
137
137
 
138
138
  assert.strictEqual(result.name, 'web');
139
139
  assert.strictEqual(result.fullCmd, 'docker-compose run --service-ports web');
@@ -142,9 +142,9 @@ describe('TemplateExpander Integration Tests', () => {
142
142
  it('should handle templates with no placeholders', () => {
143
143
  const tool = 'echo';
144
144
  const toolTemplate = 'echo hello world';
145
- const itemStr = 'item1';
145
+ const item: ItemEntry = { name: 'item1', value: 'item1' };
146
146
 
147
- const result = TemplateExpander.parseItem(tool, toolTemplate, itemStr, 0);
147
+ const result = TemplateExpander.parseItem(tool, toolTemplate, item, 0);
148
148
 
149
149
  assert.strictEqual(result.name, 'item1');
150
150
  assert.strictEqual(result.fullCmd, 'echo hello world');
@@ -155,31 +155,31 @@ describe('TemplateExpander Integration Tests', () => {
155
155
  it('should prefix command with tool name', () => {
156
156
  const tool = 'node';
157
157
  const toolTemplate = null;
158
- const itemStr = 'server.js,3000';
158
+ const item: ItemEntry = { name: 'server', value: 'server.js,3000' };
159
159
 
160
- const result = TemplateExpander.parseItem(tool, toolTemplate, itemStr, 0);
160
+ const result = TemplateExpander.parseItem(tool, toolTemplate, item, 0);
161
161
 
162
- assert.strictEqual(result.name, 'server.js');
162
+ assert.strictEqual(result.name, 'server');
163
163
  assert.strictEqual(result.fullCmd, 'node server.js,3000');
164
164
  });
165
165
 
166
166
  it('should handle null tool and toolTemplate', () => {
167
167
  const tool = null;
168
168
  const toolTemplate = null;
169
- const itemStr = 'echo hello';
169
+ const item: ItemEntry = { name: 'echo', value: 'echo hello' };
170
170
 
171
- const result = TemplateExpander.parseItem(tool, toolTemplate, itemStr, 0);
171
+ const result = TemplateExpander.parseItem(tool, toolTemplate, item, 0);
172
172
 
173
173
  assert.strictEqual(result.name, 'echo');
174
174
  assert.strictEqual(result.fullCmd, 'echo hello');
175
175
  });
176
176
 
177
- it('should use index for name when args are empty', () => {
177
+ it('should use ItemEntry name when value is empty', () => {
178
178
  const tool = null;
179
179
  const toolTemplate = null;
180
- const itemStr = '';
180
+ const item: ItemEntry = { name: 'item-3', value: '' };
181
181
 
182
- const result = TemplateExpander.parseItem(tool, toolTemplate, itemStr, 3);
182
+ const result = TemplateExpander.parseItem(tool, toolTemplate, item, 3);
183
183
 
184
184
  assert.strictEqual(result.name, 'item-3');
185
185
  });
@@ -188,11 +188,11 @@ describe('TemplateExpander Integration Tests', () => {
188
188
  const tool = 'python';
189
189
  const toolTemplate = null;
190
190
 
191
- const result1 = TemplateExpander.parseItem(tool, toolTemplate, 'script1.py', 0);
192
- const result2 = TemplateExpander.parseItem(tool, toolTemplate, 'script2.py', 1);
191
+ const result1 = TemplateExpander.parseItem(tool, toolTemplate, { name: 'script1', value: 'script1.py' }, 0);
192
+ const result2 = TemplateExpander.parseItem(tool, toolTemplate, { name: 'script2', value: 'script2.py' }, 1);
193
193
 
194
- assert.strictEqual(result1.name, 'script1.py');
195
- assert.strictEqual(result2.name, 'script2.py');
194
+ assert.strictEqual(result1.name, 'script1');
195
+ assert.strictEqual(result2.name, 'script2');
196
196
  });
197
197
  });
198
198
  });
@@ -200,9 +200,9 @@ describe('TemplateExpander Integration Tests', () => {
200
200
  describe('Real-world scenarios', () => {
201
201
  it('should handle docker service templates', () => {
202
202
  const toolTemplate = 'docker run -d --name $1_$2 -p $2:$3 $1';
203
- const itemStr = 'nginx,8080,80';
203
+ const item: ItemEntry = { name: 'nginx', value: 'nginx,8080,80' };
204
204
 
205
- const result = TemplateExpander.expand(toolTemplate, itemStr, 0);
205
+ const result = TemplateExpander.expand(toolTemplate, item, 0);
206
206
 
207
207
  assert.strictEqual(result.name, 'nginx');
208
208
  assert.strictEqual(result.fullCmd, 'docker run -d --name nginx_8080 -p 8080:80 nginx');
@@ -210,19 +210,19 @@ describe('TemplateExpander Integration Tests', () => {
210
210
 
211
211
  it('should handle node process manager templates', () => {
212
212
  const toolTemplate = 'node $1 --port $2';
213
- const itemStr = 'server.js,3000';
213
+ const item: ItemEntry = { name: 'server', value: 'server.js,3000' };
214
214
 
215
- const result = TemplateExpander.expand(toolTemplate, itemStr, 0);
215
+ const result = TemplateExpander.expand(toolTemplate, item, 0);
216
216
 
217
- assert.strictEqual(result.name, 'server.js');
217
+ assert.strictEqual(result.name, 'server');
218
218
  assert.strictEqual(result.fullCmd, 'node server.js --port 3000');
219
219
  });
220
220
 
221
221
  it('should handle database connection templates', () => {
222
222
  const toolTemplate = 'psql -h $1 -p $2 -U $3 -d $4';
223
- const itemStr = 'localhost,5432,admin,mydb';
223
+ const item: ItemEntry = { name: 'localhost', value: 'localhost,5432,admin,mydb' };
224
224
 
225
- const result = TemplateExpander.expand(toolTemplate, itemStr, 0);
225
+ const result = TemplateExpander.expand(toolTemplate, item, 0);
226
226
 
227
227
  assert.strictEqual(result.name, 'localhost');
228
228
  assert.strictEqual(result.fullCmd, 'psql -h localhost -p 5432 -U admin -d mydb');
@@ -230,9 +230,9 @@ describe('TemplateExpander Integration Tests', () => {
230
230
 
231
231
  it('should handle custom script execution', () => {
232
232
  const toolTemplate = './scripts/$1.sh $2 $3';
233
- const itemStr = 'deploy,production,force';
233
+ const item: ItemEntry = { name: 'deploy', value: 'deploy,production,force' };
234
234
 
235
- const result = TemplateExpander.expand(toolTemplate, itemStr, 0);
235
+ const result = TemplateExpander.expand(toolTemplate, item, 0);
236
236
 
237
237
  assert.strictEqual(result.name, 'deploy');
238
238
  assert.strictEqual(result.fullCmd, './scripts/deploy.sh production force');
@@ -240,11 +240,11 @@ describe('TemplateExpander Integration Tests', () => {
240
240
 
241
241
  it('should handle Windows executable paths', () => {
242
242
  const toolTemplate = '"C:\\My App\\app.exe" --config $1 --port $2';
243
- const itemStr = 'config.json,8080';
243
+ const item: ItemEntry = { name: 'config', value: 'config.json,8080' };
244
244
 
245
- const result = TemplateExpander.expand(toolTemplate, itemStr, 0);
245
+ const result = TemplateExpander.expand(toolTemplate, item, 0);
246
246
 
247
- assert.strictEqual(result.name, 'config.json');
247
+ assert.strictEqual(result.name, 'config');
248
248
  assert.strictEqual(result.fullCmd, '"C:\\My App\\app.exe" --config config.json --port 8080');
249
249
  });
250
250
  });
@@ -252,9 +252,9 @@ describe('TemplateExpander Integration Tests', () => {
252
252
  describe('Edge cases and error handling', () => {
253
253
  it('should handle very long argument lists', () => {
254
254
  const template = Array.from({ length: 20 }, (_, i) => `$${i + 1}`).join(' ');
255
- const itemStr = Array.from({ length: 20 }, (_, i) => `arg${i}`).join(',');
255
+ const item: ItemEntry = { name: 'args', value: Array.from({ length: 20 }, (_, i) => `arg${i}`).join(',') };
256
256
 
257
- const result = TemplateExpander.expand(template, itemStr, 0);
257
+ const result = TemplateExpander.expand(template, item, 0);
258
258
 
259
259
  assert.strictEqual(result.args.length, 20);
260
260
  assert.ok(result.fullCmd.includes('arg0'));
@@ -263,38 +263,38 @@ describe('TemplateExpander Integration Tests', () => {
263
263
 
264
264
  it('should handle special characters in arguments', () => {
265
265
  const template = 'echo "$1" "$2"';
266
- const itemStr = 'hello world,test&argument';
266
+ const item: ItemEntry = { name: 'args', value: 'hello world,test&argument' };
267
267
 
268
- const result = TemplateExpander.expand(template, itemStr, 0);
268
+ const result = TemplateExpander.expand(template, item, 0);
269
269
 
270
270
  assert.deepStrictEqual(result.args, ['hello world', 'test&argument']);
271
271
  });
272
272
 
273
273
  it('should handle unicode characters', () => {
274
274
  const template = 'echo $1 $2';
275
- const itemStr = 'こんにちは,世界';
275
+ const item: ItemEntry = { name: 'unicode', value: 'こんにちは,世界' };
276
276
 
277
- const result = TemplateExpander.expand(template, itemStr, 0);
277
+ const result = TemplateExpander.expand(template, item, 0);
278
278
 
279
- assert.strictEqual(result.name, 'こんにちは');
279
+ assert.strictEqual(result.name, 'unicode');
280
280
  assert.deepStrictEqual(result.args, ['こんにちは', '世界']);
281
281
  assert.strictEqual(result.fullCmd, 'echo こんにちは 世界');
282
282
  });
283
283
 
284
284
  it('should handle numeric arguments', () => {
285
285
  const template = 'app --port $1 --timeout $2 --retries $3';
286
- const itemStr = '8080,5000,5';
286
+ const item: ItemEntry = { name: 'ports', value: '8080,5000,5' };
287
287
 
288
- const result = TemplateExpander.expand(template, itemStr, 0);
288
+ const result = TemplateExpander.expand(template, item, 0);
289
289
 
290
290
  assert.strictEqual(result.fullCmd, 'app --port 8080 --timeout 5000 --retries 5');
291
291
  });
292
292
 
293
293
  it('should preserve whitespace in command template', () => {
294
294
  const template = 'cmd $1 $2';
295
- const itemStr = 'a,b';
295
+ const item: ItemEntry = { name: 'args', value: 'a,b' };
296
296
 
297
- const result = TemplateExpander.expand(template, itemStr, 0);
297
+ const result = TemplateExpander.expand(template, item, 0);
298
298
 
299
299
  // Template whitespace is preserved
300
300
  assert.strictEqual(result.fullCmd, 'cmd a b');
@@ -302,9 +302,13 @@ describe('TemplateExpander Integration Tests', () => {
302
302
  });
303
303
 
304
304
  describe('Multiple items in sequence', () => {
305
- it('should generate unique names using index', () => {
305
+ it('should generate unique names using ItemEntry name', () => {
306
306
  const template = 'worker $1';
307
- const items = ['job1', 'job2', 'job3'];
307
+ const items: ItemEntry[] = [
308
+ { name: 'job1', value: 'job1' },
309
+ { name: 'job2', value: 'job2' },
310
+ { name: 'job3', value: 'job3' }
311
+ ];
308
312
 
309
313
  const results = items.map((item, index) =>
310
314
  TemplateExpander.expand(template, item, index)
@@ -315,27 +319,31 @@ describe('TemplateExpander Integration Tests', () => {
315
319
  assert.strictEqual(results[2].name, 'job3');
316
320
  });
317
321
 
318
- it('should use index as fallback for identical names', () => {
322
+ it('should use ItemEntry name for identical values', () => {
319
323
  const template = 'echo $1';
320
- const items = ['test', 'test', 'test'];
324
+ const items: ItemEntry[] = [
325
+ { name: 'test1', value: 'test' },
326
+ { name: 'test2', value: 'test' },
327
+ { name: 'test3', value: 'test' }
328
+ ];
321
329
 
322
330
  const results = items.map((item, index) =>
323
331
  TemplateExpander.expand(template, item, index)
324
332
  );
325
333
 
326
- // All will have name 'test' since first arg is used
327
- assert.strictEqual(results[0].name, 'test');
328
- assert.strictEqual(results[1].name, 'test');
329
- assert.strictEqual(results[2].name, 'test');
334
+ // All will have their unique ItemEntry name
335
+ assert.strictEqual(results[0].name, 'test1');
336
+ assert.strictEqual(results[1].name, 'test2');
337
+ assert.strictEqual(results[2].name, 'test3');
330
338
  });
331
339
  });
332
340
 
333
341
  describe('ProcessItem type compliance', () => {
334
342
  it('should return valid ProcessItem objects', () => {
335
343
  const template = 'cmd $1';
336
- const itemStr = 'arg1,arg2';
344
+ const item: ItemEntry = { name: 'arg1', value: 'arg1,arg2' };
337
345
 
338
- const result: ProcessItem = TemplateExpander.expand(template, itemStr, 0);
346
+ const result: ProcessItem = TemplateExpander.expand(template, item, 0);
339
347
 
340
348
  assert.strictEqual(typeof result.name, 'string');
341
349
  assert.ok(Array.isArray(result.args));
@@ -346,9 +354,9 @@ describe('TemplateExpander Integration Tests', () => {
346
354
 
347
355
  it('should have consistent structure across different calls', () => {
348
356
  const results: ProcessItem[] = [
349
- TemplateExpander.expand('echo $1', 'test', 0),
350
- TemplateExpander.expand('cmd $1 $2', 'a,b', 1),
351
- TemplateExpander.parseItem('node', null, 'app.js', 2),
357
+ TemplateExpander.expand('echo $1', { name: 'test', value: 'test' }, 0),
358
+ TemplateExpander.expand('cmd $1 $2', { name: 'args', value: 'a,b' }, 1),
359
+ TemplateExpander.parseItem('node', null, { name: 'app', value: 'app.js' }, 2),
352
360
  ];
353
361
 
354
362
  for (const result of results) {
@@ -363,10 +371,10 @@ describe('TemplateExpander Integration Tests', () => {
363
371
  describe('Named params', () => {
364
372
  it('should replace named param in template', () => {
365
373
  const template = 'node $1.js --name $name';
366
- const itemStr = 'server';
374
+ const item: ItemEntry = { name: 'server', value: 'server' };
367
375
  const params = { name: 'John doe' };
368
376
 
369
- const result = TemplateExpander.expand(template, itemStr, 0, params);
377
+ const result = TemplateExpander.expand(template, item, 0, params);
370
378
 
371
379
  assert.strictEqual(result.name, 'server');
372
380
  assert.strictEqual(result.fullCmd, 'node server.js --name John doe');
@@ -374,49 +382,49 @@ describe('TemplateExpander Integration Tests', () => {
374
382
 
375
383
  it('should replace multiple named params', () => {
376
384
  const template = 'app --host $host --port $port --env $env';
377
- const itemStr = 'myapp';
385
+ const item: ItemEntry = { name: 'myapp', value: 'myapp' };
378
386
  const params = { host: 'localhost', port: '3000', env: 'production' };
379
387
 
380
- const result = TemplateExpander.expand(template, itemStr, 0, params);
388
+ const result = TemplateExpander.expand(template, item, 0, params);
381
389
 
382
390
  assert.strictEqual(result.fullCmd, 'app --host localhost --port 3000 --env production');
383
391
  });
384
392
 
385
393
  it('should combine positional and named params', () => {
386
394
  const template = 'node $1.js --name $name --port $port';
387
- const itemStr = 'server';
395
+ const item: ItemEntry = { name: 'server', value: 'server' };
388
396
  const params = { name: 'Alice', port: '8080' };
389
397
 
390
- const result = TemplateExpander.expand(template, itemStr, 0, params);
398
+ const result = TemplateExpander.expand(template, item, 0, params);
391
399
 
392
400
  assert.strictEqual(result.fullCmd, 'node server.js --name Alice --port 8080');
393
401
  });
394
402
 
395
403
  it('should handle empty params object', () => {
396
404
  const template = 'node $1.js';
397
- const itemStr = 'server';
405
+ const item: ItemEntry = { name: 'server', value: 'server' };
398
406
 
399
- const result = TemplateExpander.expand(template, itemStr, 0, {});
407
+ const result = TemplateExpander.expand(template, item, 0, {});
400
408
 
401
409
  assert.strictEqual(result.fullCmd, 'node server.js');
402
410
  });
403
411
 
404
412
  it('should leave unreplaced named params as-is', () => {
405
413
  const template = 'node $1.js --name $name --env $env';
406
- const itemStr = 'server';
414
+ const item: ItemEntry = { name: 'server', value: 'server' };
407
415
  const params = { name: 'Bob' }; // env not provided
408
416
 
409
- const result = TemplateExpander.expand(template, itemStr, 0, params);
417
+ const result = TemplateExpander.expand(template, item, 0, params);
410
418
 
411
419
  assert.strictEqual(result.fullCmd, 'node server.js --name Bob --env $env');
412
420
  });
413
421
 
414
422
  it('should replace all occurrences of named param', () => {
415
423
  const template = 'echo $name and $name again';
416
- const itemStr = 'test';
424
+ const item: ItemEntry = { name: 'test', value: 'test' };
417
425
  const params = { name: 'world' };
418
426
 
419
- const result = TemplateExpander.expand(template, itemStr, 0, params);
427
+ const result = TemplateExpander.expand(template, item, 0, params);
420
428
 
421
429
  assert.strictEqual(result.fullCmd, 'echo world and world again');
422
430
  });
@@ -424,10 +432,10 @@ describe('TemplateExpander Integration Tests', () => {
424
432
  it('should work with parseItem for registered tools', () => {
425
433
  const tool = 'node-param';
426
434
  const toolTemplate = 'node $1.js --name $name';
427
- const itemStr = 'server';
435
+ const item: ItemEntry = { name: 'server', value: 'server' };
428
436
  const params = { name: 'Charlie' };
429
437
 
430
- const result = TemplateExpander.parseItem(tool, toolTemplate, itemStr, 0, params);
438
+ const result = TemplateExpander.parseItem(tool, toolTemplate, item, 0, params);
431
439
 
432
440
  assert.strictEqual(result.name, 'server');
433
441
  assert.strictEqual(result.fullCmd, 'node server.js --name Charlie');
@@ -435,10 +443,10 @@ describe('TemplateExpander Integration Tests', () => {
435
443
 
436
444
  it('should handle named params with spaces in values', () => {
437
445
  const template = 'echo "Hello, $name!"';
438
- const itemStr = 'test';
446
+ const item: ItemEntry = { name: 'test', value: 'test' };
439
447
  const params = { name: 'John Doe' };
440
448
 
441
- const result = TemplateExpander.expand(template, itemStr, 0, params);
449
+ const result = TemplateExpander.expand(template, item, 0, params);
442
450
 
443
451
  assert.strictEqual(result.fullCmd, 'echo "Hello, John Doe!"');
444
452
  });
@@ -1,13 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(node scripts/test.js --verbose)",
5
- "Bash(node:*)",
6
- "Bash(npm test)",
7
- "Bash(git add:*)",
8
- "Bash(git commit:*)",
9
- "Bash(git reset:*)",
10
- "Bash(npm run build:*)"
11
- ]
12
- }
13
- }
@@ -1,102 +0,0 @@
1
- import { spawn, spawnSync } from "child_process";
2
- import fs from "fs";
3
- import os from "os";
4
- import path from "path";
5
- const CONFIG_FILENAME = ".cligr.yml";
6
- const TEMPLATE = `# Cligr Configuration
7
-
8
- groups:
9
- web:
10
- tool: docker
11
- restart: false
12
- items:
13
- - "nginx,8080" # $1=nginx (name), $2=8080 (port)
14
- - "nginx,3000"
15
-
16
- simple:
17
- tool: node
18
- items:
19
- - "server" # $1=server (name only)
20
-
21
- tools:
22
- docker:
23
- cmd: "docker run -p $2:$2 nginx" # $1=name, $2=port
24
- node:
25
- cmd: "node $1.js" # $1=file name
26
-
27
- # Syntax:
28
- # - Items are comma-separated: "name,arg2,arg3"
29
- # - $1 = name (first value)
30
- # - $2, $3... = additional arguments
31
- # - If no tool specified, executes directly
32
- `;
33
- function detectEditor() {
34
- const platform = process.platform;
35
- const whichCmd = platform === "win32" ? "where" : "which";
36
- const codeCheck = spawnSync(whichCmd, ["code"], { stdio: "ignore" });
37
- if (codeCheck.status === 0) {
38
- return "code";
39
- }
40
- if (process.env.EDITOR) {
41
- return process.env.EDITOR;
42
- }
43
- if (platform === "win32") {
44
- return "notepad.exe";
45
- }
46
- return "vim";
47
- }
48
- function spawnEditor(filePath, editorCmd) {
49
- const platform = process.platform;
50
- const whichCmd = platform === "win32" ? "where" : "which";
51
- const editorCheck = spawnSync(whichCmd, [editorCmd], { stdio: "ignore" });
52
- if (editorCheck.status !== 0 && editorCmd !== process.env.EDITOR) {
53
- throw new Error(
54
- `Editor '${editorCmd}' not found.
55
- Install VS Code or set EDITOR environment variable.
56
-
57
- Example:
58
- export EDITOR=vim
59
- cligr config`
60
- );
61
- }
62
- const child = spawn(editorCmd, [filePath], {
63
- detached: true,
64
- stdio: "ignore",
65
- shell: platform === "win32"
66
- });
67
- child.unref();
68
- }
69
- function createTemplate(filePath) {
70
- const dir = path.dirname(filePath);
71
- if (!fs.existsSync(dir)) {
72
- fs.mkdirSync(dir, { recursive: true });
73
- }
74
- fs.writeFileSync(filePath, TEMPLATE, "utf-8");
75
- }
76
- async function configCommand() {
77
- try {
78
- const homeDirConfig = path.join(os.homedir(), CONFIG_FILENAME);
79
- const currentDirConfig = path.resolve(CONFIG_FILENAME);
80
- let configPath;
81
- if (fs.existsSync(homeDirConfig)) {
82
- configPath = homeDirConfig;
83
- } else if (fs.existsSync(currentDirConfig)) {
84
- configPath = currentDirConfig;
85
- } else {
86
- configPath = homeDirConfig;
87
- }
88
- if (!fs.existsSync(configPath)) {
89
- createTemplate(configPath);
90
- }
91
- const editor = detectEditor();
92
- spawnEditor(configPath, editor);
93
- console.log(`Opening ${configPath} in ${editor}...`);
94
- return 0;
95
- } catch (err) {
96
- console.error(`Error: ${err.message}`);
97
- return 1;
98
- }
99
- }
100
- export {
101
- configCommand
102
- };
@@ -1,26 +0,0 @@
1
- import { ProcessManager } from "../process/manager.js";
2
- async function downCommand(groupName) {
3
- const manager = new ProcessManager();
4
- const result = await manager.killGroupByPid(groupName);
5
- if (result.killed === 0 && result.notRunning === 0) {
6
- console.log(`Group '${groupName}' is not running`);
7
- return 0;
8
- }
9
- if (result.killed > 0) {
10
- console.log(`Stopped ${result.killed} process(es) for group '${groupName}'`);
11
- }
12
- if (result.notRunning > 0) {
13
- console.log(`Cleaned up ${result.notRunning} stale PID file(s) for group '${groupName}'`);
14
- }
15
- if (result.errors.length > 0) {
16
- console.error("Errors while stopping processes:");
17
- for (const err of result.errors) {
18
- console.error(` ${err}`);
19
- }
20
- return 1;
21
- }
22
- return 0;
23
- }
24
- export {
25
- downCommand
26
- };