@backstage/backend-app-api 0.3.0-next.1 → 0.3.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.

Potentially problematic release.


This version of @backstage/backend-app-api might be problematic. Click here for more details.

package/dist/index.cjs.js CHANGED
@@ -2,11 +2,16 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var path = require('path');
6
+ var parseArgs = require('minimist');
7
+ var cliCommon = require('@backstage/cli-common');
8
+ var configLoader = require('@backstage/config-loader');
9
+ var config = require('@backstage/config');
10
+ var getPackages = require('@manypkg/get-packages');
5
11
  var http = require('http');
6
12
  var https = require('https');
7
13
  var stoppableServer = require('stoppable');
8
14
  var fs = require('fs-extra');
9
- var path = require('path');
10
15
  var forge = require('node-forge');
11
16
  var cors = require('cors');
12
17
  var helmet = require('helmet');
@@ -14,10 +19,13 @@ var morgan = require('morgan');
14
19
  var compression = require('compression');
15
20
  var minimatch = require('minimatch');
16
21
  var errors = require('@backstage/errors');
22
+ var winston = require('winston');
17
23
  var backendPluginApi = require('@backstage/backend-plugin-api');
18
- var express = require('express');
19
24
  var backendCommon = require('@backstage/backend-common');
25
+ var pluginAuthNode = require('@backstage/plugin-auth-node');
20
26
  var pluginPermissionNode = require('@backstage/plugin-permission-node');
27
+ var express = require('express');
28
+ var trimEnd = require('lodash/trimEnd');
21
29
  var backendTasks = require('@backstage/backend-tasks');
22
30
 
23
31
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -40,6 +48,7 @@ function _interopNamespace(e) {
40
48
  return Object.freeze(n);
41
49
  }
42
50
 
51
+ var parseArgs__default = /*#__PURE__*/_interopDefaultLegacy(parseArgs);
43
52
  var http__namespace = /*#__PURE__*/_interopNamespace(http);
44
53
  var https__namespace = /*#__PURE__*/_interopNamespace(https);
45
54
  var stoppableServer__default = /*#__PURE__*/_interopDefaultLegacy(stoppableServer);
@@ -50,6 +59,187 @@ var helmet__default = /*#__PURE__*/_interopDefaultLegacy(helmet);
50
59
  var morgan__default = /*#__PURE__*/_interopDefaultLegacy(morgan);
51
60
  var compression__default = /*#__PURE__*/_interopDefaultLegacy(compression);
52
61
  var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
