@sasjs/cli 3.23.6 → 3.24.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/fs/fsCommand.d.ts +1 -0
- package/build/commands/fs/fsCommand.js +87 -10
- package/build/commands/fs/spec/fsCommand.spec.js +64 -10
- package/package.json +3 -3
- package/build/commands/fs/internal/extractHashArray.d.ts +0 -1
- package/build/commands/fs/internal/extractHashArray.js +0 -20
- package/build/commands/fs/spec/extractHashArray.spec.d.ts +0 -1
- package/build/commands/fs/spec/extractHashArray.spec.js +0 -14
|
@@ -7,5 +7,6 @@ export declare class FSCommand extends TargetCommand {
|
|
|
7
7
|
getOutputPath(): Promise<string>;
|
|
8
8
|
execute(): Promise<ReturnCode>;
|
|
9
9
|
compile(): Promise<ReturnCode>;
|
|
10
|
+
deploy(): Promise<ReturnCode.Success | ReturnCode.InternalError>;
|
|
10
11
|
sync(): Promise<ReturnCode.Success | ReturnCode.InternalError>;
|
|
11
12
|
}
|
|
@@ -108,11 +108,11 @@ var utils_1 = require("../../utils");
|
|
|
108
108
|
var path_1 = __importDefault(require("path"));
|
|
109
109
|
var utils_2 = require("@sasjs/utils");
|
|
110
110
|
var executeCode_1 = require("./internal/executeCode");
|
|
111
|
-
var extractHashArray_1 = require("./internal/extractHashArray");
|
|
112
111
|
var FsSubCommand;
|
|
113
112
|
(function (FsSubCommand) {
|
|
114
113
|
FsSubCommand["Compile"] = "compile";
|
|
115
114
|
FsSubCommand["Sync"] = "sync";
|
|
115
|
+
FsSubCommand["Deploy"] = "deploy";
|
|
116
116
|
})(FsSubCommand || (FsSubCommand = {}));
|
|
117
117
|
var syntax = 'fs <subCommand> [options]';
|
|
118
118
|
var usage = 'Usage: sasjs fs <subCommand> [options]';
|
|
@@ -147,6 +147,15 @@ var syncCommandExamples = [
|
|
|
147
147
|
}
|
|
148
148
|
];
|
|
149
149
|
var syncCommandParseOptions = __assign(__assign({}, parseOptions), { local: { type: 'string', alias: 'l' }, remote: { type: 'string', alias: 'r' } });
|
|
150
|
+
var deployCommandSyntax = 'fs <subCommand> <local> <remote> [options]';
|
|
151
|
+
var deployCommandUsage = 'sasjs fs deploy <localFolder> <remoteFolder> [options]';
|
|
152
|
+
var deployCommandDescription = 'Compiles and deploys a local directory tree with one on a remote SAS server.';
|
|
153
|
+
var deployCommandExamples = [
|
|
154
|
+
{
|
|
155
|
+
command: 'sasjs fs deploy <path/of/folder> --output <path/of/outputProgram>',
|
|
156
|
+
description: 'deploys a SAS program with the contents of a local directory'
|
|
157
|
+
}
|
|
158
|
+
];
|
|
150
159
|
var FSCommand = /** @class */ (function (_super) {
|
|
151
160
|
__extends(FSCommand, _super);
|
|
152
161
|
function FSCommand(args) {
|
|
@@ -165,6 +174,12 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
165
174
|
commandOptions.description = compileCommandDescription;
|
|
166
175
|
commandOptions.examples = compileCommandExamples;
|
|
167
176
|
break;
|
|
177
|
+
case FsSubCommand.Deploy:
|
|
178
|
+
commandOptions.syntax = deployCommandSyntax;
|
|
179
|
+
commandOptions.usage = deployCommandUsage;
|
|
180
|
+
commandOptions.description = deployCommandDescription;
|
|
181
|
+
commandOptions.examples = deployCommandExamples;
|
|
182
|
+
break;
|
|
168
183
|
case FsSubCommand.Sync:
|
|
169
184
|
commandOptions.syntax = syncCommandSyntax;
|
|
170
185
|
commandOptions.usage = syncCommandUsage;
|
|
@@ -211,7 +226,7 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
211
226
|
}
|
|
212
227
|
}
|
|
213
228
|
if (!outputPath) {
|
|
214
|
-
return [2 /*return*/, path_1.default.join(process.sasjsConstants.buildDestinationResultsFolder,
|
|
229
|
+
return [2 /*return*/, path_1.default.join(process.sasjsConstants.buildDestinationResultsFolder, "fs-".concat(this.parsed.subcommand), (0, utils_2.generateTimestamp)())];
|
|
215
230
|
}
|
|
216
231
|
if (path_1.default.isAbsolute(outputPath)) {
|
|
217
232
|
return [2 /*return*/, path_1.default.join(outputPath, (0, utils_2.generateTimestamp)())];
|
|
@@ -229,10 +244,14 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
229
244
|
return [4 /*yield*/, this.compile()];
|
|
230
245
|
case 1: return [2 /*return*/, _a.sent()];
|
|
231
246
|
case 2:
|
|
232
|
-
if (!(this.parsed.subCommand === FsSubCommand.
|
|
233
|
-
return [4 /*yield*/, this.
|
|
247
|
+
if (!(this.parsed.subCommand === FsSubCommand.Deploy)) return [3 /*break*/, 4];
|
|
248
|
+
return [4 /*yield*/, this.deploy()];
|
|
234
249
|
case 3: return [2 /*return*/, _a.sent()];
|
|
235
|
-
case 4:
|
|
250
|
+
case 4:
|
|
251
|
+
if (!(this.parsed.subCommand === FsSubCommand.Sync)) return [3 /*break*/, 6];
|
|
252
|
+
return [4 /*yield*/, this.sync()];
|
|
253
|
+
case 5: return [2 /*return*/, _a.sent()];
|
|
254
|
+
case 6: return [2 /*return*/, command_1.ReturnCode.InvalidCommand];
|
|
236
255
|
}
|
|
237
256
|
});
|
|
238
257
|
});
|
|
@@ -265,6 +284,64 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
265
284
|
});
|
|
266
285
|
});
|
|
267
286
|
};
|
|
287
|
+
FSCommand.prototype.deploy = function () {
|
|
288
|
+
var _a, _b, _c, _d, _e;
|
|
289
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
290
|
+
var target, remoteFolderPath, localFolderPath, outputFolder, code, program, error_1, logPath;
|
|
291
|
+
var _this = this;
|
|
292
|
+
return __generator(this, function (_f) {
|
|
293
|
+
switch (_f.label) {
|
|
294
|
+
case 0: return [4 /*yield*/, this.getTargetInfo()];
|
|
295
|
+
case 1:
|
|
296
|
+
target = (_f.sent()).target;
|
|
297
|
+
remoteFolderPath = this.remoteFolder;
|
|
298
|
+
localFolderPath = this.localFolder;
|
|
299
|
+
return [4 /*yield*/, this.getOutputPath()];
|
|
300
|
+
case 2:
|
|
301
|
+
outputFolder = _f.sent();
|
|
302
|
+
_f.label = 3;
|
|
303
|
+
case 3:
|
|
304
|
+
_f.trys.push([3, 7, , 9]);
|
|
305
|
+
(_a = process.logger) === null || _a === void 0 ? void 0 : _a.info('generating compile program');
|
|
306
|
+
return [4 /*yield*/, (0, utils_2.generateCompileProgram)(localFolderPath)];
|
|
307
|
+
case 4:
|
|
308
|
+
code = _f.sent();
|
|
309
|
+
(_b = process.logger) === null || _b === void 0 ? void 0 : _b.info('setting fsTaregt at the start of compiled program');
|
|
310
|
+
program = "%let fsTarget=".concat((0, utils_2.generatePathForSas)(remoteFolderPath), ";\n").concat(code);
|
|
311
|
+
return [4 /*yield*/, createProgramFile(program, path_1.default.join(outputFolder, 'deploy.sas'))];
|
|
312
|
+
case 5:
|
|
313
|
+
_f.sent();
|
|
314
|
+
(_c = process.logger) === null || _c === void 0 ? void 0 : _c.info('executing program to deploy a local directory tree');
|
|
315
|
+
return [4 /*yield*/, (0, executeCode_1.executeCode)(target, program).then(function (_a) {
|
|
316
|
+
var log = _a.log;
|
|
317
|
+
return __awaiter(_this, void 0, void 0, function () {
|
|
318
|
+
return __generator(this, function (_b) {
|
|
319
|
+
switch (_b.label) {
|
|
320
|
+
case 0: return [4 /*yield*/, (0, utils_1.saveLog)(log, path_1.default.join(outputFolder, 'deploy.log'), '', false)];
|
|
321
|
+
case 1:
|
|
322
|
+
_b.sent();
|
|
323
|
+
return [2 /*return*/];
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
})];
|
|
328
|
+
case 6:
|
|
329
|
+
_f.sent();
|
|
330
|
+
(_d = process.logger) === null || _d === void 0 ? void 0 : _d.success("A local directory tree has been successfully deployed to remote sas server");
|
|
331
|
+
return [2 /*return*/, command_1.ReturnCode.Success];
|
|
332
|
+
case 7:
|
|
333
|
+
error_1 = _f.sent();
|
|
334
|
+
logPath = path_1.default.join(outputFolder, 'error.log');
|
|
335
|
+
return [4 /*yield*/, createErrorLogFile(error_1, logPath)];
|
|
336
|
+
case 8:
|
|
337
|
+
_f.sent();
|
|
338
|
+
(_e = process.logger) === null || _e === void 0 ? void 0 : _e.error("An error has occurred. For more info see ".concat(logPath));
|
|
339
|
+
return [2 /*return*/, command_1.ReturnCode.InternalError];
|
|
340
|
+
case 9: return [2 /*return*/];
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
};
|
|
268
345
|
FSCommand.prototype.sync = function () {
|
|
269
346
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
270
347
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -295,7 +372,7 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
295
372
|
return [2 /*return*/, command_1.ReturnCode.Success];
|
|
296
373
|
}
|
|
297
374
|
_loop_1 = function (obj) {
|
|
298
|
-
var outputFolder, program, log, remoteHashes, localHash, remoteHashMap_1, hashedDiff, syncProgram, syncLog, syncedHash, syncedHashMap, syncedResources_1, resourcesNotPresentLocally,
|
|
375
|
+
var outputFolder, program, log, remoteHashes, localHash, remoteHashMap_1, hashedDiff, syncProgram, syncLog, syncedHash, syncedHashMap, syncedResources_1, resourcesNotPresentLocally, error_2, logPath;
|
|
299
376
|
return __generator(this, function (_v) {
|
|
300
377
|
switch (_v.label) {
|
|
301
378
|
case 0: return [4 /*yield*/, this_1.getOutputPath()];
|
|
@@ -319,7 +396,7 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
319
396
|
case 6:
|
|
320
397
|
_v.sent();
|
|
321
398
|
(_d = process.logger) === null || _d === void 0 ? void 0 : _d.info('extracting hashes from log');
|
|
322
|
-
remoteHashes = (0,
|
|
399
|
+
remoteHashes = (0, utils_2.extractHashArray)(log);
|
|
323
400
|
return [4 /*yield*/, createHashFile(JSON.stringify(remoteHashes, null, 2), path_1.default.join(outputFolder, 'hashesBeforeSync.json'))];
|
|
324
401
|
case 7:
|
|
325
402
|
_v.sent();
|
|
@@ -357,7 +434,7 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
357
434
|
return [4 /*yield*/, (0, utils_1.saveLog)(syncLog, path_1.default.join(outputFolder, 'sync.log'), '', false)];
|
|
358
435
|
case 13:
|
|
359
436
|
_v.sent();
|
|
360
|
-
syncedHash = (0,
|
|
437
|
+
syncedHash = (0, utils_2.extractHashArray)(syncLog);
|
|
361
438
|
return [4 /*yield*/, createHashFile(JSON.stringify(syncedHash, null, 2), path_1.default.join(outputFolder, 'hashesAfterSync.json'))];
|
|
362
439
|
case 14:
|
|
363
440
|
_v.sent();
|
|
@@ -391,9 +468,9 @@ var FSCommand = /** @class */ (function (_super) {
|
|
|
391
468
|
}
|
|
392
469
|
return [3 /*break*/, 17];
|
|
393
470
|
case 15:
|
|
394
|
-
|
|
471
|
+
error_2 = _v.sent();
|
|
395
472
|
logPath = path_1.default.join(outputFolder, 'error.log');
|
|
396
|
-
return [4 /*yield*/, createErrorLogFile(
|
|
473
|
+
return [4 /*yield*/, createErrorLogFile(error_2, logPath)];
|
|
397
474
|
case 16:
|
|
398
475
|
_v.sent();
|
|
399
476
|
(_m = process.logger) === null || _m === void 0 ? void 0 : _m.error("An error has occurred. For more info see ".concat(logPath));
|
|
@@ -88,7 +88,6 @@ var FSModule = __importStar(require("@sasjs/utils/fs"));
|
|
|
88
88
|
var FileModule = __importStar(require("@sasjs/utils/file"));
|
|
89
89
|
var configUtils = __importStar(require("../../../utils/config"));
|
|
90
90
|
var executeCodeModule = __importStar(require("../internal/executeCode"));
|
|
91
|
-
var extractHashArrayModule = __importStar(require("../internal/extractHashArray"));
|
|
92
91
|
var defaultArgs = ['node', 'sasjs', 'fs'];
|
|
93
92
|
var target = new utils_1.Target({
|
|
94
93
|
name: 'test',
|
|
@@ -154,6 +153,67 @@ describe('FSCommand', function () {
|
|
|
154
153
|
});
|
|
155
154
|
}); });
|
|
156
155
|
});
|
|
156
|
+
describe('deploy', function () {
|
|
157
|
+
beforeEach(function () {
|
|
158
|
+
process.logger = new utils_1.Logger(utils_1.LogLevel.Off);
|
|
159
|
+
jest.spyOn(process.logger, 'error');
|
|
160
|
+
jest.spyOn(process.logger, 'info');
|
|
161
|
+
jest
|
|
162
|
+
.spyOn(configUtils, 'findTargetInConfiguration')
|
|
163
|
+
.mockImplementation(function () {
|
|
164
|
+
return Promise.resolve({ target: target, isLocal: true });
|
|
165
|
+
});
|
|
166
|
+
jest
|
|
167
|
+
.spyOn(FSModule, 'generateCompileProgram')
|
|
168
|
+
.mockImplementation(function () { return Promise.resolve(''); });
|
|
169
|
+
jest
|
|
170
|
+
.spyOn(FileModule, 'createFile')
|
|
171
|
+
.mockImplementation(function () { return Promise.resolve(); });
|
|
172
|
+
jest
|
|
173
|
+
.spyOn(executeCodeModule, 'executeCode')
|
|
174
|
+
.mockImplementation(function () { return Promise.resolve({ log: '' }); });
|
|
175
|
+
});
|
|
176
|
+
it('should compile and deploy a local directory tree to a remote sas server', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
177
|
+
var returnCode;
|
|
178
|
+
return __generator(this, function (_a) {
|
|
179
|
+
switch (_a.label) {
|
|
180
|
+
case 0:
|
|
181
|
+
jest
|
|
182
|
+
.spyOn(FileModule, 'createFile')
|
|
183
|
+
.mockImplementation(function () { return Promise.resolve(); });
|
|
184
|
+
return [4 /*yield*/, executeCommandWrapper([
|
|
185
|
+
'deploy',
|
|
186
|
+
'localFolder',
|
|
187
|
+
'remoteFolder'
|
|
188
|
+
])];
|
|
189
|
+
case 1:
|
|
190
|
+
returnCode = _a.sent();
|
|
191
|
+
expect(returnCode).toEqual(command_1.ReturnCode.Success);
|
|
192
|
+
return [2 /*return*/];
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}); });
|
|
196
|
+
it('should return an internal error return code', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
197
|
+
var returnCode;
|
|
198
|
+
return __generator(this, function (_a) {
|
|
199
|
+
switch (_a.label) {
|
|
200
|
+
case 0:
|
|
201
|
+
jest
|
|
202
|
+
.spyOn(FileModule, 'createFile')
|
|
203
|
+
.mockImplementationOnce(function () { return Promise.reject({}); });
|
|
204
|
+
return [4 /*yield*/, executeCommandWrapper([
|
|
205
|
+
'deploy',
|
|
206
|
+
'localFolder',
|
|
207
|
+
'remoteFolder'
|
|
208
|
+
])];
|
|
209
|
+
case 1:
|
|
210
|
+
returnCode = _a.sent();
|
|
211
|
+
expect(returnCode).toEqual(command_1.ReturnCode.InternalError);
|
|
212
|
+
return [2 /*return*/];
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}); });
|
|
216
|
+
});
|
|
157
217
|
describe('sync', function () {
|
|
158
218
|
beforeEach(function () {
|
|
159
219
|
process.logger = new utils_1.Logger(utils_1.LogLevel.Off);
|
|
@@ -197,17 +257,13 @@ describe('FSCommand', function () {
|
|
|
197
257
|
return __generator(this, function (_a) {
|
|
198
258
|
switch (_a.label) {
|
|
199
259
|
case 0:
|
|
200
|
-
jest
|
|
201
|
-
.spyOn(extractHashArrayModule, 'extractHashArray')
|
|
202
|
-
.mockImplementationOnce(function () { return [
|
|
260
|
+
jest.spyOn(FSModule, 'extractHashArray').mockImplementationOnce(function () { return [
|
|
203
261
|
{
|
|
204
262
|
FILE_PATH: 'mocked-file',
|
|
205
263
|
FILE_HASH: 'hashOfMockedFile'
|
|
206
264
|
}
|
|
207
265
|
]; });
|
|
208
|
-
jest
|
|
209
|
-
.spyOn(extractHashArrayModule, 'extractHashArray')
|
|
210
|
-
.mockImplementationOnce(function () { return [
|
|
266
|
+
jest.spyOn(FSModule, 'extractHashArray').mockImplementationOnce(function () { return [
|
|
211
267
|
{
|
|
212
268
|
FILE_PATH: 'synced-file',
|
|
213
269
|
FILE_HASH: 'hashOfSyncedFile'
|
|
@@ -239,9 +295,7 @@ describe('FSCommand', function () {
|
|
|
239
295
|
return __generator(this, function (_a) {
|
|
240
296
|
switch (_a.label) {
|
|
241
297
|
case 0:
|
|
242
|
-
jest
|
|
243
|
-
.spyOn(extractHashArrayModule, 'extractHashArray')
|
|
244
|
-
.mockImplementation(function () { return [
|
|
298
|
+
jest.spyOn(FSModule, 'extractHashArray').mockImplementation(function () { return [
|
|
245
299
|
{
|
|
246
300
|
FILE_PATH: 'mocked-file',
|
|
247
301
|
FILE_HASH: 'hashOfMockedFile'
|
package/package.json
CHANGED
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@sasjs/adapter": "4.1.0",
|
|
54
54
|
"@sasjs/core": "4.45.4",
|
|
55
|
-
"@sasjs/lint": "2.
|
|
56
|
-
"@sasjs/utils": "2.51.
|
|
55
|
+
"@sasjs/lint": "2.1.2",
|
|
56
|
+
"@sasjs/utils": "2.51.5",
|
|
57
57
|
"adm-zip": "0.5.9",
|
|
58
58
|
"chalk": "4.1.2",
|
|
59
59
|
"csv-stringify": "5.6.5",
|
|
@@ -101,5 +101,5 @@
|
|
|
101
101
|
"typescript": "4.5.4",
|
|
102
102
|
"util": "0.12.4"
|
|
103
103
|
},
|
|
104
|
-
"version": "3.
|
|
104
|
+
"version": "3.24.0"
|
|
105
105
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const extractHashArray: (log: string) => any;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractHashArray = void 0;
|
|
4
|
-
var utils_1 = require("../../../utils");
|
|
5
|
-
var extractHashArray = function (log) {
|
|
6
|
-
if (log.includes('>>weboutBEGIN<<')) {
|
|
7
|
-
try {
|
|
8
|
-
var webout = log
|
|
9
|
-
.split(/>>weboutBEGIN<<\n/)[1]
|
|
10
|
-
.split(/>>weboutEND<<\n/)[0];
|
|
11
|
-
var jsonWebout = JSON.parse(webout);
|
|
12
|
-
return jsonWebout.hashes;
|
|
13
|
-
}
|
|
14
|
-
catch (err) {
|
|
15
|
-
(0, utils_1.displayError)(err, 'An error occurred while extracting hashes array from webout.');
|
|
16
|
-
throw new Error('An error occurred while extracting hashes array from webout.');
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
exports.extractHashArray = extractHashArray;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var extractHashArray_1 = require("../internal/extractHashArray");
|
|
4
|
-
var log = "\n>>weboutBEGIN<<\n{\n \"hashes\": [{\n \"FILE_HASH\": \"someCharacters\",\n \"FILE_PATH\": \"path/to/folder/file\"\n }]\n}\n>>weboutEND<<\n";
|
|
5
|
-
var logWithInvalidJsonInWebout = "\n>>weboutBEGIN<<\n{\n \"invalid Json\"\n}\n>>weboutEND<<\n";
|
|
6
|
-
describe('extractHashArray', function () {
|
|
7
|
-
it('should extract hashed array from webout', function () {
|
|
8
|
-
var hashes = (0, extractHashArray_1.extractHashArray)(log);
|
|
9
|
-
expect(hashes).toBeArrayOfSize(1);
|
|
10
|
-
});
|
|
11
|
-
it('should throw error when log does not contain webout', function () {
|
|
12
|
-
expect(function () { return (0, extractHashArray_1.extractHashArray)(logWithInvalidJsonInWebout); }).toThrow('An error occurred while extracting hashes array from webout.');
|
|
13
|
-
});
|
|
14
|
-
});
|