@positronic/cli 0.0.3 → 0.0.4

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 (81) hide show
  1. package/dist/src/commands/helpers.js +11 -25
  2. package/dist/types/commands/helpers.d.ts.map +1 -1
  3. package/package.json +5 -1
  4. package/dist/src/commands/brain.test.js +0 -2936
  5. package/dist/src/commands/helpers.test.js +0 -832
  6. package/dist/src/commands/project.test.js +0 -1201
  7. package/dist/src/commands/resources.test.js +0 -2511
  8. package/dist/src/commands/schedule.test.js +0 -1235
  9. package/dist/src/commands/secret.test.d.js +0 -1
  10. package/dist/src/commands/secret.test.js +0 -761
  11. package/dist/src/commands/server.test.js +0 -1237
  12. package/dist/src/commands/test-utils.js +0 -737
  13. package/dist/src/components/secret-sync.js +0 -303
  14. package/dist/src/test/mock-api-client.js +0 -371
  15. package/dist/src/test/test-dev-server.js +0 -1376
  16. package/dist/types/commands/test-utils.d.ts +0 -45
  17. package/dist/types/commands/test-utils.d.ts.map +0 -1
  18. package/dist/types/components/secret-sync.d.ts +0 -9
  19. package/dist/types/components/secret-sync.d.ts.map +0 -1
  20. package/dist/types/test/mock-api-client.d.ts +0 -25
  21. package/dist/types/test/mock-api-client.d.ts.map +0 -1
  22. package/dist/types/test/test-dev-server.d.ts +0 -129
  23. package/dist/types/test/test-dev-server.d.ts.map +0 -1
  24. package/src/cli.ts +0 -997
  25. package/src/commands/backend.ts +0 -63
  26. package/src/commands/brain.test.ts +0 -1004
  27. package/src/commands/brain.ts +0 -215
  28. package/src/commands/helpers.test.ts +0 -487
  29. package/src/commands/helpers.ts +0 -870
  30. package/src/commands/project-config-manager.ts +0 -152
  31. package/src/commands/project.test.ts +0 -502
  32. package/src/commands/project.ts +0 -109
  33. package/src/commands/resources.test.ts +0 -1052
  34. package/src/commands/resources.ts +0 -97
  35. package/src/commands/schedule.test.ts +0 -481
  36. package/src/commands/schedule.ts +0 -65
  37. package/src/commands/secret.test.ts +0 -210
  38. package/src/commands/secret.ts +0 -50
  39. package/src/commands/server.test.ts +0 -493
  40. package/src/commands/server.ts +0 -353
  41. package/src/commands/test-utils.ts +0 -324
  42. package/src/components/brain-history.tsx +0 -198
  43. package/src/components/brain-list.tsx +0 -105
  44. package/src/components/brain-rerun.tsx +0 -111
  45. package/src/components/brain-show.tsx +0 -92
  46. package/src/components/error.tsx +0 -24
  47. package/src/components/project-add.tsx +0 -59
  48. package/src/components/project-create.tsx +0 -83
  49. package/src/components/project-list.tsx +0 -83
  50. package/src/components/project-remove.tsx +0 -55
  51. package/src/components/project-select.tsx +0 -200
  52. package/src/components/project-show.tsx +0 -58
  53. package/src/components/resource-clear.tsx +0 -127
  54. package/src/components/resource-delete.tsx +0 -160
  55. package/src/components/resource-list.tsx +0 -177
  56. package/src/components/resource-sync.tsx +0 -170
  57. package/src/components/resource-types.tsx +0 -55
  58. package/src/components/resource-upload.tsx +0 -182
  59. package/src/components/schedule-create.tsx +0 -90
  60. package/src/components/schedule-delete.tsx +0 -116
  61. package/src/components/schedule-list.tsx +0 -186
  62. package/src/components/schedule-runs.tsx +0 -151
  63. package/src/components/secret-bulk.tsx +0 -79
  64. package/src/components/secret-create.tsx +0 -49
  65. package/src/components/secret-delete.tsx +0 -41
  66. package/src/components/secret-list.tsx +0 -41
  67. package/src/components/watch.tsx +0 -155
  68. package/src/hooks/useApi.ts +0 -183
  69. package/src/positronic.ts +0 -40
  70. package/src/test/data/resources/config.json +0 -1
  71. package/src/test/data/resources/data/config.json +0 -1
  72. package/src/test/data/resources/data/logo.png +0 -2
  73. package/src/test/data/resources/docs/api.md +0 -3
  74. package/src/test/data/resources/docs/readme.md +0 -3
  75. package/src/test/data/resources/example.md +0 -3
  76. package/src/test/data/resources/file with spaces.txt +0 -1
  77. package/src/test/data/resources/readme.md +0 -3
  78. package/src/test/data/resources/test.txt +0 -1
  79. package/src/test/mock-api-client.ts +0 -145
  80. package/src/test/test-dev-server.ts +0 -1003
  81. package/tsconfig.json +0 -11
