@backstage/backend-plugin-api 0.2.1-next.0 → 0.3.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/dist/index.d.ts CHANGED
@@ -8,15 +8,11 @@
8
8
 
9
9
  import { Config } from '@backstage/config';
10
10
  import { Handler } from 'express';
11
- import { Logger } from 'winston';
12
- import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
11
+ import { JsonValue } from '@backstage/types';
12
+ import { Knex } from 'knex';
13
13
  import { PermissionEvaluator } from '@backstage/plugin-permission-common';
14
- import { PluginCacheManager } from '@backstage/backend-common';
15
- import { PluginDatabaseManager } from '@backstage/backend-common';
16
14
  import { PluginTaskScheduler } from '@backstage/backend-tasks';
17
15
  import { Readable } from 'stream';
18
- import { TokenManager } from '@backstage/backend-common';
19
- import { TransportStreamOptions } from 'winston-transport';
20
16
 
21
17
  /** @public */
22
18
  export declare interface BackendFeature {
@@ -50,49 +46,186 @@ export declare interface BackendRegistrationPoints {
50
46
  }): void;
51
47
  }
52
48
 
53
- /** @public */
54
- export declare type CacheService = PluginCacheManager;
55
-
56
49
  /**
50
+ * A pre-configured, storage agnostic cache client suitable for use by
51
+ * Backstage plugins.
52
+ *
57
53
  * @public
58
54
  */
59
- declare const cacheServiceRef: ServiceRef<PluginCacheManager, "plugin">;
55
+ export declare interface CacheClient {
56
+ /**
57
+ * Reads data from a cache store for the given key. If no data was found,
58
+ * returns undefined.
59
+ */
60
+ get(key: string): Promise<JsonValue | undefined>;
61
+ /**
62
+ * Writes the given data to a cache store, associated with the given key. An
63
+ * optional TTL may also be provided, otherwise it defaults to the TTL that
64
+ * was provided when the client was instantiated.
65
+ */
66
+ set(key: string, value: JsonValue, options?: CacheClientSetOptions): Promise<void>;
67
+ /**
68
+ * Removes the given key from the cache store.
69
+ */
70
+ delete(key: string): Promise<void>;
71
+ }
60
72
 
61
73
  /**
74
+ * Options given when constructing a {@link CacheClient}.
75
+ *
62
76
  * @public
63
77
  */
64
- export declare type ConfigService = Config;
78
+ export declare type CacheClientOptions = {
79
+ /**
80
+ * An optional default TTL (in milliseconds) to be set when getting a client
81
+ * instance. If not provided, data will persist indefinitely by default (or
82
+ * can be configured per entry at set-time).
83
+ */
84
+ defaultTtl?: number;
85
+ };
65
86
 
66
87
  /**
88
+ * Options passed to {@link CacheClient.set}.
89
+ *
67
90
  * @public
68
91
  */
69
- declare const configServiceRef: ServiceRef<Config, "root">;
92
+ export declare type CacheClientSetOptions = {
93
+ /**
94
+ * Optional TTL in milliseconds. Defaults to the TTL provided when the client
95
+ * was set up (or no TTL if none are provided).
96
+ */
97
+ ttl?: number;
98
+ };
70
99
 
