@sasjs/cli 6.5.0 → 6.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.
- package/README.md +2 -1
- package/build/commands/build/build.js +66 -29
- package/build/commands/build/spec/build.spec.js +31 -1
- package/build/commands/compile/compile.js +168 -33
- package/build/commands/compile/compileCommand.js +1 -1
- package/build/commands/compile/internal/checkCompileStatus.js +30 -11
- package/build/commands/compile/internal/compileFile.js +16 -7
- package/build/commands/compile/internal/compileManifest.d.ts +36 -0
- package/build/commands/compile/internal/compileManifest.js +610 -0
- package/build/commands/compile/internal/index.d.ts +2 -0
- package/build/commands/compile/internal/index.js +2 -0
- package/build/commands/compile/internal/passThrough.d.ts +12 -0
- package/build/commands/compile/internal/passThrough.js +17 -0
- package/build/commands/compile/internal/spec/compileTestFile.spec.js +9 -6
- package/build/commands/compile/spec/checkCompileStatus.spec.d.ts +1 -0
- package/build/commands/compile/spec/checkCompileStatus.spec.js +221 -0
- package/build/commands/compile/spec/compileCommand.spec.js +9 -2
- package/build/commands/compile/spec/compileManifest.spec.d.ts +1 -0
- package/build/commands/compile/spec/compileManifest.spec.js +401 -0
- package/build/commands/compile/spec/passThrough.spec.d.ts +1 -0
- package/build/commands/compile/spec/passThrough.spec.js +160 -0
- package/build/commands/deploy/spec/cbd.spec.js +11 -7
- package/build/commands/help/help.js +10 -0
- package/build/commands/index.d.ts +1 -0
- package/build/commands/index.js +3 -1
- package/build/commands/logcheck/collectLogs.d.ts +60 -0
- package/build/commands/logcheck/collectLogs.js +386 -0
- package/build/commands/logcheck/logCheckConfig.d.ts +72 -0
- package/build/commands/logcheck/logCheckConfig.js +283 -0
- package/build/commands/logcheck/logcheckCommand.d.ts +6 -0
- package/build/commands/logcheck/logcheckCommand.js +200 -0
- package/build/commands/logcheck/processLogCheck.d.ts +44 -0
- package/build/commands/logcheck/processLogCheck.js +242 -0
- package/build/commands/logcheck/renderLogCheck.d.ts +128 -0
- package/build/commands/logcheck/renderLogCheck.js +423 -0
- package/build/commands/logcheck/spec/collectLogs.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/collectLogs.spec.js +477 -0
- package/build/commands/logcheck/spec/logCheckConfig.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/logCheckConfig.spec.js +323 -0
- package/build/commands/logcheck/spec/logcheckCommand.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/logcheckCommand.spec.js +360 -0
- package/build/commands/logcheck/spec/processLogCheck.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/processLogCheck.spec.js +354 -0
- package/build/commands/logcheck/spec/renderLogCheck.spec.d.ts +1 -0
- package/build/commands/logcheck/spec/renderLogCheck.spec.js +426 -0
- package/build/commands/logcheck/types.d.ts +98 -0
- package/build/commands/logcheck/types.js +14 -0
- package/build/commands/testing/spec/testing.spec.js +8 -2
- package/build/types/command/commandAliases.js +1 -0
- package/build/types/command/commandFactory.js +2 -0
- package/build/types/command/returnCode.d.ts +2 -1
- package/build/types/command/returnCode.js +4 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[![npm package][npm-image]][npm-url]
|
|
4
4
|
[![Github Workflow][githubworkflow-image]][githubworkflow-url]
|
|
5
|
-
[]()
|
|
5
|
+
[](<>)
|
|
6
6
|

