@backstage/backend-plugin-api 0.6.18-next.1 → 0.6.19-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/alpha/package.json +1 -1
- package/dist/cjs/paths-D7KGMZeP.cjs.js +44 -0
- package/dist/cjs/paths-D7KGMZeP.cjs.js.map +1 -0
- package/dist/index.cjs.js +59 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +346 -6
- package/dist/testUtils.cjs.js +35 -0
- package/dist/testUtils.cjs.js.map +1 -0
- package/dist/testUtils.d.ts +30 -0
- package/package.json +16 -6
- package/testUtils/package.json +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @backstage/backend-plugin-api
|
|
2
2
|
|
|
3
|
+
## 0.6.19-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6551b3d: Moved the declaration of the `SchedulerService` here, along with prefixed versions of all of the types it depends on, from `@backstage/backend-tasks`
|
|
8
|
+
- 1779188: Start using the `isDatabaseConflictError` helper from the `@backstage/backend-plugin-api` package in order to avoid dependency with the soon to deprecate `@backstage/backend-common` package.
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- @backstage/plugin-auth-node@0.4.14-next.0
|
|
11
|
+
- @backstage/cli-common@0.1.13
|
|
12
|
+
- @backstage/config@1.2.0
|
|
13
|
+
- @backstage/errors@1.2.4
|
|
14
|
+
- @backstage/types@1.1.1
|
|
15
|
+
- @backstage/plugin-permission-common@0.7.13
|
|
16
|
+
|
|
17
|
+
## 0.6.18
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- d229dc4: Move path utilities from `backend-common` to the `backend-plugin-api` package.
|
|
22
|
+
- 1fedf0c: Removed explicit `toString()` method from `ServiceRef` type.
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @backstage/backend-tasks@0.5.23
|
|
25
|
+
- @backstage/plugin-auth-node@0.4.13
|
|
26
|
+
|
|
3
27
|
## 0.6.18-next.1
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/alpha/package.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var cliCommon = require('@backstage/cli-common');
|
|
4
|
+
var errors = require('@backstage/errors');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var fs = require('fs');
|
|
7
|
+
|
|
8
|
+
const packagePathMocks = /* @__PURE__ */ new Map();
|
|
9
|
+
function resolvePackagePath(name, ...paths) {
|
|
10
|
+
const mockedResolve = packagePathMocks.get(name);
|
|
11
|
+
if (mockedResolve) {
|
|
12
|
+
const resolved = mockedResolve(paths);
|
|
13
|
+
if (resolved) {
|
|
14
|
+
return resolved;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const req = typeof __non_webpack_require__ === "undefined" ? require : __non_webpack_require__;
|
|
18
|
+
return path.resolve(req.resolve(`${name}/package.json`), "..", ...paths);
|
|
19
|
+
}
|
|
20
|
+
function resolveSafeChildPath(base, path$1) {
|
|
21
|
+
const resolvedBasePath = resolveRealPath(base);
|
|
22
|
+
const targetPath = path.resolve(resolvedBasePath, path$1);
|
|
23
|
+
if (!cliCommon.isChildPath(resolvedBasePath, resolveRealPath(targetPath))) {
|
|
24
|
+
throw new errors.NotAllowedError(
|
|
25
|
+
"Relative path is not allowed to refer to a directory outside its parent"
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return path.resolve(base, path$1);
|
|
29
|
+
}
|
|
30
|
+
function resolveRealPath(path) {
|
|
31
|
+
try {
|
|
32
|
+
return fs.realpathSync(path);
|
|
33
|
+
} catch (ex) {
|
|
34
|
+
if (ex.code !== "ENOENT") {
|
|
35
|
+
throw ex;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return path;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.packagePathMocks = packagePathMocks;
|
|
42
|
+
exports.resolvePackagePath = resolvePackagePath;
|
|
43
|
+
exports.resolveSafeChildPath = resolveSafeChildPath;
|
|
44
|
+
//# sourceMappingURL=paths-D7KGMZeP.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths-D7KGMZeP.cjs.js","sources":["../../src/paths.ts"],"sourcesContent":["/*\n * Copyright 2020 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 { isChildPath } from '@backstage/cli-common';\nimport { NotAllowedError } from '@backstage/errors';\nimport { resolve as resolvePath } from 'path';\nimport { realpathSync as realPath } from 'fs';\n\n/** @internal */\nexport const packagePathMocks = new Map<\n string,\n (paths: string[]) => string | undefined\n>();\n\n/**\n * Resolve a path relative to the root of a package directory.\n * Additional path arguments are resolved relative to the package dir.\n *\n * This is particularly useful when you want to access assets shipped with\n * your backend plugin package. When doing so, do not forget to include the assets\n * in your published package by adding them to `files` in your `package.json`.\n *\n * @public\n */\nexport function resolvePackagePath(name: string, ...paths: string[]) {\n const mockedResolve = packagePathMocks.get(name);\n if (mockedResolve) {\n const resolved = mockedResolve(paths);\n if (resolved) {\n return resolved;\n }\n }\n\n const req =\n typeof __non_webpack_require__ === 'undefined'\n ? require\n : __non_webpack_require__;\n\n return resolvePath(req.resolve(`${name}/package.json`), '..', ...paths);\n}\n\n/**\n * Resolves a target path from a base path while guaranteeing that the result is\n * a path that point to or within the base path. This is useful for resolving\n * paths from user input, as it otherwise opens up for vulnerabilities.\n *\n * @public\n * @param base - The base directory to resolve the path from.\n * @param path - The target path, relative or absolute\n * @returns A path that is guaranteed to point to or within the base path.\n */\nexport function resolveSafeChildPath(base: string, path: string): string {\n const resolvedBasePath = resolveRealPath(base);\n const targetPath = resolvePath(resolvedBasePath, path);\n\n if (!isChildPath(resolvedBasePath, resolveRealPath(targetPath))) {\n throw new NotAllowedError(\n 'Relative path is not allowed to refer to a directory outside its parent',\n );\n }\n\n // Don't return the resolved path as the original could be a symlink\n return resolvePath(base, path);\n}\n\nfunction resolveRealPath(path: string): string {\n try {\n return realPath(path);\n } catch (ex) {\n if (ex.code !== 'ENOENT') {\n throw ex;\n }\n }\n\n return path;\n}\n// Re-export isChildPath so that backend packages don't need to depend on cli-common\nexport { isChildPath };\n"],"names":["resolvePath","path","isChildPath","NotAllowedError","realPath"],"mappings":";;;;;;;AAsBa,MAAA,gBAAA,uBAAuB,GAGlC,GAAA;AAYc,SAAA,kBAAA,CAAmB,SAAiB,KAAiB,EAAA;AACnE,EAAM,MAAA,aAAA,GAAgB,gBAAiB,CAAA,GAAA,CAAI,IAAI,CAAA,CAAA;AAC/C,EAAA,IAAI,aAAe,EAAA;AACjB,IAAM,MAAA,QAAA,GAAW,cAAc,KAAK,CAAA,CAAA;AACpC,IAAA,IAAI,QAAU,EAAA;AACZ,MAAO,OAAA,QAAA,CAAA;AAAA,KACT;AAAA,GACF;AAEA,EAAA,MAAM,GACJ,GAAA,OAAO,uBAA4B,KAAA,WAAA,GAC/B,OACA,GAAA,uBAAA,CAAA;AAEN,EAAO,OAAAA,YAAA,CAAY,IAAI,OAAQ,CAAA,CAAA,EAAG,IAAI,CAAe,aAAA,CAAA,CAAA,EAAG,IAAM,EAAA,GAAG,KAAK,CAAA,CAAA;AACxE,CAAA;AAYgB,SAAA,oBAAA,CAAqB,MAAcC,MAAsB,EAAA;AACvE,EAAM,MAAA,gBAAA,GAAmB,gBAAgB,IAAI,CAAA,CAAA;AAC7C,EAAM,MAAA,UAAA,GAAaD,YAAY,CAAA,gBAAA,EAAkBC,MAAI,CAAA,CAAA;AAErD,EAAA,IAAI,CAACC,qBAAY,CAAA,gBAAA,EAAkB,eAAgB,CAAA,UAAU,CAAC,CAAG,EAAA;AAC/D,IAAA,MAAM,IAAIC,sBAAA;AAAA,MACR,yEAAA;AAAA,KACF,CAAA;AAAA,GACF;AAGA,EAAO,OAAAH,YAAA,CAAY,MAAMC,MAAI,CAAA,CAAA;AAC/B,CAAA;AAEA,SAAS,gBAAgB,IAAsB,EAAA;AAC7C,EAAI,IAAA;AACF,IAAA,OAAOG,gBAAS,IAAI,CAAA,CAAA;AAAA,WACb,EAAI,EAAA;AACX,IAAI,IAAA,EAAA,CAAG,SAAS,QAAU,EAAA;AACxB,MAAM,MAAA,EAAA,CAAA;AAAA,KACR;AAAA,GACF;AAEA,EAAO,OAAA,IAAA,CAAA;AACT;;;;;;"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var config = require('@backstage/config');
|
|
4
|
+
var luxon = require('luxon');
|
|
5
|
+
var paths = require('./cjs/paths-D7KGMZeP.cjs.js');
|
|
6
|
+
var cliCommon = require('@backstage/cli-common');
|
|
7
|
+
require('@backstage/errors');
|
|
8
|
+
require('path');
|
|
9
|
+
require('fs');
|
|
10
|
+
|
|
3
11
|
function createServiceRef(config) {
|
|
4
12
|
const { id, scope = "plugin", defaultFactory } = config;
|
|
5
13
|
return {
|
|
@@ -37,10 +45,7 @@ function createServiceFactory(config) {
|
|
|
37
45
|
service: c.service,
|
|
38
46
|
initialization: c.initialization,
|
|
39
47
|
..."createRootContext" in c ? {
|
|
40
|
-
createRootContext: async (deps) =>
|
|
41
|
-
var _a;
|
|
42
|
-
return (_a = c == null ? void 0 : c.createRootContext) == null ? void 0 : _a.call(c, deps);
|
|
43
|
-
}
|
|
48
|
+
createRootContext: async (deps) => c?.createRootContext?.(deps)
|
|
44
49
|
} : {},
|
|
45
50
|
deps: c.deps,
|
|
46
51
|
factory: async (deps, ctx) => c.factory(deps, ctx)
|
|
@@ -79,6 +84,47 @@ exports.coreServices = void 0;
|
|
|
79
84
|
coreServices2.identity = createServiceRef({ id: "core.identity" });
|
|
80
85
|
})(exports.coreServices || (exports.coreServices = {}));
|
|
81
86
|
|
|
87
|
+
function readDuration(config$1, key) {
|
|
88
|
+
if (typeof config$1.get(key) === "string") {
|
|
89
|
+
const value = config$1.getString(key);
|
|
90
|
+
const duration = luxon.Duration.fromISO(value);
|
|
91
|
+
if (!duration.isValid) {
|
|
92
|
+
throw new Error(`Invalid duration: ${value}`);
|
|
93
|
+
}
|
|
94
|
+
return duration;
|
|
95
|
+
}
|
|
96
|
+
return config.readDurationFromConfig(config$1, { key });
|
|
97
|
+
}
|
|
98
|
+
function readCronOrDuration(config, key) {
|
|
99
|
+
const value = config.get(key);
|
|
100
|
+
if (typeof value === "object" && value.cron) {
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
return readDuration(config, key);
|
|
104
|
+
}
|
|
105
|
+
function readSchedulerServiceTaskScheduleDefinitionFromConfig(config) {
|
|
106
|
+
const frequency = readCronOrDuration(config, "frequency");
|
|
107
|
+
const timeout = readDuration(config, "timeout");
|
|
108
|
+
const initialDelay = config.has("initialDelay") ? readDuration(config, "initialDelay") : void 0;
|
|
109
|
+
const scope = config.getOptionalString("scope");
|
|
110
|
+
if (scope && !["global", "local"].includes(scope)) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Only "global" or "local" are allowed for TaskScheduleDefinition.scope, but got: ${scope}`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
frequency,
|
|
117
|
+
timeout,
|
|
118
|
+
initialDelay,
|
|
119
|
+
scope
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function isDatabaseConflictError(e) {
|
|
124
|
+
const message = e?.message;
|
|
125
|
+
return typeof message === "string" && (/SQLITE_CONSTRAINT(?:_UNIQUE)?: UNIQUE/.test(message) || /UNIQUE constraint failed:/.test(message) || /unique constraint/.test(message) || /Duplicate entry/.test(message));
|
|
126
|
+
}
|
|
127
|
+
|
|
82
128
|
function createExtensionPoint(config) {
|
|
83
129
|
return {
|
|
84
130
|
id: config.id,
|
|
@@ -195,9 +241,18 @@ function createBackendModule(config) {
|
|
|
195
241
|
return factory;
|
|
196
242
|
}
|
|
197
243
|
|
|
244
|
+
exports.packagePathMocks = paths.packagePathMocks;
|
|
245
|
+
exports.resolvePackagePath = paths.resolvePackagePath;
|
|
246
|
+
exports.resolveSafeChildPath = paths.resolveSafeChildPath;
|
|
247
|
+
Object.defineProperty(exports, "isChildPath", {
|
|
248
|
+
enumerable: true,
|
|
249
|
+
get: function () { return cliCommon.isChildPath; }
|
|
250
|
+
});
|
|
198
251
|
exports.createBackendModule = createBackendModule;
|
|
199
252
|
exports.createBackendPlugin = createBackendPlugin;
|
|
200
253
|
exports.createExtensionPoint = createExtensionPoint;
|
|
201
254
|
exports.createServiceFactory = createServiceFactory;
|
|
202
255
|
exports.createServiceRef = createServiceRef;
|
|
256
|
+
exports.isDatabaseConflictError = isDatabaseConflictError;
|
|
257
|
+
exports.readSchedulerServiceTaskScheduleDefinitionFromConfig = readSchedulerServiceTaskScheduleDefinitionFromConfig;
|
|
203
258
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/services/system/types.ts","../src/services/definitions/coreServices.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/** @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 * @public\n */\nexport type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory);\n\n/** @public */\nexport interface ServiceRefConfig<TService, TScope extends 'root' | 'plugin'> {\n id: string;\n scope?: TScope;\n defaultFactory?: (\n service: ServiceRef<TService, TScope>,\n ) => Promise<ServiceFactoryOrFunction>;\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 config: ServiceRefConfig<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 config: ServiceRefConfig<TService, 'root'>,\n): ServiceRef<TService, 'root'>;\nexport function createServiceRef<TService>(\n config: ServiceRefConfig<TService, any>,\n): ServiceRef<TService, any> {\n const { id, scope = 'plugin', defaultFactory } = config;\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{${config.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 RootServiceFactoryConfig<\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 PluginServiceFactoryConfig<\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 config - 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 config: RootServiceFactoryConfig<TService, TImpl, TDeps>,\n): () => ServiceFactory<TService, 'root'>;\n/**\n * Creates a root scoped service factory with optional options.\n *\n * @public\n * @param config - 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 config: (options?: TOpts) => RootServiceFactoryConfig<TService, TImpl, TDeps>,\n): (options?: TOpts) => ServiceFactory<TService, 'root'>;\n/**\n * Creates a plugin scoped service factory without options.\n *\n * @public\n * @param config - 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 config: PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>,\n): () => ServiceFactory<TService, 'plugin'>;\n/**\n * Creates a plugin scoped service factory with optional options.\n *\n * @public\n * @param config - 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 config: (\n options?: TOpts,\n ) => PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>,\n): (options?: TOpts) => ServiceFactory<TService, 'plugin'>;\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 config:\n | RootServiceFactoryConfig<TService, TImpl, TDeps>\n | PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>\n | ((options: TOpts) => RootServiceFactoryConfig<TService, TImpl, TDeps>)\n | ((\n options: TOpts,\n ) => PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>)\n | (() => RootServiceFactoryConfig<TService, TImpl, TDeps>)\n | (() => PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>),\n): (options: TOpts) => ServiceFactory {\n const configCallback = typeof config === 'function' ? config : () => config;\n const factory = (\n options: TOpts,\n ): InternalServiceFactory<TService, 'plugin' | 'root'> => {\n const anyConf = configCallback(options);\n if (anyConf.service.scope === 'root') {\n const c = anyConf as RootServiceFactoryConfig<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 PluginServiceFactoryConfig<\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 factory.$$type = '@backstage/BackendFeatureFactory';\n\n return factory;\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 * The service reference for the plugin scoped {@link AuthService}.\n *\n * @public\n */\n export const auth = createServiceRef<import('./AuthService').AuthService>({\n id: 'core.auth',\n });\n\n /**\n * The service reference for the plugin scoped {@link UserInfoService}.\n *\n * @public\n */\n export const userInfo = createServiceRef<\n import('./UserInfoService').UserInfoService\n >({\n id: 'core.userInfo',\n });\n\n /**\n * The service reference for the plugin scoped {@link CacheService}.\n *\n * @public\n */\n export const cache = createServiceRef<import('./CacheService').CacheService>({\n id: 'core.cache',\n });\n\n /**\n * The service reference for the root scoped {@link RootConfigService}.\n *\n * @public\n */\n export const rootConfig = createServiceRef<\n import('./RootConfigService').RootConfigService\n >({ id: 'core.rootConfig', scope: 'root' });\n\n /**\n * The service reference for the plugin scoped {@link DatabaseService}.\n *\n * @public\n */\n export const database = createServiceRef<\n import('./DatabaseService').DatabaseService\n >({ id: 'core.database' });\n\n /**\n * The service reference for the plugin scoped {@link DiscoveryService}.\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 HttpAuthService}.\n *\n * @public\n */\n export const httpAuth = createServiceRef<\n import('./HttpAuthService').HttpAuthService\n >({ id: 'core.httpAuth' });\n\n /**\n * The service reference for the plugin scoped {@link HttpRouterService}.\n *\n * @public\n */\n export const httpRouter = createServiceRef<\n import('./HttpRouterService').HttpRouterService\n >({ id: 'core.httpRouter' });\n\n /**\n * The service reference for the plugin scoped {@link LifecycleService}.\n *\n * @public\n */\n export const lifecycle = createServiceRef<\n import('./LifecycleService').LifecycleService\n >({ id: 'core.lifecycle' });\n\n /**\n * The service reference for the plugin scoped {@link LoggerService}.\n *\n * @public\n */\n export const logger = createServiceRef<\n import('./LoggerService').LoggerService\n >({ id: 'core.logger' });\n\n /**\n * The service reference for the plugin scoped {@link PermissionsService}.\n *\n * @public\n */\n export const permissions = createServiceRef<\n import('./PermissionsService').PermissionsService\n >({ id: 'core.permissions' });\n\n /**\n * The service reference for the plugin scoped {@link PluginMetadataService}.\n *\n * @public\n */\n export const pluginMetadata = createServiceRef<\n import('./PluginMetadataService').PluginMetadataService\n >({ id: 'core.pluginMetadata' });\n\n /**\n * The service reference for the root scoped {@link RootHttpRouterService}.\n *\n * @public\n */\n export const rootHttpRouter = createServiceRef<\n import('./RootHttpRouterService').RootHttpRouterService\n >({ id: 'core.rootHttpRouter', scope: 'root' });\n\n /**\n * The service reference for the root scoped {@link RootLifecycleService}.\n *\n * @public\n */\n export const rootLifecycle = createServiceRef<\n import('./RootLifecycleService').RootLifecycleService\n >({ id: 'core.rootLifecycle', scope: 'root' });\n\n /**\n * The service reference for the root scoped {@link RootLoggerService}.\n *\n * @public\n */\n export const rootLogger = createServiceRef<\n import('./RootLoggerService').RootLoggerService\n >({ id: 'core.rootLogger', scope: 'root' });\n\n /**\n * The service reference for the plugin scoped {@link SchedulerService}.\n *\n * @public\n */\n export const scheduler = createServiceRef<\n import('./SchedulerService').SchedulerService\n >({ id: 'core.scheduler' });\n\n /**\n * The service reference for the plugin scoped {@link TokenManagerService}.\n *\n * @public\n */\n export const tokenManager = createServiceRef<\n import('./TokenManagerService').TokenManagerService\n >({ id: 'core.tokenManager' });\n\n /**\n * The service reference for the plugin scoped {@link UrlReaderService}.\n *\n * @public\n */\n export const urlReader = createServiceRef<\n import('./UrlReaderService').UrlReaderService\n >({ id: 'core.urlReader' });\n\n /**\n * The service reference for the plugin scoped {@link IdentityService}.\n *\n * @public\n */\n export const identity = createServiceRef<\n import('./IdentityService').IdentityService\n >({ id: 'core.identity' });\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 { BackendFeature, BackendFeatureFactory } 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 ExtensionPointConfig {\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 config: ExtensionPointConfig,\n): ExtensionPoint<T> {\n return {\n id: config.id,\n get T(): T {\n throw new Error(`tried to read ExtensionPoint.T of ${this}`);\n },\n toString() {\n return `extensionPoint{${config.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 BackendPluginConfig {\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 config: BackendPluginConfig,\n): () => BackendFeature {\n const factory: BackendFeatureFactory = () => {\n let registrations: InternalBackendPluginRegistration[];\n\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n getRegistrations() {\n if (registrations) {\n return registrations;\n }\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendPluginRegistration['init'] | undefined =\n undefined;\n\n config.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error(\n 'registerExtensionPoint called after registerInit',\n );\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 ${config.pluginId}`,\n );\n }\n\n registrations = [\n {\n type: 'plugin',\n pluginId: config.pluginId,\n extensionPoints,\n init,\n },\n ];\n return registrations;\n },\n };\n };\n factory.$$type = '@backstage/BackendFeatureFactory';\n\n return factory;\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 BackendModuleConfig {\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 config: BackendModuleConfig,\n): () => BackendFeature {\n const factory: BackendFeatureFactory = () => {\n let registrations: InternalBackendModuleRegistration[];\n\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n getRegistrations() {\n if (registrations) {\n return registrations;\n }\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendModuleRegistration['init'] | undefined =\n undefined;\n\n config.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error(\n 'registerExtensionPoint called after registerInit',\n );\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 ${config.moduleId} module for ${config.pluginId}`,\n );\n }\n\n registrations = [\n {\n type: 'module',\n pluginId: config.pluginId,\n moduleId: config.moduleId,\n extensionPoints,\n init,\n },\n ];\n return registrations;\n },\n };\n };\n factory.$$type = '@backstage/BackendFeatureFactory';\n\n return factory;\n}\n"],"names":["c","coreServices"],"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/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/** @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 * @public\n */\nexport type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory);\n\n/** @public */\nexport interface ServiceRefConfig<TService, TScope extends 'root' | 'plugin'> {\n id: string;\n scope?: TScope;\n defaultFactory?: (\n service: ServiceRef<TService, TScope>,\n ) => Promise<ServiceFactoryOrFunction>;\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 config: ServiceRefConfig<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 config: ServiceRefConfig<TService, 'root'>,\n): ServiceRef<TService, 'root'>;\nexport function createServiceRef<TService>(\n config: ServiceRefConfig<TService, any>,\n): ServiceRef<TService, any> {\n const { id, scope = 'plugin', defaultFactory } = config;\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{${config.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 RootServiceFactoryConfig<\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 PluginServiceFactoryConfig<\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 config - 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 config: RootServiceFactoryConfig<TService, TImpl, TDeps>,\n): () => ServiceFactory<TService, 'root'>;\n/**\n * Creates a root scoped service factory with optional options.\n *\n * @public\n * @param config - 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 config: (options?: TOpts) => RootServiceFactoryConfig<TService, TImpl, TDeps>,\n): (options?: TOpts) => ServiceFactory<TService, 'root'>;\n/**\n * Creates a plugin scoped service factory without options.\n *\n * @public\n * @param config - 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 config: PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>,\n): () => ServiceFactory<TService, 'plugin'>;\n/**\n * Creates a plugin scoped service factory with optional options.\n *\n * @public\n * @param config - 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 config: (\n options?: TOpts,\n ) => PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>,\n): (options?: TOpts) => ServiceFactory<TService, 'plugin'>;\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 config:\n | RootServiceFactoryConfig<TService, TImpl, TDeps>\n | PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>\n | ((options: TOpts) => RootServiceFactoryConfig<TService, TImpl, TDeps>)\n | ((\n options: TOpts,\n ) => PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>)\n | (() => RootServiceFactoryConfig<TService, TImpl, TDeps>)\n | (() => PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>),\n): (options: TOpts) => ServiceFactory {\n const configCallback = typeof config === 'function' ? config : () => config;\n const factory = (\n options: TOpts,\n ): InternalServiceFactory<TService, 'plugin' | 'root'> => {\n const anyConf = configCallback(options);\n if (anyConf.service.scope === 'root') {\n const c = anyConf as RootServiceFactoryConfig<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 PluginServiceFactoryConfig<\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 factory.$$type = '@backstage/BackendFeatureFactory';\n\n return factory;\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 * The service reference for the plugin scoped {@link AuthService}.\n *\n * @public\n */\n export const auth = createServiceRef<import('./AuthService').AuthService>({\n id: 'core.auth',\n });\n\n /**\n * The service reference for the plugin scoped {@link UserInfoService}.\n *\n * @public\n */\n export const userInfo = createServiceRef<\n import('./UserInfoService').UserInfoService\n >({\n id: 'core.userInfo',\n });\n\n /**\n * The service reference for the plugin scoped {@link CacheService}.\n *\n * @public\n */\n export const cache = createServiceRef<import('./CacheService').CacheService>({\n id: 'core.cache',\n });\n\n /**\n * The service reference for the root scoped {@link RootConfigService}.\n *\n * @public\n */\n export const rootConfig = createServiceRef<\n import('./RootConfigService').RootConfigService\n >({ id: 'core.rootConfig', scope: 'root' });\n\n /**\n * The service reference for the plugin scoped {@link DatabaseService}.\n *\n * @public\n */\n export const database = createServiceRef<\n import('./DatabaseService').DatabaseService\n >({ id: 'core.database' });\n\n /**\n * The service reference for the plugin scoped {@link DiscoveryService}.\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 HttpAuthService}.\n *\n * @public\n */\n export const httpAuth = createServiceRef<\n import('./HttpAuthService').HttpAuthService\n >({ id: 'core.httpAuth' });\n\n /**\n * The service reference for the plugin scoped {@link HttpRouterService}.\n *\n * @public\n */\n export const httpRouter = createServiceRef<\n import('./HttpRouterService').HttpRouterService\n >({ id: 'core.httpRouter' });\n\n /**\n * The service reference for the plugin scoped {@link LifecycleService}.\n *\n * @public\n */\n export const lifecycle = createServiceRef<\n import('./LifecycleService').LifecycleService\n >({ id: 'core.lifecycle' });\n\n /**\n * The service reference for the plugin scoped {@link LoggerService}.\n *\n * @public\n */\n export const logger = createServiceRef<\n import('./LoggerService').LoggerService\n >({ id: 'core.logger' });\n\n /**\n * The service reference for the plugin scoped {@link PermissionsService}.\n *\n * @public\n */\n export const permissions = createServiceRef<\n import('./PermissionsService').PermissionsService\n >({ id: 'core.permissions' });\n\n /**\n * The service reference for the plugin scoped {@link PluginMetadataService}.\n *\n * @public\n */\n export const pluginMetadata = createServiceRef<\n import('./PluginMetadataService').PluginMetadataService\n >({ id: 'core.pluginMetadata' });\n\n /**\n * The service reference for the root scoped {@link RootHttpRouterService}.\n *\n * @public\n */\n export const rootHttpRouter = createServiceRef<\n import('./RootHttpRouterService').RootHttpRouterService\n >({ id: 'core.rootHttpRouter', scope: 'root' });\n\n /**\n * The service reference for the root scoped {@link RootLifecycleService}.\n *\n * @public\n */\n export const rootLifecycle = createServiceRef<\n import('./RootLifecycleService').RootLifecycleService\n >({ id: 'core.rootLifecycle', scope: 'root' });\n\n /**\n * The service reference for the root scoped {@link RootLoggerService}.\n *\n * @public\n */\n export const rootLogger = createServiceRef<\n import('./RootLoggerService').RootLoggerService\n >({ id: 'core.rootLogger', scope: 'root' });\n\n /**\n * The service reference for the plugin scoped {@link SchedulerService}.\n *\n * @public\n */\n export const scheduler = createServiceRef<\n import('./SchedulerService').SchedulerService\n >({ id: 'core.scheduler' });\n\n /**\n * The service reference for the plugin scoped {@link TokenManagerService}.\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 * The service reference for the plugin scoped {@link UrlReaderService}.\n *\n * @public\n */\n export const urlReader = createServiceRef<\n import('./UrlReaderService').UrlReaderService\n >({ id: 'core.urlReader' });\n\n /**\n * The service reference for the plugin scoped {@link IdentityService}.\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 * @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): Duration | 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;\n }\n\n return readDurationFromConfig(config, { key });\n}\n\nfunction readCronOrDuration(\n config: Config,\n key: string,\n): { cron: string } | Duration | 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 { BackendFeature, BackendFeatureFactory } 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 ExtensionPointConfig {\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 config: ExtensionPointConfig,\n): ExtensionPoint<T> {\n return {\n id: config.id,\n get T(): T {\n throw new Error(`tried to read ExtensionPoint.T of ${this}`);\n },\n toString() {\n return `extensionPoint{${config.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 BackendPluginConfig {\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 config: BackendPluginConfig,\n): () => BackendFeature {\n const factory: BackendFeatureFactory = () => {\n let registrations: InternalBackendPluginRegistration[];\n\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n getRegistrations() {\n if (registrations) {\n return registrations;\n }\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendPluginRegistration['init'] | undefined =\n undefined;\n\n config.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error(\n 'registerExtensionPoint called after registerInit',\n );\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 ${config.pluginId}`,\n );\n }\n\n registrations = [\n {\n type: 'plugin',\n pluginId: config.pluginId,\n extensionPoints,\n init,\n },\n ];\n return registrations;\n },\n };\n };\n factory.$$type = '@backstage/BackendFeatureFactory';\n\n return factory;\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 BackendModuleConfig {\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 config: BackendModuleConfig,\n): () => BackendFeature {\n const factory: BackendFeatureFactory = () => {\n let registrations: InternalBackendModuleRegistration[];\n\n return {\n $$type: '@backstage/BackendFeature',\n version: 'v1',\n getRegistrations() {\n if (registrations) {\n return registrations;\n }\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendModuleRegistration['init'] | undefined =\n undefined;\n\n config.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error(\n 'registerExtensionPoint called after registerInit',\n );\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 ${config.moduleId} module for ${config.pluginId}`,\n );\n }\n\n registrations = [\n {\n type: 'module',\n pluginId: config.pluginId,\n moduleId: config.moduleId,\n extensionPoints,\n init,\n },\n ];\n return registrations;\n },\n };\n };\n factory.$$type = '@backstage/BackendFeatureFactory';\n\n return factory;\n}\n"],"names":["c","coreServices","config","Duration","readDurationFromConfig"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { IdentityApi } from '@backstage/plugin-auth-node';
|
|
3
3
|
import { Readable } from 'stream';
|
|
4
|
-
import {
|
|
5
|
-
import { JsonObject, JsonValue } from '@backstage/types';
|
|
4
|
+
import { Config } from '@backstage/config';
|
|
5
|
+
import { JsonObject, HumanDuration, JsonValue } from '@backstage/types';
|
|
6
|
+
import { Duration } from 'luxon';
|
|
6
7
|
import { Handler, Request, Response } from 'express';
|
|
7
8
|
import { PermissionEvaluator, AuthorizePermissionRequest, AuthorizePermissionResponse, QueryPermissionRequest, QueryPermissionResponse } from '@backstage/plugin-permission-common';
|
|
8
9
|
import { Knex } from 'knex';
|
|
9
|
-
|
|
10
|
+
export { isChildPath } from '@backstage/cli-common';
|
|
10
11
|
|
|
11
12
|
/** @public */
|
|
12
13
|
interface IdentityService extends IdentityApi {
|
|
@@ -351,9 +352,313 @@ interface TokenManagerService {
|
|
|
351
352
|
authenticate(token: string): Promise<void>;
|
|
352
353
|
}
|
|
353
354
|
|
|
354
|
-
/**
|
|
355
|
-
|
|
355
|
+
/**
|
|
356
|
+
* A function that can be called as a scheduled task.
|
|
357
|
+
*
|
|
358
|
+
* It may optionally accept an abort signal argument. When the signal triggers,
|
|
359
|
+
* processing should abort and return as quickly as possible.
|
|
360
|
+
*
|
|
361
|
+
* @public
|
|
362
|
+
*/
|
|
363
|
+
type SchedulerServiceTaskFunction = ((abortSignal: AbortSignal) => void | Promise<void>) | (() => void | Promise<void>);
|
|
364
|
+
/**
|
|
365
|
+
* A semi-opaque type to describe an actively scheduled task.
|
|
366
|
+
*
|
|
367
|
+
* @public
|
|
368
|
+
*/
|
|
369
|
+
type SchedulerServiceTaskDescriptor = {
|
|
370
|
+
/**
|
|
371
|
+
* The unique identifier of the task.
|
|
372
|
+
*/
|
|
373
|
+
id: string;
|
|
374
|
+
/**
|
|
375
|
+
* The scope of the task.
|
|
376
|
+
*/
|
|
377
|
+
scope: 'global' | 'local';
|
|
378
|
+
/**
|
|
379
|
+
* The settings that control the task flow. This is a semi-opaque structure
|
|
380
|
+
* that is mainly there for debugging purposes. Do not make any assumptions
|
|
381
|
+
* about the contents of this field.
|
|
382
|
+
*/
|
|
383
|
+
settings: {
|
|
384
|
+
version: number;
|
|
385
|
+
} & JsonObject;
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* Options that control the scheduling of a task.
|
|
389
|
+
*
|
|
390
|
+
* @public
|
|
391
|
+
*/
|
|
392
|
+
interface SchedulerServiceTaskScheduleDefinition {
|
|
393
|
+
/**
|
|
394
|
+
* How often you want the task to run. The system does its best to avoid
|
|
395
|
+
* overlapping invocations.
|
|
396
|
+
*
|
|
397
|
+
* @remarks
|
|
398
|
+
*
|
|
399
|
+
* This is the best effort value; under some circumstances there can be
|
|
400
|
+
* deviations. For example, if the task runtime is longer than the frequency
|
|
401
|
+
* and the timeout has not been given or not been exceeded yet, the next
|
|
402
|
+
* invocation of this task will be delayed until after the previous one
|
|
403
|
+
* finishes.
|
|
404
|
+
*
|
|
405
|
+
* This is a required field.
|
|
406
|
+
*/
|
|
407
|
+
frequency: {
|
|
408
|
+
/**
|
|
409
|
+
* A crontab style string.
|
|
410
|
+
*
|
|
411
|
+
* @remarks
|
|
412
|
+
*
|
|
413
|
+
* Overview:
|
|
414
|
+
*
|
|
415
|
+
* ```
|
|
416
|
+
* ┌────────────── second (optional)
|
|
417
|
+
* │ ┌──────────── minute
|
|
418
|
+
* │ │ ┌────────── hour
|
|
419
|
+
* │ │ │ ┌──────── day of month
|
|
420
|
+
* │ │ │ │ ┌────── month
|
|
421
|
+
* │ │ │ │ │ ┌──── day of week
|
|
422
|
+
* │ │ │ │ │ │
|
|
423
|
+
* │ │ │ │ │ │
|
|
424
|
+
* * * * * * *
|
|
425
|
+
* ```
|
|
426
|
+
*/
|
|
427
|
+
cron: string;
|
|
428
|
+
} | Duration | HumanDuration;
|
|
429
|
+
/**
|
|
430
|
+
* The maximum amount of time that a single task invocation can take, before
|
|
431
|
+
* it's considered timed out and gets "released" such that a new invocation
|
|
432
|
+
* is permitted to take place (possibly, then, on a different worker).
|
|
433
|
+
*/
|
|
434
|
+
timeout: Duration | HumanDuration;
|
|
435
|
+
/**
|
|
436
|
+
* The amount of time that should pass before the first invocation happens.
|
|
437
|
+
*
|
|
438
|
+
* @remarks
|
|
439
|
+
*
|
|
440
|
+
* This can be useful in cold start scenarios to stagger or delay some heavy
|
|
441
|
+
* compute jobs. If no value is given for this field then the first invocation
|
|
442
|
+
* will happen as soon as possible according to the cadence.
|
|
443
|
+
*
|
|
444
|
+
* NOTE: This is a per-worker delay. If you have a cluster of workers all
|
|
445
|
+
* collaborating on a task that has its `scope` field set to `'global'`, then
|
|
446
|
+
* you may still see the task being processed by other long-lived workers,
|
|
447
|
+
* while any given single worker is in its initial sleep delay time e.g. after
|
|
448
|
+
* a deployment. Therefore, this parameter is not useful for "globally" pausing
|
|
449
|
+
* work; its main intended use is for individual machines to get a chance to
|
|
450
|
+
* reach some equilibrium at startup before triggering heavy batch workloads.
|
|
451
|
+
*/
|
|
452
|
+
initialDelay?: Duration | HumanDuration;
|
|
453
|
+
/**
|
|
454
|
+
* Sets the scope of concurrency control / locking to apply for invocations of
|
|
455
|
+
* this task.
|
|
456
|
+
*
|
|
457
|
+
* @remarks
|
|
458
|
+
*
|
|
459
|
+
* When the scope is set to the default value `'global'`, the scheduler will
|
|
460
|
+
* attempt to ensure that only one worker machine runs the task at a time,
|
|
461
|
+
* according to the given cadence. This means that as the number of worker
|
|
462
|
+
* hosts increases, the invocation frequency of this task will not go up.
|
|
463
|
+
* Instead, the load is spread randomly across hosts. This setting is useful
|
|
464
|
+
* for tasks that access shared resources, for example catalog ingestion tasks
|
|
465
|
+
* where you do not want many machines to repeatedly import the same data and
|
|
466
|
+
* trample over each other.
|
|
467
|
+
*
|
|
468
|
+
* When the scope is set to `'local'`, there is no concurrency control across
|
|
469
|
+
* hosts. Each host runs the task according to the given cadence similarly to
|
|
470
|
+
* `setInterval`, but the runtime ensures that there are no overlapping runs.
|
|
471
|
+
*
|
|
472
|
+
* @defaultValue 'global'
|
|
473
|
+
*/
|
|
474
|
+
scope?: 'global' | 'local';
|
|
356
475
|
}
|
|
476
|
+
/**
|
|
477
|
+
* Config options for {@link SchedulerServiceTaskScheduleDefinition}
|
|
478
|
+
* that control the scheduling of a task.
|
|
479
|
+
*
|
|
480
|
+
* @public
|
|
481
|
+
*/
|
|
482
|
+
interface SchedulerServiceTaskScheduleDefinitionConfig {
|
|
483
|
+
/**
|
|
484
|
+
* How often you want the task to run. The system does its best to avoid
|
|
485
|
+
* overlapping invocations.
|
|
486
|
+
*
|
|
487
|
+
* @remarks
|
|
488
|
+
*
|
|
489
|
+
* This is the best effort value; under some circumstances there can be
|
|
490
|
+
* deviations. For example, if the task runtime is longer than the frequency
|
|
491
|
+
* and the timeout has not been given or not been exceeded yet, the next
|
|
492
|
+
* invocation of this task will be delayed until after the previous one
|
|
493
|
+
* finishes.
|
|
494
|
+
*
|
|
495
|
+
* This is a required field.
|
|
496
|
+
*/
|
|
497
|
+
frequency: {
|
|
498
|
+
/**
|
|
499
|
+
* A crontab style string.
|
|
500
|
+
*
|
|
501
|
+
* @remarks
|
|
502
|
+
*
|
|
503
|
+
* Overview:
|
|
504
|
+
*
|
|
505
|
+
* ```
|
|
506
|
+
* ┌────────────── second (optional)
|
|
507
|
+
* │ ┌──────────── minute
|
|
508
|
+
* │ │ ┌────────── hour
|
|
509
|
+
* │ │ │ ┌──────── day of month
|
|
510
|
+
* │ │ │ │ ┌────── month
|
|
511
|
+
* │ │ │ │ │ ┌──── day of week
|
|
512
|
+
* │ │ │ │ │ │
|
|
513
|
+
* │ │ │ │ │ │
|
|
514
|
+
* * * * * * *
|
|
515
|
+
* ```
|
|
516
|
+
*/
|
|
517
|
+
cron: string;
|
|
518
|
+
} | string | HumanDuration;
|
|
519
|
+
/**
|
|
520
|
+
* The maximum amount of time that a single task invocation can take, before
|
|
521
|
+
* it's considered timed out and gets "released" such that a new invocation
|
|
522
|
+
* is permitted to take place (possibly, then, on a different worker).
|
|
523
|
+
*/
|
|
524
|
+
timeout: string | HumanDuration;
|
|
525
|
+
/**
|
|
526
|
+
* The amount of time that should pass before the first invocation happens.
|
|
527
|
+
*
|
|
528
|
+
* @remarks
|
|
529
|
+
*
|
|
530
|
+
* This can be useful in cold start scenarios to stagger or delay some heavy
|
|
531
|
+
* compute jobs. If no value is given for this field then the first invocation
|
|
532
|
+
* will happen as soon as possible according to the cadence.
|
|
533
|
+
*
|
|
534
|
+
* NOTE: This is a per-worker delay. If you have a cluster of workers all
|
|
535
|
+
* collaborating on a task that has its `scope` field set to `'global'`, then
|
|
536
|
+
* you may still see the task being processed by other long-lived workers,
|
|
537
|
+
* while any given single worker is in its initial sleep delay time e.g. after
|
|
538
|
+
* a deployment. Therefore, this parameter is not useful for "globally" pausing
|
|
539
|
+
* work; its main intended use is for individual machines to get a chance to
|
|
540
|
+
* reach some equilibrium at startup before triggering heavy batch workloads.
|
|
541
|
+
*/
|
|
542
|
+
initialDelay?: string | HumanDuration;
|
|
543
|
+
/**
|
|
544
|
+
* Sets the scope of concurrency control / locking to apply for invocations of
|
|
545
|
+
* this task.
|
|
546
|
+
*
|
|
547
|
+
* @remarks
|
|
548
|
+
*
|
|
549
|
+
* When the scope is set to the default value `'global'`, the scheduler will
|
|
550
|
+
* attempt to ensure that only one worker machine runs the task at a time,
|
|
551
|
+
* according to the given cadence. This means that as the number of worker
|
|
552
|
+
* hosts increases, the invocation frequency of this task will not go up.
|
|
553
|
+
* Instead, the load is spread randomly across hosts. This setting is useful
|
|
554
|
+
* for tasks that access shared resources, for example catalog ingestion tasks
|
|
555
|
+
* where you do not want many machines to repeatedly import the same data and
|
|
556
|
+
* trample over each other.
|
|
557
|
+
*
|
|
558
|
+
* When the scope is set to `'local'`, there is no concurrency control across
|
|
559
|
+
* hosts. Each host runs the task according to the given cadence similarly to
|
|
560
|
+
* `setInterval`, but the runtime ensures that there are no overlapping runs.
|
|
561
|
+
*
|
|
562
|
+
* @defaultValue 'global'
|
|
563
|
+
*/
|
|
564
|
+
scope?: 'global' | 'local';
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Options that apply to the invocation of a given task.
|
|
568
|
+
*
|
|
569
|
+
* @public
|
|
570
|
+
*/
|
|
571
|
+
interface SchedulerServiceTaskInvocationDefinition {
|
|
572
|
+
/**
|
|
573
|
+
* A unique ID (within the scope of the plugin) for the task.
|
|
574
|
+
*/
|
|
575
|
+
id: string;
|
|
576
|
+
/**
|
|
577
|
+
* The actual task function to be invoked regularly.
|
|
578
|
+
*/
|
|
579
|
+
fn: SchedulerServiceTaskFunction;
|
|
580
|
+
/**
|
|
581
|
+
* An abort signal that, when triggered, will stop the recurring execution of
|
|
582
|
+
* the task.
|
|
583
|
+
*/
|
|
584
|
+
signal?: AbortSignal;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* A previously prepared task schedule, ready to be invoked.
|
|
588
|
+
*
|
|
589
|
+
* @public
|
|
590
|
+
*/
|
|
591
|
+
interface SchedulerServiceTaskRunner {
|
|
592
|
+
/**
|
|
593
|
+
* Takes the schedule and executes an actual task using it.
|
|
594
|
+
*
|
|
595
|
+
* @param task - The actual runtime properties of the task
|
|
596
|
+
*/
|
|
597
|
+
run(task: SchedulerServiceTaskInvocationDefinition): Promise<void>;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Deals with the scheduling of distributed tasks, for a given plugin.
|
|
601
|
+
*
|
|
602
|
+
* @public
|
|
603
|
+
*/
|
|
604
|
+
interface SchedulerService {
|
|
605
|
+
/**
|
|
606
|
+
* Manually triggers a task by ID.
|
|
607
|
+
*
|
|
608
|
+
* If the task doesn't exist, a NotFoundError is thrown. If the task is
|
|
609
|
+
* currently running, a ConflictError is thrown.
|
|
610
|
+
*
|
|
611
|
+
* @param id - The task ID
|
|
612
|
+
*/
|
|
613
|
+
triggerTask(id: string): Promise<void>;
|
|
614
|
+
/**
|
|
615
|
+
* Schedules a task function for recurring runs.
|
|
616
|
+
*
|
|
617
|
+
* @remarks
|
|
618
|
+
*
|
|
619
|
+
* The `scope` task field controls whether to use coordinated exclusive
|
|
620
|
+
* invocation across workers, or to just coordinate within the current worker.
|
|
621
|
+
*
|
|
622
|
+
* This convenience method performs both the scheduling and invocation in one
|
|
623
|
+
* go.
|
|
624
|
+
*
|
|
625
|
+
* @param task - The task definition
|
|
626
|
+
*/
|
|
627
|
+
scheduleTask(task: SchedulerServiceTaskScheduleDefinition & SchedulerServiceTaskInvocationDefinition): Promise<void>;
|
|
628
|
+
/**
|
|
629
|
+
* Creates a scheduled but dormant recurring task, ready to be launched at a
|
|
630
|
+
* later time.
|
|
631
|
+
*
|
|
632
|
+
* @remarks
|
|
633
|
+
*
|
|
634
|
+
* This method is useful for pre-creating a schedule in outer code to be
|
|
635
|
+
* passed into an inner implementation, such that the outer code controls
|
|
636
|
+
* scheduling while inner code controls implementation.
|
|
637
|
+
*
|
|
638
|
+
* @param schedule - The task schedule
|
|
639
|
+
*/
|
|
640
|
+
createScheduledTaskRunner(schedule: SchedulerServiceTaskScheduleDefinition): SchedulerServiceTaskRunner;
|
|
641
|
+
/**
|
|
642
|
+
* Returns all scheduled tasks registered to this scheduler.
|
|
643
|
+
*
|
|
644
|
+
* @remarks
|
|
645
|
+
*
|
|
646
|
+
* This method is useful for triggering tasks manually using the triggerTask
|
|
647
|
+
* functionality. Note that the returned tasks contain only tasks that have
|
|
648
|
+
* been initialized in this instance of the scheduler.
|
|
649
|
+
*
|
|
650
|
+
* @returns Scheduled tasks
|
|
651
|
+
*/
|
|
652
|
+
getScheduledTasks(): Promise<SchedulerServiceTaskDescriptor[]>;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Reads a {@link SchedulerServiceTaskScheduleDefinition} from config. Expects
|
|
656
|
+
* the config not to be the root config, but the config for the definition.
|
|
657
|
+
*
|
|
658
|
+
* @param config - config for a TaskScheduleDefinition.
|
|
659
|
+
* @public
|
|
660
|
+
*/
|
|
661
|
+
declare function readSchedulerServiceTaskScheduleDefinitionFromConfig(config: Config): SchedulerServiceTaskScheduleDefinition;
|
|
357
662
|
|
|
358
663
|
/**
|
|
359
664
|
* A service that provides a logging facility.
|
|
@@ -932,6 +1237,7 @@ declare namespace coreServices {
|
|
|
932
1237
|
* The service reference for the plugin scoped {@link TokenManagerService}.
|
|
933
1238
|
*
|
|
934
1239
|
* @public
|
|
1240
|
+
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
|
|
935
1241
|
*/
|
|
936
1242
|
const tokenManager: ServiceRef<TokenManagerService, "plugin">;
|
|
937
1243
|
/**
|
|
@@ -944,10 +1250,44 @@ declare namespace coreServices {
|
|
|
944
1250
|
* The service reference for the plugin scoped {@link IdentityService}.
|
|
945
1251
|
*
|
|
946
1252
|
* @public
|
|
1253
|
+
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
|
|
947
1254
|
*/
|
|
948
1255
|
const identity: ServiceRef<IdentityService, "plugin">;
|
|
949
1256
|
}
|
|
950
1257
|
|
|
1258
|
+
/**
|
|
1259
|
+
* Tries to deduce whether a thrown error is a database conflict.
|
|
1260
|
+
*
|
|
1261
|
+
* @public
|
|
1262
|
+
* @param e - A thrown error
|
|
1263
|
+
* @returns True if the error looks like it was a conflict error thrown by a
|
|
1264
|
+
* known database engine
|
|
1265
|
+
*/
|
|
1266
|
+
declare function isDatabaseConflictError(e: unknown): boolean;
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* Resolve a path relative to the root of a package directory.
|
|
1270
|
+
* Additional path arguments are resolved relative to the package dir.
|
|
1271
|
+
*
|
|
1272
|
+
* This is particularly useful when you want to access assets shipped with
|
|
1273
|
+
* your backend plugin package. When doing so, do not forget to include the assets
|
|
1274
|
+
* in your published package by adding them to `files` in your `package.json`.
|
|
1275
|
+
*
|
|
1276
|
+
* @public
|
|
1277
|
+
*/
|
|
1278
|
+
declare function resolvePackagePath(name: string, ...paths: string[]): string;
|
|
1279
|
+
/**
|
|
1280
|
+
* Resolves a target path from a base path while guaranteeing that the result is
|
|
1281
|
+
* a path that point to or within the base path. This is useful for resolving
|
|
1282
|
+
* paths from user input, as it otherwise opens up for vulnerabilities.
|
|
1283
|
+
*
|
|
1284
|
+
* @public
|
|
1285
|
+
* @param base - The base directory to resolve the path from.
|
|
1286
|
+
* @param path - The target path, relative or absolute
|
|
1287
|
+
* @returns A path that is guaranteed to point to or within the base path.
|
|
1288
|
+
*/
|
|
1289
|
+
declare function resolveSafeChildPath(base: string, path: string): string;
|
|
1290
|
+
|
|
951
1291
|
/**
|
|
952
1292
|
* TODO
|
|
953
1293
|
*
|
|
@@ -1071,4 +1411,4 @@ interface BackendModuleConfig {
|
|
|
1071
1411
|
*/
|
|
1072
1412
|
declare function createBackendModule(config: BackendModuleConfig): () => BackendFeature;
|
|
1073
1413
|
|
|
1074
|
-
export { type AuthService, type BackendFeature, type BackendModuleConfig, type BackendModuleRegistrationPoints, type BackendPluginConfig, type BackendPluginRegistrationPoints, type BackstageCredentials, type BackstageNonePrincipal, type BackstagePrincipalTypes, type BackstageServicePrincipal, type BackstageUserInfo, type BackstageUserPrincipal, type CacheService, type CacheServiceOptions, type CacheServiceSetOptions, 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 ReadTreeOptions, type ReadTreeResponse, type ReadTreeResponseDirOptions, type ReadTreeResponseFile, type ReadUrlOptions, type ReadUrlResponse, type RootConfigService, type RootHttpRouterService, type RootLifecycleService, type RootLoggerService, type RootServiceFactoryConfig, type SchedulerService, type SearchOptions, type SearchResponse, type SearchResponseFile, type ServiceFactory, type ServiceFactoryOrFunction, type ServiceRef, type ServiceRefConfig, type TokenManagerService, type UrlReaderService, type UserInfoService, coreServices, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef };
|
|
1414
|
+
export { type AuthService, type BackendFeature, type BackendModuleConfig, type BackendModuleRegistrationPoints, type BackendPluginConfig, type BackendPluginRegistrationPoints, type BackstageCredentials, type BackstageNonePrincipal, type BackstagePrincipalTypes, type BackstageServicePrincipal, type BackstageUserInfo, type BackstageUserPrincipal, type CacheService, type CacheServiceOptions, type CacheServiceSetOptions, 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 ReadTreeOptions, type ReadTreeResponse, type ReadTreeResponseDirOptions, type ReadTreeResponseFile, type ReadUrlOptions, type ReadUrlResponse, type RootConfigService, type RootHttpRouterService, type RootLifecycleService, type RootLoggerService, type RootServiceFactoryConfig, type SchedulerService, type SchedulerServiceTaskDescriptor, type SchedulerServiceTaskFunction, type SchedulerServiceTaskInvocationDefinition, type SchedulerServiceTaskRunner, type SchedulerServiceTaskScheduleDefinition, type SchedulerServiceTaskScheduleDefinitionConfig, type SearchOptions, type SearchResponse, type SearchResponseFile, type ServiceFactory, type ServiceFactoryOrFunction, type ServiceRef, type ServiceRefConfig, type TokenManagerService, type UrlReaderService, type UserInfoService, coreServices, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var paths = require('./cjs/paths-D7KGMZeP.cjs.js');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
require('@backstage/cli-common');
|
|
6
|
+
require('@backstage/errors');
|
|
7
|
+
require('fs');
|
|
8
|
+
|
|
9
|
+
function overridePackagePathResolution(options) {
|
|
10
|
+
const name = options.packageName;
|
|
11
|
+
if (paths.packagePathMocks.has(name)) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
`Tried to override resolution for '${name}' more than once for package '${name}'`
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
paths.packagePathMocks.set(name, (paths) => {
|
|
17
|
+
const joinedPath = path.posix.join(...paths);
|
|
18
|
+
const localResolver = options.paths?.[joinedPath];
|
|
19
|
+
if (localResolver) {
|
|
20
|
+
return typeof localResolver === "function" ? localResolver() : localResolver;
|
|
21
|
+
}
|
|
22
|
+
if (options.path) {
|
|
23
|
+
return path.resolve(options.path, ...paths);
|
|
24
|
+
}
|
|
25
|
+
return void 0;
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
restore() {
|
|
29
|
+
paths.packagePathMocks.delete(name);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.overridePackagePathResolution = overridePackagePathResolution;
|
|
35
|
+
//# sourceMappingURL=testUtils.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testUtils.cjs.js","sources":["../src/testUtils.ts"],"sourcesContent":["/*\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\nimport { packagePathMocks } from './paths';\nimport { posix as posixPath, resolve as resolvePath } from 'path';\n\n/** @public */\nexport interface PackagePathResolutionOverride {\n /** Restores the normal behavior of resolvePackagePath */\n restore(): void;\n}\n\n/** @public */\nexport interface OverridePackagePathResolutionOptions {\n /** The name of the package to mock the resolved path of */\n packageName: string;\n\n /** A replacement for the root package path */\n path?: string;\n\n /**\n * Replacements for package sub-paths, each key must be an exact match of the posix-style path\n * that is being resolved within the package.\n *\n * For example, code calling `resolvePackagePath('x', 'foo', 'bar')` would match only the following\n * configuration: `overridePackagePathResolution({ packageName: 'x', paths: { 'foo/bar': baz } })`\n */\n paths?: { [path in string]: string | (() => string) };\n}\n\n/**\n * This utility helps you override the paths returned by `resolvePackagePath` for a given package.\n *\n * @public\n */\nexport function overridePackagePathResolution(\n options: OverridePackagePathResolutionOptions,\n): PackagePathResolutionOverride {\n const name = options.packageName;\n\n if (packagePathMocks.has(name)) {\n throw new Error(\n `Tried to override resolution for '${name}' more than once for package '${name}'`,\n );\n }\n\n packagePathMocks.set(name, paths => {\n const joinedPath = posixPath.join(...paths);\n const localResolver = options.paths?.[joinedPath];\n if (localResolver) {\n return typeof localResolver === 'function'\n ? localResolver()\n : localResolver;\n }\n if (options.path) {\n return resolvePath(options.path, ...paths);\n }\n return undefined;\n });\n\n return {\n restore() {\n packagePathMocks.delete(name);\n },\n };\n}\n"],"names":["packagePathMocks","posixPath","resolvePath"],"mappings":";;;;;;;;AAgDO,SAAS,8BACd,OAC+B,EAAA;AAC/B,EAAA,MAAM,OAAO,OAAQ,CAAA,WAAA,CAAA;AAErB,EAAI,IAAAA,sBAAA,CAAiB,GAAI,CAAA,IAAI,CAAG,EAAA;AAC9B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kCAAA,EAAqC,IAAI,CAAA,8BAAA,EAAiC,IAAI,CAAA,CAAA,CAAA;AAAA,KAChF,CAAA;AAAA,GACF;AAEA,EAAiBA,sBAAA,CAAA,GAAA,CAAI,MAAM,CAAS,KAAA,KAAA;AAClC,IAAA,MAAM,UAAa,GAAAC,UAAA,CAAU,IAAK,CAAA,GAAG,KAAK,CAAA,CAAA;AAC1C,IAAM,MAAA,aAAA,GAAgB,OAAQ,CAAA,KAAA,GAAQ,UAAU,CAAA,CAAA;AAChD,IAAA,IAAI,aAAe,EAAA;AACjB,MAAA,OAAO,OAAO,aAAA,KAAkB,UAC5B,GAAA,aAAA,EACA,GAAA,aAAA,CAAA;AAAA,KACN;AACA,IAAA,IAAI,QAAQ,IAAM,EAAA;AAChB,MAAA,OAAOC,YAAY,CAAA,OAAA,CAAQ,IAAM,EAAA,GAAG,KAAK,CAAA,CAAA;AAAA,KAC3C;AACA,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACR,CAAA,CAAA;AAED,EAAO,OAAA;AAAA,IACL,OAAU,GAAA;AACR,MAAAF,sBAAA,CAAiB,OAAO,IAAI,CAAA,CAAA;AAAA,KAC9B;AAAA,GACF,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** @public */
|
|
2
|
+
interface PackagePathResolutionOverride {
|
|
3
|
+
/** Restores the normal behavior of resolvePackagePath */
|
|
4
|
+
restore(): void;
|
|
5
|
+
}
|
|
6
|
+
/** @public */
|
|
7
|
+
interface OverridePackagePathResolutionOptions {
|
|
8
|
+
/** The name of the package to mock the resolved path of */
|
|
9
|
+
packageName: string;
|
|
10
|
+
/** A replacement for the root package path */
|
|
11
|
+
path?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Replacements for package sub-paths, each key must be an exact match of the posix-style path
|
|
14
|
+
* that is being resolved within the package.
|
|
15
|
+
*
|
|
16
|
+
* For example, code calling `resolvePackagePath('x', 'foo', 'bar')` would match only the following
|
|
17
|
+
* configuration: `overridePackagePathResolution({ packageName: 'x', paths: { 'foo/bar': baz } })`
|
|
18
|
+
*/
|
|
19
|
+
paths?: {
|
|
20
|
+
[path in string]: string | (() => string);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* This utility helps you override the paths returned by `resolvePackagePath` for a given package.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
declare function overridePackagePathResolution(options: OverridePackagePathResolutionOptions): PackagePathResolutionOverride;
|
|
29
|
+
|
|
30
|
+
export { type OverridePackagePathResolutionOptions, type PackagePathResolutionOverride, overridePackagePathResolution };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-plugin-api",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.19-next.0",
|
|
4
4
|
"description": "Core API used by Backstage backend plugins",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -29,13 +29,19 @@
|
|
|
29
29
|
"types": "./dist/alpha.d.ts",
|
|
30
30
|
"default": "./dist/alpha.cjs.js"
|
|
31
31
|
},
|
|
32
|
+
"./testUtils": {
|
|
33
|
+
"require": "./dist/testUtils.cjs.js",
|
|
34
|
+
"types": "./dist/testUtils.d.ts",
|
|
35
|
+
"default": "./dist/testUtils.cjs.js"
|
|
36
|
+
},
|
|
32
37
|
"./package.json": "./package.json"
|
|
33
38
|
},
|
|
34
39
|
"main": "./dist/index.cjs.js",
|
|
35
40
|
"types": "./dist/index.d.ts",
|
|
36
41
|
"files": [
|
|
37
42
|
"dist",
|
|
38
|
-
"alpha"
|
|
43
|
+
"alpha",
|
|
44
|
+
"testUtils"
|
|
39
45
|
],
|
|
40
46
|
"scripts": {
|
|
41
47
|
"build": "backstage-cli package build",
|
|
@@ -47,16 +53,20 @@
|
|
|
47
53
|
"test": "backstage-cli package test"
|
|
48
54
|
},
|
|
49
55
|
"dependencies": {
|
|
50
|
-
"@backstage/
|
|
56
|
+
"@backstage/cli-common": "^0.1.13",
|
|
51
57
|
"@backstage/config": "^1.2.0",
|
|
52
|
-
"@backstage/
|
|
58
|
+
"@backstage/errors": "^1.2.4",
|
|
59
|
+
"@backstage/plugin-auth-node": "^0.4.14-next.0",
|
|
53
60
|
"@backstage/plugin-permission-common": "^0.7.13",
|
|
54
61
|
"@backstage/types": "^1.1.1",
|
|
55
62
|
"@types/express": "^4.17.6",
|
|
63
|
+
"@types/luxon": "^3.0.0",
|
|
56
64
|
"express": "^4.17.1",
|
|
57
|
-
"knex": "^3.0.0"
|
|
65
|
+
"knex": "^3.0.0",
|
|
66
|
+
"luxon": "^3.0.0"
|
|
58
67
|
},
|
|
59
68
|
"devDependencies": {
|
|
60
|
-
"@backstage/
|
|
69
|
+
"@backstage/backend-test-utils": "^0.3.9-next.0",
|
|
70
|
+
"@backstage/cli": "^0.26.6-next.0"
|
|
61
71
|
}
|
|
62
72
|
}
|