@backstage/plugin-techdocs-backend 1.11.7-next.2 → 2.0.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # @backstage/plugin-techdocs-backend
2
2
 
3
+ ## 2.0.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/backend-defaults@0.9.0-next.0
9
+ - @backstage/plugin-techdocs-node@1.13.2-next.0
10
+ - @backstage/plugin-search-backend-module-techdocs@0.4.1-next.0
11
+ - @backstage/backend-plugin-api@1.2.1
12
+ - @backstage/catalog-client@1.9.1
13
+ - @backstage/catalog-model@1.7.3
14
+ - @backstage/config@1.3.2
15
+ - @backstage/errors@1.2.7
16
+ - @backstage/integration@1.16.2
17
+ - @backstage/plugin-catalog-common@1.1.3
18
+ - @backstage/plugin-catalog-node@1.16.1
19
+ - @backstage/plugin-permission-common@0.8.4
20
+ - @backstage/plugin-techdocs-common@0.1.0
21
+
22
+ ## 2.0.0
23
+
24
+ ### Major Changes
25
+
26
+ - d5c4a9d: **BREAKING** Removed support for the legacy backend, please migrate to the new backend system. Also removed deprecated `DefaultTechDocsCollatorFactory`. Use the `@backstage/plugin-search-backend-module-techdocs` for this instead. Finally, deprecated `DocsBuildStrategy` and `TechDocsDocument` were removed, use the versions in `@backstage/plugin-techdocs-node` instead.
27
+
28
+ ### Patch Changes
29
+
30
+ - 7828186: Minor type fix
31
+ - 8f03776: Properly clean up temporary files on build failures
32
+ - Updated dependencies
33
+ - @backstage/plugin-search-backend-module-techdocs@0.4.0
34
+ - @backstage/integration@1.16.2
35
+ - @backstage/backend-defaults@0.8.2
36
+ - @backstage/plugin-techdocs-node@1.13.1
37
+ - @backstage/backend-plugin-api@1.2.1
38
+ - @backstage/catalog-client@1.9.1
39
+ - @backstage/catalog-model@1.7.3
40
+ - @backstage/config@1.3.2
41
+ - @backstage/errors@1.2.7
42
+ - @backstage/plugin-catalog-common@1.1.3
43
+ - @backstage/plugin-catalog-node@1.16.1
44
+ - @backstage/plugin-permission-common@0.8.4
45
+ - @backstage/plugin-techdocs-common@0.1.0
46
+
3
47
  ## 1.11.7-next.2
4
48
 
5
49
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -3,21 +3,8 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var plugin = require('./plugin.cjs.js');
6
- var router = require('./service/router.cjs.js');
7
- var index = require('./search/index.cjs.js');
8
- var pluginTechdocsNode = require('@backstage/plugin-techdocs-node');
9
- var DefaultTechDocsCollator = require('./search/DefaultTechDocsCollator.cjs.js');
10
6
 
11
7
 
12
8
 
13
9
  exports.default = plugin.techdocsPlugin;
14
- exports.createRouter = router.createRouter;
15
- exports.DefaultTechDocsCollatorFactory = index.DefaultTechDocsCollatorFactory;
16
- exports.DefaultTechDocsCollator = DefaultTechDocsCollator.DefaultTechDocsCollator;
17
- Object.keys(pluginTechdocsNode).forEach(function (k) {
18
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
19
- enumerable: true,
20
- get: function () { return pluginTechdocsNode[k]; }
21
- });
22
- });
23
10
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,17 +1,4 @@
1
- import { Entity } from '@backstage/catalog-model';
2
- import { PreparerBuilder, GeneratorBuilder, PublisherBase, DocsBuildStrategy as DocsBuildStrategy$1, TechDocsDocument as TechDocsDocument$1 } from '@backstage/plugin-techdocs-node';
3
- export * from '@backstage/plugin-techdocs-node';
4
1
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
5
- import { DiscoveryService, HttpAuthService, AuthService } from '@backstage/backend-plugin-api';
6
- import { PluginCacheManager, TokenManager } from '@backstage/backend-common';
7
- import { CatalogApi } from '@backstage/catalog-client';
8
- import { Config } from '@backstage/config';
9
- import express from 'express';
10
- import { Knex } from 'knex';
11
- import * as winston from 'winston';
12
- import { Logger } from 'winston';
13
- import { TechDocsCollatorFactoryOptions as TechDocsCollatorFactoryOptions$1, DefaultTechDocsCollatorFactory as DefaultTechDocsCollatorFactory$1 } from '@backstage/plugin-search-backend-module-techdocs';
14
- import { Permission } from '@backstage/plugin-permission-common';
15
2
 
16
3
  /**
17
4
  * The TechDocs plugin is responsible for serving and building documentation for any entity.
@@ -19,133 +6,4 @@ import { Permission } from '@backstage/plugin-permission-common';
19
6
  */
20
7
  declare const techdocsPlugin: _backstage_backend_plugin_api.BackendFeature;
21
8
 
22
- /**
23
- * Required dependencies for running TechDocs in the "out-of-the-box"
24
- * deployment configuration (prepare/generate/publish all in the Backend).
25
- *
26
- * @public
27
- */
28
- type OutOfTheBoxDeploymentOptions = {
29
- preparers: PreparerBuilder;
30
- generators: GeneratorBuilder;
31
- publisher: PublisherBase;
32
- logger: winston.Logger;
33
- discovery: DiscoveryService;
34
- database?: Knex;
35
- config: Config;
36
- cache: PluginCacheManager;
37
- docsBuildStrategy?: DocsBuildStrategy$1;
38
- buildLogTransport?: winston.transport;
39
- catalogClient?: CatalogApi;
40
- httpAuth?: HttpAuthService;
41
- auth?: AuthService;
42
- };
43
- /**
44
- * Required dependencies for running TechDocs in the "recommended" deployment
45
- * configuration (prepare/generate handled externally in CI/CD).
46
- *
47
- * @public
48
- * @deprecated This type is only exported for legacy reasons and will be removed in the future.
49
- */
50
- type RecommendedDeploymentOptions = {
51
- publisher: PublisherBase;
52
- logger: winston.Logger;
53
- discovery: DiscoveryService;
54
- config: Config;
55
- cache: PluginCacheManager;
56
- docsBuildStrategy?: DocsBuildStrategy$1;
57
- buildLogTransport?: winston.transport;
58
- catalogClient?: CatalogApi;
59
- httpAuth?: HttpAuthService;
60
- auth?: AuthService;
61
- };
62
- /**
63
- * One of the two deployment configurations must be provided.
64
- *
65
- * @public
66
- * @deprecated This type is only exported for legacy reasons and will be removed in the future.
67
- */
68
- type RouterOptions = RecommendedDeploymentOptions | OutOfTheBoxDeploymentOptions;
69
- /**
70
- * Creates a techdocs router.
71
- *
72
- * @public
73
- * @deprecated This function is only exported for legacy reasons and will be removed in the future.
74
- * Please {@link https://backstage.io/docs/backend-system/building-backends/migrating | migrate } to use the new backend system and follow these {@link https://backstage.io/docs/features/techdocs/getting-started#new-backend-system | instructions } to install the user settings backend plugin.
75
- */
76
- declare function createRouter(options: RouterOptions): Promise<express.Router>;
77
-
78
- /**
79
- * Options to configure the TechDocs collator
80
- *
81
- * @public
82
- */
83
- type TechDocsCollatorOptions = {
84
- discovery: DiscoveryService;
85
- logger: Logger;
86
- tokenManager: TokenManager;
87
- locationTemplate?: string;
88
- catalogClient?: CatalogApi;
89
- parallelismLimit?: number;
90
- legacyPathCasing?: boolean;
91
- };
92
- /**
93
- * A search collator responsible for gathering and transforming TechDocs documents.
94
- *
95
- * @public
96
- * @deprecated Upgrade to a more recent `@backstage/plugin-search-backend-node` and
97
- * use `DefaultTechDocsCollatorFactory` instead.
98
- */
99
- declare class DefaultTechDocsCollator {
100
- private readonly legacyPathCasing;
101
- private readonly options;
102
- readonly type: string;
103
- readonly visibilityPermission: Permission;
104
- private constructor();
105
- static fromConfig(config: Config, options: TechDocsCollatorOptions): DefaultTechDocsCollator;
106
- execute(): Promise<TechDocsDocument$1[]>;
107
- protected applyArgsToFormat(format: string, args: Record<string, string>): string;
108
- private static constructDocsIndexUrl;
109
- private static handleEntityInfoCasing;
110
- }
111
-
112
- /**
113
- * todo(backstage/techdocs-core): stop exporting these in a future release.
114
- */
115
-
116
- /**
117
- * @public
118
- * @deprecated import from `@backstage/plugin-search-backend-module-techdocs` instead
119
- */
120
- type TechDocsCollatorFactoryOptions = TechDocsCollatorFactoryOptions$1;
121
- /**
122
- * @public
123
- * @deprecated import from `@backstage/plugin-search-backend-module-techdocs` instead
124
- */
125
- declare const DefaultTechDocsCollatorFactory: typeof DefaultTechDocsCollatorFactory$1;
126
-
127
- /**
128
- * The Backstage backend plugin that renders technical documentation for your components
129
- *
130
- * @packageDocumentation
131
- */
132
-
133
- /**
134
- * @public
135
- * @deprecated import from `@backstage/plugin-techdocs-node` instead
136
- */
137
- type DocsBuildStrategy = DocsBuildStrategy$1;
138
- /**
139
- * @public
140
- * @deprecated use direct type definition instead
141
- */
142
- type ShouldBuildParameters = {
143
- entity: Entity;
144
- };
145
- /**
146
- * @public
147
- * @deprecated import from `@backstage/plugin-techdocs-node` instead
148
- */
149
- type TechDocsDocument = TechDocsDocument$1;
150
-
151
- export { DefaultTechDocsCollator, DefaultTechDocsCollatorFactory, type DocsBuildStrategy, type OutOfTheBoxDeploymentOptions, type RecommendedDeploymentOptions, type RouterOptions, type ShouldBuildParameters, type TechDocsCollatorFactoryOptions, type TechDocsCollatorOptions, type TechDocsDocument, createRouter, techdocsPlugin as default };
9
+ export { techdocsPlugin as default };
@@ -1,10 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var backendCommon = require('@backstage/backend-common');
4
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
5
4
  var pluginTechdocsNode = require('@backstage/plugin-techdocs-node');
6
- var router = require('./service/router.cjs.js');
7
5
  var alpha = require('@backstage/plugin-catalog-node/alpha');
6
+ var router = require('./service/router.cjs.js');
8
7
 
