@sasjs/cli 6.4.5 → 6.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -67,13 +67,11 @@ var saveConfig_1 = require("./internal/saveConfig");
67
67
  * @param {boolean} insecure- boolean to use insecure connection, default is false. lf true the server will not reject any connection which is not authorized with the list of supplied CAs
68
68
  */
69
69
  var addCredential = function (target, insecure, targetScope) { return __awaiter(void 0, void 0, void 0, function () {
70
- var httpsAgentOptions, serverUrl, filePath_1, _a, _b, client, secret, _c, access_token, refresh_token, _d, userName, password, client, _e, access_token, refresh_token, filePath;
70
+ var serverUrl, filePath_1, requestTarget, _a, _b, client, secret, _c, access_token, refresh_token, _d, userName, password, client, _e, access_token, refresh_token, filePath;
71
71
  var _f, _g, _h;
72
72
  return __generator(this, function (_j) {
73
73
  switch (_j.label) {
74
74
  case 0:
75
- httpsAgentOptions = insecure
76
- ? __assign(__assign({}, target.httpsAgentOptions), { allowInsecureRequests: true, rejectUnauthorized: false }) : target.httpsAgentOptions;
77
75
  if (insecure)
78
76
  (_f = process.logger) === null || _f === void 0 ? void 0 : _f.warn('Executing with insecure connection.');
79
77
  if (!!target.serverUrl) return [3 /*break*/, 3];
@@ -87,6 +85,7 @@ var addCredential = function (target, insecure, targetScope) { return __awaiter(
87
85
  (_g = process.logger) === null || _g === void 0 ? void 0 : _g.info("Target configuration has been saved to ".concat(filePath_1, " ."));
88
86
  _j.label = 3;
89
87
  case 3:
88
+ requestTarget = (0, utils_1.targetWithInsecureHttps)(target, insecure);
90
89
  _a = target.serverType;
91
90
  switch (_a) {
92
91
  case types_1.ServerType.SasViya: return [3 /*break*/, 4];
@@ -97,7 +96,7 @@ var addCredential = function (target, insecure, targetScope) { return __awaiter(
97
96
  case 4: return [4 /*yield*/, (0, input_1.getCredentialsInputForViya)(target.name)];
98
97
  case 5:
99
98
  _b = _j.sent(), client = _b.client, secret = _b.secret;
100
- return [4 /*yield*/, (0, exports.getTokens)(target, client, secret).catch(function (err) {
99
+ return [4 /*yield*/, (0, exports.getTokens)(requestTarget, client, secret).catch(function (err) {
101
100
  throw err;
102
101
  })];
103
102
  case 6:
@@ -123,7 +122,7 @@ var addCredential = function (target, insecure, targetScope) { return __awaiter(
123
122
  target = new types_1.Target(__assign(__assign({}, target.toJson(false)), { authConfigSas9: { userName: userName, password: password } }));
124
123
  _j.label = 14;
125
124
  case 14: return [3 /*break*/, 23];
126
- case 15: return [4 /*yield*/, (0, utils_1.isSasJsServerInServerMode)(target)];
125
+ case 15: return [4 /*yield*/, (0, utils_1.isSasJsServerInServerMode)(requestTarget)];
127
126
  case 16:
128
127
  if (!(_j.sent())) {
129
128
  process.logger.info('No need to authenticate against the sasjs server running in desktop mode.');
@@ -132,7 +131,7 @@ var addCredential = function (target, insecure, targetScope) { return __awaiter(
132
131
  return [4 /*yield*/, (0, input_1.getCredentialsInputSasjs)(target)];
133
132
  case 17:
134
133
  client = (_j.sent()).client;
135
- return [4 /*yield*/, (0, exports.getTokens)(target, client, '')];
134
+ return [4 /*yield*/, (0, exports.getTokens)(requestTarget, client, '')];
136
135
  case 18:
137
136
  _e = _j.sent(), access_token = _e.access_token, refresh_token = _e.refresh_token;
138
137
  if (!(targetScope === targetScope_1.TargetScope.Local)) return [3 /*break*/, 20];
@@ -17,6 +17,13 @@ export declare function getAndValidateSasViyaFields(target: Target, scope: Targe
17
17
  export declare function getAndValidateSasjsFields(target: Target, scope: TargetScope, insecure: boolean, authenticateCallback: (target: Target, insecure: boolean, targetScope: TargetScope) => Promise<Target>): Promise<{
18
18
  target: Target;
19
19
  }>;
20
+ /**
21
+ * Lists the compute contexts a target can execute in.
22
+ *
23
+ * `insecure` is the user's `--insecure` choice, and it is carried by the
24
+ * request only: the target that is saved afterwards is the one passed in.
25
+ */
26
+ export declare function getComputeContexts(target: Target, scope: TargetScope, insecure: boolean): Promise<any[]>;
20
27
  export declare const getCredentialsInputForViya: (targetName: string) => Promise<{
21
28
  client: string;
22
29
  secret: string;
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -56,6 +45,7 @@ exports.getAndValidateServerUrl = getAndValidateServerUrl;
56
45
  exports.getAndValidateSas9Fields = getAndValidateSas9Fields;
57
46
  exports.getAndValidateSasViyaFields = getAndValidateSasViyaFields;
58
47
  exports.getAndValidateSasjsFields = getAndValidateSasjsFields;
48
+ exports.getComputeContexts = getComputeContexts;
59
49
  var input_1 = require("@sasjs/utils/input");
60
50
  var types_1 = require("@sasjs/utils/types");
61
51
  var utils_1 = require("@sasjs/utils");
@@ -256,45 +246,27 @@ var shouldAuthenticate = function () { return __awaiter(void 0, void 0, void 0,
256
246
  exports.shouldAuthenticate = shouldAuthenticate;
257
247
  function getAndValidateSasViyaFields(target, scope, serverUrl, insecure, authenticateCallback) {
258
248
  return __awaiter(this, void 0, void 0, function () {
259
- var contextName, httpsAgentOptions, sasjs, contexts, contextNumberErrorMessage, contextNumber;
249
+ var contextName, contexts, contextNumberErrorMessage, contextNumber;
260
250
  return __generator(this, function (_a) {
261
251
  switch (_a.label) {
262
252
  case 0:
263
253
  contextName = 'SAS Job Execution compute context';
264
254
  return [4 /*yield*/, (0, exports.shouldAuthenticate)()];
265
255
  case 1:
266
- if (!_a.sent()) return [3 /*break*/, 8];
256
+ if (!_a.sent()) return [3 /*break*/, 5];
267
257
  return [4 /*yield*/, authenticateCallback(target, insecure, scope)];
268
258
  case 2:
269
259
  target = _a.sent();
270
- httpsAgentOptions = insecure
271
- ? __assign(__assign({}, target.httpsAgentOptions), { allowInsecureRequests: true, rejectUnauthorized: false }) : target.httpsAgentOptions;
272
- sasjs = (0, utils_2.getSASjs)(target);
273
- contexts = [];
274
- if (!(scope === targetScope_1.TargetScope.Local)) return [3 /*break*/, 4];
275
- dotenv_1.default.config({
276
- path: path_1.default.join(process.projectDir, ".env.".concat(target.name))
277
- });
278
- return [4 /*yield*/, sasjs.getComputeContexts(process.env.ACCESS_TOKEN)];
260
+ return [4 /*yield*/, getComputeContexts(target, scope, insecure)];
279
261
  case 3:
280
262
  contexts = _a.sent();
281
- return [3 /*break*/, 6];
282
- case 4:
283
- if (!target.authConfig || !target.authConfig.access_token) {
284
- throw new Error("No access token available for target ".concat(target.name, ". Please run `sasjs add cred -t ").concat(target.name, "` to authenticate."));
285
- }
286
- return [4 /*yield*/, sasjs.getComputeContexts(target.authConfig.access_token)];
287
- case 5:
288
- contexts = _a.sent();
289
- _a.label = 6;
290
- case 6:
291
263
  contextNumberErrorMessage = "Context number must be between 1 and ".concat(contexts.length);
292
264
  return [4 /*yield*/, (0, input_1.getChoice)('Please pick your SAS Viya execution context: ', contextNumberErrorMessage, contexts.map(function (c, i) { return ({ title: c.name, value: i }); }))];
293
- case 7:
265
+ case 4:
294
266
  contextNumber = _a.sent();
295
267
  contextName = contexts[contextNumber].name;
296
268
  return [2 /*return*/, { contextName: contextName, target: target }];
297
- case 8: return [2 /*return*/, {
269
+ case 5: return [2 /*return*/, {
298
270
  contextName: contextName,
299
271
  target: target
300
272
  }];
@@ -318,6 +290,30 @@ function getAndValidateSasjsFields(target, scope, insecure, authenticateCallback
318
290
  });
319
291
  });
320
292
  }
293
+ /**
294
+ * Lists the compute contexts a target can execute in.
295
+ *
296
+ * `insecure` is the user's `--insecure` choice, and it is carried by the
297
+ * request only: the target that is saved afterwards is the one passed in.
298
+ */
299
+ function getComputeContexts(target, scope, insecure) {
300
+ return __awaiter(this, void 0, void 0, function () {
301
+ var sasjs;
302
+ return __generator(this, function (_a) {
303
+ sasjs = (0, utils_2.getSASjs)((0, utils_2.targetWithInsecureHttps)(target, insecure));
304
+ if (scope === targetScope_1.TargetScope.Local) {
305
+ dotenv_1.default.config({
306
+ path: path_1.default.join(process.projectDir, ".env.".concat(target.name))
307
+ });
308
+ return [2 /*return*/, sasjs.getComputeContexts(process.env.ACCESS_TOKEN)];
309
+ }
310
+ if (!target.authConfig || !target.authConfig.access_token) {
311
+ throw new Error("No access token available for target ".concat(target.name, ". Please run `sasjs add cred -t ").concat(target.name, "` to authenticate."));
312
+ }
313
+ return [2 /*return*/, sasjs.getComputeContexts(target.authConfig.access_token)];
314
+ });
315
+ });
316
+ }
321
317
  function getAndValidateAppLoc(targetName, target) {
322
318
  return __awaiter(this, void 0, void 0, function () {
323
319
  var errorMessage, appLoc;
@@ -68,6 +68,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
68
68
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
69
69
  }
70
70
  };
71
+ var __values = (this && this.__values) || function(o) {
72
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
73
+ if (m) return m.call(o);
74
+ if (o && typeof o.length === "number") return {
75
+ next: function () {
76
+ if (o && i >= o.length) o = void 0;
77
+ return { value: o && o[i++], done: !o };
78
+ }
79
+ };
80
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
81
+ };
71
82
  var __importDefault = (this && this.__importDefault) || function (mod) {
72
83
  return (mod && mod.__esModule) ? mod : { "default": mod };
73
84
  };
@@ -116,6 +127,96 @@ describe('addCredential', function () {
116
127
  });
117
128
  }); });
118
129
  });
130
+ describe('addCredential - insecure connections', function () {
131
+ var viyaTarget = function () {
132
+ return new utils_1.Target({
133
+ name: 'test-insecure',
134
+ serverUrl: 'https://sas.example.com',
135
+ serverType: utils_1.ServerType.SasViya,
136
+ appLoc: '/test',
137
+ contextName: utils_2.contextName
138
+ });
139
+ };
140
+ beforeEach(function () {
141
+ process.projectDir = '.';
142
+ setupMocks();
143
+ });
144
+ afterEach(function () { return __awaiter(void 0, void 0, void 0, function () {
145
+ return __generator(this, function (_a) {
146
+ switch (_a.label) {
147
+ case 0:
148
+ jest.restoreAllMocks();
149
+ return [4 /*yield*/, fileUtils.deleteFile(path_1.default.join('.', '.env.test-insecure'))];
150
+ case 1:
151
+ _a.sent();
152
+ return [2 /*return*/];
153
+ }
154
+ });
155
+ }); });
156
+ it('uses an insecure agent for the token request when insecure is true', function () { return __awaiter(void 0, void 0, void 0, function () {
157
+ var getSASjsSpy, requestTarget;
158
+ return __generator(this, function (_a) {
159
+ switch (_a.label) {
160
+ case 0:
161
+ getSASjsSpy = jest.spyOn(configUtils, 'getSASjs');
162
+ return [4 /*yield*/, (0, addCredential_1.addCredential)(viyaTarget(), true, types_1.TargetScope.Local)];
163
+ case 1:
164
+ _a.sent();
165
+ expect(getSASjsSpy).toHaveBeenCalled();
166
+ requestTarget = getSASjsSpy.mock.calls[0][0];
167
+ expect(requestTarget.httpsAgentOptions).toEqual(expect.objectContaining({
168
+ allowInsecureRequests: true,
169
+ rejectUnauthorized: false
170
+ }));
171
+ return [2 /*return*/];
172
+ }
173
+ });
174
+ }); });
175
+ it('does not write the insecure options to the saved target', function () { return __awaiter(void 0, void 0, void 0, function () {
176
+ var saveSpy, _a, _b, call;
177
+ var e_1, _c;
178
+ return __generator(this, function (_d) {
179
+ switch (_d.label) {
180
+ case 0:
181
+ jest.spyOn(configUtils, 'getSASjs');
182
+ return [4 /*yield*/, (0, addCredential_1.addCredential)(viyaTarget(), true, types_1.TargetScope.Local)];
183
+ case 1:
184
+ _d.sent();
185
+ saveSpy = configUtils.saveToLocalConfig;
186
+ expect(saveSpy).toHaveBeenCalled();
187
+ try {
188
+ for (_a = __values(saveSpy.mock.calls), _b = _a.next(); !_b.done; _b = _a.next()) {
189
+ call = _b.value;
190
+ expect(call[0].httpsAgentOptions).toBeUndefined();
191
+ }
192
+ }
193
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
194
+ finally {
195
+ try {
196
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
197
+ }
198
+ finally { if (e_1) throw e_1.error; }
199
+ }
200
+ return [2 /*return*/];
201
+ }
202
+ });
203
+ }); });
204
+ it('leaves the request target alone when insecure is false', function () { return __awaiter(void 0, void 0, void 0, function () {
205
+ var getSASjsSpy, requestTarget;
206
+ return __generator(this, function (_a) {
207
+ switch (_a.label) {
208
+ case 0:
209
+ getSASjsSpy = jest.spyOn(configUtils, 'getSASjs');
210
+ return [4 /*yield*/, (0, addCredential_1.addCredential)(viyaTarget(), false, types_1.TargetScope.Local)];
211
+ case 1:
212
+ _a.sent();
213
+ requestTarget = getSASjsSpy.mock.calls[0][0];
214
+ expect(requestTarget.httpsAgentOptions).toBeUndefined();
215
+ return [2 /*return*/];
216
+ }
217
+ });
218
+ }); });
219
+ });
119
220
  describe('validateTargetName', function () {
120
221
  it('should return the target name if valid', function () {
121
222
  var targetName = 'validTarget';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
47
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
48
+ return new (P || (P = Promise))(function (resolve, reject) {
49
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
50
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
51
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
52
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
53
+ });
54
+ };
55
+ var __generator = (this && this.__generator) || function (thisArg, body) {
56
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
57
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
58
+ function verb(n) { return function (v) { return step([n, v]); }; }
59
+ function step(op) {
60
+ if (f) throw new TypeError("Generator is already executing.");
61
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
62
+ 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;
63
+ if (y = 0, t) op = [op[0] & 2, t.value];
64
+ switch (op[0]) {
65
+ case 0: case 1: t = op; break;
66
+ case 4: _.label++; return { value: op[1], done: false };
67
+ case 5: _.label++; y = op[1]; op = [0]; continue;
68
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
69
+ default:
70
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
71
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
72
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
73
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
74
+ if (t[2]) _.ops.pop();
75
+ _.trys.pop(); continue;
76
+ }
77
+ op = body.call(thisArg, _);
78
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
79
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
80
+ }
81
+ };
82
+ Object.defineProperty(exports, "__esModule", { value: true });
83
+ var utils_1 = require("@sasjs/utils");
84
+ var targetScope_1 = require("../../../types/targetScope");
85
+ var configUtils = __importStar(require("../../../utils/config"));
86
+ var input_1 = require("../internal/input");
87
+ describe('getComputeContexts', function () {
88
+ var contexts = [{ name: 'SAS Job Execution compute context' }];
89
+ var target = new utils_1.Target({
90
+ name: 'test-target',
91
+ serverUrl: 'https://sas.example.com',
92
+ serverType: utils_1.ServerType.SasViya,
93
+ appLoc: '/Public/app',
94
+ authConfig: {
95
+ client: 'client',
96
+ secret: 'secret',
97
+ access_token: 't0k3n',
98
+ refresh_token: 'r3fr3sh'
99
+ }
100
+ });
101
+ var setup = function () {
102
+ var contextsSpy = jest.fn().mockResolvedValue(contexts);
103
+ var getSASjsSpy = jest
104
+ .spyOn(configUtils, 'getSASjs')
105
+ .mockReturnValue({ getComputeContexts: contextsSpy });
106
+ return { contextsSpy: contextsSpy, getSASjsSpy: getSASjsSpy };
107
+ };
108
+ afterEach(function () {
109
+ jest.restoreAllMocks();
110
+ });
111
+ it('sends the insecure options with the request when insecure is true', function () { return __awaiter(void 0, void 0, void 0, function () {
112
+ var _a, contextsSpy, getSASjsSpy, usedTarget;
113
+ return __generator(this, function (_b) {
114
+ switch (_b.label) {
115
+ case 0:
116
+ _a = setup(), contextsSpy = _a.contextsSpy, getSASjsSpy = _a.getSASjsSpy;
117
+ return [4 /*yield*/, expect((0, input_1.getComputeContexts)(target, targetScope_1.TargetScope.Global, true)).resolves.toEqual(contexts)];
118
+ case 1:
119
+ _b.sent();
120
+ usedTarget = getSASjsSpy.mock.calls[0][0];
121
+ expect(usedTarget.httpsAgentOptions).toEqual(expect.objectContaining({
122
+ allowInsecureRequests: true,
123
+ rejectUnauthorized: false
124
+ }));
125
+ expect(contextsSpy).toHaveBeenCalledWith('t0k3n');
126
+ return [2 /*return*/];
127
+ }
128
+ });
129
+ }); });
130
+ it('sends the target as it is when insecure is false', function () { return __awaiter(void 0, void 0, void 0, function () {
131
+ var getSASjsSpy;
132
+ return __generator(this, function (_a) {
133
+ switch (_a.label) {
134
+ case 0:
135
+ getSASjsSpy = setup().getSASjsSpy;
136
+ return [4 /*yield*/, (0, input_1.getComputeContexts)(target, targetScope_1.TargetScope.Global, false)];
137
+ case 1:
138
+ _a.sent();
139
+ expect(getSASjsSpy.mock.calls[0][0]).toBe(target);
140
+ expect(target.httpsAgentOptions).toBeUndefined();
141
+ return [2 /*return*/];
142
+ }
143
+ });
144
+ }); });
145
+ it('throws when a global target has no access token', function () { return __awaiter(void 0, void 0, void 0, function () {
146
+ var targetWithoutToken;
147
+ return __generator(this, function (_a) {
148
+ switch (_a.label) {
149
+ case 0:
150
+ setup();
151
+ targetWithoutToken = new utils_1.Target(__assign(__assign({}, target.toJson(false)), { authConfig: { client: 'client', secret: 'secret' } }));
152
+ return [4 /*yield*/, expect((0, input_1.getComputeContexts)(targetWithoutToken, targetScope_1.TargetScope.Global, false)).rejects.toThrow(/No access token available/)];
153
+ case 1:
154
+ _a.sent();
155
+ return [2 /*return*/];
156
+ }
157
+ });
158
+ }); });
159
+ });
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -197,10 +186,9 @@ var authLogin = function (target_1) {
197
186
  if (!target.serverUrl) {
198
187
  throw new Error("Target '".concat(target.name, "' does not have a serverUrl configured."));
199
188
  }
200
- if (insecure) {
201
- target = new utils_1.Target(__assign(__assign({}, target.toJson(false)), { httpsAgentOptions: __assign(__assign({}, target.httpsAgentOptions), { allowInsecureRequests: true, rejectUnauthorized: false }) }));
189
+ target = (0, utils_2.targetWithInsecureHttps)(target, insecure);
190
+ if (insecure)
202
191
  (_d = process.logger) === null || _d === void 0 ? void 0 : _d.warn('Executing with insecure connection.');
203
- }
204
192
  isTty = !!process.stdin.isTTY;
205
193
  envUser = process.env.SAS_USERNAME;
206
194
  envPass = process.env.SAS_PASSWORD;
@@ -353,7 +353,7 @@ function printHelpText() {
353
353
  { name: 'help', aliases: ['h'] },
354
354
  { name: 'request', aliases: ['rq'] },
355
355
  { name: 'run', aliases: ['r'] },
356
- { name: 'version', aliases: ['v'] },
356
+ { name: 'version', aliases: ['v', '-v', '--version'] },
357
357
  { name: 'web', aliases: ['w'] }
358
358
  ];
359
359
  outputCommands = "".concat(commands
@@ -35,17 +35,63 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
35
35
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
36
  }
37
37
  };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
38
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
+ var fs_1 = require("fs");
43
+ var os_1 = require("os");
44
+ var path_1 = __importDefault(require("path"));
39
45
  var version_1 = require("../version");
46
+ var writePackage = function (dir, version) {
47
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
48
+ (0, fs_1.writeFileSync)(path_1.default.join(dir, 'package.json'), JSON.stringify({ version: version }));
49
+ };
50
+ var tempRoot = function () { return (0, fs_1.mkdtempSync)(path_1.default.join((0, os_1.tmpdir)(), 'sasjs-version-')); };
51
+ var packageRoot = function () { return path_1.default.join(tempRoot(), 'node_modules', '@sasjs', 'cli'); };
40
52
  describe('printVersion', function () {
41
- it('should return sasjs version', function () { return __awaiter(void 0, void 0, void 0, function () {
53
+ it('reports the package that is running, with no global install involved', function () { return __awaiter(void 0, void 0, void 0, function () {
54
+ var message;
42
55
  return __generator(this, function (_a) {
43
56
  switch (_a.label) {
44
- case 0: return [4 /*yield*/, expect((0, version_1.printVersion)()).toResolve()];
57
+ case 0: return [4 /*yield*/, (0, version_1.printVersion)()];
45
58
  case 1:
46
- _a.sent();
59
+ message = _a.sent();
60
+ expect(message).toContain(path_1.default.resolve(__dirname, '../../../..'));
61
+ expect(message).toMatch(/^You are using (SASjs CLI v|a linked version)/);
47
62
  return [2 /*return*/];
48
63
  }
49
64
  });
50
65
  }); });
51
66
  });
67
+ describe('versionMessage', function () {
68
+ it('reports an installed version', function () {
69
+ var root = packageRoot();
70
+ writePackage(root, '6.4.6');
71
+ expect((0, version_1.versionMessage)(root)).toEqual('You are using SASjs CLI v6.4.6');
72
+ });
73
+ it('reports a source checkout as a linked version', function () {
74
+ var root = path_1.default.join(tempRoot(), 'cli');
75
+ writePackage(root, '6.4.7-alpha.1');
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
+ });
78
+ it('leaves the version out of a source checkout that has none', function () {
79
+ var root = path_1.default.join(tempRoot(), 'cli');
80
+ writePackage(root, undefined);
81
+ expect((0, version_1.versionMessage)(root)).toEqual("You are using a linked version of SASjs CLI running from sources at ".concat(root));
82
+ });
83
+ it('reports the whole version string, not a fragment of it', function () {
84
+ var root = packageRoot();
85
+ writePackage(root, '1.2.3-beta.4');
86
+ expect((0, version_1.versionMessage)(root)).toEqual('You are using SASjs CLI v1.2.3-beta.4');
87
+ });
88
+ it('throws an actionable error when the package.json is missing', function () {
89
+ var root = packageRoot();
90
+ expect(function () { return (0, version_1.versionMessage)(root); }).toThrow(/Unable to read the CLI version from/);
91
+ });
92
+ it('throws when an installed package carries no version', function () {
93
+ var root = packageRoot();
94
+ writePackage(root, undefined);
95
+ expect(function () { return (0, version_1.versionMessage)(root); }).toThrow(/has no version in its package.json/);
96
+ });
97
+ });
@@ -1 +1,14 @@
1
+ /**
2
+ * The message `sasjs version` prints for a given package root.
3
+ *
4
+ * Reads the version from the package.json of the package that is running, so
5
+ * it works for every install shape - global, project-local, `npx`, a temp
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.
10
+ *
11
+ * @param packageRoot - the folder holding the package.json of the running CLI.
12
+ */
13
+ export declare const versionMessage: (packageRoot: string) => string;
1
14
  export declare function printVersion(): Promise<string>;
@@ -35,22 +35,55 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
35
35
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
36
  }
37
37
  };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
38
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.versionMessage = void 0;
39
43
  exports.printVersion = printVersion;
40
- var shell_1 = require("../../utils/shell");
44
+ var fs_1 = require("fs");
45
+ var path_1 = __importDefault(require("path"));
46
+ /**
47
+ * The message `sasjs version` prints for a given package root.
48
+ *
49
+ * Reads the version from the package.json of the package that is running, so
50
+ * it works for every install shape - global, project-local, `npx`, a temp
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.
55
+ *
56
+ * @param packageRoot - the folder holding the package.json of the running CLI.
57
+ */
58
+ var versionMessage = function (packageRoot) {
59
+ var version;
60
+ try {
61
+ version = JSON.parse((0, fs_1.readFileSync)(path_1.default.join(packageRoot, 'package.json'), 'utf8')).version;
62
+ }
63
+ catch (err) {
64
+ throw new Error("Unable to read the CLI version from ".concat(packageRoot, ": ").concat(err, ". ") +
65
+ "Reinstall the CLI - 'npm i -g @sasjs/cli@latest'.");
66
+ }
67
+ var fromSources = !packageRoot.split(path_1.default.sep).includes('node_modules');
68
+ if (fromSources) {
69
+ return version
70
+ ? "You are using a linked version of SASjs CLI (v".concat(version, ") running from sources at ").concat(packageRoot)
71
+ : "You are using a linked version of SASjs CLI running from sources at ".concat(packageRoot);
72
+ }
73
+ if (!version) {
74
+ throw new Error("The installed CLI at ".concat(packageRoot, " has no version in its package.json. ") +
75
+ "Reinstall it - 'npm i -g @sasjs/cli@latest'.");
76
+ }
77
+ return "You are using SASjs CLI v".concat(version);
78
+ };
79
+ exports.versionMessage = versionMessage;
41
80
  function printVersion() {
42
81
  return __awaiter(this, void 0, void 0, function () {
43
- var stdout, line, version, message;
82
+ var packageRoot, message;
44
83
  var _a;
45
84
  return __generator(this, function (_b) {
46
- stdout = (0, shell_1.exec)("npm list -g @sasjs/cli", { silent: true }).stdout;
47
- line = stdout.split('\n').find(function (l) { return l.includes('@sasjs/cli'); }) || '';
48
- version = line.split('@')[2].trim();
49
- message = version.includes('->')
50
- ? "You are using a linked version of SASjs CLI running from sources at ".concat(version
51
- .replace('->', '')
52
- .trim())
53
- : "You are using SASjs CLI v".concat(version);
85
+ packageRoot = path_1.default.resolve(__dirname, '../../..');
86
+ message = (0, exports.versionMessage)(packageRoot);
54
87
  (_a = process.logger) === null || _a === void 0 ? void 0 : _a.info(message);
55
88
  return [2 /*return*/, message];
56
89
  });
@@ -12,7 +12,7 @@ exports.aliasMap = new Map([
12
12
  ['help', ['h']],
13
13
  ['request', ['rq']],
14
14
  ['run', ['r']],
15
- ['version', ['v']],
15
+ ['version', ['v', '-v', '--version']],
16
16
  ['web', ['w']]
17
17
  ]);
18
18
  var getAllSupportedAliases = function () { return exports.aliasMap.keys(); };
@@ -1,2 +1,8 @@
1
1
  import { CommandBase } from './commandBase';
2
+ /**
3
+ * Rewrites a version flag in the command position to the `version` command.
4
+ *
5
+ * @param args - the process arguments, as `[node, sasjs, ...]`.
6
+ */
7
+ export declare const normaliseArgs: (args: string[]) => string[];
2
8
  export declare const parse: (args: string[]) => CommandBase;
@@ -1,15 +1,57 @@
1
1
  "use strict";
2
+ var __read = (this && this.__read) || function (o, n) {
3
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
4
+ if (!m) return o;
5
+ var i = m.call(o), r, ar = [], e;
6
+ try {
7
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
8
+ }
9
+ catch (error) { e = { error: error }; }
10
+ finally {
11
+ try {
12
+ if (r && !r.done && (m = i["return"])) m.call(i);
13
+ }
14
+ finally { if (e) throw e.error; }
15
+ }
16
+ return ar;
17
+ };
18
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
20
+ if (ar || !(i in from)) {
21
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
22
+ ar[i] = from[i];
23
+ }
24
+ }
25
+ return to.concat(ar || Array.prototype.slice.call(from));
26
+ };
2
27
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parse = void 0;
28
+ exports.parse = exports.normaliseArgs = void 0;
4
29
  var getBaseCommand_1 = require("../../utils/getBaseCommand");
5
30
  var commandFactory_1 = require("./commandFactory");
31
+ // `sasjs version`, `sasjs v`, `sasjs -v` and `sasjs --version` all mean the
32
+ // same thing. yargs reads a leading `-v`/`--version` as an option rather than
33
+ // a command, and its own version handling is switched off, so the token is
34
+ // rewritten to the command name before dispatch.
35
+ var versionFlags = ['-v', '--version'];
36
+ /**
37
+ * Rewrites a version flag in the command position to the `version` command.
38
+ *
39
+ * @param args - the process arguments, as `[node, sasjs, ...]`.
40
+ */
41
+ var normaliseArgs = function (args) {
42
+ var _a = __read(args, 3), command = _a[2];
43
+ return versionFlags.includes(command)
44
+ ? __spreadArray(__spreadArray(__spreadArray([], __read(args.slice(0, 2)), false), ['version'], false), __read(args.slice(3)), false) : args;
45
+ };
46
+ exports.normaliseArgs = normaliseArgs;
6
47
  var parse = function (args) {
7
48
  var _a;
8
- var baseCommand = (0, getBaseCommand_1.getBaseCommand)(args);
49
+ var commandArgs = (0, exports.normaliseArgs)(args);
50
+ var baseCommand = (0, getBaseCommand_1.getBaseCommand)(commandArgs);
9
51
  if (!Array.from(commandFactory_1.commandFactory.keys()).includes(baseCommand.name)) {
10
52
  (_a = process.logger) === null || _a === void 0 ? void 0 : _a.error('Invalid SASjs command! Run `sasjs help` for a full list of available commands.');
11
53
  process.exit(1);
12
54
  }
13
- return commandFactory_1.commandFactory.get(baseCommand.name)(args);
55
+ return commandFactory_1.commandFactory.get(baseCommand.name)(commandArgs);
14
56
  };
15
57
  exports.parse = parse;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var versionCommand_1 = require("../../../commands/version/versionCommand");
4
+ var parse_1 = require("../parse");
5
+ describe('parse', function () {
6
+ it.each(['version', 'v', '-v', '--version'])('resolves `sasjs %s` to the version command', function (token) {
7
+ var command = (0, parse_1.parse)(['node', 'sasjs', token]);
8
+ expect(command).toBeInstanceOf(versionCommand_1.VersionCommand);
9
+ expect(command.name).toEqual('version');
10
+ });
11
+ it('leaves another command as it is', function () {
12
+ var command = (0, parse_1.parse)(['node', 'sasjs', 'help']);
13
+ expect(command.name).toEqual('help');
14
+ });
15
+ });
16
+ describe('normaliseArgs', function () {
17
+ it.each(['-v', '--version'])('rewrites %s in the command position', function (flag) {
18
+ expect((0, parse_1.normaliseArgs)(['node', 'sasjs', flag])).toEqual([
19
+ 'node',
20
+ 'sasjs',
21
+ 'version'
22
+ ]);
23
+ });
24
+ it('keeps the arguments that follow the flag', function () {
25
+ expect((0, parse_1.normaliseArgs)(['node', 'sasjs', '--version', 'extra'])).toEqual([
26
+ 'node',
27
+ 'sasjs',
28
+ 'version',
29
+ 'extra'
30
+ ]);
31
+ });
32
+ it('does not rewrite a flag that is not in the command position', function () {
33
+ var args = ['node', 'sasjs', 'run', 'program.sas', '-v'];
34
+ expect((0, parse_1.normaliseArgs)(args)).toEqual(args);
35
+ });
36
+ it('leaves the command name alone', function () {
37
+ var args = ['node', 'sasjs', 'version'];
38
+ expect((0, parse_1.normaliseArgs)(args)).toEqual(args);
39
+ });
40
+ });
@@ -6,5 +6,6 @@ export * from './loadEnvVariables';
6
6
  export * from './saveLog';
7
7
  export * from './setConstants';
8
8
  export * from './setProjectDir';
9
+ export * from './target';
9
10
  export * from './utils';
10
11
  export * from './validateTargetName';
@@ -22,5 +22,6 @@ __exportStar(require("./loadEnvVariables"), exports);
22
22
  __exportStar(require("./saveLog"), exports);
23
23
  __exportStar(require("./setConstants"), exports);
24
24
  __exportStar(require("./setProjectDir"), exports);
25
+ __exportStar(require("./target"), exports);
25
26
  __exportStar(require("./utils"), exports);
26
27
  __exportStar(require("./validateTargetName"), exports);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ var utils_1 = require("@sasjs/utils");
15
+ var target_1 = require("../target");
16
+ describe('targetWithInsecureHttps', function () {
17
+ var target = new utils_1.Target({
18
+ name: 'test-target',
19
+ serverUrl: 'https://sas.example.com',
20
+ serverType: utils_1.ServerType.SasViya,
21
+ appLoc: '/Public/app'
22
+ });
23
+ it('returns the target itself when insecure is false', function () {
24
+ expect((0, target_1.targetWithInsecureHttps)(target, false)).toBe(target);
25
+ });
26
+ it('returns a copy that accepts unverifiable certificates when insecure is true', function () {
27
+ var insecureTarget = (0, target_1.targetWithInsecureHttps)(target, true);
28
+ expect(insecureTarget).not.toBe(target);
29
+ expect(insecureTarget.serverUrl).toEqual(target.serverUrl);
30
+ expect(insecureTarget.appLoc).toEqual(target.appLoc);
31
+ expect(insecureTarget.httpsAgentOptions).toEqual(expect.objectContaining({
32
+ allowInsecureRequests: true,
33
+ rejectUnauthorized: false
34
+ }));
35
+ });
36
+ it('leaves the original target unchanged', function () {
37
+ (0, target_1.targetWithInsecureHttps)(target, true);
38
+ expect(target.httpsAgentOptions).toBeUndefined();
39
+ });
40
+ it('keeps the httpsAgentOptions the target already carries', function () {
41
+ var withCaPath = new utils_1.Target(__assign(__assign({}, target.toJson(false)), { httpsAgentOptions: { caPath: '/etc/ssl/private/intermediate.pem' } }));
42
+ var insecureTarget = (0, target_1.targetWithInsecureHttps)(withCaPath, true);
43
+ expect(insecureTarget.httpsAgentOptions).toEqual(expect.objectContaining({
44
+ caPath: '/etc/ssl/private/intermediate.pem',
45
+ allowInsecureRequests: true,
46
+ rejectUnauthorized: false
47
+ }));
48
+ expect(withCaPath.httpsAgentOptions).toEqual(expect.not.objectContaining({ allowInsecureRequests: true }));
49
+ });
50
+ });
@@ -0,0 +1,15 @@
1
+ import { Target } from '@sasjs/utils/types';
2
+ /**
3
+ * The target to make requests with, given the user's `--insecure` choice.
4
+ *
5
+ * Returns the target itself when `insecure` is false, and a copy whose
6
+ * `httpsAgentOptions` accept certificates that cannot be verified otherwise
7
+ * when it is true - a self-signed certificate, or a chain with the
8
+ * intermediate missing.
9
+ *
10
+ * The copy is deliberate: `--insecure` is a property of the invocation, not of
11
+ * the target, so the settings must not reach the configuration that is saved
12
+ * afterwards. Callers keep the original target for persistence and pass this
13
+ * one to `getSASjs` and to anything else that opens a connection.
14
+ */
15
+ export declare const targetWithInsecureHttps: (target: Target, insecure: boolean) => Target;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.targetWithInsecureHttps = void 0;
15
+ var types_1 = require("@sasjs/utils/types");
16
+ /**
17
+ * The target to make requests with, given the user's `--insecure` choice.
18
+ *
19
+ * Returns the target itself when `insecure` is false, and a copy whose
20
+ * `httpsAgentOptions` accept certificates that cannot be verified otherwise
21
+ * when it is true - a self-signed certificate, or a chain with the
22
+ * intermediate missing.
23
+ *
24
+ * The copy is deliberate: `--insecure` is a property of the invocation, not of
25
+ * the target, so the settings must not reach the configuration that is saved
26
+ * afterwards. Callers keep the original target for persistence and pass this
27
+ * one to `getSASjs` and to anything else that opens a connection.
28
+ */
29
+ var targetWithInsecureHttps = function (target, insecure) {
30
+ return insecure
31
+ ? new types_1.Target(__assign(__assign({}, target.toJson(false)), { httpsAgentOptions: __assign(__assign({}, target.httpsAgentOptions), { allowInsecureRequests: true, rejectUnauthorized: false }) }))
32
+ : target;
33
+ };
34
+ exports.targetWithInsecureHttps = targetWithInsecureHttps;
package/package.json CHANGED
@@ -123,5 +123,5 @@
123
123
  "ws": "8.21.0",
124
124
  "nanoid": "3.3.18"
125
125
  },
126
- "version": "6.4.5"
126
+ "version": "6.4.7"
127
127
  }