@garyr/pt-cli 0.30.0 → 0.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/test-direct-template.json +24 -0
- package/tests/config.test.ts +650 -0
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@garyr/pt-cli",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.1",
|
|
4
4
|
"description": "Project Template CLI - Learn structures and initialize projects",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"pt": "
|
|
7
|
+
"pt": "dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"scripts": {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "direct-json-test",
|
|
3
|
+
"description": "A mock template for direct JSON scaffolding test",
|
|
4
|
+
"folders": [
|
|
5
|
+
{
|
|
6
|
+
"name": "src",
|
|
7
|
+
"info": "contains sources",
|
|
8
|
+
"children": [
|
|
9
|
+
{
|
|
10
|
+
"name": "components",
|
|
11
|
+
"info": "reusable components"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "utils",
|
|
15
|
+
"info": "utility functions"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "docs",
|
|
21
|
+
"info": "documentation folder"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
package/tests/config.test.ts
CHANGED
|
@@ -26,6 +26,12 @@ test('normalizeVariable key ordering', () => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
test('saveConfig and loadConfig roundtrip', () => {
|
|
29
|
+
// Save the current config to restore later
|
|
30
|
+
let savedConfig: PtConfig | null = null;
|
|
31
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
32
|
+
savedConfig = loadConfig();
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
// Clean up any existing test files
|
|
30
36
|
if (fs.existsSync(CONFIG_PATH)) {
|
|
31
37
|
fs.unlinkSync(CONFIG_PATH);
|
|
@@ -92,7 +98,651 @@ test('saveConfig and loadConfig roundtrip', () => {
|
|
|
92
98
|
if (fs.existsSync(backupPath)) {
|
|
93
99
|
fs.unlinkSync(backupPath);
|
|
94
100
|
}
|
|
101
|
+
|
|
102
|
+
// Restore the original config if it existed
|
|
103
|
+
if (savedConfig) {
|
|
104
|
+
saveConfig(savedConfig);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (fs.existsSync(testHome)) {
|
|
108
|
+
fs.rmdirSync(testHome);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('normalizeVariable with minimal input', () => {
|
|
113
|
+
const variableInput = {
|
|
114
|
+
name: 'minimalVar'
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const normalized = normalizeVariable(variableInput);
|
|
118
|
+
|
|
119
|
+
// Verify that only name is present
|
|
120
|
+
const keys = Object.keys(normalized);
|
|
121
|
+
assert.deepStrictEqual(keys, ['name']);
|
|
122
|
+
assert.strictEqual(normalized.name, 'minimalVar');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('normalizeVariable with all fields', () => {
|
|
126
|
+
const variableInput = {
|
|
127
|
+
required: false,
|
|
128
|
+
default: 'default-value',
|
|
129
|
+
prompt: 'Custom prompt:',
|
|
130
|
+
name: 'allFields'
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const normalized = normalizeVariable(variableInput);
|
|
134
|
+
|
|
135
|
+
// Verify all fields are present and in correct order
|
|
136
|
+
const keys = Object.keys(normalized);
|
|
137
|
+
assert.deepStrictEqual(keys, ['name', 'prompt', 'default', 'required']);
|
|
138
|
+
assert.strictEqual(normalized.name, 'allFields');
|
|
139
|
+
assert.strictEqual(normalized.prompt, 'Custom prompt:');
|
|
140
|
+
assert.strictEqual(normalized.default, 'default-value');
|
|
141
|
+
assert.strictEqual(normalized.required, false);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('saveConfig creates backup on overwrite', () => {
|
|
145
|
+
// Save the current config to restore later
|
|
146
|
+
let savedConfig: PtConfig | null = null;
|
|
147
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
148
|
+
savedConfig = loadConfig();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Clean up any existing test files
|
|
152
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
153
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
154
|
+
}
|
|
155
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
156
|
+
if (fs.existsSync(backupPath)) {
|
|
157
|
+
fs.unlinkSync(backupPath);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const config1: PtConfig = {
|
|
161
|
+
version: '1.0.0',
|
|
162
|
+
templates: {}
|
|
163
|
+
};
|
|
164
|
+
const config2: PtConfig = {
|
|
165
|
+
version: '2.0.0',
|
|
166
|
+
templates: {}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Save first config
|
|
170
|
+
saveConfig(config1);
|
|
171
|
+
assert.ok(fs.existsSync(CONFIG_PATH), 'Config file should be created');
|
|
172
|
+
|
|
173
|
+
// Save second config (should create backup)
|
|
174
|
+
saveConfig(config2);
|
|
175
|
+
assert.ok(fs.existsSync(backupPath), 'Backup file should exist');
|
|
176
|
+
|
|
177
|
+
// Verify backup contains first config
|
|
178
|
+
const backupContent = fs.readFileSync(backupPath, 'utf-8');
|
|
179
|
+
assert.ok(backupContent.includes("version: 1.0.0") || backupContent.includes("version: '1.0.0'"), 'Backup should contain previous version');
|
|
180
|
+
|
|
181
|
+
// Clean up
|
|
182
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
183
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
184
|
+
}
|
|
185
|
+
if (fs.existsSync(backupPath)) {
|
|
186
|
+
fs.unlinkSync(backupPath);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Restore the original config if it existed
|
|
190
|
+
if (savedConfig) {
|
|
191
|
+
saveConfig(savedConfig);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (fs.existsSync(testHome)) {
|
|
195
|
+
fs.rmdirSync(testHome);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('saveConfig atomic write behavior', () => {
|
|
200
|
+
// Save the current config to restore later
|
|
201
|
+
let savedConfig: PtConfig | null = null;
|
|
202
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
203
|
+
savedConfig = loadConfig();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Clean up any existing test files
|
|
207
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
208
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
209
|
+
}
|
|
210
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
211
|
+
if (fs.existsSync(backupPath)) {
|
|
212
|
+
fs.unlinkSync(backupPath);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const config: PtConfig = {
|
|
216
|
+
version: '1.0.0',
|
|
217
|
+
templates: {}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// Save config - should use atomic write
|
|
221
|
+
saveConfig(config);
|
|
222
|
+
|
|
223
|
+
// Verify config exists
|
|
224
|
+
assert.ok(fs.existsSync(CONFIG_PATH), 'Config file should be created');
|
|
225
|
+
|
|
226
|
+
// Verify no temp file remains
|
|
227
|
+
const tempPath = CONFIG_PATH + '.tmp';
|
|
228
|
+
assert.ok(!fs.existsSync(tempPath), 'Temp file should not remain');
|
|
229
|
+
|
|
230
|
+
// Clean up
|
|
231
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
232
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
233
|
+
}
|
|
234
|
+
if (fs.existsSync(backupPath)) {
|
|
235
|
+
fs.unlinkSync(backupPath);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Restore the original config if it existed
|
|
239
|
+
if (savedConfig) {
|
|
240
|
+
saveConfig(savedConfig);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (fs.existsSync(testHome)) {
|
|
244
|
+
fs.rmdirSync(testHome);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('loadConfig returns default config when file missing', () => {
|
|
249
|
+
// Save the current config to restore later
|
|
250
|
+
let savedConfig: PtConfig | null = null;
|
|
251
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
252
|
+
savedConfig = loadConfig();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Clean up any existing test files
|
|
256
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
257
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
258
|
+
}
|
|
259
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
260
|
+
if (fs.existsSync(backupPath)) {
|
|
261
|
+
fs.unlinkSync(backupPath);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const config = loadConfig();
|
|
265
|
+
|
|
266
|
+
// Verify default config structure
|
|
267
|
+
assert.strictEqual(config.version, '3.0');
|
|
268
|
+
assert.deepStrictEqual(config.templates, {});
|
|
269
|
+
assert.deepStrictEqual(config.default_post_config, []);
|
|
270
|
+
assert.deepStrictEqual(config.variables, []);
|
|
271
|
+
|
|
272
|
+
// Clean up
|
|
273
|
+
if (fs.existsSync(testHome)) {
|
|
274
|
+
fs.rmdirSync(testHome);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Restore the original config if it existed
|
|
278
|
+
if (savedConfig) {
|
|
279
|
+
saveConfig(savedConfig);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test('saveConfig with variables normalizes key order', () => {
|
|
284
|
+
// Save the current config to restore later
|
|
285
|
+
let savedConfig: PtConfig | null = null;
|
|
286
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
287
|
+
savedConfig = loadConfig();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Clean up any existing test files
|
|
291
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
292
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
293
|
+
}
|
|
294
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
295
|
+
if (fs.existsSync(backupPath)) {
|
|
296
|
+
fs.unlinkSync(backupPath);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const config: PtConfig = {
|
|
300
|
+
version: '1.0.0',
|
|
301
|
+
templates: {
|
|
302
|
+
'test-template': {
|
|
303
|
+
description: 'Test',
|
|
304
|
+
folders: [],
|
|
305
|
+
variables: [
|
|
306
|
+
{
|
|
307
|
+
required: true,
|
|
308
|
+
default: 'value1',
|
|
309
|
+
prompt: 'Prompt1:',
|
|
310
|
+
name: 'var1'
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
required: false,
|
|
314
|
+
default: 'value2',
|
|
315
|
+
prompt: 'Prompt2:',
|
|
316
|
+
name: 'var2'
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// Save config
|
|
324
|
+
saveConfig(config);
|
|
325
|
+
|
|
326
|
+
// Load and verify
|
|
327
|
+
const loaded = loadConfig();
|
|
328
|
+
const vars = loaded.templates['test-template'].variables;
|
|
329
|
+
|
|
330
|
+
assert.strictEqual(vars.length, 2, 'Should have 2 variables');
|
|
331
|
+
assert.strictEqual(vars[0].name, 'var1', 'First variable name should be var1');
|
|
332
|
+
assert.strictEqual(vars[1].name, 'var2', 'Second variable name should be var2');
|
|
333
|
+
|
|
334
|
+
// Clean up
|
|
335
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
336
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
337
|
+
}
|
|
338
|
+
if (fs.existsSync(backupPath)) {
|
|
339
|
+
fs.unlinkSync(backupPath);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Restore the original config if it existed
|
|
343
|
+
if (savedConfig) {
|
|
344
|
+
saveConfig(savedConfig);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (fs.existsSync(testHome)) {
|
|
348
|
+
fs.rmdirSync(testHome);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
test('saveConfig with empty config file', () => {
|
|
353
|
+
// Save the current config to restore later
|
|
354
|
+
let savedConfig: PtConfig | null = null;
|
|
355
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
356
|
+
savedConfig = loadConfig();
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Clean up any existing test files
|
|
360
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
361
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
362
|
+
}
|
|
363
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
364
|
+
if (fs.existsSync(backupPath)) {
|
|
365
|
+
fs.unlinkSync(backupPath);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Create empty config file
|
|
369
|
+
fs.writeFileSync(CONFIG_PATH, '');
|
|
370
|
+
|
|
371
|
+
// Try to load - should throw error
|
|
372
|
+
assert.throws(() => {
|
|
373
|
+
loadConfig();
|
|
374
|
+
}, /Config file is empty/, 'Should throw error for empty config file');
|
|
375
|
+
|
|
376
|
+
// Clean up
|
|
377
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
378
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
379
|
+
}
|
|
380
|
+
if (fs.existsSync(backupPath)) {
|
|
381
|
+
fs.unlinkSync(backupPath);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Restore the original config if it existed
|
|
385
|
+
if (savedConfig) {
|
|
386
|
+
saveConfig(savedConfig);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (fs.existsSync(testHome)) {
|
|
390
|
+
fs.rmdirSync(testHome);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
test('normalizeVariable preserves field order', () => {
|
|
395
|
+
const variableInput = {
|
|
396
|
+
required: true,
|
|
397
|
+
default: 'my-default',
|
|
398
|
+
prompt: 'Enter variable:',
|
|
399
|
+
name: 'varName'
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const normalized = normalizeVariable(variableInput);
|
|
403
|
+
|
|
404
|
+
// Verify field order is preserved
|
|
405
|
+
const keys = Object.keys(normalized);
|
|
406
|
+
assert.deepStrictEqual(keys, ['name', 'prompt', 'default', 'required']);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
test('saveConfig handles multiple templates', () => {
|
|
410
|
+
// Save the current config to restore later
|
|
411
|
+
let savedConfig: PtConfig | null = null;
|
|
412
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
413
|
+
savedConfig = loadConfig();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Clean up any existing test files
|
|
417
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
418
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
419
|
+
}
|
|
420
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
421
|
+
if (fs.existsSync(backupPath)) {
|
|
422
|
+
fs.unlinkSync(backupPath);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const config: PtConfig = {
|
|
426
|
+
version: '1.0.0',
|
|
427
|
+
templates: {
|
|
428
|
+
'template1': {
|
|
429
|
+
description: 'Template 1',
|
|
430
|
+
folders: []
|
|
431
|
+
},
|
|
432
|
+
'template2': {
|
|
433
|
+
description: 'Template 2',
|
|
434
|
+
folders: []
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// Save config
|
|
440
|
+
saveConfig(config);
|
|
441
|
+
|
|
442
|
+
// Load and verify
|
|
443
|
+
const loaded = loadConfig();
|
|
444
|
+
assert.strictEqual(Object.keys(loaded.templates).length, 2, 'Should have 2 templates');
|
|
445
|
+
assert.strictEqual(loaded.templates['template1'].description, 'Template 1');
|
|
446
|
+
assert.strictEqual(loaded.templates['template2'].description, 'Template 2');
|
|
447
|
+
|
|
448
|
+
// Clean up
|
|
449
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
450
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
451
|
+
}
|
|
452
|
+
if (fs.existsSync(backupPath)) {
|
|
453
|
+
fs.unlinkSync(backupPath);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Restore the original config if it existed
|
|
457
|
+
if (savedConfig) {
|
|
458
|
+
saveConfig(savedConfig);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (fs.existsSync(testHome)) {
|
|
462
|
+
fs.rmdirSync(testHome);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
test('saveConfig handles templates with variables', () => {
|
|
467
|
+
// Save the current config to restore later
|
|
468
|
+
let savedConfig: PtConfig | null = null;
|
|
469
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
470
|
+
savedConfig = loadConfig();
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Clean up any existing test files
|
|
474
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
475
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
476
|
+
}
|
|
477
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
478
|
+
if (fs.existsSync(backupPath)) {
|
|
479
|
+
fs.unlinkSync(backupPath);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const config: PtConfig = {
|
|
483
|
+
version: '1.0.0',
|
|
484
|
+
templates: {
|
|
485
|
+
'template-with-vars': {
|
|
486
|
+
description: 'Template with variables',
|
|
487
|
+
folders: [],
|
|
488
|
+
variables: [
|
|
489
|
+
{
|
|
490
|
+
required: true,
|
|
491
|
+
default: 'default-value',
|
|
492
|
+
prompt: 'Enter value:',
|
|
493
|
+
name: 'myVar'
|
|
494
|
+
}
|
|
495
|
+
]
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// Save config
|
|
501
|
+
saveConfig(config);
|
|
502
|
+
|
|
503
|
+
// Load and verify
|
|
504
|
+
const loaded = loadConfig();
|
|
505
|
+
const template = loaded.templates['template-with-vars'];
|
|
506
|
+
|
|
507
|
+
assert.ok(template, 'Template should exist');
|
|
508
|
+
assert.strictEqual(template.variables?.length, 1, 'Should have 1 variable');
|
|
509
|
+
assert.strictEqual(template.variables?.[0].name, 'myVar', 'Variable name should be myVar');
|
|
510
|
+
assert.strictEqual(template.variables?.[0].prompt, 'Enter value:', 'Variable prompt should match');
|
|
511
|
+
assert.strictEqual(template.variables?.[0].default, 'default-value', 'Variable default should match');
|
|
512
|
+
assert.strictEqual(template.variables?.[0].required, true, 'Variable should be required');
|
|
513
|
+
|
|
514
|
+
// Clean up
|
|
515
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
516
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
517
|
+
}
|
|
518
|
+
if (fs.existsSync(backupPath)) {
|
|
519
|
+
fs.unlinkSync(backupPath);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Restore the original config if it existed
|
|
523
|
+
if (savedConfig) {
|
|
524
|
+
saveConfig(savedConfig);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (fs.existsSync(testHome)) {
|
|
528
|
+
fs.rmdirSync(testHome);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
test('loadConfig handles migration from v2.0', () => {
|
|
533
|
+
// Save the current config to restore later
|
|
534
|
+
let savedConfig: PtConfig | null = null;
|
|
535
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
536
|
+
savedConfig = loadConfig();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Clean up any existing test files
|
|
540
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
541
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
542
|
+
}
|
|
543
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
544
|
+
if (fs.existsSync(backupPath)) {
|
|
545
|
+
fs.unlinkSync(backupPath);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Create a v2.0 config
|
|
549
|
+
const v2Config = {
|
|
550
|
+
version: '2.0',
|
|
551
|
+
templates: {
|
|
552
|
+
'test-template': {
|
|
553
|
+
name: 'Test Template',
|
|
554
|
+
description: 'Test Description',
|
|
555
|
+
type: 'web',
|
|
556
|
+
folders: []
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(v2Config));
|
|
562
|
+
|
|
563
|
+
// Load config - should migrate to v3.0
|
|
564
|
+
const config = loadConfig();
|
|
565
|
+
|
|
566
|
+
// Verify migration happened
|
|
567
|
+
assert.strictEqual(config.version, '3.0', 'Should be migrated to v3.0');
|
|
568
|
+
assert.strictEqual(config.templates['test-template'].description, 'Test Template', 'Name should be migrated to description');
|
|
569
|
+
assert.ok(!config.templates['test-template'].type, 'Type should be removed');
|
|
570
|
+
|
|
571
|
+
// Clean up
|
|
572
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
573
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
574
|
+
}
|
|
575
|
+
if (fs.existsSync(backupPath)) {
|
|
576
|
+
fs.unlinkSync(backupPath);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// Restore the original config if it existed
|
|
580
|
+
if (savedConfig) {
|
|
581
|
+
saveConfig(savedConfig);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (fs.existsSync(testHome)) {
|
|
585
|
+
fs.rmdirSync(testHome);
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
test('loadConfig handles migration from v2.0 with global_post_config', () => {
|
|
590
|
+
// Save the current config to restore later
|
|
591
|
+
let savedConfig: PtConfig | null = null;
|
|
592
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
593
|
+
savedConfig = loadConfig();
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// Clean up any existing test files
|
|
597
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
598
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
599
|
+
}
|
|
600
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
601
|
+
if (fs.existsSync(backupPath)) {
|
|
602
|
+
fs.unlinkSync(backupPath);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Create a v2.0 config with global_post_config
|
|
606
|
+
const v2Config = {
|
|
607
|
+
version: '2.0',
|
|
608
|
+
templates: {},
|
|
609
|
+
global_post_config: [
|
|
610
|
+
{
|
|
611
|
+
command: 'npm install',
|
|
612
|
+
description: 'Install dependencies'
|
|
613
|
+
}
|
|
614
|
+
]
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(v2Config));
|
|
618
|
+
|
|
619
|
+
// Load config - should migrate to v3.0
|
|
620
|
+
const config = loadConfig();
|
|
621
|
+
|
|
622
|
+
// Verify migration happened
|
|
623
|
+
assert.strictEqual(config.version, '3.0', 'Should be migrated to v3.0');
|
|
624
|
+
assert.deepStrictEqual(config.default_post_config, [
|
|
625
|
+
{
|
|
626
|
+
command: 'npm install',
|
|
627
|
+
description: 'Install dependencies'
|
|
628
|
+
}
|
|
629
|
+
], 'global_post_config should be migrated to default_post_config');
|
|
630
|
+
assert.ok(!config.global_post_config, 'global_post_config should be removed');
|
|
631
|
+
|
|
632
|
+
// Clean up
|
|
633
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
634
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
635
|
+
}
|
|
636
|
+
if (fs.existsSync(backupPath)) {
|
|
637
|
+
fs.unlinkSync(backupPath);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Restore the original config if it existed
|
|
641
|
+
if (savedConfig) {
|
|
642
|
+
saveConfig(savedConfig);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (fs.existsSync(testHome)) {
|
|
646
|
+
fs.rmdirSync(testHome);
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
test('loadConfig handles migration from v2.0 with variables', () => {
|
|
651
|
+
// Save the current config to restore later
|
|
652
|
+
let savedConfig: PtConfig | null = null;
|
|
653
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
654
|
+
savedConfig = loadConfig();
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Clean up any existing test files
|
|
658
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
659
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
660
|
+
}
|
|
661
|
+
const backupPath = CONFIG_PATH + '.bak';
|
|
662
|
+
if (fs.existsSync(backupPath)) {
|
|
663
|
+
fs.unlinkSync(backupPath);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Create a v2.0 config with variables as Record<string, string>
|
|
667
|
+
const v2Config = {
|
|
668
|
+
version: '2.0',
|
|
669
|
+
templates: {},
|
|
670
|
+
variables: {
|
|
671
|
+
'client_name': 'My Client',
|
|
672
|
+
'project_type': 'web'
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(v2Config));
|
|
677
|
+
|
|
678
|
+
// Load config - should migrate to v3.0
|
|
679
|
+
const config = loadConfig();
|
|
680
|
+
|
|
681
|
+
// Verify migration happened
|
|
682
|
+
assert.strictEqual(config.version, '3.0', 'Should be migrated to v3.0');
|
|
683
|
+
assert.strictEqual(config.variables.length, 2, 'Should have 2 variables');
|
|
684
|
+
assert.strictEqual(config.variables[0].name, 'client_name', 'First variable name should be client_name');
|
|
685
|
+
assert.strictEqual(config.variables[0].default, 'My Client', 'First variable default should be My Client');
|
|
686
|
+
assert.strictEqual(config.variables[1].name, 'project_type', 'Second variable name should be project_type');
|
|
687
|
+
assert.strictEqual(config.variables[1].default, 'web', 'Second variable default should be web');
|
|
688
|
+
|
|
689
|
+
// Clean up
|
|
690
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
691
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
692
|
+
}
|
|
693
|
+
if (fs.existsSync(backupPath)) {
|
|
694
|
+
fs.unlinkSync(backupPath);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// Restore the original config if it existed
|
|
698
|
+
if (savedConfig) {
|
|
699
|
+
saveConfig(savedConfig);
|
|
700
|
+
}
|
|
701
|
+
|
|
95
702
|
if (fs.existsSync(testHome)) {
|
|
96
703
|
fs.rmdirSync(testHome);
|
|
97
704
|
}
|
|
98
705
|
});
|
|
706
|
+
|
|
707
|
+
test('loadConfig handles existing config file', () => {
|
|
708
|
+
// Don't delete the existing config file - let it be restored by the user
|
|
709
|
+
// This test verifies that loadConfig works with an existing config
|
|
710
|
+
const config = loadConfig();
|
|
711
|
+
|
|
712
|
+
// Verify config is loaded correctly
|
|
713
|
+
assert.ok(config, 'Config should be loaded');
|
|
714
|
+
assert.ok(config.templates, 'Templates should exist');
|
|
715
|
+
assert.ok(config.version, 'Version should exist');
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
test('saveConfig preserves existing config when not deleting', () => {
|
|
719
|
+
// Save the current config to restore later
|
|
720
|
+
let savedConfig: PtConfig | null = null;
|
|
721
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
722
|
+
savedConfig = loadConfig();
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Don't delete the config file - test saving without deletion
|
|
726
|
+
const config: PtConfig = {
|
|
727
|
+
version: '1.0.0',
|
|
728
|
+
templates: {
|
|
729
|
+
'test-template': {
|
|
730
|
+
description: 'Test',
|
|
731
|
+
folders: []
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
// Save config
|
|
737
|
+
saveConfig(config);
|
|
738
|
+
|
|
739
|
+
// Load and verify
|
|
740
|
+
const loaded = loadConfig();
|
|
741
|
+
assert.strictEqual(loaded.version, '1.0.0');
|
|
742
|
+
assert.ok(loaded.templates['test-template']);
|
|
743
|
+
|
|
744
|
+
// Restore the original config if it existed
|
|
745
|
+
if (savedConfig) {
|
|
746
|
+
saveConfig(savedConfig);
|
|
747
|
+
}
|
|
748
|
+
});
|