@sasjs/cli 4.5.1 → 4.7.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.
@@ -358,7 +358,6 @@ var setupMocks = function () {
358
358
  jest
359
359
  .spyOn(configUtils, 'findTargetInConfiguration')
360
360
  .mockImplementation(function () { return Promise.resolve({ target: target, isLocal: true }); });
361
- jest.spyOn(process.logger, 'error');
362
361
  jest
363
362
  .spyOn(configUtils, 'getLocalConfig')
364
363
  .mockImplementation(function () { return Promise.resolve(config); });
@@ -322,6 +322,17 @@ function printHelpText() {
322
322
  "[2spaces]NOTE: Providing outDirectory flag is optional. If not present, CLI will use save outputs into sasjsresults folder.",
323
323
  "[2spaces]NOTE: Providing force (--force or -f) flag is optional. If present, CLI will force command to finish running all tests and will not return an error code even when some are failing. Useful when the requirement is not to make CI Pipeline fail."
324
324
  ]
325
+ },
326
+ {
327
+ name: 'snippets',
328
+ title: 'snippets',
329
+ description: [
330
+ "Generates VS Code snippets from the Doxygen headers in the SAS Macros.",
331
+ "[2spaces]command example: sasjs snippets --outDirectory <folderPath> --target <targetName>",
332
+ "",
333
+ "[2spaces]NOTE: Providing <folderPath> is optional. If not present, generated snippets will be saved to 'sasjsresults/sasjs-macro-snippets.json' file.",
334
+ "[2spaces]NOTE: more information can be found here https://cli.sasjs.io/snippets/."
335
+ ]
325
336
  }
326
337
  ];
