@sasjs/server 3.6.1 → 3.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 +39 -33
- package/build/public/SASjsApi/favicon-16x16.png +0 -0
- package/build/public/SASjsApi/favicon-32x32.png +0 -0
- package/build/public/SASjsApi/index.html +24 -0
- package/build/public/SASjsApi/oauth2-redirect.html +6 -0
- package/build/public/SASjsApi/swagger-ui-LICENSE +202 -0
- package/build/public/SASjsApi/swagger-ui-NOTICE +2 -0
- package/build/public/SASjsApi/swagger-ui-bundle.js +2 -0
- package/build/public/SASjsApi/swagger-ui-init.js +27 -0
- package/build/public/SASjsApi/swagger-ui-standalone-preset.js +2 -0
- package/build/public/SASjsApi/swagger-ui.css +1 -1
- package/build/scripts/copySwaggerUi.js +14 -0
- package/build/src/e2e/studio.spec.js +98 -3
- package/build/src/routes/api/index.js +4 -14
- package/build/src/routes/api/spec/permission.spec.js +2 -2
- package/build/src/routes/api/spec/swaggerAssets.spec.js +69 -47
- package/build/src/utils/buildInfo.generated.js +3 -3
- package/build/src/utils/swaggerUiAssets.js +53 -0
- package/package.json +2 -3
- package/web/build/index.bundle.js +24 -24
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
var path_1 = __importDefault(require("path"));
|
|
7
|
+
var swaggerUiAssets_1 = require("../src/utils/swaggerUiAssets");
|
|
8
|
+
// Runs from `npm run initial`, so the assets are in place for both the dev server
|
|
9
|
+
// (which serves api/public directly under ts-node) and the packaged build (which
|
|
10
|
+
// copies api/public into build/public). The generated files are gitignored: the
|
|
11
|
+
// installed swagger-ui-dist devDependency is the only source of truth.
|
|
12
|
+
var destination = path_1.default.resolve(__dirname, '..', 'public', 'SASjsApi');
|
|
13
|
+
(0, swaggerUiAssets_1.copySwaggerUiAssets)(destination);
|
|
14
|
+
console.log("Copied Swagger UI assets to ".concat(destination));
|
|
@@ -98,6 +98,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
98
98
|
* the unit-test run deliberately excludes.
|
|
99
99
|
*/
|
|
100
100
|
var path_1 = __importDefault(require("path"));
|
|
101
|
+
var fs_1 = require("fs");
|
|
101
102
|
var promises_1 = require("fs/promises");
|
|
102
103
|
var mongoose_1 = __importDefault(require("mongoose"));
|
|
103
104
|
var mongodb_memory_server_1 = require("mongodb-memory-server");
|
|
@@ -140,7 +141,11 @@ describe('Studio in a browser', function () {
|
|
|
140
141
|
case 2:
|
|
141
142
|
_a.sent();
|
|
142
143
|
_a.label = 3;
|
|
143
|
-
case 3:
|
|
144
|
+
case 3:
|
|
145
|
+
// The screenshots folder is gitignored, so a fresh checkout has no such
|
|
146
|
+
// directory and a failure screenshot would fail on the write itself.
|
|
147
|
+
(0, fs_1.mkdirSync)(screenshotDir, { recursive: true });
|
|
148
|
+
return [4 /*yield*/, (0, utils_1.fileExists)(path_1.default.join((0, utils_2.getWebBuildFolder)(), 'index.bundle.js'))];
|
|
144
149
|
case 4:
|
|
145
150
|
if (!(_a.sent())) {
|
|
146
151
|
throw new Error("No web build at ".concat((0, utils_2.getWebBuildFolder)(), ". Run `npm run build` in web/ before the browser test."));
|
|
@@ -185,7 +190,10 @@ describe('Studio in a browser', function () {
|
|
|
185
190
|
// An admin passes every route check, which keeps this test about the
|
|
186
191
|
// editor rather than about the permission model.
|
|
187
192
|
expect(dbUser.isAdmin).toBe(true);
|
|
188
|
-
|
|
193
|
+
// The fixture is a .sas program, and this suite never executes code for
|
|
194
|
+
// real - the log case fulfils the execute request in the browser - so one
|
|
195
|
+
// runtime, the one the fixture needs, keeps the editor from switching it.
|
|
196
|
+
process.runTimes = [utils_2.RunTimeType.SAS];
|
|
189
197
|
process.nodeLoc = process.execPath;
|
|
190
198
|
return [4 /*yield*/, app];
|
|
191
199
|
case 13:
|
|
@@ -200,7 +208,15 @@ describe('Studio in a browser', function () {
|
|
|
200
208
|
return [4 /*yield*/, browser.newPage({ viewport: { width: 1280, height: 800 } })];
|
|
201
209
|
case 15:
|
|
202
210
|
page = _a.sent();
|
|
203
|
-
page.on('pageerror', function (error) {
|
|
211
|
+
page.on('pageerror', function (error) {
|
|
212
|
+
// A request the app aborts surfaces here as an unhandled rejection with
|
|
213
|
+
// axios's "Canceled: Canceled". That is a request superseded by a newer one
|
|
214
|
+
// - the editor re-syncing, a tab switching - not a fault in the tree, which
|
|
215
|
+
// is what this collector exists to catch.
|
|
216
|
+
if (String(error).includes('Canceled: Canceled'))
|
|
217
|
+
return;
|
|
218
|
+
pageErrors.push(String(error));
|
|
219
|
+
});
|
|
204
220
|
page.on('request', function (request) {
|
|
205
221
|
var _a;
|
|
206
222
|
if (!request.url().includes('/SASjsApi/drive/fileTree'))
|
|
@@ -576,4 +592,83 @@ describe('Studio in a browser', function () {
|
|
|
576
592
|
}
|
|
577
593
|
});
|
|
578
594
|
}); }, 60000);
|
|
595
|
+
it('lists the errors, warnings and notable notes of a SAS log, and hides the notes on request', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
596
|
+
var log, _a, _b, _c, stored;
|
|
597
|
+
return __generator(this, function (_d) {
|
|
598
|
+
switch (_d.label) {
|
|
599
|
+
case 0:
|
|
600
|
+
log = [
|
|
601
|
+
'NOTE: SAS (r) Proprietary Software 9.4 (TS1M9 MBCS3170)',
|
|
602
|
+
'1 data want;',
|
|
603
|
+
'2 x = age / 0;',
|
|
604
|
+
'3 run;',
|
|
605
|
+
'WARNING: Division by zero detected at line 3 column 11.',
|
|
606
|
+
'NOTE: Variable y is uninitialized.',
|
|
607
|
+
'ERROR Libref X is not assigned.',
|
|
608
|
+
'NOTE 49-169: The meaning of an identifier after a quoted string may change.',
|
|
609
|
+
'ERROR: File WORK.MISSING_DS.DATA does not exist.',
|
|
610
|
+
''
|
|
611
|
+
].join('\n');
|
|
612
|
+
return [4 /*yield*/, page.route('**/SASjsApi/code/execute', function (route) {
|
|
613
|
+
return route.fulfill({
|
|
614
|
+
status: 200,
|
|
615
|
+
contentType: 'text/plain',
|
|
616
|
+
body: ['<html></html>', log, ''].join('SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784')
|
|
617
|
+
});
|
|
618
|
+
})
|
|
619
|
+
// The fixture program is a .sas file, so opening it selects the SAS runtime
|
|
620
|
+
// and the log pane will render the parsed shape.
|
|
621
|
+
];
|
|
622
|
+
case 1:
|
|
623
|
+
_d.sent();
|
|
624
|
+
// The fixture program is a .sas file, so opening it selects the SAS runtime
|
|
625
|
+
// and the log pane will render the parsed shape.
|
|
626
|
+
return [4 /*yield*/, page.click('button:has-text("RUN")')];
|
|
627
|
+
case 2:
|
|
628
|
+
// The fixture program is a .sas file, so opening it selects the SAS runtime
|
|
629
|
+
// and the log pane will render the parsed shape.
|
|
630
|
+
_d.sent();
|
|
631
|
+
return [4 /*yield*/, page.waitForSelector('text=Errors (2)', { timeout: 30000 })];
|
|
632
|
+
case 3:
|
|
633
|
+
_d.sent();
|
|
634
|
+
_a = expect;
|
|
635
|
+
return [4 /*yield*/, page.isVisible('text=Warnings (1)')];
|
|
636
|
+
case 4:
|
|
637
|
+
_a.apply(void 0, [_d.sent()]).toBe(true);
|
|
638
|
+
_b = expect;
|
|
639
|
+
return [4 /*yield*/, page.isVisible('text=Notes (2)')];
|
|
640
|
+
case 5:
|
|
641
|
+
_b.apply(void 0, [_d.sent()]).toBe(true);
|
|
642
|
+
return [4 /*yield*/, page.screenshot({
|
|
643
|
+
path: path_1.default.join(screenshotDir, '02-log-issues.png')
|
|
644
|
+
})
|
|
645
|
+
// The switch hides them without another run.
|
|
646
|
+
];
|
|
647
|
+
case 6:
|
|
648
|
+
_d.sent();
|
|
649
|
+
// The switch hides them without another run.
|
|
650
|
+
return [4 /*yield*/, page.click('[aria-label="Hide notable notes"]')];
|
|
651
|
+
case 7:
|
|
652
|
+
// The switch hides them without another run.
|
|
653
|
+
_d.sent();
|
|
654
|
+
return [4 /*yield*/, page.waitForSelector('text=Notes (2)', {
|
|
655
|
+
state: 'detached',
|
|
656
|
+
timeout: 30000
|
|
657
|
+
})];
|
|
658
|
+
case 8:
|
|
659
|
+
_d.sent();
|
|
660
|
+
_c = expect;
|
|
661
|
+
return [4 /*yield*/, page.isVisible('text=Errors (2)')];
|
|
662
|
+
case 9:
|
|
663
|
+
_c.apply(void 0, [_d.sent()]).toBe(true);
|
|
664
|
+
return [4 /*yield*/, page.evaluate(function () {
|
|
665
|
+
return window.localStorage.getItem('studio-settings');
|
|
666
|
+
})];
|
|
667
|
+
case 10:
|
|
668
|
+
stored = _d.sent();
|
|
669
|
+
expect(JSON.parse(stored)['log.notableNotes']).toBe(false);
|
|
670
|
+
return [2 /*return*/];
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
}); }, 120000);
|
|
579
674
|
});
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
var express_1 = __importDefault(require("express"));
|
|
7
|
-
var swagger_ui_express_1 = __importDefault(require("swagger-ui-express"));
|
|
8
7
|
var middlewares_1 = require("../../middlewares");
|
|
9
8
|
var info_1 = __importDefault(require("./info"));
|
|
10
9
|
var admin_1 = __importDefault(require("./admin"));
|
|
@@ -34,17 +33,8 @@ router.use('/code', middlewares_1.authenticateAccessToken, code_1.default);
|
|
|
34
33
|
router.use('/user', middlewares_1.desktopRestrict, user_1.default);
|
|
35
34
|
router.use('/permission', middlewares_1.desktopRestrict, middlewares_1.authenticateAccessToken, permission_1.default);
|
|
36
35
|
router.use('/authConfig', middlewares_1.desktopRestrict, middlewares_1.authenticateAccessToken, middlewares_1.verifyAdmin, authConfig_1.default);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
request.credentials = 'include';
|
|
42
|
-
var cookie = document.cookie;
|
|
43
|
-
var startIndex = cookie.indexOf('XSRF-TOKEN');
|
|
44
|
-
var csrf = cookie.slice(startIndex + 11).split('; ')[0];
|
|
45
|
-
request.headers['X-XSRF-TOKEN'] = csrf;
|
|
46
|
-
return request;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}));
|
|
36
|
+
// The API documentation page is a file in public/SASjsApi/ (index.html plus the
|
|
37
|
+
// assets copied beside it at build time), served by the express.static mount in
|
|
38
|
+
// app.ts. It is not a route here: the page and its assets are plain files, and
|
|
39
|
+
// nothing in them is rendered per request.
|
|
50
40
|
exports.default = router;
|
|
@@ -58,7 +58,7 @@ var controllers_1 = require("../../../controllers/");
|
|
|
58
58
|
var utils_1 = require("../../../utils");
|
|
59
59
|
var crypto_1 = require("crypto");
|
|
60
60
|
var deployPayload = {
|
|
61
|
-
appLoc: '
|
|
61
|
+
appLoc: '/Public/example',
|
|
62
62
|
streamWebFolder: 'string',
|
|
63
63
|
fileTree: {
|
|
64
64
|
members: [
|
|
@@ -772,7 +772,7 @@ describe('permission', function () {
|
|
|
772
772
|
case 1:
|
|
773
773
|
accessToken = _a.sent();
|
|
774
774
|
return [4 /*yield*/, (0, supertest_1.default)(app)
|
|
775
|
-
.
|
|
775
|
+
.post('/SASjsApi/drive/deploy')
|
|
776
776
|
.auth(accessToken, { type: 'bearer' })
|
|
777
777
|
.send(deployPayload)
|
|
778
778
|
.expect(200)];
|
|
@@ -3,63 +3,85 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
var crypto_1 = __importDefault(require("crypto"));
|
|
7
6
|
var fs_1 = __importDefault(require("fs"));
|
|
7
|
+
var os_1 = __importDefault(require("os"));
|
|
8
8
|
var path_1 = __importDefault(require("path"));
|
|
9
|
+
var swaggerUiAssets_1 = require("../../../utils/swaggerUiAssets");
|
|
9
10
|
/**
|
|
10
|
-
* Guard for the Swagger UI
|
|
11
|
+
* Guard for the Swagger UI the API serves.
|
|
11
12
|
*
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
14
|
-
* `
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* `public/SASjsApi/index.html` is the documentation page, and the assets beside
|
|
14
|
+
* it are copied from the pinned `swagger-ui-dist` devDependency by
|
|
15
|
+
* `scripts/copySwaggerUi.ts`. Nothing from that package is installed at
|
|
16
|
+
* runtime, because it depends on `@scarf/scarf`, whose postinstall reports the
|
|
17
|
+
* install to scarf.sh.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* not know about, while its own `.opblock-summary-path` rule still caps the
|
|
22
|
-
* width at `calc(100% - 110px - 15rem)`. With no wrapper rule the cap resolved
|
|
23
|
-
* against a container narrower than the subtraction, so the path wrapped at
|
|
24
|
-
* every character.
|
|
25
|
-
*
|
|
26
|
-
* These tests keep the copy in step with the package that renders the DOM.
|
|
19
|
+
* Two things can therefore go wrong silently, and both are covered here: a page
|
|
20
|
+
* that points at an asset the build does not copy (a blank or unstyled UI), and
|
|
21
|
+
* a page that reaches a third party (the leak this arrangement exists to stop).
|
|
27
22
|
*/
|
|
28
23
|
var apiRoot = path_1.default.resolve(__dirname, '../../../..');
|
|
29
|
-
var
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
var sha256 = function (buffer) {
|
|
34
|
-
return crypto_1.default.createHash('sha256').update(buffer).digest('hex');
|
|
35
|
-
};
|
|
24
|
+
var pagePath = path_1.default.join(apiRoot, 'public', 'SASjsApi', 'index.html');
|
|
25
|
+
var initPath = path_1.default.join(apiRoot, 'public', 'SASjsApi', 'swagger-ui-init.js');
|
|
26
|
+
var page = function () { return fs_1.default.readFileSync(pagePath, 'utf8'); };
|
|
27
|
+
var init = function () { return fs_1.default.readFileSync(initPath, 'utf8'); };
|
|
36
28
|
describe('bundled Swagger UI assets', function () {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
29
|
+
var destination;
|
|
30
|
+
beforeAll(function () {
|
|
31
|
+
destination = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'sasjs-swagger-ui-'));
|
|
32
|
+
(0, swaggerUiAssets_1.copySwaggerUiAssets)(destination);
|
|
33
|
+
});
|
|
34
|
+
afterAll(function () {
|
|
35
|
+
fs_1.default.rmSync(destination, { recursive: true, force: true });
|
|
36
|
+
});
|
|
37
|
+
it('copies every asset the page loads from swagger-ui-dist', function () {
|
|
38
|
+
var distFolder = (0, swaggerUiAssets_1.swaggerUiDistFolder)();
|
|
39
|
+
for (var _i = 0, swaggerUiAssets_2 = swaggerUiAssets_1.swaggerUiAssets; _i < swaggerUiAssets_2.length; _i++) {
|
|
40
|
+
var file = swaggerUiAssets_2[_i];
|
|
41
|
+
expect(fs_1.default.existsSync(path_1.default.join(destination, file))).toBe(true);
|
|
42
|
+
expect(fs_1.default
|
|
43
|
+
.readFileSync(path_1.default.join(destination, file))
|
|
44
|
+
.equals(fs_1.default.readFileSync(path_1.default.join(distFolder, file)))).toBe(true);
|
|
45
|
+
}
|
|
46
|
+
// Apache-2.0: the licence and notice travel with the files
|
|
47
|
+
for (var _a = 0, swaggerUiNotices_1 = swaggerUiAssets_1.swaggerUiNotices; _a < swaggerUiNotices_1.length; _a++) {
|
|
48
|
+
var file = swaggerUiNotices_1[_a];
|
|
49
|
+
expect(fs_1.default.existsSync(path_1.default.join(destination, "swagger-ui-".concat(file)))).toBe(true);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
it('loads the page and its styles from this folder, not from a third party', function () {
|
|
53
|
+
var html = page();
|
|
54
|
+
var loaded = [
|
|
55
|
+
'swagger-ui.css',
|
|
56
|
+
'swagger-ui-bundle.js',
|
|
57
|
+
'swagger-ui-standalone-preset.js',
|
|
58
|
+
'swagger-ui-init.js',
|
|
59
|
+
'favicon-32x32.png'
|
|
60
|
+
];
|
|
61
|
+
for (var _i = 0, loaded_1 = loaded; _i < loaded_1.length; _i++) {
|
|
62
|
+
var file = loaded_1[_i];
|
|
63
|
+
expect(html).toContain("./".concat(file));
|
|
46
64
|
}
|
|
65
|
+
var external = html.match(/(src|href)\s*=\s*["']?https?:\/\//gi) || [];
|
|
66
|
+
expect(external).toEqual([]);
|
|
47
67
|
});
|
|
48
|
-
it('
|
|
49
|
-
var
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
it('starts Swagger UI against the local spec with no third-party validator', function () {
|
|
69
|
+
var script = init();
|
|
70
|
+
expect(script).toContain("url: '/swagger.yaml'");
|
|
71
|
+
// the online validator posts the spec URL to validator.swagger.io
|
|
72
|
+
expect(script).toContain('validatorUrl: null');
|
|
73
|
+
// the API's own calls carry the session cookie and the CSRF header
|
|
74
|
+
expect(script).toContain("request.credentials = 'include'");
|
|
75
|
+
expect(script).toContain('X-XSRF-TOKEN');
|
|
54
76
|
});
|
|
55
|
-
it('
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
expect(
|
|
77
|
+
it('keeps swagger-ui out of the runtime dependencies', function () {
|
|
78
|
+
// swagger-ui-dist is a devDependency: it is the source of the copied
|
|
79
|
+
// assets, and its tree carries @scarf/scarf's postinstall. Installing
|
|
80
|
+
// @sasjs/server must not run anything that calls out.
|
|
81
|
+
var manifest = JSON.parse(fs_1.default.readFileSync(path_1.default.join(apiRoot, 'package.json'), 'utf8'));
|
|
82
|
+
var runtime = Object.keys(manifest.dependencies || {});
|
|
83
|
+
expect(runtime).not.toContain('swagger-ui-express');
|
|
84
|
+
expect(runtime).not.toContain('swagger-ui-dist');
|
|
85
|
+
expect(Object.keys(manifest.devDependencies || {})).toContain('swagger-ui-dist');
|
|
64
86
|
});
|
|
65
87
|
});
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BUILD_INFO = void 0;
|
|
4
4
|
// Generated by scripts/generateBuildInfo.ts. Do not edit by hand.
|
|
5
5
|
exports.BUILD_INFO = {
|
|
6
|
-
version: "v3.
|
|
7
|
-
gitHash: "
|
|
8
|
-
buildDate: "2026-
|
|
6
|
+
version: "v3.7.0",
|
|
7
|
+
gitHash: "d1cc0c9",
|
|
8
|
+
buildDate: "2026-11-01T21:13:10.033Z"
|
|
9
9
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.copySwaggerUiAssets = exports.swaggerUiDistFolder = exports.swaggerUiNotices = exports.swaggerUiAssets = void 0;
|
|
7
|
+
var fs_1 = __importDefault(require("fs"));
|
|
8
|
+
var path_1 = __importDefault(require("path"));
|
|
9
|
+
/**
|
|
10
|
+
* The Swagger UI assets the API serves from its own public folder.
|
|
11
|
+
*
|
|
12
|
+
* They are generated from `swagger-ui-dist` at build time instead of being
|
|
13
|
+
* carried as a runtime dependency. `swagger-ui-dist` depends on `@scarf/scarf`,
|
|
14
|
+
* whose postinstall reports the installation to scarf.sh - a published package
|
|
15
|
+
* must not make outbound calls when it is installed, so nothing from
|
|
16
|
+
* swagger-ui-dist is installed with it. `swagger-ui-dist` stays a devDependency:
|
|
17
|
+
* it is the source these files are copied from, and swaggerAssets.spec.ts
|
|
18
|
+
* compares the two.
|
|
19
|
+
*/
|
|
20
|
+
exports.swaggerUiAssets = [
|
|
21
|
+
'swagger-ui.css',
|
|
22
|
+
'swagger-ui-bundle.js',
|
|
23
|
+
'swagger-ui-standalone-preset.js',
|
|
24
|
+
'favicon-16x16.png',
|
|
25
|
+
'favicon-32x32.png',
|
|
26
|
+
'oauth2-redirect.html'
|
|
27
|
+
];
|
|
28
|
+
/** Apache-2.0 requires the licence and the notice to travel with the files. */
|
|
29
|
+
exports.swaggerUiNotices = ['LICENSE', 'NOTICE'];
|
|
30
|
+
var swaggerUiDistFolder = function () {
|
|
31
|
+
return path_1.default.dirname(require.resolve('swagger-ui-dist/package.json'));
|
|
32
|
+
};
|
|
33
|
+
exports.swaggerUiDistFolder = swaggerUiDistFolder;
|
|
34
|
+
/**
|
|
35
|
+
* Copies the browser assets, and the licence files, into `destination`.
|
|
36
|
+
*
|
|
37
|
+
* Same function for the build (`api/scripts/copySwaggerUi.ts`) and for the
|
|
38
|
+
* spec, so what the test compares is what the build produces.
|
|
39
|
+
*/
|
|
40
|
+
var copySwaggerUiAssets = function (destination) {
|
|
41
|
+
var source = (0, exports.swaggerUiDistFolder)();
|
|
42
|
+
fs_1.default.mkdirSync(destination, { recursive: true });
|
|
43
|
+
for (var _i = 0, swaggerUiAssets_1 = exports.swaggerUiAssets; _i < swaggerUiAssets_1.length; _i++) {
|
|
44
|
+
var file = swaggerUiAssets_1[_i];
|
|
45
|
+
fs_1.default.copyFileSync(path_1.default.join(source, file), path_1.default.join(destination, file));
|
|
46
|
+
}
|
|
47
|
+
for (var _a = 0, swaggerUiNotices_1 = exports.swaggerUiNotices; _a < swaggerUiNotices_1.length; _a++) {
|
|
48
|
+
var file = swaggerUiNotices_1[_a];
|
|
49
|
+
fs_1.default.copyFileSync(path_1.default.join(source, file), path_1.default.join(destination, "swagger-ui-".concat(file)));
|
|
50
|
+
}
|
|
51
|
+
return destination;
|
|
52
|
+
};
|
|
53
|
+
exports.copySwaggerUiAssets = copySwaggerUiAssets;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sasjs/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "NodeJS wrapper for calling the SAS binary executable",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "https://github.com/sasjs/server",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"express-session": "^1.19.0",
|
|
36
36
|
"helmet": "^8.3.0",
|
|
37
37
|
"http-headers-validation": "^0.0.2",
|
|
38
|
-
"joi": "^18.
|
|
38
|
+
"joi": "^18.3.1",
|
|
39
39
|
"jose": "5.10.0",
|
|
40
40
|
"jsonwebtoken": "^9.0.3",
|
|
41
41
|
"ldapjs": "2.3.3",
|
|
@@ -43,7 +43,6 @@
|
|
|
43
43
|
"morgan": "^1.12.1",
|
|
44
44
|
"multer": "^2.4.0",
|
|
45
45
|
"rotating-file-stream": "^3.2.10",
|
|
46
|
-
"swagger-ui-express": "5.0.1",
|
|
47
46
|
"tsoa": "5.1.1",
|
|
48
47
|
"unzipper": "^0.12.5",
|
|
49
48
|
"url": "^0.11.4"
|