@backstage/backend-plugin-api 0.2.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.
@@ -4,18 +4,15 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
 
7
+ /// <reference types="node" />
8
+
7
9
  import { Config } from '@backstage/config';
8
10
  import { Handler } from 'express';
9
- import { Logger } from 'winston';
10
- import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
11
+ import { JsonValue } from '@backstage/types';
12
+ import { Knex } from 'knex';
11
13
  import { PermissionEvaluator } from '@backstage/plugin-permission-common';
12
- import { PluginCacheManager } from '@backstage/backend-common';
13
- import { PluginDatabaseManager } from '@backstage/backend-common';
14
- import { PluginEndpointDiscovery } from '@backstage/backend-common';
15
14
  import { PluginTaskScheduler } from '@backstage/backend-tasks';
16
- import { TokenManager } from '@backstage/backend-common';
17
- import { TransportStreamOptions } from 'winston-transport';
18
- import { UrlReader } from '@backstage/backend-common';
15
+ import { Readable } from 'stream';
19
16
 
20
17
  /** @public */
21
18
  export declare interface BackendFeature {
@@ -49,48 +46,186 @@ export declare interface BackendRegistrationPoints {
49
46
  }): void;
50
47
  }
51
48
 
52
- /** @public */
53
- export declare type CacheService = PluginCacheManager;
54
-
55
49
  /**
50
+ * A pre-configured, storage agnostic cache client suitable for use by
51
+ * Backstage plugins.
52
+ *
56
53
  * @public
57
54
  */
58
- 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
+ }
59
72
 
60
73
  /**
74
+ * Options given when constructing a {@link CacheClient}.
75
+ *
61
76
  * @public
62
77
  */
63
- 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
+ };
64
86
 
65
87
  /**
88
+ * Options passed to {@link CacheClient.set}.
89
+ *
66
90
  * @public
67
91
  */
68
- 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
+ };
69
99
 
70
- declare namespace coreServices {
71
- export {
72
- configServiceRef as config,
73
- httpRouterServiceRef as httpRouter,
74
- loggerServiceRef as logger,
75
- urlReaderServiceRef as urlReader,
76
- cacheServiceRef as cache,
77
- databaseServiceRef as database,
78
- discoveryServiceRef as discovery,
79
- tokenManagerServiceRef as tokenManager,
80
- permissionsServiceRef as permissions,
81
- schedulerServiceRef as scheduler,
82
- rootLoggerServiceRef as rootLogger,
83
- pluginMetadataServiceRef as pluginMetadata,
84
- lifecycleServiceRef as lifecycle
85
- }
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;
86
116
  }
87
- export { coreServices }
88
117
 
89
118
  /**
90
119
  * @public
120
+ */
121
+ export declare interface ConfigService extends Config {
122
+ }
123
+
124
+ /**
125
+ * All core services references
91
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
+ /**
92
223
  * Creates a new backend module for a given plugin.
93
224
  *
225
+ * @public
226
+ *
227
+ * @remarks
228
+ *
94
229
  * The `moduleId` should be equal to the module-specific prefix of the exported name, such
95
230
  * that the full name is `moduleId + PluginId + "Module"`. For example, a GitHub entity
96
231
  * provider module for the `catalog` plugin might have the module ID `'githubEntityProvider'`,
@@ -98,59 +233,107 @@ export { coreServices }
98
233
  *
99
234
  * The `pluginId` should exactly match the `id` of the plugin that the module extends.
100
235
  */
101
- 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>;
102
237
 
103
238
  /** @public */
104
- export declare function createBackendPlugin<TOptions extends object | undefined = undefined>(config: {
105
- id: string;
106
- register(reg: BackendRegistrationPoints, options: TOptions): void;
107
- }): undefined extends TOptions ? (options?: TOptions) => BackendFeature : (options: TOptions) => BackendFeature;
239
+ export declare function createBackendPlugin<TOptions extends MaybeOptions = undefined>(config: BackendPluginConfig<TOptions>): FactoryFunctionWithOptions<BackendFeature, TOptions>;
108
240
 
