@sasjs/cli 4.6.0 → 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); }]
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.6.0"
107
+ "version": "4.7.0"
108
108
  }