@backstage/backend-app-api 0.2.5-next.0 → 0.3.0-next.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.
Potentially problematic release.
This version of @backstage/backend-app-api might be problematic. Click here for more details.
- package/CHANGELOG.md +24 -0
- package/alpha/package.json +1 -1
- package/dist/index.alpha.d.ts +266 -10
- package/dist/index.beta.d.ts +266 -10
- package/dist/index.cjs.js +822 -137
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +266 -10
- package/package.json +26 -6
package/dist/index.cjs.js
CHANGED
|
@@ -2,32 +2,575 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var http = require('http');
|
|
6
|
+
var https = require('https');
|
|
7
|
+
var stoppableServer = require('stoppable');
|
|
8
|
+
var fs = require('fs-extra');
|
|
9
|
+
var path = require('path');
|
|
10
|
+
var forge = require('node-forge');
|
|
11
|
+
var cors = require('cors');
|
|
12
|
+
var helmet = require('helmet');
|
|
13
|
+
var morgan = require('morgan');
|
|
14
|
+
var compression = require('compression');
|
|
15
|
+
var minimatch = require('minimatch');
|
|
6
16
|
var errors = require('@backstage/errors');
|
|
17
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
18
|
+
var express = require('express');
|
|
7
19
|
var backendCommon = require('@backstage/backend-common');
|
|
8
20
|
var pluginPermissionNode = require('@backstage/plugin-permission-node');
|
|
9
21
|
var backendTasks = require('@backstage/backend-tasks');
|
|
10
|
-
var Router = require('express-promise-router');
|
|
11
22
|
|
|
12
23
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
24
|
|
|
14
|
-
|
|
25
|
+
function _interopNamespace(e) {
|
|
26
|
+
if (e && e.__esModule) return e;
|
|
27
|
+
var n = Object.create(null);
|
|
28
|
+
if (e) {
|
|
29
|
+
Object.keys(e).forEach(function (k) {
|
|
30
|
+
if (k !== 'default') {
|
|
31
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
32
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return e[k]; }
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
n["default"] = e;
|
|
40
|
+
return Object.freeze(n);
|
|
41
|
+
}
|
|
15
42
|
|
|
16
|
-
var
|
|
43
|
+
var http__namespace = /*#__PURE__*/_interopNamespace(http);
|
|
44
|
+
var https__namespace = /*#__PURE__*/_interopNamespace(https);
|
|
45
|
+
var stoppableServer__default = /*#__PURE__*/_interopDefaultLegacy(stoppableServer);
|
|
46
|
+
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
47
|
+
var forge__default = /*#__PURE__*/_interopDefaultLegacy(forge);
|
|
48
|
+
var cors__default = /*#__PURE__*/_interopDefaultLegacy(cors);
|
|
49
|
+
var helmet__default = /*#__PURE__*/_interopDefaultLegacy(helmet);
|
|
50
|
+
var morgan__default = /*#__PURE__*/_interopDefaultLegacy(morgan);
|
|
51
|
+
var compression__default = /*#__PURE__*/_interopDefaultLegacy(compression);
|
|
52
|
+
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
53
|
+
|
|
54
|
+
const DEFAULT_PORT = 7007;
|
|
55
|
+
const DEFAULT_HOST = "";
|
|
56
|
+
function readHttpServerOptions(config) {
|
|
57
|
+
return {
|
|
58
|
+
listen: readHttpListenOptions(config),
|
|
59
|
+
https: readHttpsOptions(config)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function readHttpListenOptions(config) {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
const listen = config == null ? void 0 : config.getOptional("listen");
|
|
65
|
+
if (typeof listen === "string") {
|
|
66
|
+
const parts = String(listen).split(":");
|
|
67
|
+
const port = parseInt(parts[parts.length - 1], 10);
|
|
68
|
+
if (!isNaN(port)) {
|
|
69
|
+
if (parts.length === 1) {
|
|
70
|
+
return { port, host: DEFAULT_HOST };
|
|
71
|
+
}
|
|
72
|
+
if (parts.length === 2) {
|
|
73
|
+
return { host: parts[0], port };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
throw new Error(
|
|
77
|
+
`Unable to parse listen address ${listen}, expected <port> or <host>:<port>`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const host = (_a = config == null ? void 0 : config.getOptional("listen.host")) != null ? _a : DEFAULT_HOST;
|
|
81
|
+
if (typeof host !== "string") {
|
|
82
|
+
config == null ? void 0 : config.getOptionalString("listen.host");
|
|
83
|
+
throw new Error("unreachable");
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
port: (_b = config == null ? void 0 : config.getOptionalNumber("listen.port")) != null ? _b : DEFAULT_PORT,
|
|
87
|
+
host
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function readHttpsOptions(config) {
|
|
91
|
+
const https = config == null ? void 0 : config.getOptional("https");
|
|
92
|
+
if (https === true) {
|
|
93
|
+
const baseUrl = config.getString("baseUrl");
|
|
94
|
+
let hostname;
|
|
95
|
+
try {
|
|
96
|
+
hostname = new URL(baseUrl).hostname;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
throw new Error(`Invalid baseUrl "${baseUrl}"`);
|
|
99
|
+
}
|
|
100
|
+
return { certificate: { type: "generated", hostname } };
|
|
101
|
+
}
|
|
102
|
+
const cc = config == null ? void 0 : config.getOptionalConfig("https");
|
|
103
|
+
if (!cc) {
|
|
104
|
+
return void 0;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
certificate: {
|
|
108
|
+
type: "plain",
|
|
109
|
+
cert: cc.getString("certificate.cert"),
|
|
110
|
+
key: cc.getString("certificate.key")
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const FIVE_DAYS_IN_MS = 5 * 24 * 60 * 60 * 1e3;
|
|
116
|
+
const IP_HOSTNAME_REGEX = /:|^\d+\.\d+\.\d+\.\d+$/;
|
|
117
|
+
async function getGeneratedCertificate(hostname, logger) {
|
|
118
|
+
const hasModules = await fs__default["default"].pathExists("node_modules");
|
|
119
|
+
let certPath;
|
|
120
|
+
if (hasModules) {
|
|
121
|
+
certPath = path.resolve(
|
|
122
|
+
"node_modules/.cache/backstage-backend/dev-cert.pem"
|
|
123
|
+
);
|
|
124
|
+
await fs__default["default"].ensureDir(path.dirname(certPath));
|
|
125
|
+
} else {
|
|
126
|
+
certPath = path.resolve(".dev-cert.pem");
|
|
127
|
+
}
|
|
128
|
+
if (await fs__default["default"].pathExists(certPath)) {
|
|
129
|
+
try {
|
|
130
|
+
const cert = await fs__default["default"].readFile(certPath);
|
|
131
|
+
const crt = forge__default["default"].pki.certificateFromPem(cert.toString());
|
|
132
|
+
const remainingMs = crt.validity.notAfter.getTime() - Date.now();
|
|
133
|
+
if (remainingMs > FIVE_DAYS_IN_MS) {
|
|
134
|
+
logger.info("Using existing self-signed certificate");
|
|
135
|
+
return {
|
|
136
|
+
key: cert,
|
|
137
|
+
cert
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
logger.warn(`Unable to use existing self-signed certificate, ${error}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
logger.info("Generating new self-signed certificate");
|
|
145
|
+
const newCert = await generateCertificate(hostname);
|
|
146
|
+
await fs__default["default"].writeFile(certPath, newCert.cert + newCert.key, "utf8");
|
|
147
|
+
return newCert;
|
|
148
|
+
}
|
|
149
|
+
async function generateCertificate(hostname) {
|
|
150
|
+
const attributes = [
|
|
151
|
+
{
|
|
152
|
+
name: "commonName",
|
|
153
|
+
value: "dev-cert"
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
const sans = [
|
|
157
|
+
{
|
|
158
|
+
type: 2,
|
|
159
|
+
// DNS
|
|
160
|
+
value: "localhost"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 2,
|
|
164
|
+
value: "localhost.localdomain"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 2,
|
|
168
|
+
value: "[::1]"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: 7,
|
|
172
|
+
// IP
|
|
173
|
+
ip: "127.0.0.1"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 7,
|
|
177
|
+
ip: "fe80::1"
|
|
178
|
+
}
|
|
179
|
+
];
|
|
180
|
+
if (!sans.find(({ value, ip }) => value === hostname || ip === hostname)) {
|
|
181
|
+
sans.push(
|
|
182
|
+
IP_HOSTNAME_REGEX.test(hostname) ? {
|
|
183
|
+
type: 7,
|
|
184
|
+
ip: hostname
|
|
185
|
+
} : {
|
|
186
|
+
type: 2,
|
|
187
|
+
value: hostname
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
const params = {
|
|
192
|
+
algorithm: "sha256",
|
|
193
|
+
keySize: 2048,
|
|
194
|
+
days: 30,
|
|
195
|
+
extensions: [
|
|
196
|
+
{
|
|
197
|
+
name: "keyUsage",
|
|
198
|
+
keyCertSign: true,
|
|
199
|
+
digitalSignature: true,
|
|
200
|
+
nonRepudiation: true,
|
|
201
|
+
keyEncipherment: true,
|
|
202
|
+
dataEncipherment: true
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "extKeyUsage",
|
|
206
|
+
serverAuth: true,
|
|
207
|
+
clientAuth: true,
|
|
208
|
+
codeSigning: true,
|
|
209
|
+
timeStamping: true
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: "subjectAltName",
|
|
213
|
+
altNames: sans
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
};
|
|
217
|
+
return new Promise(
|
|
218
|
+
(resolve, reject) => require("selfsigned").generate(
|
|
219
|
+
attributes,
|
|
220
|
+
params,
|
|
221
|
+
(err, bundle) => {
|
|
222
|
+
if (err) {
|
|
223
|
+
reject(err);
|
|
224
|
+
} else {
|
|
225
|
+
resolve({ key: bundle.private, cert: bundle.cert });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function createHttpServer(listener, options, deps) {
|
|
233
|
+
const server = await createServer(listener, options, deps);
|
|
234
|
+
const stopper = stoppableServer__default["default"](server, 0);
|
|
235
|
+
const stopServer = stopper.stop.bind(stopper);
|
|
236
|
+
return Object.assign(server, {
|
|
237
|
+
start() {
|
|
238
|
+
return new Promise((resolve, reject) => {
|
|
239
|
+
const handleStartupError = (error) => {
|
|
240
|
+
server.close();
|
|
241
|
+
reject(error);
|
|
242
|
+
};
|
|
243
|
+
server.on("error", handleStartupError);
|
|
244
|
+
const { host, port } = options.listen;
|
|
245
|
+
server.listen(port, host, () => {
|
|
246
|
+
server.off("error", handleStartupError);
|
|
247
|
+
deps.logger.info(`Listening on ${host}:${port}`);
|
|
248
|
+
resolve();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
},
|
|
252
|
+
stop() {
|
|
253
|
+
return new Promise((resolve, reject) => {
|
|
254
|
+
stopServer((error) => {
|
|
255
|
+
if (error) {
|
|
256
|
+
reject(error);
|
|
257
|
+
} else {
|
|
258
|
+
resolve();
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
port() {
|
|
264
|
+
const address = server.address();
|
|
265
|
+
if (typeof address === "string" || address === null) {
|
|
266
|
+
throw new Error(`Unexpected server address '${address}'`);
|
|
267
|
+
}
|
|
268
|
+
return address.port;
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
async function createServer(listener, options, deps) {
|
|
273
|
+
if (options.https) {
|
|
274
|
+
const { certificate } = options.https;
|
|
275
|
+
if (certificate.type === "generated") {
|
|
276
|
+
const credentials = await getGeneratedCertificate(
|
|
277
|
+
certificate.hostname,
|
|
278
|
+
deps.logger
|
|
279
|
+
);
|
|
280
|
+
return https__namespace.createServer(credentials, listener);
|
|
281
|
+
}
|
|
282
|
+
return https__namespace.createServer(certificate, listener);
|
|
283
|
+
}
|
|
284
|
+
return http__namespace.createServer(listener);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function readHelmetOptions(config) {
|
|
288
|
+
const cspOptions = readCspDirectives(config);
|
|
289
|
+
return {
|
|
290
|
+
contentSecurityPolicy: {
|
|
291
|
+
useDefaults: false,
|
|
292
|
+
directives: applyCspDirectives(cspOptions)
|
|
293
|
+
},
|
|
294
|
+
// These are all disabled in order to maintain backwards compatibility
|
|
295
|
+
// when bumping helmet v5. We can't enable these by default because
|
|
296
|
+
// there is no way for users to configure them.
|
|
297
|
+
// TODO(Rugvip): We should give control of this setup to consumers
|
|
298
|
+
crossOriginEmbedderPolicy: false,
|
|
299
|
+
crossOriginOpenerPolicy: false,
|
|
300
|
+
crossOriginResourcePolicy: false,
|
|
301
|
+
originAgentCluster: false
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
function readCspDirectives(config) {
|
|
305
|
+
const cc = config == null ? void 0 : config.getOptionalConfig("csp");
|
|
306
|
+
if (!cc) {
|
|
307
|
+
return void 0;
|
|
308
|
+
}
|
|
309
|
+
const result = {};
|
|
310
|
+
for (const key of cc.keys()) {
|
|
311
|
+
if (cc.get(key) === false) {
|
|
312
|
+
result[key] = false;
|
|
313
|
+
} else {
|
|
314
|
+
result[key] = cc.getStringArray(key);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
function applyCspDirectives(directives) {
|
|
320
|
+
const result = helmet__default["default"].contentSecurityPolicy.getDefaultDirectives();
|
|
321
|
+
result["script-src"] = ["'self'", "'unsafe-eval'"];
|
|
322
|
+
delete result["form-action"];
|
|
323
|
+
if (directives) {
|
|
324
|
+
for (const [key, value] of Object.entries(directives)) {
|
|
325
|
+
if (value === false) {
|
|
326
|
+
delete result[key];
|
|
327
|
+
} else {
|
|
328
|
+
result[key] = value;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function readCorsOptions(config) {
|
|
336
|
+
const cc = config == null ? void 0 : config.getOptionalConfig("cors");
|
|
337
|
+
if (!cc) {
|
|
338
|
+
return { origin: false };
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
origin: createCorsOriginMatcher(readStringArray(cc, "origin")),
|
|
342
|
+
methods: readStringArray(cc, "methods"),
|
|
343
|
+
allowedHeaders: readStringArray(cc, "allowedHeaders"),
|
|
344
|
+
exposedHeaders: readStringArray(cc, "exposedHeaders"),
|
|
345
|
+
credentials: cc.getOptionalBoolean("credentials"),
|
|
346
|
+
maxAge: cc.getOptionalNumber("maxAge"),
|
|
347
|
+
preflightContinue: cc.getOptionalBoolean("preflightContinue"),
|
|
348
|
+
optionsSuccessStatus: cc.getOptionalNumber("optionsSuccessStatus")
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function readStringArray(config, key) {
|
|
352
|
+
const value = config.getOptional(key);
|
|
353
|
+
if (typeof value === "string") {
|
|
354
|
+
return [value];
|
|
355
|
+
} else if (!value) {
|
|
356
|
+
return void 0;
|
|
357
|
+
}
|
|
358
|
+
return config.getStringArray(key);
|
|
359
|
+
}
|
|
360
|
+
function createCorsOriginMatcher(allowedOriginPatterns) {
|
|
361
|
+
if (!allowedOriginPatterns) {
|
|
362
|
+
return void 0;
|
|
363
|
+
}
|
|
364
|
+
const allowedOriginMatchers = allowedOriginPatterns.map(
|
|
365
|
+
(pattern) => new minimatch.Minimatch(pattern, { nocase: true, noglobstar: true })
|
|
366
|
+
);
|
|
367
|
+
return (origin, callback) => {
|
|
368
|
+
return callback(
|
|
369
|
+
null,
|
|
370
|
+
allowedOriginMatchers.some((pattern) => pattern.match(origin != null ? origin : ""))
|
|
371
|
+
);
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
var __accessCheck$5 = (obj, member, msg) => {
|
|
17
376
|
if (!member.has(obj))
|
|
18
377
|
throw TypeError("Cannot " + msg);
|
|
19
378
|
};
|
|
20
|
-
var __privateGet$
|
|
21
|
-
__accessCheck$
|
|
379
|
+
var __privateGet$5 = (obj, member, getter) => {
|
|
380
|
+
__accessCheck$5(obj, member, "read from private field");
|
|
22
381
|
return getter ? getter.call(obj) : member.get(obj);
|
|
23
382
|
};
|
|
24
|
-
var __privateAdd$
|
|
383
|
+
var __privateAdd$5 = (obj, member, value) => {
|
|
25
384
|
if (member.has(obj))
|
|
26
385
|
throw TypeError("Cannot add the same private member more than once");
|
|
27
386
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
28
387
|
};
|
|
29
|
-
var __privateSet$
|
|
30
|
-
__accessCheck$
|
|
388
|
+
var __privateSet$5 = (obj, member, value, setter) => {
|
|
389
|
+
__accessCheck$5(obj, member, "write to private field");
|
|
390
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
391
|
+
return value;
|
|
392
|
+
};
|
|
393
|
+
var _config, _logger;
|
|
394
|
+
const _MiddlewareFactory = class {
|
|
395
|
+
constructor(options) {
|
|
396
|
+
__privateAdd$5(this, _config, void 0);
|
|
397
|
+
__privateAdd$5(this, _logger, void 0);
|
|
398
|
+
__privateSet$5(this, _config, options.config);
|
|
399
|
+
__privateSet$5(this, _logger, options.logger);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Creates a new {@link MiddlewareFactory}.
|
|
403
|
+
*/
|
|
404
|
+
static create(options) {
|
|
405
|
+
return new _MiddlewareFactory(options);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Returns a middleware that unconditionally produces a 404 error response.
|
|
409
|
+
*
|
|
410
|
+
* @remarks
|
|
411
|
+
*
|
|
412
|
+
* Typically you want to place this middleware at the end of the chain, such
|
|
413
|
+
* that it's the last one attempted after no other routes matched.
|
|
414
|
+
*
|
|
415
|
+
* @returns An Express request handler
|
|
416
|
+
*/
|
|
417
|
+
notFound() {
|
|
418
|
+
return (_req, res) => {
|
|
419
|
+
res.status(404).end();
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Returns the compression middleware.
|
|
424
|
+
*
|
|
425
|
+
* @remarks
|
|
426
|
+
*
|
|
427
|
+
* The middleware will attempt to compress response bodies for all requests
|
|
428
|
+
* that traverse through the middleware.
|
|
429
|
+
*/
|
|
430
|
+
compression() {
|
|
431
|
+
return compression__default["default"]();
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Returns a request logging middleware.
|
|
435
|
+
*
|
|
436
|
+
* @remarks
|
|
437
|
+
*
|
|
438
|
+
* Typically you want to place this middleware at the start of the chain, such
|
|
439
|
+
* that it always logs requests whether they are "caught" by handlers farther
|
|
440
|
+
* down or not.
|
|
441
|
+
*
|
|
442
|
+
* @returns An Express request handler
|
|
443
|
+
*/
|
|
444
|
+
logging() {
|
|
445
|
+
const logger = __privateGet$5(this, _logger).child({
|
|
446
|
+
type: "incomingRequest"
|
|
447
|
+
});
|
|
448
|
+
return morgan__default["default"]("combined", {
|
|
449
|
+
stream: {
|
|
450
|
+
write(message) {
|
|
451
|
+
logger.info(message.trimEnd());
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Returns a middleware that implements the helmet library.
|
|
458
|
+
*
|
|
459
|
+
* @remarks
|
|
460
|
+
*
|
|
461
|
+
* This middleware applies security policies to incoming requests and outgoing
|
|
462
|
+
* responses. It is configured using config keys such as `backend.csp`.
|
|
463
|
+
*
|
|
464
|
+
* @see {@link https://helmetjs.github.io/}
|
|
465
|
+
*
|
|
466
|
+
* @returns An Express request handler
|
|
467
|
+
*/
|
|
468
|
+
helmet() {
|
|
469
|
+
return helmet__default["default"](readHelmetOptions(__privateGet$5(this, _config).getOptionalConfig("backend")));
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Returns a middleware that implements the cors library.
|
|
473
|
+
*
|
|
474
|
+
* @remarks
|
|
475
|
+
*
|
|
476
|
+
* This middleware handles CORS. It is configured using the config key
|
|
477
|
+
* `backend.cors`.
|
|
478
|
+
*
|
|
479
|
+
* @see {@link https://github.com/expressjs/cors}
|
|
480
|
+
*
|
|
481
|
+
* @returns An Express request handler
|
|
482
|
+
*/
|
|
483
|
+
cors() {
|
|
484
|
+
return cors__default["default"](readCorsOptions(__privateGet$5(this, _config).getOptionalConfig("backend")));
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Express middleware to handle errors during request processing.
|
|
488
|
+
*
|
|
489
|
+
* @remarks
|
|
490
|
+
*
|
|
491
|
+
* This is commonly the very last middleware in the chain.
|
|
492
|
+
*
|
|
493
|
+
* Its primary purpose is not to do translation of business logic exceptions,
|
|
494
|
+
* but rather to be a global catch-all for uncaught "fatal" errors that are
|
|
495
|
+
* expected to result in a 500 error. However, it also does handle some common
|
|
496
|
+
* error types (such as http-error exceptions, and the well-known error types
|
|
497
|
+
* in the `@backstage/errors` package) and returns the enclosed status code
|
|
498
|
+
* accordingly.
|
|
499
|
+
*
|
|
500
|
+
* It will also produce a response body with a serialized form of the error,
|
|
501
|
+
* unless a previous handler already did send a body. See
|
|
502
|
+
* {@link @backstage/errors#ErrorResponseBody} for the response shape used.
|
|
503
|
+
*
|
|
504
|
+
* @returns An Express error request handler
|
|
505
|
+
*/
|
|
506
|
+
error(options = {}) {
|
|
507
|
+
var _a;
|
|
508
|
+
const showStackTraces = (_a = options.showStackTraces) != null ? _a : process.env.NODE_ENV === "development";
|
|
509
|
+
const logger = __privateGet$5(this, _logger).child({
|
|
510
|
+
type: "errorHandler"
|
|
511
|
+
});
|
|
512
|
+
return (error, req, res, next) => {
|
|
513
|
+
const statusCode = getStatusCode(error);
|
|
514
|
+
if (options.logAllErrors || statusCode >= 500) {
|
|
515
|
+
logger.error(`Request failed with status ${statusCode}`, error);
|
|
516
|
+
}
|
|
517
|
+
if (res.headersSent) {
|
|
518
|
+
next(error);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
const body = {
|
|
522
|
+
error: errors.serializeError(error, { includeStack: showStackTraces }),
|
|
523
|
+
request: { method: req.method, url: req.url },
|
|
524
|
+
response: { statusCode }
|
|
525
|
+
};
|
|
526
|
+
res.status(statusCode).json(body);
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
let MiddlewareFactory = _MiddlewareFactory;
|
|
531
|
+
_config = new WeakMap();
|
|
532
|
+
_logger = new WeakMap();
|
|
533
|
+
function getStatusCode(error) {
|
|
534
|
+
const knownStatusCodeFields = ["statusCode", "status"];
|
|
535
|
+
for (const field of knownStatusCodeFields) {
|
|
536
|
+
const statusCode = error[field];
|
|
537
|
+
if (typeof statusCode === "number" && (statusCode | 0) === statusCode && // is whole integer
|
|
538
|
+
statusCode >= 100 && statusCode <= 599) {
|
|
539
|
+
return statusCode;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
switch (error.name) {
|
|
543
|
+
case errors.NotModifiedError.name:
|
|
544
|
+
return 304;
|
|
545
|
+
case errors.InputError.name:
|
|
546
|
+
return 400;
|
|
547
|
+
case errors.AuthenticationError.name:
|
|
548
|
+
return 401;
|
|
549
|
+
case errors.NotAllowedError.name:
|
|
550
|
+
return 403;
|
|
551
|
+
case errors.NotFoundError.name:
|
|
552
|
+
return 404;
|
|
553
|
+
case errors.ConflictError.name:
|
|
554
|
+
return 409;
|
|
555
|
+
}
|
|
556
|
+
return 500;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
var __accessCheck$4 = (obj, member, msg) => {
|
|
560
|
+
if (!member.has(obj))
|
|
561
|
+
throw TypeError("Cannot " + msg);
|
|
562
|
+
};
|
|
563
|
+
var __privateGet$4 = (obj, member, getter) => {
|
|
564
|
+
__accessCheck$4(obj, member, "read from private field");
|
|
565
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
566
|
+
};
|
|
567
|
+
var __privateAdd$4 = (obj, member, value) => {
|
|
568
|
+
if (member.has(obj))
|
|
569
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
570
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
571
|
+
};
|
|
572
|
+
var __privateSet$4 = (obj, member, value, setter) => {
|
|
573
|
+
__accessCheck$4(obj, member, "write to private field");
|
|
31
574
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
32
575
|
return value;
|
|
33
576
|
};
|
|
@@ -36,26 +579,27 @@ const CALLBACKS = ["SIGTERM", "SIGINT", "beforeExit"];
|
|
|
36
579
|
class BackendLifecycleImpl {
|
|
37
580
|
constructor(logger) {
|
|
38
581
|
this.logger = logger;
|
|
39
|
-
__privateAdd$
|
|
40
|
-
__privateAdd$
|
|
582
|
+
__privateAdd$4(this, _isCalled, false);
|
|
583
|
+
__privateAdd$4(this, _shutdownTasks, []);
|
|
41
584
|
CALLBACKS.map((signal) => process.on(signal, () => this.shutdown()));
|
|
42
585
|
}
|
|
43
586
|
addShutdownHook(options) {
|
|
44
|
-
__privateGet$
|
|
587
|
+
__privateGet$4(this, _shutdownTasks).push(options);
|
|
45
588
|
}
|
|
46
589
|
async shutdown() {
|
|
47
|
-
if (__privateGet$
|
|
590
|
+
if (__privateGet$4(this, _isCalled)) {
|
|
48
591
|
return;
|
|
49
592
|
}
|
|
50
|
-
__privateSet$
|
|
51
|
-
this.logger.info(`Running ${__privateGet$
|
|
593
|
+
__privateSet$4(this, _isCalled, true);
|
|
594
|
+
this.logger.info(`Running ${__privateGet$4(this, _shutdownTasks).length} shutdown tasks...`);
|
|
52
595
|
await Promise.all(
|
|
53
|
-
__privateGet$
|
|
596
|
+
__privateGet$4(this, _shutdownTasks).map(async (hook) => {
|
|
597
|
+
const { logger = this.logger } = hook;
|
|
54
598
|
try {
|
|
55
599
|
await hook.fn();
|
|
56
|
-
|
|
600
|
+
logger.info(`Shutdown hook succeeded`);
|
|
57
601
|
} catch (error) {
|
|
58
|
-
|
|
602
|
+
logger.error(`Shutdown hook failed, ${error}`);
|
|
59
603
|
}
|
|
60
604
|
})
|
|
61
605
|
);
|
|
@@ -69,61 +613,61 @@ const rootLifecycleFactory = backendPluginApi.createServiceFactory({
|
|
|
69
613
|
logger: backendPluginApi.coreServices.rootLogger
|
|
70
614
|
},
|
|
71
615
|
async factory({ logger }) {
|
|
72
|
-
return new BackendLifecycleImpl(
|
|
616
|
+
return new BackendLifecycleImpl(logger);
|
|
73
617
|
}
|
|
74
618
|
});
|
|
75
619
|
|
|
76
|
-
var __accessCheck$
|
|
620
|
+
var __accessCheck$3 = (obj, member, msg) => {
|
|
77
621
|
if (!member.has(obj))
|
|
78
622
|
throw TypeError("Cannot " + msg);
|
|
79
623
|
};
|
|
80
|
-
var __privateGet$
|
|
81
|
-
__accessCheck$
|
|
624
|
+
var __privateGet$3 = (obj, member, getter) => {
|
|
625
|
+
__accessCheck$3(obj, member, "read from private field");
|
|
82
626
|
return getter ? getter.call(obj) : member.get(obj);
|
|
83
627
|
};
|
|
84
|
-
var __privateAdd$
|
|
628
|
+
var __privateAdd$3 = (obj, member, value) => {
|
|
85
629
|
if (member.has(obj))
|
|
86
630
|
throw TypeError("Cannot add the same private member more than once");
|
|
87
631
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
88
632
|
};
|
|
89
|
-
var __privateSet$
|
|
90
|
-
__accessCheck$
|
|
633
|
+
var __privateSet$3 = (obj, member, value, setter) => {
|
|
634
|
+
__accessCheck$3(obj, member, "write to private field");
|
|
91
635
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
92
636
|
return value;
|
|
93
637
|
};
|
|
94
|
-
var __privateMethod$
|
|
95
|
-
__accessCheck$
|
|
638
|
+
var __privateMethod$2 = (obj, member, method) => {
|
|
639
|
+
__accessCheck$3(obj, member, "access private method");
|
|
96
640
|
return method;
|
|
97
641
|
};
|
|
98
642
|
var _started, _features, _registerInits, _extensionPoints, _serviceHolder, _getInitDeps, getInitDeps_fn, _resolveInitOrder, resolveInitOrder_fn;
|
|
99
643
|
class BackendInitializer {
|
|
100
644
|
constructor(serviceHolder) {
|
|
101
|
-
__privateAdd$
|
|
102
|
-
__privateAdd$
|
|
103
|
-
__privateAdd$
|
|
104
|
-
__privateAdd$
|
|
105
|
-
__privateAdd$
|
|
106
|
-
__privateAdd$
|
|
107
|
-
__privateAdd$
|
|
108
|
-
__privateSet$
|
|
645
|
+
__privateAdd$3(this, _getInitDeps);
|
|
646
|
+
__privateAdd$3(this, _resolveInitOrder);
|
|
647
|
+
__privateAdd$3(this, _started, false);
|
|
648
|
+
__privateAdd$3(this, _features, /* @__PURE__ */ new Map());
|
|
649
|
+
__privateAdd$3(this, _registerInits, new Array());
|
|
650
|
+
__privateAdd$3(this, _extensionPoints, /* @__PURE__ */ new Map());
|
|
651
|
+
__privateAdd$3(this, _serviceHolder, void 0);
|
|
652
|
+
__privateSet$3(this, _serviceHolder, serviceHolder);
|
|
109
653
|
}
|
|
110
654
|
add(feature, options) {
|
|
111
|
-
if (__privateGet$
|
|
655
|
+
if (__privateGet$3(this, _started)) {
|
|
112
656
|
throw new Error("feature can not be added after the backend has started");
|
|
113
657
|
}
|
|
114
|
-
__privateGet$
|
|
658
|
+
__privateGet$3(this, _features).set(feature, options);
|
|
115
659
|
}
|
|
116
660
|
async start() {
|
|
117
|
-
if (__privateGet$
|
|
661
|
+
if (__privateGet$3(this, _started)) {
|
|
118
662
|
throw new Error("Backend has already started");
|
|
119
663
|
}
|
|
120
|
-
__privateSet$
|
|
121
|
-
for (const ref of __privateGet$
|
|
664
|
+
__privateSet$3(this, _started, true);
|
|
665
|
+
for (const ref of __privateGet$3(this, _serviceHolder).getServiceRefs()) {
|
|
122
666
|
if (ref.scope === "root") {
|
|
123
|
-
await __privateGet$
|
|
667
|
+
await __privateGet$3(this, _serviceHolder).get(ref, "root");
|
|
124
668
|
}
|
|
125
669
|
}
|
|
126
|
-
for (const [feature] of __privateGet$
|
|
670
|
+
for (const [feature] of __privateGet$3(this, _features)) {
|
|
127
671
|
const provides = /* @__PURE__ */ new Set();
|
|
128
672
|
let registerInit = void 0;
|
|
129
673
|
feature.register({
|
|
@@ -131,10 +675,10 @@ class BackendInitializer {
|
|
|
131
675
|
if (registerInit) {
|
|
132
676
|
throw new Error("registerExtensionPoint called after registerInit");
|
|
133
677
|
}
|
|
134
|
-
if (__privateGet$
|
|
678
|
+
if (__privateGet$3(this, _extensionPoints).has(extensionPointRef)) {
|
|
135
679
|
throw new Error(`API ${extensionPointRef.id} already registered`);
|
|
136
680
|
}
|
|
137
|
-
__privateGet$
|
|
681
|
+
__privateGet$3(this, _extensionPoints).set(extensionPointRef, impl);
|
|
138
682
|
provides.add(extensionPointRef);
|
|
139
683
|
},
|
|
140
684
|
registerInit: (registerOptions) => {
|
|
@@ -155,19 +699,19 @@ class BackendInitializer {
|
|
|
155
699
|
`registerInit was not called by register in ${feature.id}`
|
|
156
700
|
);
|
|
157
701
|
}
|
|
158
|
-
__privateGet$
|
|
702
|
+
__privateGet$3(this, _registerInits).push(registerInit);
|
|
159
703
|
}
|
|
160
|
-
const orderedRegisterResults = __privateMethod$
|
|
704
|
+
const orderedRegisterResults = __privateMethod$2(this, _resolveInitOrder, resolveInitOrder_fn).call(this, __privateGet$3(this, _registerInits));
|
|
161
705
|
for (const registerInit of orderedRegisterResults) {
|
|
162
|
-
const deps = await __privateMethod$
|
|
706
|
+
const deps = await __privateMethod$2(this, _getInitDeps, getInitDeps_fn).call(this, registerInit.deps, registerInit.id);
|
|
163
707
|
await registerInit.init(deps);
|
|
164
708
|
}
|
|
165
709
|
}
|
|
166
710
|
async stop() {
|
|
167
|
-
if (!__privateGet$
|
|
711
|
+
if (!__privateGet$3(this, _started)) {
|
|
168
712
|
return;
|
|
169
713
|
}
|
|
170
|
-
const lifecycleService = await __privateGet$
|
|
714
|
+
const lifecycleService = await __privateGet$3(this, _serviceHolder).get(
|
|
171
715
|
backendPluginApi.coreServices.rootLifecycle,
|
|
172
716
|
"root"
|
|
173
717
|
);
|
|
@@ -188,13 +732,13 @@ getInitDeps_fn = async function(deps, pluginId) {
|
|
|
188
732
|
const result = /* @__PURE__ */ new Map();
|
|
189
733
|
const missingRefs = /* @__PURE__ */ new Set();
|
|
190
734
|
for (const [name, ref] of Object.entries(deps)) {
|
|
191
|
-
const extensionPoint = __privateGet$
|
|
735
|
+
const extensionPoint = __privateGet$3(this, _extensionPoints).get(
|
|
192
736
|
ref
|
|
193
737
|
);
|
|
194
738
|
if (extensionPoint) {
|
|
195
739
|
result.set(name, extensionPoint);
|
|
196
740
|
} else {
|
|
197
|
-
const impl = await __privateGet$
|
|
741
|
+
const impl = await __privateGet$3(this, _serviceHolder).get(
|
|
198
742
|
ref,
|
|
199
743
|
pluginId
|
|
200
744
|
);
|
|
@@ -238,59 +782,51 @@ resolveInitOrder_fn = function(registerInits) {
|
|
|
238
782
|
return orderedRegisterInits;
|
|
239
783
|
};
|
|
240
784
|
|
|
241
|
-
var __accessCheck$
|
|
785
|
+
var __accessCheck$2 = (obj, member, msg) => {
|
|
242
786
|
if (!member.has(obj))
|
|
243
787
|
throw TypeError("Cannot " + msg);
|
|
244
788
|
};
|
|
245
|
-
var __privateGet$
|
|
246
|
-
__accessCheck$
|
|
789
|
+
var __privateGet$2 = (obj, member, getter) => {
|
|
790
|
+
__accessCheck$2(obj, member, "read from private field");
|
|
247
791
|
return getter ? getter.call(obj) : member.get(obj);
|
|
248
792
|
};
|
|
249
|
-
var __privateAdd$
|
|
793
|
+
var __privateAdd$2 = (obj, member, value) => {
|
|
250
794
|
if (member.has(obj))
|
|
251
795
|
throw TypeError("Cannot add the same private member more than once");
|
|
252
796
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
253
797
|
};
|
|
254
|
-
var __privateSet$
|
|
255
|
-
__accessCheck$
|
|
798
|
+
var __privateSet$2 = (obj, member, value, setter) => {
|
|
799
|
+
__accessCheck$2(obj, member, "write to private field");
|
|
256
800
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
257
801
|
return value;
|
|
258
802
|
};
|
|
259
|
-
var __privateMethod = (obj, member, method) => {
|
|
260
|
-
__accessCheck$
|
|
803
|
+
var __privateMethod$1 = (obj, member, method) => {
|
|
804
|
+
__accessCheck$2(obj, member, "access private method");
|
|
261
805
|
return method;
|
|
262
806
|
};
|
|
263
807
|
var _providedFactories, _loadedDefaultFactories, _implementations, _resolveFactory, resolveFactory_fn, _separateMapForTheRootService, _checkForMissingDeps, checkForMissingDeps_fn;
|
|
264
808
|
class ServiceRegistry {
|
|
265
809
|
constructor(factories) {
|
|
266
|
-
__privateAdd$
|
|
267
|
-
__privateAdd$
|
|
268
|
-
__privateAdd$
|
|
269
|
-
__privateAdd$
|
|
270
|
-
__privateAdd$
|
|
271
|
-
__privateAdd$
|
|
272
|
-
__privateSet$
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const cf = f();
|
|
276
|
-
return [cf.service.id, cf];
|
|
277
|
-
}
|
|
278
|
-
return [f.service.id, f];
|
|
279
|
-
})
|
|
280
|
-
));
|
|
281
|
-
__privateSet$1(this, _loadedDefaultFactories, /* @__PURE__ */ new Map());
|
|
282
|
-
__privateSet$1(this, _implementations, /* @__PURE__ */ new Map());
|
|
810
|
+
__privateAdd$2(this, _resolveFactory);
|
|
811
|
+
__privateAdd$2(this, _checkForMissingDeps);
|
|
812
|
+
__privateAdd$2(this, _providedFactories, void 0);
|
|
813
|
+
__privateAdd$2(this, _loadedDefaultFactories, void 0);
|
|
814
|
+
__privateAdd$2(this, _implementations, void 0);
|
|
815
|
+
__privateAdd$2(this, _separateMapForTheRootService, /* @__PURE__ */ new Map());
|
|
816
|
+
__privateSet$2(this, _providedFactories, new Map(factories.map((f) => [f.service.id, f])));
|
|
817
|
+
__privateSet$2(this, _loadedDefaultFactories, /* @__PURE__ */ new Map());
|
|
818
|
+
__privateSet$2(this, _implementations, /* @__PURE__ */ new Map());
|
|
283
819
|
}
|
|
284
820
|
getServiceRefs() {
|
|
285
|
-
return Array.from(__privateGet$
|
|
821
|
+
return Array.from(__privateGet$2(this, _providedFactories).values()).map((f) => f.service);
|
|
286
822
|
}
|
|
287
823
|
get(ref, pluginId) {
|
|
288
824
|
var _a;
|
|
289
|
-
return (_a = __privateMethod(this, _resolveFactory, resolveFactory_fn).call(this, ref, pluginId)) == null ? void 0 : _a.then((factory) => {
|
|
825
|
+
return (_a = __privateMethod$1(this, _resolveFactory, resolveFactory_fn).call(this, ref, pluginId)) == null ? void 0 : _a.then((factory) => {
|
|
290
826
|
if (factory.scope === "root") {
|
|
291
|
-
let existing = __privateGet$
|
|
827
|
+
let existing = __privateGet$2(this, _separateMapForTheRootService).get(factory);
|
|
292
828
|
if (!existing) {
|
|
293
|
-
__privateMethod(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
|
|
829
|
+
__privateMethod$1(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
|
|
294
830
|
const rootDeps = new Array();
|
|
295
831
|
for (const [name, serviceRef] of Object.entries(factory.deps)) {
|
|
296
832
|
if (serviceRef.scope !== "root") {
|
|
@@ -304,13 +840,13 @@ class ServiceRegistry {
|
|
|
304
840
|
existing = Promise.all(rootDeps).then(
|
|
305
841
|
(entries) => factory.factory(Object.fromEntries(entries))
|
|
306
842
|
);
|
|
307
|
-
__privateGet$
|
|
843
|
+
__privateGet$2(this, _separateMapForTheRootService).set(factory, existing);
|
|
308
844
|
}
|
|
309
845
|
return existing;
|
|
310
846
|
}
|
|
311
|
-
let implementation = __privateGet$
|
|
847
|
+
let implementation = __privateGet$2(this, _implementations).get(factory);
|
|
312
848
|
if (!implementation) {
|
|
313
|
-
__privateMethod(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
|
|
849
|
+
__privateMethod$1(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
|
|
314
850
|
const rootDeps = new Array();
|
|
315
851
|
for (const [name, serviceRef] of Object.entries(factory.deps)) {
|
|
316
852
|
if (serviceRef.scope === "root") {
|
|
@@ -327,7 +863,7 @@ class ServiceRegistry {
|
|
|
327
863
|
}),
|
|
328
864
|
byPlugin: /* @__PURE__ */ new Map()
|
|
329
865
|
};
|
|
330
|
-
__privateGet$
|
|
866
|
+
__privateGet$2(this, _implementations).set(factory, implementation);
|
|
331
867
|
}
|
|
332
868
|
let result = implementation.byPlugin.get(pluginId);
|
|
333
869
|
if (!result) {
|
|
@@ -369,18 +905,18 @@ resolveFactory_fn = function(ref, pluginId) {
|
|
|
369
905
|
})
|
|
370
906
|
});
|
|
371
907
|
}
|
|
372
|
-
let resolvedFactory = __privateGet$
|
|
908
|
+
let resolvedFactory = __privateGet$2(this, _providedFactories).get(ref.id);
|
|
373
909
|
const { __defaultFactory: defaultFactory } = ref;
|
|
374
910
|
if (!resolvedFactory && !defaultFactory) {
|
|
375
911
|
return void 0;
|
|
376
912
|
}
|
|
377
913
|
if (!resolvedFactory) {
|
|
378
|
-
let loadedFactory = __privateGet$
|
|
914
|
+
let loadedFactory = __privateGet$2(this, _loadedDefaultFactories).get(defaultFactory);
|
|
379
915
|
if (!loadedFactory) {
|
|
380
916
|
loadedFactory = Promise.resolve().then(() => defaultFactory(ref)).then(
|
|
381
917
|
(f) => typeof f === "function" ? f() : f
|
|
382
918
|
);
|
|
383
|
-
__privateGet$
|
|
919
|
+
__privateGet$2(this, _loadedDefaultFactories).set(defaultFactory, loadedFactory);
|
|
384
920
|
}
|
|
385
921
|
resolvedFactory = loadedFactory.catch((error) => {
|
|
386
922
|
throw new Error(
|
|
@@ -399,7 +935,7 @@ checkForMissingDeps_fn = function(factory, pluginId) {
|
|
|
399
935
|
if (ref.id === backendPluginApi.coreServices.pluginMetadata.id) {
|
|
400
936
|
return false;
|
|
401
937
|
}
|
|
402
|
-
if (__privateGet$
|
|
938
|
+
if (__privateGet$2(this, _providedFactories).get(ref.id)) {
|
|
403
939
|
return false;
|
|
404
940
|
}
|
|
405
941
|
return !ref.__defaultFactory;
|
|
@@ -412,51 +948,220 @@ checkForMissingDeps_fn = function(factory, pluginId) {
|
|
|
412
948
|
}
|
|
413
949
|
};
|
|
414
950
|
|
|
415
|
-
var __accessCheck = (obj, member, msg) => {
|
|
951
|
+
var __accessCheck$1 = (obj, member, msg) => {
|
|
416
952
|
if (!member.has(obj))
|
|
417
953
|
throw TypeError("Cannot " + msg);
|
|
418
954
|
};
|
|
419
|
-
var __privateGet = (obj, member, getter) => {
|
|
420
|
-
__accessCheck(obj, member, "read from private field");
|
|
955
|
+
var __privateGet$1 = (obj, member, getter) => {
|
|
956
|
+
__accessCheck$1(obj, member, "read from private field");
|
|
421
957
|
return getter ? getter.call(obj) : member.get(obj);
|
|
422
958
|
};
|
|
423
|
-
var __privateAdd = (obj, member, value) => {
|
|
959
|
+
var __privateAdd$1 = (obj, member, value) => {
|
|
424
960
|
if (member.has(obj))
|
|
425
961
|
throw TypeError("Cannot add the same private member more than once");
|
|
426
962
|
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
427
963
|
};
|
|
428
|
-
var __privateSet = (obj, member, value, setter) => {
|
|
429
|
-
__accessCheck(obj, member, "write to private field");
|
|
964
|
+
var __privateSet$1 = (obj, member, value, setter) => {
|
|
965
|
+
__accessCheck$1(obj, member, "write to private field");
|
|
430
966
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
431
967
|
return value;
|
|
432
968
|
};
|
|
433
969
|
var _services, _initializer;
|
|
434
970
|
class BackstageBackend {
|
|
435
971
|
constructor(apiFactories) {
|
|
436
|
-
__privateAdd(this, _services, void 0);
|
|
437
|
-
__privateAdd(this, _initializer, void 0);
|
|
438
|
-
__privateSet(this, _services, new ServiceRegistry(apiFactories));
|
|
439
|
-
__privateSet(this, _initializer, new BackendInitializer(__privateGet(this, _services)));
|
|
972
|
+
__privateAdd$1(this, _services, void 0);
|
|
973
|
+
__privateAdd$1(this, _initializer, void 0);
|
|
974
|
+
__privateSet$1(this, _services, new ServiceRegistry(apiFactories));
|
|
975
|
+
__privateSet$1(this, _initializer, new BackendInitializer(__privateGet$1(this, _services)));
|
|
440
976
|
}
|
|
441
977
|
add(feature) {
|
|
442
|
-
__privateGet(this, _initializer).add(feature);
|
|
978
|
+
__privateGet$1(this, _initializer).add(feature);
|
|
443
979
|
}
|
|
444
980
|
async start() {
|
|
445
|
-
await __privateGet(this, _initializer).start();
|
|
981
|
+
await __privateGet$1(this, _initializer).start();
|
|
446
982
|
}
|
|
447
983
|
async stop() {
|
|
448
|
-
await __privateGet(this, _initializer).stop();
|
|
984
|
+
await __privateGet$1(this, _initializer).stop();
|
|
449
985
|
}
|
|
450
986
|
}
|
|
451
987
|
_services = new WeakMap();
|
|
452
988
|
_initializer = new WeakMap();
|
|
453
989
|
|
|
454
990
|
function createSpecializedBackend(options) {
|
|
455
|
-
|
|
456
|
-
|
|
991
|
+
const services = options.services.map(
|
|
992
|
+
(sf) => typeof sf === "function" ? sf() : sf
|
|
457
993
|
);
|
|
994
|
+
const exists = /* @__PURE__ */ new Set();
|
|
995
|
+
const duplicates = /* @__PURE__ */ new Set();
|
|
996
|
+
for (const { service } of services) {
|
|
997
|
+
if (exists.has(service.id)) {
|
|
998
|
+
duplicates.add(service.id);
|
|
999
|
+
} else {
|
|
1000
|
+
exists.add(service.id);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
if (duplicates.size > 0) {
|
|
1004
|
+
const ids = Array.from(duplicates).join(", ");
|
|
1005
|
+
throw new Error(`Duplicate service implementations provided for ${ids}`);
|
|
1006
|
+
}
|
|
1007
|
+
if (exists.has(backendPluginApi.coreServices.pluginMetadata.id)) {
|
|
1008
|
+
throw new Error(
|
|
1009
|
+
`The ${backendPluginApi.coreServices.pluginMetadata.id} service cannot be overridden`
|
|
1010
|
+
);
|
|
1011
|
+
}
|
|
1012
|
+
return new BackstageBackend(services);
|
|
458
1013
|
}
|
|
459
1014
|
|
|
1015
|
+
const httpRouterFactory = backendPluginApi.createServiceFactory({
|
|
1016
|
+
service: backendPluginApi.coreServices.httpRouter,
|
|
1017
|
+
deps: {
|
|
1018
|
+
plugin: backendPluginApi.coreServices.pluginMetadata,
|
|
1019
|
+
rootHttpRouter: backendPluginApi.coreServices.rootHttpRouter
|
|
1020
|
+
},
|
|
1021
|
+
async factory({ rootHttpRouter }, options) {
|
|
1022
|
+
var _a;
|
|
1023
|
+
const getPath = (_a = options == null ? void 0 : options.getPath) != null ? _a : (id) => `/api/${id}`;
|
|
1024
|
+
return async ({ plugin }) => {
|
|
1025
|
+
const path = getPath(plugin.getId());
|
|
1026
|
+
return {
|
|
1027
|
+
use(handler) {
|
|
1028
|
+
rootHttpRouter.use(path, handler);
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
var __accessCheck = (obj, member, msg) => {
|
|
1036
|
+
if (!member.has(obj))
|
|
1037
|
+
throw TypeError("Cannot " + msg);
|
|
1038
|
+
};
|
|
1039
|
+
var __privateGet = (obj, member, getter) => {
|
|
1040
|
+
__accessCheck(obj, member, "read from private field");
|
|
1041
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
1042
|
+
};
|
|
1043
|
+
var __privateAdd = (obj, member, value) => {
|
|
1044
|
+
if (member.has(obj))
|
|
1045
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
1046
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1047
|
+
};
|
|
1048
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
1049
|
+
__accessCheck(obj, member, "write to private field");
|
|
1050
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1051
|
+
return value;
|
|
1052
|
+
};
|
|
1053
|
+
var __privateMethod = (obj, member, method) => {
|
|
1054
|
+
__accessCheck(obj, member, "access private method");
|
|
1055
|
+
return method;
|
|
1056
|
+
};
|
|
1057
|
+
var _indexPath, _router, _namedRoutes, _indexRouter, _existingPaths, _findConflictingPath, findConflictingPath_fn;
|
|
1058
|
+
function normalizePath(path) {
|
|
1059
|
+
return path.replace(/\/*$/, "/");
|
|
1060
|
+
}
|
|
1061
|
+
class RestrictedIndexedRouter {
|
|
1062
|
+
constructor(indexPath) {
|
|
1063
|
+
__privateAdd(this, _findConflictingPath);
|
|
1064
|
+
__privateAdd(this, _indexPath, void 0);
|
|
1065
|
+
__privateAdd(this, _router, express.Router());
|
|
1066
|
+
__privateAdd(this, _namedRoutes, express.Router());
|
|
1067
|
+
__privateAdd(this, _indexRouter, express.Router());
|
|
1068
|
+
__privateAdd(this, _existingPaths, new Array());
|
|
1069
|
+
__privateSet(this, _indexPath, indexPath);
|
|
1070
|
+
__privateGet(this, _router).use(__privateGet(this, _namedRoutes));
|
|
1071
|
+
__privateGet(this, _router).use(__privateGet(this, _indexRouter));
|
|
1072
|
+
}
|
|
1073
|
+
use(path, handler) {
|
|
1074
|
+
if (path.match(/^[/\s]*$/)) {
|
|
1075
|
+
throw new Error(`Root router path may not be empty`);
|
|
1076
|
+
}
|
|
1077
|
+
const conflictingPath = __privateMethod(this, _findConflictingPath, findConflictingPath_fn).call(this, path);
|
|
1078
|
+
if (conflictingPath) {
|
|
1079
|
+
throw new Error(
|
|
1080
|
+
`Path ${path} conflicts with the existing path ${conflictingPath}`
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
__privateGet(this, _existingPaths).push(path);
|
|
1084
|
+
__privateGet(this, _namedRoutes).use(path, handler);
|
|
1085
|
+
if (__privateGet(this, _indexPath) === path) {
|
|
1086
|
+
__privateGet(this, _indexRouter).use(handler);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
handler() {
|
|
1090
|
+
return __privateGet(this, _router);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
_indexPath = new WeakMap();
|
|
1094
|
+
_router = new WeakMap();
|
|
1095
|
+
_namedRoutes = new WeakMap();
|
|
1096
|
+
_indexRouter = new WeakMap();
|
|
1097
|
+
_existingPaths = new WeakMap();
|
|
1098
|
+
_findConflictingPath = new WeakSet();
|
|
1099
|
+
findConflictingPath_fn = function(newPath) {
|
|
1100
|
+
const normalizedNewPath = normalizePath(newPath);
|
|
1101
|
+
for (const path of __privateGet(this, _existingPaths)) {
|
|
1102
|
+
const normalizedPath = normalizePath(path);
|
|
1103
|
+
if (normalizedPath.startsWith(normalizedNewPath)) {
|
|
1104
|
+
return path;
|
|
1105
|
+
}
|
|
1106
|
+
if (normalizedNewPath.startsWith(normalizedPath)) {
|
|
1107
|
+
return path;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
return void 0;
|
|
1111
|
+
};
|
|
1112
|
+
|
|
1113
|
+
function defaultConfigure({
|
|
1114
|
+
app,
|
|
1115
|
+
routes,
|
|
1116
|
+
middleware
|
|
1117
|
+
}) {
|
|
1118
|
+
app.use(middleware.helmet());
|
|
1119
|
+
app.use(middleware.cors());
|
|
1120
|
+
app.use(middleware.compression());
|
|
1121
|
+
app.use(middleware.logging());
|
|
1122
|
+
app.use(routes);
|
|
1123
|
+
app.use(middleware.notFound());
|
|
1124
|
+
app.use(middleware.error());
|
|
1125
|
+
}
|
|
1126
|
+
const rootHttpRouterFactory = backendPluginApi.createServiceFactory({
|
|
1127
|
+
service: backendPluginApi.coreServices.rootHttpRouter,
|
|
1128
|
+
deps: {
|
|
1129
|
+
config: backendPluginApi.coreServices.config,
|
|
1130
|
+
rootLogger: backendPluginApi.coreServices.rootLogger,
|
|
1131
|
+
lifecycle: backendPluginApi.coreServices.rootLifecycle
|
|
1132
|
+
},
|
|
1133
|
+
async factory({ config, rootLogger, lifecycle }, {
|
|
1134
|
+
indexPath,
|
|
1135
|
+
configure = defaultConfigure
|
|
1136
|
+
} = {}) {
|
|
1137
|
+
const router = new RestrictedIndexedRouter(indexPath != null ? indexPath : "/api/app");
|
|
1138
|
+
const logger = rootLogger.child({ service: "rootHttpRouter" });
|
|
1139
|
+
const app = express__default["default"]();
|
|
1140
|
+
const middleware = MiddlewareFactory.create({ config, logger });
|
|
1141
|
+
configure({
|
|
1142
|
+
app,
|
|
1143
|
+
routes: router.handler(),
|
|
1144
|
+
middleware,
|
|
1145
|
+
config,
|
|
1146
|
+
logger,
|
|
1147
|
+
lifecycle
|
|
1148
|
+
});
|
|
1149
|
+
const server = await createHttpServer(
|
|
1150
|
+
app,
|
|
1151
|
+
readHttpServerOptions(config.getOptionalConfig("backend")),
|
|
1152
|
+
{ logger }
|
|
1153
|
+
);
|
|
1154
|
+
lifecycle.addShutdownHook({
|
|
1155
|
+
async fn() {
|
|
1156
|
+
await server.stop();
|
|
1157
|
+
},
|
|
1158
|
+
logger
|
|
1159
|
+
});
|
|
1160
|
+
await server.start();
|
|
1161
|
+
return router;
|
|
1162
|
+
}
|
|
1163
|
+
});
|
|
1164
|
+
|
|
460
1165
|
const cacheFactory = backendPluginApi.createServiceFactory({
|
|
461
1166
|
service: backendPluginApi.coreServices.cache,
|
|
462
1167
|
deps: {
|
|
@@ -479,7 +1184,7 @@ const configFactory = backendPluginApi.createServiceFactory({
|
|
|
479
1184
|
async factory({ logger }) {
|
|
480
1185
|
const config = await backendCommon.loadBackendConfig({
|
|
481
1186
|
argv: process.argv,
|
|
482
|
-
logger:
|
|
1187
|
+
logger: backendCommon.loggerToWinstonLogger(logger)
|
|
483
1188
|
});
|
|
484
1189
|
return config;
|
|
485
1190
|
}
|
|
@@ -520,7 +1225,7 @@ const loggerFactory = backendPluginApi.createServiceFactory({
|
|
|
520
1225
|
},
|
|
521
1226
|
async factory({ rootLogger }) {
|
|
522
1227
|
return async ({ plugin }) => {
|
|
523
|
-
return rootLogger.child({
|
|
1228
|
+
return rootLogger.child({ plugin: plugin.getId() });
|
|
524
1229
|
};
|
|
525
1230
|
}
|
|
526
1231
|
});
|
|
@@ -596,7 +1301,7 @@ const tokenManagerFactory = backendPluginApi.createServiceFactory({
|
|
|
596
1301
|
async factory() {
|
|
597
1302
|
return async ({ config, logger }) => {
|
|
598
1303
|
return backendCommon.ServerTokenManager.fromConfig(config, {
|
|
599
|
-
logger:
|
|
1304
|
+
logger: backendCommon.loggerToWinstonLogger(logger)
|
|
600
1305
|
});
|
|
601
1306
|
};
|
|
602
1307
|
}
|
|
@@ -612,54 +1317,28 @@ const urlReaderFactory = backendPluginApi.createServiceFactory({
|
|
|
612
1317
|
return async ({ config, logger }) => {
|
|
613
1318
|
return backendCommon.UrlReaders.default({
|
|
614
1319
|
config,
|
|
615
|
-
logger:
|
|
1320
|
+
logger: backendCommon.loggerToWinstonLogger(logger)
|
|
616
1321
|
});
|
|
617
1322
|
};
|
|
618
1323
|
}
|
|
619
1324
|
});
|
|
620
1325
|
|
|
621
|
-
const httpRouterFactory = backendPluginApi.createServiceFactory({
|
|
622
|
-
service: backendPluginApi.coreServices.httpRouter,
|
|
623
|
-
deps: {
|
|
624
|
-
config: backendPluginApi.coreServices.config,
|
|
625
|
-
plugin: backendPluginApi.coreServices.pluginMetadata
|
|
626
|
-
},
|
|
627
|
-
async factory({ config }, options) {
|
|
628
|
-
var _a;
|
|
629
|
-
const defaultPluginId = (_a = options == null ? void 0 : options.indexPlugin) != null ? _a : "app";
|
|
630
|
-
const apiRouter = Router__default["default"]();
|
|
631
|
-
const rootRouter = Router__default["default"]();
|
|
632
|
-
const service = backendCommon.createServiceBuilder(module).loadConfig(config).addRouter("/api", apiRouter).addRouter("", rootRouter);
|
|
633
|
-
await service.start();
|
|
634
|
-
return async ({ plugin }) => {
|
|
635
|
-
const pluginId = plugin.getId();
|
|
636
|
-
return {
|
|
637
|
-
use(handler) {
|
|
638
|
-
if (pluginId === defaultPluginId) {
|
|
639
|
-
rootRouter.use(handler);
|
|
640
|
-
} else {
|
|
641
|
-
apiRouter.use(`/${pluginId}`, handler);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
};
|
|
645
|
-
};
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
|
|
649
1326
|
const lifecycleFactory = backendPluginApi.createServiceFactory({
|
|
650
1327
|
service: backendPluginApi.coreServices.lifecycle,
|
|
651
1328
|
deps: {
|
|
1329
|
+
logger: backendPluginApi.coreServices.logger,
|
|
652
1330
|
rootLifecycle: backendPluginApi.coreServices.rootLifecycle,
|
|
653
1331
|
pluginMetadata: backendPluginApi.coreServices.pluginMetadata
|
|
654
1332
|
},
|
|
655
1333
|
async factory({ rootLifecycle }) {
|
|
656
|
-
return async ({ pluginMetadata }) => {
|
|
1334
|
+
return async ({ logger, pluginMetadata }) => {
|
|
657
1335
|
const plugin = pluginMetadata.getId();
|
|
658
1336
|
return {
|
|
659
1337
|
addShutdownHook(options) {
|
|
1338
|
+
var _a, _b;
|
|
660
1339
|
rootLifecycle.addShutdownHook({
|
|
661
1340
|
...options,
|
|
662
|
-
|
|
1341
|
+
logger: (_b = (_a = options.logger) == null ? void 0 : _a.child({ plugin })) != null ? _b : logger
|
|
663
1342
|
});
|
|
664
1343
|
}
|
|
665
1344
|
};
|
|
@@ -667,8 +1346,10 @@ const lifecycleFactory = backendPluginApi.createServiceFactory({
|
|
|
667
1346
|
}
|
|
668
1347
|
});
|
|
669
1348
|
|
|
1349
|
+
exports.MiddlewareFactory = MiddlewareFactory;
|
|
670
1350
|
exports.cacheFactory = cacheFactory;
|
|
671
1351
|
exports.configFactory = configFactory;
|
|
1352
|
+
exports.createHttpServer = createHttpServer;
|
|
672
1353
|
exports.createSpecializedBackend = createSpecializedBackend;
|
|
673
1354
|
exports.databaseFactory = databaseFactory;
|
|
674
1355
|
exports.discoveryFactory = discoveryFactory;
|
|
@@ -676,6 +1357,10 @@ exports.httpRouterFactory = httpRouterFactory;
|
|
|
676
1357
|
exports.lifecycleFactory = lifecycleFactory;
|
|
677
1358
|
exports.loggerFactory = loggerFactory;
|
|
678
1359
|
exports.permissionsFactory = permissionsFactory;
|
|
1360
|
+
exports.readCorsOptions = readCorsOptions;
|
|
1361
|
+
exports.readHelmetOptions = readHelmetOptions;
|
|
1362
|
+
exports.readHttpServerOptions = readHttpServerOptions;
|
|
1363
|
+
exports.rootHttpRouterFactory = rootHttpRouterFactory;
|
|
679
1364
|
exports.rootLifecycleFactory = rootLifecycleFactory;
|
|
680
1365
|
exports.rootLoggerFactory = rootLoggerFactory;
|
|
681
1366
|
exports.schedulerFactory = schedulerFactory;
|