|
|
7
7
|
[](https://github.com/sasjs/cli/issues?q=is%3Aissue+is%3Aclosed)
|
|
8
8
|
[](https://github.com/sasjs/cli/issues)
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
- Optionally synchronise a local folder onto the server filesystem using `sasjs fs`
|
|
24
24
|
- Trigger Viya Jobs & Flows (`sasjs job execute` / `sasjs flow execute`)
|
|
25
25
|
- Enforce code quality rules with `sasjs lint`
|
|
26
|
+
- Check what SAS actually printed, and fail a pipeline on it, with `sasjs logcheck`
|
|
26
27
|
- Generate HTML5 documentation (requires doxygen) with `sasjs doc`
|
|
27
28
|
- Create and execute SAS tests (`sasjs test`)
|
|
28
29
|
|
|
@@ -46,6 +46,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
46
46
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
+
var __values = (this && this.__values) || function(o) {
|
|
50
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
51
|
+
if (m) return m.call(o);
|
|
52
|
+
if (o && typeof o.length === "number") return {
|
|
53
|
+
next: function () {
|
|
54
|
+
if (o && i >= o.length) o = void 0;
|
|
55
|
+
return { value: o && o[i++], done: !o };
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
59
|
+
};
|
|
49
60
|
var __read = (this && this.__read) || function (o, n) {
|
|
50
61
|
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
51
62
|
if (!m) return o;
|
|
@@ -71,17 +82,6 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
71
82
|
}
|
|
72
83
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
73
84
|
};
|
|
74
|
-
var __values = (this && this.__values) || function(o) {
|
|
75
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
76
|
-
if (m) return m.call(o);
|
|
77
|
-
if (o && typeof o.length === "number") return {
|
|
78
|
-
next: function () {
|
|
79
|
-
if (o && i >= o.length) o = void 0;
|
|
80
|
-
return { value: o && o[i++], done: !o };
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
84
|
-
};
|
|
85
85
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
86
86
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
87
87
|
};
|
|
@@ -96,7 +96,6 @@ var types_1 = require("@sasjs/utils/types");
|
|
|
96
96
|
var compressAndSave_1 = require("../../utils/compressAndSave");
|
|
97
97
|
var config_1 = require("../../utils/config");
|
|
98
98
|
var file_1 = require("../../utils/file");
|
|
99
|
-
var compile_1 = require("../compile/compile");
|
|
100
99
|
var internal_1 = require("../compile/internal");
|
|
101
100
|
var config_2 = require("./internal/config");
|
|
102
101
|
var getLaunchPageCode_1 = require("./internal/getLaunchPageCode");
|
|
@@ -124,28 +123,65 @@ function build(target) {
|
|
|
124
123
|
_a = !(_d.sent());
|
|
125
124
|
_d.label = 2;
|
|
126
125
|
case 2:
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
// build packages the build folder, it does not produce it: compiling here
|
|
127
|
+
// would make `build` and `bd` compile on a fresh clone, where the documented
|
|
128
|
+
// workflow is to run compile (or cbd) first and treat the build folder as the
|
|
129
|
+
// input - including when it has been adjusted by hand.
|
|
130
|
+
if (_a) {
|
|
131
|
+
throw new Error("The build folder ".concat(process.sasjsConstants.buildDestinationFolder, " does not exist.\n") +
|
|
132
|
+
"Run 'sasjs compile' (or 'sasjs cbd') first.");
|
|
133
|
+
}
|
|
134
|
+
return [4 /*yield*/, createFinalSasFiles(target)
|
|
135
|
+
// streamConfig.mockWeb opts the target into a static site that runs the same
|
|
136
|
+
// services in a browser. It is built from what compile just produced, so it
|
|
137
|
+
// is only meaningful after the tree above exists.
|
|
138
|
+
];
|
|
129
139
|
case 3:
|
|
130
140
|
_d.sent();
|
|
131
|
-
|
|
132
|
-
case 4: return [4 /*yield*/, createFinalSasFiles(target)
|
|
133
|
-
// streamConfig.mockWeb opts the target into a static site that runs the same
|
|
134
|
-
// services in a browser. It is built from what compile just produced, so it
|
|
135
|
-
// is only meaningful after the tree above exists.
|
|
136
|
-
];
|
|
137
|
-
case 5:
|
|
138
|
-
_d.sent();
|
|
139
|
-
if (!((_c = target.streamConfig) === null || _c === void 0 ? void 0 : _c.mockWeb)) return [3 /*break*/, 7];
|
|
141
|
+
if (!((_c = target.streamConfig) === null || _c === void 0 ? void 0 : _c.mockWeb)) return [3 /*break*/, 5];
|
|
140
142
|
return [4 /*yield*/, (0, mockSite_1.buildMockSite)(target)];
|
|
141
|
-
case
|
|
143
|
+
case 4:
|
|
142
144
|
_d.sent();
|
|
143
|
-
_d.label =
|
|
144
|
-
case
|
|
145
|
+
_d.label = 5;
|
|
146
|
+
case 5: return [2 /*return*/];
|
|
145
147
|
}
|
|
146
148
|
});
|
|
147
149
|
});
|
|
148
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Reports what the pack holds. A SASjs target can legitimately produce a pack
|
|
153
|
+
* with no SAS services at all - the services are stored programs for another
|
|
154
|
+
* runtime - and that is exactly the case where an unreported zero would look
|
|
155
|
+
* like a successful deploy.
|
|
156
|
+
*/
|
|
157
|
+
var logPackedFileCounts = function (tree) {
|
|
158
|
+
var _a;
|
|
159
|
+
var counts = { services: 0, files: 0 };
|
|
160
|
+
var walk = function (folder) {
|
|
161
|
+
var e_1, _a;
|
|
162
|
+
var _b;
|
|
163
|
+
try {
|
|
164
|
+
for (var _c = __values((_b = folder.members) !== null && _b !== void 0 ? _b : []), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
165
|
+
var member = _d.value;
|
|
166
|
+
if (member.type === types_1.MemberType.service)
|
|
167
|
+
counts.services++;
|
|
168
|
+
else if (member.type === types_1.MemberType.file)
|
|
169
|
+
counts.files++;
|
|
170
|
+
else
|
|
171
|
+
walk(member);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
175
|
+
finally {
|
|
176
|
+
try {
|
|
177
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
178
|
+
}
|
|
179
|
+
finally { if (e_1) throw e_1.error; }
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
walk(tree);
|
|
183
|
+
(_a = process.logger) === null || _a === void 0 ? void 0 : _a.info("Packing ".concat(counts.services, " SAS ").concat(counts.services === 1 ? 'service' : 'services', " and ").concat(counts.files, " ").concat(counts.files === 1 ? 'file' : 'files', "."));
|
|
184
|
+
};
|
|
149
185
|
function createFinalSasFiles(target) {
|
|
150
186
|
return __awaiter(this, void 0, void 0, function () {
|
|
151
187
|
var streamConfig, streamWeb, buildConfig, serverType, name, macroFolders, buildOutputFileName, buildDestinationFolder, finalSasFileContent, finalFilePath, finalFilePathJSON, finalFilePathZipped, buildInfo, buildInit, buildTerm, macroCorePath, dependencyFilePaths, dependenciesContent, _a, folderContent, folderContentJSON, servicePackSASjs, servicePack;
|
|
@@ -189,6 +225,7 @@ function createFinalSasFiles(target) {
|
|
|
189
225
|
return [4 /*yield*/, getFolderContent(serverType)];
|
|
190
226
|
case 8:
|
|
191
227
|
_a = _l.sent(), folderContent = _a.folderContent, folderContentJSON = _a.folderContentJSON;
|
|
228
|
+
logPackedFileCounts(folderContentJSON);
|
|
192
229
|
servicePackSASjs = {
|
|
193
230
|
appLoc: target.appLoc,
|
|
194
231
|
fileTree: folderContentJSON
|
|
@@ -549,7 +586,7 @@ function getBuildVars(target) {
|
|
|
549
586
|
});
|
|
550
587
|
}
|
|
551
588
|
var convertVarsToSasFormat = function (vars) {
|
|
552
|
-
var
|
|
589
|
+
var e_2, _a;
|
|
553
590
|
var entries = Object.entries(vars);
|
|
554
591
|
var varsContent = '\n';
|
|
555
592
|
try {
|
|
@@ -560,12 +597,12 @@ var convertVarsToSasFormat = function (vars) {
|
|
|
560
597
|
varsContent += "%let ".concat(name_1, "=").concat(chunkedString, ";\n");
|
|
561
598
|
}
|
|
562
599
|
}
|
|
563
|
-
catch (
|
|
600
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
564
601
|
finally {
|
|
565
602
|
try {
|
|
566
603
|
if (entries_1_1 && !entries_1_1.done && (_a = entries_1.return)) _a.call(entries_1);
|
|
567
604
|
}
|
|
568
|
-
finally { if (
|
|
605
|
+
finally { if (e_2) throw e_2.error; }
|
|
569
606
|
}
|
|
570
607
|
return varsContent;
|
|
571
608
|
};
|
|
@@ -72,8 +72,11 @@ describe('sasjs build', function () {
|
|
|
72
72
|
return [4 /*yield*/, (0, utils_2.findTargetInConfiguration)('viya')];
|
|
73
73
|
case 2:
|
|
74
74
|
target = (_a.sent()).target;
|
|
75
|
-
return [4 /*yield*/,
|
|
75
|
+
return [4 /*yield*/, (0, __1.compile)(target)];
|
|
76
76
|
case 3:
|
|
77
|
+
_a.sent();
|
|
78
|
+
return [4 /*yield*/, expect((0, build_1.build)(target)).toResolve()];
|
|
79
|
+
case 4:
|
|
77
80
|
_a.sent();
|
|
78
81
|
return [2 /*return*/];
|
|
79
82
|
}
|
|
@@ -101,6 +104,33 @@ describe('sasjs build', function () {
|
|
|
101
104
|
}
|
|
102
105
|
});
|
|
103
106
|
}); }, 2 * 60 * 1000);
|
|
107
|
+
it('reports a missing build folder instead of compiling one', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
108
|
+
var target, buildDestinationFolder;
|
|
109
|
+
return __generator(this, function (_a) {
|
|
110
|
+
switch (_a.label) {
|
|
111
|
+
case 0:
|
|
112
|
+
appName = "test-app-build-".concat((0, test_1.generateUniqueTimestamp)());
|
|
113
|
+
return [4 /*yield*/, (0, test_1.createTestApp)(__dirname, appName)];
|
|
114
|
+
case 1:
|
|
115
|
+
_a.sent();
|
|
116
|
+
return [4 /*yield*/, (0, utils_2.findTargetInConfiguration)('viya')];
|
|
117
|
+
case 2:
|
|
118
|
+
target = (_a.sent()).target;
|
|
119
|
+
buildDestinationFolder = process.sasjsConstants.buildDestinationFolder;
|
|
120
|
+
return [4 /*yield*/, (0, utils_1.folderExists)(buildDestinationFolder)];
|
|
121
|
+
case 3:
|
|
122
|
+
if (!_a.sent()) return [3 /*break*/, 5];
|
|
123
|
+
return [4 /*yield*/, (0, utils_1.deleteFolder)(buildDestinationFolder)];
|
|
124
|
+
case 4:
|
|
125
|
+
_a.sent();
|
|
126
|
+
_a.label = 5;
|
|
127
|
+
case 5: return [4 /*yield*/, expect((0, build_1.build)(target)).rejects.toThrow(/Run 'sasjs compile' \(or 'sasjs cbd'\) first/)];
|
|
128
|
+
case 6:
|
|
129
|
+
_a.sent();
|
|
130
|
+
return [2 /*return*/];
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}); }, 2 * 60 * 1000);
|
|
104
134
|
it("should compile and build remaining multiline comments", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
105
135
|
var beforeComment, afterComment, commentLine1, commentLine2, testContent, macroPath, _a, _b, target, finalSasFilePath, finalSasFile;
|
|
106
136
|
return __generator(this, function (_c) {
|
|
@@ -79,6 +79,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
79
79
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
80
80
|
}
|
|
81
81
|
};
|
|
82
|
+
var __values = (this && this.__values) || function(o) {
|
|
83
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
84
|
+
if (m) return m.call(o);
|
|
85
|
+
if (o && typeof o.length === "number") return {
|
|
86
|
+
next: function () {
|
|
87
|
+
if (o && i >= o.length) o = void 0;
|
|
88
|
+
return { value: o && o[i++], done: !o };
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
92
|
+
};
|
|
82
93
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
83
94
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
84
95
|
};
|
|
@@ -97,57 +108,67 @@ var compileModule = __importStar(require("./compile"));
|
|
|
97
108
|
var internal_1 = require("./internal");
|
|
98
109
|
function compile(target_1) {
|
|
99
110
|
return __awaiter(this, arguments, void 0, function (target, forceCompile) {
|
|
100
|
-
var result, compileTree, macroFolders, programFolders_1, buildMacroTestFolder_1, macroTestFiles;
|
|
111
|
+
var result, compileTree, _a, _b, macroFolders, programFolders_1, buildMacroTestFolder_1, macroTestFiles;
|
|
101
112
|
var _this = this;
|
|
102
|
-
var
|
|
113
|
+
var _c, _d, _e;
|
|
103
114
|
if (forceCompile === void 0) { forceCompile = false; }
|
|
104
|
-
return __generator(this, function (
|
|
105
|
-
switch (
|
|
115
|
+
return __generator(this, function (_f) {
|
|
116
|
+
switch (_f.label) {
|
|
106
117
|
case 0: return [4 /*yield*/, (0, internal_1.checkCompileStatus)(target, ['tests'])
|
|
107
118
|
// no need to compile again
|
|
108
119
|
];
|
|
109
120
|
case 1:
|
|
110
|
-
result =
|
|
121
|
+
result = _f.sent();
|
|
111
122
|
// no need to compile again
|
|
112
123
|
if (result.compiled && !forceCompile) {
|
|
113
|
-
(
|
|
114
|
-
(
|
|
124
|
+
(_c = process.logger) === null || _c === void 0 ? void 0 : _c.info('Skipping compilation.');
|
|
125
|
+
(_d = process.logger) === null || _d === void 0 ? void 0 : _d.info(result.message);
|
|
115
126
|
return [2 /*return*/];
|
|
116
127
|
}
|
|
128
|
+
if (!result.compiled)
|
|
129
|
+
(_e = process.logger) === null || _e === void 0 ? void 0 : _e.info("Compiling: ".concat(result.message));
|
|
117
130
|
return [4 /*yield*/, compileModule.copyFilesToBuildFolder(target).catch(function (error) {
|
|
118
131
|
var _a;
|
|
119
132
|
(_a = process.logger) === null || _a === void 0 ? void 0 : _a.error('Project compilation has failed.');
|
|
120
133
|
throw error;
|
|
121
134
|
})];
|
|
122
135
|
case 2:
|
|
123
|
-
|
|
136
|
+
_f.sent();
|
|
124
137
|
compileTree = (0, internal_1.getCompileTree)(target);
|
|
125
138
|
return [4 /*yield*/, compileModule.compileJobsServicesTests(target, compileTree)];
|
|
126
139
|
case 3:
|
|
127
|
-
|
|
128
|
-
|
|
140
|
+
_f.sent();
|
|
141
|
+
_a = internal_1.writeCompileManifest;
|
|
142
|
+
return [4 /*yield*/, (0, internal_1.getManifestFolders)(target)];
|
|
129
143
|
case 4:
|
|
130
|
-
|
|
131
|
-
|
|
144
|
+
_b = [_f.sent()];
|
|
145
|
+
return [4 /*yield*/, (0, internal_1.getManifestStamps)(target)];
|
|
146
|
+
case 5: return [4 /*yield*/, _a.apply(void 0, _b.concat([_f.sent()]))];
|
|
147
|
+
case 6:
|
|
148
|
+
_f.sent();
|
|
149
|
+
return [4 /*yield*/, (0, config_1.getMacroFolders)(target)];
|
|
150
|
+
case 7:
|
|
151
|
+
macroFolders = _f.sent();
|
|
152
|
+
if (!macroFolders.length) return [3 /*break*/, 14];
|
|
132
153
|
return [4 /*yield*/, (0, config_1.getProgramFolders)(target)];
|
|
133
|
-
case
|
|
134
|
-
programFolders_1 =
|
|
154
|
+
case 8:
|
|
155
|
+
programFolders_1 = _f.sent();
|
|
135
156
|
return [4 /*yield*/, (0, utils_1.asyncForEach)(macroFolders, function (macroFolder) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
136
157
|
switch (_a.label) {
|
|
137
158
|
case 0: return [4 /*yield*/, (0, internal_1.copyTestMacroFiles)(macroFolder)];
|
|
138
159
|
case 1: return [2 /*return*/, _a.sent()];
|
|
139
160
|
}
|
|
140
161
|
}); }); })];
|
|
141
|
-
case
|
|
142
|
-
|
|
162
|
+
case 9:
|
|
163
|
+
_f.sent();
|
|
143
164
|
buildMacroTestFolder_1 = path_1.default.join(process.sasjsConstants.buildDestinationTestFolder, 'macros');
|
|
144
165
|
return [4 /*yield*/, (0, utils_1.folderExists)(buildMacroTestFolder_1)];
|
|
145
|
-
case
|
|
146
|
-
if (!
|
|
166
|
+
case 10:
|
|
167
|
+
if (!_f.sent()) return [3 /*break*/, 14];
|
|
147
168
|
return [4 /*yield*/, (0, utils_1.listFilesAndSubFoldersInFolder)(buildMacroTestFolder_1)];
|
|
148
|
-
case
|
|
149
|
-
case
|
|
150
|
-
macroTestFiles =
|
|
169
|
+
case 11: return [4 /*yield*/, (_f.sent()).filter(file_1.isSasFile)];
|
|
170
|
+
case 12:
|
|
171
|
+
macroTestFiles = _f.sent();
|
|
151
172
|
return [4 /*yield*/, (0, utils_1.asyncForEach)(macroTestFiles, function (macroTestFile) { return __awaiter(_this, void 0, void 0, function () {
|
|
152
173
|
return __generator(this, function (_a) {
|
|
153
174
|
switch (_a.label) {
|
|
@@ -156,21 +177,24 @@ function compile(target_1) {
|
|
|
156
177
|
}
|
|
157
178
|
});
|
|
158
179
|
}); })];
|
|
159
|
-
case 10:
|
|
160
|
-
_c.sent();
|
|
161
|
-
_c.label = 11;
|
|
162
|
-
case 11: return [4 /*yield*/, compileTree.saveTree()];
|
|
163
|
-
case 12:
|
|
164
|
-
_c.sent();
|
|
165
|
-
return [4 /*yield*/, (0, internal_1.compileTestFlow)(target).catch(function (err) { var _a; return (_a = process.logger) === null || _a === void 0 ? void 0 : _a.error('Test flow compilation has failed.'); })];
|
|
166
180
|
case 13:
|
|
167
|
-
|
|
181
|
+
_f.sent();
|
|
182
|
+
_f.label = 14;
|
|
183
|
+
case 14: return [4 /*yield*/, compileTree.saveTree()];
|
|
184
|
+
case 15:
|
|
185
|
+
_f.sent();
|
|
186
|
+
return [4 /*yield*/, (0, internal_1.compileTestFlow)(target).catch(function (err) { var _a; return (_a = process.logger) === null || _a === void 0 ? void 0 : _a.error('Test flow compilation has failed.'); })];
|
|
187
|
+
case 16:
|
|
188
|
+
_f.sent();
|
|
168
189
|
return [4 /*yield*/, compileWeb(target)];
|
|
169
|
-
case
|
|
170
|
-
|
|
190
|
+
case 17:
|
|
191
|
+
_f.sent();
|
|
171
192
|
return [4 /*yield*/, syncFolder(target)];
|
|
172
|
-
case
|
|
173
|
-
|
|
193
|
+
case 18:
|
|
194
|
+
_f.sent();
|
|
195
|
+
return [4 /*yield*/, logCopiedFileCounts()];
|
|
196
|
+
case 19:
|
|
197
|
+
_f.sent();
|
|
174
198
|
return [2 /*return*/];
|
|
175
199
|
}
|
|
176
200
|
});
|
|
@@ -316,6 +340,117 @@ function compileJobsServicesTests(target, compileTree) {
|
|
|
316
340
|
});
|
|
317
341
|
});
|
|
318
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Reports what the build folder holds, SAS and otherwise.
|
|
345
|
+
*
|
|
346
|
+
* A JS-only services folder is a legitimate shape for a SASjs server, and it is
|
|
347
|
+
* also the shape where a silent "compiled" would hide an empty build - the
|
|
348
|
+
* counts make the difference between "0 and 45" and "nothing happened" visible.
|
|
349
|
+
*/
|
|
350
|
+
var logCopiedFileCounts = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
351
|
+
var _a, buildDestinationServicesFolder, buildDestinationJobsFolder, countFiles, services, jobs, sas, runtime, runtimeNote;
|
|
352
|
+
var _b;
|
|
353
|
+
return __generator(this, function (_c) {
|
|
354
|
+
switch (_c.label) {
|
|
355
|
+
case 0:
|
|
356
|
+
_a = process.sasjsConstants, buildDestinationServicesFolder = _a.buildDestinationServicesFolder, buildDestinationJobsFolder = _a.buildDestinationJobsFolder;
|
|
357
|
+
countFiles = function (folder) { return __awaiter(void 0, void 0, void 0, function () {
|
|
358
|
+
var counts, walk;
|
|
359
|
+
return __generator(this, function (_a) {
|
|
360
|
+
switch (_a.label) {
|
|
361
|
+
case 0:
|
|
362
|
+
counts = { sas: 0, runtime: 0 };
|
|
363
|
+
return [4 /*yield*/, (0, utils_1.folderExists)(folder)];
|
|
364
|
+
case 1:
|
|
365
|
+
if (!(_a.sent()))
|
|
366
|
+
return [2 /*return*/, counts];
|
|
367
|
+
walk = function (dir) { return __awaiter(void 0, void 0, void 0, function () {
|
|
368
|
+
var _a, _b, fileName, e_1_1, _c, _d, subFolder, e_2_1;
|
|
369
|
+
var e_1, _e, e_2, _f;
|
|
370
|
+
return __generator(this, function (_g) {
|
|
371
|
+
switch (_g.label) {
|
|
372
|
+
case 0:
|
|
373
|
+
_g.trys.push([0, 5, 6, 7]);
|
|
374
|
+
return [4 /*yield*/, (0, utils_1.listFilesInFolder)(dir)];
|
|
375
|
+
case 1:
|
|
376
|
+
_a = __values.apply(void 0, [_g.sent()]), _b = _a.next();
|
|
377
|
+
_g.label = 2;
|
|
378
|
+
case 2:
|
|
379
|
+
if (!!_b.done) return [3 /*break*/, 4];
|
|
380
|
+
fileName = _b.value;
|
|
381
|
+
if ((0, file_1.isSasFile)(fileName))
|
|
382
|
+
counts.sas++;
|
|
383
|
+
else
|
|
384
|
+
counts.runtime++;
|
|
385
|
+
_g.label = 3;
|
|
386
|
+
case 3:
|
|
387
|
+
_b = _a.next();
|
|
388
|
+
return [3 /*break*/, 2];
|
|
389
|
+
case 4: return [3 /*break*/, 7];
|
|
390
|
+
case 5:
|
|
391
|
+
e_1_1 = _g.sent();
|
|
392
|
+
e_1 = { error: e_1_1 };
|
|
393
|
+
return [3 /*break*/, 7];
|
|
394
|
+
case 6:
|
|
395
|
+
try {
|
|
396
|
+
if (_b && !_b.done && (_e = _a.return)) _e.call(_a);
|
|
397
|
+
}
|
|
398
|
+
finally { if (e_1) throw e_1.error; }
|
|
399
|
+
return [7 /*endfinally*/];
|
|
400
|
+
case 7:
|
|
401
|
+
_g.trys.push([7, 13, 14, 15]);
|
|
402
|
+
return [4 /*yield*/, (0, utils_1.listSubFoldersInFolder)(dir)];
|
|
403
|
+
case 8:
|
|
404
|
+
_c = __values.apply(void 0, [_g.sent()]), _d = _c.next();
|
|
405
|
+
_g.label = 9;
|
|
406
|
+
case 9:
|
|
407
|
+
if (!!_d.done) return [3 /*break*/, 12];
|
|
408
|
+
subFolder = _d.value;
|
|
409
|
+
return [4 /*yield*/, walk(path_1.default.join(dir, subFolder))];
|
|
410
|
+
case 10:
|
|
411
|
+
_g.sent();
|
|
412
|
+
_g.label = 11;
|
|
413
|
+
case 11:
|
|
414
|
+
_d = _c.next();
|
|
415
|
+
return [3 /*break*/, 9];
|
|
416
|
+
case 12: return [3 /*break*/, 15];
|
|
417
|
+
case 13:
|
|
418
|
+
e_2_1 = _g.sent();
|
|
419
|
+
e_2 = { error: e_2_1 };
|
|
420
|
+
return [3 /*break*/, 15];
|
|
421
|
+
case 14:
|
|
422
|
+
try {
|
|
423
|
+
if (_d && !_d.done && (_f = _c.return)) _f.call(_c);
|
|
424
|
+
}
|
|
425
|
+
finally { if (e_2) throw e_2.error; }
|
|
426
|
+
return [7 /*endfinally*/];
|
|
427
|
+
case 15: return [2 /*return*/];
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}); };
|
|
431
|
+
return [4 /*yield*/, walk(folder)];
|
|
432
|
+
case 2:
|
|
433
|
+
_a.sent();
|
|
434
|
+
return [2 /*return*/, counts];
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}); };
|
|
438
|
+
return [4 /*yield*/, countFiles(buildDestinationServicesFolder)];
|
|
439
|
+
case 1:
|
|
440
|
+
services = _c.sent();
|
|
441
|
+
return [4 /*yield*/, countFiles(buildDestinationJobsFolder)];
|
|
442
|
+
case 2:
|
|
443
|
+
jobs = _c.sent();
|
|
444
|
+
sas = services.sas + jobs.sas;
|
|
445
|
+
runtime = services.runtime + jobs.runtime;
|
|
446
|
+
runtimeNote = runtime === 0
|
|
447
|
+
? ''
|
|
448
|
+
: "; ".concat(runtime, " ").concat(runtime === 1 ? 'file' : 'files', " copied through unchanged (not SAS programs)");
|
|
449
|
+
(_b = process.logger) === null || _b === void 0 ? void 0 : _b.info("Compiled ".concat(sas, " SAS ").concat(sas === 1 ? 'file' : 'files').concat(runtimeNote, "."));
|
|
450
|
+
return [2 /*return*/];
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
}); };
|
|
319
454
|
function recreateBuildFolder() {
|
|
320
455
|
return __awaiter(this, void 0, void 0, function () {
|
|
321
456
|
var buildDestinationFolder, pathExists;
|
|
@@ -152,7 +152,7 @@ var CompileCommand = /** @class */ (function (_super) {
|
|
|
152
152
|
case 1:
|
|
153
153
|
target = (_a.sent()).target;
|
|
154
154
|
buildDestinationFolder = process.sasjsConstants.buildDestinationFolder;
|
|
155
|
-
return [4 /*yield*/, (0, compile_1.compile)(target
|
|
155
|
+
return [4 /*yield*/, (0, compile_1.compile)(target)
|
|
156
156
|
.then(function () {
|
|
157
157
|
var _a;
|
|
158
158
|
(_a = process.logger) === null || _a === void 0 ? void 0 : _a.success("The project was successfully compiled for ".concat(target.serverType, " using target '").concat(target.name, "'\nThe compile output is located in the ").concat(buildDestinationFolder, " directory."));
|
|
@@ -41,14 +41,14 @@ var utils_1 = require("@sasjs/utils");
|
|
|
41
41
|
var _1 = require("./");
|
|
42
42
|
function checkCompileStatus(target, exceptions) {
|
|
43
43
|
return __awaiter(this, void 0, void 0, function () {
|
|
44
|
-
var buildDestinationFolder, pathExists, _a, areServiceFoldersMatching, serviceReasons, _b, areJobFoldersMatching, jobReasons,
|
|
45
|
-
return __generator(this, function (
|
|
46
|
-
switch (
|
|
44
|
+
var buildDestinationFolder, pathExists, _a, areServiceFoldersMatching, serviceReasons, _b, areJobFoldersMatching, jobReasons, reasons, changedFiles, _c, _d;
|
|
45
|
+
return __generator(this, function (_e) {
|
|
46
|
+
switch (_e.label) {
|
|
47
47
|
case 0:
|
|
48
48
|
buildDestinationFolder = process.sasjsConstants.buildDestinationFolder;
|
|
49
49
|
return [4 /*yield*/, (0, utils_1.folderExists)(buildDestinationFolder)];
|
|
50
50
|
case 1:
|
|
51
|
-
pathExists =
|
|
51
|
+
pathExists = _e.sent();
|
|
52
52
|
if (!pathExists) {
|
|
53
53
|
return [2 /*return*/, {
|
|
54
54
|
compiled: false,
|
|
@@ -57,16 +57,35 @@ function checkCompileStatus(target, exceptions) {
|
|
|
57
57
|
}
|
|
58
58
|
return [4 /*yield*/, checkServiceFolders(target, exceptions)];
|
|
59
59
|
case 2:
|
|
60
|
-
_a =
|
|
60
|
+
_a = _e.sent(), areServiceFoldersMatching = _a.areServiceFoldersMatching, serviceReasons = _a.reasons;
|
|
61
61
|
return [4 /*yield*/, checkJobFolders(target, exceptions)];
|
|
62
62
|
case 3:
|
|
63
|
-
_b =
|
|
64
|
-
|
|
63
|
+
_b = _e.sent(), areJobFoldersMatching = _b.areJobFoldersMatching, jobReasons = _b.reasons;
|
|
64
|
+
if (!areServiceFoldersMatching || !areJobFoldersMatching) {
|
|
65
|
+
reasons = [];
|
|
66
|
+
if (!areServiceFoldersMatching)
|
|
67
|
+
reasons.push("Missing Services: ".concat(serviceReasons.join(', ')));
|
|
68
|
+
if (!areJobFoldersMatching)
|
|
69
|
+
reasons.push("Missing jobs: ".concat(jobReasons.join(', ')));
|
|
70
|
+
return [2 /*return*/, { compiled: false, message: reasons.join('\n') }];
|
|
71
|
+
}
|
|
72
|
+
_c = _1.getChangedFiles;
|
|
73
|
+
return [4 /*yield*/, (0, _1.getManifestFolders)(target)];
|
|
74
|
+
case 4:
|
|
75
|
+
_d = [_e.sent()];
|
|
76
|
+
return [4 /*yield*/, (0, _1.getManifestStamps)(target)];
|
|
77
|
+
case 5: return [4 /*yield*/, _c.apply(void 0, _d.concat([_e.sent()]))];
|
|
78
|
+
case 6:
|
|
79
|
+
changedFiles = _e.sent();
|
|
80
|
+
if (changedFiles.length) {
|
|
81
|
+
return [2 /*return*/, {
|
|
82
|
+
compiled: false,
|
|
83
|
+
message: "Changed since the last compile: ".concat(changedFiles.join(', '))
|
|
84
|
+
}];
|
|
85
|
+
}
|
|
65
86
|
return [2 /*return*/, {
|
|
66
|
-
compiled:
|
|
67
|
-
message:
|
|
68
|
-
? 'All services and jobs are already present.'
|
|
69
|
-
: "Missing Services: ".concat(serviceReasons.join(', '), "\nMissing jobs: ").concat(jobReasons.join(', '))
|
|
87
|
+
compiled: true,
|
|
88
|
+
message: 'All services and jobs are already present and up to date.'
|
|
70
89
|
}];
|
|
71
90
|
}
|
|
72
91
|
});
|
|
@@ -58,14 +58,23 @@ var path_1 = __importDefault(require("path"));
|
|
|
58
58
|
function compileFile(target_1, filePath_1, macroFolders_1, programFolders_1) {
|
|
59
59
|
return __awaiter(this, arguments, void 0, function (target, filePath, macroFolders, programFolders, programVar, compileTree, fileType, sourceFolder) {
|
|
60
60
|
var dependencies;
|
|
61
|
+
var _a;
|
|
61
62
|
if (programVar === void 0) { programVar = ''; }
|
|
62
|
-
return __generator(this, function (
|
|
63
|
-
switch (
|
|
64
|
-
case 0:
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
return __generator(this, function (_b) {
|
|
64
|
+
switch (_b.label) {
|
|
65
|
+
case 0:
|
|
66
|
+
// Only SAS programs are compiled. Anything else - a `.js` stored program, a
|
|
67
|
+
// web asset, a file a deploy script reads - is already in the build folder
|
|
68
|
+
// from the folder copy, and parsing it as SAS would corrupt it.
|
|
69
|
+
if ((0, _1.shouldPassThrough)(path_1.default.basename(filePath))) {
|
|
70
|
+
(_a = process.logger) === null || _a === void 0 ? void 0 : _a.info("Copying ".concat(path_1.default.basename(filePath), " to the build folder unchanged - it is not a SAS program."));
|
|
71
|
+
return [2 /*return*/];
|
|
72
|
+
}
|
|
73
|
+
return [4 /*yield*/, (0, _1.loadDependencies)(target, sourceFolder
|
|
74
|
+
? path_1.default.join(sourceFolder, filePath.split(path_1.default.sep).pop())
|
|
75
|
+
: filePath, macroFolders, programFolders, (0, utils_1.isTestFile)(filePath) ? types_1.SASJsFileType.test : fileType, compileTree)];
|
|
67
76
|
case 1:
|
|
68
|
-
dependencies =
|
|
77
|
+
dependencies = _b.sent();
|
|
69
78
|
if (fileType === types_1.SASJsFileType.service) {
|
|
70
79
|
dependencies = "".concat(programVar, "\n").concat(dependencies);
|
|
71
80
|
}
|
|
@@ -74,7 +83,7 @@ function compileFile(target_1, filePath_1, macroFolders_1, programFolders_1) {
|
|
|
74
83
|
}
|
|
75
84
|
return [4 /*yield*/, (0, utils_1.createFile)(filePath, dependencies)];
|
|
76
85
|
case 2:
|
|
77
|
-
|
|
86
|
+
_b.sent();
|
|
78
87
|
return [2 /*return*/];
|
|
79
88
|
}
|
|
80
89
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Target } from '@sasjs/utils';
|
|
2
|
+
/**
|
|
3
|
+
* Hashes of the source files the last compile read, keyed by absolute path.
|
|
4
|
+
*
|
|
5
|
+
* The build folder cannot be used as the record of what was compiled: `compile`
|
|
6
|
+
* transforms the files it writes (macros and includes are inlined), so a
|
|
7
|
+
* compiled service never matches its source byte for byte. Comparing content
|
|
8
|
+
* hashes against a manifest written at the end of a successful compile is what
|
|
9
|
+
* makes "the source changed" detectable without the reader passing a force flag.
|
|
10
|
+
*/
|
|
11
|
+
export type CompileManifest = Record<string, string>;
|
|
12
|
+
export declare const getManifestPath: () => string;
|
|
13
|
+
export declare const writeCompileManifest: (folders: string[], stampFiles?: string[]) => Promise<void>;
|
|
14
|
+
export declare const readCompileManifest: () => Promise<CompileManifest | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Names the source files that have changed since the last successful compile:
|
|
17
|
+
* edited content, new files, and files the manifest has never seen.
|
|
18
|
+
*/
|
|
19
|
+
export declare const getChangedFiles: (folders: string[], stampFiles?: string[]) => Promise<string[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Every folder whose contents feed the build: the services and jobs, plus the
|
|
22
|
+
* web app and the sync folder when the target uses them. A skip is only safe if
|
|
23
|
+
* it accounts for all of them - a frontend change with an unchanged services
|
|
24
|
+
* folder must still rebuild.
|
|
25
|
+
*/
|
|
26
|
+
export declare const getManifestFolders: (target: Target) => Promise<string[]>;
|
|
27
|
+
/**
|
|
28
|
+
* Individual files whose change invalidates the whole build.
|
|
29
|
+
*
|
|
30
|
+
* The test programs are not inside a service folder, and the dependency
|
|
31
|
+
* manifests are the record of which @sasjs/core a build used: a core bump
|
|
32
|
+
* arrives as an install, so the version in `node_modules/@sasjs/core` and the
|
|
33
|
+
* lockfile are the signals - walking every macro of the library would cost
|
|
34
|
+
* more than it catches.
|
|
35
|
+
*/
|
|
36
|
+
export declare const getManifestStamps: (target: Target) => Promise<string[]>;
|