62
+ var trimEnd__default = /*#__PURE__*/_interopDefaultLegacy(trimEnd);
63
+
64
+ class ObservableConfigProxy {
65
+ constructor(parent, parentKey) {
66
+ this.parent = parent;
67
+ this.parentKey = parentKey;
68
+ this.config = new config.ConfigReader({});
69
+ this.subscribers = [];
70
+ if (parent && !parentKey) {
71
+ throw new Error("parentKey is required if parent is set");
72
+ }
73
+ }
74
+ setConfig(config) {
75
+ if (this.parent) {
76
+ throw new Error("immutable");
77
+ }
78
+ this.config = config;
79
+ for (const subscriber of this.subscribers) {
80
+ try {
81
+ subscriber();
82
+ } catch (error) {
83
+ console.error(`Config subscriber threw error, ${error}`);
84
+ }
85
+ }
86
+ }
87
+ subscribe(onChange) {
88
+ if (this.parent) {
89
+ return this.parent.subscribe(onChange);
90
+ }
91
+ this.subscribers.push(onChange);
92
+ return {
93
+ unsubscribe: () => {
94
+ const index = this.subscribers.indexOf(onChange);
95
+ if (index >= 0) {
96
+ this.subscribers.splice(index, 1);
97
+ }
98
+ }
99
+ };
100
+ }
101
+ select(required) {
102
+ var _a;
103
+ if (this.parent && this.parentKey) {
104
+ if (required) {
105
+ return this.parent.select(true).getConfig(this.parentKey);
106
+ }
107
+ return (_a = this.parent.select(false)) == null ? void 0 : _a.getOptionalConfig(this.parentKey);
108
+ }
109
+ return this.config;
110
+ }
111
+ has(key) {
112
+ var _a, _b;
113
+ return (_b = (_a = this.select(false)) == null ? void 0 : _a.has(key)) != null ? _b : false;
114
+ }
115
+ keys() {
116
+ var _a, _b;
117
+ return (_b = (_a = this.select(false)) == null ? void 0 : _a.keys()) != null ? _b : [];
118
+ }
119
+ get(key) {
120
+ return this.select(true).get(key);
121
+ }
122
+ getOptional(key) {
123
+ var _a;
124
+ return (_a = this.select(false)) == null ? void 0 : _a.getOptional(key);
125
+ }
126
+ getConfig(key) {
127
+ return new ObservableConfigProxy(this, key);
128
+ }
129
+ getOptionalConfig(key) {
130
+ var _a;
131
+ if ((_a = this.select(false)) == null ? void 0 : _a.has(key)) {
132
+ return new ObservableConfigProxy(this, key);
133
+ }
134
+ return void 0;
135
+ }
136
+ getConfigArray(key) {
137
+ return this.select(true).getConfigArray(key);
138
+ }
139
+ getOptionalConfigArray(key) {
140
+ var _a;
141
+ return (_a = this.select(false)) == null ? void 0 : _a.getOptionalConfigArray(key);
142
+ }
143
+ getNumber(key) {
144
+ return this.select(true).getNumber(key);
145
+ }
146
+ getOptionalNumber(key) {
147
+ var _a;
148
+ return (_a = this.select(false)) == null ? void 0 : _a.getOptionalNumber(key);
149
+ }
150
+ getBoolean(key) {
151
+ return this.select(true).getBoolean(key);
152
+ }
153
+ getOptionalBoolean(key) {
154
+ var _a;
155
+ return (_a = this.select(false)) == null ? void 0 : _a.getOptionalBoolean(key);
156
+ }
157
+ getString(key) {
158
+ return this.select(true).getString(key);
159
+ }
160
+ getOptionalString(key) {
161
+ var _a;
162
+ return (_a = this.select(false)) == null ? void 0 : _a.getOptionalString(key);
163
+ }
164
+ getStringArray(key) {
165
+ return this.select(true).getStringArray(key);
166
+ }
167
+ getOptionalStringArray(key) {
168
+ var _a;
169
+ return (_a = this.select(false)) == null ? void 0 : _a.getOptionalStringArray(key);
170
+ }
171
+ }
172
+
173
+ function isValidUrl(url) {
174
+ try {
175
+ new URL(url);
176
+ return true;
177
+ } catch {
178
+ return false;
179
+ }
180
+ }
181
+
182
+ async function createConfigSecretEnumerator(options) {
183
+ const { logger, dir = process.cwd() } = options;
184
+ const { packages } = await getPackages.getPackages(dir);
185
+ const schema = await configLoader.loadConfigSchema({
186
+ dependencies: packages.map((p) => p.packageJson.name)
187
+ });
188
+ return (config) => {
189
+ var _a;
190
+ const [secretsData] = schema.process(
191
+ [{ data: (_a = config.getOptional()) != null ? _a : {}, context: "schema-enumerator" }],
192
+ {
193
+ visibility: ["secret"],
194
+ ignoreSchemaErrors: true
195
+ }
196
+ );
197
+ const secrets = /* @__PURE__ */ new Set();
198
+ JSON.parse(
199
+ JSON.stringify(secretsData),
200
+ (_, v) => typeof v === "string" && secrets.add(v)
201
+ );
202
+ logger.info(
203
+ `Found ${secrets.size} new secrets in config that will be redacted`
204
+ );
205
+ return secrets;
206
+ };
207
+ }
208
+ async function loadBackendConfig(options) {
209
+ var _a;
210
+ const args = parseArgs__default["default"](options.argv);
211
+ const configTargets = [(_a = args.config) != null ? _a : []].flat().map((arg) => isValidUrl(arg) ? { url: arg } : { path: path.resolve(arg) });
212
+ const paths = cliCommon.findPaths(__dirname);
213
+ let currentCancelFunc = void 0;
214
+ const config$1 = new ObservableConfigProxy();
215
+ const { appConfigs } = await configLoader.loadConfig({
216
+ configRoot: paths.targetRoot,
217
+ configTargets,
218
+ remote: options.remote,
219
+ watch: {
220
+ onChange(newConfigs) {
221
+ console.info(
222
+ `Reloaded config from ${newConfigs.map((c) => c.context).join(", ")}`
223
+ );
224
+ config$1.setConfig(config.ConfigReader.fromConfigs(newConfigs));
225
+ },
226
+ stopSignal: new Promise((resolve) => {
227
+ if (currentCancelFunc) {
228
+ currentCancelFunc();
229
+ }
230
+ currentCancelFunc = resolve;
231
+ if (module.hot) {
232
+ module.hot.addDisposeHandler(resolve);
233
+ }
234
+ })
235
+ }
236
+ });
237
+ console.info(
238
+ `Loaded config from ${appConfigs.map((c) => c.context).join(", ")}`
239
+ );
240
+ config$1.setConfig(config.ConfigReader.fromConfigs(appConfigs));
241
+ return { config: config$1 };
242
+ }
53
243
 
54
244
  const DEFAULT_PORT = 7007;
55
245
  const DEFAULT_HOST = "";
