@backstage/backend-plugin-api 1.6.2 → 1.7.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,14 +1,31 @@
1
1
  # @backstage/backend-plugin-api
2
2
 
3
- ## 1.6.2
3
+ ## 1.7.0-next.1
4
+
5
+ ### Minor Changes
6
+
7
+ - bb9b471: Plugin IDs that do not match the standard format are deprecated (letters, digits, and dashes only, starting with a letter). Plugin IDs that do no match this format will be rejected in a future release.
8
+
9
+ In addition, plugin IDs that don't match the legacy pattern that also allows underscores, with be rejected.
10
+
11
+ ## 1.7.0-next.0
12
+
13
+ ### Minor Changes
14
+
15
+ - f1d29b4: Added support for extension point factories. This makes it possible to call `registerExtensionPoint` with a single options argument and provide a factory for the extension point rather than a direct implementation. The factory is passed a context with a `reportModuleStartupFailure` method that makes it possible for plugins to report and attribute startup errors to the module that consumed the extension point.
4
16
 
5
17
  ### Patch Changes
6
18
 
7
- - 5683c85: Bump to latest zod to ensure it has the latest features
19
+ - 7455dae: Use node prefix on native imports
20
+ - 69d880e: Bump to latest zod to ensure it has the latest features
8
21
  - Updated dependencies
9
- - @backstage/plugin-permission-common@0.9.5
10
- - @backstage/plugin-permission-node@0.10.9
11
- - @backstage/plugin-auth-node@0.6.12
22
+ - @backstage/cli-common@0.1.18-next.0
23
+ - @backstage/plugin-auth-node@0.6.12-next.0
24
+ - @backstage/plugin-permission-common@0.9.5-next.0
25
+ - @backstage/plugin-permission-node@0.10.9-next.0
26
+ - @backstage/config@1.3.6
27
+ - @backstage/errors@1.2.7
28
+ - @backstage/types@1.2.2
12
29
 
13
30
  ## 1.6.1
14
31
 
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ import { Knex } from 'knex';
5
5
  import { PermissionRule, PermissionResourceRef, PermissionRuleset } from '@backstage/plugin-permission-node';
6
6
  import { Config } from '@backstage/config';
7
7
  import { Duration } from 'luxon';
8
- import { Readable } from 'stream';
8
+ import { Readable } from 'node:stream';
9
9
  export { isChildPath } from '@backstage/cli-common';
10
10
 
11
11
  /**
@@ -1907,6 +1907,21 @@ type ExtensionPoint<T> = {
1907
1907
  toString(): string;
1908
1908
  $$type: '@backstage/ExtensionPoint';
1909
1909
  };
1910
+ /**
1911
+ * Context provided to extension point factories.
1912
+ *
1913
+ * @public
1914
+ */
1915
+ interface ExtensionPointFactoryContext {
1916
+ /**
1917
+ * Report a startup failure that happened as part of using an extension that
1918
+ * the module provided. This should be called before the plugin's `init`
1919
+ * function returns.
1920
+ */
1921
+ reportModuleStartupFailure(options: {
1922
+ error: Error;
1923
+ }): void;
1924
+ }
1910
1925
  /** @ignore */
