@sasjs/cli 5.0.2 → 5.1.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.
- package/build/commands/docs/generateDocs.js +6 -17
- package/build/commands/docs/spec/generateDocs.spec.js +2 -2
- package/build/commands/shared/createLintConfigFile.js +2 -2
- package/build/utils/shell.d.ts +18 -6
- package/build/utils/shell.js +42 -15
- package/build/utils/spec/shell.spec.js +27 -0
- package/build/utils/spec/zip.spec.js +54 -0
- package/package.json +16 -13
|
@@ -94,7 +94,7 @@ var shell_1 = require("../../utils/shell");
|
|
|
94
94
|
*/
|
|
95
95
|
function generateDocs(target, config, outDirectory) {
|
|
96
96
|
return __awaiter(this, void 0, void 0, function () {
|
|
97
|
-
var _a, serverUrl, newOutDirectory, enableLineage, doxyContentFromConfig, _b, macroCoreFolders, macroFolders, programFolders, serviceFolders, jobFolders, combinedFolders, PROJECT_NAME, PROJECT_BRIEF, packageJsonContent, packageJson, e_1, doxyContent, layoutFilePath, LAYOUT_FILE, readMePath,
|
|
97
|
+
var _a, serverUrl, newOutDirectory, enableLineage, doxyContentFromConfig, _b, macroCoreFolders, macroFolders, programFolders, serviceFolders, jobFolders, combinedFolders, PROJECT_NAME, PROJECT_BRIEF, packageJsonContent, packageJson, e_1, doxyContent, layoutFilePath, LAYOUT_FILE, readMePath, doxyVariables, doxyConfigPath, spinner, pathExists, _c, stderr, code, foldersListForDot;
|
|
98
98
|
var _this = this;
|
|
99
99
|
var _d, _e;
|
|
100
100
|
return __generator(this, function (_f) {
|
|
@@ -163,7 +163,7 @@ function generateDocs(target, config, outDirectory) {
|
|
|
163
163
|
case 5:
|
|
164
164
|
LAYOUT_FILE = _f.sent();
|
|
165
165
|
readMePath = path_1.default.join(doxyContent.path, doxyContent.readMe);
|
|
166
|
-
|
|
166
|
+
doxyVariables = {
|
|
167
167
|
DOXY_HTML_OUTPUT: newOutDirectory,
|
|
168
168
|
DOXY_INPUT: "\"".concat(readMePath, "\" ").concat(combinedFolders),
|
|
169
169
|
DOXY_MAINPAGE: readMePath,
|
|
@@ -175,7 +175,7 @@ function generateDocs(target, config, outDirectory) {
|
|
|
175
175
|
PROJECT_BRIEF: PROJECT_BRIEF,
|
|
176
176
|
PROJECT_LOGO: path_1.default.join(doxyContent.path, doxyContent.logo),
|
|
177
177
|
PROJECT_NAME: PROJECT_NAME
|
|
178
|
-
}
|
|
178
|
+
};
|
|
179
179
|
return [4 /*yield*/, getDoxyConfigPath(doxyContent.path)];
|
|
180
180
|
case 6:
|
|
181
181
|
doxyConfigPath = _f.sent();
|
|
@@ -194,8 +194,9 @@ function generateDocs(target, config, outDirectory) {
|
|
|
194
194
|
case 9: return [4 /*yield*/, (0, utils_1.createFolder)(newOutDirectory)];
|
|
195
195
|
case 10:
|
|
196
196
|
_f.sent();
|
|
197
|
-
_c = (0, shell_1.
|
|
198
|
-
silent: process.env.LOG_LEVEL !== utils_1.LogLevel.Debug
|
|
197
|
+
_c = (0, shell_1.execFile)('doxygen', [doxyConfigPath], {
|
|
198
|
+
silent: process.env.LOG_LEVEL !== utils_1.LogLevel.Debug,
|
|
199
|
+
env: doxyVariables
|
|
199
200
|
}), stderr = _c.stderr, code = _c.code;
|
|
200
201
|
if (process.env.LOG_LEVEL !== utils_1.LogLevel.Debug)
|
|
201
202
|
spinner.stop();
|
|
@@ -228,18 +229,6 @@ function generateDocs(target, config, outDirectory) {
|
|
|
228
229
|
});
|
|
229
230
|
});
|
|
230
231
|
}
|
|
231
|
-
function setVariableCmd(params) {
|
|
232
|
-
var command = '';
|
|
233
|
-
if ((0, utils_1.isWindows)()) {
|
|
234
|
-
for (var param in params)
|
|
235
|
-
command += "set ".concat(param, "=").concat(params[param], " && ");
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
for (var param in params)
|
|
239
|
-
command += "".concat(param, "='").concat(params[param], "' ");
|
|
240
|
-
}
|
|
241
|
-
return command;
|
|
242
|
-
}
|
|
243
232
|
var getDoxyConfigPath = function (doxyContentPath) { return __awaiter(void 0, void 0, void 0, function () {
|
|
244
233
|
var doxyFilePath;
|
|
245
234
|
return __generator(this, function (_a) {
|
|
@@ -555,7 +555,7 @@ describe('sasjs doc', function () {
|
|
|
555
555
|
return __generator(this, function (_a) {
|
|
556
556
|
switch (_a.label) {
|
|
557
557
|
case 0:
|
|
558
|
-
jest.spyOn(shell, '
|
|
558
|
+
jest.spyOn(shell, 'execFile').mockReturnValueOnce({
|
|
559
559
|
code: 1,
|
|
560
560
|
stderr: 'error: bad config',
|
|
561
561
|
stdout: ''
|
|
@@ -571,7 +571,7 @@ describe('sasjs doc', function () {
|
|
|
571
571
|
return __generator(this, function (_a) {
|
|
572
572
|
switch (_a.label) {
|
|
573
573
|
case 0:
|
|
574
|
-
jest.spyOn(shell, '
|
|
574
|
+
jest.spyOn(shell, 'execFile').mockReturnValueOnce({
|
|
575
575
|
code: 1,
|
|
576
576
|
stderr: 'command not found',
|
|
577
577
|
stdout: ''
|
|
@@ -41,7 +41,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
42
|
exports.createLintConfigFile = void 0;
|
|
43
43
|
var path_1 = __importDefault(require("path"));
|
|
44
|
-
var
|
|
44
|
+
var lint_1 = require("@sasjs/lint");
|
|
45
45
|
var utils_1 = require("@sasjs/utils");
|
|
46
46
|
/**
|
|
47
47
|
* Creates a SASjs Lint configuration file.
|
|
@@ -54,7 +54,7 @@ var createLintConfigFile = function (parentFolderName) { return __awaiter(void 0
|
|
|
54
54
|
switch (_a.label) {
|
|
55
55
|
case 0:
|
|
56
56
|
configDestinationPath = path_1.default.join(process.projectDir, parentFolderName, '.sasjslint');
|
|
57
|
-
return [4 /*yield*/, (0, utils_1.createFile)(configDestinationPath, JSON.stringify(
|
|
57
|
+
return [4 /*yield*/, (0, utils_1.createFile)(configDestinationPath, JSON.stringify(lint_1.DefaultLintConfiguration, null, 2))];
|
|
58
58
|
case 1:
|
|
59
59
|
_a.sent();
|
|
60
60
|
return [2 /*return*/];
|
package/build/utils/shell.d.ts
CHANGED
|
@@ -17,15 +17,27 @@ export interface ShellResult {
|
|
|
17
17
|
stderr: string;
|
|
18
18
|
code: number;
|
|
19
19
|
}
|
|
20
|
+
export interface ExecOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Whether the command's output also reaches this process's streams, which is
|
|
23
|
+
* how shelljs' option of the same name behaved.
|
|
24
|
+
*/
|
|
25
|
+
silent?: boolean;
|
|
26
|
+
/** Extra variables for the child, on top of this process's environment. */
|
|
27
|
+
env?: NodeJS.ProcessEnv;
|
|
28
|
+
}
|
|
29
|
+
/** Runs a command through the platform shell. */
|
|
30
|
+
export declare const exec: (command: string, options?: ExecOptions) => ShellResult;
|
|
20
31
|
/**
|
|
21
|
-
* Runs
|
|
32
|
+
* Runs an executable with an argument array, without a shell.
|
|
22
33
|
*
|
|
23
|
-
* `
|
|
24
|
-
*
|
|
34
|
+
* `exec` hands its command to a shell, which re-parses everything in it: a path
|
|
35
|
+
* containing a quote, `$` or `&` changes the command's meaning, and a variable
|
|
36
|
+
* assigned on the command line is no different - on Windows the assignment form
|
|
37
|
+
* does not even quote the value. Arguments and `env` given here are passed to
|
|
38
|
+
* the child as they are, so they are safe whatever they contain.
|
|
25
39
|
*/
|
|
26
|
-
export declare const
|
|
27
|
-
silent?: boolean;
|
|
28
|
-
}) => ShellResult;
|
|
40
|
+
export declare const execFile: (command: string, args: string[], options?: ExecOptions) => ShellResult;
|
|
29
41
|
/**
|
|
30
42
|
* Copies the contents of a folder into another folder, matching
|
|
31
43
|
* `cp -r <source>/. <destination>`.
|
package/build/utils/shell.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
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
|
+
};
|
|
2
13
|
var __values = (this && this.__values) || function(o) {
|
|
3
14
|
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
4
15
|
if (m) return m.call(o);
|
|
@@ -14,28 +25,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
25
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
26
|
};
|
|
16
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.which = exports.ls = exports.rm = exports.cp = exports.exec = void 0;
|
|
28
|
+
exports.which = exports.ls = exports.rm = exports.cp = exports.execFile = exports.exec = void 0;
|
|
18
29
|
var child_process_1 = require("child_process");
|
|
19
30
|
var fs_1 = __importDefault(require("fs"));
|
|
20
31
|
var path_1 = __importDefault(require("path"));
|
|
21
32
|
var utils_1 = require("@sasjs/utils");
|
|
22
33
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* streams, which is how shelljs' option of the same name behaved.
|
|
34
|
+
* The options both runners share. shelljs allowed 20MB of output; spawnSync's
|
|
35
|
+
* 1MB default kills a chatty command mid-run, and a deploy script can easily be
|
|
36
|
+
* chatty.
|
|
27
37
|
*/
|
|
28
|
-
var
|
|
38
|
+
var spawnOptions = function (options) { return ({
|
|
39
|
+
encoding: 'utf8',
|
|
40
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
41
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
42
|
+
env: options.env ? __assign(__assign({}, process.env), options.env) : undefined
|
|
43
|
+
}); };
|
|
44
|
+
/** The result both runners answer with, from one place. */
|
|
45
|
+
var toShellResult = function (result, options) {
|
|
29
46
|
var _a, _b, _c;
|
|
30
|
-
if (options === void 0) { options = {}; }
|
|
31
|
-
var result = (0, child_process_1.spawnSync)(command, {
|
|
32
|
-
shell: true,
|
|
33
|
-
encoding: 'utf8',
|
|
34
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
35
|
-
// shelljs allowed 20MB of output; spawnSync's 1MB default kills a chatty
|
|
36
|
-
// command mid-run, and a deploy script can easily be chatty.
|
|
37
|
-
maxBuffer: 20 * 1024 * 1024
|
|
38
|
-
});
|
|
39
47
|
var stdout = (_a = result.stdout) !== null && _a !== void 0 ? _a : '';
|
|
40
48
|
var stderr = (_b = result.stderr) !== null && _b !== void 0 ? _b : '';
|
|
41
49
|
if (!options.silent) {
|
|
@@ -56,7 +64,26 @@ var exec = function (command, options) {
|
|
|
56
64
|
}
|
|
57
65
|
return { stdout: stdout, stderr: stderr, code: (_c = result.status) !== null && _c !== void 0 ? _c : 0 };
|
|
58
66
|
};
|
|
67
|
+
/** Runs a command through the platform shell. */
|
|
68
|
+
var exec = function (command, options) {
|
|
69
|
+
if (options === void 0) { options = {}; }
|
|
70
|
+
return toShellResult((0, child_process_1.spawnSync)(command, __assign(__assign({}, spawnOptions(options)), { shell: true })), options);
|
|
71
|
+
};
|
|
59
72
|
exports.exec = exec;
|
|
73
|
+
/**
|
|
74
|
+
* Runs an executable with an argument array, without a shell.
|
|
75
|
+
*
|
|
76
|
+
* `exec` hands its command to a shell, which re-parses everything in it: a path
|
|
77
|
+
* containing a quote, `$` or `&` changes the command's meaning, and a variable
|
|
78
|
+
* assigned on the command line is no different - on Windows the assignment form
|
|
79
|
+
* does not even quote the value. Arguments and `env` given here are passed to
|
|
80
|
+
* the child as they are, so they are safe whatever they contain.
|
|
81
|
+
*/
|
|
82
|
+
var execFile = function (command, args, options) {
|
|
83
|
+
if (options === void 0) { options = {}; }
|
|
84
|
+
return toShellResult((0, child_process_1.spawnSync)(command, args, spawnOptions(options)), options);
|
|
85
|
+
};
|
|
86
|
+
exports.execFile = execFile;
|
|
60
87
|
/**
|
|
61
88
|
* Copies the contents of a folder into another folder, matching
|
|
62
89
|
* `cp -r <source>/. <destination>`.
|
|
@@ -54,6 +54,33 @@ describe('shell', function () {
|
|
|
54
54
|
expect(result.stdout.length).toEqual(3 * 1024 * 1024);
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
|
+
describe('execFile', function () {
|
|
58
|
+
// The values below are the point: a shell would interpret each of them -
|
|
59
|
+
// `&` and `;` separate commands, `$(...)` and backticks substitute, `'`
|
|
60
|
+
// closes a quote - and on Windows the `set NAME=value` form does not quote
|
|
61
|
+
// the value at all. Nothing here is parsed, so each arrives intact.
|
|
62
|
+
var metacharacters = "a'b&c;$(echo pwned)`id`|d>e";
|
|
63
|
+
it('should answer with stdout for an executable run with an argument array', function () {
|
|
64
|
+
var result = (0, shell_1.execFile)(process.execPath, ['-e', "process.stdout.write('hello')"], { silent: true });
|
|
65
|
+
expect(result.stdout).toEqual('hello');
|
|
66
|
+
expect(result.code).toEqual(0);
|
|
67
|
+
});
|
|
68
|
+
it('should pass an argument through without the shell interpreting it', function () {
|
|
69
|
+
var result = (0, shell_1.execFile)(process.execPath, ['-e', 'process.stdout.write(process.argv[1])', metacharacters], { silent: true });
|
|
70
|
+
expect(result.stdout).toEqual(metacharacters);
|
|
71
|
+
expect(result.code).toEqual(0);
|
|
72
|
+
});
|
|
73
|
+
it('should pass an environment value through without the shell interpreting it', function () {
|
|
74
|
+
var result = (0, shell_1.execFile)(process.execPath, ['-e', 'process.stdout.write(process.env.PROBE)'], { silent: true, env: { PROBE: metacharacters } });
|
|
75
|
+
expect(result.stdout).toEqual(metacharacters);
|
|
76
|
+
expect(result.code).toEqual(0);
|
|
77
|
+
});
|
|
78
|
+
it('should answer with the exit code and stderr for an executable that fails', function () {
|
|
79
|
+
var result = (0, shell_1.execFile)(process.execPath, ['-e', "process.stderr.write('boom'); process.exit(3)"], { silent: true });
|
|
80
|
+
expect(result.code).toEqual(3);
|
|
81
|
+
expect(result.stderr).toContain('boom');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
57
84
|
describe('ls', function () {
|
|
58
85
|
beforeEach(function () {
|
|
59
86
|
fs_1.default.mkdirSync(path_1.default.join(root, 'sasjs-react-seed-app-main'));
|
|
@@ -84,6 +84,32 @@ var setEntryPlatform = function (zipPath, platform) {
|
|
|
84
84
|
}
|
|
85
85
|
fs_1.default.writeFileSync(zipPath, buffer);
|
|
86
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* Rewrites an entry name in the archive bytes, in both the local file header
|
|
89
|
+
* and the central directory record.
|
|
90
|
+
*
|
|
91
|
+
* yazl refuses to create an entry whose name is absolute or contains `..`, so
|
|
92
|
+
* a traversal entry has to be patched in after the fact. The replacement must
|
|
93
|
+
* be the same length as the original: both records carry the name length, and
|
|
94
|
+
* changing it would move every offset that follows.
|
|
95
|
+
*/
|
|
96
|
+
var replaceEntryName = function (zipPath, from, to) {
|
|
97
|
+
if (from.length !== to.length)
|
|
98
|
+
throw new Error('the replacement name must be the same length');
|
|
99
|
+
var buffer = fs_1.default.readFileSync(zipPath);
|
|
100
|
+
var fromBuffer = Buffer.from(from, 'utf8');
|
|
101
|
+
var toBuffer = Buffer.from(to, 'utf8');
|
|
102
|
+
var index = buffer.indexOf(fromBuffer);
|
|
103
|
+
var replaced = 0;
|
|
104
|
+
while (index !== -1) {
|
|
105
|
+
toBuffer.copy(buffer, index);
|
|
106
|
+
replaced++;
|
|
107
|
+
index = buffer.indexOf(fromBuffer, index + 1);
|
|
108
|
+
}
|
|
109
|
+
if (!replaced)
|
|
110
|
+
throw new Error("entry name not found in the archive: ".concat(from));
|
|
111
|
+
fs_1.default.writeFileSync(zipPath, buffer);
|
|
112
|
+
};
|
|
87
113
|
describe('zip', function () {
|
|
88
114
|
var tmpRoot = path_1.default.join(__dirname, "zip-spec-".concat((0, test_1.generateUniqueTimestamp)()));
|
|
89
115
|
var destDir = path_1.default.join(tmpRoot, 'dest');
|
|
@@ -279,5 +305,33 @@ describe('zip', function () {
|
|
|
279
305
|
}
|
|
280
306
|
});
|
|
281
307
|
}); });
|
|
308
|
+
/**
|
|
309
|
+
* The safety of `path.join(destDir, entry.fileName)` rests on the entry
|
|
310
|
+
* name never containing `..` or a leading slash. That is yauzl's
|
|
311
|
+
* validateFileName, which only runs because the reader is opened with
|
|
312
|
+
* decodeStrings - so the property is pinned here rather than left to the
|
|
313
|
+
* comment that documents it.
|
|
314
|
+
*/
|
|
315
|
+
it('should refuse an entry whose name traverses out of the destination', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
316
|
+
var zipPath;
|
|
317
|
+
return __generator(this, function (_a) {
|
|
318
|
+
switch (_a.label) {
|
|
319
|
+
case 0:
|
|
320
|
+
zipPath = path_1.default.join(tmpRoot, 'traversal.zip');
|
|
321
|
+
return [4 /*yield*/, makeZip([{ name: 'aa/evil.txt', content: 'pwned' }], zipPath)];
|
|
322
|
+
case 1:
|
|
323
|
+
_a.sent();
|
|
324
|
+
replaceEntryName(zipPath, 'aa/evil.txt', '../evil.txt');
|
|
325
|
+
return [4 /*yield*/, expect((0, zip_1.extractZip)(zipPath, destDir)).rejects.toThrow()
|
|
326
|
+
// destDir/../evil.txt resolves to tmpRoot/evil.txt
|
|
327
|
+
];
|
|
328
|
+
case 2:
|
|
329
|
+
_a.sent();
|
|
330
|
+
// destDir/../evil.txt resolves to tmpRoot/evil.txt
|
|
331
|
+
expect(fs_1.default.existsSync(path_1.default.join(tmpRoot, 'evil.txt'))).toBeFalse();
|
|
332
|
+
return [2 /*return*/];
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}); });
|
|
282
336
|
});
|
|
283
337
|
});
|
package/package.json
CHANGED
|
@@ -69,14 +69,13 @@
|
|
|
69
69
|
"registry": "https://registry.npmjs.org"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@sasjs/adapter": "5.1.
|
|
72
|
+
"@sasjs/adapter": "5.1.1",
|
|
73
73
|
"@sasjs/core": "5.5.2",
|
|
74
|
-
"@sasjs/
|
|
75
|
-
"@sasjs/utils": "4.0.0",
|
|
74
|
+
"@sasjs/utils": "4.0.1",
|
|
76
75
|
"axios": "1.20.0",
|
|
77
76
|
"chalk": "4.1.2",
|
|
78
|
-
"dotenv": "
|
|
79
|
-
"js-base64": "3.9.
|
|
77
|
+
"dotenv": "18.0.8",
|
|
78
|
+
"js-base64": "3.9.4",
|
|
80
79
|
"jsdom": "26.0.0",
|
|
81
80
|
"lodash.uniqby": "4.7.0",
|
|
82
81
|
"node-graphviz": "0.1.1",
|
|
@@ -94,6 +93,7 @@
|
|
|
94
93
|
"@babel/preset-env": "7.29.7",
|
|
95
94
|
"@babel/preset-typescript": "7.29.7",
|
|
96
95
|
"@nogoo9/gitleaks": "8.30.1-post.2",
|
|
96
|
+
"@sasjs/lint": "4.2.0",
|
|
97
97
|
"@types/debug": "4.1.13",
|
|
98
98
|
"@types/find": "0.2.4",
|
|
99
99
|
"@types/jest": "30.0.0",
|
|
@@ -105,15 +105,15 @@
|
|
|
105
105
|
"@types/xml": "1.0.11",
|
|
106
106
|
"@types/yauzl": "3.4.0",
|
|
107
107
|
"@types/yazl": "3.3.1",
|
|
108
|
-
"babel-jest": "30.5.
|
|
108
|
+
"babel-jest": "30.5.2",
|
|
109
109
|
"copyfiles": "2.4.1",
|
|
110
|
-
"jest": "30.5.
|
|
111
|
-
"jest-cli": "30.5.
|
|
112
|
-
"jest-environment-jsdom": "30.5.
|
|
113
|
-
"jest-extended": "
|
|
110
|
+
"jest": "30.5.2",
|
|
111
|
+
"jest-cli": "30.5.2",
|
|
112
|
+
"jest-environment-jsdom": "30.5.2",
|
|
113
|
+
"jest-extended": "7.0.0",
|
|
114
114
|
"nodemon": "3.1.14",
|
|
115
|
-
"prettier": "3.9.
|
|
116
|
-
"ts-jest": "29.4.
|
|
115
|
+
"prettier": "3.9.10",
|
|
116
|
+
"ts-jest": "29.4.15",
|
|
117
117
|
"ts-node": "10.9.2",
|
|
118
118
|
"typescript": "5.9.3",
|
|
119
119
|
"util": "0.12.5"
|
|
@@ -122,5 +122,8 @@
|
|
|
122
122
|
"ws": "8.21.0",
|
|
123
123
|
"nanoid": "3.3.18"
|
|
124
124
|
},
|
|
125
|
-
"
|
|
125
|
+
"peerDependencies": {
|
|
126
|
+
"@sasjs/lint": "^4.1.4"
|
|
127
|
+
},
|
|
128
|
+
"version": "5.1.0"
|
|
126
129
|
}
|