@@ -337,7 +527,7 @@ function readCorsOptions(config) {
337
527
  if (!cc) {
338
528
  return { origin: false };
339
529
  }
340
- return {
530
+ return removeUnknown({
341
531
  origin: createCorsOriginMatcher(readStringArray(cc, "origin")),
342
532
  methods: readStringArray(cc, "methods"),
343
533
  allowedHeaders: readStringArray(cc, "allowedHeaders"),
@@ -346,7 +536,12 @@ function readCorsOptions(config) {
346
536
  maxAge: cc.getOptionalNumber("maxAge"),
347
537
  preflightContinue: cc.getOptionalBoolean("preflightContinue"),
348
538
  optionsSuccessStatus: cc.getOptionalNumber("optionsSuccessStatus")
349
- };
539
+ });
540
+ }
541
+ function removeUnknown(obj) {
542
+ return Object.fromEntries(
543
+ Object.entries(obj).filter(([, v]) => v !== void 0)
544
+ );
350
545
  }
351
546
  function readStringArray(config, key) {
352
547
  const value = config.getOptional(key);
@@ -372,31 +567,31 @@ function createCorsOriginMatcher(allowedOriginPatterns) {
372
567
  };
373
568
  }
374
569
 
375
- var __accessCheck$5 = (obj, member, msg) => {
570
+ var __accessCheck$6 = (obj, member, msg) => {
376
571
  if (!member.has(obj))
377
572
  throw TypeError("Cannot " + msg);
378
573
  };
379
- var __privateGet$5 = (obj, member, getter) => {
380
- __accessCheck$5(obj, member, "read from private field");
574
+ var __privateGet$6 = (obj, member, getter) => {
575
+ __accessCheck$6(obj, member, "read from private field");
381
576
  return getter ? getter.call(obj) : member.get(obj);
382
577
  };
383
- var __privateAdd$5 = (obj, member, value) => {
578
+ var __privateAdd$6 = (obj, member, value) => {
384
579
  if (member.has(obj))
385
580
  throw TypeError("Cannot add the same private member more than once");
386
581
  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
387
582
  };
388
- var __privateSet$5 = (obj, member, value, setter) => {
389
- __accessCheck$5(obj, member, "write to private field");
583
+ var __privateSet$6 = (obj, member, value, setter) => {
584
+ __accessCheck$6(obj, member, "write to private field");
390
585
  setter ? setter.call(obj, value) : member.set(obj, value);
391
586
  return value;
392
587
  };
393
588
  var _config, _logger;
394
589
  const _MiddlewareFactory = class {
395
590
  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);
591
+ __privateAdd$6(this, _config, void 0);
592
+ __privateAdd$6(this, _logger, void 0);
593
+ __privateSet$6(this, _config, options.config);
594
+ __privateSet$6(this, _logger, options.logger);
400
595
  }
401
596
  /**
402
597
  * Creates a new {@link MiddlewareFactory}.
@@ -442,7 +637,7 @@ const _MiddlewareFactory = class {
442
637
  * @returns An Express request handler
443
638
  */
444
639
  logging() {
445
- const logger = __privateGet$5(this, _logger).child({
640
+ const logger = __privateGet$6(this, _logger).child({
446
641
  type: "incomingRequest"
447
642
  });
448
643
  return morgan__default["default"]("combined", {
@@ -466,7 +661,7 @@ const _MiddlewareFactory = class {
466
661
  * @returns An Express request handler
467
662
  */
468
663
  helmet() {
469
- return helmet__default["default"](readHelmetOptions(__privateGet$5(this, _config).getOptionalConfig("backend")));
664
+ return helmet__default["default"](readHelmetOptions(__privateGet$6(this, _config).getOptionalConfig("backend")));
470
665
  }
471
666
  /**
472
667
  * Returns a middleware that implements the cors library.
@@ -481,7 +676,7 @@ const _MiddlewareFactory = class {
481
676
  * @returns An Express request handler
482
677
  */
483
678
  cors() {
484
- return cors__default["default"](readCorsOptions(__privateGet$5(this, _config).getOptionalConfig("backend")));
679
+ return cors__default["default"](readCorsOptions(__privateGet$6(this, _config).getOptionalConfig("backend")));
485
680
  }
486
681
  /**
487
682
  * Express middleware to handle errors during request processing.
@@ -506,7 +701,7 @@ const _MiddlewareFactory = class {
506
701
  error(options = {}) {
507
702
  var _a;
508
703
  const showStackTraces = (_a = options.showStackTraces) != null ? _a : process.env.NODE_ENV === "development";
509
- const logger = __privateGet$5(this, _logger).child({
704
+ const logger = __privateGet$6(this, _logger).child({
510
705
  type: "errorHandler"
511
706
  });
512
707
  return (error, req, res, next) => {
@@ -556,6 +751,132 @@ function getStatusCode(error) {
556
751
  return 500;
557
752
  }
558
753
 
754
+ var __accessCheck$5 = (obj, member, msg) => {
755
+ if (!member.has(obj))
756
+ throw TypeError("Cannot " + msg);
757
+ };
758
+ var __privateGet$5 = (obj, member, getter) => {
759
+ __accessCheck$5(obj, member, "read from private field");
760
+ return getter ? getter.call(obj) : member.get(obj);
761
+ };
762
+ var __privateAdd$5 = (obj, member, value) => {
763
+ if (member.has(obj))
764
+ throw TypeError("Cannot add the same private member more than once");
765
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
766
+ };
767
+ var __privateSet$5 = (obj, member, value, setter) => {
768
+ __accessCheck$5(obj, member, "write to private field");
769
+ setter ? setter.call(obj, value) : member.set(obj, value);
770
+ return value;
771
+ };
772
+ var _winston, _addRedactions;
773
+ const _WinstonLogger = class {
774
+ constructor(winston, addRedactions) {
775
+ __privateAdd$5(this, _winston, void 0);
776
+ __privateAdd$5(this, _addRedactions, void 0);
777
+ __privateSet$5(this, _winston, winston);
778
+ __privateSet$5(this, _addRedactions, addRedactions);
779
+ }
780
+ /**
781
+ * Creates a {@link WinstonLogger} instance.
782
+ */
783
+ static create(options) {
784
+ var _a;
785
+ const redacter = _WinstonLogger.redacter();
786
+ let logger = winston.createLogger({
787
+ level: options.level,
788
+ format: winston.format.combine(redacter.format, options.format),
789
+ transports: (_a = options.transports) != null ? _a : new winston.transports.Console()
790
+ });
791
+ if (options.meta) {
792
+ logger = logger.child(options.meta);
793
+ }
794
+ return new _WinstonLogger(logger, redacter.add);
795
+ }
796
+ /**
797
+ * Creates a winston log formatter for redacting secrets.
798
+ */
799
+ static redacter() {
800
+ const redactionSet = /* @__PURE__ */ new Set();
801
+ let redactionPattern = void 0;
802
+ return {
803
+ format: winston.format((info) => {
804
+ if (redactionPattern && typeof info.message === "string") {
805
+ info.message = info.message.replace(redactionPattern, "[REDACTED]");
806
+ }
807
+ return info;
808
+ })(),
809
+ add(newRedactions) {
810
+ let added = 0;
811
+ for (const redaction of newRedactions) {
812
+ if (redaction.length <= 1) {
813
+ continue;
814
+ }
815
+ if (!redactionSet.has(redaction)) {
816
+ redactionSet.add(redaction);
817
+ added += 1;
818
+ }
819
+ }
820
+ if (added > 0) {
821
+ redactionPattern = new RegExp(
822
+ `(${Array.from(redactionSet).join("|")})`,
823
+ "g"
824
+ );
825
+ }
826
+ }
827
+ };
828
+ }
829
+ /**
830
+ * Creates a pretty printed winston log formatter.
831
+ */
832
+ static colorFormat() {
833
+ const colorizer = winston.format.colorize();
834
+ return winston.format.combine(
835
+ winston.format.timestamp(),
836
+ winston.format.colorize({
837
+ colors: {
838
+ timestamp: "dim",
839
+ prefix: "blue",
840
+ field: "cyan",
841
+ debug: "grey"
842
+ }
843
+ }),
844
+ winston.format.printf((info) => {
845
+ const { timestamp, level, message, plugin, service, ...fields } = info;
846
+ const prefix = plugin || service;
847
+ const timestampColor = colorizer.colorize("timestamp", timestamp);
848
+ const prefixColor = colorizer.colorize("prefix", prefix);
849
+ const extraFields = Object.entries(fields).map(
850
+ ([key, value]) => `${colorizer.colorize("field", `${key}`)}=${value}`
851
+ ).join(" ");
852
+ return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;
853
+ })
854
+ );
855
+ }
856
+ error(message, meta) {
857
+ __privateGet$5(this, _winston).error(message, meta);
858
+ }
859
+ warn(message, meta) {
860
+ __privateGet$5(this, _winston).warn(message, meta);
861
+ }
862
+ info(message, meta) {
863
+ __privateGet$5(this, _winston).info(message, meta);
864
+ }
865
+ debug(message, meta) {
866
+ __privateGet$5(this, _winston).debug(message, meta);
867
+ }
868
+ child(meta) {
869
+ return new _WinstonLogger(__privateGet$5(this, _winston).child(meta));
870
+ }
871
+ addRedactions(redactions) {
872
+ var _a;
873
+ (_a = __privateGet$5(this, _addRedactions)) == null ? void 0 : _a.call(this, redactions);
874
+ }
875
+ };
876
+ let WinstonLogger = _WinstonLogger;
877
+ _winston = new WeakMap();
878
+ _addRedactions = new WeakMap();
879
+
559
880
  var __accessCheck$4 = (obj, member, msg) => {
560
881
  if (!member.has(obj))
561
882
  throw TypeError("Cannot " + msg);
@@ -804,7 +1125,7 @@ var __privateMethod$1 = (obj, member, method) => {
804
1125
  __accessCheck$2(obj, member, "access private method");
805
1126
  return method;
806
1127
  };
807
- var _providedFactories, _loadedDefaultFactories, _implementations, _resolveFactory, resolveFactory_fn, _separateMapForTheRootService, _checkForMissingDeps, checkForMissingDeps_fn;
1128
+ var _providedFactories, _loadedDefaultFactories, _implementations, _rootServiceImplementations, _resolveFactory, resolveFactory_fn, _checkForMissingDeps, checkForMissingDeps_fn;
808
1129
  class ServiceRegistry {
809
1130
  constructor(factories) {
810
1131
  __privateAdd$2(this, _resolveFactory);
@@ -812,7 +1133,7 @@ class ServiceRegistry {
812
1133
  __privateAdd$2(this, _providedFactories, void 0);
813
1134
  __privateAdd$2(this, _loadedDefaultFactories, void 0);
814
1135
  __privateAdd$2(this, _implementations, void 0);
815
- __privateAdd$2(this, _separateMapForTheRootService, /* @__PURE__ */ new Map());
1136
+ __privateAdd$2(this, _rootServiceImplementations, /* @__PURE__ */ new Map());
816
1137
  __privateSet$2(this, _providedFactories, new Map(factories.map((f) => [f.service.id, f])));
817
1138
  __privateSet$2(this, _loadedDefaultFactories, /* @__PURE__ */ new Map());
818
1139
  __privateSet$2(this, _implementations, /* @__PURE__ */ new Map());
@@ -824,7 +1145,7 @@ class ServiceRegistry {
824
1145
  var _a;
825
1146
  return (_a = __privateMethod$1(this, _resolveFactory, resolveFactory_fn).call(this, ref, pluginId)) == null ? void 0 : _a.then((factory) => {
826
1147
  if (factory.scope === "root") {
827
- let existing = __privateGet$2(this, _separateMapForTheRootService).get(factory);
1148
+ let existing = __privateGet$2(this, _rootServiceImplementations).get(factory);
828
1149
  if (!existing) {
829
1150
  __privateMethod$1(this, _checkForMissingDeps, checkForMissingDeps_fn).call(this, factory, pluginId);
830
1151
  const rootDeps = new Array();
@@ -840,7 +1161,7 @@ class ServiceRegistry {
840
1161
  existing = Promise.all(rootDeps).then(
841
1162
  (entries) => factory.factory(Object.fromEntries(entries))
842
1163
  );
843
- __privateGet$2(this, _separateMapForTheRootService).set(factory, existing);
1164
+ __privateGet$2(this, _rootServiceImplementations).set(factory, existing);
844
1165
  }
845
1166
  return existing;
846
1167
  }
@@ -855,10 +1176,15 @@ class ServiceRegistry {
855
1176
  }
856
1177
  }
857
1178
  implementation = {
858
- factoryFunc: Promise.all(rootDeps).then((entries) => factory.factory(Object.fromEntries(entries))).catch((error) => {
1179
+ context: Promise.all(rootDeps).then(
1180
+ (entries) => {
1181
+ var _a2;
1182
+ return (_a2 = factory.createRootContext) == null ? void 0 : _a2.call(factory, Object.fromEntries(entries));
1183
+ }
1184
+ ).catch((error) => {
859
1185
  const cause = errors.stringifyError(error);
860
1186
  throw new Error(
861
- `Failed to instantiate service '${ref.id}' because the top-level factory function threw an error, ${cause}`
1187
+ `Failed to instantiate service '${ref.id}' because createRootContext threw an error, ${cause}`
862
1188
  );
863
1189
  }),
864
1190
  byPlugin: /* @__PURE__ */ new Map()
@@ -872,9 +1198,9 @@ class ServiceRegistry {
872
1198
  const target = this.get(serviceRef, pluginId);
873
1199
  allDeps.push(target.then((impl) => [name, impl]));
874
1200
  }
875
- result = implementation.factoryFunc.then(
876
- (func) => Promise.all(allDeps).then(
877
- (entries) => func(Object.fromEntries(entries))
1201
+ result = implementation.context.then(
1202
+ (context) => Promise.all(allDeps).then(
1203
+ (entries) => factory.factory(Object.fromEntries(entries), context)
878
1204
  )
879
1205
  ).catch((error) => {
880
1206
  const cause = errors.stringifyError(error);
@@ -891,6 +1217,7 @@ class ServiceRegistry {
891
1217
  _providedFactories = new WeakMap();
892
1218
  _loadedDefaultFactories = new WeakMap();
893
1219
  _implementations = new WeakMap();
1220
+ _rootServiceImplementations = new WeakMap();
894
1221
  _resolveFactory = new WeakSet();
895
1222
  resolveFactory_fn = function(ref, pluginId) {
896
1223
  if (ref.id === backendPluginApi.coreServices.pluginMetadata.id) {
@@ -898,11 +1225,7 @@ resolveFactory_fn = function(ref, pluginId) {
898
1225
  scope: "plugin",
899
1226
  service: backendPluginApi.coreServices.pluginMetadata,
900
1227
  deps: {},
901
- factory: async () => async () => ({
902
- getId() {
903
- return pluginId;
904
- }
905
- })
1228
+ factory: async () => ({ getId: () => pluginId })
906
1229
  });
907
1230
  }
908
1231
  let resolvedFactory = __privateGet$2(this, _providedFactories).get(ref.id);
@@ -928,7 +1251,6 @@ resolveFactory_fn = function(ref, pluginId) {
928
1251
  }
929
1252
  return Promise.resolve(resolvedFactory);
930
1253
  };
931
- _separateMapForTheRootService = new WeakMap();
932
1254
  _checkForMissingDeps = new WeakSet();
933
1255
  checkForMissingDeps_fn = function(factory, pluginId) {
934
1256
  const missingDeps = Object.values(factory.deps).filter((ref) => {
@@ -1012,26 +1334,139 @@ function createSpecializedBackend(options) {
1012
1334
  return new BackstageBackend(services);
1013
1335
  }
1014
1336
 
1015
- const httpRouterFactory = backendPluginApi.createServiceFactory({
1016
- service: backendPluginApi.coreServices.httpRouter,
1337
+ const cacheFactory = backendPluginApi.createServiceFactory({
1338
+ service: backendPluginApi.coreServices.cache,
1017
1339
  deps: {
1018
- plugin: backendPluginApi.coreServices.pluginMetadata,
1019
- rootHttpRouter: backendPluginApi.coreServices.rootHttpRouter
1340
+ config: backendPluginApi.coreServices.config,
1341
+ plugin: backendPluginApi.coreServices.pluginMetadata
1020
1342
  },
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 }) => {
1343
+ async createRootContext({ config }) {
1344
+ return backendCommon.CacheManager.fromConfig(config);
1345
+ },
1346
+ async factory({ plugin }, manager) {
1347
+ return manager.forPlugin(plugin.getId());
1348
+ }
1349
+ });
1350
+
1351
+ const configFactory = backendPluginApi.createServiceFactory({
1352
+ service: backendPluginApi.coreServices.config,
1353
+ deps: {},
1354
+ async factory({}, options) {
1355
+ const { argv = process.argv, remote } = options != null ? options : {};
1356
+ const { config } = await loadBackendConfig({ argv, remote });
1357
+ return config;
1358
+ }
1359
+ });
1360
+
1361
+ const databaseFactory = backendPluginApi.createServiceFactory({
1362
+ service: backendPluginApi.coreServices.database,
1363
+ deps: {
1364
+ config: backendPluginApi.coreServices.config,
1365
+ plugin: backendPluginApi.coreServices.pluginMetadata
1366
+ },
1367
+ async createRootContext({ config: config$1 }) {
1368
+ return config$1.getOptional("backend.database") ? backendCommon.DatabaseManager.fromConfig(config$1) : backendCommon.DatabaseManager.fromConfig(
1369
+ new config.ConfigReader({
1370
+ backend: {
1371
+ database: { client: "better-sqlite3", connection: ":memory:" }
1372
+ }
1373
+ })
1374
+ );
1375
+ },
1376
+ async factory({ plugin }, databaseManager) {
1377
+ return databaseManager.forPlugin(plugin.getId());
1378
+ }
1379
+ });
1380
+
1381
+ const discoveryFactory = backendPluginApi.createServiceFactory({
1382
+ service: backendPluginApi.coreServices.discovery,
1383
+ deps: {
1384
+ config: backendPluginApi.coreServices.config
1385
+ },
1386
+ async factory({ config }) {
1387
+ return backendCommon.SingleHostDiscovery.fromConfig(config);
1388
+ }
1389
+ });
1390
+
1391
+ const httpRouterFactory = backendPluginApi.createServiceFactory(
1392
+ (options) => ({
1393
+ service: backendPluginApi.coreServices.httpRouter,
1394
+ deps: {
1395
+ plugin: backendPluginApi.coreServices.pluginMetadata,
1396
+ rootHttpRouter: backendPluginApi.coreServices.rootHttpRouter
1397
+ },
1398
+ async factory({ plugin, rootHttpRouter }) {
1399
+ var _a;
1400
+ const getPath = (_a = options == null ? void 0 : options.getPath) != null ? _a : (id) => `/api/${id}`;
1025
1401
  const path = getPath(plugin.getId());
1026
1402
  return {
1027
1403
  use(handler) {
1028
1404
  rootHttpRouter.use(path, handler);
1029
1405
  }
1030
1406
  };
1407
+ }
1408
+ })
1409
+ );
1410
+
1411
+ const identityFactory = backendPluginApi.createServiceFactory(
1412
+ (options) => ({
1413
+ service: backendPluginApi.coreServices.identity,
1414
+ deps: {
1415
+ discovery: backendPluginApi.coreServices.discovery
1416
+ },
1417
+ async factory({ discovery }) {
1418
+ return pluginAuthNode.DefaultIdentityClient.create({ discovery, ...options });
1419
+ }
1420
+ })
1421
+ );
1422
+
1423
+ const lifecycleFactory = backendPluginApi.createServiceFactory({
1424
+ service: backendPluginApi.coreServices.lifecycle,
1425
+ deps: {
1426
+ logger: backendPluginApi.coreServices.logger,
1427
+ rootLifecycle: backendPluginApi.coreServices.rootLifecycle,
1428
+ pluginMetadata: backendPluginApi.coreServices.pluginMetadata
1429
+ },
1430
+ async factory({ rootLifecycle, logger, pluginMetadata }) {
1431
+ const plugin = pluginMetadata.getId();
1432
+ return {
1433
+ addShutdownHook(options) {
1434
+ var _a, _b;
1435
+ rootLifecycle.addShutdownHook({
1436
+ ...options,
1437
+ logger: (_b = (_a = options.logger) == null ? void 0 : _a.child({ plugin })) != null ? _b : logger
1438
+ });
1439
+ }
1031
1440
  };
1032
1441
  }
1033
1442
  });
1034
1443
 
1444
+ const loggerFactory = backendPluginApi.createServiceFactory({
1445
+ service: backendPluginApi.coreServices.logger,
1446
+ deps: {
1447
+ rootLogger: backendPluginApi.coreServices.rootLogger,
1448
+ plugin: backendPluginApi.coreServices.pluginMetadata
1449
+ },
1450
+ factory({ rootLogger, plugin }) {
1451
+ return rootLogger.child({ plugin: plugin.getId() });
1452
+ }
1453
+ });
1454
+
1455
+ const permissionsFactory = backendPluginApi.createServiceFactory({
1456
+ service: backendPluginApi.coreServices.permissions,
1457
+ deps: {
1458
+ config: backendPluginApi.coreServices.config,
1459
+ discovery: backendPluginApi.coreServices.discovery,
1460
+ tokenManager: backendPluginApi.coreServices.tokenManager
1461
+ },
1462
+ async factory({ config, discovery, tokenManager }) {
1463
+ return pluginPermissionNode.ServerPermissionClient.fromConfig(config, {
1464
+ discovery,
1465
+ tokenManager
1466
+ });
1467
+ }
1468
+ });
1469
+
1035
1470
  var __accessCheck = (obj, member, msg) => {
1036
1471
  if (!member.has(obj))
1037
1472
  throw TypeError("Cannot " + msg);
@@ -1056,9 +1491,9 @@ var __privateMethod = (obj, member, method) => {
1056
1491
  };
1057
1492
  var _indexPath, _router, _namedRoutes, _indexRouter, _existingPaths, _findConflictingPath, findConflictingPath_fn;
1058
1493
  function normalizePath(path) {
1059
- return path.replace(/\/*$/, "/");
1494
+ return `${trimEnd__default["default"](path, "/")}/`;
1060
1495
  }
1061
- class RestrictedIndexedRouter {
1496
+ const _DefaultRootHttpRouter = class {
1062
1497
  constructor(indexPath) {
1063
1498
  __privateAdd(this, _findConflictingPath);
1064
1499
  __privateAdd(this, _indexPath, void 0);
@@ -1068,7 +1503,22 @@ class RestrictedIndexedRouter {
1068
1503
  __privateAdd(this, _existingPaths, new Array());
1069
1504
  __privateSet(this, _indexPath, indexPath);
1070
1505
  __privateGet(this, _router).use(__privateGet(this, _namedRoutes));
1071
- __privateGet(this, _router).use(__privateGet(this, _indexRouter));
1506
+ if (__privateGet(this, _indexPath)) {
1507
+ __privateGet(this, _router).use(__privateGet(this, _indexRouter));
1508
+ }
1509
+ }
1510
+ static create(options) {
1511
+ let indexPath;
1512
+ if ((options == null ? void 0 : options.indexPath) === false) {
1513
+ indexPath = void 0;
1514
+ } else if ((options == null ? void 0 : options.indexPath) === void 0) {
1515
+ indexPath = "/api/app";
1516
+ } else if ((options == null ? void 0 : options.indexPath) === "") {
1517
+ throw new Error("indexPath option may not be an empty string");
1518
+ } else {
1519
+ indexPath = options.indexPath;
1520
+ }
1521
+ return new _DefaultRootHttpRouter(indexPath);
1072
1522
  }
1073
1523
  use(path, handler) {
1074
1524
  if (path.match(/^[/\s]*$/)) {
@@ -1089,7 +1539,8 @@ class RestrictedIndexedRouter {
1089
1539
  handler() {
1090
1540
  return __privateGet(this, _router);
1091
1541
  }
1092
- }
1542
+ };
1543
+ let DefaultRootHttpRouter = _DefaultRootHttpRouter;
1093
1544
  _indexPath = new WeakMap();
1094
1545
  _router = new WeakMap();
1095
1546
  _namedRoutes = new WeakMap();
@@ -1134,9 +1585,9 @@ const rootHttpRouterFactory = backendPluginApi.createServiceFactory({
1134
1585
  indexPath,
1135
1586
  configure = defaultConfigure
1136
1587
  } = {}) {
1137
- const router = new RestrictedIndexedRouter(indexPath != null ? indexPath : "/api/app");
1138
1588
  const logger = rootLogger.child({ service: "rootHttpRouter" });
1139
1589
  const app = express__default["default"]();
1590
+ const router = DefaultRootHttpRouter.create({ indexPath });
1140
1591
  const middleware = MiddlewareFactory.create({ config, logger });
1141
1592
  configure({
1142
1593
  app,
@@ -1162,133 +1613,41 @@ const rootHttpRouterFactory = backendPluginApi.createServiceFactory({
1162
1613
  }
1163
1614
  });
1164
1615
 
1165
- const cacheFactory = backendPluginApi.createServiceFactory({
1166
- service: backendPluginApi.coreServices.cache,
1167
- deps: {
1168
- config: backendPluginApi.coreServices.config,
1169
- plugin: backendPluginApi.coreServices.pluginMetadata
1170
- },
1171
- async factory({ config }) {
1172
- const cacheManager = backendCommon.CacheManager.fromConfig(config);
1173
- return async ({ plugin }) => {
1174
- return cacheManager.forPlugin(plugin.getId());
1175
- };
1176
- }
1177
- });
1178
-
1179
- const configFactory = backendPluginApi.createServiceFactory({
1180
- service: backendPluginApi.coreServices.config,
1181
- deps: {
1182
- logger: backendPluginApi.coreServices.rootLogger
1183
- },
1184
- async factory({ logger }) {
1185
- const config = await backendCommon.loadBackendConfig({
1186
- argv: process.argv,
1187
- logger: backendCommon.loggerToWinstonLogger(logger)
1188
- });
1189
- return config;
1190
- }
1191
- });
1192
-
1193
- const databaseFactory = backendPluginApi.createServiceFactory({
1194
- service: backendPluginApi.coreServices.database,
1195
- deps: {
1196
- config: backendPluginApi.coreServices.config,
1197
- plugin: backendPluginApi.coreServices.pluginMetadata
1198
- },
1199
- async factory({ config }) {
1200
- const databaseManager = backendCommon.DatabaseManager.fromConfig(config);
1201
- return async ({ plugin }) => {
1202
- return databaseManager.forPlugin(plugin.getId());
1203
- };
1204
- }
1205
- });
1206
-
1207
- const discoveryFactory = backendPluginApi.createServiceFactory({
1208
- service: backendPluginApi.coreServices.discovery,
1209
- deps: {
1210
- config: backendPluginApi.coreServices.config
1211
- },
1212
- async factory({ config }) {
1213
- const discovery = backendCommon.SingleHostDiscovery.fromConfig(config);
1214
- return async () => {
1215
- return discovery;
1216
- };
1217
- }
1218
- });
1219
-
1220
- const loggerFactory = backendPluginApi.createServiceFactory({
1221
- service: backendPluginApi.coreServices.logger,
1222
- deps: {
1223
- rootLogger: backendPluginApi.coreServices.rootLogger,
1224
- plugin: backendPluginApi.coreServices.pluginMetadata
1225
- },
1226
- async factory({ rootLogger }) {
1227
- return async ({ plugin }) => {
1228
- return rootLogger.child({ plugin: plugin.getId() });
1229
- };
1230
- }
1231
- });
1232
-
1233
- class BackstageLogger {
1234
- constructor(winston) {
1235
- this.winston = winston;
1236
- }
1237
- static fromWinston(logger) {
1238
- return new BackstageLogger(logger);
1239
- }
1240
- error(message, meta) {
1241
- this.winston.error(message, meta);
1242
- }
1243
- warn(message, meta) {
1244
- this.winston.warn(message, meta);
1245
- }
1246
- info(message, meta) {
1247
- this.winston.info(message, meta);
1248
- }
1249
- debug(message, meta) {
1250
- this.winston.debug(message, meta);
1251
- }
1252
- child(meta) {
1253
- return new BackstageLogger(this.winston.child(meta));
1254
- }
1255
- }
1256
1616
  const rootLoggerFactory = backendPluginApi.createServiceFactory({
1257
1617
  service: backendPluginApi.coreServices.rootLogger,
1258
- deps: {},
1259
- async factory() {
1260
- return BackstageLogger.fromWinston(backendCommon.createRootLogger());
1261
- }
1262
- });
1263
-
1264
- const permissionsFactory = backendPluginApi.createServiceFactory({
1265
- service: backendPluginApi.coreServices.permissions,
1266
1618
  deps: {
1267
- config: backendPluginApi.coreServices.config,
1268
- discovery: backendPluginApi.coreServices.discovery,
1269
- tokenManager: backendPluginApi.coreServices.tokenManager
1619
+ config: backendPluginApi.coreServices.config
1270
1620
  },
1271
1621
  async factory({ config }) {
1272
- return async ({ discovery, tokenManager }) => {
1273
- return pluginPermissionNode.ServerPermissionClient.fromConfig(config, {
1274
- discovery,
1275
- tokenManager
1276
- });
1277
- };
1622
+ var _a;
1623
+ const logger = WinstonLogger.create({
1624
+ meta: {
1625
+ service: "backstage"
1626
+ },
1627
+ level: process.env.LOG_LEVEL || "info",
1628
+ format: process.env.NODE_ENV === "production" ? winston.format.json() : WinstonLogger.colorFormat(),
1629
+ transports: [new winston.transports.Console()]
1630
+ });
1631
+ const secretEnumerator = await createConfigSecretEnumerator({ logger });
1632
+ logger.addRedactions(secretEnumerator(config));
1633
+ (_a = config.subscribe) == null ? void 0 : _a.call(config, () => logger.addRedactions(secretEnumerator(config)));
1634
+ return logger;
1278
1635
  }
1279
1636
  });
1280
1637
 
1281
1638
  const schedulerFactory = backendPluginApi.createServiceFactory({
1282
1639
  service: backendPluginApi.coreServices.scheduler,
1283
1640
  deps: {
1284
- config: backendPluginApi.coreServices.config,
1285
- plugin: backendPluginApi.coreServices.pluginMetadata
1641
+ plugin: backendPluginApi.coreServices.pluginMetadata,
1642
+ databaseManager: backendPluginApi.coreServices.database,
1643
+ logger: backendPluginApi.coreServices.logger
1286
1644
  },
1287
- async factory({ config }) {
1288
- const taskScheduler = backendTasks.TaskScheduler.fromConfig(config);
1289
- return async ({ plugin }) => {
1290
- return taskScheduler.forPlugin(plugin.getId());
1291
- };
1645
+ async factory({ plugin, databaseManager, logger }) {
1646
+ return backendTasks.TaskScheduler.forPlugin({
1647
+ pluginId: plugin.getId(),
1648
+ databaseManager,
1649
+ logger: backendCommon.loggerToWinstonLogger(logger)
1650
+ });
1292
1651
  }
1293
1652
  });
1294
1653
 
@@ -1296,14 +1655,15 @@ const tokenManagerFactory = backendPluginApi.createServiceFactory({
1296
1655
  service: backendPluginApi.coreServices.tokenManager,
1297
1656
  deps: {
1298
1657
  config: backendPluginApi.coreServices.config,
1299
- logger: backendPluginApi.coreServices.logger
1658
+ logger: backendPluginApi.coreServices.rootLogger
1300
1659
  },
1301
- async factory() {
1302
- return async ({ config, logger }) => {
1303
- return backendCommon.ServerTokenManager.fromConfig(config, {
1304
- logger: backendCommon.loggerToWinstonLogger(logger)
1305
- });
1306
- };
1660
+ createRootContext({ config, logger }) {
1661
+ return backendCommon.ServerTokenManager.fromConfig(config, {
1662
+ logger
1663
+ });
1664
+ },
1665
+ async factory(_deps, tokenManager) {
1666
+ return tokenManager;
1307
1667
  }
1308
1668
  });
1309
1669
 
@@ -1313,48 +1673,28 @@ const urlReaderFactory = backendPluginApi.createServiceFactory({
1313
1673
  config: backendPluginApi.coreServices.config,
1314
1674
  logger: backendPluginApi.coreServices.logger
1315
1675
  },
1316
- async factory() {
1317
- return async ({ config, logger }) => {
1318
- return backendCommon.UrlReaders.default({
1319
- config,
1320
- logger: backendCommon.loggerToWinstonLogger(logger)
1321
- });
1322
- };
1323
- }
1324
- });
1325
-
1326
- const lifecycleFactory = backendPluginApi.createServiceFactory({
1327
- service: backendPluginApi.coreServices.lifecycle,
1328
- deps: {
1329
- logger: backendPluginApi.coreServices.logger,
1330
- rootLifecycle: backendPluginApi.coreServices.rootLifecycle,
1331
- pluginMetadata: backendPluginApi.coreServices.pluginMetadata
1332
- },
1333
- async factory({ rootLifecycle }) {
1334
- return async ({ logger, pluginMetadata }) => {
1335
- const plugin = pluginMetadata.getId();
1336
- return {
1337
- addShutdownHook(options) {
1338
- var _a, _b;
1339
- rootLifecycle.addShutdownHook({
1340
- ...options,
1341
- logger: (_b = (_a = options.logger) == null ? void 0 : _a.child({ plugin })) != null ? _b : logger
1342
- });
1343
- }
1344
- };
1345
- };
1676
+ async factory({ config, logger }) {
1677
+ return backendCommon.UrlReaders.default({
1678
+ config,
1679
+ logger: backendCommon.loggerToWinstonLogger(logger)
1680
+ });
1346
1681
  }
1347
1682
  });
1348
1683
 
1684
+ exports.DefaultRootHttpRouter = DefaultRootHttpRouter;
1349
1685
  exports.MiddlewareFactory = MiddlewareFactory;
1686
+ exports.WinstonLogger = WinstonLogger;
1350
1687
  exports.cacheFactory = cacheFactory;
1351
1688
  exports.configFactory = configFactory;
1689
+ exports.createConfigSecretEnumerator = createConfigSecretEnumerator;
1352
1690
  exports.createHttpServer = createHttpServer;
1353
1691
  exports.createSpecializedBackend = createSpecializedBackend;
1354
1692
  exports.databaseFactory = databaseFactory;
1355
1693
  exports.discoveryFactory = discoveryFactory;
1356
1694
  exports.httpRouterFactory = httpRouterFactory;
1695
+ exports.identityFactory = identityFactory;
1357
1696
  exports.lifecycleFactory = lifecycleFactory;
1697
+ exports.loadBackendConfig = loadBackendConfig;
1358
1698
  exports.loggerFactory = loggerFactory;
1359
1699
  exports.permissionsFactory = permissionsFactory;
1360
1700
  exports.readCorsOptions = readCorsOptions;