@backstage/plugin-techdocs-node 2.0.2 → 2.1.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.
Files changed (30) hide show
  1. package/CHANGELOG.md +54 -5
  2. package/dist/extensions.cjs.js.map +1 -1
  3. package/dist/helpers.cjs.js.map +1 -1
  4. package/dist/index.cjs.js +2 -0
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.d.ts +19 -4
  7. package/dist/stages/generate/DockerContainerRunner.cjs.js.map +1 -1
  8. package/dist/stages/generate/generators.cjs.js +22 -6
  9. package/dist/stages/generate/generators.cjs.js.map +1 -1
  10. package/dist/stages/generate/helpers.cjs.js +52 -34
  11. package/dist/stages/generate/helpers.cjs.js.map +1 -1
  12. package/dist/stages/generate/index.cjs.js.map +1 -1
  13. package/dist/stages/generate/mkdocsPatchers.cjs.js +21 -3
  14. package/dist/stages/generate/mkdocsPatchers.cjs.js.map +1 -1
  15. package/dist/stages/generate/techdocs.cjs.js +2 -1
  16. package/dist/stages/generate/techdocs.cjs.js.map +1 -1
  17. package/dist/stages/prepare/dir.cjs.js.map +1 -1
  18. package/dist/stages/prepare/preparers.cjs.js.map +1 -1
  19. package/dist/stages/prepare/url.cjs.js.map +1 -1
  20. package/dist/stages/publish/awsS3.cjs.js.map +1 -1
  21. package/dist/stages/publish/azureBlobStorage.cjs.js.map +1 -1
  22. package/dist/stages/publish/googleStorage.cjs.js.map +1 -1
  23. package/dist/stages/publish/helpers.cjs.js.map +1 -1
  24. package/dist/stages/publish/local.cjs.js.map +1 -1
  25. package/dist/stages/publish/migrations/GoogleMigration.cjs.js.map +1 -1
  26. package/dist/stages/publish/openStackSwift.cjs.js.map +1 -1
  27. package/dist/stages/publish/publish.cjs.js.map +1 -1
  28. package/dist/techdocsTypes.cjs.js +6 -0
  29. package/dist/techdocsTypes.cjs.js.map +1 -0
  30. package/package.json +12 -12
package/CHANGELOG.md CHANGED
@@ -1,17 +1,66 @@
1
1
  # @backstage/plugin-techdocs-node
2
2
 
3
- ## 2.0.2
3
+ ## 2.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 4d4f987: Add engine abstraction layer for multi-engine TechDocs support. Introduces `--engine` flag, engine config map, generator registry with `backstage.io/techdocs-engine` annotation support, `engine` field in `techdocs_metadata.json`, `serve:raw` command, and live-reload adapter interface. MkDocs remains the default with no behavior change.
8
+
9
+ The built-in generator is now registered under `mkdocs`; the previous `techdocs` key is kept as an alias, so existing `generators.register('techdocs', ...)` calls continue to work. The CLI's `--engine` flag takes precedence over the `backstage.io/techdocs-engine` annotation for all commands, and `serve:mkdocs` and the `--mkdocs-parameter-*` flags now print deprecation warnings.
10
+
11
+ ### Patch Changes
12
+
13
+ - 9fc5387: Improved handling of mapping-style Markdown extension configuration.
14
+ - 0fd5fe5: Fixed TechDocs allowing `custom_icons` paths in `mkdocs.yml` that resolve outside the documentation input directory. A `custom_icons` option with such a path is now removed from the configuration with a warning.
15
+ - 8a37336: Fixed TechDocs generation rejecting `mkdocs.yml` files that use the emoji indexes and generators or the `pymdownx.superfences` custom fence formats documented by mkdocs-material, pymdown-extensions and mkdocs-mermaid2.
16
+ - 76ac6ed: Updated dependency `js-yaml` to `^5.0.0`.
17
+ - Updated dependencies
18
+ - @backstage/integration@2.1.3
19
+ - @backstage/backend-plugin-api@1.11.0
20
+ - @backstage/config@1.3.10
21
+ - @backstage/errors@1.3.2
22
+ - @backstage/plugin-techdocs-common@0.1.2
23
+ - @backstage/catalog-model@1.10.2
24
+ - @backstage/integration-aws-node@0.2.3
25
+ - @backstage/plugin-search-common@1.2.26
26
+
27
+ ## 2.0.3-next.2
28
+
29
+ ### Patch Changes
30
+
31
+ - 76ac6ed: Updated dependency `js-yaml` to `^5.0.0`.
32
+ - Updated dependencies
33
+ - @backstage/integration@2.1.3-next.1
34
+ - @backstage/plugin-techdocs-common@0.1.2-next.0
35
+
36
+ ## 2.0.3-next.1
37
+
38
+ ### Patch Changes
39
+
40
+ - Bumped version to account for a patch release.
41
+
42
+ ## 2.0.2-next.1
4
43
 
5
44
  ### Patch Changes
6
45
 
7
- - 717f5e3: Fixed TechDocs allowing `custom_icons` paths in `mkdocs.yml` that resolve outside the documentation input directory. A `custom_icons` option with such a path is now removed from the configuration with a warning.
8
- - 717f5e3: Fixed TechDocs generation rejecting `mkdocs.yml` files that use the emoji indexes and generators or the `pymdownx.superfences` custom fence formats documented by mkdocs-material, pymdown-extensions and mkdocs-mermaid2.
46
+ - 9fc5387: Improved handling of mapping-style Markdown extension configuration.
47
+ - 0fd5fe5: Fixed TechDocs allowing `custom_icons` paths in `mkdocs.yml` that resolve outside the documentation input directory. A `custom_icons` option with such a path is now removed from the configuration with a warning.
48
+ - 8a37336: Fixed TechDocs generation rejecting `mkdocs.yml` files that use the emoji indexes and generators or the `pymdownx.superfences` custom fence formats documented by mkdocs-material, pymdown-extensions and mkdocs-mermaid2.
49
+ - Updated dependencies
50
+ - @backstage/backend-plugin-api@1.11.0-next.1
9
51
 
10
- ## 2.0.1
52
+ ## 2.0.1-next.0
11
53
 
12
54
  ### Patch Changes
13
55
 
14
- - 944edb5: Improved handling of mapping-style Markdown extension configuration.
56
+ - Updated dependencies
57
+ - @backstage/integration@2.1.3-next.0
58
+ - @backstage/config@1.3.10-next.0
59
+ - @backstage/errors@1.3.2-next.0
60
+ - @backstage/backend-plugin-api@1.10.2-next.0
61
+ - @backstage/integration-aws-node@0.2.3-next.0
62
+ - @backstage/catalog-model@1.10.2-next.0
63
+ - @backstage/plugin-search-common@1.2.26-next.0
15
64
 
16
65
  ## 2.0.0
