@backstage/backend-plugin-api 0.7.1-next.1 → 0.8.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,112 @@
1
1
  # @backstage/backend-plugin-api
2
2
 
3
+ ## 0.8.0-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - ddde5fe: Fixed a type issue where plugin and modules depending on multiton services would not receive the correct type.
8
+ - Updated dependencies
9
+ - @backstage/cli-common@0.1.14
10
+ - @backstage/config@1.2.0
11
+ - @backstage/errors@1.2.4
12
+ - @backstage/types@1.1.1
13
+ - @backstage/plugin-auth-node@0.5.0-next.3
14
+ - @backstage/plugin-permission-common@0.8.1-next.1
15
+
16
+ ## 0.8.0-next.2
17
+
18
+ ### Minor Changes
19
+
20
+ - 7c5f3b0: The `createServiceRef` function now accepts a new boolean `multiple` option. The `multiple` option defaults to `false` and when set to `true`, it enables that multiple implementation are installed for the created service ref.
21
+
22
+ We're looking for ways to make it possible to augment services without the need to replace the entire service.
23
+
24
+ Typical example of that being the ability to install support for additional targets for the `UrlReader` service without replacing the service itself. This achieves that by allowing us to define services that can have multiple simultaneous implementation, allowing the `UrlReader` implementation to depend on such a service to collect all possible implementation of support for external targets:
25
+
26
+ ```diff
27
+ // @backstage/backend-defaults
28
+
29
+ + export const urlReaderFactoriesServiceRef = createServiceRef<ReaderFactory>({
30
+ + id: 'core.urlReader.factories',
31
+ + scope: 'plugin',
32
+ + multiton: true,
33
+ + });
34
+
35
+ ...
36
+
37
+ export const urlReaderServiceFactory = createServiceFactory({
38
+ service: coreServices.urlReader,
39
+ deps: {
40
+ config: coreServices.rootConfig,
41
+ logger: coreServices.logger,
42
+ + factories: urlReaderFactoriesServiceRef,
43
+ },
44
+ - async factory({ config, logger }) {
45
+ + async factory({ config, logger, factories }) {
46
+ return UrlReaders.default({
47
+ config,
48
+ logger,
49
+ + factories,
50
+ });
51
+ },
52
+ });
53
+ ```
54
+
55
+ With that, you can then add more custom `UrlReader` factories by installing more implementations of the `urlReaderFactoriesServiceRef` in your backend instance. Something like:
56
+
57
+ ```ts
58
+ // packages/backend/index.ts
59
+ import { createServiceFactory } from '@backstage/backend-plugin-api';
60
+ import { urlReaderFactoriesServiceRef } from '@backstage/backend-defaults';
61
+ ...
62
+
63
+ backend.add(createServiceFactory({
64
+ service: urlReaderFactoriesServiceRef,
65
+ deps: {},
66
+ async factory() {
67
+ return CustomUrlReader.factory;
68
+ },
69
+ }));
70
+
71
+ ...
72
+
73
+ ```
74
+
75
+ ### Patch Changes
76
+
77
+ - 6061061: Added `createBackendFeatureLoader`, which can be used to create an installable backend feature that can in turn load in additional backend features in a dynamic way.
78
+ - ba9abf4: The `SchedulerService` now allows tasks with `frequency: { trigger: 'manual' }`. This means that the task will not be scheduled, but rather run only when manually triggered with `SchedulerService.triggerTask`.
79
+ - 8b13183: Added `createBackendFeatureLoader`, which can be used to programmatically select and install backend features.
80
+
81
+ A feature loader can return an list of features to be installed, for example in the form on an `Array` or other for of iterable, which allows for the loader to be defined as a generator function. Both synchronous and asynchronous loaders are supported.
82
+
83
+ Additionally, a loader can depend on services in its implementation, with the restriction that it can only depend on root-scoped services, and it may not override services that have already been instantiated.
84
+
85
+ ```ts
86
+ const searchLoader = createBackendFeatureLoader({
87
+ deps: {
88
+ config: coreServices.rootConfig,
89
+ },
90
+ *loader({ config }) {
91
+ // Example of a custom config flag to enable search
92
+ if (config.getOptionalString('customFeatureToggle.search')) {
93
+ yield import('@backstage/plugin-search-backend/alpha');
94
+ yield import('@backstage/plugin-search-backend-module-catalog/alpha');
95
+ yield import('@backstage/plugin-search-backend-module-explore/alpha');
96
+ yield import('@backstage/plugin-search-backend-module-techdocs/alpha');
97
+ }
98
+ },
99
+ });
100
+ ```
101
+
102
+ - Updated dependencies
103
+ - @backstage/plugin-permission-common@0.8.1-next.1
104
+ - @backstage/plugin-auth-node@0.5.0-next.2
105
+ - @backstage/cli-common@0.1.14
106
+ - @backstage/config@1.2.0
107
+ - @backstage/errors@1.2.4
108
+ - @backstage/types@1.1.1
109
+
3
110
  ## 0.7.1-next.1
4
111
 
5
112
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-plugin-api__alpha",
3
- "version": "0.7.1-next.1",
3
+ "version": "0.8.0-next.3",
4
4
  "main": "../dist/alpha.cjs.js",
5
5
  "types": "../dist/alpha.d.ts"
6
6
  }
