@sasjs/cli 6.29.0 → 6.30.1
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/build/internal/mockSite/assets/boot.js +23 -1
- package/build/commands/build/internal/mockSite/assets/persist.js +76 -5
- package/build/commands/build/internal/mockSite/assets/runtime-core.js +413 -50
- package/build/commands/build/internal/mockSite/assets/sw.js +182 -12
- package/build/commands/build/internal/mockSite/mockSite.d.ts +23 -0
- package/build/commands/build/internal/mockSite/mockSite.js +245 -29
- package/build/commands/build/internal/mockSite/spec/boot.spec.js +50 -3
- package/build/commands/build/internal/mockSite/spec/mockSite.spec.js +132 -3
- package/build/commands/build/internal/mockSite/spec/persist.spec.js +179 -1
- package/build/commands/build/internal/mockSite/spec/runtime-core.spec.js +546 -0
- package/build/commands/build/internal/mockSite/spec/sw.spec.js +587 -4
- package/build/commands/create/spec/create.spec.js +22 -18
- package/build/commands/deploy/spec/cbd.spec.js +149 -75
- package/build/utils/test.d.ts +12 -0
- package/build/utils/test.js +66 -1
- package/build/utils/utils.d.ts +8 -0
- package/build/utils/utils.js +16 -4
- package/package.json +2 -2
- package/build/commands/create/spec/angularAppFiles.d.ts +0 -2
- package/build/commands/create/spec/angularAppFiles.js +0 -117
- package/build/commands/create/spec/minimalAppFiles.d.ts +0 -2
- package/build/commands/create/spec/minimalAppFiles.js +0 -44
- package/build/commands/create/spec/reactAppFiles.d.ts +0 -2
- package/build/commands/create/spec/reactAppFiles.js +0 -93
|
@@ -44,11 +44,9 @@ var path_1 = __importDefault(require("path"));
|
|
|
44
44
|
var test_1 = require("../../../utils/test");
|
|
45
45
|
var utils_1 = require("@sasjs/utils");
|
|
46
46
|
var config_1 = require("../../../utils/config");
|
|
47
|
-
var minimalAppFiles_1 = require("./minimalAppFiles");
|
|
48
|
-
var reactAppFiles_1 = require("./reactAppFiles");
|
|
49
|
-
var angularAppFiles_1 = require("./angularAppFiles");
|
|
50
47
|
var create_1 = require("../create");
|
|
51
48
|
var utils_2 = require("../../../utils");
|
|
49
|
+
var utils_3 = require("../../../utils/utils");
|
|
52
50
|
describe('sasjs create', function () {
|
|
53
51
|
beforeAll(function () {
|
|
54
52
|
dotenv_1.default.config();
|
|
@@ -249,28 +247,34 @@ describe('sasjs create', function () {
|
|
|
249
247
|
}); });
|
|
250
248
|
});
|
|
251
249
|
var verifyCreateWeb = function (appName, appType) { return __awaiter(void 0, void 0, void 0, function () {
|
|
252
|
-
var
|
|
250
|
+
var template, docsCandidates, present;
|
|
253
251
|
return __generator(this, function (_a) {
|
|
254
252
|
switch (_a.label) {
|
|
255
|
-
case 0:
|
|
256
|
-
fileStructure = appType === 'minimal'
|
|
257
|
-
? minimalAppFiles_1.minimalAppFiles
|
|
258
|
-
: appType === 'react'
|
|
259
|
-
? reactAppFiles_1.reactAppFiles
|
|
260
|
-
: appType === 'angular'
|
|
261
|
-
? angularAppFiles_1.angularAppFiles
|
|
262
|
-
: minimalAppFiles_1.minimalAppFiles;
|
|
263
|
-
fileStructure.folderName = appName;
|
|
264
|
-
return [4 /*yield*/, (0, test_1.verifyFolder)(fileStructure)];
|
|
253
|
+
case 0: return [4 /*yield*/, (0, test_1.getTemplateFileTree)(utils_3.seedAppUrls[appType])];
|
|
265
254
|
case 1:
|
|
255
|
+
template = _a.sent();
|
|
256
|
+
template.folderName = appName;
|
|
257
|
+
return [4 /*yield*/, (0, test_1.verifyFolder)(template)];
|
|
258
|
+
case 2:
|
|
266
259
|
_a.sent();
|
|
267
260
|
return [4 /*yield*/, (0, test_1.verifyPackageJsonContent)(appName)
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
//
|
|
261
|
+
// The docs are a submodule fetched after the archive, and the archive carries
|
|
262
|
+
// the folder empty - so the derived tree can only assert that the folder is
|
|
263
|
+
// there. A create whose docs download silently failed used to pass; assert
|
|
264
|
+
// the site itself arrived. Every template gets the docs (create routes all
|
|
265
|
+
// three through a create*App that passes the docs URL), and the path differs:
|
|
266
|
+
// react keeps them under `public`, the others at the root.
|
|
271
267
|
];
|
|
272
|
-
case
|
|
268
|
+
case 3:
|
|
273
269
|
_a.sent();
|
|
270
|
+
docsCandidates = [
|
|
271
|
+
path_1.default.join(process.projectDir, appName, 'public', 'docs', 'index.html'),
|
|
272
|
+
path_1.default.join(process.projectDir, appName, 'docs', 'index.html')
|
|
273
|
+
];
|
|
274
|
+
return [4 /*yield*/, Promise.all(docsCandidates.map(function (candidate) { return (0, utils_1.fileExists)(candidate); }))];
|
|
275
|
+
case 4:
|
|
276
|
+
present = _a.sent();
|
|
277
|
+
expect(present.some(Boolean)).toEqual(true);
|
|
274
278
|
// A seed app carries its dependencies in the template's package.json, so the
|
|
275
279
|
// command create issues for it is a plain install - the same trade as above:
|
|
276
280
|
// the stub writes what npm would, and this asserts the CLI asked for it.
|
|
@@ -68,10 +68,38 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
68
68
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
69
69
|
}
|
|
70
70
|
};
|
|
71
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
72
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
73
|
+
if (!m) return o;
|
|
74
|
+
var i = m.call(o), r, ar = [], e;
|
|
75
|
+
try {
|
|
76
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
77
|
+
}
|
|
78
|
+
catch (error) { e = { error: error }; }
|
|
79
|
+
finally {
|
|
80
|
+
try {
|
|
81
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
82
|
+
}
|
|
83
|
+
finally { if (e) throw e.error; }
|
|
84
|
+
}
|
|
85
|
+
return ar;
|
|
86
|
+
};
|
|
87
|
+
var __values = (this && this.__values) || function(o) {
|
|
88
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
89
|
+
if (m) return m.call(o);
|
|
90
|
+
if (o && typeof o.length === "number") return {
|
|
91
|
+
next: function () {
|
|
92
|
+
if (o && i >= o.length) o = void 0;
|
|
93
|
+
return { value: o && o[i++], done: !o };
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
97
|
+
};
|
|
71
98
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
72
99
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
73
100
|
};
|
|
74
101
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102
|
+
var fs_1 = __importDefault(require("fs"));
|
|
75
103
|
var path_1 = __importDefault(require("path"));
|
|
76
104
|
var node_1 = require("@sasjs/adapter/node");
|
|
77
105
|
var js_base64_1 = require("js-base64");
|
|
@@ -85,6 +113,13 @@ var compile_1 = require("../../compile/compile");
|
|
|
85
113
|
var deploy_1 = require("../deploy");
|
|
86
114
|
var utils_2 = require("./utils");
|
|
87
115
|
var config_1 = require("../../../utils/config");
|
|
116
|
+
/** Every file under a folder, recursively, as absolute paths. */
|
|
117
|
+
var listFiles = function (folderPath) {
|
|
118
|
+
return fs_1.default.readdirSync(folderPath, { withFileTypes: true }).flatMap(function (entry) {
|
|
119
|
+
var entryPath = path_1.default.join(folderPath, entry.name);
|
|
120
|
+
return entry.isDirectory() ? listFiles(entryPath) : [entryPath];
|
|
121
|
+
});
|
|
122
|
+
};
|
|
88
123
|
describe('sasjs cbd with server type SASJS', function () {
|
|
89
124
|
var target;
|
|
90
125
|
var appName;
|
|
@@ -115,9 +150,10 @@ describe('sasjs cbd with server type SASJS', function () {
|
|
|
115
150
|
});
|
|
116
151
|
}); });
|
|
117
152
|
it("should deploy compile and build to sasjs/server", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
118
|
-
var deployMock, _a, customTarget, macroCorePath, mf_getuser, _b, mp_jsonout, ms_webout, webout,
|
|
119
|
-
|
|
120
|
-
|
|
153
|
+
var deployMock, _a, customTarget, macroCorePath, mf_getuser, _b, mp_jsonout, ms_webout, webout, depsInserts, getCode, _c, payload, deployed, indexMembers, projectRoot, mocksRoot, mockFiles, mockFiles_1, mockFiles_1_1, filePath, relative, _d, _e, _f, e_1_1, serviceFiles, serviceFiles_1, serviceFiles_1_1, filePath, name_1, contents, member, e_2_1;
|
|
154
|
+
var e_1, _g, _h, e_2, _j;
|
|
155
|
+
return __generator(this, function (_k) {
|
|
156
|
+
switch (_k.label) {
|
|
121
157
|
case 0:
|
|
122
158
|
jest.spyOn(fileModule, 'fileExists').mockImplementation(function (filePath) {
|
|
123
159
|
if (filePath.endsWith('.zip'))
|
|
@@ -141,7 +177,7 @@ describe('sasjs cbd with server type SASJS', function () {
|
|
|
141
177
|
}
|
|
142
178
|
})];
|
|
143
179
|
case 1:
|
|
144
|
-
|
|
180
|
+
_k.sent();
|
|
145
181
|
return [4 /*yield*/, (0, utils_2.updateLocalTarget)(target.name, {
|
|
146
182
|
jobConfig: undefined,
|
|
147
183
|
serviceConfig: undefined,
|
|
@@ -151,101 +187,139 @@ describe('sasjs cbd with server type SASJS', function () {
|
|
|
151
187
|
}
|
|
152
188
|
})];
|
|
153
189
|
case 2:
|
|
154
|
-
|
|
190
|
+
_k.sent();
|
|
155
191
|
_a = process;
|
|
156
192
|
return [4 /*yield*/, (0, config_1.getLocalConfig)()];
|
|
157
193
|
case 3:
|
|
158
|
-
_a.sasjsConfig =
|
|
194
|
+
_a.sasjsConfig = _k.sent();
|
|
159
195
|
return [4 /*yield*/, (0, config_1.findTargetInConfiguration)(target.name, types_1.TargetScope.Local)];
|
|
160
196
|
case 4:
|
|
161
|
-
customTarget = (
|
|
197
|
+
customTarget = (_k.sent()).target;
|
|
162
198
|
return [4 /*yield*/, (0, compile_1.compile)(customTarget)];
|
|
163
199
|
case 5:
|
|
164
|
-
|
|
200
|
+
_k.sent();
|
|
165
201
|
return [4 /*yield*/, expect((0, build_1.build)(customTarget)).toResolve()];
|
|
166
202
|
case 6:
|
|
167
|
-
|
|
203
|
+
_k.sent();
|
|
168
204
|
return [4 /*yield*/, (0, deploy_1.deploy)(customTarget, true)];
|
|
169
205
|
case 7:
|
|
170
|
-
|
|
206
|
+
_k.sent();
|
|
171
207
|
macroCorePath = process.sasjsConstants.macroCorePath;
|
|
172
208
|
_b = utils_1.removeHeader;
|
|
173
209
|
return [4 /*yield*/, (0, utils_1.readFile)("".concat(macroCorePath, "/base/mf_getuser.sas"))];
|
|
174
210
|
case 8:
|
|
175
|
-
mf_getuser = _b.apply(void 0, [
|
|
211
|
+
mf_getuser = _b.apply(void 0, [_k.sent()]);
|
|
176
212
|
return [4 /*yield*/, (0, utils_1.readFile)("".concat(macroCorePath, "/base/mp_jsonout.sas"))];
|
|
177
213
|
case 9:
|
|
178
|
-
mp_jsonout =
|
|
214
|
+
mp_jsonout = _k.sent();
|
|
179
215
|
return [4 /*yield*/, (0, utils_1.readFile)("".concat(macroCorePath, "/server/ms_webout.sas"))];
|
|
180
216
|
case 10:
|
|
181
|
-
ms_webout =
|
|
217
|
+
ms_webout = _k.sent();
|
|
182
218
|
webout = "%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO,maxobs=MAX);\n %ms_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt\n ,missing=&missing\n ,showmeta=&showmeta\n ,maxobs=&maxobs\n )\n%mend;\n";
|
|
183
|
-
mocksPath = path_1.default.join(__dirname, appName, 'sasjs', 'mocks');
|
|
184
|
-
appinitJSPath = path_1.default.join(mocksPath, 'services', 'common', 'appinit.js');
|
|
185
|
-
getdataJSPath = path_1.default.join(mocksPath, 'services', 'common', 'getdata.js');
|
|
186
|
-
springsJSONPath = path_1.default.join(mocksPath, 'services', 'common', 'springs.json');
|
|
187
|
-
return [4 /*yield*/, (0, utils_1.readFile)(appinitJSPath)];
|
|
188
|
-
case 11:
|
|
189
|
-
appinitJSContents = _c.sent();
|
|
190
|
-
return [4 /*yield*/, (0, utils_1.readFile)(getdataJSPath)];
|
|
191
|
-
case 12:
|
|
192
|
-
getdataJSContents = _c.sent();
|
|
193
|
-
return [4 /*yield*/, (0, utils_1.readFile)(springsJSONPath)];
|
|
194
|
-
case 13:
|
|
195
|
-
springsJSONContents = _c.sent();
|
|
196
219
|
depsInserts = "\n\n* Service Variables start;\n\n\n* Service Variables end;\n* SAS Macros start;\n\n\n\n* SAS Macros end;\n* SAS Includes start;\n\n* SAS Includes end;\n* Binary Files start;\n\n* Binary Files end;\n\n\n* Service start;\n";
|
|
197
|
-
appinit = "/**\n @file appinit.sas\n @brief Initialisation service - runs on app startup\n @details This is always the first service called when the app is opened.\n\n <h4> SAS Macros </h4>\n\n**/\n\nproc sql;\ncreate table areas as select distinct area\n from mydb.springs;\n\n%webout(OPEN)\n%webout(OBJ,areas)\n%webout(CLOSE)\n\n";
|
|
198
|
-
getdata = "/**\n @file getdata.sas\n @brief Get Data service - runs on app startup\n @details This is always the first service called when the app is opened.\n\n <h4> SAS Macros </h4>\n\n**/\n\n%webout(FETCH)\n\nproc sql;\ncreate table springs as select * from mydb.springs\n where area in (select area from work.areas);\n\n%webout(OPEN)\n%webout(OBJ,springs)\n%webout(CLOSE)\n\n";
|
|
199
220
|
getCode = function (file) {
|
|
200
221
|
return "".concat(mf_getuser).concat(mp_jsonout).concat(ms_webout).concat(webout, "/* provide additional debug info */\n%global _program;\n%put &=syscc;\n%put user=%mf_getuser();\n%put pgm=&_program;\n%put timestamp=%sysfunc(datetime(),datetime19.);").concat(depsInserts).concat(file, "* Service end;");
|
|
201
222
|
};
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
223
|
+
// The payload is derived from the project the command created rather than
|
|
224
|
+
// listed by hand. A hand-kept list turned this spec red when the seed app
|
|
225
|
+
// gained a data file beside its services - a file the CLI deploys correctly
|
|
226
|
+
// - so the reference here is the project itself. What stays explicit is the
|
|
227
|
+
// CLI's own contribution: the wrapper, built by `getCode` above.
|
|
228
|
+
expect(deployMock).toHaveBeenCalledTimes(1);
|
|
229
|
+
_c = __read(deployMock.mock.calls[0], 1), payload = _c[0];
|
|
230
|
+
expect(payload.appLoc).toEqual(target.appLoc);
|
|
231
|
+
deployed = new Map();
|
|
232
|
+
indexMembers = function (members, prefix) {
|
|
233
|
+
if (members === void 0) { members = []; }
|
|
234
|
+
if (prefix === void 0) { prefix = ''; }
|
|
235
|
+
return members.forEach(function (member) {
|
|
236
|
+
var memberPath = prefix ? "".concat(prefix, "/").concat(member.name) : member.name;
|
|
237
|
+
if (member.type === 'folder')
|
|
238
|
+
indexMembers(member.members, memberPath);
|
|
239
|
+
else
|
|
240
|
+
deployed.set(memberPath, member);
|
|
241
|
+
});
|
|
242
|
+
};
|
|
243
|
+
indexMembers(payload.fileTree.members);
|
|
244
|
+
projectRoot = path_1.default.join(__dirname, appName);
|
|
245
|
+
mocksRoot = path_1.default.join(projectRoot, 'sasjs', 'mocks');
|
|
246
|
+
mockFiles = listFiles(mocksRoot);
|
|
247
|
+
_k.label = 11;
|
|
248
|
+
case 11:
|
|
249
|
+
_k.trys.push([11, 16, 17, 18]);
|
|
250
|
+
mockFiles_1 = __values(mockFiles), mockFiles_1_1 = mockFiles_1.next();
|
|
251
|
+
_k.label = 12;
|
|
252
|
+
case 12:
|
|
253
|
+
if (!!mockFiles_1_1.done) return [3 /*break*/, 15];
|
|
254
|
+
filePath = mockFiles_1_1.value;
|
|
255
|
+
relative = path_1.default
|
|
256
|
+
.relative(mocksRoot, filePath)
|
|
257
|
+
.split(path_1.default.sep)
|
|
258
|
+
.join('/');
|
|
259
|
+
_e = (_d = expect(deployed.get(relative))).toEqual;
|
|
260
|
+
_h = {
|
|
261
|
+
name: path_1.default.basename(filePath),
|
|
262
|
+
type: 'file',
|
|
263
|
+
encoding: 'base64'
|
|
264
|
+
};
|
|
265
|
+
_f = js_base64_1.encode;
|
|
266
|
+
return [4 /*yield*/, (0, utils_1.readFile)(filePath)];
|
|
267
|
+
case 13:
|
|
268
|
+
_e.apply(_d, [(_h.code = _f.apply(void 0, [_k.sent()]),
|
|
269
|
+
_h)]);
|
|
270
|
+
_k.label = 14;
|
|
271
|
+
case 14:
|
|
272
|
+
mockFiles_1_1 = mockFiles_1.next();
|
|
273
|
+
return [3 /*break*/, 12];
|
|
274
|
+
case 15: return [3 /*break*/, 18];
|
|
275
|
+
case 16:
|
|
276
|
+
e_1_1 = _k.sent();
|
|
277
|
+
e_1 = { error: e_1_1 };
|
|
278
|
+
return [3 /*break*/, 18];
|
|
279
|
+
case 17:
|
|
280
|
+
try {
|
|
281
|
+
if (mockFiles_1_1 && !mockFiles_1_1.done && (_g = mockFiles_1.return)) _g.call(mockFiles_1);
|
|
282
|
+
}
|
|
283
|
+
finally { if (e_1) throw e_1.error; }
|
|
284
|
+
return [7 /*endfinally*/];
|
|
285
|
+
case 18:
|
|
286
|
+
serviceFiles = listFiles(path_1.default.join(projectRoot, 'sasjs', 'services', 'common')).filter(function (filePath) { return filePath.endsWith('.sas'); });
|
|
287
|
+
_k.label = 19;
|
|
288
|
+
case 19:
|
|
289
|
+
_k.trys.push([19, 24, 25, 26]);
|
|
290
|
+
serviceFiles_1 = __values(serviceFiles), serviceFiles_1_1 = serviceFiles_1.next();
|
|
291
|
+
_k.label = 20;
|
|
292
|
+
case 20:
|
|
293
|
+
if (!!serviceFiles_1_1.done) return [3 /*break*/, 23];
|
|
294
|
+
filePath = serviceFiles_1_1.value;
|
|
295
|
+
name_1 = path_1.default.basename(filePath, '.sas');
|
|
296
|
+
return [4 /*yield*/, (0, utils_1.readFile)(filePath)];
|
|
297
|
+
case 21:
|
|
298
|
+
contents = _k.sent();
|
|
299
|
+
member = deployed.get("services/common/".concat(name_1));
|
|
300
|
+
expect(member).toMatchObject({ name: name_1, type: 'service' });
|
|
301
|
+
// the compiled service ends its text with a blank line before the end
|
|
302
|
+
// marker, whatever trailing whitespace the source file carries
|
|
303
|
+
expect(member.code).toEqual(getCode((0, utils_1.removeHeader)(contents).trimEnd() + '\n\n'));
|
|
304
|
+
_k.label = 22;
|
|
305
|
+
case 22:
|
|
306
|
+
serviceFiles_1_1 = serviceFiles_1.next();
|
|
307
|
+
return [3 /*break*/, 20];
|
|
308
|
+
case 23: return [3 /*break*/, 26];
|
|
309
|
+
case 24:
|
|
310
|
+
e_2_1 = _k.sent();
|
|
311
|
+
e_2 = { error: e_2_1 };
|
|
312
|
+
return [3 /*break*/, 26];
|
|
313
|
+
case 25:
|
|
314
|
+
try {
|
|
315
|
+
if (serviceFiles_1_1 && !serviceFiles_1_1.done && (_j = serviceFiles_1.return)) _j.call(serviceFiles_1);
|
|
316
|
+
}
|
|
317
|
+
finally { if (e_2) throw e_2.error; }
|
|
318
|
+
return [7 /*endfinally*/];
|
|
319
|
+
case 26:
|
|
320
|
+
// and nothing else: a member the CLI gains or loses shows as a difference
|
|
321
|
+
// in the count, rather than silently passing inside a hand-written tree
|
|
322
|
+
expect(deployed.size).toEqual(mockFiles.length + serviceFiles.length);
|
|
249
323
|
return [2 /*return*/];
|
|
250
324
|
}
|
|
251
325
|
});
|
package/build/utils/test.d.ts
CHANGED
|
@@ -50,6 +50,18 @@ export declare const generateTestTarget: (targetName: string, appLoc: string, se
|
|
|
50
50
|
export declare const createTestGlobalTarget: (targetName: string, appLoc: string, serviceConfig?: ServiceConfig, serverType?: ServerType) => Promise<Target>;
|
|
51
51
|
export declare const verifyStep: (step?: "db" | "compile" | "build", buildFileName?: string, customFiles?: "custom" | "no") => Promise<void>;
|
|
52
52
|
export declare const mockProcessExit: () => jest.SpyInstance<never, [code?: string | number | null | undefined], any>;
|
|
53
|
+
/**
|
|
54
|
+
* The file tree of a seed app, read from the archive `sasjs create` downloads.
|
|
55
|
+
*
|
|
56
|
+
* A created project used to be compared against a hand-kept list of the files
|
|
57
|
+
* each template ships, so every seed release that added or removed one turned
|
|
58
|
+
* this suite red with no change to the CLI - twice in one afternoon, for
|
|
59
|
+
* `springs.json` and for the angular template's component specs. The template
|
|
60
|
+
* is what the command copies, so it is what the test compares against: the same
|
|
61
|
+
* repository, fetched the same way, with the copy's own normalisations applied
|
|
62
|
+
* where the command makes them.
|
|
63
|
+
*/
|
|
64
|
+
export declare const getTemplateFileTree: (repoUrl: string) => Promise<Folder>;
|
|
53
65
|
export declare const verifyFolder: (folder: Folder, parentFolderName?: string) => Promise<boolean>;
|
|
54
66
|
export declare const verifyPackageJsonContent: (parentFolderName?: string) => Promise<void>;
|
|
55
67
|
export declare const removeAllTargetsFromConfigs: () => Promise<void>;
|
package/build/utils/test.js
CHANGED
|
@@ -108,8 +108,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
108
108
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
109
109
|
};
|
|
110
110
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
111
|
-
exports.verifyGitNotPresent = exports.verifyCompiledJob = exports.verifyCompiledService = exports.verifyDotFilesNotGenerated = exports.verifyDotFiles = exports.verifyDocs = exports.updateConfig = exports.updateTarget = exports.removeAllTargetsFromConfigs = exports.verifyPackageJsonContent = exports.verifyFolder = exports.mockProcessExit = exports.verifyStep = exports.createTestGlobalTarget = exports.generateTestTarget = exports.removeTestServerFolder = exports.removeTestApp = exports.createTestMinimalApp = exports.createTestJobsApp = exports.createTestApp = exports.stubNpm = exports.npmCommands = exports.generateUniqueTimestamp = void 0;
|
|
111
|
+
exports.verifyGitNotPresent = exports.verifyCompiledJob = exports.verifyCompiledService = exports.verifyDotFilesNotGenerated = exports.verifyDotFiles = exports.verifyDocs = exports.updateConfig = exports.updateTarget = exports.removeAllTargetsFromConfigs = exports.verifyPackageJsonContent = exports.verifyFolder = exports.getTemplateFileTree = exports.mockProcessExit = exports.verifyStep = exports.createTestGlobalTarget = exports.generateTestTarget = exports.removeTestServerFolder = exports.removeTestApp = exports.createTestMinimalApp = exports.createTestJobsApp = exports.createTestApp = exports.stubNpm = exports.npmCommands = exports.generateUniqueTimestamp = void 0;
|
|
112
112
|
var fs_1 = __importDefault(require("fs"));
|
|
113
|
+
var os_1 = __importDefault(require("os"));
|
|
113
114
|
var path_1 = __importDefault(require("path"));
|
|
114
115
|
var dotenv_1 = __importDefault(require("dotenv"));
|
|
115
116
|
var utils_1 = require("@sasjs/utils");
|
|
@@ -122,6 +123,8 @@ var compiledFilesCustom1_1 = require("./fileStructures/compiledFilesCustom1");
|
|
|
122
123
|
var builtFiles_1 = require("./fileStructures/builtFiles");
|
|
123
124
|
var builtFilesCustom1_1 = require("./fileStructures/builtFilesCustom1");
|
|
124
125
|
var create_1 = require("../commands/create/create");
|
|
126
|
+
var utils_2 = require("./utils");
|
|
127
|
+
var zip_1 = require("./zip");
|
|
125
128
|
var setConstants_1 = require("./setConstants");
|
|
126
129
|
var shell = __importStar(require("./shell"));
|
|
127
130
|
/**
|
|
@@ -524,6 +527,68 @@ var verifyBuildJson = function (folders, buildJson, buildSas) {
|
|
|
524
527
|
});
|
|
525
528
|
return true;
|
|
526
529
|
};
|
|
530
|
+
/**
|
|
531
|
+
* The file tree of a seed app, read from the archive `sasjs create` downloads.
|
|
532
|
+
*
|
|
533
|
+
* A created project used to be compared against a hand-kept list of the files
|
|
534
|
+
* each template ships, so every seed release that added or removed one turned
|
|
535
|
+
* this suite red with no change to the CLI - twice in one afternoon, for
|
|
536
|
+
* `springs.json` and for the angular template's component specs. The template
|
|
537
|
+
* is what the command copies, so it is what the test compares against: the same
|
|
538
|
+
* repository, fetched the same way, with the copy's own normalisations applied
|
|
539
|
+
* where the command makes them.
|
|
540
|
+
*/
|
|
541
|
+
var getTemplateFileTree = function (repoUrl) { return __awaiter(void 0, void 0, void 0, function () {
|
|
542
|
+
var workspace, archive, main_1, root;
|
|
543
|
+
return __generator(this, function (_a) {
|
|
544
|
+
switch (_a.label) {
|
|
545
|
+
case 0:
|
|
546
|
+
if (!repoUrl) {
|
|
547
|
+
throw new Error("No seed app URL for that template - add it to seedAppUrls in src/utils/utils.ts");
|
|
548
|
+
}
|
|
549
|
+
workspace = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'sasjs-template-'));
|
|
550
|
+
_a.label = 1;
|
|
551
|
+
case 1:
|
|
552
|
+
_a.trys.push([1, , 3, 4]);
|
|
553
|
+
archive = path_1.default.join(workspace, 'main.zip');
|
|
554
|
+
main_1 = (0, utils_2.downloadFile)("".concat(repoUrl, "/archive/refs/heads/main.zip"), archive);
|
|
555
|
+
// the seed repos are on `main`, but the command falls back to `master` and
|
|
556
|
+
// the reference has to be taken from whatever it would have downloaded
|
|
557
|
+
if (main_1.code || main_1.stderr.includes('404')) {
|
|
558
|
+
(0, utils_2.downloadFile)("".concat(repoUrl, "/archive/refs/heads/master.zip"), archive);
|
|
559
|
+
}
|
|
560
|
+
return [4 /*yield*/, (0, zip_1.extractZip)(archive, workspace, true)];
|
|
561
|
+
case 2:
|
|
562
|
+
_a.sent();
|
|
563
|
+
root = fs_1.default
|
|
564
|
+
.readdirSync(workspace, { withFileTypes: true })
|
|
565
|
+
.find(function (entry) { return entry.isDirectory(); });
|
|
566
|
+
if (!root) {
|
|
567
|
+
throw new Error("Could not find the unzipped folder for ".concat(repoUrl));
|
|
568
|
+
}
|
|
569
|
+
return [2 /*return*/, toFileTree(path_1.default.join(workspace, root.name), root.name)];
|
|
570
|
+
case 3:
|
|
571
|
+
fs_1.default.rmSync(workspace, { recursive: true, force: true });
|
|
572
|
+
return [7 /*endfinally*/];
|
|
573
|
+
case 4: return [2 /*return*/];
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
}); };
|
|
577
|
+
exports.getTemplateFileTree = getTemplateFileTree;
|
|
578
|
+
var toFileTree = function (folderPath, folderName) {
|
|
579
|
+
var entries = fs_1.default.readdirSync(folderPath, { withFileTypes: true });
|
|
580
|
+
return {
|
|
581
|
+
folderName: folderName,
|
|
582
|
+
// `create` removes this once the docs have been fetched into the folder, so
|
|
583
|
+
// it is the one file the project is not expected to carry
|
|
584
|
+
files: entries
|
|
585
|
+
.filter(function (entry) { return entry.isFile() && entry.name !== '.gitmodules'; })
|
|
586
|
+
.map(function (entry) { return ({ fileName: entry.name }); }),
|
|
587
|
+
subFolders: entries
|
|
588
|
+
.filter(function (entry) { return entry.isDirectory(); })
|
|
589
|
+
.map(function (entry) { return toFileTree(path_1.default.join(folderPath, entry.name), entry.name); })
|
|
590
|
+
};
|
|
591
|
+
};
|
|
527
592
|
var verifyFolder = function (folder_1) {
|
|
528
593
|
var args_1 = [];
|
|
529
594
|
for (var _i = 1; _i < arguments.length; _i++) {
|
package/build/utils/utils.d.ts
CHANGED
|
@@ -4,6 +4,14 @@ import SASjs from '@sasjs/adapter/node';
|
|
|
4
4
|
import { LogJson } from '../types';
|
|
5
5
|
export declare function inExistingProject(folderPath: string): Promise<boolean>;
|
|
6
6
|
export declare function diff(a: any[], b: any[]): any[];
|
|
7
|
+
/**
|
|
8
|
+
* The seed apps `sasjs create` downloads, by template name.
|
|
9
|
+
*
|
|
10
|
+
* One map for the commands that fetch them and the specs that compare their
|
|
11
|
+
* output, so a template added here is covered by both rather than downloaded
|
|
12
|
+
* by one and unknown to the other.
|
|
13
|
+
*/
|
|
14
|
+
export declare const seedAppUrls: Record<string, string>;
|
|
7
15
|
export declare function createReactApp(folderPath: string): Promise<void>;
|
|
8
16
|
export declare function createAngularApp(folderPath: string): Promise<void>;
|
|
9
17
|
export declare function createMinimalApp(folderPath: string): Promise<void>;
|
package/build/utils/utils.js
CHANGED
|
@@ -90,7 +90,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
90
90
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
91
91
|
};
|
|
92
92
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
93
|
-
exports.isSasJsServerInServerMode = exports.getNodeModulePath = exports.isSASjsProject = exports.terminateProcess = exports.loadEnvVariables = exports.millisecondsToDdHhMmSs = exports.arrToObj = void 0;
|
|
93
|
+
exports.isSasJsServerInServerMode = exports.getNodeModulePath = exports.isSASjsProject = exports.terminateProcess = exports.loadEnvVariables = exports.millisecondsToDdHhMmSs = exports.arrToObj = exports.seedAppUrls = void 0;
|
|
94
94
|
exports.inExistingProject = inExistingProject;
|
|
95
95
|
exports.diff = diff;
|
|
96
96
|
exports.createReactApp = createReactApp;
|
|
@@ -147,6 +147,18 @@ function diff(a, b) {
|
|
|
147
147
|
});
|
|
148
148
|
return __spreadArray(__spreadArray([], __read(notInA), false), __read(notInB), false);
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* The seed apps `sasjs create` downloads, by template name.
|
|
152
|
+
*
|
|
153
|
+
* One map for the commands that fetch them and the specs that compare their
|
|
154
|
+
* output, so a template added here is covered by both rather than downloaded
|
|
155
|
+
* by one and unknown to the other.
|
|
156
|
+
*/
|
|
157
|
+
exports.seedAppUrls = {
|
|
158
|
+
angular: 'https://github.com/sasjs/angular-seed-app',
|
|
159
|
+
minimal: 'https://github.com/sasjs/minimal-seed-app',
|
|
160
|
+
react: 'https://github.com/sasjs/react-seed-app'
|
|
161
|
+
};
|
|
150
162
|
function createReactApp(folderPath) {
|
|
151
163
|
return __awaiter(this, void 0, void 0, function () {
|
|
152
164
|
var _this = this;
|
|
@@ -154,7 +166,7 @@ function createReactApp(folderPath) {
|
|
|
154
166
|
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
155
167
|
return __generator(this, function (_a) {
|
|
156
168
|
switch (_a.label) {
|
|
157
|
-
case 0: return [4 /*yield*/, createApp(folderPath,
|
|
169
|
+
case 0: return [4 /*yield*/, createApp(folderPath, exports.seedAppUrls.react, 'https://github.com/sasjs/docs', function (err) {
|
|
158
170
|
return reject(new Error(err));
|
|
159
171
|
})];
|
|
160
172
|
case 1:
|
|
@@ -173,7 +185,7 @@ function createAngularApp(folderPath) {
|
|
|
173
185
|
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
174
186
|
return __generator(this, function (_a) {
|
|
175
187
|
switch (_a.label) {
|
|
176
|
-
case 0: return [4 /*yield*/, createApp(folderPath,
|
|
188
|
+
case 0: return [4 /*yield*/, createApp(folderPath, exports.seedAppUrls.angular, 'https://github.com/sasjs/docs', function (err) {
|
|
177
189
|
return reject(new Error(err));
|
|
178
190
|
})];
|
|
179
191
|
case 1:
|
|
@@ -192,7 +204,7 @@ function createMinimalApp(folderPath) {
|
|
|
192
204
|
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
193
205
|
return __generator(this, function (_a) {
|
|
194
206
|
switch (_a.label) {
|
|
195
|
-
case 0: return [4 /*yield*/, createApp(folderPath,
|
|
207
|
+
case 0: return [4 /*yield*/, createApp(folderPath, exports.seedAppUrls.minimal, 'https://github.com/sasjs/docs', function (err) {
|
|
196
208
|
return reject(new Error(err));
|
|
197
209
|
})];
|
|
198
210
|
case 1:
|
package/package.json
CHANGED
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@sasjs/adapter": "6.0.2",
|
|
74
|
-
"@sasjs/api": "0.
|
|
74
|
+
"@sasjs/api": "0.38.0",
|
|
75
75
|
"@sasjs/core": "7.1.12",
|
|
76
76
|
"@sasjs/lint": "5.3.0",
|
|
77
77
|
"@sasjs/utils": "4.11.0",
|
|
@@ -125,5 +125,5 @@
|
|
|
125
125
|
"ws": "8.21.0",
|
|
126
126
|
"nanoid": "3.3.18"
|
|
127
127
|
},
|
|
128
|
-
"version": "6.
|
|
128
|
+
"version": "6.30.1"
|
|
129
129
|
}
|