109
241
  /** @public */
110
- export declare function createExtensionPoint<T>(options: {
111
- id: string;
112
- }): ExtensionPoint<T>;
242
+ export declare function createExtensionPoint<T>(config: ExtensionPointConfig): ExtensionPoint<T>;
113
243
 
114
244
  /**
115
245
  * @public
116
246
  */
117
247
  export declare function createServiceFactory<TService, TScope extends 'root' | 'plugin', TImpl extends TService, TDeps extends {
118
248
  [name in string]: ServiceRef<unknown>;
119
- }, TOpts extends object | undefined = undefined>(config: {
120
- service: ServiceRef<TService, TScope>;
121
- deps: TDeps;
122
- factory(deps: ServiceRefsToInstances<TDeps, 'root'>, options: TOpts): TScope extends 'root' ? Promise<TImpl> : Promise<(deps: ServiceRefsToInstances<TDeps>) => Promise<TImpl>>;
123
- }): undefined extends TOpts ? (options?: TOpts) => ServiceFactory<TService> : (options: TOpts) => ServiceFactory<TService>;
124
-
125
- /** @public */
126
- export declare function createServiceRef<T>(options: {
127
- id: string;
128
- scope?: 'plugin';
129
- defaultFactory?: (service: ServiceRef<T, 'plugin'>) => Promise<ServiceFactory<T> | (() => ServiceFactory<T>)>;
130
- }): ServiceRef<T, 'plugin'>;
249
+ }, TOpts extends MaybeOptions = undefined>(config: ServiceFactoryConfig<TService, TScope, TImpl, TDeps, TOpts>): FactoryFunctionWithOptions<ServiceFactory<TService>, TOpts>;
131
250
 
132
- /** @public */
133
- export declare function createServiceRef<T>(options: {
134
- id: string;
135
- scope: 'root';
136
- defaultFactory?: (service: ServiceRef<T, 'root'>) => Promise<ServiceFactory<T> | (() => ServiceFactory<T>)>;
137
- }): ServiceRef<T, 'root'>;
138
-
139
- /** @public */
140
- export declare type DatabaseService = PluginDatabaseManager;
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'>;
141
257
 
142
258
  /**
259
+ * Creates a new service definition. This overload is used to create root scoped services.
260
+ *
143
261
  * @public
144
262
  */
145
- declare const databaseServiceRef: ServiceRef<PluginDatabaseManager, "plugin">;
263
+ export declare function createServiceRef<TService>(config: ServiceRefConfig<TService, 'root'>): ServiceRef<TService, 'root'>;
146
264
 
147
- /** @public */
148
- export declare type DiscoveryService = PluginEndpointDiscovery;
265
+ /**
266
+ * The DatabaseService manages access to databases that Plugins get.
267
+ *gs
268
+ * @public
269
+ */
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
+ }
149
290
 
150
291
  /**
292
+ * The DiscoveryService is used to provide a mechanism for backend
293
+ * plugins to discover the endpoints for itself or other backend plugins.
294
+ *
295
+ * The purpose of the discovery API is to allow for many different deployment
296
+ * setups and routing methods through a central configuration, instead
297
+ * of letting each individual plugin manage that configuration.
298
+ *
299
+ * Implementations of the discovery API can be as simple as a URL pattern
300
+ * using the pluginId, but could also have overrides for individual plugins,
301
+ * or query a separate discovery service.
302
+ *
151
303
  * @public
152
304
  */