17
66
 
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.cjs.js","sources":["../src/extensions.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 */\nimport { createExtensionPoint } from '@backstage/backend-plugin-api';\nimport { DocsBuildStrategy } from './techdocsTypes';\nimport {\n PreparerBase,\n PublisherBase,\n PublisherType,\n RemoteProtocol,\n TechdocsGenerator,\n} from './stages';\nimport * as winston from 'winston';\nimport { PublisherSettings } from './stages/publish/types';\n\n/**\n * Extension point type for configuring TechDocs builds.\n *\n * @public\n */\nexport interface TechdocsBuildsExtensionPoint {\n setBuildStrategy(buildStrategy: DocsBuildStrategy): void;\n setBuildLogTransport(transport: winston.transport): void;\n}\n\n/**\n * Extension point for configuring TechDocs builds.\n *\n * @public\n */\nexport const techdocsBuildsExtensionPoint =\n createExtensionPoint<TechdocsBuildsExtensionPoint>({\n id: 'techdocs.builds',\n });\n\n/**\n * Extension point type for configuring a custom TechDocs generator\n *\n * @public\n */\nexport interface TechdocsGeneratorExtensionPoint {\n setTechdocsGenerator(generator: TechdocsGenerator): void;\n}\n\n/**\n * Extension point for configuring a custom TechDocs generator\n *\n * @public\n */\nexport const techdocsGeneratorExtensionPoint =\n createExtensionPoint<TechdocsGeneratorExtensionPoint>({\n id: 'techdocs.generator',\n });\n\n/**\n * Extension point type for configuring a custom TechDocs preparer\n *\n * @public\n */\nexport interface TechdocsPreparerExtensionPoint {\n registerPreparer(protocol: RemoteProtocol, preparer: PreparerBase): void;\n}\n\n/**\n * Extension point for configuring a custom TechDocs preparer\n *\n * @public\n */\nexport const techdocsPreparerExtensionPoint =\n createExtensionPoint<TechdocsPreparerExtensionPoint>({\n id: 'techdocs.preparer',\n });\n\n/**\n * Extension point type for configuring a custom TechDocs publisher\n *\n * @public\n */\nexport interface TechdocsPublisherExtensionPoint {\n registerPublisher(type: PublisherType, publisher: PublisherBase): void;\n registerPublisherSettings<T extends keyof PublisherSettings>(\n publisher: T,\n settings: PublisherSettings[T],\n ): void;\n}\n\n/**\n * Extension point for configuring a custom TechDocs publisher\n *\n * @public\n */\nexport const techdocsPublisherExtensionPoint =\n createExtensionPoint<TechdocsPublisherExtensionPoint>({\n id: 'techdocs.publisher',\n });\n"],"names":["createExtensionPoint"],"mappings":";;;;AA0CO,MAAM,+BACXA,qCAAA,CAAmD;AAAA,EACjD,EAAA,EAAI;AACN,CAAC;AAgBI,MAAM,kCACXA,qCAAA,CAAsD;AAAA,EACpD,EAAA,EAAI;AACN,CAAC;AAgBI,MAAM,iCACXA,qCAAA,CAAqD;AAAA,EACnD,EAAA,EAAI;AACN,CAAC;AAoBI,MAAM,kCACXA,qCAAA,CAAsD;AAAA,EACpD,EAAA,EAAI;AACN,CAAC;;;;;;;"}
1
+ {"version":3,"file":"extensions.cjs.js","sources":["../src/extensions.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 */\nimport { createExtensionPoint } from '@backstage/backend-plugin-api';\nimport { DocsBuildStrategy } from './techdocsTypes';\nimport {\n GeneratorBase,\n PreparerBase,\n PublisherBase,\n PublisherType,\n RemoteProtocol,\n SupportedGeneratorKey,\n} from './stages';\nimport * as winston from 'winston';\nimport { PublisherSettings } from './stages/publish/types';\n\n/**\n * Extension point type for configuring TechDocs builds.\n *\n * @public\n */\nexport interface TechdocsBuildsExtensionPoint {\n setBuildStrategy(buildStrategy: DocsBuildStrategy): void;\n setBuildLogTransport(transport: winston.transport): void;\n}\n\n/**\n * Extension point for configuring TechDocs builds.\n *\n * @public\n */\nexport const techdocsBuildsExtensionPoint =\n createExtensionPoint<TechdocsBuildsExtensionPoint>({\n id: 'techdocs.builds',\n });\n\n/**\n * Extension point type for configuring TechDocs generators.\n *\n * Use `registerGenerator` to add an engine-specific generator from a backend\n * module (e.g. `plugin-techdocs-backend-module-zensical`). The key corresponds\n * to the `backstage.io/techdocs-engine` entity annotation value.\n *\n * `setTechdocsGenerator` is kept for backwards compatibility — it replaces the\n * default MkDocs generator.\n *\n * @public\n */\nexport interface TechdocsGeneratorExtensionPoint {\n setTechdocsGenerator(generator: GeneratorBase): void;\n registerGenerator(key: SupportedGeneratorKey, generator: GeneratorBase): void;\n}\n\n/**\n * Extension point for configuring a custom TechDocs generator\n *\n * @public\n */\nexport const techdocsGeneratorExtensionPoint =\n createExtensionPoint<TechdocsGeneratorExtensionPoint>({\n id: 'techdocs.generator',\n });\n\n/**\n * Extension point type for configuring a custom TechDocs preparer\n *\n * @public\n */\nexport interface TechdocsPreparerExtensionPoint {\n registerPreparer(protocol: RemoteProtocol, preparer: PreparerBase): void;\n}\n\n/**\n * Extension point for configuring a custom TechDocs preparer\n *\n * @public\n */\nexport const techdocsPreparerExtensionPoint =\n createExtensionPoint<TechdocsPreparerExtensionPoint>({\n id: 'techdocs.preparer',\n });\n\n/**\n * Extension point type for configuring a custom TechDocs publisher\n *\n * @public\n */\nexport interface TechdocsPublisherExtensionPoint {\n registerPublisher(type: PublisherType, publisher: PublisherBase): void;\n registerPublisherSettings<T extends keyof PublisherSettings>(\n publisher: T,\n settings: PublisherSettings[T],\n ): void;\n}\n\n/**\n * Extension point for configuring a custom TechDocs publisher\n *\n * @public\n */\nexport const techdocsPublisherExtensionPoint =\n createExtensionPoint<TechdocsPublisherExtensionPoint>({\n id: 'techdocs.publisher',\n });\n"],"names":["createExtensionPoint"],"mappings":";;;;AA2CO,MAAM,+BACXA,qCAAA,CAAmD;AAAA,EACjD,EAAA,EAAI;AACN,CAAC;AAwBI,MAAM,kCACXA,qCAAA,CAAsD;AAAA,EACpD,EAAA,EAAI;AACN,CAAC;AAgBI,MAAM,iCACXA,qCAAA,CAAqD;AAAA,EACnD,EAAA,EAAI;AACN,CAAC;AAoBI,MAAM,kCACXA,qCAAA,CAAsD;AAAA,EACpD,EAAA,EAAI;AACN,CAAC;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.cjs.js","sources":["../src/helpers.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 LoggerService,\n UrlReaderService,\n resolveSafeChildPath,\n} from '@backstage/backend-plugin-api';\nimport {\n Entity,\n getEntitySourceLocation,\n parseLocationRef,\n} from '@backstage/catalog-model';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { TECHDOCS_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport path from 'node:path';\nimport { PreparerResponse, RemoteProtocol } from './stages/prepare/types';\n\n/**\n * Parsed location annotation\n * @public\n */\nexport type ParsedLocationAnnotation = {\n type: RemoteProtocol;\n target: string;\n};\n\n/**\n * Returns a parsed locations annotation\n * @public\n * @param annotationName - The name of the annotation in the entity metadata\n * @param entity - A TechDocs entity instance\n */\nexport const parseReferenceAnnotation = (\n annotationName: string,\n entity: Entity,\n): ParsedLocationAnnotation => {\n const annotation = entity.metadata.annotations?.[annotationName];\n if (!annotation) {\n throw new InputError(\n `No ${annotationName} annotation provided in entity: ${entity.metadata.name}`,\n );\n }\n\n const { type, target } = parseLocationRef(annotation);\n return {\n type: type as RemoteProtocol,\n target,\n };\n};\n\n/**\n * TechDocs references of type `dir` are relative the source location of the entity.\n * This function transforms relative references to absolute ones, based on the\n * location the entity was ingested from. If the entity was registered by a `url`\n * location, it returns a `url` location with a resolved target that points to the\n * targeted subfolder. If the entity was registered by a `file` location, it returns\n * an absolute `dir` location.\n * @public\n * @param entity - the entity with annotations\n * @param dirAnnotation - the parsed techdocs-ref annotation of type 'dir'\n * @param scmIntegrations - access to the scmIntegration to do url transformations\n * @throws if the entity doesn't specify a `dir` location or is ingested from an unsupported location.\n * @returns the transformed location with an absolute target.\n */\nexport const transformDirLocation = (\n entity: Entity,\n dirAnnotation: ParsedLocationAnnotation,\n scmIntegrations: ScmIntegrationRegistry,\n): { type: 'dir' | 'url'; target: string } => {\n const location = getEntitySourceLocation(entity);\n\n switch (location.type) {\n case 'url': {\n const target = scmIntegrations.resolveUrl({\n url: dirAnnotation.target,\n base: location.target,\n });\n\n return {\n type: 'url',\n target,\n };\n }\n\n case 'file': {\n // only permit targets in the same folder as the target of the `file` location!\n const target = resolveSafeChildPath(\n path.dirname(location.target),\n dirAnnotation.target,\n );\n\n return {\n type: 'dir',\n target,\n };\n }\n\n default:\n throw new InputError(`Unable to resolve location type ${location.type}`);\n }\n};\n\n/**\n * Returns an entity reference based on the TechDocs annotation type\n * @public\n * @param entity - A TechDocs instance\n * @param scmIntegration - An implementation for SCM integration API\n */\nexport const getLocationForEntity = (\n entity: Entity,\n scmIntegration: ScmIntegrationRegistry,\n): ParsedLocationAnnotation => {\n const annotation = parseReferenceAnnotation(TECHDOCS_ANNOTATION, entity);\n\n switch (annotation.type) {\n case 'url':\n return annotation;\n case 'dir':\n return transformDirLocation(entity, annotation, scmIntegration);\n default:\n throw new Error(`Invalid reference annotation ${annotation.type}`);\n }\n};\n\n/**\n * Returns a preparer response {@link PreparerResponse}\n * @public\n * @param reader - Read a tree of files from a repository\n * @param entity - A TechDocs entity instance\n * @param opts - Options for configuring the reader, e.g. logger, etag, etc.\n */\nexport const getDocFilesFromRepository = async (\n reader: UrlReaderService,\n entity: Entity,\n opts?: { etag?: string; logger?: LoggerService },\n): Promise<PreparerResponse> => {\n const { target } = parseReferenceAnnotation(TECHDOCS_ANNOTATION, entity);\n\n opts?.logger?.debug(`Reading files from ${target}`);\n // readTree will throw NotModifiedError if etag has not changed.\n const readTreeResponse = await reader.readTree(target, { etag: opts?.etag });\n const preparedDir = await readTreeResponse.dir();\n\n opts?.logger?.debug(`Tree downloaded and stored at ${preparedDir}`);\n\n return {\n preparedDir,\n etag: readTreeResponse.etag,\n };\n};\n"],"names":["InputError","parseLocationRef","getEntitySourceLocation","resolveSafeChildPath","path","TECHDOCS_ANNOTATION"],"mappings":";;;;;;;;;;;;AA+CO,MAAM,wBAAA,GAA2B,CACtC,cAAA,EACA,MAAA,KAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,cAAc,CAAA;AAC/D,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,MAAM,IAAIA,iBAAA;AAAA,MACR,CAAA,GAAA,EAAM,cAAc,CAAA,gCAAA,EAAmC,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,KAC7E;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAIC,8BAAiB,UAAU,CAAA;AACpD,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAgBO,MAAM,oBAAA,GAAuB,CAClC,MAAA,EACA,aAAA,EACA,eAAA,KAC4C;AAC5C,EAAA,MAAM,QAAA,GAAWC,qCAAwB,MAAM,CAAA;AAE/C,EAAA,QAAQ,SAAS,IAAA;AAAM,IACrB,KAAK,KAAA,EAAO;AACV,MAAA,MAAM,MAAA,GAAS,gBAAgB,UAAA,CAAW;AAAA,QACxC,KAAK,aAAA,CAAc,MAAA;AAAA,QACnB,MAAM,QAAA,CAAS;AAAA,OAChB,CAAA;AAED,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,KAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAAA,IAEA,KAAK,MAAA,EAAQ;AAEX,MAAA,MAAM,MAAA,GAASC,qCAAA;AAAA,QACbC,qBAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA;AAAA,QAC5B,aAAA,CAAc;AAAA,OAChB;AAEA,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,KAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAAA,IAEA;AACE,MAAA,MAAM,IAAIJ,iBAAA,CAAW,CAAA,gCAAA,EAAmC,QAAA,CAAS,IAAI,CAAA,CAAE,CAAA;AAAA;AAE7E;AAQO,MAAM,oBAAA,GAAuB,CAClC,MAAA,EACA,cAAA,KAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,wBAAA,CAAyBK,wCAAA,EAAqB,MAAM,CAAA;AAEvE,EAAA,QAAQ,WAAW,IAAA;AAAM,IACvB,KAAK,KAAA;AACH,MAAA,OAAO,UAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,oBAAA,CAAqB,MAAA,EAAQ,UAAA,EAAY,cAAc,CAAA;AAAA,IAChE;AACE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6BAAA,EAAgC,UAAA,CAAW,IAAI,CAAA,CAAE,CAAA;AAAA;AAEvE;AASO,MAAM,yBAAA,GAA4B,OACvC,MAAA,EACA,MAAA,EACA,IAAA,KAC8B;AAC9B,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,wBAAA,CAAyBA,0CAAqB,MAAM,CAAA;AAEvE,EAAA,IAAA,EAAM,MAAA,EAAQ,KAAA,CAAM,CAAA,mBAAA,EAAsB,MAAM,CAAA,CAAE,CAAA;AAElD,EAAA,MAAM,gBAAA,GAAmB,MAAM,MAAA,CAAO,QAAA,CAAS,QAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,CAAA;AAC3E,EAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,GAAA,EAAI;AAE/C,EAAA,IAAA,EAAM,MAAA,EAAQ,KAAA,CAAM,CAAA,8BAAA,EAAiC,WAAW,CAAA,CAAE,CAAA;AAElE,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,MAAM,gBAAA,CAAiB;AAAA,GACzB;AACF;;;;;;;"}
1
+ {"version":3,"file":"helpers.cjs.js","sources":["../src/helpers.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 LoggerService,\n UrlReaderService,\n resolveSafeChildPath,\n} from '@backstage/backend-plugin-api';\nimport {\n Entity,\n getEntitySourceLocation,\n parseLocationRef,\n} from '@backstage/catalog-model';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { TECHDOCS_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport path from 'node:path';\nimport { PreparerResponse, RemoteProtocol } from './stages/prepare/types';\n\n/**\n * Parsed location annotation\n * @public\n */\nexport type ParsedLocationAnnotation = {\n type: RemoteProtocol;\n target: string;\n};\n\n/**\n * Returns a parsed locations annotation\n * @public\n * @param annotationName - The name of the annotation in the entity metadata\n * @param entity - A TechDocs entity instance\n */\nexport const parseReferenceAnnotation = (\n annotationName: string,\n entity: Entity,\n): ParsedLocationAnnotation => {\n const annotation = entity.metadata.annotations?.[annotationName];\n if (!annotation) {\n throw new InputError(\n `No ${annotationName} annotation provided in entity: ${entity.metadata.name}`,\n );\n }\n\n const { type, target } = parseLocationRef(annotation);\n return {\n type: type as RemoteProtocol,\n target,\n };\n};\n\n/**\n * TechDocs references of type `dir` are relative the source location of the entity.\n * This function transforms relative references to absolute ones, based on the\n * location the entity was ingested from. If the entity was registered by a `url`\n * location, it returns a `url` location with a resolved target that points to the\n * targeted subfolder. If the entity was registered by a `file` location, it returns\n * an absolute `dir` location.\n * @public\n * @param entity - the entity with annotations\n * @param dirAnnotation - the parsed techdocs-ref annotation of type 'dir'\n * @param scmIntegrations - access to the scmIntegration to do url transformations\n * @throws if the entity doesn't specify a `dir` location or is ingested from an unsupported location.\n * @returns the transformed location with an absolute target.\n */\nexport const transformDirLocation = (\n entity: Entity,\n dirAnnotation: ParsedLocationAnnotation,\n scmIntegrations: ScmIntegrationRegistry,\n): { type: 'dir' | 'url'; target: string } => {\n const location = getEntitySourceLocation(entity);\n\n switch (location.type) {\n case 'url': {\n const target = scmIntegrations.resolveUrl({\n url: dirAnnotation.target,\n base: location.target,\n });\n\n return {\n type: 'url',\n target,\n };\n }\n\n case 'file': {\n // only permit targets in the same folder as the target of the `file` location!\n const target = resolveSafeChildPath(\n path.dirname(location.target),\n dirAnnotation.target,\n );\n\n return {\n type: 'dir',\n target,\n };\n }\n\n default:\n throw new InputError(`Unable to resolve location type ${location.type}`);\n }\n};\n\n/**\n * Returns an entity reference based on the TechDocs annotation type\n * @public\n * @param entity - A TechDocs instance\n * @param scmIntegration - An implementation for SCM integration API\n */\nexport const getLocationForEntity = (\n entity: Entity,\n scmIntegration: ScmIntegrationRegistry,\n): ParsedLocationAnnotation => {\n const annotation = parseReferenceAnnotation(TECHDOCS_ANNOTATION, entity);\n\n switch (annotation.type) {\n case 'url':\n return annotation;\n case 'dir':\n return transformDirLocation(entity, annotation, scmIntegration);\n default:\n throw new Error(`Invalid reference annotation ${annotation.type}`);\n }\n};\n\n/**\n * Returns a preparer response {@link PreparerResponse}\n * @public\n * @param reader - Read a tree of files from a repository\n * @param entity - A TechDocs entity instance\n * @param opts - Options for configuring the reader, e.g. logger, etag, etc.\n */\nexport const getDocFilesFromRepository = async (\n reader: UrlReaderService,\n entity: Entity,\n opts?: { etag?: string; logger?: LoggerService },\n): Promise<PreparerResponse> => {\n const { target } = parseReferenceAnnotation(TECHDOCS_ANNOTATION, entity);\n\n opts?.logger?.debug(`Reading files from ${target}`);\n // readTree will throw NotModifiedError if etag has not changed.\n const readTreeResponse = await reader.readTree(target, { etag: opts?.etag });\n const preparedDir = await readTreeResponse.dir();\n\n opts?.logger?.debug(`Tree downloaded and stored at ${preparedDir}`);\n\n return {\n preparedDir,\n etag: readTreeResponse.etag,\n };\n};\n"],"names":["InputError","parseLocationRef","getEntitySourceLocation","resolveSafeChildPath","path","TECHDOCS_ANNOTATION"],"mappings":";;;;;;;;;;;;AA+CO,MAAM,wBAAA,GAA2B,CACtC,cAAA,EACA,MAAA,KAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,cAAc,CAAA;AAC/D,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,MAAM,IAAIA,iBAAA;AAAA,MACR,CAAA,GAAA,EAAM,cAAc,CAAA,gCAAA,EAAmC,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,KAC7E;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAIC,8BAAiB,UAAU,CAAA;AACpD,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA;AAAA,GACF;AACF;AAgBO,MAAM,oBAAA,GAAuB,CAClC,MAAA,EACA,aAAA,EACA,eAAA,KAC4C;AAC5C,EAAA,MAAM,QAAA,GAAWC,qCAAwB,MAAM,CAAA;AAE/C,EAAA,QAAQ,SAAS,IAAA;AAAM,IACrB,KAAK,KAAA,EAAO;AACV,MAAA,MAAM,MAAA,GAAS,gBAAgB,UAAA,CAAW;AAAA,QACxC,KAAK,aAAA,CAAc,MAAA;AAAA,QACnB,MAAM,QAAA,CAAS;AAAA,OAChB,CAAA;AAED,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,KAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAAA,IAEA,KAAK,MAAA,EAAQ;AAEX,MAAA,MAAM,MAAA,GAASC,qCAAA;AAAA,QACbC,qBAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,MAAM,CAAA;AAAA,QAC5B,aAAA,CAAc;AAAA,OAChB;AAEA,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,KAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAAA,IAEA;AACE,MAAA,MAAM,IAAIJ,iBAAA,CAAW,CAAA,gCAAA,EAAmC,QAAA,CAAS,IAAI,CAAA,CAAE,CAAA;AAAA;AAE7E;AAQO,MAAM,oBAAA,GAAuB,CAClC,MAAA,EACA,cAAA,KAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,wBAAA,CAAyBK,wCAAA,EAAqB,MAAM,CAAA;AAEvE,EAAA,QAAQ,WAAW,IAAA;AAAM,IACvB,KAAK,KAAA;AACH,MAAA,OAAO,UAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,oBAAA,CAAqB,MAAA,EAAQ,UAAA,EAAY,cAAc,CAAA;AAAA,IAChE;AACE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6BAAA,EAAgC,UAAA,CAAW,IAAI,CAAA,CAAE,CAAA;AAAA;AAEvE;AASO,MAAM,yBAAA,GAA4B,OACvC,MAAA,EACA,MAAA,EACA,IAAA,KAC8B;AAC9B,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,wBAAA,CAAyBA,0CAAqB,MAAM,CAAA;AAEvE,EAAA,IAAA,EAAM,MAAA,EAAQ,KAAA,CAAM,CAAA,mBAAA,EAAsB,MAAM,CAAA,CAAE,CAAA;AAElD,EAAA,MAAM,gBAAA,GAAmB,MAAM,MAAA,CAAO,QAAA,CAAS,QAAQ,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,CAAA;AAC3E,EAAA,MAAM,WAAA,GAAc,MAAM,gBAAA,CAAiB,GAAA,EAAI;AAE/C,EAAA,IAAA,EAAM,MAAA,EAAQ,KAAA,CAAM,CAAA,8BAAA,EAAiC,WAAW,CAAA,CAAE,CAAA;AAElE,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,MAAM,gBAAA,CAAiB;AAAA,GACzB;AACF;;;;;"}
package/dist/index.cjs.js CHANGED
@@ -6,6 +6,7 @@ var url = require('./stages/prepare/url.cjs.js');
6
6
  var preparers = require('./stages/prepare/preparers.cjs.js');
