@sasjs/cli 6.30.1 → 6.31.0

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.
@@ -86,6 +86,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
86
86
  return (mod && mod.__esModule) ? mod : { "default": mod };
87
87
  };
88
88
  Object.defineProperty(exports, "__esModule", { value: true });
89
+ var fs_1 = __importDefault(require("fs"));
89
90
  var path_1 = __importDefault(require("path"));
90
91
  var api_1 = require("@sasjs/api");
91
92
  var os_1 = __importDefault(require("os"));
@@ -2561,6 +2562,55 @@ describe('service worker host', function () {
2561
2562
  }
2562
2563
  });
2563
2564
  }); });
2565
+ /**
2566
+ * The console's own files are the page, not an API call.
2567
+ *
2568
+ * `/api/...` is the API's short spelling, so the worker answers it - except for
2569
+ * the four files the console is made of, which the static host serves. Getting
2570
+ * that wrong answers the page's own script with an API 404, and the console
2571
+ * renders nothing.
2572
+ */
2573
+ it('leaves the API console to the static host, and still answers /api calls', function () { return __awaiter(void 0, void 0, void 0, function () {
2574
+ var worker, source, listed, files, files_1, files_1_1, name_1, log, response;
2575
+ var e_2, _a;
2576
+ return __generator(this, function (_b) {
2577
+ switch (_b.label) {
2578
+ case 0:
2579
+ worker = seeded();
2580
+ source = fs_1.default.readFileSync(path_1.default.join(__dirname, '..', 'assets', 'sw.js'), 'utf8');
2581
+ listed = /const API_CONSOLE_FILES = \[([^\]]*)\]/.exec(source);
2582
+ expect(listed).not.toBeNull();
2583
+ files = listed[1]
2584
+ .split(',')
2585
+ .map(function (entry) { return entry.trim().replace(/^'|'$/g, ''); })
2586
+ .filter(Boolean);
2587
+ expect(files.length).toBeGreaterThan(3);
2588
+ expect(worker.dispatch('/api/')).toBeUndefined();
2589
+ try {
2590
+ for (files_1 = __values(files), files_1_1 = files_1.next(); !files_1_1.done; files_1_1 = files_1.next()) {
2591
+ name_1 = files_1_1.value;
2592
+ expect(worker.dispatch("/api/".concat(name_1))).toBeUndefined();
2593
+ }
2594
+ }
2595
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2596
+ finally {
2597
+ try {
2598
+ if (files_1_1 && !files_1_1.done && (_a = files_1.return)) _a.call(files_1);
2599
+ }
2600
+ finally { if (e_2) throw e_2.error; }
2601
+ }
2602
+ return [4 /*yield*/, worker.dispatch('/api/admin/logs/missing.log')];
2603
+ case 1:
2604
+ log = _b.sent();
2605
+ expect(log.status).not.toBeUndefined();
2606
+ return [4 /*yield*/, worker.dispatch('/api/user')];
2607
+ case 2:
2608
+ response = _b.sent();
2609
+ expect(response.status).toBe(200);
2610
+ return [2 /*return*/];
2611
+ }
2612
+ });
2613
+ }); });
2564
2614
  it('answers 404 for a drive file the drive does not hold', function () { return __awaiter(void 0, void 0, void 0, function () {
2565
2615
  var dispatch, response, _a;
2566
2616
  return __generator(this, function (_b) {
@@ -2580,8 +2630,8 @@ describe('service worker host', function () {
2580
2630
  });
2581
2631
  }); });
2582
2632
  it('publishes, lists, serves and removes an app through the package surface', function () { return __awaiter(void 0, void 0, void 0, function () {
2583
- var dispatch, _a, _b, path_2, listing, _c, e_2_1, _d, _e, path_3, landing, e_3_1, root, archive, form, published, app, _f, _g, path_4, listing, _h, e_4_1, _j, _k, path_5, page, _l, e_5_1, folder, _m, refused, missing, removed, _o, after, _p, gone;
2584
- var e_2, _q, e_3, _r, e_4, _s, e_5, _t;
2633
+ var dispatch, _a, _b, path_2, listing, _c, e_3_1, _d, _e, path_3, landing, e_4_1, root, archive, form, published, app, _f, _g, path_4, listing, _h, e_5_1, _j, _k, path_5, page, _l, e_6_1, folder, _m, refused, missing, removed, _o, after, _p, gone;
2634
+ var e_3, _q, e_4, _r, e_5, _s, e_6, _t;
2585
2635
  return __generator(this, function (_u) {
2586
2636
  switch (_u.label) {
2587
2637
  case 0:
@@ -2608,14 +2658,14 @@ describe('service worker host', function () {
2608
2658
  return [3 /*break*/, 2];
2609
2659
  case 6: return [3 /*break*/, 9];
2610
2660
  case 7:
2611
- e_2_1 = _u.sent();
2612
- e_2 = { error: e_2_1 };
2661
+ e_3_1 = _u.sent();
2662
+ e_3 = { error: e_3_1 };
2613
2663
  return [3 /*break*/, 9];
2614
2664
  case 8:
2615
2665
  try {
2616
2666
  if (_b && !_b.done && (_q = _a.return)) _q.call(_a);
2617
2667
  }
2618
- finally { if (e_2) throw e_2.error; }
2668
+ finally { if (e_3) throw e_3.error; }
2619
2669
  return [7 /*endfinally*/];
2620
2670
  case 9:
2621
2671
  _u.trys.push([9, 14, 15, 16]);
@@ -2635,14 +2685,14 @@ describe('service worker host', function () {
2635
2685
  return [3 /*break*/, 10];
2636
2686
  case 13: return [3 /*break*/, 16];
2637
2687
  case 14:
2638
- e_3_1 = _u.sent();
2639
- e_3 = { error: e_3_1 };
2688
+ e_4_1 = _u.sent();
2689
+ e_4 = { error: e_4_1 };
2640
2690
  return [3 /*break*/, 16];
2641
2691
  case 15:
2642
2692
  try {
2643
2693
  if (_e && !_e.done && (_r = _d.return)) _r.call(_d);
2644
2694
  }
2645
- finally { if (e_3) throw e_3.error; }
2695
+ finally { if (e_4) throw e_4.error; }
2646
2696
  return [7 /*endfinally*/];
2647
2697
  case 16: return [4 /*yield*/, dispatch('/AppStream')];
2648
2698
  case 17:
@@ -2695,14 +2745,14 @@ describe('service worker host', function () {
2695
2745
  return [3 /*break*/, 22];
2696
2746
  case 26: return [3 /*break*/, 29];
2697
2747
  case 27:
2698
- e_4_1 = _u.sent();
2699
- e_4 = { error: e_4_1 };
2748
+ e_5_1 = _u.sent();
2749
+ e_5 = { error: e_5_1 };
2700
2750
  return [3 /*break*/, 29];
2701
2751
  case 28:
2702
2752
  try {
2703
2753
  if (_g && !_g.done && (_s = _f.return)) _s.call(_f);
2704
2754
  }
2705
- finally { if (e_4) throw e_4.error; }
2755
+ finally { if (e_5) throw e_5.error; }
2706
2756
  return [7 /*endfinally*/];
2707
2757
  case 29:
2708
2758
  _u.trys.push([29, 35, 36, 37]);
@@ -2729,14 +2779,14 @@ describe('service worker host', function () {
2729
2779
  return [3 /*break*/, 30];
2730
2780
  case 34: return [3 /*break*/, 37];
2731
2781
  case 35:
2732
- e_5_1 = _u.sent();
2733
- e_5 = { error: e_5_1 };
2782
+ e_6_1 = _u.sent();
2783
+ e_6 = { error: e_6_1 };
2734
2784
  return [3 /*break*/, 37];
2735
2785
  case 36:
2736
2786
  try {
2737
2787
  if (_k && !_k.done && (_t = _j.return)) _t.call(_j);
2738
2788
  }
2739
- finally { if (e_5) throw e_5.error; }
2789
+ finally { if (e_6) throw e_6.error; }
2740
2790
  return [7 /*endfinally*/];
2741
2791
  case 37: return [4 /*yield*/, dispatch("/app/".concat(app.id))];
2742
2792
  case 38:
@@ -3685,7 +3735,7 @@ describe('service worker host', function () {
3685
3735
  }); });
3686
3736
  });
3687
3737
  describe('conformance corpus', function () {
3688
- var e_6, _a, e_7, _b;
3738
+ var e_7, _a, e_8, _b;
3689
3739
  /**
3690
3740
  * The corpus is what "the same API" means: the cases @sasjs/api runs against
3691
3741
  * its own services, and against a live sasjs/server, run here against this
@@ -3694,7 +3744,7 @@ describe('service worker host', function () {
3694
3744
  * used to have - and it is a test rather than a review.
3695
3745
  */
3696
3746
  var httpFor = function (testCase) {
3697
- var e_8, _a;
3747
+ var e_9, _a;
3698
3748
  var _b;
3699
3749
  var _c = __read(testCase.route.split(' '), 2), method = _c[0], routePath = _c[1];
3700
3750
  var query = new URLSearchParams();
@@ -3705,12 +3755,12 @@ describe('service worker host', function () {
3705
3755
  query.set(key, String(value));
3706
3756
  }
3707
3757
  }
3708
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
3758
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
3709
3759
  finally {
3710
3760
  try {
3711
3761
  if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
3712
3762
  }
3713
- finally { if (e_8) throw e_8.error; }
3763
+ finally { if (e_9) throw e_9.error; }
3714
3764
  }
3715
3765
  var suffix = query.toString() ? "?".concat(query) : '';
3716
3766
  var init = { method: method };
@@ -3741,8 +3791,8 @@ describe('service worker host', function () {
3741
3791
  * does.
3742
3792
  */
3743
3793
  var seedDrive = function (runtime, testCase) { return __awaiter(void 0, void 0, void 0, function () {
3744
- var text, _a, _b, _c, file, contents, _d, _e, _f, file, contents, e_9_1;
3745
- var e_10, _g, e_9, _h;
3794
+ var text, _a, _b, _c, file, contents, _d, _e, _f, file, contents, e_10_1;
3795
+ var e_11, _g, e_10, _h;
3746
3796
  return __generator(this, function (_j) {
3747
3797
  switch (_j.label) {
3748
3798
  case 0:
@@ -3754,12 +3804,12 @@ describe('service worker host', function () {
3754
3804
  text["/sasjs/drive/files".concat(file)] = contents;
3755
3805
  }
3756
3806
  }
3757
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
3807
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
3758
3808
  finally {
3759
3809
  try {
3760
3810
  if (_b && !_b.done && (_g = _a.return)) _g.call(_a);
3761
3811
  }
3762
- finally { if (e_10) throw e_10.error; }
3812
+ finally { if (e_11) throw e_11.error; }
3763
3813
  }
3764
3814
  return [4 /*yield*/, runtime.load(text)];
3765
3815
  case 1:
@@ -3782,14 +3832,14 @@ describe('service worker host', function () {
3782
3832
  return [3 /*break*/, 3];
3783
3833
  case 6: return [3 /*break*/, 9];
3784
3834
  case 7:
3785
- e_9_1 = _j.sent();
3786
- e_9 = { error: e_9_1 };
3835
+ e_10_1 = _j.sent();
3836
+ e_10 = { error: e_10_1 };
3787
3837
  return [3 /*break*/, 9];
3788
3838
  case 8:
3789
3839
  try {
3790
3840
  if (_e && !_e.done && (_h = _d.return)) _h.call(_d);
3791
3841
  }
3792
- finally { if (e_9) throw e_9.error; }
3842
+ finally { if (e_10) throw e_10.error; }
3793
3843
  return [7 /*endfinally*/];
3794
3844
  case 9: return [2 /*return*/];
3795
3845
  }
@@ -3900,12 +3950,12 @@ describe('service worker host', function () {
3900
3950
  _loop_1(testCase);
3901
3951
  }
3902
3952
  }
3903
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
3953
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
3904
3954
  finally {
3905
3955
  try {
3906
3956
  if (DRIVE_CORPUS_1_1 && !DRIVE_CORPUS_1_1.done && (_a = DRIVE_CORPUS_1.return)) _a.call(DRIVE_CORPUS_1);
3907
3957
  }
3908
- finally { if (e_6) throw e_6.error; }
3958
+ finally { if (e_7) throw e_7.error; }
3909
3959
  }
3910
3960
  /** The app a removal case names, as the corpus states it. */
3911
3961
  var CORPUS_APP = {
@@ -3974,7 +4024,7 @@ describe('service worker host', function () {
3974
4024
  return __generator(this, function (_a) {
3975
4025
  files = {};
3976
4026
  walk = function (members, prefix) {
3977
- var e_11, _a;
4027
+ var e_12, _a;
3978
4028
  var _b;
3979
4029
  try {
3980
4030
  for (var _c = __values(members || []), _d = _c.next(); !_d.done; _d = _c.next()) {
@@ -3989,12 +4039,12 @@ describe('service worker host', function () {
3989
4039
  : String((_b = member.code) !== null && _b !== void 0 ? _b : '');
3990
4040
  }
3991
4041
  }
3992
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
4042
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
3993
4043
  finally {
3994
4044
  try {
3995
4045
  if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
3996
4046
  }
3997
- finally { if (e_11) throw e_11.error; }
4047
+ finally { if (e_12) throw e_12.error; }
3998
4048
  }
3999
4049
  };
4000
4050
  walk(tree === null || tree === void 0 ? void 0 : tree.members, '');
@@ -4011,7 +4061,7 @@ describe('service worker host', function () {
4011
4061
  */
4012
4062
  var deployRequest = function (testCase) { return __awaiter(void 0, void 0, void 0, function () {
4013
4063
  var _a, requestPath, init, body, archive, form, _b, _c, _d, field, value;
4014
- var e_12, _e;
4064
+ var e_13, _e;
4015
4065
  return __generator(this, function (_f) {
4016
4066
  switch (_f.label) {
4017
4067
  case 0:
@@ -4030,12 +4080,12 @@ describe('service worker host', function () {
4030
4080
  form.set(field, String(value));
4031
4081
  }
4032
4082
  }
4033
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
4083
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
4034
4084
  finally {
4035
4085
  try {
4036
4086
  if (_c && !_c.done && (_e = _b.return)) _e.call(_b);
4037
4087
  }
4038
- finally { if (e_12) throw e_12.error; }
4088
+ finally { if (e_13) throw e_13.error; }
4039
4089
  }
4040
4090
  form.set('file', new Blob([new Uint8Array(archive)]), 'deploy.zip');
4041
4091
  return [2 /*return*/, { requestPath: requestPath, init: { method: 'POST', body: form } }];
@@ -4044,8 +4094,8 @@ describe('service worker host', function () {
4044
4094
  }); };
4045
4095
  var _loop_2 = function (testCase) {
4046
4096
  it(testCase.id, function () { return __awaiter(void 0, void 0, void 0, function () {
4047
- var worker, _a, requestPath, init, response, listing, ids, _b, _c, path_6, file, e_13_1, _d, _e, path_7, file, e_14_1;
4048
- var e_13, _f, e_14, _g;
4097
+ var worker, _a, requestPath, init, response, listing, ids, _b, _c, path_6, file, e_14_1, _d, _e, path_7, file, e_15_1;
4098
+ var e_14, _f, e_15, _g;
4049
4099
  var _h, _j, _k;
4050
4100
  return __generator(this, function (_l) {
4051
4101
  switch (_l.label) {
@@ -4097,14 +4147,14 @@ describe('service worker host', function () {
4097
4147
  return [3 /*break*/, 9];
4098
4148
  case 12: return [3 /*break*/, 15];
4099
4149
  case 13:
4100
- e_13_1 = _l.sent();
4101
- e_13 = { error: e_13_1 };
4150
+ e_14_1 = _l.sent();
4151
+ e_14 = { error: e_14_1 };
4102
4152
  return [3 /*break*/, 15];
4103
4153
  case 14:
4104
4154
  try {
4105
4155
  if (_c && !_c.done && (_f = _b.return)) _f.call(_b);
4106
4156
  }
4107
- finally { if (e_13) throw e_13.error; }
4157
+ finally { if (e_14) throw e_14.error; }
4108
4158
  return [7 /*endfinally*/];
4109
4159
  case 15:
4110
4160
  _l.trys.push([15, 20, 21, 22]);
@@ -4123,14 +4173,14 @@ describe('service worker host', function () {
4123
4173
  return [3 /*break*/, 16];
4124
4174
  case 19: return [3 /*break*/, 22];
4125
4175
  case 20:
4126
- e_14_1 = _l.sent();
4127
- e_14 = { error: e_14_1 };
4176
+ e_15_1 = _l.sent();
4177
+ e_15 = { error: e_15_1 };
4128
4178
  return [3 /*break*/, 22];
4129
4179
  case 21:
4130
4180
  try {
4131
4181
  if (_e && !_e.done && (_g = _d.return)) _g.call(_d);
4132
4182
  }
4133
- finally { if (e_14) throw e_14.error; }
4183
+ finally { if (e_15) throw e_15.error; }
4134
4184
  return [7 /*endfinally*/];
4135
4185
  case 22: return [2 /*return*/];
4136
4186
  }
@@ -4163,12 +4213,12 @@ describe('service worker host', function () {
4163
4213
  _loop_2(testCase);
4164
4214
  }
4165
4215
  }
4166
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
4216
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
4167
4217
  finally {
4168
4218
  try {
4169
4219
  if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
4170
4220
  }
4171
- finally { if (e_7) throw e_7.error; }
4221
+ finally { if (e_8) throw e_8.error; }
4172
4222
  }
4173
4223
  });
4174
4224
  /**
@@ -4180,7 +4230,7 @@ describe('service worker host', function () {
4180
4230
  * are the package's.
4181
4231
  */
4182
4232
  describe('identity and record conformance', function () {
4183
- var e_15, _a;
4233
+ var e_16, _a;
4184
4234
  /**
4185
4235
  * Boots the worker from a fixture, the way the page does: the case's own
4186
4236
  * identity, and `subject: null` for no implicit caller, so a case that
@@ -4213,7 +4263,7 @@ describe('service worker host', function () {
4213
4263
  };
4214
4264
  /** The request a case describes, as HTTP: path parameters filled, token sent. */
4215
4265
  var httpForCase = function (testCase) {
4216
- var e_16, _a;
4266
+ var e_17, _a;
4217
4267
  var _b = __read(testCase.route.split(' '), 2), method = _b[0], routePath = _b[1];
4218
4268
  var filled = routePath.replace(/\{(\w+)\}/g, function (_match, name) {
4219
4269
  return encodeURIComponent(String((testCase.request.params || {})[name]));
@@ -4226,12 +4276,12 @@ describe('service worker host', function () {
4226
4276
  query.set(key, String(value));
4227
4277
  }
4228
4278
  }
4229
- catch (e_16_1) { e_16 = { error: e_16_1 }; }
4279
+ catch (e_17_1) { e_17 = { error: e_17_1 }; }
4230
4280
  finally {
4231
4281
  try {
4232
4282
  if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
4233
4283
  }
4234
- finally { if (e_16) throw e_16.error; }
4284
+ finally { if (e_17) throw e_17.error; }
4235
4285
  }
4236
4286
  var suffix = query.toString() ? "?".concat(query) : '';
4237
4287
  var headers = {};
@@ -4353,12 +4403,12 @@ describe('service worker host', function () {
4353
4403
  _loop_3(testCase);
4354
4404
  }
4355
4405
  }
4356
- catch (e_15_1) { e_15 = { error: e_15_1 }; }
4406
+ catch (e_16_1) { e_16 = { error: e_16_1 }; }
4357
4407
  finally {
4358
4408
  try {
4359
4409
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
4360
4410
  }
4361
- finally { if (e_15) throw e_15.error; }
4411
+ finally { if (e_16) throw e_16.error; }
4362
4412
  }
4363
4413
  it('answers as the fixture administrator when no subject was chosen', function () { return __awaiter(void 0, void 0, void 0, function () {
4364
4414
  var worker, response, rules;
@@ -75,6 +75,11 @@ describe('versionMessage', function () {
75
75
  writePackage(root, '6.4.7-alpha.1');
76
76
  expect((0, version_1.versionMessage)(root)).toEqual("You are using a linked version of SASjs CLI (v6.4.7-alpha.1) running from sources at ".concat(root));
77
77
  });
78
+ it('leaves the placeholder version out of a source checkout', function () {
79
+ var root = path_1.default.join(tempRoot(), 'cli');
80
+ writePackage(root, '0.0.0');
81
+ expect((0, version_1.versionMessage)(root)).toEqual("You are using a linked version of SASjs CLI running from sources at ".concat(root));
82
+ });
78
83
  it('leaves the version out of a source checkout that has none', function () {
79
84
  var root = path_1.default.join(tempRoot(), 'cli');
80
85
  writePackage(root, undefined);
@@ -92,6 +97,11 @@ describe('versionMessage', function () {
92
97
  it('throws when an installed package carries no version', function () {
93
98
  var root = packageRoot();
94
99
  writePackage(root, undefined);
95
- expect(function () { return (0, version_1.versionMessage)(root); }).toThrow(/has no version in its package.json/);
100
+ expect(function () { return (0, version_1.versionMessage)(root); }).toThrow(/has no version in its package.json\./);
101
+ });
102
+ it('names the placeholder when an installed package was never stamped', function () {
103
+ var root = packageRoot();
104
+ writePackage(root, '0.0.0');
105
+ expect(function () { return (0, version_1.versionMessage)(root); }).toThrow(/carries the placeholder version 0\.0\.0, so it was never stamped from a tag/);
96
106
  });
97
107
  });
@@ -4,9 +4,11 @@
4
4
  * Reads the version from the package.json of the package that is running, so
5
5
  * it works for every install shape - global, project-local, `npx`, a temp
6
6
  * prefix, or embedded as a dependency. A package root outside a
7
- * `node_modules` folder is a source checkout (an `npm link`, or a local
8
- * build), and is reported as such; a source checkout carries no version until
9
- * semantic-release writes one, so the version is left out when it is absent.
7
+ * `node_modules` folder is a source checkout (an `npm link`, or a local build),
8
+ * and is reported as such. Its package.json carries the placeholder version
9
+ * (`0.0.0`): the version is the git tag, stamped in when the package is
10
+ * published, so from sources there is nothing to report and the version is left
11
+ * out.
10
12
  *
11
13
  * @param packageRoot - the folder holding the package.json of the running CLI.
12
14
  */
@@ -49,9 +49,11 @@ var path_1 = __importDefault(require("path"));
49
49
  * Reads the version from the package.json of the package that is running, so
50
50
  * it works for every install shape - global, project-local, `npx`, a temp
51
51
  * prefix, or embedded as a dependency. A package root outside a
52
- * `node_modules` folder is a source checkout (an `npm link`, or a local
53
- * build), and is reported as such; a source checkout carries no version until
54
- * semantic-release writes one, so the version is left out when it is absent.
52
+ * `node_modules` folder is a source checkout (an `npm link`, or a local build),
53
+ * and is reported as such. Its package.json carries the placeholder version
54
+ * (`0.0.0`): the version is the git tag, stamped in when the package is
55
+ * published, so from sources there is nothing to report and the version is left
56
+ * out.
55
57
  *
56
58
  * @param packageRoot - the folder holding the package.json of the running CLI.
57
59
  */
@@ -65,13 +67,21 @@ var versionMessage = function (packageRoot) {
65
67
  "Reinstall the CLI - 'npm i -g @sasjs/cli@latest'.");
66
68
  }
67
69
  var fromSources = !packageRoot.split(path_1.default.sep).includes('node_modules');
70
+ // the placeholder means "not stamped from a tag" - the same thing as absent
71
+ var stated = version && !/^0\.0\.0(-|$)/.test(version) ? version : undefined;
68
72
  if (fromSources) {
69
- return version
70
- ? "You are using a linked version of SASjs CLI (v".concat(version, ") running from sources at ").concat(packageRoot)
73
+ return stated
74
+ ? "You are using a linked version of SASjs CLI (v".concat(stated, ") running from sources at ").concat(packageRoot)
71
75
  : "You are using a linked version of SASjs CLI running from sources at ".concat(packageRoot);
72
76
  }
73
- if (!version) {
74
- throw new Error("The installed CLI at ".concat(packageRoot, " has no version in its package.json. ") +
77
+ if (!stated) {
78
+ // two ways to get here, and they mean different things to whoever is reading
79
+ // it: no version field at all, or the placeholder that was never stamped from
80
+ // a tag
81
+ var reason = version
82
+ ? "carries the placeholder version ".concat(version, ", so it was never stamped from a tag")
83
+ : 'has no version in its package.json';
84
+ throw new Error("The installed CLI at ".concat(packageRoot, " ").concat(reason, ". ") +
75
85
  "Reinstall it - 'npm i -g @sasjs/cli@latest'.");
76
86
  }
77
87
  return "You are using SASjs CLI v".concat(version);
@@ -20,5 +20,14 @@ declare module '@sasjs/utils/types/config' {
20
20
  * slash (`/demo`). Unset means the origin root.
21
21
  */
22
22
  mockWebBasePath?: string;
23
+ /**
24
+ * Whether the mock site carries the API console at `<base>/api/`.
25
+ *
26
+ * On unless it is set to false: the console is how a demonstration site lets
27
+ * a visitor try the API it is a mock of, and a page nothing links to costs
28
+ * the app nothing. A site whose output must be the app and nothing else
29
+ * turns it off.
30
+ */
31
+ mockApi?: boolean;
23
32
  }
24
33
  }
package/package.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "@sasjs/cli",
3
+ "version": "6.31.0",
3
4
  "description": "Command line interface for SASjs",
4
5
  "engines": {
5
6
  "node": "^22.14.0 || >=24.10.0"
@@ -9,43 +10,23 @@
9
10
  "build/**/*"
10
11
  ],
11
12
  "scripts": {
12
- "start:ci": "npm run build && npm run set:permissions",
13
- "start": "nodemon --watch \"src/**/*\" --exec \"npm run build && npm run set:permissions\"",
14
- "set:permissions": "node -e \"require('fs').chmodSync('build/index.js', '755')\"",
15
13
  "build": "npx rimraf build && tsc -p . && npm run copy:files",
16
- "copy:files": "copyfiles -u 1 ./src/config.json ./build/ && npm run copy:doxy && npm run copy:mock",
17
14
  "copy:doxy": "copyfiles -u 2 src/doxy/* build/doxy/",
15
+ "copy:files": "copyfiles -u 1 ./src/config.json ./build/ && npm run copy:doxy && npm run copy:mock",
18
16
  "copy:mock": "copyfiles -u 6 src/commands/build/internal/mockSite/assets/* build/commands/build/internal/mockSite/assets/",
17
+ "doc": "npx compodoc -p tsconfig.doc.json --coverageTest 16 --coverageTestThresholdFail",
18
+ "lint": "npx prettier --check \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"",
19
+ "lint:fix": "npx prettier --write \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"",
20
+ "prepublishOnly": "node -e \"const v=require('./package.json').version; if (/^0\\.0\\.0/.test(v)) { console.error('refusing to publish ' + v + ': the version is stamped from the tag (npm version <tag> --no-git-tag-version)'); process.exit(1) }\"",
21
+ "release": "sasjs-release",
22
+ "set:permissions": "node -e \"require('fs').chmodSync('build/index.js', '755')\"",
23
+ "start": "nodemon --watch \"src/**/*\" --exec \"npm run build && npm run set:permissions\"",
24
+ "start:ci": "npm run build && npm run set:permissions",
19
25
  "test": "npm run test:mocked && npm run test:server",
20
- "test:server": "jest --silent --runInBand --config=jest.server.config.js",
21
26
  "test:mocked": "jest --silent --runInBand --config=jest.config.js --coverage",
22
- "lint:fix": "npx prettier --write \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"",
23
- "lint": "npx prettier --check \"{src,test}/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"",
24
- "doc": "npx compodoc -p tsconfig.doc.json --coverageTest 16 --coverageTestThresholdFail"
27
+ "test:server": "jest --silent --runInBand --config=jest.server.config.js"
25
28
  },
26
29
  "testServerTypes": "sasjs",
27
- "release": {
28
- "branches": [
29
- "main"
30
- ],
31
- "plugins": [
32
- "@semantic-release/commit-analyzer",
33
- "@semantic-release/release-notes-generator",
34
- [
35
- "@semantic-release/npm",
36
- {
37
- "npmPublish": false
38
- }
39
- ],
40
- [
41
- "@semantic-release/exec",
42
- {
43
- "publishCmd": "npm publish --provenance --access public"
44
- }
45
- ],
46
- "@semantic-release/github"
47
- ]
48
- },
49
30
  "bin": {
50
31
  "sasjs": "build/index.js"
51
32
  },
@@ -97,6 +78,7 @@
97
78
  "@babel/preset-env": "7.29.7",
98
79
  "@babel/preset-typescript": "7.29.7",
99
80
  "@nogoo9/gitleaks": "8.30.1-post.2",
81
+ "@sasjs/release": "0.1.3",
100
82
  "@types/debug": "4.1.13",
101
83
  "@types/find": "0.2.4",
102
84
  "@types/jest": "30.0.0",
@@ -124,6 +106,5 @@
124
106
  "overrides": {
125
107
  "ws": "8.21.0",
126
108
  "nanoid": "3.3.18"
127
- },
128
- "version": "6.30.1"
109
+ }
129
110
  }