153
- declare const discoveryServiceRef: ServiceRef<PluginEndpointDiscovery, "plugin">;
305
+ export declare interface DiscoveryService {
306
+ /**
307
+ * Returns the internal HTTP base URL for a given plugin, without a trailing slash.
308
+ *
309
+ * The returned URL should point to an internal endpoint for the plugin, with
310
+ * the shortest route possible. The URL should be used for service-to-service
311
+ * communication within a Backstage backend deployment.
312
+ *
313
+ * This method must always be called just before making a request, as opposed to
314
+ * fetching the URL when constructing an API client. That is to ensure that more
315
+ * flexible routing patterns can be supported.
316
+ *
317
+ * For example, asking for the URL for `catalog` may return something
318
+ * like `http://10.1.2.3/api/catalog`
319
+ */
320
+ getBaseUrl(pluginId: string): Promise<string>;
321
+ /**
322
+ * Returns the external HTTP base backend URL for a given plugin, without a trailing slash.
323
+ *
324
+ * The returned URL should point to an external endpoint for the plugin, such that
325
+ * it is reachable from the Backstage frontend and other external services. The returned
326
+ * URL should be usable for example as a callback / webhook URL.
327
+ *
328
+ * The returned URL should be stable and in general not change unless other static
329
+ * or external configuration is changed. Changes should not come as a surprise
330
+ * to an operator of the Backstage backend.
331
+ *
332
+ * For example, asking for the URL for `catalog` may return something
333
+ * like `https://backstage.example.com/api/catalog`
334
+ */
335
+ getExternalBaseUrl(pluginId: string): Promise<string>;
336
+ }
154
337
 
155
338
  /**
156
339
  * TODO
@@ -168,17 +351,24 @@ export declare type ExtensionPoint<T> = {
168
351
  $$ref: 'extension-point';
169
352
  };
170
353
 
354
+ /** @public */
355
+ export declare interface ExtensionPointConfig {
356
+ id: string;
357
+ }
358
+
171
359
  /**
172
- * @public
360
+ * Helper type that makes the options argument optional if options are not required.
361
+ *
362
+ * @ignore
173
363
  */
174
- export declare interface HttpRouterService {
175
- use(handler: Handler): void;
176
- }
364
+ declare type FactoryFunctionWithOptions<TResult, TOptions> = undefined extends TOptions ? (options?: TOptions) => TResult : (options: TOptions) => TResult;
177
365
 
178
366
  /**
179
367
  * @public
180
368
  */
181
- declare const httpRouterServiceRef: ServiceRef<HttpRouterService, "plugin">;
369
+ export declare interface HttpRouterService {
370
+ use(handler: Handler): void;
371
+ }
182
372
 
183
373
  /**
184
374
  * @public
@@ -190,19 +380,20 @@ export declare interface LifecycleService {
190
380
  addShutdownHook(options: LifecycleServiceShutdownHook): void;
191
381
  }
192
382
 
193
- /**
194
- * @public
195
- */
196
- declare const lifecycleServiceRef: ServiceRef<LifecycleService, "plugin">;
197
-
198
383
  /**
199
384
  * @public
200
385
  **/
201
386
  export declare type LifecycleServiceShutdownHook = {
202
387
  fn: () => void | Promise<void>;
388
+ /**
389
+ * Optional {@link LoggerService} that will be used for logging instead of the default logger.
390
+ */
391
+ logger?: LoggerService;
203
392
  };
204
393
 
205
394
  /**
395
+ * A service that provides a logging facility.
396
+ *
206
397
  * @public
207
398
  */
