@backstage/backend-plugin-api 1.9.2-next.0 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @backstage/backend-plugin-api
2
2
 
3
+ ## 1.9.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 02c4e8a: Removed unused `json-schema` runtime dependency. The package was only used for TypeScript types from `@types/json-schema`; affected imports have been converted to `import type` to allow safe removal.
8
+ - 0211390: Added optional `secrets` schema support to `ActionsRegistryActionOptions` and `ActionsRegistryActionContext`. Actions can now declare a Zod secrets schema separate from the input schema, enabling surfaces to collect sensitive credentials independently from tool arguments. Added optional `secrets` field to `ActionsServiceAction` metadata and `ActionsService.invoke()` parameters.
9
+ - Updated dependencies
10
+ - @backstage/plugin-auth-node@0.7.2
11
+ - @backstage/plugin-permission-node@0.11.1
12
+
13
+ ## 1.9.2-next.1
14
+
15
+ ### Patch Changes
16
+
17
+ - 0211390: Added optional `secrets` schema support to `ActionsRegistryActionOptions` and `ActionsRegistryActionContext`. Actions can now declare a Zod secrets schema separate from the input schema, enabling surfaces to collect sensitive credentials independently from tool arguments. Added optional `secrets` field to `ActionsServiceAction` metadata and `ActionsService.invoke()` parameters.
18
+
3
19
  ## 1.9.2-next.0
4
20
 
5
21
  ### Patch Changes
package/dist/alpha.d.ts CHANGED
@@ -5,6 +5,7 @@ import { LoggerService, BackstageCredentials } from '@backstage/backend-plugin-a
5
5
  import { JsonObject, JsonValue } from '@backstage/types';
6
6
  import { JSONSchema7 } from 'json-schema';
7
7
  import { Request } from 'express';
8
+ export { C as ConnectionRegistration } from './types/types.d-BJ6KGQ77.js';
8
9
 
9
10
  /** @public */