71
- declare namespace coreServices {
72
- export {
73
- configServiceRef as config,
74
- httpRouterServiceRef as httpRouter,
75
- loggerServiceRef as logger,
76
- urlReaderServiceRef as urlReader,
77
- cacheServiceRef as cache,
78
- databaseServiceRef as database,
79
- discoveryServiceRef as discovery,
80
- tokenManagerServiceRef as tokenManager,
81
- permissionsServiceRef as permissions,
82
- schedulerServiceRef as scheduler,
83
- rootLifecycleServiceRef as rootLifecycle,
84
- rootLoggerServiceRef as rootLogger,
85
- pluginMetadataServiceRef as pluginMetadata,
86
- lifecycleServiceRef as lifecycle
87
- }
100
+ /**
101
+ * Manages access to cache stores that plugins get.
102
+ *
103
+ * @public
104
+ */
105
+ export declare interface CacheService {
106
+ /**
107
+ * Provides backend plugins cache connections for themselves.
108
+ *
109
+ * @remarks
110
+ *
111
+ * The purpose of this method is to allow plugins to get isolated data stores
112
+ * so that plugins are discouraged from cache-level integration and/or cache
113
+ * key collisions.
114
+ */
115
+ getClient: (options?: CacheClientOptions) => CacheClient;
88
116
  }
89
- export { coreServices }
90
117
 
91
118
  /**
92
119
  * @public
120
+ */
121
+ export declare interface ConfigService extends Config {
122
+ }
123
+
124
+ /**
125
+ * All core services references
93
126
  *
127
+ * @public
128
+ */
129
+ export declare namespace coreServices {
130
+ /**
131
+ * The service reference for the plugin scoped {@link CacheService}.
132
+ *
133
+ * @public
134
+ */
135
+ const cache: ServiceRef<CacheService, "plugin">;
136
+ /**
137
+ * The service reference for the root scoped {@link ConfigService}.
138
+ *
139
+ * @public
140
+ */
141
+ const config: ServiceRef<ConfigService, "root">;
142
+ /**
143
+ * The service reference for the plugin scoped {@link DatabaseService}.
144
+ *
145
+ * @public
146
+ */
147
+ const database: ServiceRef<DatabaseService, "plugin">;
148
+ /**
149
+ * The service reference for the plugin scoped {@link DiscoveryService}.
150
+ *
151
+ * @public
152
+ */
153
+ const discovery: ServiceRef<DiscoveryService, "plugin">;
154
+ /**
155
+ * The service reference for the plugin scoped {@link HttpRouterService}.
156
+ *
157
+ * @public
158
+ */
159
+ const httpRouter: ServiceRef<HttpRouterService, "plugin">;
160
+ /**
161
+ * The service reference for the plugin scoped {@link LifecycleService}.
162
+ *
163
+ * @public
164
+ */
165
+ const lifecycle: ServiceRef<LifecycleService, "plugin">;
166
+ /**
167
+ * The service reference for the plugin scoped {@link LoggerService}.
168
+ *
169
+ * @public
170
+ */
171
+ const logger: ServiceRef<LoggerService, "plugin">;
172
+ /**
173
+ * The service reference for the plugin scoped {@link PermissionsService}.
174
+ *
175
+ * @public
176
+ */
177
+ const permissions: ServiceRef<PermissionsService, "plugin">;
178
+ /**
179
+ * The service reference for the plugin scoped {@link PluginMetadataService}.
180
+ *
181
+ * @public
182
+ */
183
+ const pluginMetadata: ServiceRef<PluginMetadataService, "plugin">;
184
+ /**
185
+ * The service reference for the root scoped {@link RootHttpRouterService}.
186
+ *
187
+ * @public
188
+ */
189
+ const rootHttpRouter: ServiceRef<RootHttpRouterService, "root">;
190
+ /**
191
+ * The service reference for the root scoped {@link RootLifecycleService}.
192
+ *
193
+ * @public
194
+ */
195
+ const rootLifecycle: ServiceRef<RootLifecycleService, "root">;
196
+ /**
197
+ * The service reference for the root scoped {@link RootLoggerService}.
198
+ *
199
+ * @public
200
+ */
201
+ const rootLogger: ServiceRef<RootLoggerService, "root">;
202
+ /**
203
+ * The service reference for the plugin scoped {@link SchedulerService}.
204
+ *
205
+ * @public
206
+ */
207
+ const scheduler: ServiceRef<SchedulerService, "plugin">;
208
+ /**
209
+ * The service reference for the plugin scoped {@link TokenManagerService}.
210
+ *
211
+ * @public
212
+ */
213
+ const tokenManager: ServiceRef<TokenManagerService, "plugin">;
214
+ /**
215
+ * The service reference for the plugin scoped {@link UrlReaderService}.
216
+ *
217
+ * @public
218
+ */
219
+ const urlReader: ServiceRef<UrlReaderService, "plugin">;
220
+ }
221
+
222
+ /**
94
223
  * Creates a new backend module for a given plugin.
95
224
  *
225
+ * @public
226
+ *
227
+ * @remarks
228
+ *
96
229
  * The `moduleId` should be equal to the module-specific prefix of the exported name, such
97
230
  * that the full name is `moduleId + PluginId + "Module"`. For example, a GitHub entity
98
231
  * provider module for the `catalog` plugin might have the module ID `'githubEntityProvider'`,
@@ -100,51 +233,60 @@ export { coreServices }
100
233
  *
101
234
  * The `pluginId` should exactly match the `id` of the plugin that the module extends.
102
235
  */
103
- export declare function createBackendModule<TOptions extends object | undefined = undefined>(config: BackendModuleConfig<TOptions>): undefined extends TOptions ? (options?: TOptions) => BackendFeature : (options: TOptions) => BackendFeature;
236
+ export declare function createBackendModule<TOptions extends MaybeOptions = undefined>(config: BackendModuleConfig<TOptions>): FactoryFunctionWithOptions<BackendFeature, TOptions>;
104
237
 
105
238
  /** @public */
106
- export declare function createBackendPlugin<TOptions extends object | undefined = undefined>(config: {
107
- id: string;
108
- register(reg: BackendRegistrationPoints, options: TOptions): void;
109
- }): undefined extends TOptions ? (options?: TOptions) => BackendFeature : (options: TOptions) => BackendFeature;
239
+ export declare function createBackendPlugin<TOptions extends MaybeOptions = undefined>(config: BackendPluginConfig<TOptions>): FactoryFunctionWithOptions<BackendFeature, TOptions>;
110
240
 
111
241
  /** @public */
112
- export declare function createExtensionPoint<T>(options: {
113
- id: string;
114
- }): ExtensionPoint<T>;
242
+ export declare function createExtensionPoint<T>(config: ExtensionPointConfig): ExtensionPoint<T>;
115
243
 
116
244
  /**
117
245
  * @public
118
246
  */
119
247
  export declare function createServiceFactory<TService, TScope extends 'root' | 'plugin', TImpl extends TService, TDeps extends {
120
248
  [name in string]: ServiceRef<unknown>;
121
- }, TOpts extends object | undefined = undefined>(config: {
122
- service: ServiceRef<TService, TScope>;
123
- deps: TDeps;
124
- factory(deps: ServiceRefsToInstances<TDeps, 'root'>, options: TOpts): TScope extends 'root' ? Promise<TImpl> : Promise<(deps: ServiceRefsToInstances<TDeps>) => Promise<TImpl>>;
125
- }): undefined extends TOpts ? (options?: TOpts) => ServiceFactory<TService> : (options: TOpts) => ServiceFactory<TService>;
249
+ }, TOpts extends MaybeOptions = undefined>(config: ServiceFactoryConfig<TService, TScope, TImpl, TDeps, TOpts>): FactoryFunctionWithOptions<ServiceFactory<TService>, TOpts>;
126
250
 