7
7
  var publish = require('./stages/publish/publish.cjs.js');
8
8
  var helpers = require('./helpers.cjs.js');
9
+ var techdocsTypes = require('./techdocsTypes.cjs.js');
9
10
  var extensions = require('./extensions.cjs.js');
10
11
  var generators = require('./stages/generate/generators.cjs.js');
11
12
  var techdocs = require('./stages/generate/techdocs.cjs.js');
@@ -22,6 +23,7 @@ exports.getDocFilesFromRepository = helpers.getDocFilesFromRepository;
22
23
  exports.getLocationForEntity = helpers.getLocationForEntity;
23
24
  exports.parseReferenceAnnotation = helpers.parseReferenceAnnotation;
24
25
  exports.transformDirLocation = helpers.transformDirLocation;
26
+ exports.TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY = techdocsTypes.TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY;
25
27
  exports.techdocsBuildsExtensionPoint = extensions.techdocsBuildsExtensionPoint;
26
28
  exports.techdocsGeneratorExtensionPoint = extensions.techdocsGeneratorExtensionPoint;
27
29
  exports.techdocsPreparerExtensionPoint = extensions.techdocsPreparerExtensionPoint;
@@ -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
@@ -273,6 +273,7 @@ declare class TechdocsGenerator implements GeneratorBase {
273
273
  */
274
274
  declare class Generators implements GeneratorBuilder {
275
275
  private generatorMap;
276
+ private defaultEngine;
276
277
  /**
277
278
  * Returns a generators instance containing a generator for TechDocs
278
279
  * @param config - A Backstage configuration
@@ -281,7 +282,7 @@ declare class Generators implements GeneratorBuilder {
281
282
  static fromConfig(config: Config, options: {
282
283
  logger: LoggerService;
283
284
  containerRunner?: TechDocsContainerRunner;
284
- customGenerator?: TechdocsGenerator;
285
+ customGenerator?: GeneratorBase;
285
286
  }): Promise<GeneratorBuilder>;
286
287
  /**
287
288
  * Register a generator in the generators collection
@@ -587,6 +588,12 @@ interface DocsBuildStrategy {
587
588
  entity: Entity;
588
589
  }): Promise<boolean>;
589
590
  }
591
+ /**
592
+ * A catalog annotation key indicating which TechDoc Generation Engine to use
593
+ *
594
+ * @public
595
+ */
596
+ declare const TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY = "backstage.io/techdocs-engine";
590
597
 
591
598
  /**
592
599
  * Extension point type for configuring TechDocs builds.
@@ -604,12 +611,20 @@ interface TechdocsBuildsExtensionPoint {
604
611
  */
605
612
  declare const techdocsBuildsExtensionPoint: _backstage_backend_plugin_api.ExtensionPoint<TechdocsBuildsExtensionPoint>;
606
613
  /**
607
- * Extension point type for configuring a custom TechDocs generator
614
+ * Extension point type for configuring TechDocs generators.
615
+ *
616
+ * Use `registerGenerator` to add an engine-specific generator from a backend
617
+ * module (e.g. `plugin-techdocs-backend-module-zensical`). The key corresponds
618
+ * to the `backstage.io/techdocs-engine` entity annotation value.
619
+ *
620
+ * `setTechdocsGenerator` is kept for backwards compatibility — it replaces the
621
+ * default MkDocs generator.
608
622
  *
609
623
  * @public
610
624
  */
611
625
  interface TechdocsGeneratorExtensionPoint {
612
- setTechdocsGenerator(generator: TechdocsGenerator): void;
626
+ setTechdocsGenerator(generator: GeneratorBase): void;
627
+ registerGenerator(key: SupportedGeneratorKey, generator: GeneratorBase): void;
613
628
  }
614
629
  /**
615
630
  * Extension point for configuring a custom TechDocs generator
@@ -647,5 +662,5 @@ interface TechdocsPublisherExtensionPoint {
647
662
  */
648
663
  declare const techdocsPublisherExtensionPoint: _backstage_backend_plugin_api.ExtensionPoint<TechdocsPublisherExtensionPoint>;
649
664
 
650
- export { DirectoryPreparer, Generators, Preparers, Publisher, TechdocsGenerator, UrlPreparer, getDocFilesFromRepository, getLocationForEntity, getMkDocsYml, getMkdocsYml, parseReferenceAnnotation, techdocsBuildsExtensionPoint, techdocsGeneratorExtensionPoint, techdocsPreparerExtensionPoint, techdocsPublisherExtensionPoint, transformDirLocation };
665
+ export { DirectoryPreparer, Generators, Preparers, Publisher, TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY, TechdocsGenerator, UrlPreparer, getDocFilesFromRepository, getLocationForEntity, getMkDocsYml, getMkdocsYml, parseReferenceAnnotation, techdocsBuildsExtensionPoint, techdocsGeneratorExtensionPoint, techdocsPreparerExtensionPoint, techdocsPublisherExtensionPoint, transformDirLocation };
651
666
  export type { ContainerRunnerPullOptions, DocsBuildStrategy, ETag, GeneratorBase, GeneratorBuilder, GeneratorOptions, GeneratorRunOptions, MigrateRequest, ParsedLocationAnnotation, PreparerBase, PreparerBuilder, PreparerConfig, PreparerOptions, PreparerResponse, PublishRequest, PublishResponse, PublisherBase, PublisherBuilder, PublisherFactory, PublisherSettings, PublisherType, ReadinessResponse, RemoteProtocol, SupportedGeneratorKey, TechDocsContainerRunner, TechDocsDocument, TechDocsMetadata, TechdocsBuildsExtensionPoint, TechdocsGeneratorExtensionPoint, TechdocsPreparerExtensionPoint, TechdocsPublisherExtensionPoint };
@@ -1 +1 @@
1
- {"version":3,"file":"DockerContainerRunner.cjs.js","sources":["../../../src/stages/generate/DockerContainerRunner.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 Docker from 'dockerode';\nimport fs from 'fs-extra';\nimport { ForwardedError } from '@backstage/errors';\nimport { PassThrough } from 'node:stream';\nimport { pipeline as pipelineStream } from 'node:stream';\nimport { promisify } from 'node:util';\nimport { ContainerRunnerPullOptions, TechDocsContainerRunner } from './types';\nimport { Writable } from 'node:stream';\n\nconst pipeline = promisify(pipelineStream);\n\nexport type UserOptions = {\n User?: string;\n};\n\n/**\n * @internal\n */\nexport class DockerContainerRunner implements TechDocsContainerRunner {\n private readonly dockerClient: Docker;\n\n constructor() {\n this.dockerClient = new Docker();\n }\n\n async runContainer(options: {\n imageName: string;\n command?: string | string[];\n args: string[];\n logStream?: Writable;\n mountDirs?: Record<string, string>;\n workingDir?: string;\n envVars?: Record<string, string>;\n pullImage?: boolean;\n pullOptions?: ContainerRunnerPullOptions;\n defaultUser?: boolean;\n }) {\n const {\n imageName,\n command,\n args,\n logStream = new PassThrough(),\n mountDirs = {},\n workingDir,\n envVars = {},\n pullImage = true,\n pullOptions = {},\n defaultUser = false,\n } = options;\n\n // Show a better error message when Docker is unavailable.\n try {\n await this.dockerClient.ping();\n } catch (e) {\n throw new ForwardedError(\n 'This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with',\n e,\n );\n }\n\n if (pullImage) {\n await new Promise<void>((resolve, reject) => {\n this.dockerClient.pull(imageName, pullOptions, (err, stream) => {\n if (err) {\n reject(err);\n } else if (!stream) {\n reject(\n new Error(\n 'Unexpected error: no stream returned from Docker while pulling image',\n ),\n );\n } else {\n pipeline(stream, logStream, { end: false })\n .then(resolve)\n .catch(reject);\n }\n });\n });\n }\n\n const userOptions: UserOptions = {};\n if (!defaultUser && process.getuid && process.getgid) {\n // Files that are created inside the Docker container will be owned by\n // root on the host system on non Mac systems, because of reasons. Mainly the fact that\n // volume sharing is done using NFS on Mac and actual mounts in Linux world.\n // So we set the user in the container as the same user and group id as the host.\n // On Windows we don't have process.getuid nor process.getgid\n userOptions.User = `${process.getuid()}:${process.getgid()}`;\n }\n\n // Initialize volumes to mount based on mountDirs map\n const Volumes: { [T: string]: object } = {};\n for (const containerDir of Object.values(mountDirs)) {\n Volumes[containerDir] = {};\n }\n\n // Create bind volumes\n const Binds: string[] = [];\n for (const [hostDir, containerDir] of Object.entries(mountDirs)) {\n // Need to use realpath here as Docker mounting does not like\n // symlinks for binding volumes\n const realHostDir = await fs.realpath(hostDir);\n Binds.push(`${realHostDir}:${containerDir}`);\n }\n\n // Create docker environment variables array\n const Env = new Array<string>();\n for (const [key, value] of Object.entries(envVars)) {\n Env.push(`${key}=${value}`);\n }\n\n const [{ Error: error, StatusCode: statusCode }] =\n await this.dockerClient.run(imageName, args, logStream, {\n Volumes,\n HostConfig: {\n AutoRemove: true,\n Binds,\n },\n ...(workingDir ? { WorkingDir: workingDir } : {}),\n Entrypoint: command,\n Env,\n ...userOptions,\n } as Docker.ContainerCreateOptions);\n\n if (error) {\n throw new Error(\n `Docker failed to run with the following error message: ${error}`,\n );\n }\n\n if (statusCode !== 0) {\n throw new Error(\n `Docker container returned a non-zero exit code (${statusCode})`,\n );\n }\n }\n}\n"],"names":["promisify","pipelineStream","Docker","PassThrough","ForwardedError","fs"],"mappings":"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"}
1
+ {"version":3,"file":"DockerContainerRunner.cjs.js","sources":["../../../src/stages/generate/DockerContainerRunner.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 Docker from 'dockerode';\nimport fs from 'fs-extra';\nimport { ForwardedError } from '@backstage/errors';\nimport { PassThrough } from 'node:stream';\nimport { pipeline as pipelineStream } from 'node:stream';\nimport { promisify } from 'node:util';\nimport { ContainerRunnerPullOptions, TechDocsContainerRunner } from './types';\nimport { Writable } from 'node:stream';\n\nconst pipeline = promisify(pipelineStream);\n\nexport type UserOptions = {\n User?: string;\n};\n\n/**\n * @internal\n */\nexport class DockerContainerRunner implements TechDocsContainerRunner {\n private readonly dockerClient: Docker;\n\n constructor() {\n this.dockerClient = new Docker();\n }\n\n async runContainer(options: {\n imageName: string;\n command?: string | string[];\n args: string[];\n logStream?: Writable;\n mountDirs?: Record<string, string>;\n workingDir?: string;\n envVars?: Record<string, string>;\n pullImage?: boolean;\n pullOptions?: ContainerRunnerPullOptions;\n defaultUser?: boolean;\n }) {\n const {\n imageName,\n command,\n args,\n logStream = new PassThrough(),\n mountDirs = {},\n workingDir,\n envVars = {},\n pullImage = true,\n pullOptions = {},\n defaultUser = false,\n } = options;\n\n // Show a better error message when Docker is unavailable.\n try {\n await this.dockerClient.ping();\n } catch (e) {\n throw new ForwardedError(\n 'This operation requires Docker. Docker does not appear to be available. Docker.ping() failed with',\n e,\n );\n }\n\n if (pullImage) {\n await new Promise<void>((resolve, reject) => {\n this.dockerClient.pull(imageName, pullOptions, (err, stream) => {\n if (err) {\n reject(err);\n } else if (!stream) {\n reject(\n new Error(\n 'Unexpected error: no stream returned from Docker while pulling image',\n ),\n );\n } else {\n pipeline(stream, logStream, { end: false })\n .then(resolve)\n .catch(reject);\n }\n });\n });\n }\n\n const userOptions: UserOptions = {};\n if (!defaultUser && process.getuid && process.getgid) {\n // Files that are created inside the Docker container will be owned by\n // root on the host system on non Mac systems, because of reasons. Mainly the fact that\n // volume sharing is done using NFS on Mac and actual mounts in Linux world.\n // So we set the user in the container as the same user and group id as the host.\n // On Windows we don't have process.getuid nor process.getgid\n userOptions.User = `${process.getuid()}:${process.getgid()}`;\n }\n\n // Initialize volumes to mount based on mountDirs map\n const Volumes: { [T: string]: object } = {};\n for (const containerDir of Object.values(mountDirs)) {\n Volumes[containerDir] = {};\n }\n\n // Create bind volumes\n const Binds: string[] = [];\n for (const [hostDir, containerDir] of Object.entries(mountDirs)) {\n // Need to use realpath here as Docker mounting does not like\n // symlinks for binding volumes\n const realHostDir = await fs.realpath(hostDir);\n Binds.push(`${realHostDir}:${containerDir}`);\n }\n\n // Create docker environment variables array\n const Env = new Array<string>();\n for (const [key, value] of Object.entries(envVars)) {\n Env.push(`${key}=${value}`);\n }\n\n const [{ Error: error, StatusCode: statusCode }] =\n await this.dockerClient.run(imageName, args, logStream, {\n Volumes,\n HostConfig: {\n AutoRemove: true,\n Binds,\n },\n ...(workingDir ? { WorkingDir: workingDir } : {}),\n Entrypoint: command,\n Env,\n ...userOptions,\n } as Docker.ContainerCreateOptions);\n\n if (error) {\n throw new Error(\n `Docker failed to run with the following error message: ${error}`,\n );\n }\n\n if (statusCode !== 0) {\n throw new Error(\n `Docker container returned a non-zero exit code (${statusCode})`,\n );\n }\n }\n}\n"],"names":["promisify","pipelineStream","Docker","PassThrough","ForwardedError","fs"],"mappings":"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"}
@@ -1,10 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var helpers = require('./helpers.cjs.js');
4
3
  var techdocs = require('./techdocs.cjs.js');
4
+ var techdocsTypes = require('../../techdocsTypes.cjs.js');
5
5
 
6
+ function normalizeGeneratorKey(key) {
7
+ return key === "techdocs" ? "mkdocs" : key;
8
+ }
6
9
  class Generators {
7
10
  generatorMap = /* @__PURE__ */ new Map();
11
+ defaultEngine = "mkdocs";
8
12
  /**
9
13
  * Returns a generators instance containing a generator for TechDocs
10
14
  * @param config - A Backstage configuration
@@ -12,8 +16,11 @@ class Generators {
12
16
  */
13
17
  static async fromConfig(config, options) {
14
18
  const generators = new Generators();
15
- const techdocsGenerator = options.customGenerator ?? techdocs.TechdocsGenerator.fromConfig(config, options);
16
- generators.register("techdocs", techdocsGenerator);
19
+ const defaultEngine = config.getOptionalString("techdocs.generator.defaultEngine") ?? "mkdocs";
20
+ generators.defaultEngine = defaultEngine;
21
+ options.logger.info(`TechDocs generator defaultEngine: ${defaultEngine}`);
22
+ const mkdocsGenerator = options.customGenerator ?? techdocs.TechdocsGenerator.fromConfig(config, options);
23
+ generators.register("mkdocs", mkdocsGenerator);
17
24
  return generators;
18
25
  }
19
26
  /**
@@ -22,17 +29,26 @@ class Generators {
22
29
  * @param generator - The generator instance to register
23
30
  */
24
31
  register(generatorKey, generator) {
25
- this.generatorMap.set(generatorKey, generator);
32
+ this.generatorMap.set(normalizeGeneratorKey(generatorKey), generator);
26
33
  }
27
34
  /**
28
35
  * Returns the generator for a given TechDocs entity
29
36
  * @param entity - A TechDocs entity instance
30
37
  */
31
38
  get(entity) {
32
- const generatorKey = helpers.getGeneratorKey(entity);
39
+ if (!entity) {
40
+ throw new Error("No entity provided");
41
+ }
42
+ const annotatedEngine = entity.metadata?.annotations?.[techdocsTypes.TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY];
43
+ const generatorKey = normalizeGeneratorKey(
44
+ annotatedEngine ?? this.defaultEngine
45
+ );
33
46
  const generator = this.generatorMap.get(generatorKey);
34
47
  if (!generator) {
35
- throw new Error(`No generator registered for entity: "${generatorKey}"`);
48
+ const source = annotatedEngine ? `the ${techdocsTypes.TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY} annotation` : "techdocs.generator.defaultEngine";
49
+ throw new Error(
50
+ `No TechDocs generator registered for engine "${generatorKey}" (from ${source}). Registered engines: ${[...this.generatorMap.keys()].join(", ")}`
51
+ );
36
52
  }
37
53
  return generator;
38
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generators.cjs.js","sources":["../../../src/stages/generate/generators.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 { Entity } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { getGeneratorKey } from './helpers';\nimport { TechdocsGenerator } from './techdocs';\nimport {\n GeneratorBase,\n GeneratorBuilder,\n SupportedGeneratorKey,\n} from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { TechDocsContainerRunner } from './types';\n\n/**\n * Collection of docs generators\n * @public\n */\nexport class Generators implements GeneratorBuilder {\n private generatorMap = new Map<SupportedGeneratorKey, GeneratorBase>();\n\n /**\n * Returns a generators instance containing a generator for TechDocs\n * @param config - A Backstage configuration\n * @param options - Options to configure the TechDocs generator\n */\n static async fromConfig(\n config: Config,\n options: {\n logger: LoggerService;\n containerRunner?: TechDocsContainerRunner;\n customGenerator?: TechdocsGenerator;\n },\n ): Promise<GeneratorBuilder> {\n const generators = new Generators();\n\n const techdocsGenerator =\n options.customGenerator ?? TechdocsGenerator.fromConfig(config, options);\n generators.register('techdocs', techdocsGenerator);\n\n return generators;\n }\n\n /**\n * Register a generator in the generators collection\n * @param generatorKey - Unique identifier for the generator\n * @param generator - The generator instance to register\n */\n register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase) {\n this.generatorMap.set(generatorKey, generator);\n }\n\n /**\n * Returns the generator for a given TechDocs entity\n * @param entity - A TechDocs entity instance\n */\n get(entity: Entity): GeneratorBase {\n const generatorKey = getGeneratorKey(entity);\n const generator = this.generatorMap.get(generatorKey);\n\n if (!generator) {\n throw new Error(`No generator registered for entity: \"${generatorKey}\"`);\n }\n\n return generator;\n }\n}\n"],"names":["TechdocsGenerator","getGeneratorKey"],"mappings":";;;;;AAgCO,MAAM,UAAA,CAAuC;AAAA,EAC1C,YAAA,uBAAmB,GAAA,EAA0C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrE,aAAa,UAAA,CACX,MAAA,EACA,OAAA,EAK2B;AAC3B,IAAA,MAAM,UAAA,GAAa,IAAI,UAAA,EAAW;AAElC,IAAA,MAAM,oBACJ,OAAA,CAAQ,eAAA,IAAmBA,0BAAA,CAAkB,UAAA,CAAW,QAAQ,OAAO,CAAA;AACzE,IAAA,UAAA,CAAW,QAAA,CAAS,YAAY,iBAAiB,CAAA;AAEjD,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAA,CAAS,cAAqC,SAAA,EAA0B;AACtE,IAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,SAAS,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,MAAA,EAA+B;AACjC,IAAA,MAAM,YAAA,GAAeC,wBAAgB,MAAM,CAAA;AAC3C,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,YAAY,CAAA;AAEpD,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,YAAY,CAAA,CAAA,CAAG,CAAA;AAAA,IACzE;AAEA,IAAA,OAAO,SAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"generators.cjs.js","sources":["../../../src/stages/generate/generators.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 { Entity } from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport { TechdocsGenerator } from './techdocs';\nimport {\n GeneratorBase,\n GeneratorBuilder,\n SupportedGeneratorKey,\n} from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { TechDocsContainerRunner } from './types';\nimport { TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY } from '../../techdocsTypes';\n\n/**\n * 'techdocs' was the generator key before engines were introduced, and is\n * kept as an alias of 'mkdocs' so that existing registrations keep working.\n */\nfunction normalizeGeneratorKey(key: SupportedGeneratorKey): string {\n return key === 'techdocs' ? 'mkdocs' : key;\n}\n\n/**\n * Collection of docs generators\n * @public\n */\nexport class Generators implements GeneratorBuilder {\n private generatorMap = new Map<SupportedGeneratorKey, GeneratorBase>();\n private defaultEngine: SupportedGeneratorKey = 'mkdocs';\n\n /**\n * Returns a generators instance containing a generator for TechDocs\n * @param config - A Backstage configuration\n * @param options - Options to configure the TechDocs generator\n */\n static async fromConfig(\n config: Config,\n options: {\n logger: LoggerService;\n containerRunner?: TechDocsContainerRunner;\n customGenerator?: GeneratorBase;\n },\n ): Promise<GeneratorBuilder> {\n const generators = new Generators();\n const defaultEngine =\n config.getOptionalString('techdocs.generator.defaultEngine') ?? 'mkdocs';\n\n generators.defaultEngine = defaultEngine;\n\n options.logger.info(`TechDocs generator defaultEngine: ${defaultEngine}`);\n\n const mkdocsGenerator =\n options.customGenerator ?? TechdocsGenerator.fromConfig(config, options);\n generators.register('mkdocs', mkdocsGenerator);\n\n return generators;\n }\n\n /**\n * Register a generator in the generators collection\n * @param generatorKey - Unique identifier for the generator\n * @param generator - The generator instance to register\n */\n register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase) {\n this.generatorMap.set(normalizeGeneratorKey(generatorKey), generator);\n }\n\n /**\n * Returns the generator for a given TechDocs entity\n * @param entity - A TechDocs entity instance\n */\n get(entity: Entity): GeneratorBase {\n if (!entity) {\n throw new Error('No entity provided');\n }\n\n const annotatedEngine =\n entity.metadata?.annotations?.[TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY];\n const generatorKey = normalizeGeneratorKey(\n annotatedEngine ?? this.defaultEngine,\n );\n const generator = this.generatorMap.get(generatorKey);\n\n if (!generator) {\n const source = annotatedEngine\n ? `the ${TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY} annotation`\n : 'techdocs.generator.defaultEngine';\n throw new Error(\n `No TechDocs generator registered for engine \"${generatorKey}\" (from ${source}). ` +\n `Registered engines: ${[...this.generatorMap.keys()].join(', ')}`,\n );\n }\n\n return generator;\n }\n}\n"],"names":["TechdocsGenerator","TECHDOCS_ENGINE_CATALOG_ANNOTATION_KEY"],"mappings":";;;;;AAgCA,SAAS,sBAAsB,GAAA,EAAoC;AACjE,EAAA,OAAO,GAAA,KAAQ,aAAa,QAAA,GAAW,GAAA;AACzC;AAMO,MAAM,UAAA,CAAuC;AAAA,EAC1C,YAAA,uBAAmB,GAAA,EAA0C;AAAA,EAC7D,aAAA,GAAuC,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/C,aAAa,UAAA,CACX,MAAA,EACA,OAAA,EAK2B;AAC3B,IAAA,MAAM,UAAA,GAAa,IAAI,UAAA,EAAW;AAClC,IAAA,MAAM,aAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,kCAAkC,CAAA,IAAK,QAAA;AAElE,IAAA,UAAA,CAAW,aAAA,GAAgB,aAAA;AAE3B,IAAA,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,CAAA,kCAAA,EAAqC,aAAa,CAAA,CAAE,CAAA;AAExE,IAAA,MAAM,kBACJ,OAAA,CAAQ,eAAA,IAAmBA,0BAAA,CAAkB,UAAA,CAAW,QAAQ,OAAO,CAAA;AACzE,IAAA,UAAA,CAAW,QAAA,CAAS,UAAU,eAAe,CAAA;AAE7C,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAA,CAAS,cAAqC,SAAA,EAA0B;AACtE,IAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,qBAAA,CAAsB,YAAY,GAAG,SAAS,CAAA;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,MAAA,EAA+B;AACjC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,IACtC;AAEA,IAAA,MAAM,eAAA,GACJ,MAAA,CAAO,QAAA,EAAU,WAAA,GAAcC,oDAAsC,CAAA;AACvE,IAAA,MAAM,YAAA,GAAe,qBAAA;AAAA,MACnB,mBAAmB,IAAA,CAAK;AAAA,KAC1B;AACA,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,CAAa,GAAA,CAAI,YAAY,CAAA;AAEpD,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,MAAA,GAAS,eAAA,GACX,CAAA,IAAA,EAAOA,oDAAsC,CAAA,WAAA,CAAA,GAC7C,kCAAA;AACJ,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,6CAAA,EAAgD,YAAY,CAAA,QAAA,EAAW,MAAM,0BACpD,CAAC,GAAG,IAAA,CAAK,YAAA,CAAa,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OACnE;AAAA,IACF;AAEA,IAAA,OAAO,SAAA;AAAA,EACT;AACF;;"}
@@ -12,17 +12,29 @@ var helpers = require('../publish/helpers.cjs.js');
12
12
 
13
13
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
14
14
 
15
+ function _interopNamespaceCompat(e) {
16
+ if (e && typeof e === 'object' && 'default' in e) return e;
17
+ var n = Object.create(null);
18
+ if (e) {
19
+ Object.keys(e).forEach(function (k) {
20
+ if (k !== 'default') {
21
+ var d = Object.getOwnPropertyDescriptor(e, k);
22
+ Object.defineProperty(n, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: function () { return e[k]; }
25
+ });
26
+ }
27
+ });
28
+ }
29
+ n.default = e;
30
+ return Object.freeze(n);
31
+ }
32
+
15
33
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
16
34
  var gitUrlParse__default = /*#__PURE__*/_interopDefaultCompat(gitUrlParse);
17
- var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
35
+ var yaml__namespace = /*#__PURE__*/_interopNamespaceCompat(yaml);
18
36
  var path__default = /*#__PURE__*/_interopDefaultCompat(path);
19
37
 
20
- function getGeneratorKey(entity) {
21
- if (!entity) {
22
- throw new Error("No entity provided");
23
- }
24
- return "techdocs";
25
- }
26
38
  const runCommand = async ({
27
39
  command,
28
40
  args,
@@ -107,32 +119,36 @@ class UnknownTag {
107
119
  this.type = type;
108
120
  }
109
121
  }
110
- const MKDOCS_SCHEMA = yaml.DEFAULT_SCHEMA.extend([
111
- new yaml.Type("", {
112
- kind: "scalar",
113
- multi: true,
114
- representName: (o) => o.type,
115
- represent: (o) => o.data ?? "",
116
- instanceOf: UnknownTag,
117
- construct: (data, type) => new UnknownTag(data, type)
122
+ const MKDOCS_SCHEMA = yaml.YAML11_SCHEMA.withTags(
123
+ yaml.defineScalarTag("", {
124
+ matchByTagPrefix: true,
125
+ resolve: (data, _isExplicit, tagName) => new UnknownTag(data, tagName),
126
+ identify: (data) => data instanceof UnknownTag && typeof data.data === "string",
127
+ represent: (data) => data.data,
128
+ representTagName: (data) => data.type
118
129
  }),
119
- new yaml.Type("tag:", {
120
- kind: "mapping",
121
- multi: true,
122
- representName: (o) => o.type,
123
- represent: (o) => o.data ?? "",
124
- instanceOf: UnknownTag,
125
- construct: (data, type) => new UnknownTag(data, type)
130
+ yaml.defineSequenceTag("", {
131
+ matchByTagPrefix: true,
132
+ create: (tagName) => new UnknownTag([], tagName),
133
+ addItem: (carrier, item) => {
134
+ carrier.data.push(item);
135
+ },
136
+ identify: (data) => data instanceof UnknownTag && Array.isArray(data.data),
137
+ represent: (data) => data.data,
138
+ representTagName: (data) => data.type
126
139
  }),
127
- new yaml.Type("", {
128
- kind: "sequence",
129
- multi: true,
130
- representName: (o) => o.type,
131
- represent: (o) => o.data ?? "",
132
- instanceOf: UnknownTag,
133
- construct: (data, type) => new UnknownTag(data, type)
140
+ yaml.defineMappingTag("tag:", {
141
+ matchByTagPrefix: true,
142
+ create: (tagName) => new UnknownTag({}, tagName),
143
+ addPair: (carrier, key, value) => yaml.mapTag.addPair(carrier.data, key, value),
144
+ has: (carrier, key) => yaml.mapTag.has(carrier.data, key),
145
+ keys: (result) => yaml.mapTag.keys(result.data),
146
+ get: (result, key) => yaml.mapTag.get(result.data, key),
147
+ identify: (data) => data instanceof UnknownTag && typeof data.data === "object" && data.data !== null && !Array.isArray(data.data),
148
+ represent: (data) => new Map(Object.entries(data.data)),
149
+ representTagName: (data) => data.type
134
150
  })
135
- ]);
151
+ );
136
152
  const generateMkdocsYml = async (inputDir, siteOptions) => {
137
153
  try {
138
154
  const mkdocsYmlPath = path__default.default.join(inputDir, "mkdocs.yml");
@@ -144,7 +160,7 @@ const generateMkdocsYml = async (inputDir, siteOptions) => {
144
160
  };
145
161
  await fs__default.default.writeFile(
146
162
  mkdocsYmlPath,
147
- yaml__default.default.dump(defaultMkdocsContent, { schema: MKDOCS_SCHEMA })
163
+ yaml__namespace.dump(defaultMkdocsContent, { schema: MKDOCS_SCHEMA })
148
164
  );
149
165
  } catch (error) {
150
166
  throw new errors.ForwardedError("Could not generate mkdocs.yml file", error);
@@ -248,7 +264,7 @@ const ALLOWED_THEME_KEYS = /* @__PURE__ */ new Set([
248
264
  "features"
249
265
  ]);
250
266
  const validateMkdocsYaml = async (inputDir, mkdocsYmlFileString) => {
251
- const mkdocsYml = yaml__default.default.load(mkdocsYmlFileString, {
267
+ const mkdocsYml = yaml__namespace.load(mkdocsYmlFileString, {
252
268
  schema: MKDOCS_SCHEMA
253
269
  });
254
270
  if (mkdocsYml === null || typeof mkdocsYml !== "object") {
@@ -323,7 +339,7 @@ const patchIndexPreBuild = async ({
323
339
  ].join(" ")} exists.`
324
340
  );
325
341
  };
326
- const createOrUpdateMetadata = async (techdocsMetadataPath, logger) => {
342
+ const createOrUpdateMetadata = async (techdocsMetadataPath, logger, engine) => {
327
343
  const techdocsMetadataDir = techdocsMetadataPath.split(path__default.default.sep).slice(0, -1).join(path__default.default.sep);
328
344
  try {
329
345
  await fs__default.default.access(techdocsMetadataPath, fs__default.default.constants.F_OK);
@@ -339,6 +355,9 @@ const createOrUpdateMetadata = async (techdocsMetadataPath, logger) => {
339
355
  throw new Error(message);
340
356
  }
341
357
  json.build_timestamp = Date.now();
358
+ {
359
+ json.engine = engine;
360
+ }
342
361
  try {
343
362
  json.files = (await helpers.getFileTreeRecursively(techdocsMetadataDir)).map(
344
363
  (file) => file.replace(`${techdocsMetadataDir}${path__default.default.sep}`, "")
@@ -365,7 +384,6 @@ exports.MKDOCS_SCHEMA = MKDOCS_SCHEMA;
365
384
  exports.UnknownTag = UnknownTag;
366
385
  exports.createOrUpdateMetadata = createOrUpdateMetadata;
367
386
  exports.generateMkdocsYml = generateMkdocsYml;
368
- exports.getGeneratorKey = getGeneratorKey;
369
387
  exports.getMkdocsYml = getMkdocsYml;
370
388
  exports.getRepoUrlFromLocationAnnotation = getRepoUrlFromLocationAnnotation;
371
389
  exports.patchIndexPreBuild = patchIndexPreBuild;