10
11
  interface RootSystemMetadataServicePluginInfo {
@@ -18,8 +19,9 @@ interface RootSystemMetadataService {
18
19
  /**
19
20
  * @alpha
20
21
  */
21
- type ActionsRegistryActionContext<TInputSchema extends AnyZodObject> = {
22
+ type ActionsRegistryActionContext<TInputSchema extends AnyZodObject, TSecretsSchema extends AnyZodObject | undefined = undefined> = {
22
23
  input: z.infer<TInputSchema>;
24
+ secrets: TSecretsSchema extends AnyZodObject ? z.infer<TSecretsSchema> : undefined;
23
25
  logger: LoggerService;
24
26
  credentials: BackstageCredentials;
25
27
  };
@@ -37,13 +39,14 @@ type ActionsRegistryActionExample<TInputSchema extends AnyZodObject, TOutputSche
37
39
  /**
38
40
  * @alpha
39
41
  */
40
- type ActionsRegistryActionOptions<TInputSchema extends AnyZodObject, TOutputSchema extends AnyZodObject> = {
42
+ type ActionsRegistryActionOptions<TInputSchema extends AnyZodObject, TOutputSchema extends AnyZodObject, TSecretsSchema extends AnyZodObject | undefined = undefined> = {
41
43
  name: string;
42
44
  title: string;
43
45
  description: string;
44
46
  schema: {
45
47
  input: (zod: typeof z) => TInputSchema;
46
48
  output: (zod: typeof z) => TOutputSchema;
49
+ secrets?: (zod: typeof z) => TSecretsSchema extends AnyZodObject ? TSecretsSchema : never;
47
50
  };
48
51
  examples?: Array<ActionsRegistryActionExample<TInputSchema, TOutputSchema>>;
49
52
  visibilityPermission?: BasicPermission;
@@ -52,7 +55,7 @@ type ActionsRegistryActionOptions<TInputSchema extends AnyZodObject, TOutputSche
52
55
  idempotent?: boolean;
53
56
  readOnly?: boolean;
54
57
  };
55
- action: (context: ActionsRegistryActionContext<TInputSchema>) => Promise<z.infer<TOutputSchema> extends void ? void : {
58
+ action: (context: ActionsRegistryActionContext<TInputSchema, TSecretsSchema>) => Promise<z.infer<TOutputSchema> extends void ? void : {
56
59
  output: z.infer<TOutputSchema>;
57
60
  }>;
58
61
  };
@@ -60,7 +63,7 @@ type ActionsRegistryActionOptions<TInputSchema extends AnyZodObject, TOutputSche
60
63
  * @alpha
61
64
  */
62
65
  interface ActionsRegistryService {
63
- register<TInputSchema extends AnyZodObject, TOutputSchema extends AnyZodObject>(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void;
66
+ register<TInputSchema extends AnyZodObject, TOutputSchema extends AnyZodObject, TSecretsSchema extends AnyZodObject | undefined = undefined>(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema, TSecretsSchema>): void;
64
67
  }
65
68
 
66
69
  /**
@@ -75,6 +78,7 @@ type ActionsServiceAction = {
75
78
  schema: {
76
79
  input: JSONSchema7;
77
80
  output: JSONSchema7;
81
+ secrets?: JSONSchema7;
78
82
  };
79
83
  examples?: Array<{
80
84
  title: string;
@@ -100,6 +104,7 @@ interface ActionsService {
100
104
  invoke(opts: {
101
105
  id: string;
102
106
  input?: JsonObject;
107
+ secrets?: JsonObject;
103
108
  credentials: BackstageCredentials;
104
109
  }): Promise<{
105
110
  output: JsonValue;
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ import { PermissionRule, PermissionResourceRef, PermissionRuleset } from '@backs
6
6
  import { Config } from '@backstage/config';
7
7
  import { Duration } from 'luxon';
8
8
  import { Readable } from 'node:stream';
9
+ import { d as ServiceRef, a as BackendModuleRegistrationPoints, B as BackendFeature, b as BackendPluginRegistrationPoints, E as ExtensionPoint } from './types/types.d-BJ6KGQ77.js';
10
+ export { c as ExtensionPointFactoryContext, P as PluginServiceFactoryOptions, R as RootServiceFactoryOptions, S as ServiceFactory, e as ServiceRefOptions, f as createServiceFactory, g as createServiceRef } from './types/types.d-BJ6KGQ77.js';
9
11
  export { isChildPath } from '@backstage/cli-common';
10
12
 
11
13
  /**
@@ -1732,142 +1734,6 @@ declare namespace coreServices {
1732
1734
  const rootInstanceMetadata: ServiceRef<RootInstanceMetadataService, "root", "singleton">;
1733
1735
  }
1734
1736
 
1735
- /** @public */
1736
- interface BackendFeature {
1737
- $$type: '@backstage/BackendFeature';
1738
- }
1739
-
1740
- /**
1741
- * A reference to a backend service. You can use these references to mark
1742
- * dependencies on services and having their implementations injected
1743
- * automatically.
1744
- *
1745
- * @public
1746
- */
1747
- type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'root' | 'plugin', TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton'> = {
1748
- id: string;
1749
- /**
1750
- * This determines the scope at which this service is available.
1751
- *
1752
- * Root scoped services are available to all other services but
1753
- * may only depend on other root scoped services.
1754
- *
1755
- * Plugin scoped services are only available to other plugin scoped
1756
- * services but may depend on all other services.
1757
- */
1758
- scope: TScope;
1759
- /**
1760
- * Marks whether the service is a multiton or not. Multiton services the
1761
- * opposite of singletons - they can be provided many times, and when depended
1762
- * on, you receive an array of all provided instances.
1763
- */
1764
- multiton?: TInstances extends 'multiton' ? true : false;
1765
- /**
1766
- * Utility for getting the type of the service, using `typeof serviceRef.T`.
1767
- * Reading this value will always return `null`. It is only intended for use with `typeof serviceRef.T`.
1768
- */
1769
- T: TService;
1770
- $$type: '@backstage/ServiceRef';
1771
- };
1772
- /** @public */
1773
- interface ServiceFactory<TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root', TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton'> extends BackendFeature {
1774
- service: ServiceRef<TService, TScope, TInstances>;
1775
- }
1776
- /** @public */
1777
- interface ServiceRefOptions<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton'> {
1778
- id: string;
1779
- scope?: TScope;
1780
- multiton?: TInstances extends 'multiton' ? true : false;
1781
- defaultFactory?(service: ServiceRef<TService, TScope>): Promise<ServiceFactory>;
1782
- }
1783
- /**
1784
- * Creates a new service definition. This overload is used to create plugin scoped services.
1785
- *
1786
- * @public
1787
- */
1788
- declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'plugin', 'singleton'>): ServiceRef<TService, 'plugin', 'singleton'>;
1789
- /**
1790
- * Creates a new service definition. This overload is used to create root scoped services.
1791
- *
1792
- * @public
1793
- */
1794
- declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'root', 'singleton'>): ServiceRef<TService, 'root', 'singleton'>;
1795
- /**
1796
- * Creates a new service definition. This overload is used to create plugin scoped services.
1797
- *
1798
- * @public
1799
- */
1800
- declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'plugin', 'multiton'>): ServiceRef<TService, 'plugin', 'multiton'>;
1801
- /**
1802
- * Creates a new service definition. This overload is used to create root scoped services.
1803
- *
1804
- * @public
1805
- */
1806
- declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'root', 'multiton'>): ServiceRef<TService, 'root', 'multiton'>;
1807
- /** @ignore */
1808
- type ServiceRefsToInstances<T extends {
1809
- [key in string]: ServiceRef<unknown>;
1810
- }, TScope extends 'root' | 'plugin' = 'root' | 'plugin'> = {
1811
- [key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['multiton'] extends true | undefined ? Array<T[key]['T']> : T[key]['T'];
1812
- };
1813
- /** @public */
1814
- interface RootServiceFactoryOptions<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1815
- [name in string]: ServiceRef<unknown>;
1816
- }> {
1817
- /**
1818
- * The initialization strategy for the service factory. This service is root scoped and will use `always` by default.
1819
- *
1820
- * @remarks
1821
- *
1822
- * - `always` - The service will always be initialized regardless if it is used or not.
1823
- * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.
1824
- *
1825
- * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.
1826
- */
1827
- initialization?: 'always' | 'lazy';
1828
- service: ServiceRef<TService, 'root', TInstances>;
1829
- deps: TDeps;
1830
- factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;
1831
- }
1832
- /** @public */
1833
- interface PluginServiceFactoryOptions<TService, TInstances extends 'singleton' | 'multiton', TContext, TImpl extends TService, TDeps extends {
1834
- [name in string]: ServiceRef<unknown>;
1835
- }> {
1836
- /**
1837
- * The initialization strategy for the service factory. This service is plugin scoped and will use `lazy` by default.
1838
- *
1839
- * @remarks
1840
- *
1841
- * - `always` - The service will always be initialized regardless if it is used or not.
1842
- * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.
1843
- *
1844
- * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.
1845
- */
1846
- initialization?: 'always' | 'lazy';
1847
- service: ServiceRef<TService, 'plugin', TInstances>;
1848
- deps: TDeps;
1849
- createRootContext?(deps: ServiceRefsToInstances<TDeps, 'root'>): TContext | Promise<TContext>;
1850
- factory(deps: ServiceRefsToInstances<TDeps>, context: TContext): TImpl | Promise<TImpl>;
1851
- }
1852
- /**
1853
- * Creates a root scoped service factory without options.
1854
- *
1855
- * @public
1856
- * @param options - The service factory configuration.
1857
- */
1858
- declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1859
- [name in string]: ServiceRef<unknown, 'root'>;
1860
- }>(options: RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>): ServiceFactory<TService, 'root', TInstances>;
1861
- /**
1862
- * Creates a plugin scoped service factory without options.
1863
- *
1864
- * @public
1865
- * @param options - The service factory configuration.
1866
- */
1867
- declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
1868
- [name in string]: ServiceRef<unknown>;
1869
- }, TContext = undefined>(options: PluginServiceFactoryOptions<TService, TInstances, TContext, TImpl, TDeps>): ServiceFactory<TService, 'plugin', TInstances>;
1870
-
1871
1737
  /**
1872
1738
  * Tries to deduce whether a thrown error is a database conflict.
1873
1739
  *
@@ -1901,85 +1767,6 @@ declare function resolvePackagePath(name: string, ...paths: string[]): string;
1901
1767
  */