127
- /** @public */
128
- export declare function createServiceRef<T>(options: {
129
- id: string;
130
- scope?: 'plugin';
131
- defaultFactory?: (service: ServiceRef<T, 'plugin'>) => Promise<ServiceFactory<T> | (() => ServiceFactory<T>)>;
132
- }): ServiceRef<T, 'plugin'>;
133
-
134
- /** @public */
135
- export declare function createServiceRef<T>(options: {
136
- id: string;
137
- scope: 'root';
138
- defaultFactory?: (service: ServiceRef<T, 'root'>) => Promise<ServiceFactory<T> | (() => ServiceFactory<T>)>;
139
- }): ServiceRef<T, 'root'>;
251
+ /**
252
+ * Creates a new service definition. This overload is used to create plugin scoped services.
253
+ *
254
+ * @public
255
+ */
256
+ export declare function createServiceRef<TService>(config: ServiceRefConfig<TService, 'plugin'>): ServiceRef<TService, 'plugin'>;
140
257
 
141
- /** @public */
142
- export declare type DatabaseService = PluginDatabaseManager;
258
+ /**
259
+ * Creates a new service definition. This overload is used to create root scoped services.
260
+ *
261
+ * @public
262
+ */
263
+ export declare function createServiceRef<TService>(config: ServiceRefConfig<TService, 'root'>): ServiceRef<TService, 'root'>;
143
264
 