1911
1926
  type DepsToInstances<TDeps extends {
1912
1927
  [key in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
@@ -1919,7 +1934,17 @@ type DepsToInstances<TDeps extends {
1919
1934
  * @public
1920
1935
  */
1921
1936
  interface BackendPluginRegistrationPoints {
1937
+ /**
1938
+ * Registers an implementation for an extension point.
1939
+ */
1922
1940
  registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
1941
+ /**
1942
+ * Registers a factory that produces a separate implementation for an extension point for each module.
1943
+ */
1944
+ registerExtensionPoint<TExtensionPoint>(options: {
1945
+ extensionPoint: ExtensionPoint<TExtensionPoint>;
1946
+ factory: (context: ExtensionPointFactoryContext) => TExtensionPoint;
1947
+ }): void;
1923
1948
  registerInit<TDeps extends {
1924
1949
  [name in string]: ServiceRef<unknown>;
1925
1950
  }>(options: {
@@ -1934,6 +1959,10 @@ interface BackendPluginRegistrationPoints {
1934
1959
  */
1935
1960
  interface BackendModuleRegistrationPoints {
1936
1961
  registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
1962
+ registerExtensionPoint<TExtensionPoint>(options: {
1963
+ extensionPoint: ExtensionPoint<TExtensionPoint>;
1964
+ factory: (context: ExtensionPointFactoryContext) => TExtensionPoint;
1965
+ }): void;
1937
1966
  registerInit<TDeps extends {
1938
1967
  [name in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
1939
1968
  }>(options: {
@@ -2046,4 +2075,4 @@ declare function createBackendFeatureLoader<TDeps extends {
2046
2075
  }>(options: CreateBackendFeatureLoaderOptions<TDeps>): BackendFeature;
2047
2076
 
2048
2077
  export { coreServices, createBackendFeatureLoader, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };
2049
- export type { AuditorService, AuditorServiceCreateEventOptions, AuditorServiceEvent, AuditorServiceEventSeverityLevel, AuthService, BackendFeature, BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, BackstageCredentials, BackstageNonePrincipal, BackstagePrincipalAccessRestrictions, BackstagePrincipalTypes, BackstageServicePrincipal, BackstageUserInfo, BackstageUserPrincipal, CacheService, CacheServiceOptions, CacheServiceSetOptions, CreateBackendFeatureLoaderOptions, CreateBackendModuleOptions, CreateBackendPluginOptions, CreateExtensionPointOptions, DatabaseService, DiscoveryService, ExtensionPoint, HttpAuthService, HttpRouterService, HttpRouterServiceAuthPolicy, LifecycleService, LifecycleServiceShutdownHook, LifecycleServiceShutdownOptions, LifecycleServiceStartupHook, LifecycleServiceStartupOptions, LoggerService, PermissionsRegistryService, PermissionsRegistryServiceAddResourceTypeOptions, PermissionsService, PermissionsServiceRequestOptions, PluginMetadataService, PluginServiceFactoryOptions, RootConfigService, RootHealthService, RootHttpRouterService, RootInstanceMetadataService, RootInstanceMetadataServicePluginInfo, RootLifecycleService, RootLoggerService, RootServiceFactoryOptions, SchedulerService, SchedulerServiceTaskDescriptor, SchedulerServiceTaskFunction, SchedulerServiceTaskInvocationDefinition, SchedulerServiceTaskRunner, SchedulerServiceTaskScheduleDefinition, SchedulerServiceTaskScheduleDefinitionConfig, ServiceFactory, ServiceRef, ServiceRefOptions, UrlReaderService, UrlReaderServiceReadTreeOptions, UrlReaderServiceReadTreeResponse, UrlReaderServiceReadTreeResponseDirOptions, UrlReaderServiceReadTreeResponseFile, UrlReaderServiceReadUrlOptions, UrlReaderServiceReadUrlResponse, UrlReaderServiceSearchOptions, UrlReaderServiceSearchResponse, UrlReaderServiceSearchResponseFile, UserInfoService };
2078
+ export type { AuditorService, AuditorServiceCreateEventOptions, AuditorServiceEvent, AuditorServiceEventSeverityLevel, AuthService, BackendFeature, BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, BackstageCredentials, BackstageNonePrincipal, BackstagePrincipalAccessRestrictions, BackstagePrincipalTypes, BackstageServicePrincipal, BackstageUserInfo, BackstageUserPrincipal, CacheService, CacheServiceOptions, CacheServiceSetOptions, CreateBackendFeatureLoaderOptions, CreateBackendModuleOptions, CreateBackendPluginOptions, CreateExtensionPointOptions, DatabaseService, DiscoveryService, ExtensionPoint, ExtensionPointFactoryContext, HttpAuthService, HttpRouterService, HttpRouterServiceAuthPolicy, LifecycleService, LifecycleServiceShutdownHook, LifecycleServiceShutdownOptions, LifecycleServiceStartupHook, LifecycleServiceStartupOptions, LoggerService, PermissionsRegistryService, PermissionsRegistryServiceAddResourceTypeOptions, PermissionsService, PermissionsServiceRequestOptions, PluginMetadataService, PluginServiceFactoryOptions, RootConfigService, RootHealthService, RootHttpRouterService, RootInstanceMetadataService, RootInstanceMetadataServicePluginInfo, RootLifecycleService, RootLoggerService, RootServiceFactoryOptions, SchedulerService, SchedulerServiceTaskDescriptor, SchedulerServiceTaskFunction, SchedulerServiceTaskInvocationDefinition, SchedulerServiceTaskRunner, SchedulerServiceTaskScheduleDefinition, SchedulerServiceTaskScheduleDefinitionConfig, ServiceFactory, ServiceRef, ServiceRefOptions, UrlReaderService, UrlReaderServiceReadTreeOptions, UrlReaderServiceReadTreeResponse, UrlReaderServiceReadTreeResponseDirOptions, UrlReaderServiceReadTreeResponseFile, UrlReaderServiceReadUrlOptions, UrlReaderServiceReadUrlResponse, UrlReaderServiceSearchOptions, UrlReaderServiceSearchResponse, UrlReaderServiceSearchResponseFile, UserInfoService };
package/dist/paths.cjs.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var cliCommon = require('@backstage/cli-common');
4
4
  var errors = require('@backstage/errors');
5
- var path = require('path');
5
+ var node_path = require('node:path');
6
6
 
7
7
  const packagePathMocks = /* @__PURE__ */ new Map();
8
8
  function resolvePackagePath(name, ...paths) {
@@ -14,16 +14,16 @@ function resolvePackagePath(name, ...paths) {
14
14
  }
15
15
  }
16
16
  const req = typeof __non_webpack_require__ === "undefined" ? require : __non_webpack_require__;
17
- return path.resolve(req.resolve(`${name}/package.json`), "..", ...paths);
17
+ return node_path.resolve(req.resolve(`${name}/package.json`), "..", ...paths);
18
18
  }
19
- function resolveSafeChildPath(base, path$1) {
20
- const targetPath = path.resolve(base, path$1);
19
+ function resolveSafeChildPath(base, path) {
20
+ const targetPath = node_path.resolve(base, path);
21
21
  if (!cliCommon.isChildPath(base, targetPath)) {
22
22
  throw new errors.NotAllowedError(
23
23
  "Relative path is not allowed to refer to a directory outside its parent"
24
24
  );
25
25
  }
26
- return path.resolve(base, path$1);
26
+ return node_path.resolve(base, path);
27
27
  }
28
28
 
29
29
  Object.defineProperty(exports, "isChildPath", {
@@ -1 +1 @@
1
- {"version":3,"file":"paths.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';\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 targetPath = resolvePath(base, path);\n\n if (!isChildPath(base, 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\n// Re-export isChildPath so that backend packages don't need to depend on cli-common\nexport { isChildPath };\n"],"names":["resolvePath","path","isChildPath","NotAllowedError"],"mappings":";;;;;;AAqBO,MAAM,gBAAA,uBAAuB,GAAA;AAe7B,SAAS,kBAAA,CAAmB,SAAiB,KAAA,EAAiB;AACnE,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA;AAC/C,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,MAAM,QAAA,GAAW,cAAc,KAAK,CAAA;AACpC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,MAAM,GAAA,GACJ,OAAO,uBAAA,KAA4B,WAAA,GAC/B,OAAA,GACA,uBAAA;AAEN,EAAA,OAAOA,YAAA,CAAY,IAAI,OAAA,CAAQ,CAAA,EAAG,IAAI,CAAA,aAAA,CAAe,CAAA,EAAG,IAAA,EAAM,GAAG,KAAK,CAAA;AACxE;AAYO,SAAS,oBAAA,CAAqB,MAAcC,MAAA,EAAsB;AACvE,EAAA,MAAM,UAAA,GAAaD,YAAA,CAAY,IAAA,EAAMC,MAAI,CAAA;AAEzC,EAAA,IAAI,CAACC,qBAAA,CAAY,IAAA,EAAM,UAAU,CAAA,EAAG;AAClC,IAAA,MAAM,IAAIC,sBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,OAAOH,YAAA,CAAY,MAAMC,MAAI,CAAA;AAC/B;;;;;;;;;;"}
1
+ {"version":3,"file":"paths.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 'node:path';\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 targetPath = resolvePath(base, path);\n\n if (!isChildPath(base, 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\n// Re-export isChildPath so that backend packages don't need to depend on cli-common\nexport { isChildPath };\n"],"names":["resolvePath","isChildPath","NotAllowedError"],"mappings":";;;;;;AAqBO,MAAM,gBAAA,uBAAuB,GAAA;AAe7B,SAAS,kBAAA,CAAmB,SAAiB,KAAA,EAAiB;AACnE,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA;AAC/C,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,MAAM,QAAA,GAAW,cAAc,KAAK,CAAA;AACpC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,MAAM,GAAA,GACJ,OAAO,uBAAA,KAA4B,WAAA,GAC/B,OAAA,GACA,uBAAA;AAEN,EAAA,OAAOA,iBAAA,CAAY,IAAI,OAAA,CAAQ,CAAA,EAAG,IAAI,CAAA,aAAA,CAAe,CAAA,EAAG,IAAA,EAAM,GAAG,KAAK,CAAA;AACxE;AAYO,SAAS,oBAAA,CAAqB,MAAc,IAAA,EAAsB;AACvE,EAAA,MAAM,UAAA,GAAaA,iBAAA,CAAY,IAAA,EAAM,IAAI,CAAA;AAEzC,EAAA,IAAI,CAACC,qBAAA,CAAY,IAAA,EAAM,UAAU,CAAA,EAAG;AAClC,IAAA,MAAM,IAAIC,sBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,OAAOF,iBAAA,CAAY,MAAM,IAAI,CAAA;AAC/B;;;;;;;;;;"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var paths = require('./paths.cjs.js');
4
- var path = require('path');
4
+ var node_path = require('node:path');
5
5
 
6
6
  function overridePackagePathResolution(options) {
7
7
  const name = options.packageName;
@@ -11,13 +11,13 @@ function overridePackagePathResolution(options) {
11
11
  );
12
12
  }
13
13
  paths.packagePathMocks.set(name, (paths) => {
14
- const joinedPath = path.posix.join(...paths);
14
+ const joinedPath = node_path.posix.join(...paths);
15
15
  const localResolver = options.paths?.[joinedPath];
16
16
  if (localResolver) {
17
17
  return typeof localResolver === "function" ? localResolver() : localResolver;
18
18
  }
19
19
  if (options.path) {
20
- return path.resolve(options.path, ...paths);
20
+ return node_path.resolve(options.path, ...paths);
21
21
  }
22
22
  return void 0;
23
23
  });
@@ -1 +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,OAAA,EAC+B;AAC/B,EAAA,MAAM,OAAO,OAAA,CAAQ,WAAA;AAErB,EAAA,IAAIA,sBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kCAAA,EAAqC,IAAI,CAAA,8BAAA,EAAiC,IAAI,CAAA,CAAA;AAAA,KAChF;AAAA,EACF;AAEA,EAAAA,sBAAA,CAAiB,GAAA,CAAI,MAAM,CAAA,KAAA,KAAS;AAClC,IAAA,MAAM,UAAA,GAAaC,UAAA,CAAU,IAAA,CAAK,GAAG,KAAK,CAAA;AAC1C,IAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,KAAA,GAAQ,UAAU,CAAA;AAChD,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,OAAO,OAAO,aAAA,KAAkB,UAAA,GAC5B,aAAA,EAAc,GACd,aAAA;AAAA,IACN;AACA,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,OAAOC,YAAA,CAAY,OAAA,CAAQ,IAAA,EAAM,GAAG,KAAK,CAAA;AAAA,IAC3C;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,OAAA,GAAU;AACR,MAAAF,sBAAA,CAAiB,OAAO,IAAI,CAAA;AAAA,IAC9B;AAAA,GACF;AACF;;;;"}
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 'node: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,OAAA,EAC+B;AAC/B,EAAA,MAAM,OAAO,OAAA,CAAQ,WAAA;AAErB,EAAA,IAAIA,sBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kCAAA,EAAqC,IAAI,CAAA,8BAAA,EAAiC,IAAI,CAAA,CAAA;AAAA,KAChF;AAAA,EACF;AAEA,EAAAA,sBAAA,CAAiB,GAAA,CAAI,MAAM,CAAA,KAAA,KAAS;AAClC,IAAA,MAAM,UAAA,GAAaC,eAAA,CAAU,IAAA,CAAK,GAAG,KAAK,CAAA;AAC1C,IAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,KAAA,GAAQ,UAAU,CAAA;AAChD,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,OAAO,OAAO,aAAA,KAAkB,UAAA,GAC5B,aAAA,EAAc,GACd,aAAA;AAAA,IACN;AACA,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,OAAOC,iBAAA,CAAY,OAAA,CAAQ,IAAA,EAAM,GAAG,KAAK,CAAA;AAAA,IAC3C;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,OAAA,GAAU;AACR,MAAAF,sBAAA,CAAiB,OAAO,IAAI,CAAA;AAAA,IAC9B;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ const ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/i;
4
+ const ID_PATTERN_OLD = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/i;
5
+
6
+ exports.ID_PATTERN = ID_PATTERN;
7
+ exports.ID_PATTERN_OLD = ID_PATTERN_OLD;
8
+ //# sourceMappingURL=constants.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.cjs.js","sources":["../../src/wiring/constants.ts"],"sourcesContent":["/*\n * Copyright 2025 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// NOTE: changing any of these constants need to be reflected in\n// @backstage/frontend-plugin-api/src/wiring/constants.ts as well\n\n/**\n * The pattern that IDs must match.\n *\n * @remarks\n * ids must only contain the letters `a` through `z` and digits, in groups separated by\n * dashes. Additionally, the very first character of the first group\n * must be a letter, not a digit\n *\n * @public\n */\nexport const ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/i;\nexport const ID_PATTERN_OLD = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/i;\n"],"names":[],"mappings":";;AA6BO,MAAM,UAAA,GAAa;AACnB,MAAM,cAAA,GAAiB;;;;;"}
@@ -1,15 +1,37 @@
1
1
  'use strict';
2
2
 
3
+ var constants = require('./constants.cjs.js');
4
+
3
5
  function createBackendModule(options) {
6
+ if (!constants.ID_PATTERN.test(options.moduleId)) {
7
+ console.warn(
8
+ `WARNING: The moduleId '${options.moduleId}' for plugin '${options.pluginId}', will be invalid soon, please change it to match the pattern ${constants.ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`
9
+ );
10
+ }
11
+ if (!constants.ID_PATTERN_OLD.test(options.moduleId)) {
12
+ throw new Error(
13
+ `Invalid moduleId '${options.moduleId}' for plugin '${options.pluginId}', must match the pattern ${constants.ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`
14
+ );
15
+ }
4
16
  function getRegistrations() {
5
17
  const extensionPoints = [];
6
18
  let init = void 0;
7
19
  options.register({
8
- registerExtensionPoint(ext, impl) {
20
+ registerExtensionPoint(extOrOpts, impl) {
9
21
  if (init) {
10
22
  throw new Error("registerExtensionPoint called after registerInit");
11
23
  }
12
- extensionPoints.push([ext, impl]);
24
+ if (typeof extOrOpts === "object" && extOrOpts !== null && "extensionPoint" in extOrOpts) {
25
+ extensionPoints.push({
26
+ extensionPoint: extOrOpts.extensionPoint,
27
+ factory: extOrOpts.factory
28
+ });
29
+ } else {
30
+ extensionPoints.push({
31
+ extensionPoint: extOrOpts,
32
+ factory: () => impl
33
+ });
34
+ }
13
35
  },
14
36
  registerInit(regInit) {
15
37
  if (init) {
@@ -28,7 +50,7 @@ function createBackendModule(options) {
28
50
  }
29
51
  return [
30
52
  {
31
- type: "module",
53
+ type: "module-v1.1",
32
54
  pluginId: options.pluginId,
33
55
  moduleId: options.moduleId,
34
56
  extensionPoints,
@@ -1 +1 @@
1
- {"version":3,"file":"createBackendModule.cjs.js","sources":["../../src/wiring/createBackendModule.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';\nimport {\n BackendModuleRegistrationPoints,\n InternalBackendModuleRegistration,\n InternalBackendPluginRegistration,\n InternalBackendRegistrations,\n} from './types';\n\n/**\n * The configuration options passed to {@link createBackendModule}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendModuleOptions {\n /**\n * Should exactly match the `id` of the plugin that the module extends.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n\n /**\n * The ID of this module, used to identify the module and ensure that it is not installed twice.\n */\n moduleId: string;\n register(reg: BackendModuleRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend module for a given plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendModule(\n options: CreateBackendModuleOptions,\n): BackendFeature {\n function getRegistrations() {\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendModuleRegistration['init'] | undefined = undefined;\n\n options.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n extensionPoints.push([ext, impl]);\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'module',\n pluginId: options.pluginId,\n moduleId: options.moduleId,\n extensionPoints,\n init,\n },\n ];\n }\n\n return {\n $$type: '@backstage/BackendFeature' as const,\n featureType: 'registrations',\n version: 'v1',\n getRegistrations,\n } as InternalBackendRegistrations;\n}\n"],"names":[],"mappings":";;AAqDO,SAAS,oBACd,OAAA,EACgB;AAChB,EAAA,SAAS,gBAAA,GAAmB;AAC1B,IAAA,MAAM,kBACJ,EAAC;AACH,IAAA,IAAI,IAAA,GAA8D,MAAA;AAElE,IAAA,OAAA,CAAQ,QAAA,CAAS;AAAA,MACf,sBAAA,CAAuB,KAAK,IAAA,EAAM;AAChC,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,QACpE;AACA,QAAA,eAAA,CAAgB,IAAA,CAAK,CAAC,GAAA,EAAK,IAAI,CAAC,CAAA;AAAA,MAClC,CAAA;AAAA,MACA,aAAa,OAAA,EAAS;AACpB,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,QACzD;AACA,QAAA,IAAA,GAAO;AAAA,UACL,MAAM,OAAA,CAAQ,IAAA;AAAA,UACd,MAAM,OAAA,CAAQ;AAAA,SAChB;AAAA,MACF;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,2CAAA,EAA8C,OAAA,CAAQ,QAAQ,CAAA,YAAA,EAAe,QAAQ,QAAQ,CAAA;AAAA,OAC/F;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,eAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,2BAAA;AAAA,IACR,WAAA,EAAa,eAAA;AAAA,IACb,OAAA,EAAS,IAAA;AAAA,IACT;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"createBackendModule.cjs.js","sources":["../../src/wiring/createBackendModule.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';\nimport { ID_PATTERN, ID_PATTERN_OLD } from './constants';\nimport {\n BackendModuleRegistrationPoints,\n ExtensionPoint,\n ExtensionPointFactoryContext,\n InternalBackendModuleRegistrationV1_1,\n InternalBackendRegistrations,\n} from './types';\n\n/**\n * The configuration options passed to {@link createBackendModule}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendModuleOptions {\n /**\n * Should exactly match the `id` of the plugin that the module extends.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n\n /**\n * The ID of this module, used to identify the module and ensure that it is not installed twice.\n */\n moduleId: string;\n register(reg: BackendModuleRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend module for a given plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/modules | The architecture of modules}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendModule(\n options: CreateBackendModuleOptions,\n): BackendFeature {\n if (!ID_PATTERN.test(options.moduleId)) {\n console.warn(\n `WARNING: The moduleId '${options.moduleId}' for plugin '${options.pluginId}', will be invalid soon, please change it to match the pattern ${ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`,\n );\n }\n if (!ID_PATTERN_OLD.test(options.moduleId)) {\n throw new Error(\n `Invalid moduleId '${options.moduleId}' for plugin '${options.pluginId}', must match the pattern ${ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`,\n );\n }\n\n function getRegistrations() {\n const extensionPoints: InternalBackendModuleRegistrationV1_1['extensionPoints'] =\n [];\n let init: InternalBackendModuleRegistrationV1_1['init'] | undefined =\n undefined;\n\n options.register({\n registerExtensionPoint<TExtensionPoint>(\n extOrOpts:\n | ExtensionPoint<TExtensionPoint>\n | {\n extensionPoint: ExtensionPoint<TExtensionPoint>;\n factory: (\n context: ExtensionPointFactoryContext,\n ) => TExtensionPoint;\n },\n impl?: TExtensionPoint,\n ) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n if (\n typeof extOrOpts === 'object' &&\n extOrOpts !== null &&\n 'extensionPoint' in extOrOpts\n ) {\n extensionPoints.push({\n extensionPoint: extOrOpts.extensionPoint,\n factory: extOrOpts.factory as (\n context: ExtensionPointFactoryContext,\n ) => unknown,\n });\n } else {\n extensionPoints.push({\n extensionPoint: extOrOpts,\n factory: () => impl,\n });\n }\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'module-v1.1',\n pluginId: options.pluginId,\n moduleId: options.moduleId,\n extensionPoints,\n init,\n },\n ];\n }\n\n return {\n $$type: '@backstage/BackendFeature' as const,\n featureType: 'registrations',\n version: 'v1',\n getRegistrations,\n } as InternalBackendRegistrations;\n}\n"],"names":["ID_PATTERN","ID_PATTERN_OLD"],"mappings":";;;;AAuDO,SAAS,oBACd,OAAA,EACgB;AAChB,EAAA,IAAI,CAACA,oBAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACtC,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,0BAA0B,OAAA,CAAQ,QAAQ,iBAAiB,OAAA,CAAQ,QAAQ,kEAAkEA,oBAAU,CAAA,2DAAA;AAAA,KACzJ;AAAA,EACF;AACA,EAAA,IAAI,CAACC,wBAAA,CAAe,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC1C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,qBAAqB,OAAA,CAAQ,QAAQ,iBAAiB,OAAA,CAAQ,QAAQ,6BAA6BD,oBAAU,CAAA,2DAAA;AAAA,KAC/G;AAAA,EACF;AAEA,EAAA,SAAS,gBAAA,GAAmB;AAC1B,IAAA,MAAM,kBACJ,EAAC;AACH,IAAA,IAAI,IAAA,GACF,MAAA;AAEF,IAAA,OAAA,CAAQ,QAAA,CAAS;AAAA,MACf,sBAAA,CACE,WAQA,IAAA,EACA;AACA,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,QACpE;AACA,QAAA,IACE,OAAO,SAAA,KAAc,QAAA,IACrB,SAAA,KAAc,IAAA,IACd,oBAAoB,SAAA,EACpB;AACA,UAAA,eAAA,CAAgB,IAAA,CAAK;AAAA,YACnB,gBAAgB,SAAA,CAAU,cAAA;AAAA,YAC1B,SAAS,SAAA,CAAU;AAAA,WAGpB,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,eAAA,CAAgB,IAAA,CAAK;AAAA,YACnB,cAAA,EAAgB,SAAA;AAAA,YAChB,SAAS,MAAM;AAAA,WAChB,CAAA;AAAA,QACH;AAAA,MACF,CAAA;AAAA,MACA,aAAa,OAAA,EAAS;AACpB,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,QACzD;AACA,QAAA,IAAA,GAAO;AAAA,UACL,MAAM,OAAA,CAAQ,IAAA;AAAA,UACd,MAAM,OAAA,CAAQ;AAAA,SAChB;AAAA,MACF;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,2CAAA,EAA8C,OAAA,CAAQ,QAAQ,CAAA,YAAA,EAAe,QAAQ,QAAQ,CAAA;AAAA,OAC/F;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,aAAA;AAAA,QACN,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,eAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,2BAAA;AAAA,IACR,WAAA,EAAa,eAAA;AAAA,IACb,OAAA,EAAS,IAAA;AAAA,IACT;AAAA,GACF;AACF;;;;"}
@@ -1,15 +1,37 @@
1
1
  'use strict';
2
2
 
3
+ var constants = require('./constants.cjs.js');
4
+
3
5
  function createBackendPlugin(options) {
6
+ if (!constants.ID_PATTERN.test(options.pluginId)) {
7
+ console.warn(
8
+ `WARNING: The pluginId '${options.pluginId}' will be invalid soon, please change it to match the pattern ${constants.ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`
9
+ );
10
+ }
11
+ if (!constants.ID_PATTERN_OLD.test(options.pluginId)) {
12
+ throw new Error(
13
+ `Invalid pluginId '${options.pluginId}', must match the pattern ${constants.ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`
14
+ );
15
+ }
4
16
  function getRegistrations() {
5
17
  const extensionPoints = [];
6
18
  let init = void 0;
7
19
  options.register({
8
- registerExtensionPoint(ext, impl) {
20
+ registerExtensionPoint(extOrOpts, impl) {
9
21
  if (init) {
10
22
  throw new Error("registerExtensionPoint called after registerInit");
11
23
  }
12
- extensionPoints.push([ext, impl]);
24
+ if (typeof extOrOpts === "object" && extOrOpts !== null && "extensionPoint" in extOrOpts) {
25
+ extensionPoints.push({
26
+ extensionPoint: extOrOpts.extensionPoint,
27
+ factory: extOrOpts.factory
28
+ });
29
+ } else {
30
+ extensionPoints.push({
31
+ extensionPoint: extOrOpts,
32
+ factory: () => impl
33
+ });
34
+ }
13
35
  },
14
36
  registerInit(regInit) {
15
37
  if (init) {
@@ -28,7 +50,7 @@ function createBackendPlugin(options) {
28
50
  }
29
51
  return [
30
52
  {
31
- type: "plugin",
53
+ type: "plugin-v1.1",
32
54
  pluginId: options.pluginId,
33
55
  extensionPoints,
34
56
  init
@@ -1 +1 @@
1
- {"version":3,"file":"createBackendPlugin.cjs.js","sources":["../../src/wiring/createBackendPlugin.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';\nimport {\n BackendPluginRegistrationPoints,\n InternalBackendPluginRegistration,\n InternalBackendRegistrations,\n} from './types';\n\n/**\n * The configuration options passed to {@link createBackendPlugin}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendPluginOptions {\n /**\n * The ID of this plugin.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n register(reg: BackendPluginRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendPlugin(\n options: CreateBackendPluginOptions,\n): BackendFeature {\n function getRegistrations() {\n const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] =\n [];\n let init: InternalBackendPluginRegistration['init'] | undefined = undefined;\n\n options.register({\n registerExtensionPoint(ext, impl) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n extensionPoints.push([ext, impl]);\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'plugin',\n pluginId: options.pluginId,\n extensionPoints,\n init,\n },\n ];\n }\n\n return {\n $$type: '@backstage/BackendFeature' as const,\n version: 'v1',\n featureType: 'registrations',\n getRegistrations,\n } as InternalBackendRegistrations;\n}\n"],"names":[],"mappings":";;AA+CO,SAAS,oBACd,OAAA,EACgB;AAChB,EAAA,SAAS,gBAAA,GAAmB;AAC1B,IAAA,MAAM,kBACJ,EAAC;AACH,IAAA,IAAI,IAAA,GAA8D,MAAA;AAElE,IAAA,OAAA,CAAQ,QAAA,CAAS;AAAA,MACf,sBAAA,CAAuB,KAAK,IAAA,EAAM;AAChC,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,QACpE;AACA,QAAA,eAAA,CAAgB,IAAA,CAAK,CAAC,GAAA,EAAK,IAAI,CAAC,CAAA;AAAA,MAClC,CAAA;AAAA,MACA,aAAa,OAAA,EAAS;AACpB,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,QACzD;AACA,QAAA,IAAA,GAAO;AAAA,UACL,MAAM,OAAA,CAAQ,IAAA;AAAA,UACd,MAAM,OAAA,CAAQ;AAAA,SAChB;AAAA,MACF;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,2CAAA,EAA8C,QAAQ,QAAQ,CAAA;AAAA,OAChE;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,eAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,2BAAA;AAAA,IACR,OAAA,EAAS,IAAA;AAAA,IACT,WAAA,EAAa,eAAA;AAAA,IACb;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"createBackendPlugin.cjs.js","sources":["../../src/wiring/createBackendPlugin.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';\nimport {\n BackendPluginRegistrationPoints,\n ExtensionPoint,\n ExtensionPointFactoryContext,\n InternalBackendPluginRegistrationV1_1,\n InternalBackendRegistrations,\n} from './types';\nimport { ID_PATTERN, ID_PATTERN_OLD } from './constants';\n\n/**\n * The configuration options passed to {@link createBackendPlugin}.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport interface CreateBackendPluginOptions {\n /**\n * The ID of this plugin.\n *\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\n pluginId: string;\n register(reg: BackendPluginRegistrationPoints): void;\n}\n\n/**\n * Creates a new backend plugin.\n *\n * @public\n * @see {@link https://backstage.io/docs/backend-system/architecture/plugins | The architecture of plugins}\n * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns}\n */\nexport function createBackendPlugin(\n options: CreateBackendPluginOptions,\n): BackendFeature {\n if (!ID_PATTERN.test(options.pluginId)) {\n console.warn(\n `WARNING: The pluginId '${options.pluginId}' will be invalid soon, please change it to match the pattern ${ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`,\n );\n }\n if (!ID_PATTERN_OLD.test(options.pluginId)) {\n throw new Error(\n `Invalid pluginId '${options.pluginId}', must match the pattern ${ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`,\n );\n }\n\n function getRegistrations() {\n const extensionPoints: InternalBackendPluginRegistrationV1_1['extensionPoints'] =\n [];\n let init: InternalBackendPluginRegistrationV1_1['init'] | undefined =\n undefined;\n\n options.register({\n registerExtensionPoint<TExtensionPoint>(\n extOrOpts:\n | ExtensionPoint<TExtensionPoint>\n | {\n extensionPoint: ExtensionPoint<TExtensionPoint>;\n factory: (\n context: ExtensionPointFactoryContext,\n ) => TExtensionPoint;\n },\n impl?: TExtensionPoint,\n ) {\n if (init) {\n throw new Error('registerExtensionPoint called after registerInit');\n }\n if (\n typeof extOrOpts === 'object' &&\n extOrOpts !== null &&\n 'extensionPoint' in extOrOpts\n ) {\n extensionPoints.push({\n extensionPoint: extOrOpts.extensionPoint,\n factory: extOrOpts.factory as (\n context: ExtensionPointFactoryContext,\n ) => unknown,\n });\n } else {\n extensionPoints.push({\n extensionPoint: extOrOpts,\n factory: () => impl,\n });\n }\n },\n registerInit(regInit) {\n if (init) {\n throw new Error('registerInit must only be called once');\n }\n init = {\n deps: regInit.deps,\n func: regInit.init,\n };\n },\n });\n\n if (!init) {\n throw new Error(\n `registerInit was not called by register in ${options.pluginId}`,\n );\n }\n\n return [\n {\n type: 'plugin-v1.1',\n pluginId: options.pluginId,\n extensionPoints,\n init,\n },\n ];\n }\n\n return {\n $$type: '@backstage/BackendFeature' as const,\n version: 'v1',\n featureType: 'registrations',\n getRegistrations,\n } as InternalBackendRegistrations;\n}\n"],"names":["ID_PATTERN","ID_PATTERN_OLD"],"mappings":";;;;AAkDO,SAAS,oBACd,OAAA,EACgB;AAChB,EAAA,IAAI,CAACA,oBAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACtC,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,CAAA,uBAAA,EAA0B,OAAA,CAAQ,QAAQ,CAAA,8DAAA,EAAiEA,oBAAU,CAAA,2DAAA;AAAA,KACvH;AAAA,EACF;AACA,EAAA,IAAI,CAACC,wBAAA,CAAe,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC1C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,kBAAA,EAAqB,OAAA,CAAQ,QAAQ,CAAA,0BAAA,EAA6BD,oBAAU,CAAA,2DAAA;AAAA,KAC9E;AAAA,EACF;AAEA,EAAA,SAAS,gBAAA,GAAmB;AAC1B,IAAA,MAAM,kBACJ,EAAC;AACH,IAAA,IAAI,IAAA,GACF,MAAA;AAEF,IAAA,OAAA,CAAQ,QAAA,CAAS;AAAA,MACf,sBAAA,CACE,WAQA,IAAA,EACA;AACA,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,QACpE;AACA,QAAA,IACE,OAAO,SAAA,KAAc,QAAA,IACrB,SAAA,KAAc,IAAA,IACd,oBAAoB,SAAA,EACpB;AACA,UAAA,eAAA,CAAgB,IAAA,CAAK;AAAA,YACnB,gBAAgB,SAAA,CAAU,cAAA;AAAA,YAC1B,SAAS,SAAA,CAAU;AAAA,WAGpB,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,eAAA,CAAgB,IAAA,CAAK;AAAA,YACnB,cAAA,EAAgB,SAAA;AAAA,YAChB,SAAS,MAAM;AAAA,WAChB,CAAA;AAAA,QACH;AAAA,MACF,CAAA;AAAA,MACA,aAAa,OAAA,EAAS;AACpB,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,QACzD;AACA,QAAA,IAAA,GAAO;AAAA,UACL,MAAM,OAAA,CAAQ,IAAA;AAAA,UACd,MAAM,OAAA,CAAQ;AAAA,SAChB;AAAA,MACF;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,2CAAA,EAA8C,QAAQ,QAAQ,CAAA;AAAA,OAChE;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,aAAA;AAAA,QACN,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,eAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,2BAAA;AAAA,IACR,OAAA,EAAS,IAAA;AAAA,IACT,WAAA,EAAa,eAAA;AAAA,IACb;AAAA,GACF;AACF;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-plugin-api",
3
- "version": "1.6.2",
3
+ "version": "1.7.0-next.1",
4
4
  "description": "Core API used by Backstage backend plugins",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -65,13 +65,13 @@
65
65
  "test": "backstage-cli package test"
66
66
  },
67
67
  "dependencies": {
68
- "@backstage/cli-common": "^0.1.17",
69
- "@backstage/config": "^1.3.6",
70
- "@backstage/errors": "^1.2.7",
71
- "@backstage/plugin-auth-node": "^0.6.12",
72
- "@backstage/plugin-permission-common": "^0.9.5",
73
- "@backstage/plugin-permission-node": "^0.10.9",
74
- "@backstage/types": "^1.2.2",
68
+ "@backstage/cli-common": "0.1.18-next.0",
69
+ "@backstage/config": "1.3.6",
70
+ "@backstage/errors": "1.2.7",
71
+ "@backstage/plugin-auth-node": "0.6.13-next.0",
72
+ "@backstage/plugin-permission-common": "0.9.6-next.0",
73
+ "@backstage/plugin-permission-node": "0.10.10-next.0",
74
+ "@backstage/types": "1.2.2",
75
75
  "@types/express": "^4.17.6",
76
76
  "@types/json-schema": "^7.0.6",
77
77
  "@types/luxon": "^3.0.0",
@@ -81,8 +81,8 @@
81
81
  "zod": "^3.25.76"
82
82
  },
83
83
  "devDependencies": {
84
- "@backstage/backend-test-utils": "^1.10.4",
85
- "@backstage/cli": "^0.35.3"
84
+ "@backstage/backend-test-utils": "1.10.5-next.0",
85
+ "@backstage/cli": "0.35.4-next.1"
86
86
  },
87
87
  "configSchema": "config.d.ts"
88
88
  }