208
399
  export declare interface LoggerService {
@@ -216,53 +407,283 @@ export declare interface LoggerService {
216
407
  /**
217
408
  * @public
218
409
  */
219
- declare const loggerServiceRef: ServiceRef<LoggerService, "plugin">;
410
+ export declare type LogMeta = {
411
+ [name: string]: unknown;
412
+ };
413
+
414
+ /**
415
+ * Base type for options objects that aren't required.
416
+ *
417
+ * @ignore
418
+ */
419
+ declare type MaybeOptions = object | undefined;
220
420
 
221
421
  /** @public */
222
- export declare function loggerToWinstonLogger(logger: LoggerService, opts?: TransportStreamOptions): Logger;
422
+ export declare interface PermissionsService extends PermissionEvaluator {
423
+ }
223
424
 
224
425
  /**
225
426
  * @public
226
427
  */
227
- export declare type LogMeta = {
228
- [name: string]: unknown;
428
+ export declare interface PluginMetadataService {
429
+ getId(): string;
430
+ }
431
+
432
+ /**
433
+ * An options object for {@link UrlReaderService.readTree} operations.
434
+ *
435
+ * @public
436
+ */
437
+ export declare type ReadTreeOptions = {
438
+ /**
439
+ * A filter that can be used to select which files should be included.
440
+ *
441
+ * @remarks
442
+ *
443
+ * The path passed to the filter function is the relative path from the URL
444
+ * that the file tree is fetched from, without any leading '/'.
445
+ *
446
+ * For example, given the URL https://github.com/my/repo/tree/master/my-dir, a file
447
+ * at https://github.com/my/repo/blob/master/my-dir/my-subdir/my-file.txt will
448
+ * be represented as my-subdir/my-file.txt
449
+ *
450
+ * If no filter is provided, all files are extracted.
451
+ */
452
+ filter?(path: string, info?: {
453
+ size: number;
454
+ }): boolean;
455
+ /**
456
+ * An ETag which can be provided to check whether a
457
+ * {@link UrlReaderService.readTree} response has changed from a previous execution.
458
+ *
459
+ * @remarks
460
+ *
461
+ * In the {@link UrlReaderService.readTree} response, an ETag is returned along with
462
+ * the tree blob. The ETag is a unique identifier of the tree blob, usually
463
+ * the commit SHA or ETag from the target.
464
+ *
465
+ * When an ETag is given as a request option, {@link UrlReaderService.readTree} will
466
+ * first compare the ETag against the ETag on the target branch. If they
467
+ * match, {@link UrlReaderService.readTree} will throw a
468
+ * {@link @backstage/errors#NotModifiedError} indicating that the response
469
+ * will not differ from the previous response which included this particular
470
+ * ETag. If they do not match, {@link UrlReaderService.readTree} will return the
471
+ * rest of the response along with a new ETag.
472
+ */
473
+ etag?: string;
474
+ /**
475
+ * An abort signal to pass down to the underlying request.
476
+ *
477
+ * @remarks
478
+ *
479
+ * Not all reader implementations may take this field into account.
480
+ */
481
+ signal?: AbortSignal;
229
482
  };
230
483
 
231
- /** @public */
232
- export declare type PermissionsService = PermissionEvaluator | PermissionAuthorizer;
484
+ /**
485
+ * A response object for {@link UrlReaderService.readTree} operations.
486
+ *
487
+ * @public
488
+ */
489
+ export declare type ReadTreeResponse = {
490
+ /**
491
+ * Returns an array of all the files inside the tree, and corresponding
492
+ * functions to read their content.
493
+ */
494
+ files(): Promise<ReadTreeResponseFile[]>;
495
+ /**
496
+ * Returns the tree contents as a binary archive, using a stream.
497
+ */
498
+ archive(): Promise<NodeJS.ReadableStream>;
499
+ /**
500
+ * Extracts the tree response into a directory and returns the path of the
501
+ * directory.
502
+ *
503
+ * **NOTE**: It is the responsibility of the caller to remove the directory after use.
504
+ */
505
+ dir(options?: ReadTreeResponseDirOptions): Promise<string>;
506
+ /**
507
+ * Etag returned by content provider.
508
+ *
509
+ * @remarks
510
+ *
511
+ * Can be used to compare and cache responses when doing subsequent calls.
512
+ */
513
+ etag: string;
514
+ };
233
515
 
234
516
  /**
517
+ * Options that control {@link ReadTreeResponse.dir} execution.
518
+ *
235
519
  * @public
236
520
  */
237
- declare const permissionsServiceRef: ServiceRef<PermissionsService, "plugin">;
521
+ export declare type ReadTreeResponseDirOptions = {
522
+ /**
523
+ * The directory to write files to.
524
+ *
525
+ * @remarks
526
+ *
527
+ * Defaults to the OS tmpdir, or `backend.workingDirectory` if set in config.
528
+ */
529
+ targetDir?: string;
530
+ };
238
531
 
239
532
  /**
533
+ * Represents a single file in a {@link UrlReaderService.readTree} response.
534
+ *
240
535
  * @public
241
536
  */
242
- export declare interface PluginMetadataService {
243
- getId(): string;
244
- }
537
+ export declare type ReadTreeResponseFile = {
538
+ path: string;
539
+ content(): Promise<Buffer>;
540
+ };
245
541
 
246
542
  /**
543
+ * An options object for readUrl operations.
544
+ *
247
545
  * @public
248
546
  */
249
- declare const pluginMetadataServiceRef: ServiceRef<PluginMetadataService, "plugin">;
547
+ export declare type ReadUrlOptions = {
548
+ /**
549
+ * An ETag which can be provided to check whether a
550
+ * {@link UrlReaderService.readUrl} response has changed from a previous execution.
551
+ *
552
+ * @remarks
553
+ *
554
+ * In the {@link UrlReaderService.readUrl} response, an ETag is returned along with
555
+ * the data. The ETag is a unique identifier of the data, usually the commit
556
+ * SHA or ETag from the target.
557
+ *
558
+ * When an ETag is given in ReadUrlOptions, {@link UrlReaderService.readUrl} will
559
+ * first compare the ETag against the ETag of the target. If they match,
560
+ * {@link UrlReaderService.readUrl} will throw a
561
+ * {@link @backstage/errors#NotModifiedError} indicating that the response
562
+ * will not differ from the previous response which included this particular
563
+ * ETag. If they do not match, {@link UrlReaderService.readUrl} will return the rest
564
+ * of the response along with a new ETag.
565
+ */
566
+ etag?: string;
567
+ /**
568
+ * An abort signal to pass down to the underlying request.
569
+ *
570
+ * @remarks
571
+ *
572
+ * Not all reader implementations may take this field into account.
573
+ */
574
+ signal?: AbortSignal;
575
+ };
250
576
 
251
- /** @public */
252
- export declare type RootLoggerService = LoggerService;
577
+ /**
578
+ * A response object for {@link UrlReaderService.readUrl} operations.
579
+ *
580
+ * @public
581
+ */
582
+ export declare type ReadUrlResponse = {
583
+ /**
584
+ * Returns the data that was read from the remote URL.
585
+ */
586
+ buffer(): Promise<Buffer>;
587
+ /**
588
+ * Returns the data that was read from the remote URL as a Readable stream.
589
+ *
590
+ * @remarks
591
+ *
592
+ * This method will be required in a future release.
593
+ */
594
+ stream?(): Readable;
595
+ /**
596
+ * Etag returned by content provider.
597
+ *
598
+ * @remarks
599
+ *
600
+ * Can be used to compare and cache responses when doing subsequent calls.
601
+ */
602
+ etag?: string;
603
+ };
253
604
 
254
605
  /**
255
606
  * @public
256
607
  */
257
- declare const rootLoggerServiceRef: ServiceRef<LoggerService, "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
+ }
615
+
616
+ /** @public */
617
+ export declare interface RootLifecycleService extends LifecycleService {
618
+ }
619
+
620
+ /** @public */
621
+ export declare interface RootLoggerService extends LoggerService {
622
+ }
258
623
 
259
624
  /** @public */
260
- export declare type SchedulerService = PluginTaskScheduler;
625
+ export declare interface SchedulerService extends PluginTaskScheduler {
626
+ }
261
627
 
262
628
  /**
629
+ * An options object for search operations.
630
+ *
263
631
  * @public
264
632
  */
265
- declare const schedulerServiceRef: ServiceRef<PluginTaskScheduler, "plugin">;
633
+ export declare type SearchOptions = {
634
+ /**
635
+ * An etag can be provided to check whether the search response has changed from a previous execution.
636
+ *
637
+ * In the search() response, an etag is returned along with the files. The etag is a unique identifier
638
+ * of the current tree, usually the commit SHA or etag from the target.
639
+ *
640
+ * When an etag is given in SearchOptions, search will first compare the etag against the etag
641
+ * on the target branch. If they match, search will throw a NotModifiedError indicating that the search
642
+ * response will not differ from the previous response which included this particular etag. If they mismatch,
643
+ * search will return the rest of SearchResponse along with a new etag.
644
+ */
645
+ etag?: string;
646
+ /**
647
+ * An abort signal to pass down to the underlying request.
648
+ *
649
+ * @remarks
650
+ *
651
+ * Not all reader implementations may take this field into account.
652
+ */
653
+ signal?: AbortSignal;
654
+ };
655
+
656
+ /**
657
+ * The output of a search operation.
658
+ *
659
+ * @public
660
+ */
661
+ export declare type SearchResponse = {
662
+ /**
663
+ * The files that matched the search query.
664
+ */
665
+ files: SearchResponseFile[];
666
+ /**
667
+ * A unique identifier of the current remote tree, usually the commit SHA or etag from the target.
668
+ */
669
+ etag: string;
670
+ };
671
+
672
+ /**
673
+ * Represents a single file in a search response.
674
+ *
675
+ * @public
676
+ */
677
+ export declare type SearchResponseFile = {
678
+ /**
679
+ * The full URL to the file.
680
+ */
681
+ url: string;
682
+ /**
683
+ * The binary contents of the file.
684
+ */
685
+ content(): Promise<Buffer>;
686
+ };
266
687
 
267
688
  /** @public */
268
689
  export declare type ServiceFactory<TService = unknown> = {
@@ -287,6 +708,22 @@ export declare type ServiceFactory<TService = unknown> = {
287
708
  }) => Promise<TService>>;
288
709
  };
289
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
+
290
727
  /**
291
728
  * TODO
292
729
  *
@@ -313,6 +750,13 @@ export declare type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'roo
313
750
  $$ref: 'service';
314
751
  };
315
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
+
316
760
  /** @ignore */
317
761
  declare type ServiceRefsToInstances<T extends {
318
762
  [key in string]: ServiceRef<unknown>;
@@ -322,25 +766,54 @@ declare type ServiceRefsToInstances<T extends {
322
766
  }[keyof T]]: T[name] extends ServiceRef<infer TImpl> ? TImpl : never;
323
767
  };