package/dist/alpha.d.ts CHANGED
@@ -11,6 +11,6 @@ interface FeatureDiscoveryService {
11
11
  * An optional service that can be used to dynamically load in additional BackendFeatures at runtime.
12
12
  * @alpha
13
13
  */
14
- declare const featureDiscoveryServiceRef: _backstage_backend_plugin_api.ServiceRef<FeatureDiscoveryService, "root">;
14
+ declare const featureDiscoveryServiceRef: _backstage_backend_plugin_api.ServiceRef<FeatureDiscoveryService, "root", "singleton">;
15
15
 
16
16
  export { type FeatureDiscoveryService, featureDiscoveryServiceRef };
package/dist/index.cjs.js CHANGED
@@ -9,10 +9,11 @@ require('path');
9
9
  require('fs');
10
10
 
11
11
  function createServiceRef(options) {
12
- const { id, scope = "plugin", defaultFactory } = options;
12
+ const { id, scope = "plugin", multiton = false, defaultFactory } = options;
13
13
  return {
14
14
  id,
15
15
  scope,
16
+ multiton,
16
17
  get T() {
17
18
  throw new Error(`tried to read ServiceRef.T of ${this}`);
18
19
  },
@@ -32,6 +33,7 @@ function createServiceFactory(options) {
32
33
  return {
33
34
  $$type: "@backstage/BackendFeature",
34
35
  version: "v1",
36
+ featureType: "service",
35
37
  service: c2.service,
36
38
  initialization: c2.initialization,
37
39
  deps: c2.deps,
@@ -42,6 +44,7 @@ function createServiceFactory(options) {
42
44
  return {
43
45
  $$type: "@backstage/BackendFeature",
44
46
  version: "v1",
47
+ featureType: "service",
45
48
  service: c.service,
46
49
  initialization: c.initialization,
47
50
  ..."createRootContext" in c ? {
@@ -95,15 +98,18 @@ function readDuration(config$1, key) {
95
98
  }
96
99
  return config.readDurationFromConfig(config$1, { key });
97
100
  }
98
- function readCronOrDuration(config, key) {
101
+ function readFrequency(config, key) {
99
102
  const value = config.get(key);
100
103
  if (typeof value === "object" && value.cron) {
101
104
  return value;
102
105
  }
106
+ if (typeof value === "object" && value.trigger === "manual") {
107
+ return { trigger: "manual" };
108
+ }
103
109
  return readDuration(config, key);
104
110
  }
105
111
  function readSchedulerServiceTaskScheduleDefinitionFromConfig(config) {
106
- const frequency = readCronOrDuration(config, "frequency");
112
+ const frequency = readFrequency(config, "frequency");
107
113
  const timeout = readDuration(config, "timeout");
108
114
  const initialDelay = config.has("initialDelay") ? readDuration(config, "initialDelay") : void 0;
109
115
  const scope = config.getOptionalString("scope");
@@ -125,22 +131,7 @@ function isDatabaseConflictError(e) {
125
131
  return typeof message === "string" && (/SQLITE_CONSTRAINT(?:_UNIQUE)?: UNIQUE/.test(message) || /UNIQUE constraint failed:/.test(message) || /unique constraint/.test(message) || /Duplicate entry/.test(message));
126
132
  }
127
133
 
128
- function createExtensionPoint(options) {
129
- return {
130
- id: options.id,
131
- get T() {
132
- if (process.env.NODE_ENV === "test") {
133
- return null;
134
- }
135
- throw new Error(`tried to read ExtensionPoint.T of ${this}`);
136
- },
137
- toString() {
138
- return `extensionPoint{${options.id}}`;
139
- },
140
- $$type: "@backstage/ExtensionPoint"
141
- };
142
- }
143
- function createBackendPlugin(options) {
134
+ function createBackendModule(options) {
144
135
  function getRegistrations() {
145
136
  const extensionPoints = [];
146
137
  let init = void 0;
@@ -163,13 +154,14 @@ function createBackendPlugin(options) {
163
154
  });
164
155
  if (!init) {
165
156
  throw new Error(
166
- `registerInit was not called by register in ${options.pluginId}`
157
+ `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`
167
158
  );
168
159
  }
169
160
  return [
170
161
  {
171
- type: "plugin",
162
+ type: "module",
172
163
  pluginId: options.pluginId,
164
+ moduleId: options.moduleId,
173
165
  extensionPoints,
174
166
  init
175
167
  }
@@ -185,7 +177,8 @@ function createBackendPlugin(options) {
185
177
  });
186
178
  return backendFeatureCompatWrapper;
187
179
  }
188
- function createBackendModule(options) {
180
+
181
+ function createBackendPlugin(options) {
189
182
  function getRegistrations() {
190
183
  const extensionPoints = [];
191
184
  let init = void 0;
@@ -208,14 +201,13 @@ function createBackendModule(options) {
208
201
  });
209
202
  if (!init) {
210
203
  throw new Error(
211
- `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`
204
+ `registerInit was not called by register in ${options.pluginId}`
212
205
  );
213
206
  }
214
207
  return [
215
208
  {
216
- type: "module",
209
+ type: "plugin",
217
210
  pluginId: options.pluginId,
218
- moduleId: options.moduleId,
219
211
  extensionPoints,
220
212
  init
221
213
  }
@@ -232,6 +224,68 @@ function createBackendModule(options) {
232
224
  return backendFeatureCompatWrapper;
233
225
  }
234
226
 
227
+ function createExtensionPoint(options) {
228
+ return {
229
+ id: options.id,
230
+ get T() {
231
+ if (process.env.NODE_ENV === "test") {
232
+ return null;
233
+ }
234
+ throw new Error(`tried to read ExtensionPoint.T of ${this}`);
235
+ },
236
+ toString() {
237
+ return `extensionPoint{${options.id}}`;
238
+ },
239
+ $$type: "@backstage/ExtensionPoint"
240
+ };
241
+ }
242
+
243
+ const MESSAGE_MARKER = "eHgtF5hmbrXyiEvo";
244
+ function describeParentCallSite(ErrorConstructor = Error) {
245
+ const { stack } = new ErrorConstructor(MESSAGE_MARKER);
246
+ if (!stack) {
247
+ return "<unknown>";
248
+ }
249
+ const startIndex = stack.includes(MESSAGE_MARKER) ? stack.indexOf("\n") + 1 : 0;
250
+ const secondEntryStart = stack.indexOf("\n", stack.indexOf("\n", startIndex) + 1) + 1;
251
+ const secondEntryEnd = stack.indexOf("\n", secondEntryStart);
252
+ const line = stack.substring(secondEntryStart, secondEntryEnd).trim();
253
+ if (!line) {
254
+ return "unknown";
255
+ }
256
+ if (line.includes("(")) {
257
+ return line.substring(line.indexOf("(") + 1, line.indexOf(")"));
258
+ }
259
+ if (line.includes("@")) {
260
+ return line.substring(line.indexOf("@") + 1);
261
+ }
262
+ return line;
263
+ }
264
+
265
+ function createBackendFeatureLoader(options) {
266
+ return {
267
+ $$type: "@backstage/BackendFeature",
268
+ version: "v1",
269
+ featureType: "loader",
270
+ description: `created at '${describeParentCallSite()}'`,
271
+ deps: options.deps,
272
+ async loader(deps) {
273
+ const it = await options.loader(deps);
274
+ const result = new Array();
275
+ for await (const item of it) {
276
+ if ("$$type" in item && item.$$type === "@backstage/BackendFeature") {
277
+ result.push(item);
278
+ } else if ("default" in item) {
279
+ result.push(item.default);
280
+ } else {
281
+ throw new Error(`Invalid item "${item}"`);
282
+ }
283
+ }
284
+ return result;
285
+ }
286
+ };
287
+ }
288
+
235
289
  exports.packagePathMocks = paths.packagePathMocks;
236
290
  exports.resolvePackagePath = paths.resolvePackagePath;
237
291
  exports.resolveSafeChildPath = paths.resolveSafeChildPath;
@@ -239,6 +293,7 @@ Object.defineProperty(exports, "isChildPath", {
239
293
  enumerable: true,
240
294
  get: function () { return cliCommon.isChildPath; }
241
295
  });
296
+ exports.createBackendFeatureLoader = createBackendFeatureLoader;
242
297
  exports.createBackendModule = createBackendModule;
243
298
  exports.createBackendPlugin = createBackendPlugin;
244
299
  exports.createExtensionPoint = createExtensionPoint;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/services/system/types.ts","../src/services/definitions/coreServices.ts","../src/services/definitions/SchedulerService.ts","../src/services/utilities/database.ts","../src/wiring/factories.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackendFeature } from '../../types';\n\n/**\n * TODO\n *\n * @public\n */\nexport type ServiceRef<\n TService,\n TScope extends 'root' | 'plugin' = 'root' | 'plugin',\n> = {\n id: string;\n\n /**\n * This determines the scope at which this service is available.\n *\n * Root scoped services are available to all other services but\n * may only depend on other root scoped services.\n *\n * Plugin scoped services are only available to other plugin scoped\n * services but may depend on all other services.\n */\n scope: TScope;\n\n /**\n * Utility for getting the type of the service, using `typeof serviceRef.T`.\n * Attempting to actually read this value will result in an exception.\n */\n T: TService;\n\n $$type: '@backstage/ServiceRef';\n};\n\n/** @public */\nexport interface ServiceFactory<\n TService = unknown,\n TScope extends 'plugin' | 'root' = 'plugin' | 'root',\n> extends BackendFeature {\n service: ServiceRef<TService, TScope>;\n}\n\n/**\n * @public\n * @deprecated This type exists only as a helper for old code that relied on `createServiceFactory` to return `() => ServiceFactory` instead of `ServiceFactory`. You should remove the `()` parentheses at the end of your usages. This type will be removed in a future release.\n */\nexport interface ServiceFactoryCompat<\n TService = unknown,\n TScope extends 'plugin' | 'root' = 'plugin' | 'root',\n TOpts extends object | undefined = undefined,\n> extends ServiceFactory<TService, TScope> {\n /**\n * @deprecated Callable service factories will be removed in a future release, please re-implement the service factory using the available APIs instead. If no options are being passed, you can simply remove the trailing `()`.\n */\n (\n ...options: undefined extends TOpts ? [] : [options?: TOpts]\n ): ServiceFactory<TService, TScope>;\n}\n\n/** @internal */\nexport interface InternalServiceFactory<\n TService = unknown,\n TScope extends 'plugin' | 'root' = 'plugin' | 'root',\n> extends ServiceFactory<TService, TScope> {\n version: 'v1';\n initialization?: 'always' | 'lazy';\n deps: { [key in string]: ServiceRef<unknown> };\n createRootContext?(deps: { [key in string]: unknown }): Promise<unknown>;\n factory(\n deps: { [key in string]: unknown },\n context: unknown,\n ): Promise<TService>;\n}\n\n/**\n * Represents either a {@link ServiceFactory} or a function that returns one.\n *\n * @deprecated The support for service factory functions is deprecated and will be removed.\n * @public\n */\nexport type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory);\n\n/** @public */\nexport interface ServiceRefOptions<TService, TScope extends 'root' | 'plugin'> {\n id: string;\n scope?: TScope;\n defaultFactory?(\n service: ServiceRef<TService, TScope>,\n ): Promise<ServiceFactory>;\n /**\n * @deprecated The defaultFactory must return a plain `ServiceFactory` object, support for returning a function will be removed.\n */\n defaultFactory?(\n service: ServiceRef<TService, TScope>,\n ): Promise<() => ServiceFactory>;\n}\n\n/**\n * Creates a new service definition. This overload is used to create plugin scoped services.\n *\n * @public\n */\nexport function createServiceRef<TService>(\n options: ServiceRefOptions<TService, 'plugin'>,\n): ServiceRef<TService, 'plugin'>;\n\n/**\n * Creates a new service definition. This overload is used to create root scoped services.\n *\n * @public\n */\nexport function createServiceRef<TService>(\n options: ServiceRefOptions<TService, 'root'>,\n): ServiceRef<TService, 'root'>;\n\nexport function createServiceRef<TService>(\n options: ServiceRefOptions<TService, any>,\n): ServiceRef<TService, any> {\n const { id, scope = 'plugin', defaultFactory } = options;\n return {\n id,\n scope,\n get T(): TService {\n throw new Error(`tried to read ServiceRef.T of ${this}`);\n },\n toString() {\n return `serviceRef{${options.id}}`;\n },\n $$type: '@backstage/ServiceRef',\n __defaultFactory: defaultFactory,\n } as ServiceRef<TService, typeof scope> & {\n __defaultFactory?: (\n service: ServiceRef<TService>,\n ) => Promise<ServiceFactory<TService> | (() => ServiceFactory<TService>)>;\n };\n}\n\n/** @ignore */\ntype ServiceRefsToInstances<\n T extends { [key in string]: ServiceRef<unknown> },\n TScope extends 'root' | 'plugin' = 'root' | 'plugin',\n> = {\n [key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['T'];\n};\n\n/** @public */\nexport interface RootServiceFactoryOptions<\n TService,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n> {\n /**\n * The initialization strategy for the service factory. This service is root scoped and will use `always` by default.\n *\n * @remarks\n *\n * - `always` - The service will always be initialized regardless if it is used or not.\n * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.\n *\n * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.\n */\n initialization?: 'always' | 'lazy';\n service: ServiceRef<TService, 'root'>;\n deps: TDeps;\n factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;\n}\n\n/** @public */\nexport interface PluginServiceFactoryOptions<\n TService,\n TContext,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n> {\n /**\n * The initialization strategy for the service factory. This service is plugin scoped and will use `lazy` by default.\n *\n * @remarks\n *\n * - `always` - The service will always be initialized regardless if it is used or not.\n * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.\n *\n * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.\n */\n initialization?: 'always' | 'lazy';\n service: ServiceRef<TService, 'plugin'>;\n deps: TDeps;\n createRootContext?(\n deps: ServiceRefsToInstances<TDeps, 'root'>,\n ): TContext | Promise<TContext>;\n factory(\n deps: ServiceRefsToInstances<TDeps>,\n context: TContext,\n ): TImpl | Promise<TImpl>;\n}\n\n/**\n * Creates a root scoped service factory without options.\n *\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown, 'root'> },\n TOpts extends object | undefined = undefined,\n>(\n options: RootServiceFactoryOptions<TService, TImpl, TDeps>,\n): ServiceFactoryCompat<TService, 'root'>;\n/**\n * Creates a root scoped service factory with optional options.\n *\n * @deprecated The ability to define options for service factories is deprecated\n * and will be removed. Please use the non-callback form of createServiceFactory\n * and provide an API that allows for a simple re-implementation of the service\n * factory instead.\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown, 'root'> },\n TOpts extends object | undefined = undefined,\n>(\n options: (\n options?: TOpts,\n ) => RootServiceFactoryOptions<TService, TImpl, TDeps>,\n): ServiceFactoryCompat<TService, 'root', TOpts>;\n/**\n * Creates a plugin scoped service factory without options.\n *\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n TContext = undefined,\n TOpts extends object | undefined = undefined,\n>(\n options: PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>,\n): ServiceFactoryCompat<TService, 'plugin'>;\n/**\n * Creates a plugin scoped service factory with optional options.\n *\n * @deprecated The ability to define options for service factories is deprecated\n * and will be removed. Please use the non-callback form of createServiceFactory\n * and provide an API that allows for a simple re-implementation of the service\n * factory instead.\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n TContext = undefined,\n TOpts extends object | undefined = undefined,\n>(\n options: (\n options?: TOpts,\n ) => PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>,\n): ServiceFactoryCompat<TService, 'plugin', TOpts>;\nexport function createServiceFactory<\n TService,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n TContext,\n TOpts extends object | undefined = undefined,\n>(\n options:\n | RootServiceFactoryOptions<TService, TImpl, TDeps>\n | PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>\n | ((options: TOpts) => RootServiceFactoryOptions<TService, TImpl, TDeps>)\n | ((\n options: TOpts,\n ) => PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>)\n | (() => RootServiceFactoryOptions<TService, TImpl, TDeps>)\n | (() => PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>),\n): ServiceFactoryCompat<TService, 'root' | 'plugin', TOpts> {\n const configCallback =\n typeof options === 'function' ? options : () => options;\n const factory = (\n o?: TOpts,\n ): InternalServiceFactory<TService, 'plugin' | 'root'> => {\n const anyConf = configCallback(o!);\n if (anyConf.service.scope === 'root') {\n const c = anyConf as RootServiceFactoryOptions<TService, TImpl, TDeps>;\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n service: c.service,\n initialization: c.initialization,\n deps: c.deps,\n factory: async (deps: TDeps) => c.factory(deps),\n };\n }\n const c = anyConf as PluginServiceFactoryOptions<\n TService,\n TContext,\n TImpl,\n TDeps\n >;\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n service: c.service,\n initialization: c.initialization,\n ...('createRootContext' in c\n ? {\n createRootContext: async (deps: TDeps) =>\n c?.createRootContext?.(deps),\n }\n : {}),\n deps: c.deps,\n factory: async (deps: TDeps, ctx: TContext) => c.factory(deps, ctx),\n };\n };\n\n // This constructs the `ServiceFactoryCompat` type, which is both a plain\n // factory object as well as a function that can be called to construct a\n // factory, potentially with options. In the future only the plain factory\n // form will be supported, but for now we need to allow callers to call the\n // factory too.\n return Object.assign(factory, factory(undefined as TOpts));\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createServiceRef } from '../system';\n\n/**\n * All core services references\n *\n * @public\n */\nexport namespace coreServices {\n /**\n * Handles token authentication and credentials management.\n *\n * See {@link AuthService}\n * and {@link https://backstage.io/docs/backend-system/core-services/auth | the service docs}\n * for more information.\n *\n * @public\n */\n export const auth = createServiceRef<import('./AuthService').AuthService>({\n id: 'core.auth',\n });\n\n /**\n * Authenticated user information retrieval.\n *\n * See {@link UserInfoService}\n * and {@link https://backstage.io/docs/backend-system/core-services/user-info | the service docs}\n * for more information.\n *\n * @public\n */\n export const userInfo = createServiceRef<\n import('./UserInfoService').UserInfoService\n >({\n id: 'core.userInfo',\n });\n\n /**\n * Key-value store for caching data.\n *\n * See {@link CacheService}\n * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs}\n * for more information.\n *\n * @public\n */\n export const cache = createServiceRef<import('./CacheService').CacheService>({\n id: 'core.cache',\n });\n\n /**\n * Access to static configuration.\n *\n * See {@link RootConfigService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-config | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootConfig = createServiceRef<\n import('./RootConfigService').RootConfigService\n >({ id: 'core.rootConfig', scope: 'root' });\n\n /**\n * Database access and management via `knex`.\n *\n * See {@link DatabaseService}\n * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs}\n * for more information.\n *\n * @public\n */\n export const database = createServiceRef<\n import('./DatabaseService').DatabaseService\n >({ id: 'core.database' });\n\n /**\n * Service discovery for inter-plugin communication.\n *\n * See {@link DiscoveryService}\n * and {@link https://backstage.io/docs/backend-system/core-services/discovery | the service docs}\n * for more information.\n *\n * @public\n */\n export const discovery = createServiceRef<\n import('./DiscoveryService').DiscoveryService\n >({ id: 'core.discovery' });\n\n /**\n * The service reference for the plugin scoped {@link RootHealthService}.\n */\n export const rootHealth = createServiceRef<\n import('./RootHealthService').RootHealthService\n >({ id: 'core.rootHealth', scope: 'root' });\n\n /**\n * Authentication of HTTP requests.\n *\n * See {@link HttpAuthService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-auth | the service docs}\n * for more information.\n *\n * @public\n */\n export const httpAuth = createServiceRef<\n import('./HttpAuthService').HttpAuthService\n >({ id: 'core.httpAuth' });\n\n /**\n * HTTP route registration for plugins.\n *\n * See {@link HttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-router | the service docs}\n * for more information.\n *\n * @public\n */\n export const httpRouter = createServiceRef<\n import('./HttpRouterService').HttpRouterService\n >({ id: 'core.httpRouter' });\n\n /**\n * Registration of plugin startup and shutdown lifecycle hooks.\n *\n * See {@link LifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\n export const lifecycle = createServiceRef<\n import('./LifecycleService').LifecycleService\n >({ id: 'core.lifecycle' });\n\n /**\n * Plugin-level logging.\n *\n * See {@link LoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/logger | the service docs}\n * for more information.\n *\n * @public\n */\n export const logger = createServiceRef<\n import('./LoggerService').LoggerService\n >({ id: 'core.logger' });\n\n /**\n * Permission system integration for authorization of user actions.\n *\n * See {@link PermissionsService}\n * and {@link https://backstage.io/docs/backend-system/core-services/permissions | the service docs}\n * for more information.\n *\n * @public\n */\n export const permissions = createServiceRef<\n import('./PermissionsService').PermissionsService\n >({ id: 'core.permissions' });\n\n /**\n * Built-in service for accessing metadata about the current plugin.\n *\n * See {@link PluginMetadataService}\n * and {@link https://backstage.io/docs/backend-system/core-services/plugin-metadata | the service docs}\n * for more information.\n *\n * @public\n */\n export const pluginMetadata = createServiceRef<\n import('./PluginMetadataService').PluginMetadataService\n >({ id: 'core.pluginMetadata' });\n\n /**\n * HTTP route registration for root services.\n *\n * See {@link RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootHttpRouter = createServiceRef<\n import('./RootHttpRouterService').RootHttpRouterService\n >({ id: 'core.rootHttpRouter', scope: 'root' });\n\n /**\n * Registration of backend startup and shutdown lifecycle hooks.\n *\n * See {@link RootLifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootLifecycle = createServiceRef<\n import('./RootLifecycleService').RootLifecycleService\n >({ id: 'core.rootLifecycle', scope: 'root' });\n\n /**\n * Root-level logging.\n *\n * See {@link RootLoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootLogger = createServiceRef<\n import('./RootLoggerService').RootLoggerService\n >({ id: 'core.rootLogger', scope: 'root' });\n\n /**\n * Scheduling of distributed background tasks.\n *\n * See {@link SchedulerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/scheduler | the service docs}\n * for more information.\n *\n * @public\n */\n export const scheduler = createServiceRef<\n import('./SchedulerService').SchedulerService\n >({ id: 'core.scheduler' });\n\n /**\n * Deprecated service authentication service, use the `auth` service instead.\n *\n * See {@link TokenManagerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/token-manager | the service docs}\n * for more information.\n *\n * @public\n * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead\n */\n export const tokenManager = createServiceRef<\n import('./TokenManagerService').TokenManagerService\n >({ id: 'core.tokenManager' });\n\n /**\n * Reading content from external systems.\n *\n * See {@link UrlReaderService}\n * and {@link https://backstage.io/docs/backend-system/core-services/url-reader | the service docs}\n * for more information.\n *\n * @public\n */\n export const urlReader = createServiceRef<\n import('./UrlReaderService').UrlReaderService\n >({ id: 'core.urlReader' });\n\n /**\n * Deprecated user authentication service, use the `auth` service instead.\n *\n * See {@link IdentityService}\n * and {@link https://backstage.io/docs/backend-system/core-services/identity | the service docs}\n * for more information.\n *\n * @public\n * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead\n */\n export const identity = createServiceRef<\n import('./IdentityService').IdentityService\n >({ id: 'core.identity' });\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { HumanDuration, JsonObject } from '@backstage/types';\nimport { Duration } from 'luxon';\n\n/**\n * A function that can be called as a scheduled task.\n *\n * It may optionally accept an abort signal argument. When the signal triggers,\n * processing should abort and return as quickly as possible.\n *\n * @public\n */\nexport type SchedulerServiceTaskFunction =\n | ((abortSignal: AbortSignal) => void | Promise<void>)\n | (() => void | Promise<void>);\n\n/**\n * A semi-opaque type to describe an actively scheduled task.\n *\n * @public\n */\nexport type SchedulerServiceTaskDescriptor = {\n /**\n * The unique identifier of the task.\n */\n id: string;\n /**\n * The scope of the task.\n */\n scope: 'global' | 'local';\n /**\n * The settings that control the task flow. This is a semi-opaque structure\n * that is mainly there for debugging purposes. Do not make any assumptions\n * about the contents of this field.\n */\n settings: { version: number } & JsonObject;\n};\n\n/**\n * Options that control the scheduling of a task.\n *\n * @public\n */\nexport interface SchedulerServiceTaskScheduleDefinition {\n /**\n * How often you want the task to run. The system does its best to avoid\n * overlapping invocations.\n *\n * @remarks\n *\n * This is the best effort value; under some circumstances there can be\n * deviations. For example, if the task runtime is longer than the frequency\n * and the timeout has not been given or not been exceeded yet, the next\n * invocation of this task will be delayed until after the previous one\n * finishes.\n *\n * This is a required field.\n */\n frequency:\n | {\n /**\n * A crontab style string.\n *\n * @remarks\n *\n * Overview:\n *\n * ```\n * ┌────────────── second (optional)\n * │ ┌──────────── minute\n * │ │ ┌────────── hour\n * │ │ │ ┌──────── day of month\n * │ │ │ │ ┌────── month\n * │ │ │ │ │ ┌──── day of week\n * │ │ │ │ │ │\n * │ │ │ │ │ │\n * * * * * * *\n * ```\n */\n cron: string;\n }\n | Duration\n | HumanDuration;\n\n /**\n * The maximum amount of time that a single task invocation can take, before\n * it's considered timed out and gets \"released\" such that a new invocation\n * is permitted to take place (possibly, then, on a different worker).\n */\n timeout: Duration | HumanDuration;\n\n /**\n * The amount of time that should pass before the first invocation happens.\n *\n * @remarks\n *\n * This can be useful in cold start scenarios to stagger or delay some heavy\n * compute jobs. If no value is given for this field then the first invocation\n * will happen as soon as possible according to the cadence.\n *\n * NOTE: This is a per-worker delay. If you have a cluster of workers all\n * collaborating on a task that has its `scope` field set to `'global'`, then\n * you may still see the task being processed by other long-lived workers,\n * while any given single worker is in its initial sleep delay time e.g. after\n * a deployment. Therefore, this parameter is not useful for \"globally\" pausing\n * work; its main intended use is for individual machines to get a chance to\n * reach some equilibrium at startup before triggering heavy batch workloads.\n */\n initialDelay?: Duration | HumanDuration;\n\n /**\n * Sets the scope of concurrency control / locking to apply for invocations of\n * this task.\n *\n * @remarks\n *\n * When the scope is set to the default value `'global'`, the scheduler will\n * attempt to ensure that only one worker machine runs the task at a time,\n * according to the given cadence. This means that as the number of worker\n * hosts increases, the invocation frequency of this task will not go up.\n * Instead, the load is spread randomly across hosts. This setting is useful\n * for tasks that access shared resources, for example catalog ingestion tasks\n * where you do not want many machines to repeatedly import the same data and\n * trample over each other.\n *\n * When the scope is set to `'local'`, there is no concurrency control across\n * hosts. Each host runs the task according to the given cadence similarly to\n * `setInterval`, but the runtime ensures that there are no overlapping runs.\n *\n * @defaultValue 'global'\n */\n scope?: 'global' | 'local';\n}\n\n/**\n * Config options for {@link SchedulerServiceTaskScheduleDefinition}\n * that control the scheduling of a task.\n *\n * @public\n */\nexport interface SchedulerServiceTaskScheduleDefinitionConfig {\n /**\n * How often you want the task to run. The system does its best to avoid\n * overlapping invocations.\n *\n * @remarks\n *\n * This is the best effort value; under some circumstances there can be\n * deviations. For example, if the task runtime is longer than the frequency\n * and the timeout has not been given or not been exceeded yet, the next\n * invocation of this task will be delayed until after the previous one\n * finishes.\n *\n * This is a required field.\n */\n frequency:\n | {\n /**\n * A crontab style string.\n *\n * @remarks\n *\n * Overview:\n *\n * ```\n * ┌────────────── second (optional)\n * │ ┌──────────── minute\n * │ │ ┌────────── hour\n * │ │ │ ┌──────── day of month\n * │ │ │ │ ┌────── month\n * │ │ │ │ │ ┌──── day of week\n * │ │ │ │ │ │\n * │ │ │ │ │ │\n * * * * * * *\n * ```\n */\n cron: string;\n }\n | string\n | HumanDuration;\n\n /**\n * The maximum amount of time that a single task invocation can take, before\n * it's considered timed out and gets \"released\" such that a new invocation\n * is permitted to take place (possibly, then, on a different worker).\n */\n timeout: string | HumanDuration;\n\n /**\n * The amount of time that should pass before the first invocation happens.\n *\n * @remarks\n *\n * This can be useful in cold start scenarios to stagger or delay some heavy\n * compute jobs. If no value is given for this field then the first invocation\n * will happen as soon as possible according to the cadence.\n *\n * NOTE: This is a per-worker delay. If you have a cluster of workers all\n * collaborating on a task that has its `scope` field set to `'global'`, then\n * you may still see the task being processed by other long-lived workers,\n * while any given single worker is in its initial sleep delay time e.g. after\n * a deployment. Therefore, this parameter is not useful for \"globally\" pausing\n * work; its main intended use is for individual machines to get a chance to\n * reach some equilibrium at startup before triggering heavy batch workloads.\n */\n initialDelay?: string | HumanDuration;\n\n /**\n * Sets the scope of concurrency control / locking to apply for invocations of\n * this task.\n *\n * @remarks\n *\n * When the scope is set to the default value `'global'`, the scheduler will\n * attempt to ensure that only one worker machine runs the task at a time,\n * according to the given cadence. This means that as the number of worker\n * hosts increases, the invocation frequency of this task will not go up.\n * Instead, the load is spread randomly across hosts. This setting is useful\n * for tasks that access shared resources, for example catalog ingestion tasks\n * where you do not want many machines to repeatedly import the same data and\n * trample over each other.\n *\n * When the scope is set to `'local'`, there is no concurrency control across\n * hosts. Each host runs the task according to the given cadence similarly to\n * `setInterval`, but the runtime ensures that there are no overlapping runs.\n *\n * @defaultValue 'global'\n */\n scope?: 'global' | 'local';\n}\n\n/**\n * Options that apply to the invocation of a given task.\n *\n * @public\n */\nexport interface SchedulerServiceTaskInvocationDefinition {\n /**\n * A unique ID (within the scope of the plugin) for the task.\n */\n id: string;\n\n /**\n * The actual task function to be invoked regularly.\n */\n fn: SchedulerServiceTaskFunction;\n\n /**\n * An abort signal that, when triggered, will stop the recurring execution of\n * the task.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A previously prepared task schedule, ready to be invoked.\n *\n * @public\n */\nexport interface SchedulerServiceTaskRunner {\n /**\n * Takes the schedule and executes an actual task using it.\n *\n * @param task - The actual runtime properties of the task\n */\n run(task: SchedulerServiceTaskInvocationDefinition): Promise<void>;\n}\n\n/**\n * Deals with the scheduling of distributed tasks, for a given plugin.\n *\n * See the {@link https://backstage.io/docs/backend-system/core-services/scheduler | service documentation} for more details.\n *\n * @public\n */\nexport interface SchedulerService {\n /**\n * Manually triggers a task by ID.\n *\n * If the task doesn't exist, a NotFoundError is thrown. If the task is\n * currently running, a ConflictError is thrown.\n *\n * @param id - The task ID\n */\n triggerTask(id: string): Promise<void>;\n\n /**\n * Schedules a task function for recurring runs.\n *\n * @remarks\n *\n * The `scope` task field controls whether to use coordinated exclusive\n * invocation across workers, or to just coordinate within the current worker.\n *\n * This convenience method performs both the scheduling and invocation in one\n * go.\n *\n * @param task - The task definition\n */\n scheduleTask(\n task: SchedulerServiceTaskScheduleDefinition &\n SchedulerServiceTaskInvocationDefinition,\n ): Promise<void>;\n\n /**\n * Creates a scheduled but dormant recurring task, ready to be launched at a\n * later time.\n *\n * @remarks\n *\n * This method is useful for pre-creating a schedule in outer code to be\n * passed into an inner implementation, such that the outer code controls\n * scheduling while inner code controls implementation.\n *\n * @param schedule - The task schedule\n */\n createScheduledTaskRunner(\n schedule: SchedulerServiceTaskScheduleDefinition,\n ): SchedulerServiceTaskRunner;\n\n /**\n * Returns all scheduled tasks registered to this scheduler.\n *\n * @remarks\n *\n * This method is useful for triggering tasks manually using the triggerTask\n * functionality. Note that the returned tasks contain only tasks that have\n * been initialized in this instance of the scheduler.\n *\n * @returns Scheduled tasks\n */\n getScheduledTasks(): Promise<SchedulerServiceTaskDescriptor[]>;\n}\n\nfunction readDuration(config: Config, key: string): HumanDuration {\n if (typeof config.get(key) === 'string') {\n const value = config.getString(key);\n const duration = Duration.fromISO(value);\n if (!duration.isValid) {\n throw new Error(`Invalid duration: ${value}`);\n }\n return duration.toObject();\n }\n\n return readDurationFromConfig(config, { key });\n}\n\nfunction readCronOrDuration(\n config: Config,\n key: string,\n): { cron: string } | HumanDuration {\n const value = config.get(key);\n if (typeof value === 'object' && (value as { cron?: string }).cron) {\n return value as { cron: string };\n }\n\n return readDuration(config, key);\n}\n\n/**\n * Reads a {@link SchedulerServiceTaskScheduleDefinition} from config. Expects\n * the config not to be the root config, but the config for the definition.\n *\n * @param config - config for a TaskScheduleDefinition.\n * @public\n */\nexport function readSchedulerServiceTaskScheduleDefinitionFromConfig(\n config: Config,\n): SchedulerServiceTaskScheduleDefinition {\n const frequency = readCronOrDuration(config, 'frequency');\n const timeout = readDuration(config, 'timeout');\n\n const initialDelay = config.has('initialDelay')\n ? readDuration(config, 'initialDelay')\n : undefined;\n\n const scope = config.getOptionalString('scope');\n if (scope && !['global', 'local'].includes(scope)) {\n throw new Error(\n `Only \"global\" or \"local\" are allowed for TaskScheduleDefinition.scope, but got: ${scope}`,\n );\n }\n\n return {\n frequency,\n timeout,\n initialDelay,\n scope: scope as 'global' | 'local' | undefined,\n };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Tries to deduce whether a thrown error is a database conflict.\n *\n * @public\n * @param e - A thrown error\n * @returns True if the error looks like it was a conflict error thrown by a\n * known database engine\n */\nexport function isDatabaseConflictError(e: unknown) {\n const message = (e as any)?.message;\n\n return (\n typeof message === 'string' &&\n (/SQLITE_CONSTRAINT(?:_UNIQUE)?: UNIQUE/.test(message) ||\n /UNIQUE constraint failed:/.test(message) ||\n /unique constraint/.test(message) ||\n /Duplicate entry/.test(message)) // MySQL uniqueness error msg\n );\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackendFeatureCompat } from '../types';\nimport {\n BackendModuleRegistrationPoints,\n BackendPluginRegistrationPoints,\n ExtensionPoint,\n InternalBackendModuleRegistration,\n InternalBackendPluginRegistration,\n} from './types';\n\n/**\n * The configuration options passed to {@link createExtensionPoint}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateExtensionPointOptions {\n /**\n * The ID of this extension point.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n id: string;\n}\n\n/**\n * Creates a new backend extension point.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}\n */\nexport function createExtensionPoint<T>(\n options: CreateExtensionPointOptions,\n): ExtensionPoint<T> {\n return {\n id: options.id,\n get T(): T {\n if (process.env.NODE_ENV === 'test') {\n // Avoid throwing errors so tests asserting extensions' properties cannot be easily broken\n return null as T;\n }\n throw new Error(`tried to read ExtensionPoint.T of ${this}`);\n },\n toString() {\n return `extensionPoint{${options.id}}`;\n },\n $$type: '@backstage/ExtensionPoint',\n };\n}\n\n/**\n * The configuration options passed to {@link createBackendPlugin}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendPluginOptions {\n /**\n * The ID of this plugin.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n register(reg: BackendPluginRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendPlugin(\n options: CreateBackendPluginOptions,\n): BackendFeatureCompat {\n function getRegistrations() {\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendPluginRegistration['init'] | undefined = undefined;\n\n options.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n extensionPoints.push([ext, impl]);\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'plugin',\n pluginId: options.pluginId,\n extensionPoints,\n init,\n },\n ];\n }\n\n function backendFeatureCompatWrapper() {\n return backendFeatureCompatWrapper;\n }\n\n Object.assign(backendFeatureCompatWrapper, {\n $$type: '@backstage/BackendFeature' as const,\n version: 'v1',\n getRegistrations,\n });\n\n return backendFeatureCompatWrapper as BackendFeatureCompat;\n}\n\n/**\n * The configuration options passed to {@link createBackendModule}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendModuleOptions {\n /**\n * Should exactly match the `id` of the plugin that the module extends.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n\n /**\n * The ID of this module, used to identify the module and ensure that it is not installed twice.\n */\n moduleId: string;\n register(reg: BackendModuleRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend module for a given plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendModule(\n options: CreateBackendModuleOptions,\n): BackendFeatureCompat {\n function getRegistrations() {\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendModuleRegistration['init'] | undefined = undefined;\n\n options.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n extensionPoints.push([ext, impl]);\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'module',\n pluginId: options.pluginId,\n moduleId: options.moduleId,\n extensionPoints,\n init,\n },\n ];\n }\n\n function backendFeatureCompatWrapper() {\n return backendFeatureCompatWrapper;\n }\n\n Object.assign(backendFeatureCompatWrapper, {\n $$type: '@backstage/BackendFeature' as const,\n version: 'v1',\n getRegistrations,\n });\n\n return backendFeatureCompatWrapper as BackendFeatureCompat;\n}\n"],"names":["c","coreServices","config","Duration","readDurationFromConfig"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/services/system/types.ts","../src/services/definitions/coreServices.ts","../src/services/definitions/SchedulerService.ts","../src/services/utilities/database.ts","../src/wiring/createBackendModule.ts","../src/wiring/createBackendPlugin.ts","../src/wiring/createExtensionPoint.ts","../../frontend-plugin-api/src/routing/describeParentCallSite.ts","../src/wiring/createBackendFeatureLoader.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackendFeature } from '../../types';\n\n/**\n * TODO\n *\n * @public\n */\nexport type ServiceRef<\n TService,\n TScope extends 'root' | 'plugin' = 'root' | 'plugin',\n TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton',\n> = {\n id: string;\n\n /**\n * This determines the scope at which this service is available.\n *\n * Root scoped services are available to all other services but\n * may only depend on other root scoped services.\n *\n * Plugin scoped services are only available to other plugin scoped\n * services but may depend on all other services.\n */\n scope: TScope;\n\n multiton?: TInstances extends 'multiton' ? true : false;\n\n /**\n * Utility for getting the type of the service, using `typeof serviceRef.T`.\n * Attempting to actually read this value will result in an exception.\n */\n T: TService;\n\n $$type: '@backstage/ServiceRef';\n};\n\n/** @public */\nexport interface ServiceFactory<\n TService = unknown,\n TScope extends 'plugin' | 'root' = 'plugin' | 'root',\n TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton',\n> extends BackendFeature {\n service: ServiceRef<TService, TScope, TInstances>;\n}\n\n/**\n * @public\n * @deprecated This type exists only as a helper for old code that relied on `createServiceFactory` to return `() => ServiceFactory` instead of `ServiceFactory`. You should remove the `()` parentheses at the end of your usages. This type will be removed in a future release.\n */\nexport interface ServiceFactoryCompat<\n TService = unknown,\n TScope extends 'plugin' | 'root' = 'plugin' | 'root',\n TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton',\n TOpts extends object | undefined = undefined,\n> extends ServiceFactory<TService, TScope, TInstances> {\n /**\n * @deprecated Callable service factories will be removed in a future release, please re-implement the service factory using the available APIs instead. If no options are being passed, you can simply remove the trailing `()`.\n */\n (\n ...options: undefined extends TOpts ? [] : [options?: TOpts]\n ): ServiceFactory<TService, TScope, TInstances>;\n}\n\n/** @internal */\nexport interface InternalServiceFactory<\n TService = unknown,\n TScope extends 'plugin' | 'root' = 'plugin' | 'root',\n TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton',\n> extends ServiceFactory<TService, TScope, TInstances> {\n version: 'v1';\n featureType: 'service';\n initialization?: 'always' | 'lazy';\n deps: { [key in string]: ServiceRef<unknown> };\n createRootContext?(deps: { [key in string]: unknown }): Promise<unknown>;\n factory(\n deps: { [key in string]: unknown },\n context: unknown,\n ): Promise<TService>;\n}\n\n/**\n * Represents either a {@link ServiceFactory} or a function that returns one.\n *\n * @deprecated The support for service factory functions is deprecated and will be removed.\n * @public\n */\nexport type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory);\n\n/** @public */\nexport interface ServiceRefOptions<\n TService,\n TScope extends 'root' | 'plugin',\n TInstances extends 'singleton' | 'multiton',\n> {\n id: string;\n scope?: TScope;\n multiton?: TInstances extends 'multiton' ? true : false;\n defaultFactory?(\n service: ServiceRef<TService, TScope>,\n ): Promise<ServiceFactory>;\n /**\n * @deprecated The defaultFactory must return a plain `ServiceFactory` object, support for returning a function will be removed.\n */\n defaultFactory?(\n service: ServiceRef<TService, TScope>,\n ): Promise<() => ServiceFactory>;\n}\n\n/**\n * Creates a new service definition. This overload is used to create plugin scoped services.\n *\n * @public\n */\nexport function createServiceRef<TService>(\n options: ServiceRefOptions<TService, 'plugin', 'singleton'>,\n): ServiceRef<TService, 'plugin', 'singleton'>;\n\n/**\n * Creates a new service definition. This overload is used to create root scoped services.\n *\n * @public\n */\nexport function createServiceRef<TService>(\n options: ServiceRefOptions<TService, 'root', 'singleton'>,\n): ServiceRef<TService, 'root', 'singleton'>;\n\n/**\n * Creates a new service definition. This overload is used to create plugin scoped services.\n *\n * @public\n */\nexport function createServiceRef<TService>(\n options: ServiceRefOptions<TService, 'plugin', 'multiton'>,\n): ServiceRef<TService, 'plugin', 'multiton'>;\n\n/**\n * Creates a new service definition. This overload is used to create root scoped services.\n *\n * @public\n */\nexport function createServiceRef<TService>(\n options: ServiceRefOptions<TService, 'root', 'multiton'>,\n): ServiceRef<TService, 'root', 'multiton'>;\nexport function createServiceRef<\n TService,\n TInstances extends 'singleton' | 'multiton',\n>(\n options: ServiceRefOptions<TService, any, TInstances>,\n): ServiceRef<TService, any, TInstances> {\n const { id, scope = 'plugin', multiton = false, defaultFactory } = options;\n return {\n id,\n scope,\n multiton,\n get T(): TService {\n throw new Error(`tried to read ServiceRef.T of ${this}`);\n },\n toString() {\n return `serviceRef{${options.id}}`;\n },\n $$type: '@backstage/ServiceRef',\n __defaultFactory: defaultFactory,\n } as ServiceRef<TService, typeof scope, TInstances> & {\n __defaultFactory?: (\n service: ServiceRef<TService>,\n ) => Promise<ServiceFactory<TService> | (() => ServiceFactory<TService>)>;\n };\n}\n\n/** @ignore */\ntype ServiceRefsToInstances<\n T extends { [key in string]: ServiceRef<unknown> },\n TScope extends 'root' | 'plugin' = 'root' | 'plugin',\n> = {\n [key in keyof T as T[key]['scope'] extends TScope\n ? key\n : never]: T[key]['multiton'] extends true | undefined\n ? Array<T[key]['T']>\n : T[key]['T'];\n};\n\n/** @public */\nexport interface RootServiceFactoryOptions<\n TService, // TODO(Rugvip): Can we forward the entire service ref type here instead of forwarding each type arg once the callback form is gone?\n TInstances extends 'singleton' | 'multiton',\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n> {\n /**\n * The initialization strategy for the service factory. This service is root scoped and will use `always` by default.\n *\n * @remarks\n *\n * - `always` - The service will always be initialized regardless if it is used or not.\n * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.\n *\n * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.\n */\n initialization?: 'always' | 'lazy';\n service: ServiceRef<TService, 'root', TInstances>;\n deps: TDeps;\n factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;\n}\n\n/** @public */\nexport interface PluginServiceFactoryOptions<\n TService,\n TInstances extends 'singleton' | 'multiton',\n TContext,\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n> {\n /**\n * The initialization strategy for the service factory. This service is plugin scoped and will use `lazy` by default.\n *\n * @remarks\n *\n * - `always` - The service will always be initialized regardless if it is used or not.\n * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.\n *\n * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.\n */\n initialization?: 'always' | 'lazy';\n service: ServiceRef<TService, 'plugin', TInstances>;\n deps: TDeps;\n createRootContext?(\n deps: ServiceRefsToInstances<TDeps, 'root'>,\n ): TContext | Promise<TContext>;\n factory(\n deps: ServiceRefsToInstances<TDeps>,\n context: TContext,\n ): TImpl | Promise<TImpl>;\n}\n\n/**\n * Creates a root scoped service factory without options.\n *\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TInstances extends 'singleton' | 'multiton',\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown, 'root'> },\n TOpts extends object | undefined = undefined,\n>(\n options: RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>,\n): ServiceFactoryCompat<TService, 'root', TInstances>;\n/**\n * Creates a root scoped service factory with optional options.\n *\n * @deprecated The ability to define options for service factories is deprecated\n * and will be removed. Please use the non-callback form of createServiceFactory\n * and provide an API that allows for a simple re-implementation of the service\n * factory instead.\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TInstances extends 'singleton' | 'multiton',\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown, 'root'> },\n TOpts extends object | undefined = undefined,\n>(\n options: (\n options?: TOpts,\n ) => RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>,\n): ServiceFactoryCompat<TService, 'root', TInstances, TOpts>;\n/**\n * Creates a plugin scoped service factory without options.\n *\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TInstances extends 'singleton' | 'multiton',\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n TContext = undefined,\n TOpts extends object | undefined = undefined,\n>(\n options: PluginServiceFactoryOptions<\n TService,\n TInstances,\n TContext,\n TImpl,\n TDeps\n >,\n): ServiceFactoryCompat<TService, 'plugin', TInstances>;\n/**\n * Creates a plugin scoped service factory with optional options.\n *\n * @deprecated The ability to define options for service factories is deprecated\n * and will be removed. Please use the non-callback form of createServiceFactory\n * and provide an API that allows for a simple re-implementation of the service\n * factory instead.\n * @public\n * @param options - The service factory configuration.\n */\nexport function createServiceFactory<\n TService,\n TInstances extends 'singleton' | 'multiton',\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n TContext = undefined,\n TOpts extends object | undefined = undefined,\n>(\n options: (\n options?: TOpts,\n ) => PluginServiceFactoryOptions<\n TService,\n TInstances,\n TContext,\n TImpl,\n TDeps\n >,\n): ServiceFactoryCompat<TService, 'plugin', TInstances, TOpts>;\nexport function createServiceFactory<\n TService,\n TInstances extends 'singleton' | 'multiton',\n TImpl extends TService,\n TDeps extends { [name in string]: ServiceRef<unknown> },\n TContext,\n TOpts extends object | undefined = undefined,\n>(\n options:\n | RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>\n | PluginServiceFactoryOptions<TService, TInstances, TContext, TImpl, TDeps>\n | ((\n options: TOpts,\n ) => RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>)\n | ((\n options: TOpts,\n ) => PluginServiceFactoryOptions<\n TService,\n TInstances,\n TContext,\n TImpl,\n TDeps\n >)\n | (() => RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>)\n | (() => PluginServiceFactoryOptions<\n TService,\n TInstances,\n TContext,\n TImpl,\n TDeps\n >),\n): ServiceFactoryCompat<\n TService,\n 'root' | 'plugin',\n 'singleton' | 'multiton',\n TOpts\n> {\n const configCallback =\n typeof options === 'function' ? options : () => options;\n const factory = (\n o?: TOpts,\n ): InternalServiceFactory<TService, 'plugin' | 'root'> => {\n const anyConf = configCallback(o!);\n if (anyConf.service.scope === 'root') {\n const c = anyConf as RootServiceFactoryOptions<\n TService,\n TInstances,\n TImpl,\n TDeps\n >;\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n featureType: 'service',\n service: c.service,\n initialization: c.initialization,\n deps: c.deps,\n factory: async (deps: ServiceRefsToInstances<TDeps, 'root'>) =>\n c.factory(deps),\n };\n }\n const c = anyConf as PluginServiceFactoryOptions<\n TService,\n TInstances,\n TContext,\n TImpl,\n TDeps\n >;\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n featureType: 'service',\n service: c.service,\n initialization: c.initialization,\n ...('createRootContext' in c\n ? {\n createRootContext: async (\n deps: ServiceRefsToInstances<TDeps, 'root'>,\n ) => c?.createRootContext?.(deps),\n }\n : {}),\n deps: c.deps,\n factory: async (deps: ServiceRefsToInstances<TDeps>, ctx: TContext) =>\n c.factory(deps, ctx),\n };\n };\n\n // This constructs the `ServiceFactoryCompat` type, which is both a plain\n // factory object as well as a function that can be called to construct a\n // factory, potentially with options. In the future only the plain factory\n // form will be supported, but for now we need to allow callers to call the\n // factory too.\n return Object.assign(factory, factory(undefined as TOpts));\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createServiceRef } from '../system';\n\n/**\n * All core services references\n *\n * @public\n */\nexport namespace coreServices {\n /**\n * Handles token authentication and credentials management.\n *\n * See {@link AuthService}\n * and {@link https://backstage.io/docs/backend-system/core-services/auth | the service docs}\n * for more information.\n *\n * @public\n */\n export const auth = createServiceRef<import('./AuthService').AuthService>({\n id: 'core.auth',\n });\n\n /**\n * Authenticated user information retrieval.\n *\n * See {@link UserInfoService}\n * and {@link https://backstage.io/docs/backend-system/core-services/user-info | the service docs}\n * for more information.\n *\n * @public\n */\n export const userInfo = createServiceRef<\n import('./UserInfoService').UserInfoService\n >({\n id: 'core.userInfo',\n });\n\n /**\n * Key-value store for caching data.\n *\n * See {@link CacheService}\n * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs}\n * for more information.\n *\n * @public\n */\n export const cache = createServiceRef<import('./CacheService').CacheService>({\n id: 'core.cache',\n });\n\n /**\n * Access to static configuration.\n *\n * See {@link RootConfigService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-config | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootConfig = createServiceRef<\n import('./RootConfigService').RootConfigService\n >({ id: 'core.rootConfig', scope: 'root' });\n\n /**\n * Database access and management via `knex`.\n *\n * See {@link DatabaseService}\n * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs}\n * for more information.\n *\n * @public\n */\n export const database = createServiceRef<\n import('./DatabaseService').DatabaseService\n >({ id: 'core.database' });\n\n /**\n * Service discovery for inter-plugin communication.\n *\n * See {@link DiscoveryService}\n * and {@link https://backstage.io/docs/backend-system/core-services/discovery | the service docs}\n * for more information.\n *\n * @public\n */\n export const discovery = createServiceRef<\n import('./DiscoveryService').DiscoveryService\n >({ id: 'core.discovery' });\n\n /**\n * The service reference for the plugin scoped {@link RootHealthService}.\n */\n export const rootHealth = createServiceRef<\n import('./RootHealthService').RootHealthService\n >({ id: 'core.rootHealth', scope: 'root' });\n\n /**\n * Authentication of HTTP requests.\n *\n * See {@link HttpAuthService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-auth | the service docs}\n * for more information.\n *\n * @public\n */\n export const httpAuth = createServiceRef<\n import('./HttpAuthService').HttpAuthService\n >({ id: 'core.httpAuth' });\n\n /**\n * HTTP route registration for plugins.\n *\n * See {@link HttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/http-router | the service docs}\n * for more information.\n *\n * @public\n */\n export const httpRouter = createServiceRef<\n import('./HttpRouterService').HttpRouterService\n >({ id: 'core.httpRouter' });\n\n /**\n * Registration of plugin startup and shutdown lifecycle hooks.\n *\n * See {@link LifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\n export const lifecycle = createServiceRef<\n import('./LifecycleService').LifecycleService\n >({ id: 'core.lifecycle' });\n\n /**\n * Plugin-level logging.\n *\n * See {@link LoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/logger | the service docs}\n * for more information.\n *\n * @public\n */\n export const logger = createServiceRef<\n import('./LoggerService').LoggerService\n >({ id: 'core.logger' });\n\n /**\n * Permission system integration for authorization of user actions.\n *\n * See {@link PermissionsService}\n * and {@link https://backstage.io/docs/backend-system/core-services/permissions | the service docs}\n * for more information.\n *\n * @public\n */\n export const permissions = createServiceRef<\n import('./PermissionsService').PermissionsService\n >({ id: 'core.permissions' });\n\n /**\n * Built-in service for accessing metadata about the current plugin.\n *\n * See {@link PluginMetadataService}\n * and {@link https://backstage.io/docs/backend-system/core-services/plugin-metadata | the service docs}\n * for more information.\n *\n * @public\n */\n export const pluginMetadata = createServiceRef<\n import('./PluginMetadataService').PluginMetadataService\n >({ id: 'core.pluginMetadata' });\n\n /**\n * HTTP route registration for root services.\n *\n * See {@link RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootHttpRouter = createServiceRef<\n import('./RootHttpRouterService').RootHttpRouterService\n >({ id: 'core.rootHttpRouter', scope: 'root' });\n\n /**\n * Registration of backend startup and shutdown lifecycle hooks.\n *\n * See {@link RootLifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootLifecycle = createServiceRef<\n import('./RootLifecycleService').RootLifecycleService\n >({ id: 'core.rootLifecycle', scope: 'root' });\n\n /**\n * Root-level logging.\n *\n * See {@link RootLoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs}\n * for more information.\n *\n * @public\n */\n export const rootLogger = createServiceRef<\n import('./RootLoggerService').RootLoggerService\n >({ id: 'core.rootLogger', scope: 'root' });\n\n /**\n * Scheduling of distributed background tasks.\n *\n * See {@link SchedulerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/scheduler | the service docs}\n * for more information.\n *\n * @public\n */\n export const scheduler = createServiceRef<\n import('./SchedulerService').SchedulerService\n >({ id: 'core.scheduler' });\n\n /**\n * Deprecated service authentication service, use the `auth` service instead.\n *\n * See {@link TokenManagerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/token-manager | the service docs}\n * for more information.\n *\n * @public\n * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead\n */\n export const tokenManager = createServiceRef<\n import('./TokenManagerService').TokenManagerService\n >({ id: 'core.tokenManager' });\n\n /**\n * Reading content from external systems.\n *\n * See {@link UrlReaderService}\n * and {@link https://backstage.io/docs/backend-system/core-services/url-reader | the service docs}\n * for more information.\n *\n * @public\n */\n export const urlReader = createServiceRef<\n import('./UrlReaderService').UrlReaderService\n >({ id: 'core.urlReader' });\n\n /**\n * Deprecated user authentication service, use the `auth` service instead.\n *\n * See {@link IdentityService}\n * and {@link https://backstage.io/docs/backend-system/core-services/identity | the service docs}\n * for more information.\n *\n * @public\n * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead\n */\n export const identity = createServiceRef<\n import('./IdentityService').IdentityService\n >({ id: 'core.identity' });\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { HumanDuration, JsonObject } from '@backstage/types';\nimport { Duration } from 'luxon';\n\n/**\n * A function that can be called as a scheduled task.\n *\n * It may optionally accept an abort signal argument. When the signal triggers,\n * processing should abort and return as quickly as possible.\n *\n * @public\n */\nexport type SchedulerServiceTaskFunction =\n | ((abortSignal: AbortSignal) => void | Promise<void>)\n | (() => void | Promise<void>);\n\n/**\n * A semi-opaque type to describe an actively scheduled task.\n *\n * @public\n */\nexport type SchedulerServiceTaskDescriptor = {\n /**\n * The unique identifier of the task.\n */\n id: string;\n /**\n * The scope of the task.\n */\n scope: 'global' | 'local';\n /**\n * The settings that control the task flow. This is a semi-opaque structure\n * that is mainly there for debugging purposes. Do not make any assumptions\n * about the contents of this field.\n */\n settings: { version: number } & JsonObject;\n};\n\n/**\n * Options that control the scheduling of a task.\n *\n * @public\n */\nexport interface SchedulerServiceTaskScheduleDefinition {\n /**\n * How often you want the task to run. The system does its best to avoid\n * overlapping invocations.\n *\n * @remarks\n *\n * This is the best effort value; under some circumstances there can be\n * deviations. For example, if the task runtime is longer than the frequency\n * and the timeout has not been given or not been exceeded yet, the next\n * invocation of this task will be delayed until after the previous one\n * finishes.\n *\n * This is a required field.\n */\n frequency:\n | {\n /**\n * A crontab style string.\n *\n * @remarks\n *\n * Overview:\n *\n * ```\n * ┌────────────── second (optional)\n * │ ┌──────────── minute\n * │ │ ┌────────── hour\n * │ │ │ ┌──────── day of month\n * │ │ │ │ ┌────── month\n * │ │ │ │ │ ┌──── day of week\n * │ │ │ │ │ │\n * │ │ │ │ │ │\n * * * * * * *\n * ```\n */\n cron: string;\n }\n | Duration\n | HumanDuration\n | { trigger: 'manual' };\n\n /**\n * The maximum amount of time that a single task invocation can take, before\n * it's considered timed out and gets \"released\" such that a new invocation\n * is permitted to take place (possibly, then, on a different worker).\n */\n timeout: Duration | HumanDuration;\n\n /**\n * The amount of time that should pass before the first invocation happens.\n *\n * @remarks\n *\n * This can be useful in cold start scenarios to stagger or delay some heavy\n * compute jobs. If no value is given for this field then the first invocation\n * will happen as soon as possible according to the cadence.\n *\n * NOTE: This is a per-worker delay. If you have a cluster of workers all\n * collaborating on a task that has its `scope` field set to `'global'`, then\n * you may still see the task being processed by other long-lived workers,\n * while any given single worker is in its initial sleep delay time e.g. after\n * a deployment. Therefore, this parameter is not useful for \"globally\" pausing\n * work; its main intended use is for individual machines to get a chance to\n * reach some equilibrium at startup before triggering heavy batch workloads.\n */\n initialDelay?: Duration | HumanDuration;\n\n /**\n * Sets the scope of concurrency control / locking to apply for invocations of\n * this task.\n *\n * @remarks\n *\n * When the scope is set to the default value `'global'`, the scheduler will\n * attempt to ensure that only one worker machine runs the task at a time,\n * according to the given cadence. This means that as the number of worker\n * hosts increases, the invocation frequency of this task will not go up.\n * Instead, the load is spread randomly across hosts. This setting is useful\n * for tasks that access shared resources, for example catalog ingestion tasks\n * where you do not want many machines to repeatedly import the same data and\n * trample over each other.\n *\n * When the scope is set to `'local'`, there is no concurrency control across\n * hosts. Each host runs the task according to the given cadence similarly to\n * `setInterval`, but the runtime ensures that there are no overlapping runs.\n *\n * @defaultValue 'global'\n */\n scope?: 'global' | 'local';\n}\n\n/**\n * Config options for {@link SchedulerServiceTaskScheduleDefinition}\n * that control the scheduling of a task.\n *\n * @public\n */\nexport interface SchedulerServiceTaskScheduleDefinitionConfig {\n /**\n * How often you want the task to run. The system does its best to avoid\n * overlapping invocations.\n *\n * @remarks\n *\n * This is the best effort value; under some circumstances there can be\n * deviations. For example, if the task runtime is longer than the frequency\n * and the timeout has not been given or not been exceeded yet, the next\n * invocation of this task will be delayed until after the previous one\n * finishes.\n *\n * This is a required field.\n */\n frequency:\n | {\n /**\n * A crontab style string.\n *\n * @remarks\n *\n * Overview:\n *\n * ```\n * ┌────────────── second (optional)\n * │ ┌──────────── minute\n * │ │ ┌────────── hour\n * │ │ │ ┌──────── day of month\n * │ │ │ │ ┌────── month\n * │ │ │ │ │ ┌──── day of week\n * │ │ │ │ │ │\n * │ │ │ │ │ │\n * * * * * * *\n * ```\n */\n cron: string;\n }\n | string\n | HumanDuration\n /**\n * This task will only run when manually triggered with the `triggerTask` method; no automatic\n * scheduling. This is useful for locking of global tasks that should not be run concurrently.\n */\n | { trigger: 'manual' };\n\n /**\n * The maximum amount of time that a single task invocation can take, before\n * it's considered timed out and gets \"released\" such that a new invocation\n * is permitted to take place (possibly, then, on a different worker).\n */\n timeout: string | HumanDuration;\n\n /**\n * The amount of time that should pass before the first invocation happens.\n *\n * @remarks\n *\n * This can be useful in cold start scenarios to stagger or delay some heavy\n * compute jobs. If no value is given for this field then the first invocation\n * will happen as soon as possible according to the cadence.\n *\n * NOTE: This is a per-worker delay. If you have a cluster of workers all\n * collaborating on a task that has its `scope` field set to `'global'`, then\n * you may still see the task being processed by other long-lived workers,\n * while any given single worker is in its initial sleep delay time e.g. after\n * a deployment. Therefore, this parameter is not useful for \"globally\" pausing\n * work; its main intended use is for individual machines to get a chance to\n * reach some equilibrium at startup before triggering heavy batch workloads.\n */\n initialDelay?: string | HumanDuration;\n\n /**\n * Sets the scope of concurrency control / locking to apply for invocations of\n * this task.\n *\n * @remarks\n *\n * When the scope is set to the default value `'global'`, the scheduler will\n * attempt to ensure that only one worker machine runs the task at a time,\n * according to the given cadence. This means that as the number of worker\n * hosts increases, the invocation frequency of this task will not go up.\n * Instead, the load is spread randomly across hosts. This setting is useful\n * for tasks that access shared resources, for example catalog ingestion tasks\n * where you do not want many machines to repeatedly import the same data and\n * trample over each other.\n *\n * When the scope is set to `'local'`, there is no concurrency control across\n * hosts. Each host runs the task according to the given cadence similarly to\n * `setInterval`, but the runtime ensures that there are no overlapping runs.\n *\n * @defaultValue 'global'\n */\n scope?: 'global' | 'local';\n}\n\n/**\n * Options that apply to the invocation of a given task.\n *\n * @public\n */\nexport interface SchedulerServiceTaskInvocationDefinition {\n /**\n * A unique ID (within the scope of the plugin) for the task.\n */\n id: string;\n\n /**\n * The actual task function to be invoked regularly.\n */\n fn: SchedulerServiceTaskFunction;\n\n /**\n * An abort signal that, when triggered, will stop the recurring execution of\n * the task.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A previously prepared task schedule, ready to be invoked.\n *\n * @public\n */\nexport interface SchedulerServiceTaskRunner {\n /**\n * Takes the schedule and executes an actual task using it.\n *\n * @param task - The actual runtime properties of the task\n */\n run(task: SchedulerServiceTaskInvocationDefinition): Promise<void>;\n}\n\n/**\n * Deals with the scheduling of distributed tasks, for a given plugin.\n *\n * See the {@link https://backstage.io/docs/backend-system/core-services/scheduler | service documentation} for more details.\n *\n * @public\n */\nexport interface SchedulerService {\n /**\n * Manually triggers a task by ID.\n *\n * If the task doesn't exist, a NotFoundError is thrown. If the task is\n * currently running, a ConflictError is thrown.\n *\n * @param id - The task ID\n */\n triggerTask(id: string): Promise<void>;\n\n /**\n * Schedules a task function for recurring runs.\n *\n * @remarks\n *\n * The `scope` task field controls whether to use coordinated exclusive\n * invocation across workers, or to just coordinate within the current worker.\n *\n * This convenience method performs both the scheduling and invocation in one\n * go.\n *\n * @param task - The task definition\n */\n scheduleTask(\n task: SchedulerServiceTaskScheduleDefinition &\n SchedulerServiceTaskInvocationDefinition,\n ): Promise<void>;\n\n /**\n * Creates a scheduled but dormant recurring task, ready to be launched at a\n * later time.\n *\n * @remarks\n *\n * This method is useful for pre-creating a schedule in outer code to be\n * passed into an inner implementation, such that the outer code controls\n * scheduling while inner code controls implementation.\n *\n * @param schedule - The task schedule\n */\n createScheduledTaskRunner(\n schedule: SchedulerServiceTaskScheduleDefinition,\n ): SchedulerServiceTaskRunner;\n\n /**\n * Returns all scheduled tasks registered to this scheduler.\n *\n * @remarks\n *\n * This method is useful for triggering tasks manually using the triggerTask\n * functionality. Note that the returned tasks contain only tasks that have\n * been initialized in this instance of the scheduler.\n *\n * @returns Scheduled tasks\n */\n getScheduledTasks(): Promise<SchedulerServiceTaskDescriptor[]>;\n}\n\nfunction readDuration(config: Config, key: string): HumanDuration {\n if (typeof config.get(key) === 'string') {\n const value = config.getString(key);\n const duration = Duration.fromISO(value);\n if (!duration.isValid) {\n throw new Error(`Invalid duration: ${value}`);\n }\n return duration.toObject();\n }\n\n return readDurationFromConfig(config, { key });\n}\n\nfunction readFrequency(\n config: Config,\n key: string,\n): { cron: string } | HumanDuration | { trigger: 'manual' } {\n const value = config.get(key);\n if (typeof value === 'object' && (value as { cron?: string }).cron) {\n return value as { cron: string };\n }\n if (\n typeof value === 'object' &&\n (value as { trigger?: string }).trigger === 'manual'\n ) {\n return { trigger: 'manual' };\n }\n\n return readDuration(config, key);\n}\n\n/**\n * Reads a {@link SchedulerServiceTaskScheduleDefinition} from config. Expects\n * the config not to be the root config, but the config for the definition.\n *\n * @param config - config for a TaskScheduleDefinition.\n * @public\n */\nexport function readSchedulerServiceTaskScheduleDefinitionFromConfig(\n config: Config,\n): SchedulerServiceTaskScheduleDefinition {\n const frequency = readFrequency(config, 'frequency');\n const timeout = readDuration(config, 'timeout');\n\n const initialDelay = config.has('initialDelay')\n ? readDuration(config, 'initialDelay')\n : undefined;\n\n const scope = config.getOptionalString('scope');\n if (scope && !['global', 'local'].includes(scope)) {\n throw new Error(\n `Only \"global\" or \"local\" are allowed for TaskScheduleDefinition.scope, but got: ${scope}`,\n );\n }\n\n return {\n frequency,\n timeout,\n initialDelay,\n scope: scope as 'global' | 'local' | undefined,\n };\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Tries to deduce whether a thrown error is a database conflict.\n *\n * @public\n * @param e - A thrown error\n * @returns True if the error looks like it was a conflict error thrown by a\n * known database engine\n */\nexport function isDatabaseConflictError(e: unknown) {\n const message = (e as any)?.message;\n\n return (\n typeof message === 'string' &&\n (/SQLITE_CONSTRAINT(?:_UNIQUE)?: UNIQUE/.test(message) ||\n /UNIQUE constraint failed:/.test(message) ||\n /unique constraint/.test(message) ||\n /Duplicate entry/.test(message)) // MySQL uniqueness error msg\n );\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackendFeatureCompat } from '../types';\nimport {\n BackendModuleRegistrationPoints,\n InternalBackendModuleRegistration,\n InternalBackendPluginRegistration,\n} from './types';\n\n/**\n * The configuration options passed to {@link createBackendModule}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendModuleOptions {\n /**\n * Should exactly match the `id` of the plugin that the module extends.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n\n /**\n * The ID of this module, used to identify the module and ensure that it is not installed twice.\n */\n moduleId: string;\n register(reg: BackendModuleRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend module for a given plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendModule(\n options: CreateBackendModuleOptions,\n): BackendFeatureCompat {\n function getRegistrations() {\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendModuleRegistration['init'] | undefined = undefined;\n\n options.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n extensionPoints.push([ext, impl]);\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'module',\n pluginId: options.pluginId,\n moduleId: options.moduleId,\n extensionPoints,\n init,\n },\n ];\n }\n\n function backendFeatureCompatWrapper() {\n return backendFeatureCompatWrapper;\n }\n\n Object.assign(backendFeatureCompatWrapper, {\n $$type: '@backstage/BackendFeature' as const,\n version: 'v1',\n getRegistrations,\n });\n\n return backendFeatureCompatWrapper as BackendFeatureCompat;\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackendFeatureCompat } from '../types';\nimport {\n BackendPluginRegistrationPoints,\n InternalBackendPluginRegistration,\n} from './types';\n\n/**\n * The configuration options passed to {@link createBackendPlugin}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendPluginOptions {\n /**\n * The ID of this plugin.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n register(reg: BackendPluginRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendPlugin(\n options: CreateBackendPluginOptions,\n): BackendFeatureCompat {\n function getRegistrations() {\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendPluginRegistration['init'] | undefined = undefined;\n\n options.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n extensionPoints.push([ext, impl]);\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'plugin',\n pluginId: options.pluginId,\n extensionPoints,\n init,\n },\n ];\n }\n\n function backendFeatureCompatWrapper() {\n return backendFeatureCompatWrapper;\n }\n\n Object.assign(backendFeatureCompatWrapper, {\n $$type: '@backstage/BackendFeature' as const,\n version: 'v1',\n getRegistrations,\n });\n\n return backendFeatureCompatWrapper as BackendFeatureCompat;\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ExtensionPoint } from './types';\n\n/**\n * The configuration options passed to {@link createExtensionPoint}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateExtensionPointOptions {\n /**\n * The ID of this extension point.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n id: string;\n}\n\n/**\n * Creates a new backend extension point.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}\n */\nexport function createExtensionPoint<T>(\n options: CreateExtensionPointOptions,\n): ExtensionPoint<T> {\n return {\n id: options.id,\n get T(): T {\n if (process.env.NODE_ENV === 'test') {\n // Avoid throwing errors so tests asserting extensions' properties cannot be easily broken\n return null as T;\n }\n throw new Error(`tried to read ExtensionPoint.T of ${this}`);\n },\n toString() {\n return `extensionPoint{${options.id}}`;\n },\n $$type: '@backstage/ExtensionPoint',\n };\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst MESSAGE_MARKER = 'eHgtF5hmbrXyiEvo';\n\n// NOTE: This function is also imported and used in backend code\n\n/**\n * Internal helper that describes the location of the parent caller.\n * @internal\n */\nexport function describeParentCallSite(\n ErrorConstructor: { new (message: string): Error } = Error,\n): string {\n const { stack } = new ErrorConstructor(MESSAGE_MARKER);\n if (!stack) {\n return '<unknown>';\n }\n\n // Safari and Firefox don't include the error itself in the stack\n const startIndex = stack.includes(MESSAGE_MARKER)\n ? stack.indexOf('\\n') + 1\n : 0;\n const secondEntryStart =\n stack.indexOf('\\n', stack.indexOf('\\n', startIndex) + 1) + 1;\n const secondEntryEnd = stack.indexOf('\\n', secondEntryStart);\n\n const line = stack.substring(secondEntryStart, secondEntryEnd).trim();\n if (!line) {\n return 'unknown';\n }\n\n // Below we try to extract the location for different browsers.\n // Since RouteRefs are declared at the top-level of modules the caller name isn't interesting.\n\n // Chrome\n if (line.includes('(')) {\n return line.substring(line.indexOf('(') + 1, line.indexOf(')'));\n }\n\n // Safari & Firefox\n if (line.includes('@')) {\n return line.substring(line.indexOf('@') + 1);\n }\n\n // Give up\n return line;\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ServiceRef } from '../services';\nimport { BackendFeature } from '../types';\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { InternalBackendFeatureLoader } from './types';\n\n/**\n * @public\n * Options for creating a new backend feature loader.\n */\nexport interface CreateBackendFeatureLoaderOptions<\n TDeps extends { [name in string]: unknown },\n> {\n deps?: {\n [name in keyof TDeps]: ServiceRef<TDeps[name], 'root'>;\n };\n loader(\n deps: TDeps,\n ):\n | Iterable<BackendFeature | Promise<{ default: BackendFeature }>>\n | Promise<Iterable<BackendFeature | Promise<{ default: BackendFeature }>>>\n | AsyncIterable<BackendFeature | { default: BackendFeature }>;\n}\n\n/**\n * @public\n * Creates a new backend feature loader.\n */\nexport function createBackendFeatureLoader<\n TDeps extends { [name in string]: unknown },\n>(options: CreateBackendFeatureLoaderOptions<TDeps>): BackendFeature {\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n featureType: 'loader',\n description: `created at '${describeParentCallSite()}'`,\n deps: options.deps,\n async loader(deps: TDeps) {\n const it = await options.loader(deps);\n const result = new Array<BackendFeature>();\n for await (const item of it) {\n if ('$$type' in item && item.$$type === '@backstage/BackendFeature') {\n result.push(item);\n } else if ('default' in item) {\n result.push(item.default);\n } else {\n throw new Error(`Invalid item \"${item}\"`);\n }\n }\n return result;\n },\n } as InternalBackendFeatureLoader;\n}\n"],"names":["c","coreServices","config","Duration","readDurationFromConfig"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -482,7 +482,9 @@ interface SchedulerServiceTaskScheduleDefinition {
482
482
  * ```
483
483
  */
484
484
  cron: string;
485
- } | Duration | HumanDuration;
485
+ } | Duration | HumanDuration | {
486
+ trigger: 'manual';
487
+ };
486
488
  /**
487
489
  * The maximum amount of time that a single task invocation can take, before
488
490
  * it's considered timed out and gets "released" such that a new invocation
@@ -572,7 +574,14 @@ interface SchedulerServiceTaskScheduleDefinitionConfig {
572
574
  * ```
573
575
  */
574
576
  cron: string;
575
- } | string | HumanDuration;
577
+ } | string | HumanDuration
578
+ /**
579
+ * This task will only run when manually triggered with the `triggerTask` method; no automatic
580
+ * scheduling. This is useful for locking of global tasks that should not be run concurrently.
581
+ */
582
+ | {
583
+ trigger: 'manual';
584
+ };
576
585
  /**
577
586
  * The maximum amount of time that a single task invocation can take, before
578
587
  * it's considered timed out and gets "released" such that a new invocation
@@ -1436,7 +1445,7 @@ interface BackendFeatureCompat extends BackendFeature {
1436
1445
  *
1437
1446
  * @public
1438
1447
  */
1439
- type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'root' | 'plugin'> = {
1448
+ type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'root' | 'plugin', TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton'> = {
1440
1449
  id: string;
1441
1450
  /**
1442
1451
  * This determines the scope at which this service is available.
@@ -1448,6 +1457,7 @@ type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'root' | 'plugin'>
1448
1457
  * services but may depend on all other services.
1449
1458
  */
1450
1459
  scope: TScope;
1460
+ multiton?: TInstances extends 'multiton' ? true : false;
1451
1461
  /**
1452
1462
  * Utility for getting the type of the service, using `typeof serviceRef.T`.
1453
1463
  * Attempting to actually read this value will result in an exception.
@@ -1456,18 +1466,18 @@ type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'root' | 'plugin'>
1456
1466
  $$type: '@backstage/ServiceRef';
1457
1467
  };
1458
1468
  /** @public */
1459
- interface ServiceFactory<TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root'> extends BackendFeature {
1460
- service: ServiceRef<TService, TScope>;
1469
+ interface ServiceFactory<TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root', TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton'> extends BackendFeature {
1470
+ service: ServiceRef<TService, TScope, TInstances>;
1461
1471
  }
1462
1472
  /**
1463
1473
  * @public
1464
1474
  * @deprecated This type exists only as a helper for old code that relied on `createServiceFactory` to return `() => ServiceFactory` instead of `ServiceFactory`. You should remove the `()` parentheses at the end of your usages. This type will be removed in a future release.
1465
1475
  */
1466
- interface ServiceFactoryCompat<TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root', TOpts extends object | undefined = undefined> extends ServiceFactory<TService, TScope> {
1476
+ interface ServiceFactoryCompat<TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root', TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton', TOpts extends object | undefined = undefined> extends ServiceFactory<TService, TScope, TInstances> {
1467
1477
  /**
1468
1478
  * @deprecated Callable service factories will be removed in a future release, please re-implement the service factory using the available APIs instead. If no options are being passed, you can simply remove the trailing `()`.
1469
1479
  */
1470
- (...options: undefined extends TOpts ? [] : [options?: TOpts]): ServiceFactory<TService, TScope>;
1480
+ (...options: undefined extends TOpts ? [] : [options?: TOpts]): ServiceFactory<TService, TScope, TInstances>;
1471
1481
  }
1472
1482
  /**
1473
1483
  * Represents either a {@link ServiceFactory} or a function that returns one.
@@ -1477,9 +1487,10 @@ interface ServiceFactoryCompat<TService = unknown, TScope extends 'plugin' | 'ro
1477
1487
  */
1478
1488
  type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory);
1479
1489
  /** @public */
1480
- interface ServiceRefOptions<TService, TScope extends 'root' | 'plugin'> {
1490
+ interface ServiceRefOptions<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton'> {
1481
1491
  id: string;
1482
1492
  scope?: TScope;
1493
+ multiton?: TInstances extends 'multiton' ? true : false;
1483
1494
  defaultFactory?(service: ServiceRef<TService, TScope>): Promise<ServiceFactory>;
1484
1495
  /**
1485
1496
  * @deprecated The defaultFactory must return a plain `ServiceFactory` object, support for returning a function will be removed.
@@ -1491,21 +1502,34 @@ interface ServiceRefOptions<TService, TScope extends 'root' | 'plugin'> {
1491
1502
  *
1492
1503
  * @public
1493
1504
  */
1494
- declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'plugin'>): ServiceRef<TService, 'plugin'>;
1505
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'plugin', 'singleton'>): ServiceRef<TService, 'plugin', 'singleton'>;
1495
1506
  /**
1496
1507
  * Creates a new service definition. This overload is used to create root scoped services.
1497
1508
  *
1498
1509
  * @public
1499
1510
  */
1500
- declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'root'>): ServiceRef<TService, 'root'>;
1511
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'root', 'singleton'>): ServiceRef<TService, 'root', 'singleton'>;
1512
+ /**
1513
+ * Creates a new service definition. This overload is used to create plugin scoped services.
1514
+ *
1515
+ * @public
1516
+ */
1517
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'plugin', 'multiton'>): ServiceRef<TService, 'plugin', 'multiton'>;
1518
+ /**
1519
+ * Creates a new service definition. This overload is used to create root scoped services.
1520
+ *
1521
+ * @public
1522
+ */
1523
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'root', 'multiton'>): ServiceRef<TService, 'root', 'multiton'>;
1501
1524
  /** @ignore */
1502
1525
  type ServiceRefsToInstances<T extends {
1503
1526
  [key in string]: ServiceRef<unknown>;
1504
1527
  }, TScope extends 'root' | 'plugin' = 'root' | 'plugin'> = {
1505
- [key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['T'];
1528
+ [key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['multiton'] extends true | undefined ? Array<T[key]['T']> : T[key]['T'];
1506
1529
  };
1507
1530
  /** @public */
1508
- interface RootServiceFactoryOptions<TService, TImpl extends TService, TDeps extends {
1531
+ interface RootServiceFactoryOptions<TService, // TODO(Rugvip): Can we forward the entire service ref type here instead of forwarding each type arg once the callback form is gone?
1532
+ TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1509
1533
  [name in string]: ServiceRef<unknown>;
1510
1534
  }> {
1511
1535
  /**
@@ -1519,12 +1543,12 @@ interface RootServiceFactoryOptions<TService, TImpl extends TService, TDeps exte
1519
1543
  * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.
1520
1544
  */
1521
1545
  initialization?: 'always' | 'lazy';
1522
- service: ServiceRef<TService, 'root'>;
1546
+ service: ServiceRef<TService, 'root', TInstances>;
1523
1547
  deps: TDeps;
1524
1548
  factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;
1525
1549
  }
1526
1550
  /** @public */
1527
- interface PluginServiceFactoryOptions<TService, TContext, TImpl extends TService, TDeps extends {
1551
+ interface PluginServiceFactoryOptions<TService, TInstances extends 'singleton' | 'multiton', TContext, TImpl extends TService, TDeps extends {
1528
1552
  [name in string]: ServiceRef<unknown>;
1529
1553
  }> {
1530
1554
  /**
@@ -1538,7 +1562,7 @@ interface PluginServiceFactoryOptions<TService, TContext, TImpl extends TService
1538
1562
  * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.
1539
1563
  */
1540
1564
  initialization?: 'always' | 'lazy';
1541
- service: ServiceRef<TService, 'plugin'>;
1565
+ service: ServiceRef<TService, 'plugin', TInstances>;
1542
1566
  deps: TDeps;
1543
1567
  createRootContext?(deps: ServiceRefsToInstances<TDeps, 'root'>): TContext | Promise<TContext>;
1544
1568
  factory(deps: ServiceRefsToInstances<TDeps>, context: TContext): TImpl | Promise<TImpl>;
@@ -1549,9 +1573,9 @@ interface PluginServiceFactoryOptions<TService, TContext, TImpl extends TService
1549
1573
  * @public
1550
1574
  * @param options - The service factory configuration.
1551
1575
  */
1552
- declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
1576
+ declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1553
1577
  [name in string]: ServiceRef<unknown, 'root'>;
1554
- }, TOpts extends object | undefined = undefined>(options: RootServiceFactoryOptions<TService, TImpl, TDeps>): ServiceFactoryCompat<TService, 'root'>;
1578
+ }, TOpts extends object | undefined = undefined>(options: RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>): ServiceFactoryCompat<TService, 'root', TInstances>;
1555
1579
  /**
1556
1580
  * Creates a root scoped service factory with optional options.
1557
1581
  *
@@ -1562,18 +1586,18 @@ declare function createServiceFactory<TService, TImpl extends TService, TDeps ex
1562
1586
  * @public
1563
1587
  * @param options - The service factory configuration.
1564
1588
  */
1565
- declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
1589
+ declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1566
1590
  [name in string]: ServiceRef<unknown, 'root'>;
1567
- }, TOpts extends object | undefined = undefined>(options: (options?: TOpts) => RootServiceFactoryOptions<TService, TImpl, TDeps>): ServiceFactoryCompat<TService, 'root', TOpts>;
1591
+ }, TOpts extends object | undefined = undefined>(options: (options?: TOpts) => RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>): ServiceFactoryCompat<TService, 'root', TInstances, TOpts>;
1568
1592
  /**
1569
1593
  * Creates a plugin scoped service factory without options.
1570
1594
  *
1571
1595
  * @public
1572
1596
  * @param options - The service factory configuration.
1573
1597
  */
1574
- declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
1598
+ declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1575
1599
  [name in string]: ServiceRef<unknown>;
1576
- }, TContext = undefined, TOpts extends object | undefined = undefined>(options: PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>): ServiceFactoryCompat<TService, 'plugin'>;
1600
+ }, TContext = undefined, TOpts extends object | undefined = undefined>(options: PluginServiceFactoryOptions<TService, TInstances, TContext, TImpl, TDeps>): ServiceFactoryCompat<TService, 'plugin', TInstances>;
1577
1601
  /**
1578
1602
  * Creates a plugin scoped service factory with optional options.
1579
1603
  *
@@ -1584,9 +1608,9 @@ declare function createServiceFactory<TService, TImpl extends TService, TDeps ex
1584
1608
  * @public
1585
1609
  * @param options - The service factory configuration.
1586
1610
  */
1587
- declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
1611
+ declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1588
1612
  [name in string]: ServiceRef<unknown>;
1589
- }, TContext = undefined, TOpts extends object | undefined = undefined>(options: (options?: TOpts) => PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>): ServiceFactoryCompat<TService, 'plugin', TOpts>;
1613
+ }, TContext = undefined, TOpts extends object | undefined = undefined>(options: (options?: TOpts) => PluginServiceFactoryOptions<TService, TInstances, TContext, TImpl, TDeps>): ServiceFactoryCompat<TService, 'plugin', TInstances, TOpts>;
1590
1614
 
1591
1615
  /**
1592
1616
  * All core services references
@@ -1603,7 +1627,7 @@ declare namespace coreServices {
1603
1627
  *
1604
1628
  * @public
1605
1629
  */
1606
- const auth: ServiceRef<AuthService, "plugin">;
1630
+ const auth: ServiceRef<AuthService, "plugin", "singleton">;
1607
1631
  /**
1608
1632
  * Authenticated user information retrieval.
1609
1633
  *
@@ -1613,7 +1637,7 @@ declare namespace coreServices {
1613
1637
  *
1614
1638
  * @public
1615
1639
  */
1616
- const userInfo: ServiceRef<UserInfoService, "plugin">;
1640
+ const userInfo: ServiceRef<UserInfoService, "plugin", "singleton">;
1617
1641
  /**
1618
1642
  * Key-value store for caching data.
1619
1643
  *
@@ -1623,7 +1647,7 @@ declare namespace coreServices {
1623
1647
  *
1624
1648
  * @public
1625
1649
  */
1626
- const cache: ServiceRef<CacheService, "plugin">;
1650
+ const cache: ServiceRef<CacheService, "plugin", "singleton">;
1627
1651
  /**
1628
1652
  * Access to static configuration.
1629
1653
  *
@@ -1633,7 +1657,7 @@ declare namespace coreServices {
1633
1657
  *
1634
1658
  * @public
1635
1659
  */
1636
- const rootConfig: ServiceRef<RootConfigService, "root">;
1660
+ const rootConfig: ServiceRef<RootConfigService, "root", "singleton">;
1637
1661
  /**
1638
1662
  * Database access and management via `knex`.
1639
1663
  *
@@ -1643,7 +1667,7 @@ declare namespace coreServices {
1643
1667
  *
1644
1668
  * @public
1645
1669
  */
1646
- const database: ServiceRef<DatabaseService, "plugin">;
1670
+ const database: ServiceRef<DatabaseService, "plugin", "singleton">;
1647
1671
  /**
1648
1672
  * Service discovery for inter-plugin communication.
1649
1673
  *
@@ -1653,11 +1677,11 @@ declare namespace coreServices {
1653
1677
  *
1654
1678
  * @public
1655
1679
  */
1656
- const discovery: ServiceRef<DiscoveryService, "plugin">;
1680
+ const discovery: ServiceRef<DiscoveryService, "plugin", "singleton">;
1657
1681
  /**
1658
1682
  * The service reference for the plugin scoped {@link RootHealthService}.
1659
1683
  */
1660
- const rootHealth: ServiceRef<RootHealthService, "root">;
1684
+ const rootHealth: ServiceRef<RootHealthService, "root", "singleton">;
1661
1685
  /**
1662
1686
  * Authentication of HTTP requests.
1663
1687
  *
@@ -1667,7 +1691,7 @@ declare namespace coreServices {
1667
1691
  *
1668
1692
  * @public
1669
1693
  */
1670
- const httpAuth: ServiceRef<HttpAuthService, "plugin">;
1694
+ const httpAuth: ServiceRef<HttpAuthService, "plugin", "singleton">;
1671
1695
  /**
1672
1696
  * HTTP route registration for plugins.
1673
1697
  *
@@ -1677,7 +1701,7 @@ declare namespace coreServices {
1677
1701
  *
1678
1702
  * @public
1679
1703
  */
1680
- const httpRouter: ServiceRef<HttpRouterService, "plugin">;
1704
+ const httpRouter: ServiceRef<HttpRouterService, "plugin", "singleton">;
1681
1705
  /**
1682
1706
  * Registration of plugin startup and shutdown lifecycle hooks.
1683
1707
  *
@@ -1687,7 +1711,7 @@ declare namespace coreServices {
1687
1711
  *
1688
1712
  * @public
1689
1713
  */
1690
- const lifecycle: ServiceRef<LifecycleService, "plugin">;
1714
+ const lifecycle: ServiceRef<LifecycleService, "plugin", "singleton">;
1691
1715
  /**
1692
1716
  * Plugin-level logging.
1693
1717
  *
@@ -1697,7 +1721,7 @@ declare namespace coreServices {
1697
1721
  *
1698
1722
  * @public
1699
1723
  */
1700
- const logger: ServiceRef<LoggerService, "plugin">;
1724
+ const logger: ServiceRef<LoggerService, "plugin", "singleton">;
1701
1725
  /**
1702
1726
  * Permission system integration for authorization of user actions.
1703
1727
  *
@@ -1707,7 +1731,7 @@ declare namespace coreServices {
1707
1731
  *
1708
1732
  * @public
1709
1733
  */
1710
- const permissions: ServiceRef<PermissionsService, "plugin">;
1734
+ const permissions: ServiceRef<PermissionsService, "plugin", "singleton">;
1711
1735
  /**
1712
1736
  * Built-in service for accessing metadata about the current plugin.
1713
1737
  *
@@ -1717,7 +1741,7 @@ declare namespace coreServices {
1717
1741
  *
1718
1742
  * @public
1719
1743
  */
1720
- const pluginMetadata: ServiceRef<PluginMetadataService, "plugin">;
1744
+ const pluginMetadata: ServiceRef<PluginMetadataService, "plugin", "singleton">;
1721
1745
  /**
1722
1746
  * HTTP route registration for root services.
1723
1747
  *
@@ -1727,7 +1751,7 @@ declare namespace coreServices {
1727
1751
  *
1728
1752
  * @public
1729
1753
  */
1730
- const rootHttpRouter: ServiceRef<RootHttpRouterService, "root">;
1754
+ const rootHttpRouter: ServiceRef<RootHttpRouterService, "root", "singleton">;
1731
1755
  /**
1732
1756
  * Registration of backend startup and shutdown lifecycle hooks.
1733
1757
  *
@@ -1737,7 +1761,7 @@ declare namespace coreServices {
1737
1761
  *
1738
1762
  * @public
1739
1763
  */
1740
- const rootLifecycle: ServiceRef<RootLifecycleService, "root">;
1764
+ const rootLifecycle: ServiceRef<RootLifecycleService, "root", "singleton">;
1741
1765
  /**
1742
1766
  * Root-level logging.
1743
1767
  *
@@ -1747,7 +1771,7 @@ declare namespace coreServices {
1747
1771
  *
1748
1772
  * @public
1749
1773
  */
1750
- const rootLogger: ServiceRef<RootLoggerService, "root">;
1774
+ const rootLogger: ServiceRef<RootLoggerService, "root", "singleton">;
1751
1775
  /**
1752
1776
  * Scheduling of distributed background tasks.
1753
1777
  *
@@ -1757,7 +1781,7 @@ declare namespace coreServices {
1757
1781
  *
1758
1782
  * @public
1759
1783
  */
1760
- const scheduler: ServiceRef<SchedulerService, "plugin">;
1784
+ const scheduler: ServiceRef<SchedulerService, "plugin", "singleton">;
1761
1785
  /**
1762
1786
  * Deprecated service authentication service, use the `auth` service instead.
1763
1787
  *
@@ -1768,7 +1792,7 @@ declare namespace coreServices {
1768
1792
  * @public
1769
1793
  * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
1770
1794
  */
1771
- const tokenManager: ServiceRef<TokenManagerService, "plugin">;
1795
+ const tokenManager: ServiceRef<TokenManagerService, "plugin", "singleton">;
1772
1796
  /**
1773
1797
  * Reading content from external systems.
1774
1798
  *
@@ -1778,7 +1802,7 @@ declare namespace coreServices {
1778
1802
  *
1779
1803
  * @public
1780
1804
  */
1781
- const urlReader: ServiceRef<UrlReaderService, "plugin">;
1805
+ const urlReader: ServiceRef<UrlReaderService, "plugin", "singleton">;
1782
1806
  /**
1783
1807
  * Deprecated user authentication service, use the `auth` service instead.
1784
1808
  *
@@ -1789,7 +1813,7 @@ declare namespace coreServices {
1789
1813
  * @public
1790
1814
  * @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
1791
1815
  */
1792
- const identity: ServiceRef<IdentityService, "plugin">;
1816
+ const identity: ServiceRef<IdentityService, "plugin", "singleton">;
1793
1817
  }
1794
1818
 
1795
1819
  /**
@@ -1840,6 +1864,12 @@ type ExtensionPoint<T> = {
1840
1864
  toString(): string;
1841
1865
  $$type: '@backstage/ExtensionPoint';
1842
1866
  };
1867
+ /** @ignore */
1868
+ type DepsToInstances<TDeps extends {
1869
+ [key in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
1870
+ }> = {
1871
+ [key in keyof TDeps]: TDeps[key] extends ServiceRef<unknown, any, 'multiton'> ? Array<TDeps[key]['T']> : TDeps[key]['T'];
1872
+ };
1843
1873
  /**
1844
1874
  * The callbacks passed to the `register` method of a backend plugin.
1845
1875
  *
@@ -1847,13 +1877,11 @@ type ExtensionPoint<T> = {
1847
1877
  */
1848
1878
  interface BackendPluginRegistrationPoints {
1849
1879
  registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
1850
- registerInit<Deps extends {
1851
- [name in string]: unknown;
1880
+ registerInit<TDeps extends {
1881
+ [name in string]: ServiceRef<unknown>;
1852
1882
  }>(options: {
1853
- deps: {
1854
- [name in keyof Deps]: ServiceRef<Deps[name]>;
1855
- };
1856
- init(deps: Deps): Promise<void>;
1883
+ deps: TDeps;
1884
+ init(deps: DepsToInstances<TDeps>): Promise<void>;
1857
1885
  }): void;
1858
1886
  }
1859
1887
  /**
@@ -1863,38 +1891,43 @@ interface BackendPluginRegistrationPoints {
1863
1891
  */
1864
1892
  interface BackendModuleRegistrationPoints {
1865
1893
  registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
1866
- registerInit<Deps extends {
1867
- [name in string]: unknown;
1894
+ registerInit<TDeps extends {
1895
+ [name in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
1868
1896
  }>(options: {
1869
- deps: {
1870
- [name in keyof Deps]: ServiceRef<Deps[name]> | ExtensionPoint<Deps[name]>;
1871
- };
1872
- init(deps: Deps): Promise<void>;
1897
+ deps: TDeps;
1898
+ init(deps: DepsToInstances<TDeps>): Promise<void>;
1873
1899
  }): void;
1874
1900
  }
1875
1901
 
1876
1902
  /**
1877
- * The configuration options passed to {@link createExtensionPoint}.
1903
+ * The configuration options passed to {@link createBackendModule}.
1878
1904
  *
1879
1905
  * @public
1880
- * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}
1906
+ * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}
1881
1907
  * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
1882
1908
  */
1883
- interface CreateExtensionPointOptions {
1909
+ interface CreateBackendModuleOptions {
1884
1910
  /**
1885
- * The ID of this extension point.
1911
+ * Should exactly match the `id` of the plugin that the module extends.
1886
1912
  *
1887
1913
  * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
1888
1914
  */
1889
- id: string;
1915
+ pluginId: string;
1916
+ /**
1917
+ * The ID of this module, used to identify the module and ensure that it is not installed twice.
1918
+ */
1919
+ moduleId: string;
1920
+ register(reg: BackendModuleRegistrationPoints): void;
1890
1921
  }
1891
1922
  /**
1892
- * Creates a new backend extension point.
1923
+ * Creates a new backend module for a given plugin.
1893
1924
  *
1894
1925
  * @public
1895
- * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}
1926
+ * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}
1927
+ * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
1896
1928
  */
1897
- declare function createExtensionPoint<T>(options: CreateExtensionPointOptions): ExtensionPoint<T>;
1929
+ declare function createBackendModule(options: CreateBackendModuleOptions): BackendFeatureCompat;
1930
+
1898
1931
  /**
1899
1932
  * The configuration options passed to {@link createBackendPlugin}.
1900
1933
  *
@@ -1919,34 +1952,55 @@ interface CreateBackendPluginOptions {
1919
1952
  * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
1920
1953
  */
1921
1954
  declare function createBackendPlugin(options: CreateBackendPluginOptions): BackendFeatureCompat;
1955
+
1922
1956
  /**
1923
- * The configuration options passed to {@link createBackendModule}.
1957
+ * The configuration options passed to {@link createExtensionPoint}.
1924
1958
  *
1925
1959
  * @public
1926
- * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}
1960
+ * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}
1927
1961
  * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
1928
1962
  */
1929
- interface CreateBackendModuleOptions {
1963
+ interface CreateExtensionPointOptions {
1930
1964
  /**
1931
- * Should exactly match the `id` of the plugin that the module extends.
1965
+ * The ID of this extension point.
1932
1966
  *
1933
1967
  * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
1934
1968
  */
1935
- pluginId: string;
1936
- /**
1937
- * The ID of this module, used to identify the module and ensure that it is not installed twice.
1938
- */
1939
- moduleId: string;
1940
- register(reg: BackendModuleRegistrationPoints): void;
1969
+ id: string;
1941
1970
  }
1942
1971
  /**
1943
- * Creates a new backend module for a given plugin.
1972
+ * Creates a new backend extension point.
1944
1973
  *
1945
1974
  * @public
1946
- * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}
1947
- * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}
1975
+ * @see {@link https://backstage.io/docs/backend-system/architecture/extension-points | The architecture of extension points}
1948
1976
  */
1949
- declare function createBackendModule(options: CreateBackendModuleOptions): BackendFeatureCompat;
1977
+ declare function createExtensionPoint<T>(options: CreateExtensionPointOptions): ExtensionPoint<T>;
1978
+
1979
+ /**
1980
+ * @public
1981
+ * Options for creating a new backend feature loader.
1982
+ */
1983
+ interface CreateBackendFeatureLoaderOptions<TDeps extends {
1984
+ [name in string]: unknown;
1985
+ }> {
1986
+ deps?: {
1987
+ [name in keyof TDeps]: ServiceRef<TDeps[name], 'root'>;
1988
+ };
1989
+ loader(deps: TDeps): Iterable<BackendFeature | Promise<{
1990
+ default: BackendFeature;
1991
+ }>> | Promise<Iterable<BackendFeature | Promise<{
1992
+ default: BackendFeature;
1993
+ }>>> | AsyncIterable<BackendFeature | {
1994
+ default: BackendFeature;
1995
+ }>;
1996
+ }
1997
+ /**
1998
+ * @public
1999
+ * Creates a new backend feature loader.
2000
+ */
2001
+ declare function createBackendFeatureLoader<TDeps extends {
2002
+ [name in string]: unknown;
2003
+ }>(options: CreateBackendFeatureLoaderOptions<TDeps>): BackendFeature;
1950
2004
 
1951
2005
  /**
1952
2006
  * @public
@@ -1968,20 +2022,20 @@ type ExtensionPointConfig = CreateExtensionPointOptions;
1968
2022
  * @public
1969
2023
  * @deprecated Use {@link ServiceRefOptions} instead
1970
2024
  */
1971
- type ServiceRefConfig<TService, TScope extends 'root' | 'plugin'> = ServiceRefOptions<TService, TScope>;
2025
+ type ServiceRefConfig<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton'> = ServiceRefOptions<TService, TScope, TInstances>;
1972
2026
  /**
1973
2027
  * @public
1974
2028
  * @deprecated Use {@link RootServiceFactoryOptions} instead
1975
2029
  */
1976
- type RootServiceFactoryConfig<TService, TImpl extends TService, TDeps extends {
2030
+ type RootServiceFactoryConfig<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1977
2031
  [name in string]: ServiceRef<unknown>;
1978
- }> = RootServiceFactoryOptions<TService, TImpl, TDeps>;
2032
+ }> = RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>;
1979
2033
  /**
1980
2034
  * @public
1981
2035
  * @deprecated Use {@link PluginServiceFactoryOptions} instead
1982
2036
  */
1983
- type PluginServiceFactoryConfig<TService, TContext, TImpl extends TService, TDeps extends {
2037
+ type PluginServiceFactoryConfig<TService, TInstances extends 'singleton' | 'multiton', TContext, TImpl extends TService, TDeps extends {
1984
2038
  [name in string]: ServiceRef<unknown>;
1985
- }> = PluginServiceFactoryOptions<TService, TContext, TImpl, TDeps>;
2039
+ }> = PluginServiceFactoryOptions<TService, TInstances, TContext, TImpl, TDeps>;
1986
2040
 
1987
- export { type AuthService, type BackendFeature, type BackendFeatureCompat, type BackendModuleConfig, type BackendModuleRegistrationPoints, type BackendPluginConfig, type BackendPluginRegistrationPoints, type BackstageCredentials, type BackstageNonePrincipal, type BackstagePrincipalAccessRestrictions, type BackstagePrincipalTypes, type BackstageServicePrincipal, type BackstageUserInfo, type BackstageUserPrincipal, type CacheService, type CacheServiceOptions, type CacheServiceSetOptions, type CreateBackendModuleOptions, type CreateBackendPluginOptions, type CreateExtensionPointOptions, type DatabaseService, type DiscoveryService, type ExtensionPoint, type ExtensionPointConfig, type HttpAuthService, type HttpRouterService, type HttpRouterServiceAuthPolicy, type IdentityService, type LifecycleService, type LifecycleServiceShutdownHook, type LifecycleServiceShutdownOptions, type LifecycleServiceStartupHook, type LifecycleServiceStartupOptions, type LoggerService, type PermissionsService, type PermissionsServiceRequestOptions, type PluginMetadataService, type PluginServiceFactoryConfig, type PluginServiceFactoryOptions, type ReadTreeOptions, type ReadTreeResponse, type ReadTreeResponseDirOptions, type ReadTreeResponseFile, type ReadUrlOptions, type ReadUrlResponse, type RootConfigService, type RootHealthService, type RootHttpRouterService, type RootLifecycleService, type RootLoggerService, type RootServiceFactoryConfig, type RootServiceFactoryOptions, type SchedulerService, type SchedulerServiceTaskDescriptor, type SchedulerServiceTaskFunction, type SchedulerServiceTaskInvocationDefinition, type SchedulerServiceTaskRunner, type SchedulerServiceTaskScheduleDefinition, type SchedulerServiceTaskScheduleDefinitionConfig, type SearchOptions, type SearchResponse, type SearchResponseFile, type ServiceFactory, type ServiceFactoryCompat, type ServiceFactoryOrFunction, type ServiceRef, type ServiceRefConfig, type ServiceRefOptions, type TokenManagerService, type UrlReaderService, type UrlReaderServiceReadTreeOptions, type UrlReaderServiceReadTreeResponse, type UrlReaderServiceReadTreeResponseDirOptions, type UrlReaderServiceReadTreeResponseFile, type UrlReaderServiceReadUrlOptions, type UrlReaderServiceReadUrlResponse, type UrlReaderServiceSearchOptions, type UrlReaderServiceSearchResponse, type UrlReaderServiceSearchResponseFile, type UserInfoService, coreServices, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };
2041
+ export { type AuthService, type BackendFeature, type BackendFeatureCompat, type BackendModuleConfig, type BackendModuleRegistrationPoints, type BackendPluginConfig, type BackendPluginRegistrationPoints, type BackstageCredentials, type BackstageNonePrincipal, type BackstagePrincipalAccessRestrictions, type BackstagePrincipalTypes, type BackstageServicePrincipal, type BackstageUserInfo, type BackstageUserPrincipal, type CacheService, type CacheServiceOptions, type CacheServiceSetOptions, type CreateBackendFeatureLoaderOptions, type CreateBackendModuleOptions, type CreateBackendPluginOptions, type CreateExtensionPointOptions, type DatabaseService, type DiscoveryService, type ExtensionPoint, type ExtensionPointConfig, type HttpAuthService, type HttpRouterService, type HttpRouterServiceAuthPolicy, type IdentityService, type LifecycleService, type LifecycleServiceShutdownHook, type LifecycleServiceShutdownOptions, type LifecycleServiceStartupHook, type LifecycleServiceStartupOptions, type LoggerService, type PermissionsService, type PermissionsServiceRequestOptions, type PluginMetadataService, type PluginServiceFactoryConfig, type PluginServiceFactoryOptions, type ReadTreeOptions, type ReadTreeResponse, type ReadTreeResponseDirOptions, type ReadTreeResponseFile, type ReadUrlOptions, type ReadUrlResponse, type RootConfigService, type RootHealthService, type RootHttpRouterService, type RootLifecycleService, type RootLoggerService, type RootServiceFactoryConfig, type RootServiceFactoryOptions, type SchedulerService, type SchedulerServiceTaskDescriptor, type SchedulerServiceTaskFunction, type SchedulerServiceTaskInvocationDefinition, type SchedulerServiceTaskRunner, type SchedulerServiceTaskScheduleDefinition, type SchedulerServiceTaskScheduleDefinitionConfig, type SearchOptions, type SearchResponse, type SearchResponseFile, type ServiceFactory, type ServiceFactoryCompat, type ServiceFactoryOrFunction, type ServiceRef, type ServiceRefConfig, type ServiceRefOptions, type TokenManagerService, type UrlReaderService, type UrlReaderServiceReadTreeOptions, type UrlReaderServiceReadTreeResponse, type UrlReaderServiceReadTreeResponseDirOptions, type UrlReaderServiceReadTreeResponseFile, type UrlReaderServiceReadUrlOptions, type UrlReaderServiceReadUrlResponse, type UrlReaderServiceSearchOptions, type UrlReaderServiceSearchResponse, type UrlReaderServiceSearchResponseFile, type UserInfoService, coreServices, createBackendFeatureLoader, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-plugin-api",
3
- "version": "0.7.1-next.1",
3
+ "version": "0.8.0-next.3",
4
4
  "description": "Core API used by Backstage backend plugins",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -56,8 +56,8 @@
56
56
  "@backstage/cli-common": "^0.1.14",
57
57
  "@backstage/config": "^1.2.0",
58
58
  "@backstage/errors": "^1.2.4",
59
- "@backstage/plugin-auth-node": "^0.4.18-next.1",
60
- "@backstage/plugin-permission-common": "^0.8.1-next.0",
59
+ "@backstage/plugin-auth-node": "^0.5.0-next.3",
60
+ "@backstage/plugin-permission-common": "^0.8.1-next.1",
61
61
  "@backstage/types": "^1.1.1",
62
62
  "@types/express": "^4.17.6",
63
63
  "@types/luxon": "^3.0.0",
@@ -66,7 +66,7 @@
66
66
  "luxon": "^3.0.0"
67
67
  },
68
68
  "devDependencies": {
69
- "@backstage/backend-test-utils": "^0.4.5-next.1",
70
- "@backstage/cli": "^0.27.0-next.1"
69
+ "@backstage/backend-test-utils": "^0.4.5-next.3",
70
+ "@backstage/cli": "^0.27.0-next.4"
71
71
  }
72
72
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-plugin-api__testutils",
3
- "version": "0.7.1-next.1",
3
+ "version": "0.8.0-next.3",
4
4
  "main": "../dist/testUtils.cjs.js",
5
5
  "types": "../dist/testUtils.d.ts"
6
6
  }