144
265
  /**
266
+ * The DatabaseService manages access to databases that Plugins get.
267
+ *gs
145
268
  * @public
146
269
  */
147
- declare const databaseServiceRef: ServiceRef<PluginDatabaseManager, "plugin">;
270
+ export declare interface DatabaseService {
271
+ /**
272
+ * getClient provides backend plugins database connections for itself.
273
+ *
274
+ * The purpose of this method is to allow plugins to get isolated data
275
+ * stores so that plugins are discouraged from database integration.
276
+ */
277
+ getClient(): Promise<Knex>;
278
+ /**
279
+ * This property is used to control the behavior of database migrations.
280
+ */
281
+ migrations?: {
282
+ /**
283
+ * skip database migrations. Useful if connecting to a read-only database.
284
+ *
285
+ * @defaultValue false
286
+ */
287
+ skip?: boolean;
288
+ };
289
+ }
148
290
 
149
291
  /**
150
292
  * The DiscoveryService is used to provide a mechanism for backend
@@ -160,7 +302,7 @@ declare const databaseServiceRef: ServiceRef<PluginDatabaseManager, "plugin">;
160
302
  *
161
303
  * @public
162
304
  */
163
- export declare type DiscoveryService = {
305
+ export declare interface DiscoveryService {
164
306
  /**
165
307
  * Returns the internal HTTP base URL for a given plugin, without a trailing slash.
166
308
  *
@@ -191,12 +333,7 @@ export declare type DiscoveryService = {
191
333
  * like `https://backstage.example.com/api/catalog`
192
334
  */
193
335
  getExternalBaseUrl(pluginId: string): Promise<string>;
194
- };
195
-
196
- /**
197
- * @public
198
- */
199
- declare const discoveryServiceRef: ServiceRef<DiscoveryService, "plugin">;
336
+ }
200
337
 
201
338
  /**
202
339
  * TODO
@@ -214,17 +351,24 @@ export declare type ExtensionPoint<T> = {
214
351
  $$ref: 'extension-point';
215
352
  };
216
353
 
354
+ /** @public */
355
+ export declare interface ExtensionPointConfig {
356
+ id: string;
357
+ }
358
+
217
359
  /**
218
- * @public
360
+ * Helper type that makes the options argument optional if options are not required.
361
+ *
362
+ * @ignore
219
363
  */
220
- export declare interface HttpRouterService {
221
- use(handler: Handler): void;
222
- }
364
+ declare type FactoryFunctionWithOptions<TResult, TOptions> = undefined extends TOptions ? (options?: TOptions) => TResult : (options: TOptions) => TResult;
223
365
 
224
366
  /**
225
367
  * @public
226
368
  */
227
- declare const httpRouterServiceRef: ServiceRef<HttpRouterService, "plugin">;
369
+ export declare interface HttpRouterService {
370
+ use(handler: Handler): void;
371
+ }
228
372
 
229
373
  /**
230
374
  * @public
@@ -236,21 +380,20 @@ export declare interface LifecycleService {
236
380
  addShutdownHook(options: LifecycleServiceShutdownHook): void;
237
381
  }
238
382
 
239
- /**
240
- * @public
241
- */
242
- declare const lifecycleServiceRef: ServiceRef<LifecycleService, "plugin">;
243
-
244
383
  /**
245
384
  * @public
246
385
  **/
247
386
  export declare type LifecycleServiceShutdownHook = {
248
387
  fn: () => void | Promise<void>;
249
- /** Labels to help identify the shutdown hook */
250
- labels?: Record<string, string>;
388
+ /**
389
+ * Optional {@link LoggerService} that will be used for logging instead of the default logger.
390
+ */
391
+ logger?: LoggerService;
251
392
  };
252
393
 
253
394
  /**
395
+ * A service that provides a logging facility.
396
+ *
254
397
  * @public
255
398
  */
