@backstage/plugin-techdocs-node 1.4.4-next.0 → 1.4.4-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @backstage/plugin-techdocs-node
2
2
 
3
+ ## 1.4.4-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/backend-common@0.18.0-next.1
9
+ - @backstage/catalog-model@1.1.5-next.1
10
+ - @backstage/config@1.0.6-next.0
11
+ - @backstage/errors@1.1.4
12
+ - @backstage/integration@1.4.2-next.0
13
+ - @backstage/integration-aws-node@0.1.1-next.0
14
+ - @backstage/plugin-search-common@1.2.1-next.0
15
+
16
+ ## 1.4.4-next.1
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies
21
+ - @backstage/backend-common@0.18.0-next.0
22
+ - @backstage/config@1.0.6-next.0
23
+ - @backstage/catalog-model@1.1.5-next.1
24
+ - @backstage/errors@1.1.4
25
+ - @backstage/integration@1.4.2-next.0
26
+ - @backstage/integration-aws-node@0.1.1-next.0
27
+ - @backstage/plugin-search-common@1.2.1-next.0
28
+
3
29
  ## 1.4.4-next.0
4
30
 
5
31
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -106,6 +106,7 @@ const getCloudPathForLocalPath = (entity, localPath = "", useLegacyPathCasing =
106
106
  const relativeFilePathTriplet = `${entityRootDir}/${relativeFilePathPosix}`;
107
107
  const destination = useLegacyPathCasing ? relativeFilePathTriplet : lowerCaseEntityTriplet(relativeFilePathTriplet);
108
108
  const destinationWithRoot = [
109
+ // The extra filter prevents unintended double slashes and prefixes.
109
110
  ...externalStorageRootPath.split(path__default["default"].posix.sep).filter((s) => s !== ""),
110
111
  destination
111
112
  ].join("/");
@@ -383,6 +384,11 @@ const pathMkdocsYmlWithTechdocsPlugin = async (mkdocsYmlPath, logger) => {
383
384
  };
384
385
 
385
386
  const _TechdocsGenerator = class {
387
+ /**
388
+ * Returns a instance of TechDocs generator
389
+ * @param config - A Backstage configuration
390
+ * @param options - Options to configure the generator
391
+ */
386
392
  static fromConfig(config, options) {
387
393
  const { containerRunner, logger } = options;
388
394
  const scmIntegrations = integration.ScmIntegrations.fromConfig(config);
@@ -399,6 +405,7 @@ const _TechdocsGenerator = class {
399
405
  this.containerRunner = options.containerRunner;
400
406
  this.scmIntegrations = options.scmIntegrations;
401
407
  }
408
+ /** {@inheritDoc GeneratorBase.run} */
402
409
  async run(options) {
403
410
  var _a;
404
411
  const {
@@ -456,6 +463,8 @@ const _TechdocsGenerator = class {
456
463
  logStream,
457
464
  mountDirs,
458
465
  workingDir: "/input",
466
+ // Set the home directory inside the container as something that applications can
467
+ // write to, otherwise they will just fail trying to write to /
459
468
  envVars: { HOME: "/tmp" },
460
469
  pullImage: this.options.pullImage
461
470
  });
@@ -490,6 +499,10 @@ const _TechdocsGenerator = class {
490
499
  }
491
500
  };
492
501
  let TechdocsGenerator = _TechdocsGenerator;
502
+ /**
503
+ * The default docker image (and version) used to generate content. Public
504
+ * and static so that techdocs-node consumers can use the same version.
505
+ */
493
506
  TechdocsGenerator.defaultDockerImage = "spotify/techdocs:v1.1.0";
494
507
  function readGeneratorConfig(config, logger) {
495
508
  var _a;
@@ -518,15 +531,29 @@ class Generators {
518
531
  constructor() {
519
532
  this.generatorMap = /* @__PURE__ */ new Map();
520
533
  }
534
+ /**
535
+ * Returns a generators instance containing a generator for TechDocs
536
+ * @param config - A Backstage configuration
537
+ * @param options - Options to configure the TechDocs generator
538
+ */
521
539
  static async fromConfig(config, options) {
522
540
  const generators = new Generators();
523
541
  const techdocsGenerator = TechdocsGenerator.fromConfig(config, options);
524
542
  generators.register("techdocs", techdocsGenerator);
525
543
  return generators;
526
544
  }
545
+ /**
546
+ * Register a generator in the generators collection
547
+ * @param generatorKey - Unique identifier for the generator
548
+ * @param generator - The generator instance to register
549
+ */
527
550
  register(generatorKey, generator) {
528
551
  this.generatorMap.set(generatorKey, generator);
529
552
  }
553
+ /**
554
+ * Returns the generator for a given TechDocs entity
555
+ * @param entity - A TechDocs entity instance
556
+ */
530
557
  get(entity) {
531
558
  const generatorKey = getGeneratorKey(entity);
532
559
  const generator = this.generatorMap.get(generatorKey);
@@ -609,6 +636,11 @@ const getDocFilesFromRepository = async (reader, entity, opts) => {
609
636
  };
610
637
 
611
638
  class DirectoryPreparer {
639
+ /**
640
+ * Returns a directory preparer instance
641
+ * @param config - A backstage config
642
+ * @param options - A directory preparer options containing a logger and reader
643
+ */
612
644
  static fromConfig(config, { logger, reader }) {
613
645
  return new DirectoryPreparer(config, logger, reader);
614
646
  }
@@ -616,6 +648,7 @@ class DirectoryPreparer {
616
648
  this.reader = reader;
617
649
  this.scmIntegrations = integration.ScmIntegrations.fromConfig(config);
618
650
  }
651
+ /** {@inheritDoc PreparerBase.prepare} */
619
652
  async prepare(entity, options) {
620
653
  var _a, _b;
621
654
  const annotation = parseReferenceAnnotation(
@@ -642,7 +675,9 @@ class DirectoryPreparer {
642
675
  }
643
676
  case "dir": {
644
677
  return {
678
+ // the transformation already validated that the target is in a safe location
645
679
  preparedDir: target,
680
+ // Instead of supporting caching on local sources, use techdocs-cli for local development and debugging.
646
681
  etag: ""
647
682
  };
648
683
  }
@@ -653,6 +688,10 @@ class DirectoryPreparer {
653
688
  }
654
689
 
655
690
  class UrlPreparer {
691
+ /**
692
+ * Returns a directory preparer instance
693
+ * @param config - A URL preparer config containing the a logger and reader
694
+ */
656
695
  static fromConfig({ reader, logger }) {
657
696
  return new UrlPreparer(reader, logger);
658
697
  }
@@ -660,6 +699,7 @@ class UrlPreparer {
660
699
  this.logger = logger;
661
700
  this.reader = reader;
662
701
  }
702
+ /** {@inheritDoc PreparerBase.prepare} */
663
703
  async prepare(entity, options) {
664
704
  try {
665
705
  return await getDocFilesFromRepository(this.reader, entity, {
@@ -684,6 +724,12 @@ class Preparers {
684
724
  constructor() {
685
725
  this.preparerMap = /* @__PURE__ */ new Map();
686
726
  }
727
+ /**
728
+ * Returns a generators instance containing a generator for TechDocs
729
+ * @public
730
+ * @param backstageConfig - A Backstage configuration
731
+ * @param preparerConfig - Options to configure preparers
732
+ */
687
733
  static async fromConfig(backstageConfig, { logger, reader }) {
688
734
  const preparers = new Preparers();
689
735
  const urlPreparer = UrlPreparer.fromConfig({ reader, logger });
@@ -695,9 +741,19 @@ class Preparers {
695
741
  preparers.register("dir", directoryPreparer);
696
742
  return preparers;
697
743
  }
744
+ /**
745
+ * Register a preparer in the preparers collection
746
+ * @param protocol - url or dir to associate with preparer
747
+ * @param preparer - The preparer instance to set
748
+ */
698
749
  register(protocol, preparer) {
699
750
  this.preparerMap.set(protocol, preparer);
700
751
  }
752
+ /**
753
+ * Returns the preparer for a given TechDocs entity
754
+ * @param entity - A TechDocs entity instance
755
+ * @returns
756
+ */
701
757
  get(entity) {
702
758
  const { type } = parseReferenceAnnotation(
703
759
  "backstage.io/techdocs-ref",
@@ -818,6 +874,10 @@ class AwsS3Publish {
818
874
  }
819
875
  return explicitCredentials;
820
876
  }
877
+ /**
878
+ * Check if the defined bucket exists. Being able to connect means the configuration is good
879
+ * and the storage client will work.
880
+ */
821
881
  async getReadiness() {
822
882
  try {
823
883
  await this.storageClient.send(
@@ -837,6 +897,10 @@ class AwsS3Publish {
837
897
  };
838
898
  }
839
899
  }
900
+ /**
901
+ * Upload all the files from the generated `directory` to the S3 bucket.
902
+ * Directory structure used in the bucket is - entityNamespace/entityKind/entityName/index.html
903
+ */
840
904
  async publish({
841
905
  entity,
842
906
  directory
@@ -964,6 +1028,9 @@ class AwsS3Publish {
964
1028
  throw new errors.ForwardedError("TechDocs metadata fetch failed", e);
965
1029
  }
966
1030
  }
1031
+ /**
1032
+ * Express route middleware to serve static files on a route in techdocs-backend.
1033
+ */
967
1034
  docsRouter() {
968
1035
  return async (req, res) => {
969
1036
  const decodedUri = decodeURI(req.path.replace(/^\//, ""));
@@ -990,6 +1057,10 @@ class AwsS3Publish {
990
1057
  }
991
1058
  };
992
1059
  }
1060
+ /**
1061
+ * A helper function which checks if index.html of an Entity's docs site is available. This
1062
+ * can be used to verify if there are any pre-generated docs available to serve.
1063
+ */
993
1064
  async hasDocsBeenGenerated(entity) {
994
1065
  try {
995
1066
  const entityTriplet = `${entity.metadata.namespace}/${entity.kind}/${entity.metadata.name}`;
@@ -1051,6 +1122,9 @@ class AwsS3Publish {
1051
1122
  )
1052
1123
  );
1053
1124
  }
1125
+ /**
1126
+ * Returns a list of all object keys from the configured bucket.
1127
+ */
1054
1128
  async getAllObjectsFromBucket({ prefix } = { prefix: "" }) {
1055
1129
  const objects = [];
1056
1130
  let nextContinuation;
@@ -1146,6 +1220,10 @@ class AzureBlobStoragePublish {
1146
1220
  );
1147
1221
  return { isAvailable: false };
1148
1222
  }
1223
+ /**
1224
+ * Upload all the files from the generated `directory` to the Azure Blob Storage container.
1225
+ * Directory structure used in the container is - entityNamespace/entityKind/entityName/index.html
1226
+ */
1149
1227
  async publish({
1150
1228
  entity,
1151
1229
  directory
@@ -1275,6 +1353,9 @@ class AzureBlobStoragePublish {
1275
1353
  throw new errors.ForwardedError("TechDocs metadata fetch failed", e);
1276
1354
  }
1277
1355
  }
1356
+ /**
1357
+ * Express route middleware to serve static files on a route in techdocs-backend.
1358
+ */
1278
1359
  docsRouter() {
1279
1360
  return (req, res) => {
1280
1361
  const decodedUri = decodeURI(req.path.replace(/^\//, ""));
@@ -1296,6 +1377,10 @@ class AzureBlobStoragePublish {
1296
1377
  });
1297
1378
  };
1298
1379
  }
1380
+ /**
1381
+ * A helper function which checks if index.html of an Entity's docs site is available. This
1382
+ * can be used to verify if there are any pre-generated docs available to serve.
1383
+ */
1299
1384
  hasDocsBeenGenerated(entity) {
1300
1385
  const entityTriplet = `${entity.metadata.namespace}/${entity.kind}/${entity.metadata.name}`;
1301
1386
  const entityRootDir = this.legacyPathCasing ? entityTriplet : lowerCaseEntityTriplet(entityTriplet);
@@ -1467,6 +1552,10 @@ class GoogleGCSPublish {
1467
1552
  bucketRootPath
1468
1553
  });
1469
1554
  }
1555
+ /**
1556
+ * Check if the defined bucket exists. Being able to connect means the configuration is good
1557
+ * and the storage client will work.
1558
+ */
1470
1559
  async getReadiness() {
1471
1560
  try {
1472
1561
  await this.storageClient.bucket(this.bucketName).getMetadata();
@@ -1485,6 +1574,10 @@ class GoogleGCSPublish {
1485
1574
  return { isAvailable: false };
1486
1575
  }
1487
1576
  }
1577
+ /**
1578
+ * Upload all the files from the generated `directory` to the GCS bucket.
1579
+ * Directory structure used in the bucket is - entityNamespace/entityKind/entityName/index.html
1580
+ */
1488
1581
  async publish({
1489
1582
  entity,
1490
1583
  directory
@@ -1577,6 +1670,9 @@ class GoogleGCSPublish {
1577
1670
  });
1578
1671
  });
1579
1672
  }
1673
+ /**
1674
+ * Express route middleware to serve static files on a route in techdocs-backend.
1675
+ */
1580
1676
  docsRouter() {
1581
1677
  return (req, res) => {
1582
1678
  const decodedUri = decodeURI(req.path.replace(/^\//, ""));
@@ -1598,6 +1694,10 @@ class GoogleGCSPublish {
1598
1694
  }).pipe(res);
1599
1695
  };
1600
1696
  }
1697
+ /**
1698
+ * A helper function which checks if index.html of an Entity's docs site is available. This
1699
+ * can be used to verify if there are any pre-generated docs available to serve.
1700
+ */
1601
1701
  async hasDocsBeenGenerated(entity) {
1602
1702
  return new Promise((resolve) => {
1603
1703
  const entityTriplet = `${entity.metadata.namespace}/${entity.kind}/${entity.metadata.name}`;
@@ -1775,6 +1875,7 @@ class LocalPublish {
1775
1875
  });
1776
1876
  router.use(
1777
1877
  express__default["default"].static(this.staticDocsDir, {
1878
+ // Handle content-type header the same as all other publishers.
1778
1879
  setHeaders: (res, filePath) => {
1779
1880
  const fileExtension = path__default["default"].extname(filePath);
1780
1881
  const headers = getHeadersForFileExtension(fileExtension);
@@ -1809,6 +1910,10 @@ class LocalPublish {
1809
1910
  return false;
1810
1911
  }
1811
1912
  }
1913
+ /**
1914
+ * This code will never run in practice. It is merely here to illustrate how
1915
+ * to implement this method for other storage providers.
1916
+ */
1812
1917
  async migrateDocsCase({
1813
1918
  removeOriginal = false,
1814
1919
  concurrency = 25
@@ -1842,6 +1947,9 @@ class LocalPublish {
1842
1947
  )
1843
1948
  );
1844
1949
  }
1950
+ /**
1951
+ * Utility wrapper around path.join(), used to control legacy case logic.
1952
+ */
1845
1953
  staticEntityPathJoin(...allParts) {
1846
1954
  let staticEntityPath = this.staticDocsDir;
1847
1955
  allParts.map((part) => part.split(path__default["default"].sep)).flat().forEach((part, index) => {
@@ -1904,6 +2012,10 @@ class OpenStackSwiftPublish {
1904
2012
  });
1905
2013
  return new OpenStackSwiftPublish({ storageClient, containerName, logger });
1906
2014
  }
2015
+ /*
2016
+ * Check if the defined container exists. Being able to connect means the configuration is good
2017
+ * and the storage client will work.
2018
+ */
1907
2019
  async getReadiness() {
1908
2020
  try {
1909
2021
  const container = await this.storageClient.getContainerMetadata(
@@ -1931,6 +2043,10 @@ class OpenStackSwiftPublish {
1931
2043
  };
1932
2044
  }
1933
2045
  }
2046
+ /**
2047
+ * Upload all the files from the generated `directory` to the OpenStack Swift container.
2048
+ * Directory structure used in the bucket is - entityNamespace/entityKind/entityName/index.html
2049
+ */
1934
2050
  async publish({
1935
2051
  entity,
1936
2052
  directory
@@ -2000,6 +2116,9 @@ class OpenStackSwiftPublish {
2000
2116
  }
2001
2117
  });
2002
2118
  }
2119
+ /**
2120
+ * Express route middleware to serve static files on a route in techdocs-backend.
2121
+ */
2003
2122
  docsRouter() {
2004
2123
  return async (req, res) => {
2005
2124
  const filePath = decodeURI(req.path.replace(/^\//, ""));
@@ -2033,6 +2152,10 @@ class OpenStackSwiftPublish {
2033
2152
  }
2034
2153
  };
2035
2154
  }
2155
+ /**
2156
+ * A helper function which checks if index.html of an Entity's docs site is available. This
2157
+ * can be used to verify if there are any pre-generated docs available to serve.
2158
+ */
2036
2159
  async hasDocsBeenGenerated(entity) {
2037
2160
  const entityRootDir = `${entity.metadata.namespace}/${entity.kind}/${entity.metadata.name}`;
2038
2161
  try {
@@ -2089,6 +2212,9 @@ class OpenStackSwiftPublish {
2089
2212
  )
2090
2213
  );
2091
2214
  }
2215
+ /**
2216
+ * Returns a list of all object keys from the configured container.
2217
+ */
2092
2218
  async getAllObjectsFromContainer({ prefix } = { prefix: "" }) {
2093
2219
  let objects = [];
2094
2220
  const OSS_MAX_LIMIT = Math.pow(2, 31) - 1;
@@ -2103,6 +2229,11 @@ class OpenStackSwiftPublish {
2103
2229
  }
2104
2230
 
2105
2231
  class Publisher {
2232
+ /**
2233
+ * Returns a instance of TechDocs publisher
2234
+ * @param config - A Backstage configuration
2235
+ * @param options - Options for configuring the publisher factory
2236
+ */
2106
2237
  static async fromConfig(config, { logger, discovery }) {
2107
2238
  var _a;
2108
2239
  const publisherType = (_a = config.getOptionalString(