324
768
 
325
- /** @public */
326
- export declare type TokenManagerService = TokenManager;
327
-
328
769
  /**
770
+ * Interface for creating and validating tokens.
771
+ *
329
772
  * @public
330
773
  */
331
- 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
+ }
332
793
 
333
794
  /** @public */
334
795
  export declare type TypesToServiceRef<T> = {
335
796
  [key in keyof T]: ServiceRef<T[key]>;
336
797
  };
337
798
 
338
- /** @public */
339
- export declare type UrlReaderService = UrlReader;
340
-
341
799
  /**
800
+ * A generic interface for fetching plain data from URLs.
801
+ *
342
802
  * @public
343
803
  */
344
- declare const urlReaderServiceRef: ServiceRef<UrlReader, "plugin">;
804
+ export declare interface UrlReaderService {
805
+ /**
806
+ * Reads a single file and return its content.
807
+ */
808
+ readUrl(url: string, options?: ReadUrlOptions): Promise<ReadUrlResponse>;
809
+ /**
810
+ * Reads a full or partial file tree.
811
+ */
812
+ readTree(url: string, options?: ReadTreeOptions): Promise<ReadTreeResponse>;
813
+ /**
814
+ * Searches for a file in a tree using a glob pattern.
815
+ */
816
+ search(url: string, options?: SearchOptions): Promise<SearchResponse>;
817
+ }
345
818
 
346
819
  export { }