256
399
  export declare interface LoggerService {
@@ -261,14 +404,6 @@ export declare interface LoggerService {
261
404
  child(meta: LogMeta): LoggerService;
262
405
  }
263
406
 
264
- /**
265
- * @public
266
- */
267
- declare const loggerServiceRef: ServiceRef<LoggerService, "plugin">;
268
-
269
- /** @public */
270
- export declare function loggerToWinstonLogger(logger: LoggerService, opts?: TransportStreamOptions): Logger;
271
-
272
407
  /**
273
408
  * @public
274
409
  */
@@ -276,13 +411,16 @@ export declare type LogMeta = {
276
411
  [name: string]: unknown;
277
412
  };
278
413
 
279
- /** @public */
280
- export declare type PermissionsService = PermissionEvaluator | PermissionAuthorizer;
281
-
282
414
  /**
283
- * @public
415
+ * Base type for options objects that aren't required.
416
+ *
417
+ * @ignore
284
418
  */
285
- declare const permissionsServiceRef: ServiceRef<PermissionsService, "plugin">;
419
+ declare type MaybeOptions = object | undefined;
420
+
421
+ /** @public */
422
+ export declare interface PermissionsService extends PermissionEvaluator {
423
+ }
286
424
 
287
425
  /**
288
426
  * @public
@@ -291,11 +429,6 @@ export declare interface PluginMetadataService {
291
429
  getId(): string;
292
430
  }
293
431
 
294
- /**
295
- * @public
296
- */
297
- declare const pluginMetadataServiceRef: ServiceRef<PluginMetadataService, "plugin">;
298
-
299
432
  /**
300
433
  * An options object for {@link UrlReaderService.readTree} operations.
301
434
  *
@@ -469,29 +602,28 @@ export declare type ReadUrlResponse = {
469
602
  etag?: string;
470
603
  };
471
604
 
472
- /** @public */
473
- export declare type RootLifecycleService = LifecycleService;
474
-
475
605
  /**
476
606
  * @public
477
607
  */
478
- declare const rootLifecycleServiceRef: ServiceRef<LifecycleService, "root">;
608
+ export declare interface RootHttpRouterService {
609
+ /**
610
+ * Registers a handler at the root of the backend router.
611
+ * The path is required and may not be empty.
612
+ */
613
+ use(path: string, handler: Handler): void;
614
+ }
479
615
 
480
616
  /** @public */
481
- export declare type RootLoggerService = LoggerService;
482
-
483
- /**
484
- * @public
485
- */
486
- declare const rootLoggerServiceRef: ServiceRef<LoggerService, "root">;
617
+ export declare interface RootLifecycleService extends LifecycleService {
618
+ }
487
619
 
488
620
  /** @public */
489
- export declare type SchedulerService = PluginTaskScheduler;
621
+ export declare interface RootLoggerService extends LoggerService {
622
+ }
490
623
 
491
- /**
492
- * @public
493
- */
494
- declare const schedulerServiceRef: ServiceRef<PluginTaskScheduler, "plugin">;
624
+ /** @public */
625
+ export declare interface SchedulerService extends PluginTaskScheduler {
626
+ }
495
627
 
496
628
  /**
497
629
  * An options object for search operations.
@@ -576,6 +708,22 @@ export declare type ServiceFactory<TService = unknown> = {
576
708
  }) => Promise<TService>>;
577
709
  };
578
710
 
711
+ /** @public */
712
+ export declare interface ServiceFactoryConfig<TService, TScope extends 'root' | 'plugin', TImpl extends TService, TDeps extends {
713
+ [name in string]: ServiceRef<unknown>;
714
+ }, TOpts extends MaybeOptions = undefined> {
715
+ service: ServiceRef<TService, TScope>;
716
+ deps: TDeps;
717
+ factory(deps: ServiceRefsToInstances<TDeps, 'root'>, options: TOpts): TScope extends 'root' ? Promise<TImpl> : Promise<(deps: ServiceRefsToInstances<TDeps>) => Promise<TImpl>>;
718
+ }
719
+
720
+ /**
721
+ * Represents either a {@link ServiceFactory} or a function that returns one.
722
+ *
723
+ * @public
724
+ */
725
+ export declare type ServiceFactoryOrFunction<TService = unknown> = ServiceFactory<TService> | (() => ServiceFactory<TService>);
726
+
579
727
  /**
580
728
  * TODO
581
729
  *
@@ -602,6 +750,13 @@ export declare type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'roo
602
750
  $$ref: 'service';
603
751
  };
604
752
 
753
+ /** @public */
754
+ export declare interface ServiceRefConfig<TService, TScope extends 'root' | 'plugin'> {
755
+ id: string;
756
+ scope?: TScope;
757
+ defaultFactory?: (service: ServiceRef<TService, TScope>) => Promise<ServiceFactoryOrFunction<TService>>;
758
+ }
759
+
605
760
  /** @ignore */
606
761
  declare type ServiceRefsToInstances<T extends {
607
762
  [key in string]: ServiceRef<unknown>;
@@ -611,13 +766,30 @@ declare type ServiceRefsToInstances<T extends {
611
766
  }[keyof T]]: T[name] extends ServiceRef<infer TImpl> ? TImpl : never;
612
767
  };