1902
1768
  declare function resolveSafeChildPath(base: string, path: string): string;
1903
1769
 
1904
- /**
1905
- * TODO
1906
- *
1907
- * @public
1908
- */
1909
- type ExtensionPoint<T> = {
1910
- id: string;
1911
- /**
1912
- * Utility for getting the type of the extension point, using `typeof extensionPoint.T`.
1913
- * Reading this value will always return `null`. It is only intended for use with `typeof extensionPoint.T`.
1914
- */
1915
- T: T;
1916
- toString(): string;
1917
- $$type: '@backstage/ExtensionPoint';
1918
- };
1919
- /**
1920
- * Context provided to extension point factories.
1921
- *
1922
- * @public
1923
- */
1924
- interface ExtensionPointFactoryContext {
1925
- /**
1926
- * Report a startup failure that happened as part of using an extension that
1927
- * the module provided. This should be called before the plugin's `init`
1928
- * function returns.
1929
- */
1930
- reportModuleStartupFailure(options: {
1931
- error: Error;
1932
- }): void;
1933
- }
1934
- /** @ignore */
1935
- type DepsToInstances<TDeps extends {
1936
- [key in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
1937
- }> = {
1938
- [key in keyof TDeps]: TDeps[key] extends ServiceRef<unknown, 'root' | 'plugin', 'multiton'> ? Array<TDeps[key]['T']> : TDeps[key]['T'];
1939
- };
1940
- /**
1941
- * The callbacks passed to the `register` method of a backend plugin.
1942
- *
1943
- * @public
1944
- */
1945
- interface BackendPluginRegistrationPoints {
1946
- /**
1947
- * Registers an implementation for an extension point.
1948
- */
1949
- registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
1950
- /**
1951
- * Registers a factory that produces a separate implementation for an extension point for each module.
1952
- */
1953
- registerExtensionPoint<TExtensionPoint>(options: {
1954
- extensionPoint: ExtensionPoint<TExtensionPoint>;
1955
- factory: (context: ExtensionPointFactoryContext) => TExtensionPoint;
1956
- }): void;
1957
- registerInit<TDeps extends {
1958
- [name in string]: ServiceRef<unknown>;
1959
- }>(options: {
1960
- deps: TDeps;
1961
- init(deps: DepsToInstances<TDeps>): Promise<void>;
1962
- }): void;
1963
- }
1964
- /**
1965
- * The callbacks passed to the `register` method of a backend module.
1966
- *
1967
- * @public
1968
- */
1969
- interface BackendModuleRegistrationPoints {
1970
- registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
1971
- registerExtensionPoint<TExtensionPoint>(options: {
1972
- extensionPoint: ExtensionPoint<TExtensionPoint>;
1973
- factory: (context: ExtensionPointFactoryContext) => TExtensionPoint;
1974
- }): void;
1975
- registerInit<TDeps extends {
1976
- [name in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
1977
- }>(options: {
1978
- deps: TDeps;
1979
- init(deps: DepsToInstances<TDeps>): Promise<void>;
1980
- }): void;
1981
- }
1982
-
1983
1770
  /**
1984
1771
  * The configuration options passed to {@link createBackendModule}.
1985
1772
  *
@@ -2083,5 +1870,5 @@ declare function createBackendFeatureLoader<TDeps extends {
2083
1870
  [name in string]: unknown;
2084
1871
  }>(options: CreateBackendFeatureLoaderOptions<TDeps>): BackendFeature;
2085
1872
 
2086
- export { coreServices, createBackendFeatureLoader, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };
2087
- 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 };
1873
+ export { BackendFeature, BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, ExtensionPoint, ServiceRef, coreServices, createBackendFeatureLoader, createBackendModule, createBackendPlugin, createExtensionPoint, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };
1874
+ export type { AuditorService, AuditorServiceCreateEventOptions, AuditorServiceEvent, AuditorServiceEventSeverityLevel, AuthService, BackstageCredentials, BackstageNonePrincipal, BackstagePrincipalAccessRestrictions, BackstagePrincipalTypes, BackstageServicePrincipal, BackstageUserInfo, BackstageUserPrincipal, CacheService, CacheServiceOptions, CacheServiceSetOptions, CreateBackendFeatureLoaderOptions, CreateBackendModuleOptions, CreateBackendPluginOptions, CreateExtensionPointOptions, DatabaseService, DiscoveryService, HttpAuthService, HttpRouterService, HttpRouterServiceAuthPolicy, LifecycleService, LifecycleServiceShutdownHook, LifecycleServiceShutdownOptions, LifecycleServiceStartupHook, LifecycleServiceStartupOptions, LoggerService, PermissionsRegistryService, PermissionsRegistryServiceAddResourceTypeOptions, PermissionsService, PermissionsServiceRequestOptions, PluginMetadataService, RootConfigService, RootHealthService, RootHttpRouterService, RootInstanceMetadataService, RootInstanceMetadataServicePluginInfo, RootLifecycleService, RootLoggerService, SchedulerService, SchedulerServiceTaskDescriptor, SchedulerServiceTaskFunction, SchedulerServiceTaskInvocationDefinition, SchedulerServiceTaskRunner, SchedulerServiceTaskScheduleDefinition, SchedulerServiceTaskScheduleDefinitionConfig, UrlReaderService, UrlReaderServiceReadTreeOptions, UrlReaderServiceReadTreeResponse, UrlReaderServiceReadTreeResponseDirOptions, UrlReaderServiceReadTreeResponseFile, UrlReaderServiceReadUrlOptions, UrlReaderServiceReadUrlResponse, UrlReaderServiceSearchOptions, UrlReaderServiceSearchResponse, UrlReaderServiceSearchResponseFile, UserInfoService };
@@ -0,0 +1,240 @@
1
+ /** @public */
2
+ interface BackendFeature {
3
+ $$type: '@backstage/BackendFeature';
4
+ }
5
+
6
+ /**
7
+ * A reference to a backend service. You can use these references to mark
8
+ * dependencies on services and having their implementations injected
9
+ * automatically.
10
+ *
11
+ * @public
12
+ */
13
+ type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'root' | 'plugin', TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton'> = {
14
+ id: string;
15
+ /**
16
+ * This determines the scope at which this service is available.
17
+ *
18
+ * Root scoped services are available to all other services but
19
+ * may only depend on other root scoped services.
20
+ *
21
+ * Plugin scoped services are only available to other plugin scoped
22
+ * services but may depend on all other services.
23
+ */
24
+ scope: TScope;
25
+ /**
26
+ * Marks whether the service is a multiton or not. Multiton services the
27
+ * opposite of singletons - they can be provided many times, and when depended
28
+ * on, you receive an array of all provided instances.
29
+ */
30
+ multiton?: TInstances extends 'multiton' ? true : false;
31
+ /**
32
+ * Utility for getting the type of the service, using `typeof serviceRef.T`.
33
+ * Reading this value will always return `null`. It is only intended for use with `typeof serviceRef.T`.
34
+ */
35
+ T: TService;
36
+ $$type: '@backstage/ServiceRef';
37
+ };
38
+ /** @public */
39
+ interface ServiceFactory<TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root', TInstances extends 'singleton' | 'multiton' = 'singleton' | 'multiton'> extends BackendFeature {
40
+ service: ServiceRef<TService, TScope, TInstances>;
41
+ }
42
+ /** @public */
43
+ interface ServiceRefOptions<TService, TScope extends 'root' | 'plugin', TInstances extends 'singleton' | 'multiton'> {
44
+ id: string;
45
+ scope?: TScope;
46
+ multiton?: TInstances extends 'multiton' ? true : false;
47
+ defaultFactory?(service: ServiceRef<TService, TScope>): Promise<ServiceFactory>;
48
+ }
49
+ /**
50
+ * Creates a new service definition. This overload is used to create plugin scoped services.
51
+ *
52
+ * @public
53
+ */
54
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'plugin', 'singleton'>): ServiceRef<TService, 'plugin', 'singleton'>;
55
+ /**
56
+ * Creates a new service definition. This overload is used to create root scoped services.
57
+ *
58
+ * @public
59
+ */
60
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'root', 'singleton'>): ServiceRef<TService, 'root', 'singleton'>;
61
+ /**
62
+ * Creates a new service definition. This overload is used to create plugin scoped services.
63
+ *
64
+ * @public
65
+ */
66
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'plugin', 'multiton'>): ServiceRef<TService, 'plugin', 'multiton'>;
67
+ /**
68
+ * Creates a new service definition. This overload is used to create root scoped services.
69
+ *
70
+ * @public
71
+ */
72
+ declare function createServiceRef<TService>(options: ServiceRefOptions<TService, 'root', 'multiton'>): ServiceRef<TService, 'root', 'multiton'>;
73
+ /** @ignore */
74
+ type ServiceRefsToInstances<T extends {
75
+ [key in string]: ServiceRef<unknown>;
76
+ }, TScope extends 'root' | 'plugin' = 'root' | 'plugin'> = {
77
+ [key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['multiton'] extends true | undefined ? Array<T[key]['T']> : T[key]['T'];
78
+ };
79
+ /** @public */
80
+ interface RootServiceFactoryOptions<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
81
+ [name in string]: ServiceRef<unknown>;
82
+ }> {
83
+ /**
84
+ * The initialization strategy for the service factory. This service is root scoped and will use `always` by default.
85
+ *
86
+ * @remarks
87
+ *
88
+ * - `always` - The service will always be initialized regardless if it is used or not.
89
+ * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.
90
+ *
91
+ * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.
92
+ */
93
+ initialization?: 'always' | 'lazy';
94
+ service: ServiceRef<TService, 'root', TInstances>;
95
+ deps: TDeps;
96
+ factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;
97
+ }
98
+ /** @public */
99
+ interface PluginServiceFactoryOptions<TService, TInstances extends 'singleton' | 'multiton', TContext, TImpl extends TService, TDeps extends {
100
+ [name in string]: ServiceRef<unknown>;
101
+ }> {
102
+ /**
103
+ * The initialization strategy for the service factory. This service is plugin scoped and will use `lazy` by default.
104
+ *
105
+ * @remarks
106
+ *
107
+ * - `always` - The service will always be initialized regardless if it is used or not.
108
+ * - `lazy` - The service will only be initialized if it is depended on by a different service or feature.
109
+ *
110
+ * Service factories for root scoped services use `always` as the default, while plugin scoped services use `lazy`.
111
+ */
112
+ initialization?: 'always' | 'lazy';
113
+ service: ServiceRef<TService, 'plugin', TInstances>;
114
+ deps: TDeps;
115
+ createRootContext?(deps: ServiceRefsToInstances<TDeps, 'root'>): TContext | Promise<TContext>;
116
+ factory(deps: ServiceRefsToInstances<TDeps>, context: TContext): TImpl | Promise<TImpl>;
117
+ }
118
+ /**
119
+ * Creates a root scoped service factory without options.
120
+ *
121
+ * @public
122
+ * @param options - The service factory configuration.
123
+ */
124
+ declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
125
+ [name in string]: ServiceRef<unknown, 'root'>;
126
+ }>(options: RootServiceFactoryOptions<TService, TInstances, TImpl, TDeps>): ServiceFactory<TService, 'root', TInstances>;
127
+ /**
128
+ * Creates a plugin scoped service factory without options.
129
+ *
130
+ * @public
131
+ * @param options - The service factory configuration.
132
+ */
133
+ declare function createServiceFactory<TService, TInstances extends 'singleton' | 'multiton', TImpl extends TService, TDeps extends {
134
+ [name in string]: ServiceRef<unknown>;
135
+ }, TContext = undefined>(options: PluginServiceFactoryOptions<TService, TInstances, TContext, TImpl, TDeps>): ServiceFactory<TService, 'plugin', TInstances>;
136
+
137
+ /**
138
+ * TODO
139
+ *
140
+ * @public
141
+ */
142
+ type ExtensionPoint<T> = {
143
+ id: string;
144
+ /**
145
+ * Utility for getting the type of the extension point, using `typeof extensionPoint.T`.
146
+ * Reading this value will always return `null`. It is only intended for use with `typeof extensionPoint.T`.
147
+ */
148
+ T: T;
149
+ toString(): string;
150
+ $$type: '@backstage/ExtensionPoint';
151
+ };
152
+ /**
153
+ * Context provided to extension point factories.
154
+ *
155
+ * @public
156
+ */
157
+ interface ExtensionPointFactoryContext {
158
+ /**
159
+ * Report a startup failure that happened as part of using an extension that
160
+ * the module provided. This should be called before the plugin's `init`
161
+ * function returns.
162
+ */
163
+ reportModuleStartupFailure(options: {
164
+ error: Error;
165
+ }): void;
166
+ }
167
+ /** @ignore */
168
+ type DepsToInstances<TDeps extends {
169
+ [key in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
170
+ }> = {
171
+ [key in keyof TDeps]: TDeps[key] extends ServiceRef<unknown, 'root' | 'plugin', 'multiton'> ? Array<TDeps[key]['T']> : TDeps[key]['T'];
172
+ };
173
+ /**
174
+ * Declares that a plugin or module consumes a particular connection type.
175
+ *
176
+ * @alpha
177
+ */
178
+ interface ConnectionRegistration {
179
+ /**
180
+ * The connection type identifier, matching the `type` field in connections
181
+ * config and in calls to `find` / `findOptional` on the connections service.
182
+ */
183
+ type: string;
184
+ /**
185
+ * Whether the connection is essential for the plugin or module to function.
186
+ * If true, the backend will fail to start if no matching connection is
187
+ * configured. Defaults to false.
188
+ */
189
+ required?: boolean;
190
+ /**
191
+ * Human-readable explanation of why the plugin or module needs this
192
+ * connection type. Surfaced in tooling and startup diagnostics.
193
+ */
194
+ description?: string;
195
+ }
196
+ /**
197
+ * The callbacks passed to the `register` method of a backend plugin.
198
+ *
199
+ * @public
200
+ */
201
+ interface BackendPluginRegistrationPoints {
202
+ /**
203
+ * Registers an implementation for an extension point.
204
+ */
205
+ registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
206
+ /**
207
+ * Registers a factory that produces a separate implementation for an extension point for each module.
208
+ */
209
+ registerExtensionPoint<TExtensionPoint>(options: {
210
+ extensionPoint: ExtensionPoint<TExtensionPoint>;
211
+ factory: (context: ExtensionPointFactoryContext) => TExtensionPoint;
212
+ }): void;
213
+ registerInit<TDeps extends {
214
+ [name in string]: ServiceRef<unknown>;
215
+ }>(options: {
216
+ deps: TDeps;
217
+ init(deps: DepsToInstances<TDeps>): Promise<void>;
218
+ }): void;
219
+ }
220
+ /**
221
+ * The callbacks passed to the `register` method of a backend module.
222
+ *
223
+ * @public
224
+ */
225
+ interface BackendModuleRegistrationPoints {
226
+ registerExtensionPoint<TExtensionPoint>(ref: ExtensionPoint<TExtensionPoint>, impl: TExtensionPoint): void;
227
+ registerExtensionPoint<TExtensionPoint>(options: {
228
+ extensionPoint: ExtensionPoint<TExtensionPoint>;
229
+ factory: (context: ExtensionPointFactoryContext) => TExtensionPoint;
230
+ }): void;
231
+ registerInit<TDeps extends {
232
+ [name in string]: ServiceRef<unknown> | ExtensionPoint<unknown>;
233
+ }>(options: {
234
+ deps: TDeps;
235
+ init(deps: DepsToInstances<TDeps>): Promise<void>;
236
+ }): void;
237
+ }
238
+
239
+ export { createServiceFactory as f, createServiceRef as g };
240
+ export type { BackendFeature as B, ConnectionRegistration as C, ExtensionPoint as E, PluginServiceFactoryOptions as P, RootServiceFactoryOptions as R, ServiceFactory as S, BackendModuleRegistrationPoints as a, BackendPluginRegistrationPoints as b, ExtensionPointFactoryContext as c, ServiceRef as d, ServiceRefOptions as e };
@@ -15,8 +15,9 @@ function createBackendModule(options) {
15
15
  }
16
16
  function getRegistrations() {
17
17
  const extensionPoints = [];
18
+ const connections = [];
18
19
  let init = void 0;
19
- options.register({
20
+ const reg = {
20
21
  registerExtensionPoint(extOrOpts, impl) {
21
22
  if (init) {
22
23
  throw new Error("registerExtensionPoint called after registerInit");
@@ -33,6 +34,17 @@ function createBackendModule(options) {
33
34
  });
34
35
  }
35
36
  },
37
+ registerConnection(registration) {
38
+ if (init) {
39
+ throw new Error("registerConnection called after registerInit");
40
+ }
41
+ if (connections.some((c) => c.type === registration.type)) {
42
+ throw new Error(
43
+ `Duplicate connection registration for type '${registration.type}' in module '${options.moduleId}' for plugin '${options.pluginId}'`
44
+ );
45
+ }
46
+ connections.push({ ...registration });
47
+ },
36
48
  registerInit(regInit) {
37
49
  if (init) {
38
50
  throw new Error("registerInit must only be called once");
@@ -42,7 +54,8 @@ function createBackendModule(options) {
42
54
  func: regInit.init
43
55
  };
44
56
  }
45
- });
57
+ };
58
+ options.register(reg);
46
59
  if (!init) {
47
60
  throw new Error(
48
61
  `registerInit was not called by register in ${options.moduleId} module for ${options.pluginId}`
@@ -54,6 +67,7 @@ function createBackendModule(options) {
54
67
  pluginId: options.pluginId,
55
68
  moduleId: options.moduleId,
56
69
  extensionPoints,
70
+ connections,
57
71
  init
58
72
  }
59
73
  ];
@@ -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 { 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
+ {"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 ConnectionRegistration,\n ExtensionPoint,\n ExtensionPointFactoryContext,\n InternalBackendModuleRegistrationPoints,\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 const connections: ConnectionRegistration[] = [];\n let init: InternalBackendModuleRegistrationV1_1['init'] | undefined =\n undefined;\n\n const reg: InternalBackendModuleRegistrationPoints = {\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 registerConnection(registration) {\n if (init) {\n throw new Error('registerConnection called after registerInit');\n }\n if (connections.some(c => c.type === registration.type)) {\n throw new Error(\n `Duplicate connection registration for type '${registration.type}' in module '${options.moduleId}' for plugin '${options.pluginId}'`,\n );\n }\n connections.push({ ...registration });\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 options.register(reg);\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 connections,\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":";;;;AAyDO,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,MAAM,cAAwC,EAAC;AAC/C,IAAA,IAAI,IAAA,GACF,MAAA;AAEF,IAAA,MAAM,GAAA,GAA+C;AAAA,MACnD,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,mBAAmB,YAAA,EAAc;AAC/B,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,QAChE;AACA,QAAA,IAAI,YAAY,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,YAAA,CAAa,IAAI,CAAA,EAAG;AACvD,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,4CAAA,EAA+C,aAAa,IAAI,CAAA,aAAA,EAAgB,QAAQ,QAAQ,CAAA,cAAA,EAAiB,QAAQ,QAAQ,CAAA,CAAA;AAAA,WACnI;AAAA,QACF;AACA,QAAA,WAAA,CAAY,IAAA,CAAK,EAAE,GAAG,YAAA,EAAc,CAAA;AAAA,MACtC,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,KACF;AACA,IAAA,OAAA,CAAQ,SAAS,GAAG,CAAA;AAEpB,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,WAAA;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;;;;"}
@@ -15,8 +15,9 @@ function createBackendPlugin(options) {
15
15
  }
16
16
  function getRegistrations() {
17
17
  const extensionPoints = [];
18
+ const connections = [];
18
19
  let init = void 0;
19
- options.register({
20
+ const reg = {
20
21
  registerExtensionPoint(extOrOpts, impl) {
21
22
  if (init) {
22
23
  throw new Error("registerExtensionPoint called after registerInit");
@@ -33,6 +34,17 @@ function createBackendPlugin(options) {
33
34
  });
34
35
  }
35
36
  },
37
+ registerConnection(registration) {
38
+ if (init) {
39
+ throw new Error("registerConnection called after registerInit");
40
+ }
41
+ if (connections.some((c) => c.type === registration.type)) {
42
+ throw new Error(
43
+ `Duplicate connection registration for type '${registration.type}' in plugin '${options.pluginId}'`
44
+ );
45
+ }
46
+ connections.push({ ...registration });
47
+ },
36
48
  registerInit(regInit) {
37
49
  if (init) {
38
50
  throw new Error("registerInit must only be called once");
@@ -42,7 +54,8 @@ function createBackendPlugin(options) {
42
54
  func: regInit.init
43
55
  };
44
56
  }
45
- });
57
+ };
58
+ options.register(reg);
46
59
  if (!init) {
47
60
  throw new Error(
48
61
  `registerInit was not called by register in ${options.pluginId}`
@@ -53,6 +66,7 @@ function createBackendPlugin(options) {
53
66
  type: "plugin-v1.1",
54
67
  pluginId: options.pluginId,
55
68
  extensionPoints,
69
+ connections,
56
70
  init
57
71
  }
58
72
  ];
@@ -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 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;;;;"}
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 ConnectionRegistration,\n ExtensionPoint,\n ExtensionPointFactoryContext,\n InternalBackendPluginRegistrationPoints,\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 const connections: ConnectionRegistration[] = [];\n let init: InternalBackendPluginRegistrationV1_1['init'] | undefined =\n undefined;\n\n const reg: InternalBackendPluginRegistrationPoints = {\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 registerConnection(registration) {\n if (init) {\n throw new Error('registerConnection called after registerInit');\n }\n if (connections.some(c => c.type === registration.type)) {\n throw new Error(\n `Duplicate connection registration for type '${registration.type}' in plugin '${options.pluginId}'`,\n );\n }\n connections.push({ ...registration });\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 options.register(reg);\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 connections,\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":";;;;AAoDO,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,MAAM,cAAwC,EAAC;AAC/C,IAAA,IAAI,IAAA,GACF,MAAA;AAEF,IAAA,MAAM,GAAA,GAA+C;AAAA,MACnD,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,mBAAmB,YAAA,EAAc;AAC/B,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,QAChE;AACA,QAAA,IAAI,YAAY,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,YAAA,CAAa,IAAI,CAAA,EAAG;AACvD,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,4CAAA,EAA+C,YAAA,CAAa,IAAI,CAAA,aAAA,EAAgB,QAAQ,QAAQ,CAAA,CAAA;AAAA,WAClG;AAAA,QACF;AACA,QAAA,WAAA,CAAY,IAAA,CAAK,EAAE,GAAG,YAAA,EAAc,CAAA;AAAA,MACtC,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,KACF;AACA,IAAA,OAAA,CAAQ,SAAS,GAAG,CAAA;AAEpB,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,WAAA;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.9.2-next.0",
3
+ "version": "1.9.2",
4
4
  "description": "Core API used by Backstage backend plugins",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -65,24 +65,23 @@
65
65
  "test": "backstage-cli package test"
66
66
  },
67
67
  "dependencies": {
68
- "@backstage/cli-common": "0.2.2",
69
- "@backstage/config": "1.3.8",
70
- "@backstage/errors": "1.3.1",
71
- "@backstage/plugin-auth-node": "0.7.2-next.0",
72
- "@backstage/plugin-permission-common": "0.9.9",
73
- "@backstage/plugin-permission-node": "0.11.1-next.0",
74
- "@backstage/types": "1.2.2",
68
+ "@backstage/cli-common": "^0.2.2",
69
+ "@backstage/config": "^1.3.8",
70
+ "@backstage/errors": "^1.3.1",
71
+ "@backstage/plugin-auth-node": "^0.7.2",
72
+ "@backstage/plugin-permission-common": "^0.9.9",
73
+ "@backstage/plugin-permission-node": "^0.11.1",
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",
78
- "json-schema": "^0.4.0",
79
78
  "knex": "^3.0.0",
80
79
  "luxon": "^3.0.0",
81
80
  "zod": "^3.25.76 || ^4.0.0"
82
81
  },
83
82
  "devDependencies": {
84
- "@backstage/backend-test-utils": "1.11.4-next.0",
85
- "@backstage/cli": "0.36.3-next.0"
83
+ "@backstage/backend-test-utils": "^1.11.4",
84
+ "@backstage/cli": "^0.36.3"
86
85
  },
87
86
  "configSchema": "config.d.ts"
88
87
  }