327
338
  aliases = [
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Generates VS Code snippets from the Doxygen headers in the SAS Macros.
3
+ * @param macroFolders an array of file paths of SAS Macros.
4
+ * @param outDirectory a folder path where generated snippets should be put into. If ends with '<file name>.json' then provided file name will be used, otherwise default file name ('sasjs-macro-snippets.json') will be used.
5
+ * @returns a promise that resolves into a file path with generated VS Code snippets.
6
+ */
7
+ export declare function generateSnippets(macroFolders: string[], outDirectory?: string): Promise<string>;
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ 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;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __read = (this && this.__read) || function (o, n) {
39
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
40
+ if (!m) return o;
41
+ var i = m.call(o), r, ar = [], e;
42
+ try {
43
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
44
+ }
45
+ catch (error) { e = { error: error }; }
46
+ finally {
47
+ try {
48
+ if (r && !r.done && (m = i["return"])) m.call(i);
49
+ }
50
+ finally { if (e) throw e.error; }
51
+ }
52
+ return ar;
53
+ };
54
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
55
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
56
+ if (ar || !(i in from)) {
57
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
58
+ ar[i] = from[i];
59
+ }
60
+ }
61
+ return to.concat(ar || Array.prototype.slice.call(from));
62
+ };
63
+ var __importDefault = (this && this.__importDefault) || function (mod) {
64
+ return (mod && mod.__esModule) ? mod : { "default": mod };
65
+ };
66
+ Object.defineProperty(exports, "__esModule", { value: true });
67
+ exports.generateSnippets = void 0;
68
+ var utils_1 = require("@sasjs/utils");
69
+ var path_1 = __importDefault(require("path"));
70
+ var sasRegExp = /\.sas$/; // to check if file has .sas extension
71
+ var briefRegExp = /^\s\s@brief\s/; // to get lines that has @brief keyword
72
+ var paramRegExp = /^\s\s@param\s/; // to get lines that has @param keyword
73
+ /**
74
+ * Generates VS Code snippets from the Doxygen headers in the SAS Macros.
75
+ * @param macroFolders an array of file paths of SAS Macros.
76
+ * @param outDirectory a folder path where generated snippets should be put into. If ends with '<file name>.json' then provided file name will be used, otherwise default file name ('sasjs-macro-snippets.json') will be used.
77
+ * @returns a promise that resolves into a file path with generated VS Code snippets.
78
+ */
79
+ function generateSnippets(macroFolders, outDirectory) {
80
+ return __awaiter(this, void 0, void 0, function () {
81
+ var snippets, defaultOutputFileName, buildDestinationResultsFolder, snippetsFilePath;
82
+ var _this = this;
83
+ return __generator(this, function (_a) {
84
+ switch (_a.label) {
85
+ case 0:
86
+ snippets = {};
87
+ // return an error if no macro folders has been provided
88
+ if (!macroFolders.length) {
89
+ return [2 /*return*/, Promise.reject("\"macroFolders\" array was not found in sasjs/sasjsconfig.json.")];
90
+ }
91
+ // generate snippets from all .sas file in macro folders
92
+ return [4 /*yield*/, (0, utils_1.asyncForEach)(macroFolders, function (folder) { return __awaiter(_this, void 0, void 0, function () {
93
+ var sasFiles;
94
+ var _this = this;
95
+ return __generator(this, function (_a) {
96
+ switch (_a.label) {
97
+ case 0: return [4 /*yield*/, (0, utils_1.listSasFilesInFolder)(folder, true)];
98
+ case 1:
99
+ sasFiles = (_a.sent())
100
+ .map(function (file) { return path_1.default.join(folder, file); })
101
+ .filter(function (file) { return !(0, utils_1.isTestFile)(file); });
102
+ return [4 /*yield*/, (0, utils_1.asyncForEach)(sasFiles, function (file) { return __awaiter(_this, void 0, void 0, function () {
103
+ var macro, _a, _b;
104
+ return __generator(this, function (_c) {
105
+ switch (_c.label) {
106
+ case 0:
107
+ macro = file.split(path_1.default.sep).pop().replace(sasRegExp, '');
108
+ // put generated snippet into snippets object
109
+ _a = snippets;
110
+ _b = macro;
111
+ return [4 /*yield*/, createSnippetFromMacro(file)];
112
+ case 1:
113
+ // put generated snippet into snippets object
114
+ _a[_b] = _c.sent();
115
+ return [2 /*return*/];
116
+ }
117
+ });
118
+ }); })];
119
+ case 2:
120
+ _a.sent();
121
+ return [2 /*return*/];
122
+ }
123
+ });
124
+ }); })
125
+ // return an error if no snippets has been generated
126
+ ];
127
+ case 1:
128
+ // generate snippets from all .sas file in macro folders
129
+ _a.sent();
130
+ // return an error if no snippets has been generated
131
+ if (!Object.keys(snippets).length) {
132
+ return [2 /*return*/, Promise.reject('No VS Code snippets has been found.')];
133
+ }
134
+ defaultOutputFileName = 'sasjs-macro-snippets.json';
135
+ buildDestinationResultsFolder = process.sasjsConstants.buildDestinationResultsFolder;
136
+ snippetsFilePath = path_1.default.join(outDirectory ? process.projectDir : buildDestinationResultsFolder, outDirectory
137
+ ? /\.json$/.test(outDirectory)
138
+ ? outDirectory
139
+ : path_1.default.join(outDirectory, defaultOutputFileName)
140
+ : defaultOutputFileName);
141
+ // create file with generated VS Code snippets
142
+ return [4 /*yield*/, (0, utils_1.createFile)(snippetsFilePath, JSON.stringify(snippets, null, 2))
143
+ // return file path with generated VS Code snippets
144
+ ];
145
+ case 2:
146
+ // create file with generated VS Code snippets
147
+ _a.sent();
148
+ // return file path with generated VS Code snippets
149
+ return [2 /*return*/, Promise.resolve(snippetsFilePath)];
150
+ }
151
+ });
152
+ });
153
+ }
154
+ exports.generateSnippets = generateSnippets;
155
+ /**
156
+ * Creates a VS Code snippet from SAS macro.
157
+ * @param file file path of SAS macro.
158
+ * @returns promise that resolves with VS Code snippet.
159
+ */
160
+ var createSnippetFromMacro = function (file) { return __awaiter(void 0, void 0, void 0, function () {
161
+ var fileContent, lineEnding, lines, brief, params, macro, description;
162
+ return __generator(this, function (_a) {
163
+ switch (_a.label) {
164
+ case 0: return [4 /*yield*/, (0, utils_1.readFile)(file)];
165
+ case 1:
166
+ fileContent = _a.sent();
167
+ lineEnding = (0, utils_1.getLineEnding)(fileContent) // LF or CRLF
168
+ ;
169
+ lines = fileContent.split(lineEnding);
170
+ brief = lines.filter(function (line) { return briefRegExp.test(line); });
171
+ params = lines.filter(function (line) { return paramRegExp.test(line); });
172
+ macro = file.split(path_1.default.sep).pop().replace(sasRegExp, '') // macro name
173
+ ;
174
+ // if brief present, remove @brief keyword
175
+ if (brief.length)
176
+ brief = [brief[0].replace(briefRegExp, '')];
177
+ // if params present, add a line break before list of params and a prefix to each param
178
+ if (params.length) {
179
+ brief.push('\r');
180
+ params = params.map(function (param) { return param.replace(paramRegExp, '-'); });
181
+ }
182
+ description = __spreadArray(__spreadArray(__spreadArray([], __read(brief), false), [
183
+ params.length ? "Params:" : ''
184
+ ], false), __read(params), false).filter(function (line) { return line; });
185
+ return [2 /*return*/, {
186
+ prefix: "%".concat(macro),
187
+ body: "%".concat(macro, "($1)"),
188
+ description: description
189
+ }];
190
+ }
191
+ });
192
+ }); };
@@ -0,0 +1,13 @@
1
+ import { ReturnCode } from '../../types/command';
2
+ import { TargetCommand } from '../../types/command/targetCommand';
3
+ /**
4
+ * 'snippets' command class.
5
+ */
6
+ export declare class SnippetsCommand extends TargetCommand {
7
+ constructor(args: string[]);
8
+ /**
9
+ * Command execution method.
10
+ * @returns promise that results into return code.
11
+ */
12
+ execute(): Promise<ReturnCode>;
13
+ }
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
+ return new (P || (P = Promise))(function (resolve, reject) {
20
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
24
+ });
25
+ };
26
+ var __generator = (this && this.__generator) || function (thisArg, body) {
27
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
28
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29
+ function verb(n) { return function (v) { return step([n, v]); }; }
30
+ function step(op) {
31
+ if (f) throw new TypeError("Generator is already executing.");
32
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
33
+ 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;
34
+ if (y = 0, t) op = [op[0] & 2, t.value];
35
+ switch (op[0]) {
36
+ case 0: case 1: t = op; break;
37
+ case 4: _.label++; return { value: op[1], done: false };
38
+ case 5: _.label++; y = op[1]; op = [0]; continue;
39
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
40
+ default:
41
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45
+ if (t[2]) _.ops.pop();
46
+ _.trys.pop(); continue;
47
+ }
48
+ op = body.call(thisArg, _);
49
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
+ }
52
+ };
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.SnippetsCommand = void 0;
55
+ var snippets_1 = require("./snippets");
56
+ var command_1 = require("../../types/command");
57
+ var targetCommand_1 = require("../../types/command/targetCommand");
58
+ var utils_1 = require("../../utils");
59
+ var syntax = 'snippets';
60
+ var usage = 'sasjs snippets';
61
+ var description = "Generates VS Code snippets from the Doxygen headers in the SAS Macros.";
62
+ var examples = [
63
+ {
64
+ command: 'sasjs snippets',
65
+ description: description
66
+ }
67
+ ];
68
+ var parseOptions = {
69
+ outDirectory: {
70
+ type: 'string',
71
+ alias: 'o',
72
+ description: 'Path to the directory where the VS Code snippets output will be generated.'
73
+ }
74
+ };
75
+ /**
76
+ * 'snippets' command class.
77
+ */
78
+ var SnippetsCommand = /** @class */ (function (_super) {
79
+ __extends(SnippetsCommand, _super);
80
+ function SnippetsCommand(args) {
81
+ return _super.call(this, args, { syntax: syntax, usage: usage, description: description, examples: examples, parseOptions: parseOptions }) || this;
82
+ }
83
+ /**
84
+ * Command execution method.
85
+ * @returns promise that results into return code.
86
+ */
87
+ SnippetsCommand.prototype.execute = function () {
88
+ return __awaiter(this, void 0, void 0, function () {
89
+ var target, macroFolders, outDirectory;
90
+ return __generator(this, function (_a) {
91
+ switch (_a.label) {
92
+ case 0: return [4 /*yield*/, this.getTargetInfo()];
93
+ case 1:
94
+ target = (_a.sent()).target;
95
+ return [4 /*yield*/, (0, utils_1.getMacroFolders)(target)];
96
+ case 2:
97
+ macroFolders = _a.sent();
98
+ outDirectory = this.parsed.outDirectory;
99
+ return [4 /*yield*/, (0, snippets_1.generateSnippets)(macroFolders, outDirectory)
100
+ .then(function (filePath) {
101
+ var _a, _b;
102
+ // handle command execution success
103
+ (_a = process.logger) === null || _a === void 0 ? void 0 : _a.success("VS Code snippets generated! File location: ".concat(filePath));
104
+ (_b = process.logger) === null || _b === void 0 ? void 0 : _b.info("Follow these instructions https://cli.sasjs.io/snippets/#import-snippets-to-vs-code to import generated VS Code snippets into your VS Code.");
105
+ return command_1.ReturnCode.Success;
106
+ })
107
+ .catch(function (err) {
108
+ var _a;
109
+ // handle command execution failure
110
+ (_a = process.logger) === null || _a === void 0 ? void 0 : _a.error('Error generating VS Code snippets: ', err);
111
+ return command_1.ReturnCode.InternalError;
112
+ })];
113
+ case 3:
114
+ // Generate snippets
115
+ return [2 /*return*/, _a.sent()];
116
+ }
117
+ });
118
+ });
119
+ };
120
+ return SnippetsCommand;
121
+ }(targetCommand_1.TargetCommand));
122
+ exports.SnippetsCommand = SnippetsCommand;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ 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;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ var snippets_1 = require("../snippets");
43
+ var utils_1 = require("@sasjs/utils");
44
+ var path_1 = __importDefault(require("path"));
45
+ var utils_2 = require("../../../utils");
46
+ describe('sasjs snippets', function () {
47
+ var testMacroFolder1 = 'testMacros';
48
+ var testMacroFolder2 = 'testMacros2';
49
+ var emptyMacroFolder = 'empty';
50
+ var customOutputFilePath = 'snippets.json';
51
+ var defaultFileName = 'sasjs-macro-snippets.json';
52
+ var defaultOutputFilePath = path_1.default.join(__dirname, 'sasjsresults', defaultFileName);
53
+ var customOutputFolder = 'snippets';
54
+ var customOutputFolderWithDefaultFileName = path_1.default.join(__dirname, customOutputFolder, defaultFileName);
55
+ var buildDestinationResultsFolder = path_1.default.join(__dirname, 'sasjsresults');
56
+ beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
57
+ return __generator(this, function (_a) {
58
+ switch (_a.label) {
59
+ case 0: return [4 /*yield*/, (0, utils_2.setConstants)(false)];
60
+ case 1:
61
+ _a.sent();
62
+ process.projectDir = __dirname;
63
+ process.sasjsConstants.buildDestinationResultsFolder =
64
+ buildDestinationResultsFolder;
65
+ process.sasjsConstants.buildSourceFolder = __dirname;
66
+ return [2 /*return*/];
67
+ }
68
+ });
69
+ }); });
70
+ afterAll(function () { return __awaiter(void 0, void 0, void 0, function () {
71
+ return __generator(this, function (_a) {
72
+ switch (_a.label) {
73
+ case 0: return [4 /*yield*/, (0, utils_1.deleteFolder)(path_1.default.join(__dirname, customOutputFolder))];
74
+ case 1:
75
+ _a.sent();
76
+ return [4 /*yield*/, (0, utils_1.deleteFile)(path_1.default.join(__dirname, customOutputFilePath))];
77
+ case 2:
78
+ _a.sent();
79
+ return [4 /*yield*/, (0, utils_1.deleteFolder)(buildDestinationResultsFolder)];
80
+ case 3:
81
+ _a.sent();
82
+ return [2 /*return*/];
83
+ }
84
+ });
85
+ }); });
86
+ it('should generate snippets', function () { return __awaiter(void 0, void 0, void 0, function () {
87
+ var target, config, macroFolders, outputFilePath, expectedSnippets, generatedSnippets, _a, _b;
88
+ return __generator(this, function (_c) {
89
+ switch (_c.label) {
90
+ case 0:
91
+ target = new utils_1.Target({
92
+ name: 'test',
93
+ appLoc: '/Public/test/',
94
+ serverType: utils_1.ServerType.SasViya,
95
+ macroFolders: [testMacroFolder1]
96
+ });
97
+ config = {
98
+ macroFolders: [testMacroFolder2],
99
+ targets: [target]
100
+ };
101
+ process.sasjsConfig = config;
102
+ return [4 /*yield*/, (0, utils_2.getMacroFolders)(target)];
103
+ case 1:
104
+ macroFolders = _c.sent();
105
+ return [4 /*yield*/, (0, snippets_1.generateSnippets)(macroFolders, customOutputFilePath)];
106
+ case 2:
107
+ _c.sent();
108
+ outputFilePath = path_1.default.join(__dirname, customOutputFilePath);
109
+ return [4 /*yield*/, expect((0, utils_1.fileExists)(outputFilePath)).resolves.toEqual(true)];
110
+ case 3:
111
+ _c.sent();
112
+ expectedSnippets = {
113
+ macro2: {
114
+ prefix: '%macro2',
115
+ body: '%macro2($1)',
116
+ description: [
117
+ 'Macro 2',
118
+ '\r',
119
+ 'Params:',
120
+ '-msg The message to be printed'
121
+ ]
122
+ },
123
+ badMacro: {
124
+ prefix: '%badMacro',
125
+ body: '%badMacro($1)',
126
+ description: []
127
+ },
128
+ example: {
129
+ prefix: '%example',
130
+ body: '%example($1)',
131
+ description: [
132
+ 'An example macro',
133
+ '\r',
134
+ 'Params:',
135
+ '-msg The message to be printed'
136
+ ]
137
+ },
138
+ subMacro: {
139
+ prefix: '%subMacro',
140
+ body: '%subMacro($1)',
141
+ description: [
142
+ 'A sub macro',
143
+ '\r',
144
+ 'Params:',
145
+ '-msg The message to be printed'
146
+ ]
147
+ },
148
+ subSubMacro: {
149
+ prefix: '%subSubMacro',
150
+ body: '%subSubMacro($1)',
151
+ description: [
152
+ 'A sub sub macro',
153
+ '\r',
154
+ 'Params:',
155
+ '-msg The message to be printed'
156
+ ]
157
+ }
158
+ };
159
+ _b = (_a = JSON).parse;
160
+ return [4 /*yield*/, (0, utils_1.readFile)(outputFilePath)];
161
+ case 4:
162
+ generatedSnippets = _b.apply(_a, [_c.sent()]);
163
+ expect(generatedSnippets).toEqual(expectedSnippets);
164
+ return [2 /*return*/];
165
+ }
166
+ });
167
+ }); });
168
+ it('should generate snippets with default file name', function () { return __awaiter(void 0, void 0, void 0, function () {
169
+ var targetWithoutMacroFolders, config, macroFolders;
170
+ return __generator(this, function (_a) {
171
+ switch (_a.label) {
172
+ case 0:
173
+ targetWithoutMacroFolders = new utils_1.Target({
174
+ name: 'test',
175
+ appLoc: '/Public/test/',
176
+ serverType: utils_1.ServerType.SasViya
177
+ });
178
+ config = {
179
+ macroFolders: [testMacroFolder2],
180
+ targets: [targetWithoutMacroFolders]
181
+ };
182
+ process.sasjsConfig = config;
183
+ return [4 /*yield*/, (0, utils_2.getMacroFolders)(targetWithoutMacroFolders)];
184
+ case 1:
185
+ macroFolders = _a.sent();
186
+ return [4 /*yield*/, (0, snippets_1.generateSnippets)(macroFolders)];
187
+ case 2:
188
+ _a.sent();
189
+ return [4 /*yield*/, expect((0, utils_1.fileExists)(defaultOutputFilePath)).resolves.toEqual(true)];
190
+ case 3:
191
+ _a.sent();
192
+ return [2 /*return*/];
193
+ }
194
+ });
195
+ }); });
196
+ it('should generate snippets with custom folder and default file name', function () { return __awaiter(void 0, void 0, void 0, function () {
197
+ var config, macroFolders;
198
+ return __generator(this, function (_a) {
199
+ switch (_a.label) {
200
+ case 0:
201
+ config = { macroFolders: [testMacroFolder2] };
202
+ process.sasjsConfig = config;
203
+ return [4 /*yield*/, (0, utils_2.getMacroFolders)()];
204
+ case 1:
205
+ macroFolders = _a.sent();
206
+ return [4 /*yield*/, (0, snippets_1.generateSnippets)(macroFolders, customOutputFolder)];
207
+ case 2:
208
+ _a.sent();
209
+ return [4 /*yield*/, expect((0, utils_1.fileExists)(customOutputFolderWithDefaultFileName)).resolves.toEqual(true)];
210
+ case 3:
211
+ _a.sent();
212
+ return [2 /*return*/];
213
+ }
214
+ });
215
+ }); });
216
+ it('should return an error if macroFolders array was not provided', function () { return __awaiter(void 0, void 0, void 0, function () {
217
+ var config, macroFolders;
218
+ return __generator(this, function (_a) {
219
+ switch (_a.label) {
220
+ case 0:
221
+ config = {};
222
+ process.sasjsConfig = config;
223
+ return [4 /*yield*/, (0, utils_2.getMacroFolders)()];
224
+ case 1:
225
+ macroFolders = _a.sent();
226
+ return [4 /*yield*/, expect((0, snippets_1.generateSnippets)(macroFolders)).rejects.toEqual('"macroFolders" array was not found in sasjs/sasjsconfig.json.')];
227
+ case 2:
228
+ _a.sent();
229
+ return [2 /*return*/];
230
+ }
231
+ });
232
+ }); });
233
+ it('should return an error if macros were not found', function () { return __awaiter(void 0, void 0, void 0, function () {
234
+ var config, macroFolders;
235
+ return __generator(this, function (_a) {
236
+ switch (_a.label) {
237
+ case 0:
238
+ config = { macroFolders: [emptyMacroFolder] };
239
+ process.sasjsConfig = config;
240
+ return [4 /*yield*/, (0, utils_2.getMacroFolders)()];
241
+ case 1:
242
+ macroFolders = _a.sent();
243
+ return [4 /*yield*/, expect((0, snippets_1.generateSnippets)(macroFolders)).rejects.toEqual('No VS Code snippets has been found.')];
244
+ case 2:
245
+ _a.sent();
246
+ return [2 /*return*/];
247
+ }
248
+ });
249
+ }); });
250
+ });
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __generator = (this && this.__generator) || function (thisArg, body) {
35
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
36
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
37
+ function verb(n) { return function (v) { return step([n, v]); }; }
38
+ function step(op) {
39
+ if (f) throw new TypeError("Generator is already executing.");
40
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
41
+ 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;
42
+ if (y = 0, t) op = [op[0] & 2, t.value];
43
+ switch (op[0]) {
44
+ case 0: case 1: t = op; break;
45
+ case 4: _.label++; return { value: op[1], done: false };
46
+ case 5: _.label++; y = op[1]; op = [0]; continue;
47
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
48
+ default:
49
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
50
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
51
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
52
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
53
+ if (t[2]) _.ops.pop();
54
+ _.trys.pop(); continue;
55
+ }
56
+ op = body.call(thisArg, _);
57
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
58
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
59
+ }
60
+ };
61
+ var __read = (this && this.__read) || function (o, n) {
62
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
63
+ if (!m) return o;
64
+ var i = m.call(o), r, ar = [], e;
65
+ try {
66
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
67
+ }
68
+ catch (error) { e = { error: error }; }
69
+ finally {
70
+ try {
71
+ if (r && !r.done && (m = i["return"])) m.call(i);
72
+ }
73
+ finally { if (e) throw e.error; }
74
+ }
75
+ return ar;
76
+ };
77
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
78
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
79
+ if (ar || !(i in from)) {
80
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
81
+ ar[i] = from[i];
82
+ }
83
+ }
84
+ return to.concat(ar || Array.prototype.slice.call(from));
85
+ };
86
+ Object.defineProperty(exports, "__esModule", { value: true });
87
+ var snippetsCommand_1 = require("../snippetsCommand");
88
+ var snippetsModule = __importStar(require("../snippets"));
89
+ var command_1 = require("../../../types/command");
90
+ var utils_1 = require("@sasjs/utils");
91
+ var configUtils = __importStar(require("../../../utils/config"));
92
+ var setConstantsUtils = __importStar(require("../../../utils/setConstants"));
93
+ var logger_1 = require("@sasjs/utils/logger");
94
+ var utils_2 = require("../../../utils");
95
+ var target = new utils_1.Target({
96
+ name: 'test',
97
+ appLoc: '/Public/test/',
98
+ serverType: utils_1.ServerType.SasViya,
99
+ contextName: 'test context'
100
+ });
101
+ var config = {};
102
+ describe('SnippetsCommand', function () {
103
+ var defaultArgs = ['node', 'sasjs'];
104
+ var commandName = 'snippets';
105
+ beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
106
+ return __generator(this, function (_a) {
107
+ switch (_a.label) {
108
+ case 0: return [4 /*yield*/, (0, utils_2.setConstants)(false)];
109
+ case 1:
110
+ _a.sent();
111
+ return [2 /*return*/];
112
+ }
113
+ });
114
+ }); });
115
+ beforeEach(function () {
116
+ setupMocks();
117
+ });
118
+ it('should parse sasjs snippets command without flags', function () {
119
+ var args = __spreadArray(__spreadArray([], __read(defaultArgs), false), [commandName], false);
120
+ var command = new snippetsCommand_1.SnippetsCommand(args);
121
+ expect(command.name).toEqual(commandName);
122
+ });
123
+ it('should call snippets handler when executed', function () { return __awaiter(void 0, void 0, void 0, function () {
124
+ var args, command, returnCode;
125
+ return __generator(this, function (_a) {
126
+ switch (_a.label) {
127
+ case 0:
128
+ args = __spreadArray(__spreadArray([], __read(defaultArgs), false), [commandName], false);
129
+ command = new snippetsCommand_1.SnippetsCommand(args);
130
+ return [4 /*yield*/, command.execute()];
131
+ case 1:
132
+ returnCode = _a.sent();
133
+ expect(returnCode).toEqual(command_1.ReturnCode.Success);
134
+ return [2 /*return*/];
135
+ }
136
+ });
137
+ }); });
138
+ it('should parse a sasjs snippets command with a target', function () { return __awaiter(void 0, void 0, void 0, function () {
139
+ var args, command, targetInfo;
140
+ return __generator(this, function (_a) {
141
+ switch (_a.label) {
142
+ case 0:
143
+ args = __spreadArray(__spreadArray([], __read(defaultArgs), false), [commandName, '-t', 'test'], false);
144
+ command = new snippetsCommand_1.SnippetsCommand(args);
145
+ return [4 /*yield*/, command.getTargetInfo()];
146
+ case 1:
147
+ targetInfo = _a.sent();
148
+ expect(command.name).toEqual(commandName);
149
+ expect(command.subCommand).toEqual('');
150
+ expect(targetInfo.target).toEqual(target);
151
+ return [2 /*return*/];
152
+ }
153
+ });
154
+ }); });
155
+ it('should return with the error code when execution fails', function () { return __awaiter(void 0, void 0, void 0, function () {
156
+ var args, command, returnCode;
157
+ return __generator(this, function (_a) {
158
+ switch (_a.label) {
159
+ case 0:
160
+ args = __spreadArray(__spreadArray([], __read(defaultArgs), false), [commandName], false);
161
+ jest
162
+ .spyOn(snippetsModule, 'generateSnippets')
163
+ .mockImplementation(function () { return Promise.reject(); });
164
+ command = new snippetsCommand_1.SnippetsCommand(args);
165
+ return [4 /*yield*/, command.execute()];
166
+ case 1:
167
+ returnCode = _a.sent();
168
+ expect(returnCode).toEqual(command_1.ReturnCode.InternalError);
169
+ expect(process.logger.error).toHaveBeenCalled();
170
+ return [2 /*return*/];
171
+ }
172
+ });
173
+ }); });
174
+ });
175
+ var setupMocks = function () {
176
+ jest.resetAllMocks();
177
+ jest
178
+ .spyOn(snippetsModule, 'generateSnippets')
179
+ .mockImplementation(function () { return Promise.resolve(''); });
180
+ jest
181
+ .spyOn(configUtils, 'findTargetInConfiguration')
182
+ .mockImplementation(function () { return Promise.resolve({ target: target, isLocal: true }); });
183
+ jest
184
+ .spyOn(configUtils, 'getLocalConfig')
185
+ .mockImplementation(function () { return Promise.resolve(config); });
186
+ jest
187
+ .spyOn(configUtils, 'findTargetInConfiguration')
188
+ .mockImplementation(function () { return Promise.resolve({ target: target, isLocal: true }); });
189
+ jest
190
+ .spyOn(setConstantsUtils, 'setConstants')
191
+ .mockImplementation(function () { return Promise.resolve(); });
192
+ process.logger = new logger_1.Logger(logger_1.LogLevel.Off);
193
+ jest.spyOn(process.logger, 'success');
194
+ jest.spyOn(process.logger, 'error');
195
+ };
@@ -24,6 +24,7 @@ var jobCommand_1 = require("../../commands/job/jobCommand");
24
24
  var lintCommand_1 = require("../../commands/lint/lintCommand");