613
768
 
614
- /** @public */
615
- export declare type TokenManagerService = TokenManager;
616
-
617
769
  /**
770
+ * Interface for creating and validating tokens.
771
+ *
618
772
  * @public
619
773
  */
620
- declare const tokenManagerServiceRef: ServiceRef<TokenManager, "plugin">;
774
+ export declare interface TokenManagerService {
775
+ /**
776
+ * Fetches a valid token.
777
+ *
778
+ * @remarks
779
+ *
780
+ * Tokens are valid for roughly one hour; the actual deadline is set in the
781
+ * payload `exp` claim. Never hold on to tokens for reuse; always ask for a
782
+ * new one for each outgoing request. This ensures that you always get a
783
+ * valid, fresh one.
784
+ */
785
+ getToken(): Promise<{
786
+ token: string;
787
+ }>;
788
+ /**
789
+ * Validates a given token.
790
+ */
791
+ authenticate(token: string): Promise<void>;
792
+ }
621
793
 
622
794
  /** @public */
623
795
  export declare type TypesToServiceRef<T> = {
@@ -629,7 +801,7 @@ export declare type TypesToServiceRef<T> = {
629
801
  *
630
802
  * @public
631
803
  */
632
- export declare type UrlReaderService = {
804
+ export declare interface UrlReaderService {
633
805
  /**
634
806
  * Reads a single file and return its content.
635
807
  */
@@ -642,11 +814,6 @@ export declare type UrlReaderService = {
642
814
  * Searches for a file in a tree using a glob pattern.
643
815
  */
644
816
  search(url: string, options?: SearchOptions): Promise<SearchResponse>;
645
- };
646
-
647
- /**
648
- * @public
649
- */
650
- declare const urlReaderServiceRef: ServiceRef<UrlReaderService, "plugin">;
817
+ }
651
818
 
652
819
  export { }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/backend-plugin-api",
3
3
  "description": "Core API used by Backstage backend plugins",
4
- "version": "0.2.1-next.0",
4
+ "version": "0.3.0-next.1",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "publishConfig": {
@@ -33,17 +33,16 @@
33
33
  "start": "backstage-cli package start"
34
34
  },
35
35
  "dependencies": {
36
- "@backstage/backend-common": "^0.18.0-next.0",
37
- "@backstage/backend-tasks": "^0.4.1-next.0",
36
+ "@backstage/backend-tasks": "^0.4.1-next.1",
38
37
  "@backstage/config": "^1.0.6-next.0",
39
38
  "@backstage/plugin-permission-common": "^0.7.3-next.0",
39
+ "@backstage/types": "^1.0.2",
40
40
  "@types/express": "^4.17.6",
41
41
  "express": "^4.17.1",
42
- "winston": "^3.2.1",
43
- "winston-transport": "^4.5.0"
42
+ "knex": "^2.0.0"
44
43
  },
45
44
  "devDependencies": {
46
- "@backstage/cli": "^0.22.1-next.1"
45
+ "@backstage/cli": "^0.22.1-next.2"
47
46
  },
48
47
  "files": [
49
48
  "dist",