9
8
  const techdocsPlugin = backendPluginApi.createBackendPlugin({
10
9
  pluginId: "techdocs",
@@ -81,30 +80,28 @@ const techdocsPlugin = backendPluginApi.createBackendPlugin({
81
80
  auth,
82
81
  catalog
83
82
  }) {
84
- const winstonLogger = backendCommon.loggerToWinstonLogger(logger);
85
83
  const preparers = await pluginTechdocsNode.Preparers.fromConfig(config, {
86
84
  reader: urlReader,
87
- logger: winstonLogger
85
+ logger
88
86
  });
89
87
  for (const [protocol, preparer] of customPreparers.entries()) {
90
88
  preparers.register(protocol, preparer);
91
89
  }
92
90
  const generators = await pluginTechdocsNode.Generators.fromConfig(config, {
93
- logger: winstonLogger,
91
+ logger,
94
92
  customGenerator: customTechdocsGenerator
95
93
  });
96
94
  const publisher = await pluginTechdocsNode.Publisher.fromConfig(config, {
97
- logger: winstonLogger,
95
+ logger,
98
96
  discovery,
99
97
  customPublisher: customTechdocsPublisher,
100
98
  publisherSettings
101
99
  });
102
100
  await publisher.getReadiness();
103
- const cacheManager = backendCommon.cacheToPluginCacheManager(cache);
104
101
  http.use(
105
102
  await router.createRouter({
106
- logger: winstonLogger,
107
- cache: cacheManager,
103
+ logger,
104
+ cache,
108
105
  docsBuildStrategy,
109
106
  buildLogTransport,
110
107
  preparers,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n cacheToPluginCacheManager,\n loggerToWinstonLogger,\n} from '@backstage/backend-common';\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport {\n DocsBuildStrategy,\n Generators,\n PreparerBase,\n Preparers,\n Publisher,\n PublisherBase,\n PublisherSettings,\n PublisherType,\n RemoteProtocol,\n techdocsBuildsExtensionPoint,\n TechdocsGenerator,\n techdocsGeneratorExtensionPoint,\n techdocsPreparerExtensionPoint,\n techdocsPublisherExtensionPoint,\n} from '@backstage/plugin-techdocs-node';\nimport { createRouter } from './service';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport * as winston from 'winston';\n\n/**\n * The TechDocs plugin is responsible for serving and building documentation for any entity.\n * @public\n */\nexport const techdocsPlugin = createBackendPlugin({\n pluginId: 'techdocs',\n register(env) {\n let docsBuildStrategy: DocsBuildStrategy | undefined;\n let buildLogTransport: winston.transport | undefined;\n env.registerExtensionPoint(techdocsBuildsExtensionPoint, {\n setBuildStrategy(buildStrategy: DocsBuildStrategy) {\n if (docsBuildStrategy) {\n throw new Error('DocsBuildStrategy may only be set once');\n }\n docsBuildStrategy = buildStrategy;\n },\n setBuildLogTransport(transport: winston.transport) {\n if (buildLogTransport) {\n throw new Error('BuildLogTransport may only be set once');\n }\n buildLogTransport = transport;\n },\n });\n\n let customTechdocsGenerator: TechdocsGenerator | undefined;\n env.registerExtensionPoint(techdocsGeneratorExtensionPoint, {\n setTechdocsGenerator(generator: TechdocsGenerator) {\n if (customTechdocsGenerator) {\n throw new Error('TechdocsGenerator may only be set once');\n }\n\n customTechdocsGenerator = generator;\n },\n });\n\n const customPreparers = new Map<RemoteProtocol, PreparerBase>();\n env.registerExtensionPoint(techdocsPreparerExtensionPoint, {\n registerPreparer(protocol: RemoteProtocol, preparer: PreparerBase) {\n if (customPreparers.has(protocol)) {\n throw new Error(\n `Preparer for protocol ${protocol} is already registered`,\n );\n }\n customPreparers.set(protocol, preparer);\n },\n });\n\n let customTechdocsPublisher: PublisherBase | undefined;\n const publisherSettings: PublisherSettings = {};\n env.registerExtensionPoint(techdocsPublisherExtensionPoint, {\n registerPublisher(type: PublisherType, publisher: PublisherBase) {\n if (customTechdocsPublisher) {\n throw new Error(`Publisher for type ${type} is already registered`);\n }\n customTechdocsPublisher = publisher;\n },\n registerPublisherSettings<T extends keyof PublisherSettings>(\n publisher: T,\n settings: PublisherSettings[T],\n ) {\n publisherSettings[publisher] = settings;\n },\n });\n\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n urlReader: coreServices.urlReader,\n http: coreServices.httpRouter,\n discovery: coreServices.discovery,\n cache: coreServices.cache,\n httpAuth: coreServices.httpAuth,\n auth: coreServices.auth,\n catalog: catalogServiceRef,\n },\n async init({\n config,\n logger,\n urlReader,\n http,\n discovery,\n cache,\n httpAuth,\n auth,\n catalog,\n }) {\n const winstonLogger = loggerToWinstonLogger(logger);\n // Preparers are responsible for fetching source files for documentation.\n const preparers = await Preparers.fromConfig(config, {\n reader: urlReader,\n logger: winstonLogger,\n });\n for (const [protocol, preparer] of customPreparers.entries()) {\n preparers.register(protocol, preparer);\n }\n\n // Generators are used for generating documentation sites.\n const generators = await Generators.fromConfig(config, {\n logger: winstonLogger,\n customGenerator: customTechdocsGenerator,\n });\n\n // Publisher is used for\n // 1. Publishing generated files to storage\n // 2. Fetching files from storage and passing them to TechDocs frontend.\n const publisher = await Publisher.fromConfig(config, {\n logger: winstonLogger,\n discovery: discovery,\n customPublisher: customTechdocsPublisher,\n publisherSettings,\n });\n\n // checks if the publisher is working and logs the result\n await publisher.getReadiness();\n\n const cacheManager = cacheToPluginCacheManager(cache);\n http.use(\n await createRouter({\n logger: winstonLogger,\n cache: cacheManager,\n docsBuildStrategy,\n buildLogTransport,\n preparers,\n generators,\n publisher,\n config,\n discovery,\n httpAuth,\n auth,\n catalogClient: catalog,\n }),\n );\n\n http.addAuthPolicy({\n path: '/static',\n allow: 'user-cookie',\n });\n },\n });\n },\n});\n"],"names":["createBackendPlugin","techdocsBuildsExtensionPoint","techdocsGeneratorExtensionPoint","techdocsPreparerExtensionPoint","techdocsPublisherExtensionPoint","coreServices","catalogServiceRef","loggerToWinstonLogger","Preparers","Generators","Publisher","cacheToPluginCacheManager","createRouter"],"mappings":";;;;;;;;AAgDO,MAAM,iBAAiBA,oCAAoB,CAAA;AAAA,EAChD,QAAU,EAAA,UAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAI,IAAA,iBAAA;AACJ,IAAI,IAAA,iBAAA;AACJ,IAAA,GAAA,CAAI,uBAAuBC,+CAA8B,EAAA;AAAA,MACvD,iBAAiB,aAAkC,EAAA;AACjD,QAAA,IAAI,iBAAmB,EAAA;AACrB,UAAM,MAAA,IAAI,MAAM,wCAAwC,CAAA;AAAA;AAE1D,QAAoB,iBAAA,GAAA,aAAA;AAAA,OACtB;AAAA,MACA,qBAAqB,SAA8B,EAAA;AACjD,QAAA,IAAI,iBAAmB,EAAA;AACrB,UAAM,MAAA,IAAI,MAAM,wCAAwC,CAAA;AAAA;AAE1D,QAAoB,iBAAA,GAAA,SAAA;AAAA;AACtB,KACD,CAAA;AAED,IAAI,IAAA,uBAAA;AACJ,IAAA,GAAA,CAAI,uBAAuBC,kDAAiC,EAAA;AAAA,MAC1D,qBAAqB,SAA8B,EAAA;AACjD,QAAA,IAAI,uBAAyB,EAAA;AAC3B,UAAM,MAAA,IAAI,MAAM,wCAAwC,CAAA;AAAA;AAG1D,QAA0B,uBAAA,GAAA,SAAA;AAAA;AAC5B,KACD,CAAA;AAED,IAAM,MAAA,eAAA,uBAAsB,GAAkC,EAAA;AAC9D,IAAA,GAAA,CAAI,uBAAuBC,iDAAgC,EAAA;AAAA,MACzD,gBAAA,CAAiB,UAA0B,QAAwB,EAAA;AACjE,QAAI,IAAA,eAAA,CAAgB,GAAI,CAAA,QAAQ,CAAG,EAAA;AACjC,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,yBAAyB,QAAQ,CAAA,sBAAA;AAAA,WACnC;AAAA;AAEF,QAAgB,eAAA,CAAA,GAAA,CAAI,UAAU,QAAQ,CAAA;AAAA;AACxC,KACD,CAAA;AAED,IAAI,IAAA,uBAAA;AACJ,IAAA,MAAM,oBAAuC,EAAC;AAC9C,IAAA,GAAA,CAAI,uBAAuBC,kDAAiC,EAAA;AAAA,MAC1D,iBAAA,CAAkB,MAAqB,SAA0B,EAAA;AAC/D,QAAA,IAAI,uBAAyB,EAAA;AAC3B,UAAA,MAAM,IAAI,KAAA,CAAM,CAAsB,mBAAA,EAAA,IAAI,CAAwB,sBAAA,CAAA,CAAA;AAAA;AAEpE,QAA0B,uBAAA,GAAA,SAAA;AAAA,OAC5B;AAAA,MACA,yBAAA,CACE,WACA,QACA,EAAA;AACA,QAAA,iBAAA,CAAkB,SAAS,CAAI,GAAA,QAAA;AAAA;AACjC,KACD,CAAA;AAED,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,UAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,MAAMA,6BAAa,CAAA,UAAA;AAAA,QACnB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,OAAOA,6BAAa,CAAA,KAAA;AAAA,QACpB,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,OAAS,EAAAC;AAAA,OACX;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,IAAA;AAAA,QACA,SAAA;AAAA,QACA,KAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAM,MAAA,aAAA,GAAgBC,oCAAsB,MAAM,CAAA;AAElD,QAAA,MAAM,SAAY,GAAA,MAAMC,4BAAU,CAAA,UAAA,CAAW,MAAQ,EAAA;AAAA,UACnD,MAAQ,EAAA,SAAA;AAAA,UACR,MAAQ,EAAA;AAAA,SACT,CAAA;AACD,QAAA,KAAA,MAAW,CAAC,QAAU,EAAA,QAAQ,CAAK,IAAA,eAAA,CAAgB,SAAW,EAAA;AAC5D,UAAU,SAAA,CAAA,QAAA,CAAS,UAAU,QAAQ,CAAA;AAAA;AAIvC,QAAA,MAAM,UAAa,GAAA,MAAMC,6BAAW,CAAA,UAAA,CAAW,MAAQ,EAAA;AAAA,UACrD,MAAQ,EAAA,aAAA;AAAA,UACR,eAAiB,EAAA;AAAA,SAClB,CAAA;AAKD,QAAA,MAAM,SAAY,GAAA,MAAMC,4BAAU,CAAA,UAAA,CAAW,MAAQ,EAAA;AAAA,UACnD,MAAQ,EAAA,aAAA;AAAA,UACR,SAAA;AAAA,UACA,eAAiB,EAAA,uBAAA;AAAA,UACjB;AAAA,SACD,CAAA;AAGD,QAAA,MAAM,UAAU,YAAa,EAAA;AAE7B,QAAM,MAAA,YAAA,GAAeC,wCAA0B,KAAK,CAAA;AACpD,QAAK,IAAA,CAAA,GAAA;AAAA,UACH,MAAMC,mBAAa,CAAA;AAAA,YACjB,MAAQ,EAAA,aAAA;AAAA,YACR,KAAO,EAAA,YAAA;AAAA,YACP,iBAAA;AAAA,YACA,iBAAA;AAAA,YACA,SAAA;AAAA,YACA,UAAA;AAAA,YACA,SAAA;AAAA,YACA,MAAA;AAAA,YACA,SAAA;AAAA,YACA,QAAA;AAAA,YACA,IAAA;AAAA,YACA,aAAe,EAAA;AAAA,WAChB;AAAA,SACH;AAEA,QAAA,IAAA,CAAK,aAAc,CAAA;AAAA,UACjB,IAAM,EAAA,SAAA;AAAA,UACN,KAAO,EAAA;AAAA,SACR,CAAA;AAAA;AACH,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport {\n DocsBuildStrategy,\n Generators,\n PreparerBase,\n Preparers,\n Publisher,\n PublisherBase,\n PublisherSettings,\n PublisherType,\n RemoteProtocol,\n techdocsBuildsExtensionPoint,\n TechdocsGenerator,\n techdocsGeneratorExtensionPoint,\n techdocsPreparerExtensionPoint,\n techdocsPublisherExtensionPoint,\n} from '@backstage/plugin-techdocs-node';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport * as winston from 'winston';\nimport { createRouter } from './service/router';\n\n/**\n * The TechDocs plugin is responsible for serving and building documentation for any entity.\n * @public\n */\nexport const techdocsPlugin = createBackendPlugin({\n pluginId: 'techdocs',\n register(env) {\n let docsBuildStrategy: DocsBuildStrategy | undefined;\n let buildLogTransport: winston.transport | undefined;\n env.registerExtensionPoint(techdocsBuildsExtensionPoint, {\n setBuildStrategy(buildStrategy: DocsBuildStrategy) {\n if (docsBuildStrategy) {\n throw new Error('DocsBuildStrategy may only be set once');\n }\n docsBuildStrategy = buildStrategy;\n },\n setBuildLogTransport(transport: winston.transport) {\n if (buildLogTransport) {\n throw new Error('BuildLogTransport may only be set once');\n }\n buildLogTransport = transport;\n },\n });\n\n let customTechdocsGenerator: TechdocsGenerator | undefined;\n env.registerExtensionPoint(techdocsGeneratorExtensionPoint, {\n setTechdocsGenerator(generator: TechdocsGenerator) {\n if (customTechdocsGenerator) {\n throw new Error('TechdocsGenerator may only be set once');\n }\n\n customTechdocsGenerator = generator;\n },\n });\n\n const customPreparers = new Map<RemoteProtocol, PreparerBase>();\n env.registerExtensionPoint(techdocsPreparerExtensionPoint, {\n registerPreparer(protocol: RemoteProtocol, preparer: PreparerBase) {\n if (customPreparers.has(protocol)) {\n throw new Error(\n `Preparer for protocol ${protocol} is already registered`,\n );\n }\n customPreparers.set(protocol, preparer);\n },\n });\n\n let customTechdocsPublisher: PublisherBase | undefined;\n const publisherSettings: PublisherSettings = {};\n env.registerExtensionPoint(techdocsPublisherExtensionPoint, {\n registerPublisher(type: PublisherType, publisher: PublisherBase) {\n if (customTechdocsPublisher) {\n throw new Error(`Publisher for type ${type} is already registered`);\n }\n customTechdocsPublisher = publisher;\n },\n registerPublisherSettings<T extends keyof PublisherSettings>(\n publisher: T,\n settings: PublisherSettings[T],\n ) {\n publisherSettings[publisher] = settings;\n },\n });\n\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n urlReader: coreServices.urlReader,\n http: coreServices.httpRouter,\n discovery: coreServices.discovery,\n cache: coreServices.cache,\n httpAuth: coreServices.httpAuth,\n auth: coreServices.auth,\n catalog: catalogServiceRef,\n },\n async init({\n config,\n logger,\n urlReader,\n http,\n discovery,\n cache,\n httpAuth,\n auth,\n catalog,\n }) {\n // Preparers are responsible for fetching source files for documentation.\n const preparers = await Preparers.fromConfig(config, {\n reader: urlReader,\n logger: logger,\n });\n for (const [protocol, preparer] of customPreparers.entries()) {\n preparers.register(protocol, preparer);\n }\n\n // Generators are used for generating documentation sites.\n const generators = await Generators.fromConfig(config, {\n logger: logger,\n customGenerator: customTechdocsGenerator,\n });\n\n // Publisher is used for\n // 1. Publishing generated files to storage\n // 2. Fetching files from storage and passing them to TechDocs frontend.\n const publisher = await Publisher.fromConfig(config, {\n logger: logger,\n discovery: discovery,\n customPublisher: customTechdocsPublisher,\n publisherSettings,\n });\n\n // checks if the publisher is working and logs the result\n await publisher.getReadiness();\n\n http.use(\n await createRouter({\n logger: logger,\n cache,\n docsBuildStrategy,\n buildLogTransport,\n preparers,\n generators,\n publisher,\n config,\n discovery,\n httpAuth,\n auth,\n catalogClient: catalog,\n }),\n );\n\n http.addAuthPolicy({\n path: '/static',\n allow: 'user-cookie',\n });\n },\n });\n },\n});\n"],"names":["createBackendPlugin","techdocsBuildsExtensionPoint","techdocsGeneratorExtensionPoint","techdocsPreparerExtensionPoint","techdocsPublisherExtensionPoint","coreServices","catalogServiceRef","Preparers","Generators","Publisher","createRouter"],"mappings":";;;;;;;AA4CO,MAAM,iBAAiBA,oCAAoB,CAAA;AAAA,EAChD,QAAU,EAAA,UAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAI,IAAA,iBAAA;AACJ,IAAI,IAAA,iBAAA;AACJ,IAAA,GAAA,CAAI,uBAAuBC,+CAA8B,EAAA;AAAA,MACvD,iBAAiB,aAAkC,EAAA;AACjD,QAAA,IAAI,iBAAmB,EAAA;AACrB,UAAM,MAAA,IAAI,MAAM,wCAAwC,CAAA;AAAA;AAE1D,QAAoB,iBAAA,GAAA,aAAA;AAAA,OACtB;AAAA,MACA,qBAAqB,SAA8B,EAAA;AACjD,QAAA,IAAI,iBAAmB,EAAA;AACrB,UAAM,MAAA,IAAI,MAAM,wCAAwC,CAAA;AAAA;AAE1D,QAAoB,iBAAA,GAAA,SAAA;AAAA;AACtB,KACD,CAAA;AAED,IAAI,IAAA,uBAAA;AACJ,IAAA,GAAA,CAAI,uBAAuBC,kDAAiC,EAAA;AAAA,MAC1D,qBAAqB,SAA8B,EAAA;AACjD,QAAA,IAAI,uBAAyB,EAAA;AAC3B,UAAM,MAAA,IAAI,MAAM,wCAAwC,CAAA;AAAA;AAG1D,QAA0B,uBAAA,GAAA,SAAA;AAAA;AAC5B,KACD,CAAA;AAED,IAAM,MAAA,eAAA,uBAAsB,GAAkC,EAAA;AAC9D,IAAA,GAAA,CAAI,uBAAuBC,iDAAgC,EAAA;AAAA,MACzD,gBAAA,CAAiB,UAA0B,QAAwB,EAAA;AACjE,QAAI,IAAA,eAAA,CAAgB,GAAI,CAAA,QAAQ,CAAG,EAAA;AACjC,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,yBAAyB,QAAQ,CAAA,sBAAA;AAAA,WACnC;AAAA;AAEF,QAAgB,eAAA,CAAA,GAAA,CAAI,UAAU,QAAQ,CAAA;AAAA;AACxC,KACD,CAAA;AAED,IAAI,IAAA,uBAAA;AACJ,IAAA,MAAM,oBAAuC,EAAC;AAC9C,IAAA,GAAA,CAAI,uBAAuBC,kDAAiC,EAAA;AAAA,MAC1D,iBAAA,CAAkB,MAAqB,SAA0B,EAAA;AAC/D,QAAA,IAAI,uBAAyB,EAAA;AAC3B,UAAA,MAAM,IAAI,KAAA,CAAM,CAAsB,mBAAA,EAAA,IAAI,CAAwB,sBAAA,CAAA,CAAA;AAAA;AAEpE,QAA0B,uBAAA,GAAA,SAAA;AAAA,OAC5B;AAAA,MACA,yBAAA,CACE,WACA,QACA,EAAA;AACA,QAAA,iBAAA,CAAkB,SAAS,CAAI,GAAA,QAAA;AAAA;AACjC,KACD,CAAA;AAED,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,UAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,MAAMA,6BAAa,CAAA,UAAA;AAAA,QACnB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,OAAOA,6BAAa,CAAA,KAAA;AAAA,QACpB,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,OAAS,EAAAC;AAAA,OACX;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,IAAA;AAAA,QACA,SAAA;AAAA,QACA,KAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACC,EAAA;AAED,QAAA,MAAM,SAAY,GAAA,MAAMC,4BAAU,CAAA,UAAA,CAAW,MAAQ,EAAA;AAAA,UACnD,MAAQ,EAAA,SAAA;AAAA,UACR;AAAA,SACD,CAAA;AACD,QAAA,KAAA,MAAW,CAAC,QAAU,EAAA,QAAQ,CAAK,IAAA,eAAA,CAAgB,SAAW,EAAA;AAC5D,UAAU,SAAA,CAAA,QAAA,CAAS,UAAU,QAAQ,CAAA;AAAA;AAIvC,QAAA,MAAM,UAAa,GAAA,MAAMC,6BAAW,CAAA,UAAA,CAAW,MAAQ,EAAA;AAAA,UACrD,MAAA;AAAA,UACA,eAAiB,EAAA;AAAA,SAClB,CAAA;AAKD,QAAA,MAAM,SAAY,GAAA,MAAMC,4BAAU,CAAA,UAAA,CAAW,MAAQ,EAAA;AAAA,UACnD,MAAA;AAAA,UACA,SAAA;AAAA,UACA,eAAiB,EAAA,uBAAA;AAAA,UACjB;AAAA,SACD,CAAA;AAGD,QAAA,MAAM,UAAU,YAAa,EAAA;AAE7B,QAAK,IAAA,CAAA,GAAA;AAAA,UACH,MAAMC,mBAAa,CAAA;AAAA,YACjB,MAAA;AAAA,YACA,KAAA;AAAA,YACA,iBAAA;AAAA,YACA,iBAAA;AAAA,YACA,SAAA;AAAA,YACA,UAAA;AAAA,YACA,SAAA;AAAA,YACA,MAAA;AAAA,YACA,SAAA;AAAA,YACA,QAAA;AAAA,YACA,IAAA;AAAA,YACA,aAAe,EAAA;AAAA,WAChB;AAAA,SACH;AAEA,QAAA,IAAA,CAAK,aAAc,CAAA;AAAA,UACjB,IAAM,EAAA,SAAA;AAAA,UACN,KAAO,EAAA;AAAA,SACR,CAAA;AAAA;AACH,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DocsSynchronizer.cjs.js","sources":["../../src/service/DocsSynchronizer.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DEFAULT_NAMESPACE,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { assertError, NotFoundError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport {\n GeneratorBuilder,\n PreparerBuilder,\n PublisherBase,\n} from '@backstage/plugin-techdocs-node';\nimport pLimit, { Limit } from 'p-limit';\nimport { PassThrough } from 'stream';\nimport * as winston from 'winston';\nimport { TechDocsCache } from '../cache';\nimport {\n BuildMetadataStorage,\n DocsBuilder,\n shouldCheckForUpdate,\n} from '../DocsBuilder';\nimport { DiscoveryService } from '@backstage/backend-plugin-api';\n\nexport type DocsSynchronizerSyncOpts = {\n log: (message: string) => void;\n error: (e: Error) => void;\n finish: (result: { updated: boolean }) => void;\n};\n\nexport class DocsSynchronizer {\n private readonly publisher: PublisherBase;\n private readonly logger: winston.Logger;\n private readonly buildLogTransport?: winston.transport;\n private readonly config: Config;\n private readonly scmIntegrations: ScmIntegrationRegistry;\n private readonly cache: TechDocsCache | undefined;\n private readonly buildLimiter: Limit;\n\n constructor({\n publisher,\n logger,\n buildLogTransport,\n config,\n scmIntegrations,\n cache,\n }: {\n publisher: PublisherBase;\n logger: winston.Logger;\n buildLogTransport?: winston.transport;\n config: Config;\n scmIntegrations: ScmIntegrationRegistry;\n cache: TechDocsCache | undefined;\n }) {\n this.config = config;\n this.logger = logger;\n this.buildLogTransport = buildLogTransport;\n this.publisher = publisher;\n this.scmIntegrations = scmIntegrations;\n this.cache = cache;\n\n // Single host/process: limit concurrent builds up to 10 at a time.\n this.buildLimiter = pLimit(10);\n }\n\n async doSync({\n responseHandler: { log, error, finish },\n entity,\n preparers,\n generators,\n }: {\n responseHandler: DocsSynchronizerSyncOpts;\n entity: Entity;\n preparers: PreparerBuilder;\n generators: GeneratorBuilder;\n }) {\n // create a new logger to log data to the caller\n const taskLogger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.timestamp(),\n winston.format.simple(),\n ),\n defaultMeta: {},\n });\n\n // create an in-memory stream to forward logs to the event-stream\n const logStream = new PassThrough();\n logStream.on('data', async data => {\n log(data.toString().trim());\n });\n\n taskLogger.add(new winston.transports.Stream({ stream: logStream }));\n if (this.buildLogTransport) {\n taskLogger.add(this.buildLogTransport);\n }\n\n // check if the last update check was too recent\n if (!shouldCheckForUpdate(entity.metadata.uid!)) {\n finish({ updated: false });\n return;\n }\n\n let foundDocs = false;\n\n try {\n const docsBuilder = new DocsBuilder({\n preparers,\n generators,\n publisher: this.publisher,\n logger: taskLogger,\n entity,\n config: this.config,\n scmIntegrations: this.scmIntegrations,\n logStream,\n cache: this.cache,\n });\n\n const interval = setInterval(() => {\n taskLogger.info(\n 'The docs building process is taking a little bit longer to process this entity. Please bear with us.',\n );\n }, 10000);\n const updated = await this.buildLimiter(() => docsBuilder.build());\n clearInterval(interval);\n\n if (!updated) {\n finish({ updated: false });\n return;\n }\n } catch (e) {\n assertError(e);\n const msg = `Failed to build the docs page for entity ${stringifyEntityRef(\n entity,\n )}: ${e.message}`;\n taskLogger.error(msg);\n this.logger.error(msg, e);\n error(e);\n return;\n }\n\n // With a maximum of ~5 seconds wait, check if the files got published and if docs will be fetched\n // on the user's page. If not, respond with a message asking them to check back later.\n // The delay here is to make sure GCS/AWS/etc. registers newly uploaded files which is usually <1 second\n for (let attempt = 0; attempt < 5; attempt++) {\n if (await this.publisher.hasDocsBeenGenerated(entity)) {\n foundDocs = true;\n break;\n }\n await new Promise(r => setTimeout(r, 1000));\n }\n if (!foundDocs) {\n this.logger.error(\n 'Published files are taking longer to show up in storage. Something went wrong.',\n );\n error(\n new NotFoundError(\n 'Sorry! It took too long for the generated docs to show up in storage. Are you sure the docs project is generating an `index.html` file? Otherwise, check back later.',\n ),\n );\n return;\n }\n\n finish({ updated: true });\n }\n\n async doCacheSync({\n responseHandler: { finish },\n discovery,\n token,\n entity,\n }: {\n responseHandler: DocsSynchronizerSyncOpts;\n discovery: DiscoveryService;\n token: string | undefined;\n entity: Entity;\n }) {\n // Check if the last update check was too recent.\n if (!shouldCheckForUpdate(entity.metadata.uid!) || !this.cache) {\n finish({ updated: false });\n return;\n }\n\n // Fetch techdocs_metadata.json from the publisher and from cache.\n const baseUrl = await discovery.getBaseUrl('techdocs');\n const namespace = entity.metadata?.namespace || DEFAULT_NAMESPACE;\n const kind = entity.kind;\n const name = entity.metadata.name;\n const legacyPathCasing =\n this.config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n ) || false;\n const tripletPath = `${namespace}/${kind}/${name}`;\n const entityTripletPath = `${\n legacyPathCasing ? tripletPath : tripletPath.toLocaleLowerCase('en-US')\n }`;\n try {\n const [sourceMetadata, cachedMetadata] = await Promise.all([\n this.publisher.fetchTechDocsMetadata({ namespace, kind, name }),\n fetch(\n `${baseUrl}/static/docs/${entityTripletPath}/techdocs_metadata.json`,\n {\n headers: token ? { Authorization: `Bearer ${token}` } : {},\n },\n ).then(\n f =>\n f.json().catch(() => undefined) as ReturnType<\n PublisherBase['fetchTechDocsMetadata']\n >,\n ),\n ]);\n\n // If build timestamps differ, merge their files[] lists and invalidate all objects.\n if (sourceMetadata.build_timestamp !== cachedMetadata.build_timestamp) {\n const files = [\n ...new Set([\n ...(sourceMetadata.files || []),\n ...(cachedMetadata.files || []),\n ]),\n ].map(f => `${entityTripletPath}/${f}`);\n await this.cache.invalidateMultiple(files);\n finish({ updated: true });\n } else {\n finish({ updated: false });\n }\n } catch (e) {\n assertError(e);\n // In case of error, log and allow the user to go about their business.\n this.logger.error(\n `Error syncing cache for ${entityTripletPath}: ${e.message}`,\n );\n finish({ updated: false });\n } finally {\n // Update the last check time for the entity\n new BuildMetadataStorage(entity.metadata.uid!).setLastUpdated();\n }\n }\n}\n"],"names":["pLimit","winston","PassThrough","shouldCheckForUpdate","DocsBuilder","assertError","stringifyEntityRef","NotFoundError","DEFAULT_NAMESPACE","BuildMetadataStorage"],"mappings":"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"}
1
+ {"version":3,"file":"DocsSynchronizer.cjs.js","sources":["../../src/service/DocsSynchronizer.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DEFAULT_NAMESPACE,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { assertError, NotFoundError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport {\n GeneratorBuilder,\n PreparerBuilder,\n PublisherBase,\n} from '@backstage/plugin-techdocs-node';\nimport pLimit, { Limit } from 'p-limit';\nimport { PassThrough } from 'stream';\nimport * as winston from 'winston';\nimport { TechDocsCache } from '../cache';\nimport {\n BuildMetadataStorage,\n DocsBuilder,\n shouldCheckForUpdate,\n} from '../DocsBuilder';\nimport { DiscoveryService, LoggerService } from '@backstage/backend-plugin-api';\n\nexport type DocsSynchronizerSyncOpts = {\n log: (message: string) => void;\n error: (e: Error) => void;\n finish: (result: { updated: boolean }) => void;\n};\n\nexport class DocsSynchronizer {\n private readonly publisher: PublisherBase;\n private readonly logger: LoggerService;\n private readonly buildLogTransport?: winston.transport;\n private readonly config: Config;\n private readonly scmIntegrations: ScmIntegrationRegistry;\n private readonly cache: TechDocsCache | undefined;\n private readonly buildLimiter: Limit;\n\n constructor({\n publisher,\n logger,\n buildLogTransport,\n config,\n scmIntegrations,\n cache,\n }: {\n publisher: PublisherBase;\n logger: LoggerService;\n buildLogTransport?: winston.transport;\n config: Config;\n scmIntegrations: ScmIntegrationRegistry;\n cache: TechDocsCache | undefined;\n }) {\n this.config = config;\n this.logger = logger;\n this.buildLogTransport = buildLogTransport;\n this.publisher = publisher;\n this.scmIntegrations = scmIntegrations;\n this.cache = cache;\n\n // Single host/process: limit concurrent builds up to 10 at a time.\n this.buildLimiter = pLimit(10);\n }\n\n async doSync({\n responseHandler: { log, error, finish },\n entity,\n preparers,\n generators,\n }: {\n responseHandler: DocsSynchronizerSyncOpts;\n entity: Entity;\n preparers: PreparerBuilder;\n generators: GeneratorBuilder;\n }) {\n // create a new logger to log data to the caller\n const taskLogger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.timestamp(),\n winston.format.simple(),\n ),\n defaultMeta: {},\n });\n\n // create an in-memory stream to forward logs to the event-stream\n const logStream = new PassThrough();\n logStream.on('data', async data => {\n log(data.toString().trim());\n });\n\n taskLogger.add(new winston.transports.Stream({ stream: logStream }));\n if (this.buildLogTransport) {\n taskLogger.add(this.buildLogTransport);\n }\n\n // check if the last update check was too recent\n if (!shouldCheckForUpdate(entity.metadata.uid!)) {\n finish({ updated: false });\n return;\n }\n\n let foundDocs = false;\n\n try {\n const docsBuilder = new DocsBuilder({\n preparers,\n generators,\n publisher: this.publisher,\n logger: taskLogger,\n entity,\n config: this.config,\n scmIntegrations: this.scmIntegrations,\n logStream,\n cache: this.cache,\n });\n\n const interval = setInterval(() => {\n taskLogger.info(\n 'The docs building process is taking a little bit longer to process this entity. Please bear with us.',\n );\n }, 10000);\n const updated = await this.buildLimiter(() => docsBuilder.build());\n clearInterval(interval);\n\n if (!updated) {\n finish({ updated: false });\n return;\n }\n } catch (e) {\n assertError(e);\n const msg = `Failed to build the docs page for entity ${stringifyEntityRef(\n entity,\n )}: ${e.message}`;\n taskLogger.error(msg);\n this.logger.error(msg, e);\n error(e);\n return;\n }\n\n // With a maximum of ~5 seconds wait, check if the files got published and if docs will be fetched\n // on the user's page. If not, respond with a message asking them to check back later.\n // The delay here is to make sure GCS/AWS/etc. registers newly uploaded files which is usually <1 second\n for (let attempt = 0; attempt < 5; attempt++) {\n if (await this.publisher.hasDocsBeenGenerated(entity)) {\n foundDocs = true;\n break;\n }\n await new Promise(r => setTimeout(r, 1000));\n }\n if (!foundDocs) {\n this.logger.error(\n 'Published files are taking longer to show up in storage. Something went wrong.',\n );\n error(\n new NotFoundError(\n 'Sorry! It took too long for the generated docs to show up in storage. Are you sure the docs project is generating an `index.html` file? Otherwise, check back later.',\n ),\n );\n return;\n }\n\n finish({ updated: true });\n }\n\n async doCacheSync({\n responseHandler: { finish },\n discovery,\n token,\n entity,\n }: {\n responseHandler: DocsSynchronizerSyncOpts;\n discovery: DiscoveryService;\n token: string | undefined;\n entity: Entity;\n }) {\n // Check if the last update check was too recent.\n if (!shouldCheckForUpdate(entity.metadata.uid!) || !this.cache) {\n finish({ updated: false });\n return;\n }\n\n // Fetch techdocs_metadata.json from the publisher and from cache.\n const baseUrl = await discovery.getBaseUrl('techdocs');\n const namespace = entity.metadata?.namespace || DEFAULT_NAMESPACE;\n const kind = entity.kind;\n const name = entity.metadata.name;\n const legacyPathCasing =\n this.config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n ) || false;\n const tripletPath = `${namespace}/${kind}/${name}`;\n const entityTripletPath = `${\n legacyPathCasing ? tripletPath : tripletPath.toLocaleLowerCase('en-US')\n }`;\n try {\n const [sourceMetadata, cachedMetadata] = await Promise.all([\n this.publisher.fetchTechDocsMetadata({ namespace, kind, name }),\n fetch(\n `${baseUrl}/static/docs/${entityTripletPath}/techdocs_metadata.json`,\n {\n headers: token ? { Authorization: `Bearer ${token}` } : {},\n },\n ).then(\n f =>\n f.json().catch(() => undefined) as ReturnType<\n PublisherBase['fetchTechDocsMetadata']\n >,\n ),\n ]);\n\n // If build timestamps differ, merge their files[] lists and invalidate all objects.\n if (sourceMetadata.build_timestamp !== cachedMetadata.build_timestamp) {\n const files = [\n ...new Set([\n ...(sourceMetadata.files || []),\n ...(cachedMetadata.files || []),\n ]),\n ].map(f => `${entityTripletPath}/${f}`);\n await this.cache.invalidateMultiple(files);\n finish({ updated: true });\n } else {\n finish({ updated: false });\n }\n } catch (e) {\n assertError(e);\n // In case of error, log and allow the user to go about their business.\n this.logger.error(\n `Error syncing cache for ${entityTripletPath}: ${e.message}`,\n );\n finish({ updated: false });\n } finally {\n // Update the last check time for the entity\n new BuildMetadataStorage(entity.metadata.uid!).setLastUpdated();\n }\n }\n}\n"],"names":["pLimit","winston","PassThrough","shouldCheckForUpdate","DocsBuilder","assertError","stringifyEntityRef","NotFoundError","DEFAULT_NAMESPACE","BuildMetadataStorage"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var backendCommon = require('@backstage/backend-common');
4
3
  var catalogClient = require('@backstage/catalog-client');
5
4
  var catalogModel = require('@backstage/catalog-model');
6
5
  var errors = require('@backstage/errors');
@@ -22,19 +21,18 @@ function isOutOfTheBoxOption(opt) {
22
21
  }
23
22
  async function createRouter(options) {
24
23
  const router = router__default.default();
25
- const { publisher, config, logger, discovery } = options;
26
- const { auth, httpAuth } = backendCommon.createLegacyAuthAdapters(options);
24
+ const { publisher, config, logger, discovery, httpAuth, auth } = options;
27
25
  const catalogClient$1 = options.catalogClient ?? new catalogClient.CatalogClient({ discoveryApi: discovery });
28
26
  const docsBuildStrategy = options.docsBuildStrategy ?? DefaultDocsBuildStrategy.DefaultDocsBuildStrategy.fromConfig(config);
29
27
  const buildLogTransport = options.buildLogTransport;
30
28
  const entityLoader = new CachedEntityLoader.CachedEntityLoader({
31
29
  catalog: catalogClient$1,
32
- cache: options.cache.getClient()
30
+ cache: options.cache
33
31
  });
34
32
  let cache;
35
33
  const defaultTtl = config.getOptionalNumber("techdocs.cache.ttl");
36
34
  if (defaultTtl) {
37
- const cacheClient = options.cache.getClient({ defaultTtl });
35
+ const cacheClient = options.cache.withOptions({ defaultTtl });
38
36
  cache = TechDocsCache.TechDocsCache.fromConfig(config, { cache: cacheClient, logger });
39
37
  }
40
38
  const scmIntegrations = integration.ScmIntegrations.fromConfig(config);
@@ -1 +1 @@
1
- {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createLegacyAuthAdapters,\n PluginCacheManager,\n} from '@backstage/backend-common';\nimport { CatalogApi, CatalogClient } from '@backstage/catalog-client';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { NotFoundError } from '@backstage/errors';\nimport {\n DocsBuildStrategy,\n GeneratorBuilder,\n getLocationForEntity,\n PreparerBuilder,\n PublisherBase,\n} from '@backstage/plugin-techdocs-node';\nimport express, { Response } from 'express';\nimport Router from 'express-promise-router';\nimport { Knex } from 'knex';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer';\nimport { createCacheMiddleware, TechDocsCache } from '../cache';\nimport { CachedEntityLoader } from './CachedEntityLoader';\nimport { DefaultDocsBuildStrategy } from './DefaultDocsBuildStrategy';\nimport * as winston from 'winston';\nimport {\n AuthService,\n DiscoveryService,\n HttpAuthService,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Required dependencies for running TechDocs in the \"out-of-the-box\"\n * deployment configuration (prepare/generate/publish all in the Backend).\n *\n * @public\n */\nexport type OutOfTheBoxDeploymentOptions = {\n preparers: PreparerBuilder;\n generators: GeneratorBuilder;\n publisher: PublisherBase;\n logger: winston.Logger;\n discovery: DiscoveryService;\n database?: Knex; // TODO: Make database required when we're implementing database stuff.\n config: Config;\n cache: PluginCacheManager;\n docsBuildStrategy?: DocsBuildStrategy;\n buildLogTransport?: winston.transport;\n catalogClient?: CatalogApi;\n httpAuth?: HttpAuthService;\n auth?: AuthService;\n};\n\n/**\n * Required dependencies for running TechDocs in the \"recommended\" deployment\n * configuration (prepare/generate handled externally in CI/CD).\n *\n * @public\n * @deprecated This type is only exported for legacy reasons and will be removed in the future.\n */\nexport type RecommendedDeploymentOptions = {\n publisher: PublisherBase;\n logger: winston.Logger;\n discovery: DiscoveryService;\n config: Config;\n cache: PluginCacheManager;\n docsBuildStrategy?: DocsBuildStrategy;\n buildLogTransport?: winston.transport;\n catalogClient?: CatalogApi;\n httpAuth?: HttpAuthService;\n auth?: AuthService;\n};\n\n/**\n * One of the two deployment configurations must be provided.\n *\n * @public\n * @deprecated This type is only exported for legacy reasons and will be removed in the future.\n */\nexport type RouterOptions =\n | RecommendedDeploymentOptions\n | OutOfTheBoxDeploymentOptions;\n\n/**\n * Typeguard to help createRouter() understand when we are in a \"recommended\"\n * deployment vs. when we are in an out-of-the-box deployment configuration.\n *\n * @public\n */\nfunction isOutOfTheBoxOption(\n opt: RouterOptions,\n): opt is OutOfTheBoxDeploymentOptions {\n return (opt as OutOfTheBoxDeploymentOptions).preparers !== undefined;\n}\n\n/**\n * Creates a techdocs router.\n *\n * @public\n * @deprecated This function is only exported for legacy reasons and will be removed in the future.\n * Please {@link https://backstage.io/docs/backend-system/building-backends/migrating | migrate } to use the new backend system and follow these {@link https://backstage.io/docs/features/techdocs/getting-started#new-backend-system | instructions } to install the user settings backend plugin.\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n const { publisher, config, logger, discovery } = options;\n\n const { auth, httpAuth } = createLegacyAuthAdapters(options);\n\n const catalogClient =\n options.catalogClient ?? new CatalogClient({ discoveryApi: discovery });\n const docsBuildStrategy =\n options.docsBuildStrategy ?? DefaultDocsBuildStrategy.fromConfig(config);\n const buildLogTransport = options.buildLogTransport;\n\n // Entities are cached to optimize the /static/docs request path, which can be called many times\n // when loading a single techdocs page.\n const entityLoader = new CachedEntityLoader({\n catalog: catalogClient,\n cache: options.cache.getClient(),\n });\n\n // Set up a cache client if configured.\n let cache: TechDocsCache | undefined;\n const defaultTtl = config.getOptionalNumber('techdocs.cache.ttl');\n if (defaultTtl) {\n const cacheClient = options.cache.getClient({ defaultTtl });\n cache = TechDocsCache.fromConfig(config, { cache: cacheClient, logger });\n }\n\n const scmIntegrations = ScmIntegrations.fromConfig(config);\n const docsSynchronizer = new DocsSynchronizer({\n publisher,\n logger,\n buildLogTransport,\n config,\n scmIntegrations,\n cache,\n });\n\n router.get('/metadata/techdocs/:namespace/:kind/:name', async (req, res) => {\n const { kind, namespace, name } = req.params;\n const entityName = { kind, namespace, name };\n\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n // Verify that the related entity exists and the current user has permission to view it.\n const entity = await entityLoader.load(entityName, token);\n\n if (!entity) {\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n );\n }\n\n try {\n const techdocsMetadata = await publisher.fetchTechDocsMetadata(\n entityName,\n );\n\n res.json(techdocsMetadata);\n } catch (err) {\n logger.info(\n `Unable to get metadata for '${stringifyEntityRef(\n entityName,\n )}' with error ${err}`,\n );\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n err,\n );\n }\n });\n\n router.get('/metadata/entity/:namespace/:kind/:name', async (req, res) => {\n const { kind, namespace, name } = req.params;\n const entityName = { kind, namespace, name };\n\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const entity = await entityLoader.load(entityName, token);\n\n if (!entity) {\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n );\n }\n\n try {\n const locationMetadata = getLocationForEntity(entity, scmIntegrations);\n res.json({ ...entity, locationMetadata });\n } catch (err) {\n logger.info(\n `Unable to get metadata for '${stringifyEntityRef(\n entityName,\n )}' with error ${err}`,\n );\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n err,\n );\n }\n });\n\n // Check if docs are the latest version and trigger rebuilds if not\n // Responds with an event-stream that closes after the build finished\n // Responds with an immediate success if rebuild not needed\n // If a build is required, responds with a success when finished\n router.get('/sync/:namespace/:kind/:name', async (req, res) => {\n const { kind, namespace, name } = req.params;\n\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const entity = await entityLoader.load({ kind, namespace, name }, token);\n\n if (!entity?.metadata?.uid) {\n throw new NotFoundError('Entity metadata UID missing');\n }\n\n const responseHandler: DocsSynchronizerSyncOpts = createEventStream(res);\n\n // By default, techdocs-backend will only try to build documentation for an entity if techdocs.builder is set to\n // 'local'. If set to 'external', it will assume that an external process (e.g. CI/CD pipeline\n // of the repository) is responsible for building and publishing documentation to the storage provider.\n // Altering the implementation of the injected docsBuildStrategy allows for more complex behaviours, based on\n // either config or the properties of the entity (e.g. annotations, labels, spec fields etc.).\n const shouldBuild = await docsBuildStrategy.shouldBuild({ entity });\n if (!shouldBuild) {\n // However, if caching is enabled, take the opportunity to check and\n // invalidate stale cache entries.\n if (cache) {\n const { token: techDocsToken } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'techdocs',\n });\n await docsSynchronizer.doCacheSync({\n responseHandler,\n discovery,\n token: techDocsToken,\n entity,\n });\n return;\n }\n responseHandler.finish({ updated: false });\n return;\n }\n\n // Set the synchronization and build process if \"out-of-the-box\" configuration is provided.\n if (isOutOfTheBoxOption(options)) {\n const { preparers, generators } = options;\n\n await docsSynchronizer.doSync({\n responseHandler,\n entity,\n preparers,\n generators,\n });\n return;\n }\n\n responseHandler.error(\n new Error(\n \"Invalid configuration. docsBuildStrategy.shouldBuild returned 'true', but no 'preparer' was provided to the router initialization.\",\n ),\n );\n });\n\n // Ensures that the related entity exists and the current user has permission to view it.\n if (config.getOptionalBoolean('permission.enabled')) {\n router.use(\n '/static/docs/:namespace/:kind/:name',\n async (req, _res, next) => {\n const { kind, namespace, name } = req.params;\n const entityName = { kind, namespace, name };\n\n const credentials = await httpAuth.credentials(req, {\n allowLimitedAccess: true,\n });\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const entity = await entityLoader.load(entityName, token);\n\n if (!entity) {\n throw new NotFoundError(\n `Entity not found for ${stringifyEntityRef(entityName)}`,\n );\n }\n\n next();\n },\n );\n }\n\n // If a cache manager was provided, attach the cache middleware.\n if (cache) {\n router.use(createCacheMiddleware({ logger, cache }));\n }\n\n // Route middleware which serves files from the storage set in the publisher.\n router.use('/static/docs', publisher.docsRouter());\n\n return router;\n}\n\n/**\n * Create an event-stream response that emits the events 'log', 'error', and 'finish'.\n *\n * @param res - the response to write the event-stream to\n * @returns A tuple of <log, error, finish> callbacks to emit messages. A call to 'error' or 'finish'\n * will close the event-stream.\n */\nexport function createEventStream(\n res: Response<any, any>,\n): DocsSynchronizerSyncOpts {\n // Mandatory headers and http status to keep connection open\n res.writeHead(200, {\n Connection: 'keep-alive',\n 'Cache-Control': 'no-cache',\n 'Content-Type': 'text/event-stream',\n });\n\n // client closes connection\n res.socket?.on('close', () => {\n res.end();\n });\n\n // write the event to the stream\n const send = (type: 'error' | 'finish' | 'log', data: any) => {\n res.write(`event: ${type}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n\n // res.flush() is only available with the compression middleware\n if (res.flush) {\n res.flush();\n }\n };\n\n return {\n log: data => {\n send('log', data);\n },\n\n error: e => {\n send('error', e.message);\n res.end();\n },\n\n finish: result => {\n send('finish', result);\n res.end();\n },\n };\n}\n"],"names":["Router","createLegacyAuthAdapters","catalogClient","CatalogClient","DefaultDocsBuildStrategy","CachedEntityLoader","TechDocsCache","ScmIntegrations","DocsSynchronizer","NotFoundError","stringifyEntityRef","getLocationForEntity","createCacheMiddleware"],"mappings":"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"}
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CatalogApi, CatalogClient } from '@backstage/catalog-client';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { NotFoundError } from '@backstage/errors';\nimport {\n DocsBuildStrategy,\n GeneratorBuilder,\n getLocationForEntity,\n PreparerBuilder,\n PublisherBase,\n} from '@backstage/plugin-techdocs-node';\nimport express, { Response } from 'express';\nimport Router from 'express-promise-router';\nimport { Knex } from 'knex';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer';\nimport { createCacheMiddleware, TechDocsCache } from '../cache';\nimport { CachedEntityLoader } from './CachedEntityLoader';\nimport { DefaultDocsBuildStrategy } from './DefaultDocsBuildStrategy';\nimport * as winston from 'winston';\nimport {\n AuthService,\n CacheService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/**\n * Required dependencies for running TechDocs in the \"out-of-the-box\"\n * deployment configuration (prepare/generate/publish all in the Backend).\n *\n * @internal\n */\nexport type OutOfTheBoxDeploymentOptions = {\n preparers: PreparerBuilder;\n generators: GeneratorBuilder;\n publisher: PublisherBase;\n logger: LoggerService;\n discovery: DiscoveryService;\n database?: Knex; // TODO: Make database required when we're implementing database stuff.\n config: Config;\n cache: CacheService;\n docsBuildStrategy?: DocsBuildStrategy;\n buildLogTransport?: winston.transport;\n catalogClient?: CatalogApi;\n httpAuth: HttpAuthService;\n auth: AuthService;\n};\n\n/**\n * Required dependencies for running TechDocs in the \"recommended\" deployment\n * configuration (prepare/generate handled externally in CI/CD).\n *\n * @internal\n */\nexport type RecommendedDeploymentOptions = {\n publisher: PublisherBase;\n logger: LoggerService;\n discovery: DiscoveryService;\n config: Config;\n cache: CacheService;\n docsBuildStrategy?: DocsBuildStrategy;\n buildLogTransport?: winston.transport;\n catalogClient?: CatalogApi;\n httpAuth: HttpAuthService;\n auth: AuthService;\n};\n\n/**\n * One of the two deployment configurations must be provided.\n *\n * @internal\n */\nexport type RouterOptions =\n | RecommendedDeploymentOptions\n | OutOfTheBoxDeploymentOptions;\n\n/**\n * Typeguard to help createRouter() understand when we are in a \"recommended\"\n * deployment vs. when we are in an out-of-the-box deployment configuration.\n *\n * @internal\n */\nfunction isOutOfTheBoxOption(\n opt: RouterOptions,\n): opt is OutOfTheBoxDeploymentOptions {\n return (opt as OutOfTheBoxDeploymentOptions).preparers !== undefined;\n}\n\n/**\n * Creates a techdocs router.\n *\n * @internal\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n const { publisher, config, logger, discovery, httpAuth, auth } = options;\n\n const catalogClient =\n options.catalogClient ?? new CatalogClient({ discoveryApi: discovery });\n const docsBuildStrategy =\n options.docsBuildStrategy ?? DefaultDocsBuildStrategy.fromConfig(config);\n const buildLogTransport = options.buildLogTransport;\n\n // Entities are cached to optimize the /static/docs request path, which can be called many times\n // when loading a single techdocs page.\n const entityLoader = new CachedEntityLoader({\n catalog: catalogClient,\n cache: options.cache,\n });\n\n // Set up a cache client if configured.\n let cache: TechDocsCache | undefined;\n const defaultTtl = config.getOptionalNumber('techdocs.cache.ttl');\n if (defaultTtl) {\n const cacheClient = options.cache.withOptions({ defaultTtl });\n cache = TechDocsCache.fromConfig(config, { cache: cacheClient, logger });\n }\n\n const scmIntegrations = ScmIntegrations.fromConfig(config);\n const docsSynchronizer = new DocsSynchronizer({\n publisher,\n logger,\n buildLogTransport,\n config,\n scmIntegrations,\n cache,\n });\n\n router.get('/metadata/techdocs/:namespace/:kind/:name', async (req, res) => {\n const { kind, namespace, name } = req.params;\n const entityName = { kind, namespace, name };\n\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n // Verify that the related entity exists and the current user has permission to view it.\n const entity = await entityLoader.load(entityName, token);\n\n if (!entity) {\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n );\n }\n\n try {\n const techdocsMetadata = await publisher.fetchTechDocsMetadata(\n entityName,\n );\n\n res.json(techdocsMetadata);\n } catch (err) {\n logger.info(\n `Unable to get metadata for '${stringifyEntityRef(\n entityName,\n )}' with error ${err}`,\n );\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n err,\n );\n }\n });\n\n router.get('/metadata/entity/:namespace/:kind/:name', async (req, res) => {\n const { kind, namespace, name } = req.params;\n const entityName = { kind, namespace, name };\n\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const entity = await entityLoader.load(entityName, token);\n\n if (!entity) {\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n );\n }\n\n try {\n const locationMetadata = getLocationForEntity(entity, scmIntegrations);\n res.json({ ...entity, locationMetadata });\n } catch (err) {\n logger.info(\n `Unable to get metadata for '${stringifyEntityRef(\n entityName,\n )}' with error ${err}`,\n );\n throw new NotFoundError(\n `Unable to get metadata for '${stringifyEntityRef(entityName)}'`,\n err,\n );\n }\n });\n\n // Check if docs are the latest version and trigger rebuilds if not\n // Responds with an event-stream that closes after the build finished\n // Responds with an immediate success if rebuild not needed\n // If a build is required, responds with a success when finished\n router.get('/sync/:namespace/:kind/:name', async (req, res) => {\n const { kind, namespace, name } = req.params;\n\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const entity = await entityLoader.load({ kind, namespace, name }, token);\n\n if (!entity?.metadata?.uid) {\n throw new NotFoundError('Entity metadata UID missing');\n }\n\n const responseHandler: DocsSynchronizerSyncOpts = createEventStream(res);\n\n // By default, techdocs-backend will only try to build documentation for an entity if techdocs.builder is set to\n // 'local'. If set to 'external', it will assume that an external process (e.g. CI/CD pipeline\n // of the repository) is responsible for building and publishing documentation to the storage provider.\n // Altering the implementation of the injected docsBuildStrategy allows for more complex behaviours, based on\n // either config or the properties of the entity (e.g. annotations, labels, spec fields etc.).\n const shouldBuild = await docsBuildStrategy.shouldBuild({ entity });\n if (!shouldBuild) {\n // However, if caching is enabled, take the opportunity to check and\n // invalidate stale cache entries.\n if (cache) {\n const { token: techDocsToken } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'techdocs',\n });\n await docsSynchronizer.doCacheSync({\n responseHandler,\n discovery,\n token: techDocsToken,\n entity,\n });\n return;\n }\n responseHandler.finish({ updated: false });\n return;\n }\n\n // Set the synchronization and build process if \"out-of-the-box\" configuration is provided.\n if (isOutOfTheBoxOption(options)) {\n const { preparers, generators } = options;\n\n await docsSynchronizer.doSync({\n responseHandler,\n entity,\n preparers,\n generators,\n });\n return;\n }\n\n responseHandler.error(\n new Error(\n \"Invalid configuration. docsBuildStrategy.shouldBuild returned 'true', but no 'preparer' was provided to the router initialization.\",\n ),\n );\n });\n\n // Ensures that the related entity exists and the current user has permission to view it.\n if (config.getOptionalBoolean('permission.enabled')) {\n router.use(\n '/static/docs/:namespace/:kind/:name',\n async (req, _res, next) => {\n const { kind, namespace, name } = req.params;\n const entityName = { kind, namespace, name };\n\n const credentials = await httpAuth.credentials(req, {\n allowLimitedAccess: true,\n });\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const entity = await entityLoader.load(entityName, token);\n\n if (!entity) {\n throw new NotFoundError(\n `Entity not found for ${stringifyEntityRef(entityName)}`,\n );\n }\n\n next();\n },\n );\n }\n\n // If a cache manager was provided, attach the cache middleware.\n if (cache) {\n router.use(createCacheMiddleware({ logger, cache }));\n }\n\n // Route middleware which serves files from the storage set in the publisher.\n router.use('/static/docs', publisher.docsRouter());\n\n return router;\n}\n\n/**\n * Create an event-stream response that emits the events 'log', 'error', and 'finish'.\n *\n * @param res - the response to write the event-stream to\n * @returns A tuple of <log, error, finish> callbacks to emit messages. A call to 'error' or 'finish'\n * will close the event-stream.\n */\nexport function createEventStream(\n res: Response<any, any>,\n): DocsSynchronizerSyncOpts {\n // Mandatory headers and http status to keep connection open\n res.writeHead(200, {\n Connection: 'keep-alive',\n 'Cache-Control': 'no-cache',\n 'Content-Type': 'text/event-stream',\n });\n\n // client closes connection\n res.socket?.on('close', () => {\n res.end();\n });\n\n // write the event to the stream\n const send = (type: 'error' | 'finish' | 'log', data: any) => {\n res.write(`event: ${type}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n\n // res.flush() is only available with the compression middleware\n if (res.flush) {\n res.flush();\n }\n };\n\n return {\n log: data => {\n send('log', data);\n },\n\n error: e => {\n send('error', e.message);\n res.end();\n },\n\n finish: result => {\n send('finish', result);\n res.end();\n },\n };\n}\n"],"names":["Router","catalogClient","CatalogClient","DefaultDocsBuildStrategy","CachedEntityLoader","TechDocsCache","ScmIntegrations","DocsSynchronizer","NotFoundError","stringifyEntityRef","getLocationForEntity","createCacheMiddleware"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-techdocs-backend",
3
- "version": "1.11.7-next.2",
3
+ "version": "2.0.1-next.0",
4
4
  "description": "The Backstage backend plugin that renders technical documentation for your components",
5
5
  "backstage": {
6
6
  "role": "backend-plugin",
@@ -72,20 +72,19 @@
72
72
  "test": "backstage-cli package test"
73
73
  },
74
74
  "dependencies": {
75
- "@backstage/backend-common": "^0.25.0",
76
- "@backstage/backend-plugin-api": "1.2.1-next.1",
75
+ "@backstage/backend-defaults": "0.9.0-next.0",
76
+ "@backstage/backend-plugin-api": "1.2.1",
77
77
  "@backstage/catalog-client": "1.9.1",
78
78
  "@backstage/catalog-model": "1.7.3",
79
79
  "@backstage/config": "1.3.2",
80
80
  "@backstage/errors": "1.2.7",
81
- "@backstage/integration": "1.16.2-next.0",
81
+ "@backstage/integration": "1.16.2",
82
82
  "@backstage/plugin-catalog-common": "1.1.3",
83
- "@backstage/plugin-catalog-node": "1.16.1-next.1",
83
+ "@backstage/plugin-catalog-node": "1.16.1",
84
84
  "@backstage/plugin-permission-common": "0.8.4",
85
- "@backstage/plugin-search-backend-module-techdocs": "0.3.7-next.2",
85
+ "@backstage/plugin-search-backend-module-techdocs": "0.4.1-next.0",
86
86
  "@backstage/plugin-techdocs-common": "0.1.0",
87
- "@backstage/plugin-techdocs-node": "1.13.1-next.2",
88
- "@types/express": "^4.17.6",
87
+ "@backstage/plugin-techdocs-node": "1.13.2-next.0",
89
88
  "express": "^4.17.1",
90
89
  "express-promise-router": "^4.1.0",
91
90
  "fs-extra": "^11.2.0",
@@ -95,9 +94,10 @@
95
94
  "winston": "^3.2.1"
96
95
  },
97
96
  "devDependencies": {
98
- "@backstage/backend-defaults": "0.8.2-next.2",
99
- "@backstage/backend-test-utils": "1.3.1-next.2",
100
- "@backstage/cli": "0.31.0-next.1",
97
+ "@backstage/backend-defaults": "0.9.0-next.0",
98
+ "@backstage/backend-test-utils": "1.3.2-next.0",
99
+ "@backstage/cli": "0.32.0-next.0",
100
+ "@types/express": "^4.17.6",
101
101
  "msw": "^2.0.0",
102
102
  "supertest": "^7.0.0"
103
103
  },
@@ -1,142 +0,0 @@
1
- 'use strict';
2
-
3
- var catalogModel = require('@backstage/catalog-model');
4
- var unescape = require('lodash/unescape');
5
- var pLimit = require('p-limit');
6
- var alpha = require('@backstage/plugin-catalog-common/alpha');
7
- var catalogClient = require('@backstage/catalog-client');
8
- var pluginTechdocsCommon = require('@backstage/plugin-techdocs-common');
9
-
10
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
11
-
12
- var unescape__default = /*#__PURE__*/_interopDefaultCompat(unescape);
13
- var pLimit__default = /*#__PURE__*/_interopDefaultCompat(pLimit);
14
-
15
- class DefaultTechDocsCollator {
16
- constructor(legacyPathCasing, options) {
17
- this.legacyPathCasing = legacyPathCasing;
18
- this.options = options;
19
- }
20
- type = "techdocs";
21
- visibilityPermission = alpha.catalogEntityReadPermission;
22
- static fromConfig(config, options) {
23
- const legacyPathCasing = config.getOptionalBoolean(
24
- "techdocs.legacyUseCaseSensitiveTripletPaths"
25
- ) || false;
26
- return new DefaultTechDocsCollator(legacyPathCasing, options);
27
- }
28
- async execute() {
29
- const {
30
- parallelismLimit,
31
- discovery,
32
- tokenManager,
33
- catalogClient: catalogClient$1,
34
- locationTemplate,
35
- logger
36
- } = this.options;
37
- const limit = pLimit__default.default(parallelismLimit ?? 10);
38
- const techDocsBaseUrl = await discovery.getBaseUrl("techdocs");
39
- const { token } = await tokenManager.getToken();
40
- const entities = await (catalogClient$1 ?? new catalogClient.CatalogClient({ discoveryApi: discovery })).getEntities(
41
- {
42
- filter: {
43
- [`metadata.annotations.${pluginTechdocsCommon.TECHDOCS_ANNOTATION}`]: catalogClient.CATALOG_FILTER_EXISTS
44
- },
45
- fields: [
46
- "kind",
47
- "namespace",
48
- "metadata.annotations",
49
- "metadata.name",
50
- "metadata.title",
51
- "metadata.namespace",
52
- "spec.type",
53
- "spec.lifecycle",
54
- "relations"
55
- ]
56
- },
57
- { token }
58
- );
59
- const docPromises = entities.items.map(
60
- (entity) => limit(async () => {
61
- const entityInfo = DefaultTechDocsCollator.handleEntityInfoCasing(
62
- this.legacyPathCasing ?? false,
63
- {
64
- kind: entity.kind,
65
- namespace: entity.metadata.namespace || "default",
66
- name: entity.metadata.name
67
- }
68
- );
69
- try {
70
- const { token: newToken } = await tokenManager.getToken();
71
- const searchIndexResponse = await fetch(
72
- DefaultTechDocsCollator.constructDocsIndexUrl(
73
- techDocsBaseUrl,
74
- entityInfo
75
- ),
76
- {
77
- headers: {
78
- Authorization: `Bearer ${newToken}`
79
- }
80
- }
81
- );
82
- const searchIndex = await searchIndexResponse.json();
83
- return searchIndex.docs.map((doc) => ({
84
- title: unescape__default.default(doc.title),
85
- text: unescape__default.default(doc.text || ""),
86
- location: this.applyArgsToFormat(
87
- locationTemplate || "/docs/:namespace/:kind/:name/:path",
88
- {
89
- ...entityInfo,
90
- path: doc.location
91
- }
92
- ),
93
- path: doc.location,
94
- ...entityInfo,
95
- entityTitle: entity.metadata.title,
96
- componentType: entity.spec?.type?.toString() || "other",
97
- lifecycle: entity.spec?.lifecycle || "",
98
- owner: getSimpleEntityOwnerString(entity),
99
- authorization: {
100
- resourceRef: catalogModel.stringifyEntityRef(entity)
101
- }
102
- }));
103
- } catch (e) {
104
- logger.debug(
105
- `Failed to retrieve tech docs search index for entity ${entityInfo.namespace}/${entityInfo.kind}/${entityInfo.name}`,
106
- e
107
- );
108
- return [];
109
- }
110
- })
111
- );
112
- return (await Promise.all(docPromises)).flat();
113
- }
114
- applyArgsToFormat(format, args) {
115
- let formatted = format;
116
- for (const [key, value] of Object.entries(args)) {
117
- formatted = formatted.replace(`:${key}`, value);
118
- }
119
- return formatted;
120
- }
121
- static constructDocsIndexUrl(techDocsBaseUrl, entityInfo) {
122
- return `${techDocsBaseUrl}/static/docs/${entityInfo.namespace}/${entityInfo.kind}/${entityInfo.name}/search/search_index.json`;
123
- }
124
- static handleEntityInfoCasing(legacyPaths, entityInfo) {
125
- return legacyPaths ? entityInfo : Object.entries(entityInfo).reduce((acc, [key, value]) => {
126
- return { ...acc, [key]: value.toLocaleLowerCase("en-US") };
127
- }, {});
128
- }
129
- }
130
- function getSimpleEntityOwnerString(entity) {
131
- if (entity.relations) {
132
- const owner = entity.relations.find((r) => r.type === catalogModel.RELATION_OWNED_BY);
133
- if (owner) {
134
- const { name } = catalogModel.parseEntityRef(owner.targetRef);
135
- return name;
136
- }
137
- }
138
- return "";
139
- }
140
-
141
- exports.DefaultTechDocsCollator = DefaultTechDocsCollator;
142
- //# sourceMappingURL=DefaultTechDocsCollator.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DefaultTechDocsCollator.cjs.js","sources":["../../src/search/DefaultTechDocsCollator.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TokenManager } from '@backstage/backend-common';\nimport {\n Entity,\n parseEntityRef,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport unescape from 'lodash/unescape';\nimport { Logger } from 'winston';\nimport pLimit from 'p-limit';\nimport { Config } from '@backstage/config';\nimport { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha';\nimport { Permission } from '@backstage/plugin-permission-common';\nimport {\n CatalogApi,\n CatalogClient,\n CATALOG_FILTER_EXISTS,\n} from '@backstage/catalog-client';\nimport { TechDocsDocument } from '@backstage/plugin-techdocs-node';\nimport { TECHDOCS_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport { DiscoveryService } from '@backstage/backend-plugin-api';\n\ninterface MkSearchIndexDoc {\n title: string;\n text: string;\n location: string;\n}\n\n/**\n * Options to configure the TechDocs collator\n *\n * @public\n */\nexport type TechDocsCollatorOptions = {\n discovery: DiscoveryService;\n logger: Logger;\n tokenManager: TokenManager;\n locationTemplate?: string;\n catalogClient?: CatalogApi;\n parallelismLimit?: number;\n legacyPathCasing?: boolean;\n};\n\ntype EntityInfo = {\n name: string;\n namespace: string;\n kind: string;\n};\n\n/**\n * A search collator responsible for gathering and transforming TechDocs documents.\n *\n * @public\n * @deprecated Upgrade to a more recent `@backstage/plugin-search-backend-node` and\n * use `DefaultTechDocsCollatorFactory` instead.\n */\nexport class DefaultTechDocsCollator {\n public readonly type: string = 'techdocs';\n public readonly visibilityPermission: Permission =\n catalogEntityReadPermission;\n\n private constructor(\n private readonly legacyPathCasing: boolean,\n private readonly options: TechDocsCollatorOptions,\n ) {}\n\n static fromConfig(config: Config, options: TechDocsCollatorOptions) {\n const legacyPathCasing =\n config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n ) || false;\n return new DefaultTechDocsCollator(legacyPathCasing, options);\n }\n\n async execute() {\n const {\n parallelismLimit,\n discovery,\n tokenManager,\n catalogClient,\n locationTemplate,\n logger,\n } = this.options;\n const limit = pLimit(parallelismLimit ?? 10);\n const techDocsBaseUrl = await discovery.getBaseUrl('techdocs');\n const { token } = await tokenManager.getToken();\n const entities = await (\n catalogClient ?? new CatalogClient({ discoveryApi: discovery })\n ).getEntities(\n {\n filter: {\n [`metadata.annotations.${TECHDOCS_ANNOTATION}`]:\n CATALOG_FILTER_EXISTS,\n },\n fields: [\n 'kind',\n 'namespace',\n 'metadata.annotations',\n 'metadata.name',\n 'metadata.title',\n 'metadata.namespace',\n 'spec.type',\n 'spec.lifecycle',\n 'relations',\n ],\n },\n { token },\n );\n const docPromises = entities.items.map((entity: Entity) =>\n limit(async (): Promise<TechDocsDocument[]> => {\n const entityInfo = DefaultTechDocsCollator.handleEntityInfoCasing(\n this.legacyPathCasing ?? false,\n {\n kind: entity.kind,\n namespace: entity.metadata.namespace || 'default',\n name: entity.metadata.name,\n },\n );\n\n try {\n const { token: newToken } = await tokenManager.getToken();\n const searchIndexResponse = await fetch(\n DefaultTechDocsCollator.constructDocsIndexUrl(\n techDocsBaseUrl,\n entityInfo,\n ),\n {\n headers: {\n Authorization: `Bearer ${newToken}`,\n },\n },\n );\n const searchIndex = await searchIndexResponse.json();\n\n return searchIndex.docs.map((doc: MkSearchIndexDoc) => ({\n title: unescape(doc.title),\n text: unescape(doc.text || ''),\n location: this.applyArgsToFormat(\n locationTemplate || '/docs/:namespace/:kind/:name/:path',\n {\n ...entityInfo,\n path: doc.location,\n },\n ),\n path: doc.location,\n ...entityInfo,\n entityTitle: entity.metadata.title,\n componentType: entity.spec?.type?.toString() || 'other',\n lifecycle: (entity.spec?.lifecycle as string) || '',\n owner: getSimpleEntityOwnerString(entity),\n authorization: {\n resourceRef: stringifyEntityRef(entity),\n },\n }));\n } catch (e) {\n logger.debug(\n `Failed to retrieve tech docs search index for entity ${entityInfo.namespace}/${entityInfo.kind}/${entityInfo.name}`,\n e,\n );\n return [];\n }\n }),\n );\n return (await Promise.all(docPromises)).flat();\n }\n\n protected applyArgsToFormat(\n format: string,\n args: Record<string, string>,\n ): string {\n let formatted = format;\n for (const [key, value] of Object.entries(args)) {\n formatted = formatted.replace(`:${key}`, value);\n }\n return formatted;\n }\n\n private static constructDocsIndexUrl(\n techDocsBaseUrl: string,\n entityInfo: { kind: string; namespace: string; name: string },\n ) {\n return `${techDocsBaseUrl}/static/docs/${entityInfo.namespace}/${entityInfo.kind}/${entityInfo.name}/search/search_index.json`;\n }\n\n private static handleEntityInfoCasing(\n legacyPaths: boolean,\n entityInfo: EntityInfo,\n ): EntityInfo {\n return legacyPaths\n ? entityInfo\n : Object.entries(entityInfo).reduce((acc, [key, value]) => {\n return { ...acc, [key]: value.toLocaleLowerCase('en-US') };\n }, {} as EntityInfo);\n }\n}\n\nfunction getSimpleEntityOwnerString(entity: Entity): string {\n if (entity.relations) {\n const owner = entity.relations.find(r => r.type === RELATION_OWNED_BY);\n if (owner) {\n const { name } = parseEntityRef(owner.targetRef);\n return name;\n }\n }\n return '';\n}\n"],"names":["catalogEntityReadPermission","catalogClient","pLimit","CatalogClient","TECHDOCS_ANNOTATION","CATALOG_FILTER_EXISTS","unescape","stringifyEntityRef","RELATION_OWNED_BY","parseEntityRef"],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- 'use strict';
2
-
3
- require('@backstage/catalog-model');
4
- require('lodash/unescape');
5
- require('p-limit');
6
- require('@backstage/plugin-catalog-common/alpha');
7
- require('@backstage/catalog-client');
8
- require('@backstage/plugin-techdocs-common');
9
- var pluginSearchBackendModuleTechdocs = require('@backstage/plugin-search-backend-module-techdocs');
10
-
11
- const DefaultTechDocsCollatorFactory = pluginSearchBackendModuleTechdocs.DefaultTechDocsCollatorFactory;
12
-
13
- exports.DefaultTechDocsCollatorFactory = DefaultTechDocsCollatorFactory;
14
- //# sourceMappingURL=index.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../src/search/index.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * todo(backstage/techdocs-core): stop exporting these in a future release.\n */\nexport { DefaultTechDocsCollator } from './DefaultTechDocsCollator';\nexport type { TechDocsCollatorOptions } from './DefaultTechDocsCollator';\n\nimport { DefaultTechDocsCollatorFactory as _DefaultTechDocsCollatorFactory } from '@backstage/plugin-search-backend-module-techdocs';\nimport type { TechDocsCollatorFactoryOptions as _TechDocsCollatorFactoryOptions } from '@backstage/plugin-search-backend-module-techdocs';\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-techdocs` instead\n */\nexport type TechDocsCollatorFactoryOptions = _TechDocsCollatorFactoryOptions;\n\n/**\n * @public\n * @deprecated import from `@backstage/plugin-search-backend-module-techdocs` instead\n */\nexport const DefaultTechDocsCollatorFactory = _DefaultTechDocsCollatorFactory;\n"],"names":["_DefaultTechDocsCollatorFactory"],"mappings":";;;;;;;;;;AAmCO,MAAM,8BAAiC,GAAAA;;;;"}