25
25
  var flowCommand_1 = require("../../commands/flow/flowCommand");
26
26
  var fsCommand_1 = require("../../commands/fs/fsCommand");
27
+ var snippetsCommand_1 = require("../../commands/snippets/snippetsCommand");
27
28
  exports.commandFactory = new Map([
28
29
  ['add', function (args) { return new addCommand_1.AddCommand(args); }],
29
30
  ['build', function (args) { return new buildCommand_1.BuildCommand(args); }],
@@ -48,6 +49,7 @@ exports.commandFactory = new Map([
48
49
  ['request', function (args) { return new requestCommand_1.RequestCommand(args); }],
49
50
  ['run', function (args) { return new runCommand_1.RunCommand(args); }],
50
51
  ['servicepack', function (args) { return new servicePackCommand_1.ServicePackCommand(args); }],
52
+ ['snippets', function (args) { return new snippetsCommand_1.SnippetsCommand(args); }],
51
53
  ['version', function (args) { return new versionCommand_1.VersionCommand(args); }],
52
54
  ['test', function (args) { return new testCommand_1.TestCommand(args); }],
53
55
  ['web', function (args) { return new webCommand_1.WebCommand(args); }]
@@ -1148,7 +1148,16 @@ exports.getTestTearDown = getTestTearDown;
1148
1148
  * @returns - instance of @sasjs/adapter.
1149
1149
  */
1150
1150
  function getSASjs(target) {
1151
- var verbose = process.env.VERBOSE;
1151
+ var _a = process.env, VERBOSE = _a.VERBOSE, LOG_LEVEL = _a.LOG_LEVEL;
1152
+ var verbose = false;
1153
+ // verbose mode should be enabled if VERBOSE environment variable present and is equal to 'on'(case insensitive)
1154
+ if (typeof VERBOSE === 'string' && /on/i.test(VERBOSE)) {
1155
+ verbose = true;
1156
+ }
1157
+ // verbose mode should be enabled if LOG_LEVEL environment variable present and is equal to 'trace'(case insensitive)
1158
+ else if (typeof LOG_LEVEL === 'string' && /trace/i.test(LOG_LEVEL)) {
1159
+ verbose = true;
1160
+ }
1152
1161
  return new node_1.default({
1153
1162
  serverUrl: target.serverUrl,
1154
1163
  appLoc: target.appLoc,
@@ -1157,7 +1166,7 @@ function getSASjs(target) {
1157
1166
  httpsAgentOptions: target.httpsAgentOptions,
1158
1167
  debug: true,
1159
1168
  useComputeApi: target.serverType === utils_1.ServerType.SasViya,
1160
- verbose: typeof verbose === 'string' ? /on/i.test(verbose) : false // only string equal to 'on'(case insensitive) will enable verbose mode
1169
+ verbose: verbose
1161
1170
  });
1162
1171
  }
1163
1172
  exports.getSASjs = getSASjs;
@@ -782,15 +782,29 @@ describe('getSASjs', function () {
782
782
  verbose = sasjsConfig.verbose;
783
783
  expect(verbose).toEqual(true);
784
784
  });
785
- it('should disable verbose mode if VERBOSE env is not present', function () {
785
+ it("should enable verbose mode if LOG_LEVEL env is present and is equal to 'trace'(case insensitive)", function () {
786
+ process.env.LOG_LEVEL = 'trace';
787
+ var sasjs = (0, config_1.getSASjs)({});
788
+ var sasjsConfig = sasjs.getSasjsConfig();
789
+ var verbose = sasjsConfig.verbose;
790
+ expect(verbose).toEqual(true);
791
+ process.env.LOG_LEVEL = 'TRACE';
792
+ sasjs = (0, config_1.getSASjs)({});
793
+ sasjsConfig = sasjs.getSasjsConfig();
794
+ verbose = sasjsConfig.verbose;
795
+ expect(verbose).toEqual(true);
796
+ });
797
+ it('should disable verbose mode if VERBOSE and LOG_LEVEL env are not present', function () {
786
798
  process.env.VERBOSE = '';
799
+ process.env.LOG_LEVEL = '';
787
800
  var sasjs = (0, config_1.getSASjs)({});
788
801
  var sasjsConfig = sasjs.getSasjsConfig();
789
802
  var verbose = sasjsConfig.verbose;
790
803
  expect(verbose).toEqual(false);
791
804
  });
792
- it("should disable verbose mode if VERBOSE env is present and is not equal to 'on'(case insensitive)", function () {
805
+ it("should disable verbose mode if VERBOSE env is present and is not equal to 'on'(case insensitive) and LOG_LEVEL env is present and is not equal to 'trace'(case insensitive)", function () {
793
806
  process.env.VERBOSE = 'start';
807
+ process.env.LOG_LEVEL = 'Info';
794
808
  var sasjs = (0, config_1.getSASjs)({});
795
809
  var sasjsConfig = sasjs.getSasjsConfig();
796
810
  var verbose = sasjsConfig.verbose;
package/package.json CHANGED
@@ -54,7 +54,7 @@
54
54
  "@sasjs/adapter": "4.8.0",
55
55
  "@sasjs/core": "4.46.3",
56
56
  "@sasjs/lint": "2.3.1",
57
- "@sasjs/utils": "3.3.0",
57
+ "@sasjs/utils": "3.4.0",
58
58
  "adm-zip": "0.5.9",
59
59
  "chalk": "4.1.2",
60
60
  "dotenv": "16.0.3",
@@ -104,5 +104,5 @@
104
104
  "typescript": "4.9.5",
105
105
  "util": "0.12.4"
106
106
  },
107
- "version": "4.5.1"
107
+ "version": "4.7.0"
108
108
  }