@@ -1,2511 +0,0 @@
1
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
- try {
3
- var info = gen[key](arg);
4
- var value = info.value;
5
- } catch (error) {
6
- reject(error);
7
- return;
8
- }
9
- if (info.done) {
10
- resolve(value);
11
- } else {
12
- Promise.resolve(value).then(_next, _throw);
13
- }
14
- }
15
- function _async_to_generator(fn) {
16
- return function() {
17
- var self = this, args = arguments;
18
- return new Promise(function(resolve, reject) {
19
- var gen = fn.apply(self, args);
20
- function _next(value) {
21
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
- }
23
- function _throw(err) {
24
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
- }
26
- _next(undefined);
27
- });
28
- };
29
- }
30
- function _ts_generator(thisArg, body) {
31
- var f, y, t, _ = {
32
- label: 0,
33
- sent: function() {
34
- if (t[0] & 1) throw t[1];
35
- return t[1];
36
- },
37
- trys: [],
38
- ops: []
39
- }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
40
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
41
- return this;
42
- }), g;
43
- function verb(n) {
44
- return function(v) {
45
- return step([
46
- n,
47
- v
48
- ]);
49
- };
50
- }
51
- function step(op) {
52
- if (f) throw new TypeError("Generator is already executing.");
53
- while(g && (g = 0, op[0] && (_ = 0)), _)try {
54
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
55
- if (y = 0, t) op = [
56
- op[0] & 2,
57
- t.value
58
- ];
59
- switch(op[0]){
60
- case 0:
61
- case 1:
62
- t = op;
63
- break;
64
- case 4:
65
- _.label++;
66
- return {
67
- value: op[1],
68
- done: false
69
- };
70
- case 5:
71
- _.label++;
72
- y = op[1];
73
- op = [
74
- 0
75
- ];
76
- continue;
77
- case 7:
78
- op = _.ops.pop();
79
- _.trys.pop();
80
- continue;
81
- default:
82
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
83
- _ = 0;
84
- continue;
85
- }
86
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
87
- _.label = op[1];
88
- break;
89
- }
90
- if (op[0] === 6 && _.label < t[1]) {
91
- _.label = t[1];
92
- t = op;
93
- break;
94
- }
95
- if (t && _.label < t[2]) {
96
- _.label = t[2];
97
- _.ops.push(op);
98
- break;
99
- }
100
- if (t[2]) _.ops.pop();
101
- _.trys.pop();
102
- continue;
103
- }
104
- op = body.call(thisArg, _);
105
- } catch (e) {
106
- op = [
107
- 6,
108
- e
109
- ];
110
- y = 0;
111
- } finally{
112
- f = t = 0;
113
- }
114
- if (op[0] & 5) throw op[1];
115
- return {
116
- value: op[0] ? op[1] : void 0,
117
- done: true
118
- };
119
- }
120
- }
121
- import { describe, it, expect } from '@jest/globals';
122
- import { createTestEnv, px } from './test-utils.js';
123
- import path from 'path';
124
- import fs from 'fs';
125
- describe('CLI Integration: positronic resources types', function() {
126
- it('should generate type definitions for resources', function() {
127
- return _async_to_generator(function() {
128
- var env, px, _ref, waitForOutput, waitForTypesFile, isOutputRendered, typesContent, normalizeWhitespace, expectedContent;
129
- return _ts_generator(this, function(_state) {
130
- switch(_state.label){
131
- case 0:
132
- return [
133
- 4,
134
- createTestEnv()
135
- ];
136
- case 1:
137
- env = _state.sent();
138
- return [
139
- 4,
140
- env.start()
141
- ];
142
- case 2:
143
- px = _state.sent();
144
- _state.label = 3;
145
- case 3:
146
- _state.trys.push([
147
- 3,
148
- ,
149
- 7,
150
- 9
151
- ]);
152
- return [
153
- 4,
154
- px([
155
- 'resources',
156
- 'sync'
157
- ])
158
- ];
159
- case 4:
160
- _ref = _state.sent(), waitForOutput = _ref.waitForOutput, waitForTypesFile = _ref.waitForTypesFile;
161
- return [
162
- 4,
163
- waitForOutput(/sync summary/i, 50)
164
- ];
165
- case 5:
166
- isOutputRendered = _state.sent();
167
- return [
168
- 4,
169
- waitForTypesFile('config: TextResource;')
170
- ];
171
- case 6:
172
- typesContent = _state.sent();
173
- expect(isOutputRendered).toBe(true);
174
- normalizeWhitespace = function(str) {
175
- return str.replace(/\s+/g, ' ').trim();
176
- };
177
- expectedContent = "declare module '@positronic/core' {\n interface TextResource {\n load(): Promise<string>;\n }\n interface BinaryResource {\n load(): Promise<Buffer>;\n }\n interface Resources {\n // Method signatures for loading resources by path\n loadText(path: string): Promise<string>;\n loadBinary(path: string): Promise<Buffer>;\n // Resource properties accessible via dot notation\n config: TextResource;\n data: {\n config: TextResource;\n logo: BinaryResource;\n };\n docs: {\n api: TextResource;\n readme: TextResource;\n };\n example: TextResource;\n readme: TextResource;\n test: TextResource;\n }\n }";
178
- expect(normalizeWhitespace(typesContent)).toContain(normalizeWhitespace(expectedContent));
179
- return [
180
- 3,
181
- 9
182
- ];
183
- case 7:
184
- return [
185
- 4,
186
- env.stopAndCleanup()
187
- ];
188
- case 8:
189
- _state.sent();
190
- return [
191
- 7
192
- ];
193
- case 9:
194
- return [
195
- 2
196
- ];
197
- }
198
- });
199
- })();
200
- });
201
- it('should handle empty resources directory', function() {
202
- return _async_to_generator(function() {
203
- var env, px, resourcesDir, syncElement, isOutputRendered, typesContent, listElement, resourceListOutput;
204
- return _ts_generator(this, function(_state) {
205
- switch(_state.label){
206
- case 0:
207
- return [
208
- 4,
209
- createTestEnv()
210
- ];
211
- case 1:
212
- env = _state.sent();
213
- return [
214
- 4,
215
- env.start()
216
- ];
217
- case 2:
218
- px = _state.sent();
219
- _state.label = 3;
220
- case 3:
221
- _state.trys.push([
222
- 3,
223
- ,
224
- 9,
225
- 11
226
- ]);
227
- // Remove the default resources created by createMinimalProject
228
- resourcesDir = path.join(env.projectRootDir, 'resources');
229
- // Remove all contents recursively and recreate empty directory
230
- fs.rmSync(resourcesDir, {
231
- recursive: true,
232
- force: true
233
- });
234
- fs.mkdirSync(resourcesDir);
235
- // Verify directory is empty
236
- expect(fs.readdirSync(resourcesDir).length).toBe(0);
237
- return [
238
- 4,
239
- px([
240
- 'resources',
241
- 'sync'
242
- ])
243
- ];
244
- case 4:
245
- syncElement = _state.sent();
246
- return [
247
- 4,
248
- syncElement.waitForOutput(/no files found in the resources directory/i)
249
- ];
250
- case 5:
251
- isOutputRendered = _state.sent();
252
- expect(isOutputRendered).toBe(true);
253
- return [
254
- 4,
255
- syncElement.waitForTypesFile('loadText(path: string): Promise<string>;')
256
- ];
257
- case 6:
258
- typesContent = _state.sent();
259
- // Check if the types file was generated
260
- expect(typesContent).toBeDefined();
261
- // Should still have the basic structure
262
- expect(typesContent).toContain("declare module '@positronic/core'");
263
- expect(typesContent).toContain('interface Resources');
264
- expect(typesContent).toContain('loadText(path: string): Promise<string>');
265
- expect(typesContent).toContain('loadBinary(path: string): Promise<Buffer>');
266
- return [
267
- 4,
268
- px([
269
- 'resources',
270
- 'list'
271
- ])
272
- ];
273
- case 7:
274
- listElement = _state.sent();
275
- return [
276
- 4,
277
- listElement.waitForOutput(/no resources found in the project/i)
278
- ];
279
- case 8:
280
- resourceListOutput = _state.sent();
281
- expect(resourceListOutput).toBe(true);
282
- return [
283
- 3,
284
- 11
285
- ];
286
- case 9:
287
- return [
288
- 4,
289
- env.stopAndCleanup()
290
- ];
291
- case 10:
292
- _state.sent();
293
- return [
294
- 7
295
- ];
296
- case 11:
297
- return [
298
- 2
299
- ];
300
- }
301
- });
302
- })();
303
- });
304
- it('should handle resources with special characters', function() {
305
- return _async_to_generator(function() {
306
- var env, px, _ref, waitForOutput, waitForTypesFile, isOutputRendered, typesContent;
307
- return _ts_generator(this, function(_state) {
308
- switch(_state.label){
309
- case 0:
310
- return [
311
- 4,
312
- createTestEnv()
313
- ];
314
- case 1:
315
- env = _state.sent();
316
- // Setup files with special characters
317
- env.setup(function(dir) {
318
- // Create resources directory
319
- var resourcesDir = path.join(dir, 'resources');
320
- // Remove existing resources directory if it exists
321
- if (fs.existsSync(resourcesDir)) {
322
- fs.rmSync(resourcesDir, {
323
- recursive: true,
324
- force: true
325
- });
326
- }
327
- // Create fresh resources directory
328
- fs.mkdirSync(resourcesDir, {
329
- recursive: true
330
- });
331
- // Create files with special characters
332
- fs.writeFileSync(path.join(resourcesDir, 'valid_file.txt'), 'content');
333
- fs.writeFileSync(path.join(resourcesDir, '$special.txt'), 'content'); // Valid JS identifier
334
- fs.writeFileSync(path.join(resourcesDir, '_underscore.txt'), 'content'); // Valid JS identifier
335
- fs.writeFileSync(path.join(resourcesDir, '123invalid.txt'), 'content'); // Invalid - starts with number
336
- fs.writeFileSync(path.join(resourcesDir, 'special-chars!@#.txt'), 'content'); // Invalid
337
- });
338
- return [
339
- 4,
340
- env.start()
341
- ];
342
- case 2:
343
- px = _state.sent();
344
- _state.label = 3;
345
- case 3:
346
- _state.trys.push([
347
- 3,
348
- ,
349
- 7,
350
- 9
351
- ]);
352
- return [
353
- 4,
354
- px([
355
- 'resources',
356
- 'sync'
357
- ])
358
- ];
359
- case 4:
360
- _ref = _state.sent(), waitForOutput = _ref.waitForOutput, waitForTypesFile = _ref.waitForTypesFile;
361
- return [
362
- 4,
363
- waitForOutput(/sync summary/i)
364
- ];
365
- case 5:
366
- isOutputRendered = _state.sent();
367
- expect(isOutputRendered).toBe(true);
368
- return [
369
- 4,
370
- waitForTypesFile([
371
- 'valid_file: TextResource;',
372
- '$special: TextResource;',
373
- '_underscore: TextResource;'
374
- ])
375
- ];
376
- case 6:
377
- typesContent = _state.sent();
378
- // Verify the generated content
379
- expect(typesContent).toBeDefined();
380
- // Check valid identifiers are included
381
- expect(typesContent).toContain('valid_file: TextResource;');
382
- expect(typesContent).toContain('$special: TextResource;');
383
- expect(typesContent).toContain('_underscore: TextResource;');
384
- // Check invalid identifiers are excluded
385
- expect(typesContent).not.toContain('123invalid');
386
- expect(typesContent).not.toContain('special-chars');
387
- return [
388
- 3,
389
- 9
390
- ];
391
- case 7:
392
- return [
393
- 4,
394
- env.stopAndCleanup()
395
- ];
396
- case 8:
397
- _state.sent();
398
- return [
399
- 7
400
- ];
401
- case 9:
402
- return [
403
- 2
404
- ];
405
- }
406
- });
407
- })();
408
- });
409
- it('should correctly identify text vs binary files', function() {
410
- return _async_to_generator(function() {
411
- var env, px, _ref, waitForOutput, waitForTypesFile, isOutputRendered, typesContent;
412
- return _ts_generator(this, function(_state) {
413
- switch(_state.label){
414
- case 0:
415
- return [
416
- 4,
417
- createTestEnv()
418
- ];
419
- case 1:
420
- env = _state.sent();
421
- // Setup files with various types
422
- env.setup(function(dir) {
423
- // Create resources directory
424
- var resourcesDir = path.join(dir, 'resources');
425
- // Remove existing resources directory if it exists
426
- if (fs.existsSync(resourcesDir)) {
427
- fs.rmSync(resourcesDir, {
428
- recursive: true,
429
- force: true
430
- });
431
- }
432
- // Create fresh resources directory
433
- fs.mkdirSync(resourcesDir, {
434
- recursive: true
435
- });
436
- // Create various file types
437
- fs.writeFileSync(path.join(resourcesDir, 'text.txt'), 'text');
438
- fs.writeFileSync(path.join(resourcesDir, 'script.js'), 'code');
439
- fs.writeFileSync(path.join(resourcesDir, 'config.json'), '{}');
440
- fs.writeFileSync(path.join(resourcesDir, 'styles.css'), 'css');
441
- // Create actual binary content for binary files
442
- // JPEG magic bytes
443
- var jpegHeader = Buffer.from([
444
- 0xff,
445
- 0xd8,
446
- 0xff,
447
- 0xe0,
448
- 0x00,
449
- 0x10,
450
- 0x4a,
451
- 0x46,
452
- 0x49,
453
- 0x46
454
- ]);
455
- fs.writeFileSync(path.join(resourcesDir, 'image.jpg'), jpegHeader);
456
- // Random binary data
457
- var binaryData = Buffer.from([
458
- 0x00,
459
- 0x01,
460
- 0x02,
461
- 0x03,
462
- 0x04,
463
- 0x05,
464
- 0x06,
465
- 0x07,
466
- 0x08,
467
- 0x09
468
- ]);
469
- fs.writeFileSync(path.join(resourcesDir, 'binary.bin'), binaryData);
470
- // PDF magic bytes
471
- var pdfHeader = Buffer.from('%PDF-1.4\n%âÌÊÓ\n');
472
- fs.writeFileSync(path.join(resourcesDir, 'document.pdf'), pdfHeader);
473
- });
474
- return [
475
- 4,
476
- env.start()
477
- ];
478
- case 2:
479
- px = _state.sent();
480
- _state.label = 3;
481
- case 3:
482
- _state.trys.push([
483
- 3,
484
- ,
485
- 7,
486
- 9
487
- ]);
488
- return [
489
- 4,
490
- px([
491
- 'resources',
492
- 'sync'
493
- ])
494
- ];
495
- case 4:
496
- _ref = _state.sent(), waitForOutput = _ref.waitForOutput, waitForTypesFile = _ref.waitForTypesFile;
497
- return [
498
- 4,
499
- waitForOutput(/sync summary/i)
500
- ];
501
- case 5:
502
- isOutputRendered = _state.sent();
503
- expect(isOutputRendered).toBe(true);
504
- return [
505
- 4,
506
- waitForTypesFile([
507
- 'text: TextResource;',
508
- 'script: TextResource;',
509
- 'config: TextResource;',
510
- 'styles: TextResource;',
511
- 'image: BinaryResource;',
512
- 'binary: BinaryResource;',
513
- 'document: BinaryResource;'
514
- ])
515
- ];
516
- case 6:
517
- typesContent = _state.sent();
518
- // Verify the generated content
519
- expect(typesContent).toBeDefined();
520
- // Check text resources
521
- expect(typesContent).toContain('text: TextResource;');
522
- expect(typesContent).toContain('script: TextResource;');
523
- expect(typesContent).toContain('config: TextResource;');
524
- expect(typesContent).toContain('styles: TextResource;');
525
- // Check binary resources
526
- expect(typesContent).toContain('image: BinaryResource;');
527
- expect(typesContent).toContain('binary: BinaryResource;');
528
- expect(typesContent).toContain('document: BinaryResource;');
529
- return [
530
- 3,
531
- 9
532
- ];
533
- case 7:
534
- return [
535
- 4,
536
- env.stopAndCleanup()
537
- ];
538
- case 8:
539
- _state.sent();
540
- return [
541
- 7
542
- ];
543
- case 9:
544
- return [
545
- 2
546
- ];
547
- }
548
- });
549
- })();
550
- });
551
- describe('resources list command', function() {
552
- it('should handle empty resources', function() {
553
- return _async_to_generator(function() {
554
- var env, px, waitForOutput, found;
555
- return _ts_generator(this, function(_state) {
556
- switch(_state.label){
557
- case 0:
558
- return [
559
- 4,
560
- createTestEnv()
561
- ];
562
- case 1:
563
- env = _state.sent();
564
- return [
565
- 4,
566
- env.start()
567
- ];
568
- case 2:
569
- px = _state.sent();
570
- _state.label = 3;
571
- case 3:
572
- _state.trys.push([
573
- 3,
574
- ,
575
- 6,
576
- 8
577
- ]);
578
- return [
579
- 4,
580
- px([
581
- 'resources',
582
- 'list'
583
- ])
584
- ];
585
- case 4:
586
- waitForOutput = _state.sent().waitForOutput;
587
- return [
588
- 4,
589
- waitForOutput(/No resources found in the project/)
590
- ];
591
- case 5:
592
- found = _state.sent();
593
- expect(found).toBe(true);
594
- return [
595
- 3,
596
- 8
597
- ];
598
- case 6:
599
- return [
600
- 4,
601
- env.stopAndCleanup()
602
- ];
603
- case 7:
604
- _state.sent();
605
- return [
606
- 7
607
- ];
608
- case 8:
609
- return [
610
- 2
611
- ];
612
- }
613
- });
614
- })();
615
- });
616
- it('should display resources with tree structure', function() {
617
- return _async_to_generator(function() {
618
- var env, px, waitForOutput, foundTree, foundReadme, foundData, foundConfig, foundUsers, foundAdmin, foundImages, foundLogo;
619
- return _ts_generator(this, function(_state) {
620
- switch(_state.label){
621
- case 0:
622
- return [
623
- 4,
624
- createTestEnv()
625
- ];
626
- case 1:
627
- env = _state.sent();
628
- // Add resources with nested structure
629
- env.server.addResource({
630
- key: 'readme.txt',
631
- type: 'text',
632
- size: 1024,
633
- lastModified: new Date().toISOString(),
634
- local: true
635
- });
636
- env.server.addResource({
637
- key: 'data/config.json',
638
- type: 'text',
639
- size: 2048,
640
- lastModified: new Date().toISOString(),
641
- local: true
642
- });
643
- env.server.addResource({
644
- key: 'data/users/admin.json',
645
- type: 'text',
646
- size: 512,
647
- lastModified: new Date().toISOString(),
648
- local: true
649
- });
650
- env.server.addResource({
651
- key: 'images/logo.png',
652
- type: 'binary',
653
- size: 10240,
654
- lastModified: new Date().toISOString(),
655
- local: false
656
- });
657
- return [
658
- 4,
659
- env.start()
660
- ];
661
- case 2:
662
- px = _state.sent();
663
- _state.label = 3;
664
- case 3:
665
- _state.trys.push([
666
- 3,
667
- ,
668
- 13,
669
- 15
670
- ]);
671
- return [
672
- 4,
673
- px([
674
- 'resources',
675
- 'list'
676
- ])
677
- ];
678
- case 4:
679
- waitForOutput = _state.sent().waitForOutput;
680
- return [
681
- 4,
682
- waitForOutput(/resources/)
683
- ];
684
- case 5:
685
- foundTree = _state.sent();
686
- expect(foundTree).toBe(true);
687
- return [
688
- 4,
689
- waitForOutput(/readme\.txt/)
690
- ];
691
- case 6:
692
- foundReadme = _state.sent();
693
- expect(foundReadme).toBe(true);
694
- return [
695
- 4,
696
- waitForOutput(/data/)
697
- ];
698
- case 7:
699
- foundData = _state.sent();
700
- expect(foundData).toBe(true);
701
- return [
702
- 4,
703
- waitForOutput(/config\.json/)
704
- ];
705
- case 8:
706
- foundConfig = _state.sent();
707
- expect(foundConfig).toBe(true);
708
- return [
709
- 4,
710
- waitForOutput(/users/)
711
- ];
712
- case 9:
713
- foundUsers = _state.sent();
714
- expect(foundUsers).toBe(true);
715
- return [
716
- 4,
717
- waitForOutput(/admin\.json/)
718
- ];
719
- case 10:
720
- foundAdmin = _state.sent();
721
- expect(foundAdmin).toBe(true);
722
- return [
723
- 4,
724
- waitForOutput(/images/)
725
- ];
726
- case 11:
727
- foundImages = _state.sent();
728
- expect(foundImages).toBe(true);
729
- return [
730
- 4,
731
- waitForOutput(/logo\.png/)
732
- ];
733
- case 12:
734
- foundLogo = _state.sent();
735
- expect(foundLogo).toBe(true);
736
- return [
737
- 3,
738
- 15
739
- ];
740
- case 13:
741
- return [
742
- 4,
743
- env.stopAndCleanup()
744
- ];
745
- case 14:
746
- _state.sent();
747
- return [
748
- 7
749
- ];
750
- case 15:
751
- return [
752
- 2
753
- ];
754
- }
755
- });
756
- })();
757
- });
758
- it('should display file sizes with correct formatting', function() {
759
- return _async_to_generator(function() {
760
- var env, px, waitForOutput, foundSmall, foundMedium, foundLarge, foundHuge;
761
- return _ts_generator(this, function(_state) {
762
- switch(_state.label){
763
- case 0:
764
- return [
765
- 4,
766
- createTestEnv()
767
- ];
768
- case 1:
769
- env = _state.sent();
770
- // Add resources with various sizes
771
- env.server.addResource({
772
- key: 'small.txt',
773
- type: 'text',
774
- size: 500,
775
- lastModified: new Date().toISOString(),
776
- local: true
777
- });
778
- env.server.addResource({
779
- key: 'medium.txt',
780
- type: 'text',
781
- size: 1536,
782
- lastModified: new Date().toISOString(),
783
- local: true
784
- });
785
- env.server.addResource({
786
- key: 'large.bin',
787
- type: 'binary',
788
- size: 1048576,
789
- lastModified: new Date().toISOString(),
790
- local: true
791
- });
792
- env.server.addResource({
793
- key: 'huge.bin',
794
- type: 'binary',
795
- size: 10485760,
796
- lastModified: new Date().toISOString(),
797
- local: true
798
- });
799
- return [
800
- 4,
801
- env.start()
802
- ];
803
- case 2:
804
- px = _state.sent();
805
- _state.label = 3;
806
- case 3:
807
- _state.trys.push([
808
- 3,
809
- ,
810
- 9,
811
- 11
812
- ]);
813
- return [
814
- 4,
815
- px([
816
- 'resources',
817
- 'list'
818
- ])
819
- ];
820
- case 4:
821
- waitForOutput = _state.sent().waitForOutput;
822
- return [
823
- 4,
824
- waitForOutput(/small\.txt.*500 B/)
825
- ];
826
- case 5:
827
- foundSmall = _state.sent();
828
- expect(foundSmall).toBe(true);
829
- return [
830
- 4,
831
- waitForOutput(/medium\.txt.*1\.5 KB/)
832
- ];
833
- case 6:
834
- foundMedium = _state.sent();
835
- expect(foundMedium).toBe(true);
836
- return [
837
- 4,
838
- waitForOutput(/large\.bin.*1\.0 MB/)
839
- ];
840
- case 7:
841
- foundLarge = _state.sent();
842
- expect(foundLarge).toBe(true);
843
- return [
844
- 4,
845
- waitForOutput(/huge\.bin.*10\.0 MB/)
846
- ];
847
- case 8:
848
- foundHuge = _state.sent();
849
- expect(foundHuge).toBe(true);
850
- return [
851
- 3,
852
- 11
853
- ];
854
- case 9:
855
- return [
856
- 4,
857
- env.stopAndCleanup()
858
- ];
859
- case 10:
860
- _state.sent();
861
- return [
862
- 7
863
- ];
864
- case 11:
865
- return [
866
- 2
867
- ];
868
- }
869
- });
870
- })();
871
- });
872
- it('should indicate local vs remote resources', function() {
873
- return _async_to_generator(function() {
874
- var env, px, waitForOutput, foundLocal, foundRemote, foundArrow, foundLegend;
875
- return _ts_generator(this, function(_state) {
876
- switch(_state.label){
877
- case 0:
878
- return [
879
- 4,
880
- createTestEnv()
881
- ];
882
- case 1:
883
- env = _state.sent();
884
- // Add mix of local and remote resources
885
- env.server.addResource({
886
- key: 'local-file.txt',
887
- type: 'text',
888
- size: 100,
889
- lastModified: new Date().toISOString(),
890
- local: true
891
- });
892
- env.server.addResource({
893
- key: 'remote-file.txt',
894
- type: 'text',
895
- size: 200,
896
- lastModified: new Date().toISOString(),
897
- local: false
898
- });
899
- return [
900
- 4,
901
- env.start()
902
- ];
903
- case 2:
904
- px = _state.sent();
905
- _state.label = 3;
906
- case 3:
907
- _state.trys.push([
908
- 3,
909
- ,
910
- 9,
911
- 11
912
- ]);
913
- return [
914
- 4,
915
- px([
916
- 'resources',
917
- 'list'
918
- ])
919
- ];
920
- case 4:
921
- waitForOutput = _state.sent().waitForOutput;
922
- return [
923
- 4,
924
- waitForOutput(/local-file\.txt/)
925
- ];
926
- case 5:
927
- foundLocal = _state.sent();
928
- expect(foundLocal).toBe(true);
929
- return [
930
- 4,
931
- waitForOutput(/remote-file\.txt/)
932
- ];
933
- case 6:
934
- foundRemote = _state.sent();
935
- expect(foundRemote).toBe(true);
936
- return [
937
- 4,
938
- waitForOutput(/↗/)
939
- ];
940
- case 7:
941
- foundArrow = _state.sent();
942
- expect(foundArrow).toBe(true);
943
- return [
944
- 4,
945
- waitForOutput(/uploaded resource \(not in local filesystem\)/)
946
- ];
947
- case 8:
948
- foundLegend = _state.sent();
949
- expect(foundLegend).toBe(true);
950
- return [
951
- 3,
952
- 11
953
- ];
954
- case 9:
955
- return [
956
- 4,
957
- env.stopAndCleanup()
958
- ];
959
- case 10:
960
- _state.sent();
961
- return [
962
- 7
963
- ];
964
- case 11:
965
- return [
966
- 2
967
- ];
968
- }
969
- });
970
- })();
971
- });
972
- it('should show loading state', function() {
973
- return _async_to_generator(function() {
974
- var env, px, _ref, waitForOutput, instance, foundLoading, foundError;
975
- return _ts_generator(this, function(_state) {
976
- switch(_state.label){
977
- case 0:
978
- return [
979
- 4,
980
- createTestEnv()
981
- ];
982
- case 1:
983
- env = _state.sent();
984
- return [
985
- 4,
986
- env.start()
987
- ];
988
- case 2:
989
- px = _state.sent();
990
- _state.label = 3;
991
- case 3:
992
- _state.trys.push([
993
- 3,
994
- ,
995
- 7,
996
- 8
997
- ]);
998
- // Stop server to simulate slow loading
999
- env.server.stop();
1000
- return [
1001
- 4,
1002
- px([
1003
- 'resources',
1004
- 'list'
1005
- ])
1006
- ];
1007
- case 4:
1008
- _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
1009
- return [
1010
- 4,
1011
- waitForOutput(/Loading resources\.\.\./)
1012
- ];
1013
- case 5:
1014
- foundLoading = _state.sent();
1015
- expect(foundLoading).toBe(true);
1016
- return [
1017
- 4,
1018
- waitForOutput(/Error connecting/)
1019
- ];
1020
- case 6:
1021
- foundError = _state.sent();
1022
- expect(foundError).toBe(true);
1023
- return [
1024
- 3,
1025
- 8
1026
- ];
1027
- case 7:
1028
- // Cleanup without stopping server (already stopped)
1029
- env.cleanup();
1030
- return [
1031
- 7
1032
- ];
1033
- case 8:
1034
- return [
1035
- 2
1036
- ];
1037
- }
1038
- });
1039
- })();
1040
- });
1041
- it('should display resource count summary', function() {
1042
- return _async_to_generator(function() {
1043
- var env, i, px, waitForOutput, foundCount;
1044
- return _ts_generator(this, function(_state) {
1045
- switch(_state.label){
1046
- case 0:
1047
- return [
1048
- 4,
1049
- createTestEnv()
1050
- ];
1051
- case 1:
1052
- env = _state.sent();
1053
- // Add multiple resources
1054
- for(i = 1; i <= 5; i++){
1055
- env.server.addResource({
1056
- key: "file".concat(i, ".txt"),
1057
- type: 'text',
1058
- size: 100 * i,
1059
- lastModified: new Date().toISOString(),
1060
- local: i % 2 === 0
1061
- });
1062
- }
1063
- return [
1064
- 4,
1065
- env.start()
1066
- ];
1067
- case 2:
1068
- px = _state.sent();
1069
- _state.label = 3;
1070
- case 3:
1071
- _state.trys.push([
1072
- 3,
1073
- ,
1074
- 6,
1075
- 8
1076
- ]);
1077
- return [
1078
- 4,
1079
- px([
1080
- 'resources',
1081
- 'list'
1082
- ])
1083
- ];
1084
- case 4:
1085
- waitForOutput = _state.sent().waitForOutput;
1086
- return [
1087
- 4,
1088
- waitForOutput(/Found 5 resources:/)
1089
- ];
1090
- case 5:
1091
- foundCount = _state.sent();
1092
- expect(foundCount).toBe(true);
1093
- return [
1094
- 3,
1095
- 8
1096
- ];
1097
- case 6:
1098
- return [
1099
- 4,
1100
- env.stopAndCleanup()
1101
- ];
1102
- case 7:
1103
- _state.sent();
1104
- return [
1105
- 7
1106
- ];
1107
- case 8:
1108
- return [
1109
- 2
1110
- ];
1111
- }
1112
- });
1113
- })();
1114
- });
1115
- it('should show single resource properly', function() {
1116
- return _async_to_generator(function() {
1117
- var env, px, waitForOutput, foundCount;
1118
- return _ts_generator(this, function(_state) {
1119
- switch(_state.label){
1120
- case 0:
1121
- return [
1122
- 4,
1123
- createTestEnv()
1124
- ];
1125
- case 1:
1126
- env = _state.sent();
1127
- // Add a single resource to test singular form
1128
- env.server.addResource({
1129
- key: 'single.txt',
1130
- type: 'text',
1131
- size: 42,
1132
- lastModified: new Date().toISOString(),
1133
- local: true
1134
- });
1135
- return [
1136
- 4,
1137
- env.start()
1138
- ];
1139
- case 2:
1140
- px = _state.sent();
1141
- _state.label = 3;
1142
- case 3:
1143
- _state.trys.push([
1144
- 3,
1145
- ,
1146
- 6,
1147
- 8
1148
- ]);
1149
- return [
1150
- 4,
1151
- px([
1152
- 'resources',
1153
- 'list'
1154
- ])
1155
- ];
1156
- case 4:
1157
- waitForOutput = _state.sent().waitForOutput;
1158
- return [
1159
- 4,
1160
- waitForOutput(/Found 1 resource:/)
1161
- ];
1162
- case 5:
1163
- foundCount = _state.sent();
1164
- expect(foundCount).toBe(true);
1165
- return [
1166
- 3,
1167
- 8
1168
- ];
1169
- case 6:
1170
- return [
1171
- 4,
1172
- env.stopAndCleanup()
1173
- ];
1174
- case 7:
1175
- _state.sent();
1176
- return [
1177
- 7
1178
- ];
1179
- case 8:
1180
- return [
1181
- 2
1182
- ];
1183
- }
1184
- });
1185
- })();
1186
- });
1187
- });
1188
- describe('resources delete command', function() {
1189
- it('should show error when resource does not exist', function() {
1190
- return _async_to_generator(function() {
1191
- var env, px, waitForOutput, foundChecking, foundWarning;
1192
- return _ts_generator(this, function(_state) {
1193
- switch(_state.label){
1194
- case 0:
1195
- return [
1196
- 4,
1197
- createTestEnv()
1198
- ];
1199
- case 1:
1200
- env = _state.sent();
1201
- return [
1202
- 4,
1203
- env.start()
1204
- ];
1205
- case 2:
1206
- px = _state.sent();
1207
- _state.label = 3;
1208
- case 3:
1209
- _state.trys.push([
1210
- 3,
1211
- ,
1212
- 7,
1213
- 9
1214
- ]);
1215
- return [
1216
- 4,
1217
- px([
1218
- 'resources',
1219
- 'upload',
1220
- '-d',
1221
- 'non-existent.txt'
1222
- ])
1223
- ];
1224
- case 4:
1225
- waitForOutput = _state.sent().waitForOutput;
1226
- return [
1227
- 4,
1228
- waitForOutput(/Checking resource\.\.\./)
1229
- ];
1230
- case 5:
1231
- foundChecking = _state.sent();
1232
- expect(foundChecking).toBe(true);
1233
- return [
1234
- 4,
1235
- waitForOutput(/Warning: This will permanently delete/)
1236
- ];
1237
- case 6:
1238
- foundWarning = _state.sent();
1239
- expect(foundWarning).toBe(true);
1240
- return [
1241
- 3,
1242
- 9
1243
- ];
1244
- case 7:
1245
- return [
1246
- 4,
1247
- env.stopAndCleanup()
1248
- ];
1249
- case 8:
1250
- _state.sent();
1251
- return [
1252
- 7
1253
- ];
1254
- case 9:
1255
- return [
1256
- 2
1257
- ];
1258
- }
1259
- });
1260
- })();
1261
- });
1262
- it('should prevent deletion of local resources', function() {
1263
- return _async_to_generator(function() {
1264
- var env, px, waitForOutput, foundError, foundExplanation, foundInstructions;
1265
- return _ts_generator(this, function(_state) {
1266
- switch(_state.label){
1267
- case 0:
1268
- return [
1269
- 4,
1270
- createTestEnv()
1271
- ];
1272
- case 1:
1273
- env = _state.sent();
1274
- // Add a local resource
1275
- env.server.addResource({
1276
- key: 'local-file.txt',
1277
- type: 'text',
1278
- size: 100,
1279
- lastModified: new Date().toISOString(),
1280
- local: true
1281
- });
1282
- return [
1283
- 4,
1284
- env.start()
1285
- ];
1286
- case 2:
1287
- px = _state.sent();
1288
- _state.label = 3;
1289
- case 3:
1290
- _state.trys.push([
1291
- 3,
1292
- ,
1293
- 8,
1294
- 10
1295
- ]);
1296
- return [
1297
- 4,
1298
- px([
1299
- 'resources',
1300
- 'upload',
1301
- '-d',
1302
- 'local-file.txt'
1303
- ])
1304
- ];
1305
- case 4:
1306
- waitForOutput = _state.sent().waitForOutput;
1307
- return [
1308
- 4,
1309
- waitForOutput(/Cannot Delete Local Resource/)
1310
- ];
1311
- case 5:
1312
- foundError = _state.sent();
1313
- expect(foundError).toBe(true);
1314
- return [
1315
- 4,
1316
- waitForOutput(/This resource was synced from your local filesystem/)
1317
- ];
1318
- case 6:
1319
- foundExplanation = _state.sent();
1320
- expect(foundExplanation).toBe(true);
1321
- return [
1322
- 4,
1323
- waitForOutput(/delete the file locally and run 'px resources sync'/)
1324
- ];
1325
- case 7:
1326
- foundInstructions = _state.sent();
1327
- expect(foundInstructions).toBe(true);
1328
- return [
1329
- 3,
1330
- 10
1331
- ];
1332
- case 8:
1333
- return [
1334
- 4,
1335
- env.stopAndCleanup()
1336
- ];
1337
- case 9:
1338
- _state.sent();
1339
- return [
1340
- 7
1341
- ];
1342
- case 10:
1343
- return [
1344
- 2
1345
- ];
1346
- }
1347
- });
1348
- })();
1349
- });
1350
- it('should show confirmation prompt for remote resources', function() {
1351
- return _async_to_generator(function() {
1352
- var env, px, waitForOutput, foundWarning, foundPath, foundPrompt;
1353
- return _ts_generator(this, function(_state) {
1354
- switch(_state.label){
1355
- case 0:
1356
- return [
1357
- 4,
1358
- createTestEnv()
1359
- ];
1360
- case 1:
1361
- env = _state.sent();
1362
- // Add a remote resource
1363
- env.server.addResource({
1364
- key: 'remote-file.txt',
1365
- type: 'text',
1366
- size: 200,
1367
- lastModified: new Date().toISOString(),
1368
- local: false
1369
- });
1370
- return [
1371
- 4,
1372
- env.start()
1373
- ];
1374
- case 2:
1375
- px = _state.sent();
1376
- _state.label = 3;
1377
- case 3:
1378
- _state.trys.push([
1379
- 3,
1380
- ,
1381
- 8,
1382
- 10
1383
- ]);
1384
- return [
1385
- 4,
1386
- px([
1387
- 'resources',
1388
- 'upload',
1389
- '-d',
1390
- 'remote-file.txt'
1391
- ])
1392
- ];
1393
- case 4:
1394
- waitForOutput = _state.sent().waitForOutput;
1395
- return [
1396
- 4,
1397
- waitForOutput(/Warning: This will permanently delete the following resource/)
1398
- ];
1399
- case 5:
1400
- foundWarning = _state.sent();
1401
- expect(foundWarning).toBe(true);
1402
- return [
1403
- 4,
1404
- waitForOutput(/remote-file\.txt/)
1405
- ];
1406
- case 6:
1407
- foundPath = _state.sent();
1408
- expect(foundPath).toBe(true);
1409
- return [
1410
- 4,
1411
- waitForOutput(/Type "yes" to confirm deletion:/)
1412
- ];
1413
- case 7:
1414
- foundPrompt = _state.sent();
1415
- expect(foundPrompt).toBe(true);
1416
- return [
1417
- 3,
1418
- 10
1419
- ];
1420
- case 8:
1421
- return [
1422
- 4,
1423
- env.stopAndCleanup()
1424
- ];
1425
- case 9:
1426
- _state.sent();
1427
- return [
1428
- 7
1429
- ];
1430
- case 10:
1431
- return [
1432
- 2
1433
- ];
1434
- }
1435
- });
1436
- })();
1437
- });
1438
- it('should delete resource when using force flag', function() {
1439
- return _async_to_generator(function() {
1440
- var env, px, waitForOutput, foundChecking, foundSuccess, calls, deleteCall;
1441
- return _ts_generator(this, function(_state) {
1442
- switch(_state.label){
1443
- case 0:
1444
- return [
1445
- 4,
1446
- createTestEnv()
1447
- ];
1448
- case 1:
1449
- env = _state.sent();
1450
- // Add a remote resource BEFORE starting the server
1451
- env.server.addResource({
1452
- key: 'to-delete.txt',
1453
- type: 'text',
1454
- size: 300,
1455
- lastModified: new Date().toISOString(),
1456
- local: false
1457
- });
1458
- return [
1459
- 4,
1460
- env.start()
1461
- ];
1462
- case 2:
1463
- px = _state.sent();
1464
- _state.label = 3;
1465
- case 3:
1466
- _state.trys.push([
1467
- 3,
1468
- ,
1469
- 7,
1470
- 9
1471
- ]);
1472
- return [
1473
- 4,
1474
- px([
1475
- 'resources',
1476
- 'upload',
1477
- '-d',
1478
- '-f',
1479
- 'to-delete.txt'
1480
- ])
1481
- ];
1482
- case 4:
1483
- waitForOutput = _state.sent().waitForOutput;
1484
- return [
1485
- 4,
1486
- waitForOutput(/Checking resource\.\.\./)
1487
- ];
1488
- case 5:
1489
- foundChecking = _state.sent();
1490
- expect(foundChecking).toBe(true);
1491
- return [
1492
- 4,
1493
- waitForOutput(/✅ Successfully deleted: to-delete\.txt/)
1494
- ];
1495
- case 6:
1496
- foundSuccess = _state.sent();
1497
- expect(foundSuccess).toBe(true);
1498
- // Verify the resource was actually deleted
1499
- calls = env.server.getLogs();
1500
- deleteCall = calls.find(function(c) {
1501
- return c.method === 'deleteResource' && c.args[0] === 'to-delete.txt';
1502
- });
1503
- expect(deleteCall).toBeDefined();
1504
- return [
1505
- 3,
1506
- 9
1507
- ];
1508
- case 7:
1509
- return [
1510
- 4,
1511
- env.stopAndCleanup()
1512
- ];
1513
- case 8:
1514
- _state.sent();
1515
- return [
1516
- 7
1517
- ];
1518
- case 9:
1519
- return [
1520
- 2
1521
- ];
1522
- }
1523
- });
1524
- })();
1525
- });
1526
- it('should still prevent deletion of local resources with force flag', function() {
1527
- return _async_to_generator(function() {
1528
- var env, px, waitForOutput, foundError;
1529
- return _ts_generator(this, function(_state) {
1530
- switch(_state.label){
1531
- case 0:
1532
- return [
1533
- 4,
1534
- createTestEnv()
1535
- ];
1536
- case 1:
1537
- env = _state.sent();
1538
- // Add a local resource
1539
- env.server.addResource({
1540
- key: 'local-file.txt',
1541
- type: 'text',
1542
- size: 100,
1543
- lastModified: new Date().toISOString(),
1544
- local: true
1545
- });
1546
- return [
1547
- 4,
1548
- env.start()
1549
- ];
1550
- case 2:
1551
- px = _state.sent();
1552
- _state.label = 3;
1553
- case 3:
1554
- _state.trys.push([
1555
- 3,
1556
- ,
1557
- 6,
1558
- 8
1559
- ]);
1560
- return [
1561
- 4,
1562
- px([
1563
- 'resources',
1564
- 'upload',
1565
- '-d',
1566
- '-f',
1567
- 'local-file.txt'
1568
- ])
1569
- ];
1570
- case 4:
1571
- waitForOutput = _state.sent().waitForOutput;
1572
- return [
1573
- 4,
1574
- waitForOutput(/Cannot Delete Local Resource/)
1575
- ];
1576
- case 5:
1577
- foundError = _state.sent();
1578
- expect(foundError).toBe(true);
1579
- return [
1580
- 3,
1581
- 8
1582
- ];
1583
- case 6:
1584
- return [
1585
- 4,
1586
- env.stopAndCleanup()
1587
- ];
1588
- case 7:
1589
- _state.sent();
1590
- return [
1591
- 7
1592
- ];
1593
- case 8:
1594
- return [
1595
- 2
1596
- ];
1597
- }
1598
- });
1599
- })();
1600
- });
1601
- it('should handle API connection errors', function() {
1602
- return _async_to_generator(function() {
1603
- var env, waitForOutput, foundChecking, foundError;
1604
- return _ts_generator(this, function(_state) {
1605
- switch(_state.label){
1606
- case 0:
1607
- return [
1608
- 4,
1609
- createTestEnv()
1610
- ];
1611
- case 1:
1612
- env = _state.sent();
1613
- _state.label = 2;
1614
- case 2:
1615
- _state.trys.push([
1616
- 2,
1617
- ,
1618
- 6,
1619
- 7
1620
- ]);
1621
- return [
1622
- 4,
1623
- px([
1624
- 'resources',
1625
- 'upload',
1626
- '-d',
1627
- 'any-resource.txt'
1628
- ], {
1629
- server: env.server
1630
- })
1631
- ];
1632
- case 3:
1633
- waitForOutput = _state.sent().waitForOutput;
1634
- return [
1635
- 4,
1636
- waitForOutput(/Checking resource\.\.\./)
1637
- ];
1638
- case 4:
1639
- foundChecking = _state.sent();
1640
- expect(foundChecking).toBe(true);
1641
- return [
1642
- 4,
1643
- waitForOutput(/Error connecting/)
1644
- ];
1645
- case 5:
1646
- foundError = _state.sent();
1647
- expect(foundError).toBe(true);
1648
- return [
1649
- 3,
1650
- 7
1651
- ];
1652
- case 6:
1653
- return [
1654
- 7
1655
- ];
1656
- case 7:
1657
- return [
1658
- 2
1659
- ];
1660
- }
1661
- });
1662
- })();
1663
- });
1664
- it('should handle nested resource paths with force flag', function() {
1665
- return _async_to_generator(function() {
1666
- var env, px, waitForOutput, foundSuccess, calls, deleteCall;
1667
- return _ts_generator(this, function(_state) {
1668
- switch(_state.label){
1669
- case 0:
1670
- return [
1671
- 4,
1672
- createTestEnv()
1673
- ];
1674
- case 1:
1675
- env = _state.sent();
1676
- // Add a nested resource
1677
- env.server.addResource({
1678
- key: 'folder/subfolder/nested-file.txt',
1679
- type: 'text',
1680
- size: 800,
1681
- lastModified: new Date().toISOString(),
1682
- local: false
1683
- });
1684
- return [
1685
- 4,
1686
- env.start()
1687
- ];
1688
- case 2:
1689
- px = _state.sent();
1690
- _state.label = 3;
1691
- case 3:
1692
- _state.trys.push([
1693
- 3,
1694
- ,
1695
- 6,
1696
- 8
1697
- ]);
1698
- return [
1699
- 4,
1700
- px([
1701
- 'resources',
1702
- 'upload',
1703
- '-d',
1704
- '-f',
1705
- 'folder/subfolder/nested-file.txt'
1706
- ])
1707
- ];
1708
- case 4:
1709
- waitForOutput = _state.sent().waitForOutput;
1710
- return [
1711
- 4,
1712
- waitForOutput(/✅ Successfully deleted: folder\/subfolder\/nested-file\.txt/)
1713
- ];
1714
- case 5:
1715
- foundSuccess = _state.sent();
1716
- expect(foundSuccess).toBe(true);
1717
- // Verify the resource was deleted
1718
- calls = env.server.getLogs();
1719
- deleteCall = calls.find(function(c) {
1720
- return c.method === 'deleteResource' && c.args[0] === 'folder/subfolder/nested-file.txt';
1721
- });
1722
- expect(deleteCall).toBeDefined();
1723
- return [
1724
- 3,
1725
- 8
1726
- ];
1727
- case 6:
1728
- return [
1729
- 4,
1730
- env.stopAndCleanup()
1731
- ];
1732
- case 7:
1733
- _state.sent();
1734
- return [
1735
- 7
1736
- ];
1737
- case 8:
1738
- return [
1739
- 2
1740
- ];
1741
- }
1742
- });
1743
- })();
1744
- });
1745
- it('should handle nested resource paths without force flag', function() {
1746
- return _async_to_generator(function() {
1747
- var env, px, waitForOutput, foundPath, foundPrompt;
1748
- return _ts_generator(this, function(_state) {
1749
- switch(_state.label){
1750
- case 0:
1751
- return [
1752
- 4,
1753
- createTestEnv()
1754
- ];
1755
- case 1:
1756
- env = _state.sent();
1757
- // Add a nested resource
1758
- env.server.addResource({
1759
- key: 'folder/nested.txt',
1760
- type: 'text',
1761
- size: 400,
1762
- lastModified: new Date().toISOString(),
1763
- local: false
1764
- });
1765
- return [
1766
- 4,
1767
- env.start()
1768
- ];
1769
- case 2:
1770
- px = _state.sent();
1771
- _state.label = 3;
1772
- case 3:
1773
- _state.trys.push([
1774
- 3,
1775
- ,
1776
- 7,
1777
- 9
1778
- ]);
1779
- return [
1780
- 4,
1781
- px([
1782
- 'resources',
1783
- 'upload',
1784
- '-d',
1785
- 'folder/nested.txt'
1786
- ])
1787
- ];
1788
- case 4:
1789
- waitForOutput = _state.sent().waitForOutput;
1790
- return [
1791
- 4,
1792
- waitForOutput(/folder\/nested\.txt/)
1793
- ];
1794
- case 5:
1795
- foundPath = _state.sent();
1796
- expect(foundPath).toBe(true);
1797
- return [
1798
- 4,
1799
- waitForOutput(/Type "yes" to confirm deletion:/)
1800
- ];
1801
- case 6:
1802
- foundPrompt = _state.sent();
1803
- expect(foundPrompt).toBe(true);
1804
- return [
1805
- 3,
1806
- 9
1807
- ];
1808
- case 7:
1809
- return [
1810
- 4,
1811
- env.stopAndCleanup()
1812
- ];
1813
- case 8:
1814
- _state.sent();
1815
- return [
1816
- 7
1817
- ];
1818
- case 9:
1819
- return [
1820
- 2
1821
- ];
1822
- }
1823
- });
1824
- })();
1825
- });
1826
- it('should show loading state while checking resource', function() {
1827
- return _async_to_generator(function() {
1828
- var env, px, waitForOutput, foundChecking, foundError;
1829
- return _ts_generator(this, function(_state) {
1830
- switch(_state.label){
1831
- case 0:
1832
- return [
1833
- 4,
1834
- createTestEnv()
1835
- ];
1836
- case 1:
1837
- env = _state.sent();
1838
- return [
1839
- 4,
1840
- env.start()
1841
- ];
1842
- case 2:
1843
- px = _state.sent();
1844
- _state.label = 3;
1845
- case 3:
1846
- _state.trys.push([
1847
- 3,
1848
- ,
1849
- 7,
1850
- 8
1851
- ]);
1852
- // Stop server to simulate slow loading
1853
- env.server.stop();
1854
- return [
1855
- 4,
1856
- px([
1857
- 'resources',
1858
- 'upload',
1859
- '-d',
1860
- 'any-file.txt'
1861
- ])
1862
- ];
1863
- case 4:
1864
- waitForOutput = _state.sent().waitForOutput;
1865
- return [
1866
- 4,
1867
- waitForOutput(/Checking resource\.\.\./)
1868
- ];
1869
- case 5:
1870
- foundChecking = _state.sent();
1871
- expect(foundChecking).toBe(true);
1872
- return [
1873
- 4,
1874
- waitForOutput(/Error/)
1875
- ];
1876
- case 6:
1877
- foundError = _state.sent();
1878
- expect(foundError).toBe(true);
1879
- return [
1880
- 3,
1881
- 8
1882
- ];
1883
- case 7:
1884
- // Cleanup without stopping server (already stopped)
1885
- env.cleanup();
1886
- return [
1887
- 7
1888
- ];
1889
- case 8:
1890
- return [
1891
- 2
1892
- ];
1893
- }
1894
- });
1895
- })();
1896
- });
1897
- });
1898
- describe('resources clear command', function() {
1899
- it('should handle empty resources gracefully', function() {
1900
- return _async_to_generator(function() {
1901
- var env, px, waitForOutput, isOutputRendered;
1902
- return _ts_generator(this, function(_state) {
1903
- switch(_state.label){
1904
- case 0:
1905
- return [
1906
- 4,
1907
- createTestEnv()
1908
- ];
1909
- case 1:
1910
- env = _state.sent();
1911
- return [
1912
- 4,
1913
- env.start()
1914
- ];
1915
- case 2:
1916
- px = _state.sent();
1917
- _state.label = 3;
1918
- case 3:
1919
- _state.trys.push([
1920
- 3,
1921
- ,
1922
- 6,
1923
- 8
1924
- ]);
1925
- return [
1926
- 4,
1927
- px([
1928
- 'resources',
1929
- 'clear'
1930
- ])
1931
- ];
1932
- case 4:
1933
- waitForOutput = _state.sent().waitForOutput;
1934
- return [
1935
- 4,
1936
- waitForOutput(/No resources to delete/, 20)
1937
- ];
1938
- case 5:
1939
- isOutputRendered = _state.sent();
1940
- expect(isOutputRendered).toBe(true);
1941
- return [
1942
- 3,
1943
- 8
1944
- ];
1945
- case 6:
1946
- return [
1947
- 4,
1948
- env.stopAndCleanup()
1949
- ];
1950
- case 7:
1951
- _state.sent();
1952
- return [
1953
- 7
1954
- ];
1955
- case 8:
1956
- return [
1957
- 2
1958
- ];
1959
- }
1960
- });
1961
- })();
1962
- });
1963
- it('should show warning for non-empty resources', function() {
1964
- return _async_to_generator(function() {
1965
- var env, px, waitForOutput, isWarningShown, isCountShown, isPromptShown, isCancelSelected;
1966
- return _ts_generator(this, function(_state) {
1967
- switch(_state.label){
1968
- case 0:
1969
- return [
1970
- 4,
1971
- createTestEnv()
1972
- ];
1973
- case 1:
1974
- env = _state.sent();
1975
- // Add some mock resources to the test server
1976
- env.server.addResource({
1977
- key: 'test.txt',
1978
- type: 'text',
1979
- size: 100,
1980
- lastModified: new Date().toISOString()
1981
- });
1982
- env.server.addResource({
1983
- key: 'data/config.json',
1984
- type: 'text',
1985
- size: 200,
1986
- lastModified: new Date().toISOString()
1987
- });
1988
- return [
1989
- 4,
1990
- env.start()
1991
- ];
1992
- case 2:
1993
- px = _state.sent();
1994
- _state.label = 3;
1995
- case 3:
1996
- _state.trys.push([
1997
- 3,
1998
- ,
1999
- 9,
2000
- 11
2001
- ]);
2002
- return [
2003
- 4,
2004
- px([
2005
- 'resources',
2006
- 'clear'
2007
- ])
2008
- ];
2009
- case 4:
2010
- waitForOutput = _state.sent().waitForOutput;
2011
- return [
2012
- 4,
2013
- waitForOutput(/DANGER: This will permanently delete ALL resources!/)
2014
- ];
2015
- case 5:
2016
- isWarningShown = _state.sent();
2017
- expect(isWarningShown).toBe(true);
2018
- return [
2019
- 4,
2020
- waitForOutput(/This action will delete 2 resource\(s\)/)
2021
- ];
2022
- case 6:
2023
- isCountShown = _state.sent();
2024
- expect(isCountShown).toBe(true);
2025
- return [
2026
- 4,
2027
- waitForOutput(/Use arrow keys to select, Enter to confirm:/)
2028
- ];
2029
- case 7:
2030
- isPromptShown = _state.sent();
2031
- expect(isPromptShown).toBe(true);
2032
- return [
2033
- 4,
2034
- waitForOutput(/▶ Cancel \(keep resources\)/)
2035
- ];
2036
- case 8:
2037
- isCancelSelected = _state.sent();
2038
- expect(isCancelSelected).toBe(true);
2039
- return [
2040
- 3,
2041
- 11
2042
- ];
2043
- case 9:
2044
- return [
2045
- 4,
2046
- env.stopAndCleanup()
2047
- ];
2048
- case 10:
2049
- _state.sent();
2050
- return [
2051
- 7
2052
- ];
2053
- case 11:
2054
- return [
2055
- 2
2056
- ];
2057
- }
2058
- });
2059
- })();
2060
- });
2061
- it('should navigate between options with arrow keys', function() {
2062
- return _async_to_generator(function() {
2063
- var env, px, _ref, waitForOutput, instance, isCancelSelected, isDeleteSelected, isCancelSelectedAgain;
2064
- return _ts_generator(this, function(_state) {
2065
- switch(_state.label){
2066
- case 0:
2067
- return [
2068
- 4,
2069
- createTestEnv()
2070
- ];
2071
- case 1:
2072
- env = _state.sent();
2073
- // Add a mock resource so we get the confirmation prompt
2074
- env.server.addResource({
2075
- key: 'test.txt',
2076
- type: 'text',
2077
- size: 100,
2078
- lastModified: new Date().toISOString()
2079
- });
2080
- return [
2081
- 4,
2082
- env.start()
2083
- ];
2084
- case 2:
2085
- px = _state.sent();
2086
- _state.label = 3;
2087
- case 3:
2088
- _state.trys.push([
2089
- 3,
2090
- ,
2091
- 9,
2092
- 11
2093
- ]);
2094
- return [
2095
- 4,
2096
- px([
2097
- 'resources',
2098
- 'clear'
2099
- ])
2100
- ];
2101
- case 4:
2102
- _ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
2103
- // Wait for the prompt to appear
2104
- return [
2105
- 4,
2106
- waitForOutput(/Use arrow keys to select, Enter to confirm:/)
2107
- ];
2108
- case 5:
2109
- _state.sent();
2110
- return [
2111
- 4,
2112
- waitForOutput(/▶ Cancel \(keep resources\)/)
2113
- ];
2114
- case 6:
2115
- isCancelSelected = _state.sent();
2116
- expect(isCancelSelected).toBe(true);
2117
- // Press down arrow
2118
- instance.stdin.write('\u001B[B');
2119
- return [
2120
- 4,
2121
- waitForOutput(/▶ Delete all resources/, 30)
2122
- ];
2123
- case 7:
2124
- isDeleteSelected = _state.sent();
2125
- expect(isDeleteSelected).toBe(true);
2126
- // Press up arrow to go back
2127
- instance.stdin.write('\u001B[A');
2128
- return [
2129
- 4,
2130
- waitForOutput(/▶ Cancel \(keep resources\)/, 30)
2131
- ];
2132
- case 8:
2133
- isCancelSelectedAgain = _state.sent();
2134
- expect(isCancelSelectedAgain).toBe(true);
2135
- return [
2136
- 3,
2137
- 11
2138
- ];
2139
- case 9:
2140
- return [
2141
- 4,
2142
- env.stopAndCleanup()
2143
- ];
2144
- case 10:
2145
- _state.sent();
2146
- return [
2147
- 7
2148
- ];
2149
- case 11:
2150
- return [
2151
- 2
2152
- ];
2153
- }
2154
- });
2155
- })();
2156
- });
2157
- });
2158
- describe('resources types command', function() {
2159
- it('should generate resource types successfully', function() {
2160
- return _async_to_generator(function() {
2161
- var env, px, waitForOutput, foundSuccess, typesPath, typesContent;
2162
- return _ts_generator(this, function(_state) {
2163
- switch(_state.label){
2164
- case 0:
2165
- return [
2166
- 4,
2167
- createTestEnv()
2168
- ];
2169
- case 1:
2170
- env = _state.sent();
2171
- return [
2172
- 4,
2173
- env.start()
2174
- ];
2175
- case 2:
2176
- px = _state.sent();
2177
- _state.label = 3;
2178
- case 3:
2179
- _state.trys.push([
2180
- 3,
2181
- ,
2182
- 6,
2183
- 8
2184
- ]);
2185
- return [
2186
- 4,
2187
- px([
2188
- 'resources',
2189
- 'types'
2190
- ])
2191
- ];
2192
- case 4:
2193
- waitForOutput = _state.sent().waitForOutput;
2194
- return [
2195
- 4,
2196
- waitForOutput(/Generated resource types at/i)
2197
- ];
2198
- case 5:
2199
- foundSuccess = _state.sent();
2200
- expect(foundSuccess).toBe(true);
2201
- // Verify the types file was actually created
2202
- typesPath = path.join(env.projectRootDir, 'resources.d.ts');
2203
- expect(fs.existsSync(typesPath)).toBe(true);
2204
- // Verify basic content of the types file
2205
- typesContent = fs.readFileSync(typesPath, 'utf-8');
2206
- expect(typesContent).toContain("declare module '@positronic/core'");
2207
- expect(typesContent).toContain('interface Resources');
2208
- return [
2209
- 3,
2210
- 8
2211
- ];
2212
- case 6:
2213
- return [
2214
- 4,
2215
- env.stopAndCleanup()
2216
- ];
2217
- case 7:
2218
- _state.sent();
2219
- return [
2220
- 7
2221
- ];
2222
- case 8:
2223
- return [
2224
- 2
2225
- ];
2226
- }
2227
- });
2228
- })();
2229
- });
2230
- it('should handle type generation errors gracefully', function() {
2231
- return _async_to_generator(function() {
2232
- var env, px, typesPath, waitForOutput, foundError, foundDetails;
2233
- return _ts_generator(this, function(_state) {
2234
- switch(_state.label){
2235
- case 0:
2236
- return [
2237
- 4,
2238
- createTestEnv()
2239
- ];
2240
- case 1:
2241
- env = _state.sent();
2242
- return [
2243
- 4,
2244
- env.start()
2245
- ];
2246
- case 2:
2247
- px = _state.sent();
2248
- _state.label = 3;
2249
- case 3:
2250
- _state.trys.push([
2251
- 3,
2252
- ,
2253
- 7,
2254
- 9
2255
- ]);
2256
- // Make the project directory read-only to cause an error
2257
- typesPath = path.join(env.projectRootDir, 'resources.d.ts');
2258
- // Create a directory with the same name to cause a write error
2259
- fs.mkdirSync(typesPath);
2260
- return [
2261
- 4,
2262
- px([
2263
- 'resources',
2264
- 'types'
2265
- ])
2266
- ];
2267
- case 4:
2268
- waitForOutput = _state.sent().waitForOutput;
2269
- return [
2270
- 4,
2271
- waitForOutput(/Type Generation Failed/i)
2272
- ];
2273
- case 5:
2274
- foundError = _state.sent();
2275
- expect(foundError).toBe(true);
2276
- return [
2277
- 4,
2278
- waitForOutput(/EISDIR|directory/i)
2279
- ];
2280
- case 6:
2281
- foundDetails = _state.sent();
2282
- expect(foundDetails).toBe(true);
2283
- return [
2284
- 3,
2285
- 9
2286
- ];
2287
- case 7:
2288
- return [
2289
- 4,
2290
- env.stopAndCleanup()
2291
- ];
2292
- case 8:
2293
- _state.sent();
2294
- return [
2295
- 7
2296
- ];
2297
- case 9:
2298
- return [
2299
- 2
2300
- ];
2301
- }
2302
- });
2303
- })();
2304
- });
2305
- });
2306
- describe('resources upload command', function() {
2307
- // Testing the upload command's file validation behavior
2308
- // The actual upload requires presigned URLs which aren't available in test environment
2309
- it('should handle non-existent file error', function() {
2310
- return _async_to_generator(function() {
2311
- var env, px, nonExistentPath, waitForOutput, foundError;
2312
- return _ts_generator(this, function(_state) {
2313
- switch(_state.label){
2314
- case 0:
2315
- return [
2316
- 4,
2317
- createTestEnv()
2318
- ];
2319
- case 1:
2320
- env = _state.sent();
2321
- return [
2322
- 4,
2323
- env.start()
2324
- ];
2325
- case 2:
2326
- px = _state.sent();
2327
- _state.label = 3;
2328
- case 3:
2329
- _state.trys.push([
2330
- 3,
2331
- ,
2332
- 6,
2333
- 8
2334
- ]);
2335
- nonExistentPath = path.join(env.projectRootDir, 'does-not-exist.txt');
2336
- return [
2337
- 4,
2338
- px([
2339
- 'resources',
2340
- 'upload',
2341
- nonExistentPath
2342
- ])
2343
- ];
2344
- case 4:
2345
- waitForOutput = _state.sent().waitForOutput;
2346
- return [
2347
- 4,
2348
- waitForOutput(/File Not Found/i)
2349
- ];
2350
- case 5:
2351
- foundError = _state.sent();
2352
- expect(foundError).toBe(true);
2353
- return [
2354
- 3,
2355
- 8
2356
- ];
2357
- case 6:
2358
- return [
2359
- 4,
2360
- env.stopAndCleanup()
2361
- ];
2362
- case 7:
2363
- _state.sent();
2364
- return [
2365
- 7
2366
- ];
2367
- case 8:
2368
- return [
2369
- 2
2370
- ];
2371
- }
2372
- });
2373
- })();
2374
- });
2375
- it('should handle directory path error', function() {
2376
- return _async_to_generator(function() {
2377
- var env, px, dirPath, waitForOutput, foundError;
2378
- return _ts_generator(this, function(_state) {
2379
- switch(_state.label){
2380
- case 0:
2381
- return [
2382
- 4,
2383
- createTestEnv()
2384
- ];
2385
- case 1:
2386
- env = _state.sent();
2387
- return [
2388
- 4,
2389
- env.start()
2390
- ];
2391
- case 2:
2392
- px = _state.sent();
2393
- _state.label = 3;
2394
- case 3:
2395
- _state.trys.push([
2396
- 3,
2397
- ,
2398
- 6,
2399
- 8
2400
- ]);
2401
- // Try to upload a directory instead of a file
2402
- dirPath = path.join(env.projectRootDir, 'resources');
2403
- return [
2404
- 4,
2405
- px([
2406
- 'resources',
2407
- 'upload',
2408
- dirPath
2409
- ])
2410
- ];
2411
- case 4:
2412
- waitForOutput = _state.sent().waitForOutput;
2413
- return [
2414
- 4,
2415
- waitForOutput(/Invalid Path/i)
2416
- ];
2417
- case 5:
2418
- foundError = _state.sent();
2419
- expect(foundError).toBe(true);
2420
- return [
2421
- 3,
2422
- 8
2423
- ];
2424
- case 6:
2425
- return [
2426
- 4,
2427
- env.stopAndCleanup()
2428
- ];
2429
- case 7:
2430
- _state.sent();
2431
- return [
2432
- 7
2433
- ];
2434
- case 8:
2435
- return [
2436
- 2
2437
- ];
2438
- }
2439
- });
2440
- })();
2441
- });
2442
- it('should validate files before attempting upload', function() {
2443
- return _async_to_generator(function() {
2444
- var env, px, testFilePath, waitForOutput, foundOutput;
2445
- return _ts_generator(this, function(_state) {
2446
- switch(_state.label){
2447
- case 0:
2448
- return [
2449
- 4,
2450
- createTestEnv()
2451
- ];
2452
- case 1:
2453
- env = _state.sent();
2454
- return [
2455
- 4,
2456
- env.start()
2457
- ];
2458
- case 2:
2459
- px = _state.sent();
2460
- _state.label = 3;
2461
- case 3:
2462
- _state.trys.push([
2463
- 3,
2464
- ,
2465
- 6,
2466
- 8
2467
- ]);
2468
- // Create a test file
2469
- testFilePath = path.join(env.projectRootDir, 'test.txt');
2470
- fs.writeFileSync(testFilePath, 'Hello, world!');
2471
- return [
2472
- 4,
2473
- px([
2474
- 'resources',
2475
- 'upload',
2476
- testFilePath
2477
- ])
2478
- ];
2479
- case 4:
2480
- waitForOutput = _state.sent().waitForOutput;
2481
- return [
2482
- 4,
2483
- waitForOutput(/Uploading test\.txt|Failed|Error/i)
2484
- ];
2485
- case 5:
2486
- foundOutput = _state.sent();
2487
- expect(foundOutput).toBe(true);
2488
- return [
2489
- 3,
2490
- 8
2491
- ];
2492
- case 6:
2493
- return [
2494
- 4,
2495
- env.stopAndCleanup()
2496
- ];
2497
- case 7:
2498
- _state.sent();
2499
- return [
2500
- 7
2501
- ];
2502
- case 8:
2503
- return [
2504
- 2
2505
- ];
2506
- }
2507
- });
2508
- })();
2509
- });
2510
- });
2511
- });