@backstage/backend-defaults 0.17.9-next.1 → 0.18.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.
Files changed (133) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/config.schema.json +5 -0
  3. package/dist/CreateBackend.cjs.js.map +1 -1
  4. package/dist/PackageDiscoveryService.cjs.js.map +1 -1
  5. package/dist/alpha/entrypoints/actions/DefaultActionsService.cjs.js.map +1 -1
  6. package/dist/alpha/entrypoints/actions/actionsServiceFactory.cjs.js.map +1 -1
  7. package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +1 -1
  8. package/dist/alpha/entrypoints/actionsRegistry/actionFilters.cjs.js.map +1 -1
  9. package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +1 -1
  10. package/dist/alpha/entrypoints/instanceMetadata/instanceMetadataServiceFactory.cjs.js.map +1 -1
  11. package/dist/alpha/entrypoints/metrics/DefaultMetricsService.cjs.js.map +1 -1
  12. package/dist/alpha/entrypoints/metrics/metricsServiceFactory.cjs.js.map +1 -1
  13. package/dist/alpha/entrypoints/tracing/DefaultTracingService.cjs.js.map +1 -1
  14. package/dist/alpha/entrypoints/tracing/tracingServiceFactory.cjs.js.map +1 -1
  15. package/dist/discoveryFeatureLoader.cjs.js.map +1 -1
  16. package/dist/entrypoints/auditor/DefaultAuditorService.cjs.js.map +1 -1
  17. package/dist/entrypoints/auditor/WinstonRootAuditorService.cjs.js.map +1 -1
  18. package/dist/entrypoints/auditor/auditorServiceFactory.cjs.js.map +1 -1
  19. package/dist/entrypoints/auditor/utils.cjs.js.map +1 -1
  20. package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -1
  21. package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -1
  22. package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -1
  23. package/dist/entrypoints/auth/external/ExternalAuthTokenHandler.cjs.js.map +1 -1
  24. package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -1
  25. package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -1
  26. package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -1
  27. package/dist/entrypoints/auth/external/static.cjs.js.map +1 -1
  28. package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
  29. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js +5 -5
  30. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -1
  31. package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -1
  32. package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -1
  33. package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -1
  34. package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -1
  35. package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -1
  36. package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -1
  37. package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -1
  38. package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -1
  39. package/dist/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.cjs.js.map +1 -1
  40. package/dist/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.cjs.js.map +1 -1
  41. package/dist/entrypoints/cache/types.cjs.js.map +1 -1
  42. package/dist/entrypoints/database/DatabaseManager.cjs.js +7 -1
  43. package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -1
  44. package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -1
  45. package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -1
  46. package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -1
  47. package/dist/entrypoints/database/connectors/postgres.cjs.js +18 -5
  48. package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
  49. package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -1
  50. package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -1
  51. package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -1
  52. package/dist/entrypoints/discovery/SrvResolvers.cjs.js.map +1 -1
  53. package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -1
  54. package/dist/entrypoints/discovery/parsing.cjs.js.map +1 -1
  55. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js +14 -4
  56. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -1
  57. package/dist/entrypoints/httpRouter/http/createAuthIntegrationRouter.cjs.js.map +1 -1
  58. package/dist/entrypoints/httpRouter/http/createCookieAuthRefreshMiddleware.cjs.js.map +1 -1
  59. package/dist/entrypoints/httpRouter/http/createCredentialsBarrier.cjs.js.map +1 -1
  60. package/dist/entrypoints/httpRouter/http/createLifecycleMiddleware.cjs.js.map +1 -1
  61. package/dist/entrypoints/httpRouter/http/createRateLimitMiddleware.cjs.js.map +1 -1
  62. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
  63. package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -1
  64. package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -1
  65. package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -1
  66. package/dist/entrypoints/permissionsRegistry/permissionsRegistryServiceFactory.cjs.js.map +1 -1
  67. package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -1
  68. package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -1
  69. package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -1
  70. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js +1 -1
  71. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -1
  72. package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -1
  73. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -1
  74. package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -1
  75. package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -1
  76. package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -1
  77. package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -1
  78. package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -1
  79. package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -1
  80. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
  81. package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -1
  82. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -1
  83. package/dist/entrypoints/rootLogger/config.cjs.js.map +1 -1
  84. package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -1
  85. package/dist/entrypoints/rootLogger/types.cjs.js.map +1 -1
  86. package/dist/entrypoints/rootLogger/utils.cjs.js.map +1 -1
  87. package/dist/entrypoints/rootSystemMetadata/lib/DefaultRootSystemMetadataService.cjs.js.map +1 -1
  88. package/dist/entrypoints/rootSystemMetadata/rootSystemMetadataServiceFactory.cjs.js.map +1 -1
  89. package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -1
  90. package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -1
  91. package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -1
  92. package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -1
  93. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -1
  94. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -1
  95. package/dist/entrypoints/scheduler/lib/TaskStatePoller.cjs.js.map +1 -1
  96. package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -1
  97. package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
  98. package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -1
  99. package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -1
  100. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js +22 -7
  101. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -1
  102. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js +22 -7
  103. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -1
  104. package/dist/entrypoints/urlReader/lib/AzureBlobStorageUrlReader.cjs.js.map +1 -1
  105. package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -1
  106. package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -1
  107. package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -1
  108. package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -1
  109. package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -1
  110. package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -1
  111. package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -1
  112. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
  113. package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -1
  114. package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -1
  115. package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -1
  116. package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -1
  117. package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -1
  118. package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -1
  119. package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -1
  120. package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -1
  121. package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -1
  122. package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -1
  123. package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
  124. package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -1
  125. package/dist/entrypoints/userInfo/CachedUserInfoService.cjs.js.map +1 -1
  126. package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -1
  127. package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -1
  128. package/dist/lib/RateLimitStoreFactory.cjs.js.map +1 -1
  129. package/dist/lib/escapeRegExp.cjs.js.map +1 -1
  130. package/dist/lib/rateLimitMiddleware.cjs.js.map +1 -1
  131. package/dist/package.json.cjs.js +1 -1
  132. package/dist/package.json.cjs.js.map +1 -1
  133. package/package.json +16 -15
@@ -1 +1 @@
1
- {"version":3,"file":"ReadUrlResponseFactory.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { ConflictError } from '@backstage/errors';\nimport { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api';\nimport getRawBody from 'raw-body';\nimport { Readable } from 'node:stream';\nimport { ReadUrlResponseFactoryFromStreamOptions } from './types';\nimport { parseLastModified, responseToReadable } from './util';\n\n/**\n * Utility class for UrlReader implementations to create valid ReadUrlResponse\n * instances from common response primitives.\n *\n * @public\n */\nexport class ReadUrlResponseFactory {\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from a Readable stream.\n */\n static async fromReadable(\n stream: Readable,\n options?: ReadUrlResponseFactoryFromStreamOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n // Reference to eventual buffer enables callers to call buffer() multiple\n // times without consequence.\n let buffer: Promise<Buffer>;\n\n // Prevent \"stream is not readable\" errors from bubbling up.\n const conflictError = new ConflictError(\n 'Cannot use buffer() and stream() from the same ReadUrlResponse',\n );\n let hasCalledStream = false;\n let hasCalledBuffer = false;\n\n return {\n buffer: () => {\n hasCalledBuffer = true;\n if (hasCalledStream) throw conflictError;\n if (buffer) return buffer;\n buffer = getRawBody(stream);\n return buffer;\n },\n stream: () => {\n hasCalledStream = true;\n if (hasCalledBuffer) throw conflictError;\n return stream;\n },\n etag: options?.etag,\n lastModifiedAt: options?.lastModifiedAt,\n };\n }\n\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from an old-style NodeJS.ReadableStream.\n */\n static async fromNodeJSReadable(\n oldStyleStream: NodeJS.ReadableStream,\n options?: ReadUrlResponseFactoryFromStreamOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const readable = Readable.from(oldStyleStream);\n return ReadUrlResponseFactory.fromReadable(readable, options);\n }\n\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from a native fetch response body.\n */\n static async fromResponse(\n response: Response,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const etag = response.headers.get('etag') || undefined;\n const lastModifiedAt = parseLastModified(\n response.headers.get('last-modified'),\n );\n\n return ReadUrlResponseFactory.fromReadable(responseToReadable(response), {\n etag,\n lastModifiedAt,\n });\n }\n}\n"],"names":["ConflictError","getRawBody","Readable","parseLastModified","responseToReadable"],"mappings":";;;;;;;;;;;AA6BO,MAAM,sBAAA,CAAuB;AAAA;AAAA;AAAA;AAAA,EAIlC,aAAa,YAAA,CACX,MAAA,EACA,OAAA,EAC0C;AAG1C,IAAA,IAAI,MAAA;AAGJ,IAAA,MAAM,gBAAgB,IAAIA,oBAAA;AAAA,MACxB;AAAA,KACF;AACA,IAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,IAAA,IAAI,eAAA,GAAkB,KAAA;AAEtB,IAAA,OAAO;AAAA,MACL,QAAQ,MAAM;AACZ,QAAA,eAAA,GAAkB,IAAA;AAClB,QAAA,IAAI,iBAAiB,MAAM,aAAA;AAC3B,QAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,QAAA,MAAA,GAASC,4BAAW,MAAM,CAAA;AAC1B,QAAA,OAAO,MAAA;AAAA,MACT,CAAA;AAAA,MACA,QAAQ,MAAM;AACZ,QAAA,eAAA,GAAkB,IAAA;AAClB,QAAA,IAAI,iBAAiB,MAAM,aAAA;AAC3B,QAAA,OAAO,MAAA;AAAA,MACT,CAAA;AAAA,MACA,MAAM,OAAA,EAAS,IAAA;AAAA,MACf,gBAAgB,OAAA,EAAS;AAAA,KAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,kBAAA,CACX,cAAA,EACA,OAAA,EAC0C;AAC1C,IAAA,MAAM,QAAA,GAAWC,oBAAA,CAAS,IAAA,CAAK,cAAc,CAAA;AAC7C,IAAA,OAAO,sBAAA,CAAuB,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,aACX,QAAA,EAC0C;AAC1C,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,IAAK,MAAA;AAC7C,IAAA,MAAM,cAAA,GAAiBC,sBAAA;AAAA,MACrB,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,eAAe;AAAA,KACtC;AAEA,IAAA,OAAO,sBAAA,CAAuB,YAAA,CAAaC,uBAAA,CAAmB,QAAQ,CAAA,EAAG;AAAA,MACvE,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF;;;;"}
1
+ {"version":3,"file":"ReadUrlResponseFactory.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/ReadUrlResponseFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { ConflictError } from '@backstage/errors';\nimport { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api';\nimport getRawBody from 'raw-body';\nimport { Readable } from 'node:stream';\nimport { ReadUrlResponseFactoryFromStreamOptions } from './types';\nimport { parseLastModified, responseToReadable } from './util';\n\n/**\n * Utility class for UrlReader implementations to create valid ReadUrlResponse\n * instances from common response primitives.\n *\n * @public\n */\nexport class ReadUrlResponseFactory {\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from a Readable stream.\n */\n static async fromReadable(\n stream: Readable,\n options?: ReadUrlResponseFactoryFromStreamOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n // Reference to eventual buffer enables callers to call buffer() multiple\n // times without consequence.\n let buffer: Promise<Buffer>;\n\n // Prevent \"stream is not readable\" errors from bubbling up.\n const conflictError = new ConflictError(\n 'Cannot use buffer() and stream() from the same ReadUrlResponse',\n );\n let hasCalledStream = false;\n let hasCalledBuffer = false;\n\n return {\n buffer: () => {\n hasCalledBuffer = true;\n if (hasCalledStream) throw conflictError;\n if (buffer) return buffer;\n buffer = getRawBody(stream);\n return buffer;\n },\n stream: () => {\n hasCalledStream = true;\n if (hasCalledBuffer) throw conflictError;\n return stream;\n },\n etag: options?.etag,\n lastModifiedAt: options?.lastModifiedAt,\n };\n }\n\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from an old-style NodeJS.ReadableStream.\n */\n static async fromNodeJSReadable(\n oldStyleStream: NodeJS.ReadableStream,\n options?: ReadUrlResponseFactoryFromStreamOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const readable = Readable.from(oldStyleStream);\n return ReadUrlResponseFactory.fromReadable(readable, options);\n }\n\n /**\n * Resolves a UrlReaderServiceReadUrlResponse from a native fetch response body.\n */\n static async fromResponse(\n response: Response,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const etag = response.headers.get('etag') || undefined;\n const lastModifiedAt = parseLastModified(\n response.headers.get('last-modified'),\n );\n\n return ReadUrlResponseFactory.fromReadable(responseToReadable(response), {\n etag,\n lastModifiedAt,\n });\n }\n}\n"],"names":["ConflictError","getRawBody","Readable","parseLastModified","responseToReadable"],"mappings":";;;;;;;;;;;AA6BO,MAAM,sBAAA,CAAuB;AAAA;AAAA;AAAA;AAAA,EAIlC,aAAa,YAAA,CACX,MAAA,EACA,OAAA,EAC0C;AAG1C,IAAA,IAAI,MAAA;AAGJ,IAAA,MAAM,gBAAgB,IAAIA,oBAAA;AAAA,MACxB;AAAA,KACF;AACA,IAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,IAAA,IAAI,eAAA,GAAkB,KAAA;AAEtB,IAAA,OAAO;AAAA,MACL,QAAQ,MAAM;AACZ,QAAA,eAAA,GAAkB,IAAA;AAClB,QAAA,IAAI,iBAAiB,MAAM,aAAA;AAC3B,QAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,QAAA,MAAA,GAASC,4BAAW,MAAM,CAAA;AAC1B,QAAA,OAAO,MAAA;AAAA,MACT,CAAA;AAAA,MACA,QAAQ,MAAM;AACZ,QAAA,eAAA,GAAkB,IAAA;AAClB,QAAA,IAAI,iBAAiB,MAAM,aAAA;AAC3B,QAAA,OAAO,MAAA;AAAA,MACT,CAAA;AAAA,MACA,MAAM,OAAA,EAAS,IAAA;AAAA,MACf,gBAAgB,OAAA,EAAS;AAAA,KAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,kBAAA,CACX,cAAA,EACA,OAAA,EAC0C;AAC1C,IAAA,MAAM,QAAA,GAAWC,oBAAA,CAAS,IAAA,CAAK,cAAc,CAAA;AAC7C,IAAA,OAAO,sBAAA,CAAuB,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,aACX,QAAA,EAC0C;AAC1C,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,IAAK,MAAA;AAC7C,IAAA,MAAM,cAAA,GAAiBC,sBAAA;AAAA,MACrB,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,eAAe;AAAA,KACtC;AAEA,IAAA,OAAO,sBAAA,CAAuB,YAAA,CAAaC,uBAAA,CAAmB,QAAQ,CAAA,EAAG;AAAA,MACvE,IAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"UrlReaderPredicateMux.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/UrlReaderPredicateMux.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 UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport { UrlReaderPredicateTuple } from './types';\n\nfunction notAllowedMessage(url: string) {\n return (\n `Reading from '${url}' is not allowed. ` +\n `You may need to configure an integration for the target host, or add it ` +\n `to the configured list of allowed hosts at 'backend.reading.allow'`\n );\n}\n\n/**\n * A UrlReaderService implementation that selects from a set of readers\n * based on a predicate tied to each reader.\n */\nexport class UrlReaderPredicateMux implements UrlReaderService {\n private readonly readers: UrlReaderPredicateTuple[] = [];\n\n register(tuple: UrlReaderPredicateTuple): void {\n this.readers.push(tuple);\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const parsed = new URL(url);\n\n for (const { predicate, reader } of this.readers) {\n if (predicate(parsed)) {\n return reader.readUrl(url, options);\n }\n }\n\n throw new NotAllowedError(notAllowedMessage(url));\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const parsed = new URL(url);\n\n for (const { predicate, reader } of this.readers) {\n if (predicate(parsed)) {\n return await reader.readTree(url, options);\n }\n }\n\n throw new NotAllowedError(notAllowedMessage(url));\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const parsed = new URL(url);\n\n for (const { predicate, reader } of this.readers) {\n if (predicate(parsed)) {\n return await reader.search(url, options);\n }\n }\n\n throw new NotAllowedError(notAllowedMessage(url));\n }\n\n toString() {\n return `predicateMux{readers=${this.readers.map(t => t.reader).join(',')}`;\n }\n}\n"],"names":["NotAllowedError"],"mappings":";;;;AA4BA,SAAS,kBAAkB,GAAA,EAAa;AACtC,EAAA,OACE,iBAAiB,GAAG,CAAA,4JAAA,CAAA;AAIxB;AAMO,MAAM,qBAAA,CAAkD;AAAA,EAC5C,UAAqC,EAAC;AAAA,EAEvD,SAAS,KAAA,EAAsC;AAC7C,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,OAAA,CACJ,GAAA,EACA,OAAA,EAC0C;AAC1C,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAE1B,IAAA,KAAA,MAAW,EAAE,SAAA,EAAW,MAAA,EAAO,IAAK,KAAK,OAAA,EAAS;AAChD,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG;AACrB,QAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,GAAA,EAAK,OAAO,CAAA;AAAA,MACpC;AAAA,IACF;AAEA,IAAA,MAAM,IAAIA,sBAAA,CAAgB,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,QAAA,CACJ,GAAA,EACA,OAAA,EAC2C;AAC3C,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAE1B,IAAA,KAAA,MAAW,EAAE,SAAA,EAAW,MAAA,EAAO,IAAK,KAAK,OAAA,EAAS;AAChD,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG;AACrB,QAAA,OAAO,MAAM,MAAA,CAAO,QAAA,CAAS,GAAA,EAAK,OAAO,CAAA;AAAA,MAC3C;AAAA,IACF;AAEA,IAAA,MAAM,IAAIA,sBAAA,CAAgB,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,MAAA,CACJ,GAAA,EACA,OAAA,EACyC;AACzC,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAE1B,IAAA,KAAA,MAAW,EAAE,SAAA,EAAW,MAAA,EAAO,IAAK,KAAK,OAAA,EAAS;AAChD,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG;AACrB,QAAA,OAAO,MAAM,MAAA,CAAO,MAAA,CAAO,GAAA,EAAK,OAAO,CAAA;AAAA,MACzC;AAAA,IACF;AAEA,IAAA,MAAM,IAAIA,sBAAA,CAAgB,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,qBAAA,EAAwB,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,MAAM,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,EAC1E;AACF;;;;"}
1
+ {"version":3,"file":"UrlReaderPredicateMux.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/UrlReaderPredicateMux.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 UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport { UrlReaderPredicateTuple } from './types';\n\nfunction notAllowedMessage(url: string) {\n return (\n `Reading from '${url}' is not allowed. ` +\n `You may need to configure an integration for the target host, or add it ` +\n `to the configured list of allowed hosts at 'backend.reading.allow'`\n );\n}\n\n/**\n * A UrlReaderService implementation that selects from a set of readers\n * based on a predicate tied to each reader.\n */\nexport class UrlReaderPredicateMux implements UrlReaderService {\n private readonly readers: UrlReaderPredicateTuple[] = [];\n\n register(tuple: UrlReaderPredicateTuple): void {\n this.readers.push(tuple);\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const parsed = new URL(url);\n\n for (const { predicate, reader } of this.readers) {\n if (predicate(parsed)) {\n return reader.readUrl(url, options);\n }\n }\n\n throw new NotAllowedError(notAllowedMessage(url));\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const parsed = new URL(url);\n\n for (const { predicate, reader } of this.readers) {\n if (predicate(parsed)) {\n return await reader.readTree(url, options);\n }\n }\n\n throw new NotAllowedError(notAllowedMessage(url));\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const parsed = new URL(url);\n\n for (const { predicate, reader } of this.readers) {\n if (predicate(parsed)) {\n return await reader.search(url, options);\n }\n }\n\n throw new NotAllowedError(notAllowedMessage(url));\n }\n\n toString() {\n return `predicateMux{readers=${this.readers.map(t => t.reader).join(',')}`;\n }\n}\n"],"names":["NotAllowedError"],"mappings":";;;;AA4BA,SAAS,kBAAkB,GAAA,EAAa;AACtC,EAAA,OACE,iBAAiB,GAAG,CAAA,4JAAA,CAAA;AAIxB;AAMO,MAAM,qBAAA,CAAkD;AAAA,EAC5C,UAAqC,EAAC;AAAA,EAEvD,SAAS,KAAA,EAAsC;AAC7C,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,OAAA,CACJ,GAAA,EACA,OAAA,EAC0C;AAC1C,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAE1B,IAAA,KAAA,MAAW,EAAE,SAAA,EAAW,MAAA,EAAO,IAAK,KAAK,OAAA,EAAS;AAChD,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG;AACrB,QAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,GAAA,EAAK,OAAO,CAAA;AAAA,MACpC;AAAA,IACF;AAEA,IAAA,MAAM,IAAIA,sBAAA,CAAgB,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,QAAA,CACJ,GAAA,EACA,OAAA,EAC2C;AAC3C,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAE1B,IAAA,KAAA,MAAW,EAAE,SAAA,EAAW,MAAA,EAAO,IAAK,KAAK,OAAA,EAAS;AAChD,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG;AACrB,QAAA,OAAO,MAAM,MAAA,CAAO,QAAA,CAAS,GAAA,EAAK,OAAO,CAAA;AAAA,MAC3C;AAAA,IACF;AAEA,IAAA,MAAM,IAAIA,sBAAA,CAAgB,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,MAAM,MAAA,CACJ,GAAA,EACA,OAAA,EACyC;AACzC,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAE1B,IAAA,KAAA,MAAW,EAAE,SAAA,EAAW,MAAA,EAAO,IAAK,KAAK,OAAA,EAAS;AAChD,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG;AACrB,QAAA,OAAO,MAAM,MAAA,CAAO,MAAA,CAAO,GAAA,EAAK,OAAO,CAAA;AAAA,MACzC;AAAA,IACF;AAEA,IAAA,MAAM,IAAIA,sBAAA,CAAgB,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,EAClD;AAAA,EAEA,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,qBAAA,EAAwB,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,MAAM,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,EAC1E;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"UrlReaders.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/UrlReaders.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 RootConfigService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory } from './types';\nimport { UrlReaderPredicateMux } from './UrlReaderPredicateMux';\nimport { AzureUrlReader } from './AzureUrlReader';\nimport { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader';\nimport { BitbucketServerUrlReader } from './BitbucketServerUrlReader';\nimport { GerritUrlReader } from './GerritUrlReader';\nimport { GithubUrlReader } from './GithubUrlReader';\nimport { GitlabUrlReader } from './GitlabUrlReader';\nimport { DefaultReadTreeResponseFactory } from './tree';\nimport { FetchUrlReader } from './FetchUrlReader';\nimport { GoogleGcsUrlReader } from './GoogleGcsUrlReader';\nimport { AwsS3UrlReader } from './AwsS3UrlReader';\nimport { GiteaUrlReader } from './GiteaUrlReader';\nimport { AwsCodeCommitUrlReader } from './AwsCodeCommitUrlReader';\nimport { HarnessUrlReader } from './HarnessUrlReader';\nimport { AzureBlobStorageUrlReader } from './AzureBlobStorageUrlReader';\n\n/**\n * Creation options for {@link @backstage/backend-plugin-api#UrlReaderService}.\n *\n * @public\n */\nexport type UrlReadersOptions = {\n /** Root config object */\n config: RootConfigService;\n /** Logger used by all the readers */\n logger: LoggerService;\n /** A list of factories used to construct individual readers that match on URLs */\n factories?: ReaderFactory[];\n};\n\n/**\n * Helps construct {@link @backstage/backend-plugin-api#UrlReaderService}s.\n *\n * @public\n */\nexport class UrlReaders {\n /**\n * Creates a custom {@link @backstage/backend-plugin-api#UrlReaderService} wrapper for your own set of factories.\n */\n static create(options: UrlReadersOptions): UrlReaderService {\n const { logger, config, factories } = options;\n const mux = new UrlReaderPredicateMux();\n const treeResponseFactory = DefaultReadTreeResponseFactory.create({\n config,\n });\n for (const factory of factories ?? []) {\n const tuples = factory({ config, logger: logger, treeResponseFactory });\n\n for (const tuple of tuples) {\n mux.register(tuple);\n }\n }\n\n return mux;\n }\n\n /**\n * Creates a {@link @backstage/backend-plugin-api#UrlReaderService} wrapper that includes all the default factories\n * from this package.\n *\n * Any additional factories passed will be loaded before the default ones.\n */\n static default(options: UrlReadersOptions) {\n const { logger, config, factories = [] } = options;\n return UrlReaders.create({\n logger,\n config,\n factories: factories.concat([\n AzureUrlReader.factory,\n BitbucketCloudUrlReader.factory,\n BitbucketServerUrlReader.factory,\n GerritUrlReader.factory,\n GithubUrlReader.factory,\n GiteaUrlReader.factory,\n GitlabUrlReader.factory,\n GoogleGcsUrlReader.factory,\n HarnessUrlReader.factory,\n AwsS3UrlReader.factory,\n AzureBlobStorageUrlReader.factory,\n AwsCodeCommitUrlReader.factory,\n FetchUrlReader.factory,\n ]),\n });\n }\n}\n"],"names":["UrlReaderPredicateMux","DefaultReadTreeResponseFactory","AzureUrlReader","BitbucketCloudUrlReader","BitbucketServerUrlReader","GerritUrlReader","GithubUrlReader","GiteaUrlReader","GitlabUrlReader","GoogleGcsUrlReader","HarnessUrlReader","AwsS3UrlReader","AzureBlobStorageUrlReader","AwsCodeCommitUrlReader","FetchUrlReader"],"mappings":";;;;;;;;;;;;;;;;;;AAyDO,MAAM,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA,EAItB,OAAO,OAAO,OAAA,EAA8C;AAC1D,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAA,EAAU,GAAI,OAAA;AACtC,IAAA,MAAM,GAAA,GAAM,IAAIA,2CAAA,EAAsB;AACtC,IAAA,MAAM,mBAAA,GAAsBC,uDAA+B,MAAA,CAAO;AAAA,MAChE;AAAA,KACD,CAAA;AACD,IAAA,KAAA,MAAW,OAAA,IAAW,SAAA,IAAa,EAAC,EAAG;AACrC,MAAA,MAAM,SAAS,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAgB,qBAAqB,CAAA;AAEtE,MAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,QAAA,GAAA,CAAI,SAAS,KAAK,CAAA;AAAA,MACpB;AAAA,IACF;AAEA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,QAAQ,OAAA,EAA4B;AACzC,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAA,GAAY,IAAG,GAAI,OAAA;AAC3C,IAAA,OAAO,WAAW,MAAA,CAAO;AAAA,MACvB,MAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA,EAAW,UAAU,MAAA,CAAO;AAAA,QAC1BC,6BAAA,CAAe,OAAA;AAAA,QACfC,+CAAA,CAAwB,OAAA;AAAA,QACxBC,iDAAA,CAAyB,OAAA;AAAA,QACzBC,+BAAA,CAAgB,OAAA;AAAA,QAChBC,+BAAA,CAAgB,OAAA;AAAA,QAChBC,6BAAA,CAAe,OAAA;AAAA,QACfC,+BAAA,CAAgB,OAAA;AAAA,QAChBC,qCAAA,CAAmB,OAAA;AAAA,QACnBC,iCAAA,CAAiB,OAAA;AAAA,QACjBC,6BAAA,CAAe,OAAA;AAAA,QACfC,mDAAA,CAA0B,OAAA;AAAA,QAC1BC,6CAAA,CAAuB,OAAA;AAAA,QACvBC,6BAAA,CAAe;AAAA,OAChB;AAAA,KACF,CAAA;AAAA,EACH;AACF;;;;"}
1
+ {"version":3,"file":"UrlReaders.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/UrlReaders.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 RootConfigService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory } from './types';\nimport { UrlReaderPredicateMux } from './UrlReaderPredicateMux';\nimport { AzureUrlReader } from './AzureUrlReader';\nimport { BitbucketCloudUrlReader } from './BitbucketCloudUrlReader';\nimport { BitbucketServerUrlReader } from './BitbucketServerUrlReader';\nimport { GerritUrlReader } from './GerritUrlReader';\nimport { GithubUrlReader } from './GithubUrlReader';\nimport { GitlabUrlReader } from './GitlabUrlReader';\nimport { DefaultReadTreeResponseFactory } from './tree';\nimport { FetchUrlReader } from './FetchUrlReader';\nimport { GoogleGcsUrlReader } from './GoogleGcsUrlReader';\nimport { AwsS3UrlReader } from './AwsS3UrlReader';\nimport { GiteaUrlReader } from './GiteaUrlReader';\nimport { AwsCodeCommitUrlReader } from './AwsCodeCommitUrlReader';\nimport { HarnessUrlReader } from './HarnessUrlReader';\nimport { AzureBlobStorageUrlReader } from './AzureBlobStorageUrlReader';\n\n/**\n * Creation options for {@link @backstage/backend-plugin-api#UrlReaderService}.\n *\n * @public\n */\nexport type UrlReadersOptions = {\n /** Root config object */\n config: RootConfigService;\n /** Logger used by all the readers */\n logger: LoggerService;\n /** A list of factories used to construct individual readers that match on URLs */\n factories?: ReaderFactory[];\n};\n\n/**\n * Helps construct {@link @backstage/backend-plugin-api#UrlReaderService}s.\n *\n * @public\n */\nexport class UrlReaders {\n /**\n * Creates a custom {@link @backstage/backend-plugin-api#UrlReaderService} wrapper for your own set of factories.\n */\n static create(options: UrlReadersOptions): UrlReaderService {\n const { logger, config, factories } = options;\n const mux = new UrlReaderPredicateMux();\n const treeResponseFactory = DefaultReadTreeResponseFactory.create({\n config,\n });\n for (const factory of factories ?? []) {\n const tuples = factory({ config, logger: logger, treeResponseFactory });\n\n for (const tuple of tuples) {\n mux.register(tuple);\n }\n }\n\n return mux;\n }\n\n /**\n * Creates a {@link @backstage/backend-plugin-api#UrlReaderService} wrapper that includes all the default factories\n * from this package.\n *\n * Any additional factories passed will be loaded before the default ones.\n */\n static default(options: UrlReadersOptions) {\n const { logger, config, factories = [] } = options;\n return UrlReaders.create({\n logger,\n config,\n factories: factories.concat([\n AzureUrlReader.factory,\n BitbucketCloudUrlReader.factory,\n BitbucketServerUrlReader.factory,\n GerritUrlReader.factory,\n GithubUrlReader.factory,\n GiteaUrlReader.factory,\n GitlabUrlReader.factory,\n GoogleGcsUrlReader.factory,\n HarnessUrlReader.factory,\n AwsS3UrlReader.factory,\n AzureBlobStorageUrlReader.factory,\n AwsCodeCommitUrlReader.factory,\n FetchUrlReader.factory,\n ]),\n });\n }\n}\n"],"names":["UrlReaderPredicateMux","DefaultReadTreeResponseFactory","AzureUrlReader","BitbucketCloudUrlReader","BitbucketServerUrlReader","GerritUrlReader","GithubUrlReader","GiteaUrlReader","GitlabUrlReader","GoogleGcsUrlReader","HarnessUrlReader","AwsS3UrlReader","AzureBlobStorageUrlReader","AwsCodeCommitUrlReader","FetchUrlReader"],"mappings":";;;;;;;;;;;;;;;;;;AAyDO,MAAM,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA,EAItB,OAAO,OAAO,OAAA,EAA8C;AAC1D,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAA,EAAU,GAAI,OAAA;AACtC,IAAA,MAAM,GAAA,GAAM,IAAIA,2CAAA,EAAsB;AACtC,IAAA,MAAM,mBAAA,GAAsBC,uDAA+B,MAAA,CAAO;AAAA,MAChE;AAAA,KACD,CAAA;AACD,IAAA,KAAA,MAAW,OAAA,IAAW,SAAA,IAAa,EAAC,EAAG;AACrC,MAAA,MAAM,SAAS,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAgB,qBAAqB,CAAA;AAEtE,MAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,QAAA,GAAA,CAAI,SAAS,KAAK,CAAA;AAAA,MACpB;AAAA,IACF;AAEA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,QAAQ,OAAA,EAA4B;AACzC,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAA,GAAY,IAAG,GAAI,OAAA;AAC3C,IAAA,OAAO,WAAW,MAAA,CAAO;AAAA,MACvB,MAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA,EAAW,UAAU,MAAA,CAAO;AAAA,QAC1BC,6BAAA,CAAe,OAAA;AAAA,QACfC,+CAAA,CAAwB,OAAA;AAAA,QACxBC,iDAAA,CAAyB,OAAA;AAAA,QACzBC,+BAAA,CAAgB,OAAA;AAAA,QAChBC,+BAAA,CAAgB,OAAA;AAAA,QAChBC,6BAAA,CAAe,OAAA;AAAA,QACfC,+BAAA,CAAgB,OAAA;AAAA,QAChBC,qCAAA,CAAmB,OAAA;AAAA,QACnBC,iCAAA,CAAiB,OAAA;AAAA,QACjBC,6BAAA,CAAe,OAAA;AAAA,QACfC,mDAAA,CAA0B,OAAA;AAAA,QAC1BC,6CAAA,CAAuB,OAAA;AAAA,QACvBC,6BAAA,CAAe;AAAA,OAChB;AAAA,KACF,CAAA;AAAA,EACH;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReadTreeResponseFactory.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.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 os from 'node:os';\nimport { Readable } from 'node:stream';\nimport { Config } from '@backstage/config';\nimport {\n ReadTreeResponseFactoryOptions,\n ReadTreeResponseFactory,\n FromReadableArrayOptions,\n} from '../types';\nimport { TarArchiveResponse } from './TarArchiveResponse';\nimport { ZipArchiveResponse } from './ZipArchiveResponse';\nimport { ReadableArrayResponse } from './ReadableArrayResponse';\nimport { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api';\nimport { responseToReadable } from '../util';\n\nexport class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {\n static create(options: { config: Config }): DefaultReadTreeResponseFactory {\n return new DefaultReadTreeResponseFactory(\n options.config.getOptionalString('backend.workingDirectory') ??\n os.tmpdir(),\n );\n }\n\n private readonly workDir: string;\n\n constructor(workDir: string) {\n this.workDir = workDir;\n }\n\n async fromTarArchive(\n options: ReadTreeResponseFactoryOptions & {\n stripFirstDirectory?: boolean;\n },\n ): Promise<UrlReaderServiceReadTreeResponse> {\n let stream: Readable;\n let etag: string;\n if ('stream' in options) {\n stream = options.stream;\n etag = options.etag;\n } else {\n stream = responseToReadable(options.response);\n etag = (options.etag ?? options.response.headers.get('etag')) || '';\n }\n\n return new TarArchiveResponse(\n stream,\n options.subpath ?? '',\n this.workDir,\n etag,\n options.filter,\n options.stripFirstDirectory ?? true,\n );\n }\n\n async fromZipArchive(\n options: ReadTreeResponseFactoryOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n let stream: Readable;\n let etag: string;\n if ('stream' in options) {\n stream = options.stream;\n etag = options.etag;\n } else {\n stream = responseToReadable(options.response);\n etag = (options.etag ?? options.response.headers.get('etag')) || '';\n }\n\n return new ZipArchiveResponse(\n stream,\n options.subpath ?? '',\n this.workDir,\n etag,\n options.filter,\n );\n }\n\n async fromReadableArray(\n options: FromReadableArrayOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n return new ReadableArrayResponse(options, this.workDir, '');\n }\n}\n"],"names":["os","responseToReadable","TarArchiveResponse","ZipArchiveResponse","ReadableArrayResponse"],"mappings":";;;;;;;;;;;;AA8BO,MAAM,8BAAA,CAAkE;AAAA,EAC7E,OAAO,OAAO,OAAA,EAA6D;AACzE,IAAA,OAAO,IAAI,8BAAA;AAAA,MACT,QAAQ,MAAA,CAAO,iBAAA,CAAkB,0BAA0B,CAAA,IACzDA,oBAAG,MAAA;AAAO,KACd;AAAA,EACF;AAAA,EAEiB,OAAA;AAAA,EAEjB,YAAY,OAAA,EAAiB;AAC3B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,MAAM,eACJ,OAAA,EAG2C;AAC3C,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,YAAY,OAAA,EAAS;AACvB,MAAA,MAAA,GAAS,OAAA,CAAQ,MAAA;AACjB,MAAA,IAAA,GAAO,OAAA,CAAQ,IAAA;AAAA,IACjB,CAAA,MAAO;AACL,MAAA,MAAA,GAASC,uBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAC5C,MAAA,IAAA,GAAA,CAAQ,QAAQ,IAAA,IAAQ,OAAA,CAAQ,SAAS,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,KAAM,EAAA;AAAA,IACnE;AAEA,IAAA,OAAO,IAAIC,qCAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,OAAA,IAAW,EAAA;AAAA,MACnB,IAAA,CAAK,OAAA;AAAA,MACL,IAAA;AAAA,MACA,OAAA,CAAQ,MAAA;AAAA,MACR,QAAQ,mBAAA,IAAuB;AAAA,KACjC;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,OAAA,EAC2C;AAC3C,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,YAAY,OAAA,EAAS;AACvB,MAAA,MAAA,GAAS,OAAA,CAAQ,MAAA;AACjB,MAAA,IAAA,GAAO,OAAA,CAAQ,IAAA;AAAA,IACjB,CAAA,MAAO;AACL,MAAA,MAAA,GAASD,uBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAC5C,MAAA,IAAA,GAAA,CAAQ,QAAQ,IAAA,IAAQ,OAAA,CAAQ,SAAS,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,KAAM,EAAA;AAAA,IACnE;AAEA,IAAA,OAAO,IAAIE,qCAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,OAAA,IAAW,EAAA;AAAA,MACnB,IAAA,CAAK,OAAA;AAAA,MACL,IAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AAAA,EACF;AAAA,EAEA,MAAM,kBACJ,OAAA,EAC2C;AAC3C,IAAA,OAAO,IAAIC,2CAAA,CAAsB,OAAA,EAAS,IAAA,CAAK,SAAS,EAAE,CAAA;AAAA,EAC5D;AACF;;;;"}
1
+ {"version":3,"file":"ReadTreeResponseFactory.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.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 os from 'node:os';\nimport { Readable } from 'node:stream';\nimport { Config } from '@backstage/config';\nimport {\n ReadTreeResponseFactoryOptions,\n ReadTreeResponseFactory,\n FromReadableArrayOptions,\n} from '../types';\nimport { TarArchiveResponse } from './TarArchiveResponse';\nimport { ZipArchiveResponse } from './ZipArchiveResponse';\nimport { ReadableArrayResponse } from './ReadableArrayResponse';\nimport { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api';\nimport { responseToReadable } from '../util';\n\nexport class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {\n static create(options: { config: Config }): DefaultReadTreeResponseFactory {\n return new DefaultReadTreeResponseFactory(\n options.config.getOptionalString('backend.workingDirectory') ??\n os.tmpdir(),\n );\n }\n\n private readonly workDir: string;\n\n constructor(workDir: string) {\n this.workDir = workDir;\n }\n\n async fromTarArchive(\n options: ReadTreeResponseFactoryOptions & {\n stripFirstDirectory?: boolean;\n },\n ): Promise<UrlReaderServiceReadTreeResponse> {\n let stream: Readable;\n let etag: string;\n if ('stream' in options) {\n stream = options.stream;\n etag = options.etag;\n } else {\n stream = responseToReadable(options.response);\n etag = (options.etag ?? options.response.headers.get('etag')) || '';\n }\n\n return new TarArchiveResponse(\n stream,\n options.subpath ?? '',\n this.workDir,\n etag,\n options.filter,\n options.stripFirstDirectory ?? true,\n );\n }\n\n async fromZipArchive(\n options: ReadTreeResponseFactoryOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n let stream: Readable;\n let etag: string;\n if ('stream' in options) {\n stream = options.stream;\n etag = options.etag;\n } else {\n stream = responseToReadable(options.response);\n etag = (options.etag ?? options.response.headers.get('etag')) || '';\n }\n\n return new ZipArchiveResponse(\n stream,\n options.subpath ?? '',\n this.workDir,\n etag,\n options.filter,\n );\n }\n\n async fromReadableArray(\n options: FromReadableArrayOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n return new ReadableArrayResponse(options, this.workDir, '');\n }\n}\n"],"names":["os","responseToReadable","TarArchiveResponse","ZipArchiveResponse","ReadableArrayResponse"],"mappings":";;;;;;;;;;;;AA8BO,MAAM,8BAAA,CAAkE;AAAA,EAC7E,OAAO,OAAO,OAAA,EAA6D;AACzE,IAAA,OAAO,IAAI,8BAAA;AAAA,MACT,QAAQ,MAAA,CAAO,iBAAA,CAAkB,0BAA0B,CAAA,IACzDA,oBAAG,MAAA;AAAO,KACd;AAAA,EACF;AAAA,EAEiB,OAAA;AAAA,EAEjB,YAAY,OAAA,EAAiB;AAC3B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,MAAM,eACJ,OAAA,EAG2C;AAC3C,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,YAAY,OAAA,EAAS;AACvB,MAAA,MAAA,GAAS,OAAA,CAAQ,MAAA;AACjB,MAAA,IAAA,GAAO,OAAA,CAAQ,IAAA;AAAA,IACjB,CAAA,MAAO;AACL,MAAA,MAAA,GAASC,uBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAC5C,MAAA,IAAA,GAAA,CAAQ,QAAQ,IAAA,IAAQ,OAAA,CAAQ,SAAS,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,KAAM,EAAA;AAAA,IACnE;AAEA,IAAA,OAAO,IAAIC,qCAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,OAAA,IAAW,EAAA;AAAA,MACnB,IAAA,CAAK,OAAA;AAAA,MACL,IAAA;AAAA,MACA,OAAA,CAAQ,MAAA;AAAA,MACR,QAAQ,mBAAA,IAAuB;AAAA,KACjC;AAAA,EACF;AAAA,EAEA,MAAM,eACJ,OAAA,EAC2C;AAC3C,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,YAAY,OAAA,EAAS;AACvB,MAAA,MAAA,GAAS,OAAA,CAAQ,MAAA;AACjB,MAAA,IAAA,GAAO,OAAA,CAAQ,IAAA;AAAA,IACjB,CAAA,MAAO;AACL,MAAA,MAAA,GAASD,uBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAC5C,MAAA,IAAA,GAAA,CAAQ,QAAQ,IAAA,IAAQ,OAAA,CAAQ,SAAS,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,KAAM,EAAA;AAAA,IACnE;AAEA,IAAA,OAAO,IAAIE,qCAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,OAAA,IAAW,EAAA;AAAA,MACnB,IAAA,CAAK,OAAA;AAAA,MACL,IAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AAAA,EACF;AAAA,EAEA,MAAM,kBACJ,OAAA,EAC2C;AAC3C,IAAA,OAAO,IAAIC,2CAAA,CAAsB,OAAA,EAAS,IAAA,CAAK,SAAS,EAAE,CAAA;AAAA,EAC5D;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReadableArrayResponse.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.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 resolveSafeChildPath,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadTreeResponseDirOptions,\n UrlReaderServiceReadTreeResponseFile,\n} from '@backstage/backend-plugin-api';\nimport concatStream from 'concat-stream';\nimport platformPath, { dirname } from 'node:path';\nimport getRawBody from 'raw-body';\nimport fs from 'fs-extra';\nimport { promisify } from 'node:util';\nimport * as tar from 'tar';\nimport { pipeline as pipelineCb, Readable } from 'node:stream';\nimport { FromReadableArrayOptions } from '../types';\n\nconst pipeline = promisify(pipelineCb);\n\n/**\n * Wraps a array of Readable objects into a tree response reader.\n */\nexport class ReadableArrayResponse implements UrlReaderServiceReadTreeResponse {\n private read = false;\n private readonly stream: FromReadableArrayOptions;\n private readonly workDir: string;\n public readonly etag: string;\n\n constructor(stream: FromReadableArrayOptions, workDir: string, etag: string) {\n this.stream = stream;\n this.workDir = workDir;\n this.etag = etag;\n }\n\n // Make sure the input stream is only read once\n private onlyOnce() {\n if (this.read) {\n throw new Error('Response has already been read');\n }\n this.read = true;\n }\n\n async files(): Promise<UrlReaderServiceReadTreeResponseFile[]> {\n this.onlyOnce();\n\n const files = Array<UrlReaderServiceReadTreeResponseFile>();\n\n for (let i = 0; i < this.stream.length; i++) {\n if (!this.stream[i].path.endsWith('/')) {\n files.push({\n path: this.stream[i].path,\n content: () => getRawBody(this.stream[i].data),\n lastModifiedAt: this.stream[i]?.lastModifiedAt,\n });\n }\n }\n\n return files;\n }\n\n async archive(): Promise<NodeJS.ReadableStream> {\n const tmpDir = await this.dir();\n\n try {\n const data = await new Promise<Buffer>(async resolve => {\n await pipeline(\n tar.create({ cwd: tmpDir }, ['']),\n concatStream(resolve),\n );\n });\n return Readable.from(data);\n } finally {\n await fs.remove(tmpDir);\n }\n }\n\n async dir(\n options?: UrlReaderServiceReadTreeResponseDirOptions,\n ): Promise<string> {\n this.onlyOnce();\n\n const dir =\n options?.targetDir ??\n (await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));\n\n for (let i = 0; i < this.stream.length; i++) {\n if (!this.stream[i].path.endsWith('/')) {\n const filePath = resolveSafeChildPath(dir, this.stream[i].path);\n await fs.mkdir(dirname(filePath), { recursive: true });\n await pipeline(this.stream[i].data, fs.createWriteStream(filePath));\n }\n }\n\n return dir;\n }\n}\n"],"names":["promisify","pipelineCb","getRawBody","tar","concatStream","Readable","fs","platformPath","resolveSafeChildPath","dirname"],"mappings":"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"}
1
+ {"version":3,"file":"ReadableArrayResponse.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ReadableArrayResponse.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 resolveSafeChildPath,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadTreeResponseDirOptions,\n UrlReaderServiceReadTreeResponseFile,\n} from '@backstage/backend-plugin-api';\nimport concatStream from 'concat-stream';\nimport platformPath, { dirname } from 'node:path';\nimport getRawBody from 'raw-body';\nimport fs from 'fs-extra';\nimport { promisify } from 'node:util';\nimport * as tar from 'tar';\nimport { pipeline as pipelineCb, Readable } from 'node:stream';\nimport { FromReadableArrayOptions } from '../types';\n\nconst pipeline = promisify(pipelineCb);\n\n/**\n * Wraps a array of Readable objects into a tree response reader.\n */\nexport class ReadableArrayResponse implements UrlReaderServiceReadTreeResponse {\n private read = false;\n private readonly stream: FromReadableArrayOptions;\n private readonly workDir: string;\n public readonly etag: string;\n\n constructor(stream: FromReadableArrayOptions, workDir: string, etag: string) {\n this.stream = stream;\n this.workDir = workDir;\n this.etag = etag;\n }\n\n // Make sure the input stream is only read once\n private onlyOnce() {\n if (this.read) {\n throw new Error('Response has already been read');\n }\n this.read = true;\n }\n\n async files(): Promise<UrlReaderServiceReadTreeResponseFile[]> {\n this.onlyOnce();\n\n const files = Array<UrlReaderServiceReadTreeResponseFile>();\n\n for (let i = 0; i < this.stream.length; i++) {\n if (!this.stream[i].path.endsWith('/')) {\n files.push({\n path: this.stream[i].path,\n content: () => getRawBody(this.stream[i].data),\n lastModifiedAt: this.stream[i]?.lastModifiedAt,\n });\n }\n }\n\n return files;\n }\n\n async archive(): Promise<NodeJS.ReadableStream> {\n const tmpDir = await this.dir();\n\n try {\n const data = await new Promise<Buffer>(async resolve => {\n await pipeline(\n tar.create({ cwd: tmpDir }, ['']),\n concatStream(resolve),\n );\n });\n return Readable.from(data);\n } finally {\n await fs.remove(tmpDir);\n }\n }\n\n async dir(\n options?: UrlReaderServiceReadTreeResponseDirOptions,\n ): Promise<string> {\n this.onlyOnce();\n\n const dir =\n options?.targetDir ??\n (await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));\n\n for (let i = 0; i < this.stream.length; i++) {\n if (!this.stream[i].path.endsWith('/')) {\n const filePath = resolveSafeChildPath(dir, this.stream[i].path);\n await fs.mkdir(dirname(filePath), { recursive: true });\n await pipeline(this.stream[i].data, fs.createWriteStream(filePath));\n }\n }\n\n return dir;\n }\n}\n"],"names":["promisify","pipelineCb","getRawBody","tar","concatStream","Readable","fs","platformPath","resolveSafeChildPath","dirname"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAM,QAAA,GAAWA,oBAAUC,oBAAU,CAAA;AAK9B,MAAM,qBAAA,CAAkE;AAAA,EACrE,IAAA,GAAO,KAAA;AAAA,EACE,MAAA;AAAA,EACA,OAAA;AAAA,EACD,IAAA;AAAA,EAEhB,WAAA,CAAY,MAAA,EAAkC,OAAA,EAAiB,IAAA,EAAc;AAC3E,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA,EAGQ,QAAA,GAAW;AACjB,IAAA,IAAI,KAAK,IAAA,EAAM;AACb,MAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,IAClD;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA,EAEA,MAAM,KAAA,GAAyD;AAC7D,IAAA,IAAA,CAAK,QAAA,EAAS;AAEd,IAAA,MAAM,QAAQ,KAAA,EAA4C;AAE1D,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AAC3C,MAAA,IAAI,CAAC,KAAK,MAAA,CAAO,CAAC,EAAE,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AACtC,QAAA,KAAA,CAAM,IAAA,CAAK;AAAA,UACT,IAAA,EAAM,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,IAAA;AAAA,UACrB,SAAS,MAAMC,2BAAA,CAAW,KAAK,MAAA,CAAO,CAAC,EAAE,IAAI,CAAA;AAAA,UAC7C,cAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAG;AAAA,SACjC,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAA,GAA0C;AAC9C,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA,EAAI;AAE9B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,IAAI,OAAA,CAAgB,OAAM,OAAA,KAAW;AACtD,QAAA,MAAM,QAAA;AAAA,UACJC,cAAA,CAAI,OAAO,EAAE,GAAA,EAAK,QAAO,EAAG,CAAC,EAAE,CAAC,CAAA;AAAA,UAChCC,8BAAa,OAAO;AAAA,SACtB;AAAA,MACF,CAAC,CAAA;AACD,MAAA,OAAOC,oBAAA,CAAS,KAAK,IAAI,CAAA;AAAA,IAC3B,CAAA,SAAE;AACA,MAAA,MAAMC,mBAAA,CAAG,OAAO,MAAM,CAAA;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAM,IACJ,OAAA,EACiB;AACjB,IAAA,IAAA,CAAK,QAAA,EAAS;AAEd,IAAA,MAAM,GAAA,GACJ,OAAA,EAAS,SAAA,IACR,MAAMA,mBAAA,CAAG,OAAA,CAAQC,6BAAA,CAAa,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,YAAY,CAAC,CAAA;AAEjE,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AAC3C,MAAA,IAAI,CAAC,KAAK,MAAA,CAAO,CAAC,EAAE,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AACtC,QAAA,MAAM,WAAWC,qCAAA,CAAqB,GAAA,EAAK,KAAK,MAAA,CAAO,CAAC,EAAE,IAAI,CAAA;AAC9D,QAAA,MAAMF,mBAAA,CAAG,MAAMG,oBAAA,CAAQ,QAAQ,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACrD,QAAA,MAAM,QAAA,CAAS,KAAK,MAAA,CAAO,CAAC,EAAE,IAAA,EAAMH,mBAAA,CAAG,iBAAA,CAAkB,QAAQ,CAAC,CAAA;AAAA,MACpE;AAAA,IACF;AAEA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"TarArchiveResponse.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/TarArchiveResponse.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 isChildPath,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadTreeResponseDirOptions,\n UrlReaderServiceReadTreeResponseFile,\n} from '@backstage/backend-plugin-api';\nimport concatStream from 'concat-stream';\nimport fs from 'fs-extra';\nimport platformPath from 'node:path';\nimport { pipeline as pipelineCb, Readable } from 'node:stream';\nimport * as tar from 'tar';\nimport type { ReadEntry } from 'tar';\nimport { promisify } from 'node:util';\nimport { stripFirstDirectoryFromPath } from './util';\n\nconst pipeline = promisify(pipelineCb);\n\n/**\n * Wraps a tar archive stream into a tree response reader.\n */\nexport class TarArchiveResponse implements UrlReaderServiceReadTreeResponse {\n private read = false;\n private readonly stream: Readable;\n private readonly subPath: string;\n private readonly workDir: string;\n public readonly etag: string;\n private readonly filter?: (path: string, info: { size: number }) => boolean;\n private readonly stripFirstDirectory: boolean;\n\n constructor(\n stream: Readable,\n subPath: string,\n workDir: string,\n etag: string,\n filter?: (path: string, info: { size: number }) => boolean,\n stripFirstDirectory: boolean = true,\n ) {\n this.stream = stream;\n this.subPath = subPath;\n this.workDir = workDir;\n this.etag = etag;\n this.filter = filter;\n this.stripFirstDirectory = stripFirstDirectory;\n if (subPath) {\n if (!subPath.endsWith('/')) {\n this.subPath += '/';\n }\n if (subPath.startsWith('/')) {\n throw new TypeError(\n `TarArchiveResponse subPath must not start with a /, got '${subPath}'`,\n );\n }\n }\n\n this.etag = etag;\n }\n\n // Make sure the input stream is only read once\n private onlyOnce() {\n if (this.read) {\n throw new Error('Response has already been read');\n }\n this.read = true;\n }\n\n async files(): Promise<UrlReaderServiceReadTreeResponseFile[]> {\n this.onlyOnce();\n\n const files = Array<UrlReaderServiceReadTreeResponseFile>();\n const parser = new tar.Parser();\n\n parser.on('entry', (entry: ReadEntry & Readable) => {\n if (entry.type === 'Directory') {\n entry.resume();\n return;\n }\n\n // File path relative to the root extracted directory. Will remove the\n // top level dir name from the path since its name is hard to predetermine.\n const relativePath = this.stripFirstDirectory\n ? stripFirstDirectoryFromPath(entry.path)\n : entry.path;\n\n if (this.subPath) {\n if (!relativePath.startsWith(this.subPath)) {\n entry.resume();\n return;\n }\n }\n\n const path = relativePath.slice(this.subPath.length);\n if (this.filter) {\n if (!this.filter(path, { size: entry.remain })) {\n entry.resume();\n return;\n }\n }\n\n const content = new Promise<Buffer>(async resolve => {\n await pipeline(entry, concatStream(resolve));\n });\n\n files.push({\n path,\n content: () => content,\n });\n\n entry.resume();\n });\n\n await pipeline(this.stream, parser);\n\n return files;\n }\n\n async archive(): Promise<Readable> {\n if (!this.subPath) {\n this.onlyOnce();\n\n return this.stream;\n }\n\n // TODO(Rugvip): method for repacking a tar with a subpath is to simply extract into a\n // tmp dir and recreate the archive. Would be nicer to stream things instead.\n const tmpDir = await this.dir();\n\n try {\n const data = await new Promise<Buffer>(async resolve => {\n await pipeline(\n tar.create({ cwd: tmpDir }, ['']),\n concatStream(resolve),\n );\n });\n return Readable.from(data);\n } finally {\n await fs.remove(tmpDir);\n }\n }\n\n async dir(\n options?: UrlReaderServiceReadTreeResponseDirOptions,\n ): Promise<string> {\n this.onlyOnce();\n\n const dir =\n options?.targetDir ??\n (await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));\n\n // Equivalent of tar --strip-components=N\n // When no subPath is given, remove just 1 top level directory\n let strip = this.subPath ? this.subPath.split('/').length : 1;\n if (!this.stripFirstDirectory) {\n strip--;\n }\n\n let filterError: Error | undefined = undefined;\n await pipeline(\n this.stream,\n tar.extract({\n strip,\n cwd: dir,\n filter: (path, stat) => {\n // Filter errors will short-circuit the rest of the filtering and then throw\n if (filterError) {\n return false;\n }\n\n // Block symlinks/hardlinks that escape the extraction directory\n const entry = stat as ReadEntry;\n if (\n (entry.type === 'SymbolicLink' || entry.type === 'Link') &&\n entry.linkpath\n ) {\n const strippedPath = path.split('/').slice(strip).join('/');\n const linkDir = platformPath.dirname(\n platformPath.join(dir, strippedPath),\n );\n const targetPath = platformPath.resolve(linkDir, entry.linkpath);\n if (!isChildPath(dir, targetPath)) {\n return false;\n }\n }\n\n // File path relative to the root extracted directory. Will remove the\n // top level dir name from the path since its name is hard to predetermine.\n const relativePath = this.stripFirstDirectory\n ? stripFirstDirectoryFromPath(path)\n : path;\n if (this.subPath && !relativePath.startsWith(this.subPath)) {\n return false;\n }\n if (this.filter) {\n const innerPath = path.split('/').slice(strip).join('/');\n try {\n return this.filter(innerPath, { size: stat.size });\n } catch (error) {\n filterError = error;\n return false;\n }\n }\n return true;\n },\n }),\n );\n\n if (filterError) {\n // If the dir was provided we don't want to remove it, but if it wasn't it means\n // we created a temporary directory and we should remove it.\n if (!options?.targetDir) {\n await fs.remove(dir).catch(() => {});\n }\n throw filterError;\n }\n\n return dir;\n }\n}\n"],"names":["promisify","pipelineCb","tar","stripFirstDirectoryFromPath","concatStream","Readable","fs","platformPath","isChildPath"],"mappings":"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"}
1
+ {"version":3,"file":"TarArchiveResponse.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/TarArchiveResponse.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 isChildPath,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadTreeResponseDirOptions,\n UrlReaderServiceReadTreeResponseFile,\n} from '@backstage/backend-plugin-api';\nimport concatStream from 'concat-stream';\nimport fs from 'fs-extra';\nimport platformPath from 'node:path';\nimport { pipeline as pipelineCb, Readable } from 'node:stream';\nimport * as tar from 'tar';\nimport type { ReadEntry } from 'tar';\nimport { promisify } from 'node:util';\nimport { stripFirstDirectoryFromPath } from './util';\n\nconst pipeline = promisify(pipelineCb);\n\n/**\n * Wraps a tar archive stream into a tree response reader.\n */\nexport class TarArchiveResponse implements UrlReaderServiceReadTreeResponse {\n private read = false;\n private readonly stream: Readable;\n private readonly subPath: string;\n private readonly workDir: string;\n public readonly etag: string;\n private readonly filter?: (path: string, info: { size: number }) => boolean;\n private readonly stripFirstDirectory: boolean;\n\n constructor(\n stream: Readable,\n subPath: string,\n workDir: string,\n etag: string,\n filter?: (path: string, info: { size: number }) => boolean,\n stripFirstDirectory: boolean = true,\n ) {\n this.stream = stream;\n this.subPath = subPath;\n this.workDir = workDir;\n this.etag = etag;\n this.filter = filter;\n this.stripFirstDirectory = stripFirstDirectory;\n if (subPath) {\n if (!subPath.endsWith('/')) {\n this.subPath += '/';\n }\n if (subPath.startsWith('/')) {\n throw new TypeError(\n `TarArchiveResponse subPath must not start with a /, got '${subPath}'`,\n );\n }\n }\n\n this.etag = etag;\n }\n\n // Make sure the input stream is only read once\n private onlyOnce() {\n if (this.read) {\n throw new Error('Response has already been read');\n }\n this.read = true;\n }\n\n async files(): Promise<UrlReaderServiceReadTreeResponseFile[]> {\n this.onlyOnce();\n\n const files = Array<UrlReaderServiceReadTreeResponseFile>();\n const parser = new tar.Parser();\n\n parser.on('entry', (entry: ReadEntry & Readable) => {\n if (entry.type === 'Directory') {\n entry.resume();\n return;\n }\n\n // File path relative to the root extracted directory. Will remove the\n // top level dir name from the path since its name is hard to predetermine.\n const relativePath = this.stripFirstDirectory\n ? stripFirstDirectoryFromPath(entry.path)\n : entry.path;\n\n if (this.subPath) {\n if (!relativePath.startsWith(this.subPath)) {\n entry.resume();\n return;\n }\n }\n\n const path = relativePath.slice(this.subPath.length);\n if (this.filter) {\n if (!this.filter(path, { size: entry.remain })) {\n entry.resume();\n return;\n }\n }\n\n const content = new Promise<Buffer>(async resolve => {\n await pipeline(entry, concatStream(resolve));\n });\n\n files.push({\n path,\n content: () => content,\n });\n\n entry.resume();\n });\n\n await pipeline(this.stream, parser);\n\n return files;\n }\n\n async archive(): Promise<Readable> {\n if (!this.subPath) {\n this.onlyOnce();\n\n return this.stream;\n }\n\n // TODO(Rugvip): method for repacking a tar with a subpath is to simply extract into a\n // tmp dir and recreate the archive. Would be nicer to stream things instead.\n const tmpDir = await this.dir();\n\n try {\n const data = await new Promise<Buffer>(async resolve => {\n await pipeline(\n tar.create({ cwd: tmpDir }, ['']),\n concatStream(resolve),\n );\n });\n return Readable.from(data);\n } finally {\n await fs.remove(tmpDir);\n }\n }\n\n async dir(\n options?: UrlReaderServiceReadTreeResponseDirOptions,\n ): Promise<string> {\n this.onlyOnce();\n\n const dir =\n options?.targetDir ??\n (await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));\n\n // Equivalent of tar --strip-components=N\n // When no subPath is given, remove just 1 top level directory\n let strip = this.subPath ? this.subPath.split('/').length : 1;\n if (!this.stripFirstDirectory) {\n strip--;\n }\n\n let filterError: Error | undefined = undefined;\n await pipeline(\n this.stream,\n tar.extract({\n strip,\n cwd: dir,\n filter: (path, stat) => {\n // Filter errors will short-circuit the rest of the filtering and then throw\n if (filterError) {\n return false;\n }\n\n // Block symlinks/hardlinks that escape the extraction directory\n const entry = stat as ReadEntry;\n if (\n (entry.type === 'SymbolicLink' || entry.type === 'Link') &&\n entry.linkpath\n ) {\n const strippedPath = path.split('/').slice(strip).join('/');\n const linkDir = platformPath.dirname(\n platformPath.join(dir, strippedPath),\n );\n const targetPath = platformPath.resolve(linkDir, entry.linkpath);\n if (!isChildPath(dir, targetPath)) {\n return false;\n }\n }\n\n // File path relative to the root extracted directory. Will remove the\n // top level dir name from the path since its name is hard to predetermine.\n const relativePath = this.stripFirstDirectory\n ? stripFirstDirectoryFromPath(path)\n : path;\n if (this.subPath && !relativePath.startsWith(this.subPath)) {\n return false;\n }\n if (this.filter) {\n const innerPath = path.split('/').slice(strip).join('/');\n try {\n return this.filter(innerPath, { size: stat.size });\n } catch (error) {\n filterError = error;\n return false;\n }\n }\n return true;\n },\n }),\n );\n\n if (filterError) {\n // If the dir was provided we don't want to remove it, but if it wasn't it means\n // we created a temporary directory and we should remove it.\n if (!options?.targetDir) {\n await fs.remove(dir).catch(() => {});\n }\n throw filterError;\n }\n\n return dir;\n }\n}\n"],"names":["promisify","pipelineCb","tar","stripFirstDirectoryFromPath","concatStream","Readable","fs","platformPath","isChildPath"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ZipArchiveResponse.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.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 UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadTreeResponseDirOptions,\n UrlReaderServiceReadTreeResponseFile,\n} from '@backstage/backend-plugin-api';\nimport archiver from 'archiver';\nimport yauzl, { Entry } from 'yauzl';\nimport fs from 'fs-extra';\nimport platformPath from 'node:path';\nimport { Readable } from 'node:stream';\nimport { streamToBuffer } from './util';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\n\n/**\n * Wraps a zip archive stream into a tree response reader.\n */\nexport class ZipArchiveResponse implements UrlReaderServiceReadTreeResponse {\n private read = false;\n private readonly stream: Readable;\n private readonly subPath: string;\n private readonly workDir: string;\n public readonly etag: string;\n private readonly filter?: (path: string, info: { size: number }) => boolean;\n\n constructor(\n stream: Readable,\n subPath: string,\n workDir: string,\n etag: string,\n filter?: (path: string, info: { size: number }) => boolean,\n ) {\n this.stream = stream;\n this.subPath = subPath;\n this.workDir = workDir;\n this.etag = etag;\n this.filter = filter;\n if (subPath) {\n if (!subPath.endsWith('/')) {\n this.subPath += '/';\n }\n if (subPath.startsWith('/')) {\n throw new TypeError(\n `ZipArchiveResponse subPath must not start with a /, got '${subPath}'`,\n );\n }\n }\n\n this.etag = etag;\n }\n\n // Make sure the input stream is only read once\n private onlyOnce() {\n if (this.read) {\n throw new Error('Response has already been read');\n }\n this.read = true;\n }\n\n // File path relative to the root extracted directory or a sub directory if subpath is set.\n private getInnerPath(path: string): string {\n return path.slice(this.subPath.length);\n }\n\n private shouldBeIncluded(entry: Entry): boolean {\n if (this.subPath) {\n if (!entry.fileName.startsWith(this.subPath)) {\n return false;\n }\n }\n if (this.filter) {\n return this.filter(this.getInnerPath(entry.fileName), {\n size: entry.uncompressedSize,\n });\n }\n return true;\n }\n\n private async streamToTemporaryFile(\n stream: Readable,\n ): Promise<{ fileName: string; cleanup: () => Promise<void> }> {\n const tmpDir = await fs.mkdtemp(\n platformPath.join(this.workDir, 'backstage-tmp'),\n );\n const tmpFile = platformPath.join(tmpDir, 'tmp.zip');\n\n const writeStream = fs.createWriteStream(tmpFile);\n\n return new Promise((resolve, reject) => {\n writeStream.on('error', reject);\n writeStream.on('finish', () => {\n writeStream.end();\n resolve({\n fileName: tmpFile,\n cleanup: () => fs.rm(tmpDir, { recursive: true }),\n });\n });\n stream.pipe(writeStream);\n });\n }\n\n private forEveryZipEntry(\n zip: string,\n callback: (entry: Entry, content: Readable) => Promise<void>,\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n yauzl.open(zip, { lazyEntries: true }, (err, zipfile) => {\n if (err || !zipfile) {\n reject(err || new Error(`Failed to open zip file ${zip}`));\n return;\n }\n\n zipfile.on('entry', async (entry: Entry) => {\n // Check that the file is not a directory, and that is matches the filter.\n if (!entry.fileName.endsWith('/') && this.shouldBeIncluded(entry)) {\n zipfile.openReadStream(entry, async (openErr, readStream) => {\n if (openErr || !readStream) {\n reject(\n openErr ||\n new Error(`Failed to open zip entry ${entry.fileName}`),\n );\n return;\n }\n\n await callback(entry, readStream);\n zipfile.readEntry();\n });\n } else {\n zipfile.readEntry();\n }\n });\n zipfile.once('end', () => resolve());\n zipfile.on('error', e => reject(e));\n zipfile.readEntry();\n });\n });\n }\n\n async files(): Promise<UrlReaderServiceReadTreeResponseFile[]> {\n this.onlyOnce();\n const files = Array<UrlReaderServiceReadTreeResponseFile>();\n const temporary = await this.streamToTemporaryFile(this.stream);\n\n await this.forEveryZipEntry(temporary.fileName, async (entry, content) => {\n files.push({\n path: this.getInnerPath(entry.fileName),\n content: async () => await streamToBuffer(content),\n lastModifiedAt: entry.lastModFileTime\n ? new Date(entry.lastModFileTime)\n : undefined,\n });\n });\n\n await temporary.cleanup();\n\n return files;\n }\n\n async archive(): Promise<Readable> {\n this.onlyOnce();\n\n if (!this.subPath) {\n return this.stream;\n }\n\n const archive = archiver('zip');\n const temporary = await this.streamToTemporaryFile(this.stream);\n\n await this.forEveryZipEntry(temporary.fileName, async (entry, content) => {\n archive.append(await streamToBuffer(content), {\n name: this.getInnerPath(entry.fileName),\n });\n });\n\n archive.finalize();\n\n await temporary.cleanup();\n\n return archive;\n }\n\n async dir(\n options?: UrlReaderServiceReadTreeResponseDirOptions,\n ): Promise<string> {\n this.onlyOnce();\n const dir =\n options?.targetDir ??\n (await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));\n\n const temporary = await this.streamToTemporaryFile(this.stream);\n\n await this.forEveryZipEntry(temporary.fileName, async (entry, content) => {\n const entryPath = this.getInnerPath(entry.fileName);\n const dirname = platformPath.dirname(entryPath);\n\n if (dirname) {\n await fs.mkdirp(resolveSafeChildPath(dir, dirname));\n }\n return new Promise(async (resolve, reject) => {\n const file = fs.createWriteStream(resolveSafeChildPath(dir, entryPath));\n file.on('finish', resolve);\n\n content.on('error', reject);\n content.pipe(file);\n });\n });\n\n await temporary.cleanup();\n\n return dir;\n }\n}\n"],"names":["fs","platformPath","yauzl","streamToBuffer","archiver","resolveSafeChildPath"],"mappings":"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"}
1
+ {"version":3,"file":"ZipArchiveResponse.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.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 UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadTreeResponseDirOptions,\n UrlReaderServiceReadTreeResponseFile,\n} from '@backstage/backend-plugin-api';\nimport archiver from 'archiver';\nimport yauzl, { Entry } from 'yauzl';\nimport fs from 'fs-extra';\nimport platformPath from 'node:path';\nimport { Readable } from 'node:stream';\nimport { streamToBuffer } from './util';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\n\n/**\n * Wraps a zip archive stream into a tree response reader.\n */\nexport class ZipArchiveResponse implements UrlReaderServiceReadTreeResponse {\n private read = false;\n private readonly stream: Readable;\n private readonly subPath: string;\n private readonly workDir: string;\n public readonly etag: string;\n private readonly filter?: (path: string, info: { size: number }) => boolean;\n\n constructor(\n stream: Readable,\n subPath: string,\n workDir: string,\n etag: string,\n filter?: (path: string, info: { size: number }) => boolean,\n ) {\n this.stream = stream;\n this.subPath = subPath;\n this.workDir = workDir;\n this.etag = etag;\n this.filter = filter;\n if (subPath) {\n if (!subPath.endsWith('/')) {\n this.subPath += '/';\n }\n if (subPath.startsWith('/')) {\n throw new TypeError(\n `ZipArchiveResponse subPath must not start with a /, got '${subPath}'`,\n );\n }\n }\n\n this.etag = etag;\n }\n\n // Make sure the input stream is only read once\n private onlyOnce() {\n if (this.read) {\n throw new Error('Response has already been read');\n }\n this.read = true;\n }\n\n // File path relative to the root extracted directory or a sub directory if subpath is set.\n private getInnerPath(path: string): string {\n return path.slice(this.subPath.length);\n }\n\n private shouldBeIncluded(entry: Entry): boolean {\n if (this.subPath) {\n if (!entry.fileName.startsWith(this.subPath)) {\n return false;\n }\n }\n if (this.filter) {\n return this.filter(this.getInnerPath(entry.fileName), {\n size: entry.uncompressedSize,\n });\n }\n return true;\n }\n\n private async streamToTemporaryFile(\n stream: Readable,\n ): Promise<{ fileName: string; cleanup: () => Promise<void> }> {\n const tmpDir = await fs.mkdtemp(\n platformPath.join(this.workDir, 'backstage-tmp'),\n );\n const tmpFile = platformPath.join(tmpDir, 'tmp.zip');\n\n const writeStream = fs.createWriteStream(tmpFile);\n\n return new Promise((resolve, reject) => {\n writeStream.on('error', reject);\n writeStream.on('finish', () => {\n writeStream.end();\n resolve({\n fileName: tmpFile,\n cleanup: () => fs.rm(tmpDir, { recursive: true }),\n });\n });\n stream.pipe(writeStream);\n });\n }\n\n private forEveryZipEntry(\n zip: string,\n callback: (entry: Entry, content: Readable) => Promise<void>,\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n yauzl.open(zip, { lazyEntries: true }, (err, zipfile) => {\n if (err || !zipfile) {\n reject(err || new Error(`Failed to open zip file ${zip}`));\n return;\n }\n\n zipfile.on('entry', async (entry: Entry) => {\n // Check that the file is not a directory, and that is matches the filter.\n if (!entry.fileName.endsWith('/') && this.shouldBeIncluded(entry)) {\n zipfile.openReadStream(entry, async (openErr, readStream) => {\n if (openErr || !readStream) {\n reject(\n openErr ||\n new Error(`Failed to open zip entry ${entry.fileName}`),\n );\n return;\n }\n\n await callback(entry, readStream);\n zipfile.readEntry();\n });\n } else {\n zipfile.readEntry();\n }\n });\n zipfile.once('end', () => resolve());\n zipfile.on('error', e => reject(e));\n zipfile.readEntry();\n });\n });\n }\n\n async files(): Promise<UrlReaderServiceReadTreeResponseFile[]> {\n this.onlyOnce();\n const files = Array<UrlReaderServiceReadTreeResponseFile>();\n const temporary = await this.streamToTemporaryFile(this.stream);\n\n await this.forEveryZipEntry(temporary.fileName, async (entry, content) => {\n files.push({\n path: this.getInnerPath(entry.fileName),\n content: async () => await streamToBuffer(content),\n lastModifiedAt: entry.lastModFileTime\n ? new Date(entry.lastModFileTime)\n : undefined,\n });\n });\n\n await temporary.cleanup();\n\n return files;\n }\n\n async archive(): Promise<Readable> {\n this.onlyOnce();\n\n if (!this.subPath) {\n return this.stream;\n }\n\n const archive = archiver('zip');\n const temporary = await this.streamToTemporaryFile(this.stream);\n\n await this.forEveryZipEntry(temporary.fileName, async (entry, content) => {\n archive.append(await streamToBuffer(content), {\n name: this.getInnerPath(entry.fileName),\n });\n });\n\n archive.finalize();\n\n await temporary.cleanup();\n\n return archive;\n }\n\n async dir(\n options?: UrlReaderServiceReadTreeResponseDirOptions,\n ): Promise<string> {\n this.onlyOnce();\n const dir =\n options?.targetDir ??\n (await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));\n\n const temporary = await this.streamToTemporaryFile(this.stream);\n\n await this.forEveryZipEntry(temporary.fileName, async (entry, content) => {\n const entryPath = this.getInnerPath(entry.fileName);\n const dirname = platformPath.dirname(entryPath);\n\n if (dirname) {\n await fs.mkdirp(resolveSafeChildPath(dir, dirname));\n }\n return new Promise(async (resolve, reject) => {\n const file = fs.createWriteStream(resolveSafeChildPath(dir, entryPath));\n file.on('finish', resolve);\n\n content.on('error', reject);\n content.pipe(file);\n });\n });\n\n await temporary.cleanup();\n\n return dir;\n }\n}\n"],"names":["fs","platformPath","yauzl","streamToBuffer","archiver","resolveSafeChildPath"],"mappings":";;;;;;;;;;;;;;;;AAgCO,MAAM,kBAAA,CAA+D;AAAA,EAClE,IAAA,GAAO,KAAA;AAAA,EACE,MAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACD,IAAA;AAAA,EACC,MAAA;AAAA,EAEjB,WAAA,CACE,MAAA,EACA,OAAA,EACA,OAAA,EACA,MACA,MAAA,EACA;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAC1B,QAAA,IAAA,CAAK,OAAA,IAAW,GAAA;AAAA,MAClB;AACA,MAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AAC3B,QAAA,MAAM,IAAI,SAAA;AAAA,UACR,4DAA4D,OAAO,CAAA,CAAA;AAAA,SACrE;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA,EAGQ,QAAA,GAAW;AACjB,IAAA,IAAI,KAAK,IAAA,EAAM;AACb,MAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,IAClD;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA,EAGQ,aAAa,IAAA,EAAsB;AACzC,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AAAA,EACvC;AAAA,EAEQ,iBAAiB,KAAA,EAAuB;AAC9C,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA,EAAG;AAC5C,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,OAAO,KAAK,MAAA,CAAO,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,QAAQ,CAAA,EAAG;AAAA,QACpD,MAAM,KAAA,CAAM;AAAA,OACb,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAc,sBACZ,MAAA,EAC6D;AAC7D,IAAA,MAAM,MAAA,GAAS,MAAMA,mBAAA,CAAG,OAAA;AAAA,MACtBC,6BAAA,CAAa,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,eAAe;AAAA,KACjD;AACA,IAAA,MAAM,OAAA,GAAUA,6BAAA,CAAa,IAAA,CAAK,MAAA,EAAQ,SAAS,CAAA;AAEnD,IAAA,MAAM,WAAA,GAAcD,mBAAA,CAAG,iBAAA,CAAkB,OAAO,CAAA;AAEhD,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,WAAA,CAAY,EAAA,CAAG,SAAS,MAAM,CAAA;AAC9B,MAAA,WAAA,CAAY,EAAA,CAAG,UAAU,MAAM;AAC7B,QAAA,WAAA,CAAY,GAAA,EAAI;AAChB,QAAA,OAAA,CAAQ;AAAA,UACN,QAAA,EAAU,OAAA;AAAA,UACV,OAAA,EAAS,MAAMA,mBAAA,CAAG,EAAA,CAAG,QAAQ,EAAE,SAAA,EAAW,MAAM;AAAA,SACjD,CAAA;AAAA,MACH,CAAC,CAAA;AACD,MAAA,MAAA,CAAO,KAAK,WAAW,CAAA;AAAA,IACzB,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,gBAAA,CACN,KACA,QAAA,EACe;AACf,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAAE,sBAAA,CAAM,IAAA,CAAK,KAAK,EAAE,WAAA,EAAa,MAAK,EAAG,CAAC,KAAK,OAAA,KAAY;AACvD,QAAA,IAAI,GAAA,IAAO,CAAC,OAAA,EAAS;AACnB,UAAA,MAAA,CAAO,OAAO,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,GAAG,EAAE,CAAC,CAAA;AACzD,UAAA;AAAA,QACF;AAEA,QAAA,OAAA,CAAQ,EAAA,CAAG,OAAA,EAAS,OAAO,KAAA,KAAiB;AAE1C,UAAA,IAAI,CAAC,MAAM,QAAA,CAAS,QAAA,CAAS,GAAG,CAAA,IAAK,IAAA,CAAK,gBAAA,CAAiB,KAAK,CAAA,EAAG;AACjE,YAAA,OAAA,CAAQ,cAAA,CAAe,KAAA,EAAO,OAAO,OAAA,EAAS,UAAA,KAAe;AAC3D,cAAA,IAAI,OAAA,IAAW,CAAC,UAAA,EAAY;AAC1B,gBAAA,MAAA;AAAA,kBACE,WACE,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,KAAA,CAAM,QAAQ,CAAA,CAAE;AAAA,iBAC1D;AACA,gBAAA;AAAA,cACF;AAEA,cAAA,MAAM,QAAA,CAAS,OAAO,UAAU,CAAA;AAChC,cAAA,OAAA,CAAQ,SAAA,EAAU;AAAA,YACpB,CAAC,CAAA;AAAA,UACH,CAAA,MAAO;AACL,YAAA,OAAA,CAAQ,SAAA,EAAU;AAAA,UACpB;AAAA,QACF,CAAC,CAAA;AACD,QAAA,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,MAAM,OAAA,EAAS,CAAA;AACnC,QAAA,OAAA,CAAQ,EAAA,CAAG,OAAA,EAAS,CAAA,CAAA,KAAK,MAAA,CAAO,CAAC,CAAC,CAAA;AAClC,QAAA,OAAA,CAAQ,SAAA,EAAU;AAAA,MACpB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,KAAA,GAAyD;AAC7D,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,MAAM,QAAQ,KAAA,EAA4C;AAC1D,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,qBAAA,CAAsB,KAAK,MAAM,CAAA;AAE9D,IAAA,MAAM,KAAK,gBAAA,CAAiB,SAAA,CAAU,QAAA,EAAU,OAAO,OAAO,OAAA,KAAY;AACxE,MAAA,KAAA,CAAM,IAAA,CAAK;AAAA,QACT,IAAA,EAAM,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,QAAQ,CAAA;AAAA,QACtC,OAAA,EAAS,YAAY,MAAMC,mBAAA,CAAe,OAAO,CAAA;AAAA,QACjD,gBAAgB,KAAA,CAAM,eAAA,GAClB,IAAI,IAAA,CAAK,KAAA,CAAM,eAAe,CAAA,GAC9B;AAAA,OACL,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,MAAM,UAAU,OAAA,EAAQ;AAExB,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAA,GAA6B;AACjC,IAAA,IAAA,CAAK,QAAA,EAAS;AAEd,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,MAAA,OAAO,IAAA,CAAK,MAAA;AAAA,IACd;AAEA,IAAA,MAAM,OAAA,GAAUC,0BAAS,KAAK,CAAA;AAC9B,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,qBAAA,CAAsB,KAAK,MAAM,CAAA;AAE9D,IAAA,MAAM,KAAK,gBAAA,CAAiB,SAAA,CAAU,QAAA,EAAU,OAAO,OAAO,OAAA,KAAY;AACxE,MAAA,OAAA,CAAQ,MAAA,CAAO,MAAMD,mBAAA,CAAe,OAAO,CAAA,EAAG;AAAA,QAC5C,IAAA,EAAM,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,QAAQ;AAAA,OACvC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,OAAA,CAAQ,QAAA,EAAS;AAEjB,IAAA,MAAM,UAAU,OAAA,EAAQ;AAExB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAM,IACJ,OAAA,EACiB;AACjB,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,MAAM,GAAA,GACJ,OAAA,EAAS,SAAA,IACR,MAAMH,mBAAA,CAAG,OAAA,CAAQC,6BAAA,CAAa,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,YAAY,CAAC,CAAA;AAEjE,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,qBAAA,CAAsB,KAAK,MAAM,CAAA;AAE9D,IAAA,MAAM,KAAK,gBAAA,CAAiB,SAAA,CAAU,QAAA,EAAU,OAAO,OAAO,OAAA,KAAY;AACxE,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,QAAQ,CAAA;AAClD,MAAA,MAAM,OAAA,GAAUA,6BAAA,CAAa,OAAA,CAAQ,SAAS,CAAA;AAE9C,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,MAAMD,mBAAA,CAAG,MAAA,CAAOK,qCAAA,CAAqB,GAAA,EAAK,OAAO,CAAC,CAAA;AAAA,MACpD;AACA,MAAA,OAAO,IAAI,OAAA,CAAQ,OAAO,OAAA,EAAS,MAAA,KAAW;AAC5C,QAAA,MAAM,OAAOL,mBAAA,CAAG,iBAAA,CAAkBK,qCAAA,CAAqB,GAAA,EAAK,SAAS,CAAC,CAAA;AACtE,QAAA,IAAA,CAAK,EAAA,CAAG,UAAU,OAAO,CAAA;AAEzB,QAAA,OAAA,CAAQ,EAAA,CAAG,SAAS,MAAM,CAAA;AAC1B,QAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,MACnB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,MAAM,UAAU,OAAA,EAAQ;AAExB,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"util.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/util.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 { Readable, pipeline as pipelineCb } from 'node:stream';\nimport { promisify } from 'node:util';\nimport concatStream from 'concat-stream';\n\nconst pipeline = promisify(pipelineCb);\n\n// Matches a directory name + one `/` at the start of any string,\n// containing any character except `/` one or more times, and ending with a `/`\n// e.g. Will match `dirA/` in `dirA/dirB/file.ext`\nconst directoryNameRegex = /^[^\\/]+\\//;\n// Removes the first segment of a forward-slash-separated path\nexport function stripFirstDirectoryFromPath(path: string): string {\n return path.replace(directoryNameRegex, '');\n}\n\n// Collect the stream into a buffer and return\nexport const streamToBuffer = (stream: Readable): Promise<Buffer> => {\n return new Promise(async (resolve, reject) => {\n try {\n await pipeline(stream, concatStream(resolve));\n } catch (ex) {\n reject(ex);\n }\n });\n};\n"],"names":["promisify","pipelineCb","concatStream"],"mappings":";;;;;;;;;;AAoBA,MAAM,QAAA,GAAWA,oBAAUC,oBAAU,CAAA;AAKrC,MAAM,kBAAA,GAAqB,WAAA;AAEpB,SAAS,4BAA4B,IAAA,EAAsB;AAChE,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA;AAC5C;AAGO,MAAM,cAAA,GAAiB,CAAC,MAAA,KAAsC;AACnE,EAAA,OAAO,IAAI,OAAA,CAAQ,OAAO,OAAA,EAAS,MAAA,KAAW;AAC5C,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,CAAS,MAAA,EAAQC,6BAAA,CAAa,OAAO,CAAC,CAAA;AAAA,IAC9C,SAAS,EAAA,EAAI;AACX,MAAA,MAAA,CAAO,EAAE,CAAA;AAAA,IACX;AAAA,EACF,CAAC,CAAA;AACH;;;;;"}
1
+ {"version":3,"file":"util.cjs.js","sources":["../../../../../src/entrypoints/urlReader/lib/tree/util.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 { Readable, pipeline as pipelineCb } from 'node:stream';\nimport { promisify } from 'node:util';\nimport concatStream from 'concat-stream';\n\nconst pipeline = promisify(pipelineCb);\n\n// Matches a directory name + one `/` at the start of any string,\n// containing any character except `/` one or more times, and ending with a `/`\n// e.g. Will match `dirA/` in `dirA/dirB/file.ext`\nconst directoryNameRegex = /^[^\\/]+\\//;\n// Removes the first segment of a forward-slash-separated path\nexport function stripFirstDirectoryFromPath(path: string): string {\n return path.replace(directoryNameRegex, '');\n}\n\n// Collect the stream into a buffer and return\nexport const streamToBuffer = (stream: Readable): Promise<Buffer> => {\n return new Promise(async (resolve, reject) => {\n try {\n await pipeline(stream, concatStream(resolve));\n } catch (ex) {\n reject(ex);\n }\n });\n};\n"],"names":["promisify","pipelineCb","concatStream"],"mappings":";;;;;;;;;;AAoBA,MAAM,QAAA,GAAWA,oBAAUC,oBAAU,CAAA;AAKrC,MAAM,kBAAA,GAAqB,WAAA;AAEpB,SAAS,4BAA4B,IAAA,EAAsB;AAChE,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA;AAC5C;AAGO,MAAM,cAAA,GAAiB,CAAC,MAAA,KAAsC;AACnE,EAAA,OAAO,IAAI,OAAA,CAAQ,OAAO,OAAA,EAAS,MAAA,KAAW;AAC5C,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,CAAS,MAAA,EAAQC,6BAAA,CAAa,OAAO,CAAC,CAAA;AAAA,IAC9C,SAAS,EAAA,EAAI;AACX,MAAA,MAAA,CAAO,EAAE,CAAA;AAAA,IACX;AAAA,EACF,CAAC,CAAA;AACH;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"util.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/util.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { PassThrough, Readable } from 'node:stream';\nimport { ReadableStream as WebReadableStream } from 'node:stream/web';\n\nexport function hasDotPathSegments(name: string): boolean {\n return name.split(/[/\\\\]/).some(segment => {\n try {\n const decoded = decodeURIComponent(segment);\n return decoded === '..' || decoded === '.';\n } catch {\n return false;\n }\n });\n}\n\nexport function isUrlPathWithoutDotSegments(url: string): boolean {\n const authoritySeparator = url.indexOf('://');\n if (authoritySeparator === -1) {\n return false;\n }\n\n const urlRemainder = url.slice(authoritySeparator + 3);\n const pathStart = urlRemainder.search(/[\\\\/]/);\n const suffixStart = urlRemainder.search(/[?#]/);\n let rawPathname = '';\n if (pathStart !== -1 && (suffixStart === -1 || pathStart < suffixStart)) {\n rawPathname = urlRemainder.slice(pathStart).split(/[?#]/, 1)[0];\n }\n\n try {\n return !decodeURIComponent(rawPathname)\n .split(/[\\\\/]/)\n .some(segment => segment === '.' || segment === '..');\n } catch {\n return false;\n }\n}\n\nexport function parseLastModified(\n value: string | null | undefined,\n): Date | undefined {\n if (!value) {\n return undefined;\n }\n\n try {\n const result = new Date(value);\n result.toISOString(); // triggers exception if input was invalid\n return result;\n } catch {\n return undefined;\n }\n}\n\nexport function responseToReadable(response: Response): Readable {\n return response.body\n ? Readable.from(toWeb(response.body))\n : new PassThrough().end();\n}\n\n// The NodeJS ReadableStream is that fetch returns is super basic and not even\n// iterable. This function converts it to the smarter, iterable stream/web\n// variant instead.\nfunction toWeb(\n responseBody: ReadableStream<Uint8Array>,\n): WebReadableStream<Uint8Array> {\n const reader = responseBody.getReader();\n return new WebReadableStream({\n async pull(controller) {\n const { value, done } = await reader.read();\n if (value) {\n controller.enqueue(value);\n }\n if (done) {\n controller.close();\n }\n },\n });\n}\n"],"names":["Readable","PassThrough","WebReadableStream"],"mappings":";;;;;AAmBO,SAAS,mBAAmB,IAAA,EAAuB;AACxD,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,CAAE,KAAK,CAAA,OAAA,KAAW;AACzC,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,mBAAmB,OAAO,CAAA;AAC1C,MAAA,OAAO,OAAA,KAAY,QAAQ,OAAA,KAAY,GAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF,CAAC,CAAA;AACH;AAEO,SAAS,4BAA4B,GAAA,EAAsB;AAChE,EAAA,MAAM,kBAAA,GAAqB,GAAA,CAAI,OAAA,CAAQ,KAAK,CAAA;AAC5C,EAAA,IAAI,uBAAuB,EAAA,EAAI;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAA,GAAe,GAAA,CAAI,KAAA,CAAM,kBAAA,GAAqB,CAAC,CAAA;AACrD,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,MAAA,CAAO,OAAO,CAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,MAAA,CAAO,MAAM,CAAA;AAC9C,EAAA,IAAI,WAAA,GAAc,EAAA;AAClB,EAAA,IAAI,SAAA,KAAc,EAAA,KAAO,WAAA,KAAgB,EAAA,IAAM,YAAY,WAAA,CAAA,EAAc;AACvE,IAAA,WAAA,GAAc,YAAA,CAAa,MAAM,SAAS,CAAA,CAAE,MAAM,MAAA,EAAQ,CAAC,EAAE,CAAC,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,kBAAA,CAAmB,WAAW,CAAA,CACnC,KAAA,CAAM,OAAO,CAAA,CACb,IAAA,CAAK,CAAA,OAAA,KAAW,OAAA,KAAY,GAAA,IAAO,OAAA,KAAY,IAAI,CAAA;AAAA,EACxD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,kBACd,KAAA,EACkB;AAClB,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,IAAA,CAAK,KAAK,CAAA;AAC7B,IAAA,MAAA,CAAO,WAAA,EAAY;AACnB,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEO,SAAS,mBAAmB,QAAA,EAA8B;AAC/D,EAAA,OAAO,QAAA,CAAS,IAAA,GACZA,oBAAA,CAAS,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,GAClC,IAAIC,uBAAA,EAAY,CAAE,GAAA,EAAI;AAC5B;AAKA,SAAS,MACP,YAAA,EAC+B;AAC/B,EAAA,MAAM,MAAA,GAAS,aAAa,SAAA,EAAU;AACtC,EAAA,OAAO,IAAIC,kBAAA,CAAkB;AAAA,IAC3B,MAAM,KAAK,UAAA,EAAY;AACrB,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,UAAA,CAAW,QAAQ,KAAK,CAAA;AAAA,MAC1B;AACA,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,KAAA,EAAM;AAAA,MACnB;AAAA,IACF;AAAA,GACD,CAAA;AACH;;;;;;;"}
1
+ {"version":3,"file":"util.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/util.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { PassThrough, Readable } from 'node:stream';\nimport { ReadableStream as WebReadableStream } from 'node:stream/web';\n\nexport function hasDotPathSegments(name: string): boolean {\n return name.split(/[/\\\\]/).some(segment => {\n try {\n const decoded = decodeURIComponent(segment);\n return decoded === '..' || decoded === '.';\n } catch {\n return false;\n }\n });\n}\n\nexport function isUrlPathWithoutDotSegments(url: string): boolean {\n const authoritySeparator = url.indexOf('://');\n if (authoritySeparator === -1) {\n return false;\n }\n\n const urlRemainder = url.slice(authoritySeparator + 3);\n const pathStart = urlRemainder.search(/[\\\\/]/);\n const suffixStart = urlRemainder.search(/[?#]/);\n let rawPathname = '';\n if (pathStart !== -1 && (suffixStart === -1 || pathStart < suffixStart)) {\n rawPathname = urlRemainder.slice(pathStart).split(/[?#]/, 1)[0];\n }\n\n try {\n return !decodeURIComponent(rawPathname)\n .split(/[\\\\/]/)\n .some(segment => segment === '.' || segment === '..');\n } catch {\n return false;\n }\n}\n\nexport function parseLastModified(\n value: string | null | undefined,\n): Date | undefined {\n if (!value) {\n return undefined;\n }\n\n try {\n const result = new Date(value);\n result.toISOString(); // triggers exception if input was invalid\n return result;\n } catch {\n return undefined;\n }\n}\n\nexport function responseToReadable(response: Response): Readable {\n return response.body\n ? Readable.from(toWeb(response.body))\n : new PassThrough().end();\n}\n\n// The NodeJS ReadableStream is that fetch returns is super basic and not even\n// iterable. This function converts it to the smarter, iterable stream/web\n// variant instead.\nfunction toWeb(\n responseBody: ReadableStream<Uint8Array>,\n): WebReadableStream<Uint8Array> {\n const reader = responseBody.getReader();\n return new WebReadableStream({\n async pull(controller) {\n const { value, done } = await reader.read();\n if (value) {\n controller.enqueue(value);\n }\n if (done) {\n controller.close();\n }\n },\n });\n}\n"],"names":["Readable","PassThrough","WebReadableStream"],"mappings":";;;;;AAmBO,SAAS,mBAAmB,IAAA,EAAuB;AACxD,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,CAAE,KAAK,CAAA,OAAA,KAAW;AACzC,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,mBAAmB,OAAO,CAAA;AAC1C,MAAA,OAAO,OAAA,KAAY,QAAQ,OAAA,KAAY,GAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF,CAAC,CAAA;AACH;AAEO,SAAS,4BAA4B,GAAA,EAAsB;AAChE,EAAA,MAAM,kBAAA,GAAqB,GAAA,CAAI,OAAA,CAAQ,KAAK,CAAA;AAC5C,EAAA,IAAI,uBAAuB,EAAA,EAAI;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAA,GAAe,GAAA,CAAI,KAAA,CAAM,kBAAA,GAAqB,CAAC,CAAA;AACrD,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,MAAA,CAAO,OAAO,CAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,MAAA,CAAO,MAAM,CAAA;AAC9C,EAAA,IAAI,WAAA,GAAc,EAAA;AAClB,EAAA,IAAI,SAAA,KAAc,EAAA,KAAO,WAAA,KAAgB,EAAA,IAAM,YAAY,WAAA,CAAA,EAAc;AACvE,IAAA,WAAA,GAAc,YAAA,CAAa,MAAM,SAAS,CAAA,CAAE,MAAM,MAAA,EAAQ,CAAC,EAAE,CAAC,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,kBAAA,CAAmB,WAAW,CAAA,CACnC,KAAA,CAAM,OAAO,CAAA,CACb,IAAA,CAAK,CAAA,OAAA,KAAW,OAAA,KAAY,GAAA,IAAO,OAAA,KAAY,IAAI,CAAA;AAAA,EACxD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,kBACd,KAAA,EACkB;AAClB,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,IAAA,CAAK,KAAK,CAAA;AAC7B,IAAA,MAAA,CAAO,WAAA,EAAY;AACnB,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEO,SAAS,mBAAmB,QAAA,EAA8B;AAC/D,EAAA,OAAO,QAAA,CAAS,IAAA,GACZA,oBAAA,CAAS,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA,GAClC,IAAIC,uBAAA,EAAY,CAAE,GAAA,EAAI;AAC5B;AAKA,SAAS,MACP,YAAA,EAC+B;AAC/B,EAAA,MAAM,MAAA,GAAS,aAAa,SAAA,EAAU;AACtC,EAAA,OAAO,IAAIC,kBAAA,CAAkB;AAAA,IAC3B,MAAM,KAAK,UAAA,EAAY;AACrB,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,UAAA,CAAW,QAAQ,KAAK,CAAA;AAAA,MAC1B;AACA,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,KAAA,EAAM;AAAA,MACnB;AAAA,IACF;AAAA,GACD,CAAA;AACH;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"urlReaderServiceFactory.cjs.js","sources":["../../../src/entrypoints/urlReader/urlReaderServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { ReaderFactory } from './lib';\nimport { UrlReaders } from './lib/UrlReaders';\nimport {\n coreServices,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\n\n/**\n * @public\n * A non-singleton reference to URL Reader factory services.\n *\n * @example\n * Creating a service factory implementation for a Custom URL Reader.\n * ```ts\n * createServiceFactory({\n * service: urlReaderFactoriesServiceRef,\n * deps: {},\n * async factory() {\n * return CustomUrlReader.factory;\n * },\n * });\n * ```\n */\nexport const urlReaderFactoriesServiceRef = createServiceRef<ReaderFactory>({\n id: 'core.urlReader.factories',\n scope: 'plugin',\n multiton: true,\n});\n\n/**\n * Reading content from external systems.\n *\n * See {@link @backstage/code-plugin-api#UrlReaderService}\n * and {@link https://backstage.io/docs/backend-system/core-services/url-reader | the service docs}\n * for more information.\n *\n * @public\n */\nexport const urlReaderServiceFactory = createServiceFactory({\n service: coreServices.urlReader,\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n factories: urlReaderFactoriesServiceRef,\n },\n async factory({ config, logger, factories }) {\n return UrlReaders.default({\n config,\n logger,\n factories,\n });\n },\n});\n"],"names":["createServiceRef","createServiceFactory","coreServices","UrlReaders"],"mappings":";;;;;AAwCO,MAAM,+BAA+BA,iCAAA,CAAgC;AAAA,EAC1E,EAAA,EAAI,0BAAA;AAAA,EACJ,KAAA,EAAO,QAAA;AAAA,EACP,QAAA,EAAU;AACZ,CAAC;AAWM,MAAM,0BAA0BC,qCAAA,CAAqB;AAAA,EAC1D,SAASC,6BAAA,CAAa,SAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa,MAAA;AAAA,IACrB,SAAA,EAAW;AAAA,GACb;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,WAAU,EAAG;AAC3C,IAAA,OAAOC,sBAAW,OAAA,CAAQ;AAAA,MACxB,MAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;;"}
1
+ {"version":3,"file":"urlReaderServiceFactory.cjs.js","sources":["../../../src/entrypoints/urlReader/urlReaderServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { ReaderFactory } from './lib';\nimport { UrlReaders } from './lib/UrlReaders';\nimport {\n coreServices,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\n\n/**\n * @public\n * A non-singleton reference to URL Reader factory services.\n *\n * @example\n * Creating a service factory implementation for a Custom URL Reader.\n * ```ts\n * createServiceFactory({\n * service: urlReaderFactoriesServiceRef,\n * deps: {},\n * async factory() {\n * return CustomUrlReader.factory;\n * },\n * });\n * ```\n */\nexport const urlReaderFactoriesServiceRef = createServiceRef<ReaderFactory>({\n id: 'core.urlReader.factories',\n scope: 'plugin',\n multiton: true,\n});\n\n/**\n * Reading content from external systems.\n *\n * See {@link @backstage/code-plugin-api#UrlReaderService}\n * and {@link https://backstage.io/docs/backend-system/core-services/url-reader | the service docs}\n * for more information.\n *\n * @public\n */\nexport const urlReaderServiceFactory = createServiceFactory({\n service: coreServices.urlReader,\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n factories: urlReaderFactoriesServiceRef,\n },\n async factory({ config, logger, factories }) {\n return UrlReaders.default({\n config,\n logger,\n factories,\n });\n },\n});\n"],"names":["createServiceRef","createServiceFactory","coreServices","UrlReaders"],"mappings":";;;;;AAwCO,MAAM,+BAA+BA,iCAAA,CAAgC;AAAA,EAC1E,EAAA,EAAI,0BAAA;AAAA,EACJ,KAAA,EAAO,QAAA;AAAA,EACP,QAAA,EAAU;AACZ,CAAC;AAWM,MAAM,0BAA0BC,qCAAA,CAAqB;AAAA,EAC1D,SAASC,6BAAA,CAAa,SAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa,MAAA;AAAA,IACrB,SAAA,EAAW;AAAA,GACb;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,WAAU,EAAG;AAC3C,IAAA,OAAOC,sBAAW,OAAA,CAAQ;AAAA,MACxB,MAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CachedUserInfoService.cjs.js","sources":["../../../src/entrypoints/userInfo/CachedUserInfoService.ts"],"sourcesContent":["/*\n * Copyright 2026 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 BackstageCredentials,\n BackstageUserInfo,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { toInternalBackstageCredentials } from '../auth/helpers';\n\nconst DEFAULT_TTL_MS = 5_000;\nconst SWEEP_INTERVAL_MS = 30_000;\n\nexport type UserInfoCacheEntry = {\n promise: Promise<BackstageUserInfo>;\n expiresAt: number;\n};\n\nexport class CachedUserInfoService implements UserInfoService {\n readonly #delegate: UserInfoService;\n readonly #entries: Map<string, UserInfoCacheEntry>;\n readonly #ttlMs: number;\n #lastSweep: number = Date.now();\n\n constructor(\n delegate: UserInfoService,\n options?: {\n entries?: Map<string, UserInfoCacheEntry>;\n ttlMs?: number;\n },\n ) {\n this.#delegate = delegate;\n this.#entries = options?.entries ?? new Map();\n this.#ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;\n }\n\n async getUserInfo(\n credentials: BackstageCredentials,\n ): Promise<BackstageUserInfo> {\n const internalCredentials = toInternalBackstageCredentials(credentials);\n const token = internalCredentials.token;\n if (!token) {\n return this.#delegate.getUserInfo(credentials);\n }\n\n const now = Date.now();\n\n if (now - this.#lastSweep > SWEEP_INTERVAL_MS) {\n this.#lastSweep = now;\n for (const [key, entry] of this.#entries) {\n if (entry.expiresAt <= now) {\n this.#entries.delete(key);\n }\n }\n }\n\n const cached = this.#entries.get(token);\n if (cached && cached.expiresAt > now) {\n return cached.promise;\n }\n\n const promise = this.#delegate.getUserInfo(credentials).catch(error => {\n if (this.#entries.get(token)?.promise === promise) {\n this.#entries.delete(token);\n }\n throw error;\n });\n\n this.#entries.set(token, {\n promise,\n expiresAt: now + this.#ttlMs,\n });\n\n return promise;\n }\n}\n"],"names":["toInternalBackstageCredentials"],"mappings":";;;;AAuBA,MAAM,cAAA,GAAiB,GAAA;AACvB,MAAM,iBAAA,GAAoB,GAAA;AAOnB,MAAM,qBAAA,CAAiD;AAAA,EACnD,SAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACT,UAAA,GAAqB,KAAK,GAAA,EAAI;AAAA,EAE9B,WAAA,CACE,UACA,OAAA,EAIA;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA,EAAS,OAAA,oBAAW,IAAI,GAAA,EAAI;AAC5C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAS,KAAA,IAAS,cAAA;AAAA,EAClC;AAAA,EAEA,MAAM,YACJ,WAAA,EAC4B;AAC5B,IAAA,MAAM,mBAAA,GAAsBA,uCAA+B,WAAW,CAAA;AACtE,IAAA,MAAM,QAAQ,mBAAA,CAAoB,KAAA;AAClC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,IAAA,CAAK,SAAA,CAAU,WAAA,CAAY,WAAW,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,IAAI,GAAA,GAAM,IAAA,CAAK,UAAA,GAAa,iBAAA,EAAmB;AAC7C,MAAA,IAAA,CAAK,UAAA,GAAa,GAAA;AAClB,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,KAAK,QAAA,EAAU;AACxC,QAAA,IAAI,KAAA,CAAM,aAAa,GAAA,EAAK;AAC1B,UAAA,IAAA,CAAK,QAAA,CAAS,OAAO,GAAG,CAAA;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA;AACtC,IAAA,IAAI,MAAA,IAAU,MAAA,CAAO,SAAA,GAAY,GAAA,EAAK;AACpC,MAAA,OAAO,MAAA,CAAO,OAAA;AAAA,IAChB;AAEA,IAAA,MAAM,UAAU,IAAA,CAAK,SAAA,CAAU,YAAY,WAAW,CAAA,CAAE,MAAM,CAAA,KAAA,KAAS;AACrE,MAAA,IAAI,KAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA,EAAG,YAAY,OAAA,EAAS;AACjD,QAAA,IAAA,CAAK,QAAA,CAAS,OAAO,KAAK,CAAA;AAAA,MAC5B;AACA,MAAA,MAAM,KAAA;AAAA,IACR,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,KAAA,EAAO;AAAA,MACvB,OAAA;AAAA,MACA,SAAA,EAAW,MAAM,IAAA,CAAK;AAAA,KACvB,CAAA;AAED,IAAA,OAAO,OAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"CachedUserInfoService.cjs.js","sources":["../../../src/entrypoints/userInfo/CachedUserInfoService.ts"],"sourcesContent":["/*\n * Copyright 2026 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 BackstageCredentials,\n BackstageUserInfo,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { toInternalBackstageCredentials } from '../auth/helpers';\n\nconst DEFAULT_TTL_MS = 5_000;\nconst SWEEP_INTERVAL_MS = 30_000;\n\nexport type UserInfoCacheEntry = {\n promise: Promise<BackstageUserInfo>;\n expiresAt: number;\n};\n\nexport class CachedUserInfoService implements UserInfoService {\n readonly #delegate: UserInfoService;\n readonly #entries: Map<string, UserInfoCacheEntry>;\n readonly #ttlMs: number;\n #lastSweep: number = Date.now();\n\n constructor(\n delegate: UserInfoService,\n options?: {\n entries?: Map<string, UserInfoCacheEntry>;\n ttlMs?: number;\n },\n ) {\n this.#delegate = delegate;\n this.#entries = options?.entries ?? new Map();\n this.#ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;\n }\n\n async getUserInfo(\n credentials: BackstageCredentials,\n ): Promise<BackstageUserInfo> {\n const internalCredentials = toInternalBackstageCredentials(credentials);\n const token = internalCredentials.token;\n if (!token) {\n return this.#delegate.getUserInfo(credentials);\n }\n\n const now = Date.now();\n\n if (now - this.#lastSweep > SWEEP_INTERVAL_MS) {\n this.#lastSweep = now;\n for (const [key, entry] of this.#entries) {\n if (entry.expiresAt <= now) {\n this.#entries.delete(key);\n }\n }\n }\n\n const cached = this.#entries.get(token);\n if (cached && cached.expiresAt > now) {\n return cached.promise;\n }\n\n const promise = this.#delegate.getUserInfo(credentials).catch(error => {\n if (this.#entries.get(token)?.promise === promise) {\n this.#entries.delete(token);\n }\n throw error;\n });\n\n this.#entries.set(token, {\n promise,\n expiresAt: now + this.#ttlMs,\n });\n\n return promise;\n }\n}\n"],"names":["toInternalBackstageCredentials"],"mappings":";;;;AAuBA,MAAM,cAAA,GAAiB,GAAA;AACvB,MAAM,iBAAA,GAAoB,GAAA;AAOnB,MAAM,qBAAA,CAAiD;AAAA,EACnD,SAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACT,UAAA,GAAqB,KAAK,GAAA,EAAI;AAAA,EAE9B,WAAA,CACE,UACA,OAAA,EAIA;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA,EAAS,OAAA,oBAAW,IAAI,GAAA,EAAI;AAC5C,IAAA,IAAA,CAAK,MAAA,GAAS,SAAS,KAAA,IAAS,cAAA;AAAA,EAClC;AAAA,EAEA,MAAM,YACJ,WAAA,EAC4B;AAC5B,IAAA,MAAM,mBAAA,GAAsBA,uCAA+B,WAAW,CAAA;AACtE,IAAA,MAAM,QAAQ,mBAAA,CAAoB,KAAA;AAClC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,IAAA,CAAK,SAAA,CAAU,WAAA,CAAY,WAAW,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,IAAI,GAAA,GAAM,IAAA,CAAK,UAAA,GAAa,iBAAA,EAAmB;AAC7C,MAAA,IAAA,CAAK,UAAA,GAAa,GAAA;AAClB,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,KAAK,QAAA,EAAU;AACxC,QAAA,IAAI,KAAA,CAAM,aAAa,GAAA,EAAK;AAC1B,UAAA,IAAA,CAAK,QAAA,CAAS,OAAO,GAAG,CAAA;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA;AACtC,IAAA,IAAI,MAAA,IAAU,MAAA,CAAO,SAAA,GAAY,GAAA,EAAK;AACpC,MAAA,OAAO,MAAA,CAAO,OAAA;AAAA,IAChB;AAEA,IAAA,MAAM,UAAU,IAAA,CAAK,SAAA,CAAU,YAAY,WAAW,CAAA,CAAE,MAAM,CAAA,KAAA,KAAS;AACrE,MAAA,IAAI,KAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA,EAAG,YAAY,OAAA,EAAS;AACjD,QAAA,IAAA,CAAK,QAAA,CAAS,OAAO,KAAK,CAAA;AAAA,MAC5B;AACA,MAAA,MAAM,KAAA;AAAA,IACR,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,KAAA,EAAO;AAAA,MACvB,OAAA;AAAA,MACA,SAAA,EAAW,MAAM,IAAA,CAAK;AAAA,KACvB,CAAA;AAED,IAAA,OAAO,OAAA;AAAA,EACT;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultUserInfoService.cjs.js","sources":["../../../src/entrypoints/userInfo/DefaultUserInfoService.ts"],"sourcesContent":["/*\n * Copyright 2024 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 UserInfoService,\n BackstageUserInfo,\n DiscoveryService,\n BackstageCredentials,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { decodeJwt } from 'jose';\nimport { toInternalBackstageCredentials } from '../auth/helpers';\n\nexport type Options = {\n discovery: DiscoveryService;\n};\n\nexport class DefaultUserInfoService implements UserInfoService {\n private readonly discovery: DiscoveryService;\n\n constructor(options: Options) {\n this.discovery = options.discovery;\n }\n\n async getUserInfo(\n credentials: BackstageCredentials,\n ): Promise<BackstageUserInfo> {\n const internalCredentials = toInternalBackstageCredentials(credentials);\n if (internalCredentials.principal.type !== 'user') {\n throw new Error('Only user credentials are supported');\n }\n if (!internalCredentials.token) {\n throw new Error('User credentials is unexpectedly missing token');\n }\n const { sub: userEntityRef, ent: tokenEnt } = decodeJwt(\n internalCredentials.token,\n );\n\n if (typeof userEntityRef !== 'string') {\n throw new Error('User entity ref must be a string');\n }\n\n let ownershipEntityRefs = tokenEnt;\n\n if (!ownershipEntityRefs) {\n const userInfoResp = await fetch(\n `${await this.discovery.getBaseUrl('auth')}/v1/userinfo`,\n {\n headers: {\n Authorization: `Bearer ${internalCredentials.token}`,\n },\n },\n );\n\n if (!userInfoResp.ok) {\n throw await ResponseError.fromResponse(userInfoResp);\n }\n\n const {\n claims: { ent },\n } = await userInfoResp.json();\n ownershipEntityRefs = ent;\n }\n\n if (!ownershipEntityRefs) {\n throw new Error('Ownership entity refs can not be determined');\n } else if (\n !Array.isArray(ownershipEntityRefs) ||\n ownershipEntityRefs.some(ref => typeof ref !== 'string')\n ) {\n throw new Error('Ownership entity refs must be an array of strings');\n }\n\n return { userEntityRef, ownershipEntityRefs };\n }\n}\n"],"names":["toInternalBackstageCredentials","decodeJwt","ResponseError"],"mappings":";;;;;;AA8BO,MAAM,sBAAA,CAAkD;AAAA,EAC5C,SAAA;AAAA,EAEjB,YAAY,OAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,YACJ,WAAA,EAC4B;AAC5B,IAAA,MAAM,mBAAA,GAAsBA,uCAA+B,WAAW,CAAA;AACtE,IAAA,IAAI,mBAAA,CAAoB,SAAA,CAAU,IAAA,KAAS,MAAA,EAAQ;AACjD,MAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,IACvD;AACA,IAAA,IAAI,CAAC,oBAAoB,KAAA,EAAO;AAC9B,MAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,IAClE;AACA,IAAA,MAAM,EAAE,GAAA,EAAK,aAAA,EAAe,GAAA,EAAK,UAAS,GAAIC,cAAA;AAAA,MAC5C,mBAAA,CAAoB;AAAA,KACtB;AAEA,IAAA,IAAI,OAAO,kBAAkB,QAAA,EAAU;AACrC,MAAA,MAAM,IAAI,MAAM,kCAAkC,CAAA;AAAA,IACpD;AAEA,IAAA,IAAI,mBAAA,GAAsB,QAAA;AAE1B,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,MAAM,eAAe,MAAM,KAAA;AAAA,QACzB,GAAG,MAAM,IAAA,CAAK,SAAA,CAAU,UAAA,CAAW,MAAM,CAAC,CAAA,YAAA,CAAA;AAAA,QAC1C;AAAA,UACE,OAAA,EAAS;AAAA,YACP,aAAA,EAAe,CAAA,OAAA,EAAU,mBAAA,CAAoB,KAAK,CAAA;AAAA;AACpD;AACF,OACF;AAEA,MAAA,IAAI,CAAC,aAAa,EAAA,EAAI;AACpB,QAAA,MAAM,MAAMC,oBAAA,CAAc,YAAA,CAAa,YAAY,CAAA;AAAA,MACrD;AAEA,MAAA,MAAM;AAAA,QACJ,MAAA,EAAQ,EAAE,GAAA;AAAI,OAChB,GAAI,MAAM,YAAA,CAAa,IAAA,EAAK;AAC5B,MAAA,mBAAA,GAAsB,GAAA;AAAA,IACxB;AAEA,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,IAC/D,CAAA,MAAA,IACE,CAAC,KAAA,CAAM,OAAA,CAAQ,mBAAmB,CAAA,IAClC,mBAAA,CAAoB,IAAA,CAAK,CAAA,GAAA,KAAO,OAAO,GAAA,KAAQ,QAAQ,CAAA,EACvD;AACA,MAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,IACrE;AAEA,IAAA,OAAO,EAAE,eAAe,mBAAA,EAAoB;AAAA,EAC9C;AACF;;;;"}
1
+ {"version":3,"file":"DefaultUserInfoService.cjs.js","sources":["../../../src/entrypoints/userInfo/DefaultUserInfoService.ts"],"sourcesContent":["/*\n * Copyright 2024 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 UserInfoService,\n BackstageUserInfo,\n DiscoveryService,\n BackstageCredentials,\n} from '@backstage/backend-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { decodeJwt } from 'jose';\nimport { toInternalBackstageCredentials } from '../auth/helpers';\n\nexport type Options = {\n discovery: DiscoveryService;\n};\n\nexport class DefaultUserInfoService implements UserInfoService {\n private readonly discovery: DiscoveryService;\n\n constructor(options: Options) {\n this.discovery = options.discovery;\n }\n\n async getUserInfo(\n credentials: BackstageCredentials,\n ): Promise<BackstageUserInfo> {\n const internalCredentials = toInternalBackstageCredentials(credentials);\n if (internalCredentials.principal.type !== 'user') {\n throw new Error('Only user credentials are supported');\n }\n if (!internalCredentials.token) {\n throw new Error('User credentials is unexpectedly missing token');\n }\n const { sub: userEntityRef, ent: tokenEnt } = decodeJwt(\n internalCredentials.token,\n );\n\n if (typeof userEntityRef !== 'string') {\n throw new Error('User entity ref must be a string');\n }\n\n let ownershipEntityRefs = tokenEnt;\n\n if (!ownershipEntityRefs) {\n const userInfoResp = await fetch(\n `${await this.discovery.getBaseUrl('auth')}/v1/userinfo`,\n {\n headers: {\n Authorization: `Bearer ${internalCredentials.token}`,\n },\n },\n );\n\n if (!userInfoResp.ok) {\n throw await ResponseError.fromResponse(userInfoResp);\n }\n\n const {\n claims: { ent },\n } = await userInfoResp.json();\n ownershipEntityRefs = ent;\n }\n\n if (!ownershipEntityRefs) {\n throw new Error('Ownership entity refs can not be determined');\n } else if (\n !Array.isArray(ownershipEntityRefs) ||\n ownershipEntityRefs.some(ref => typeof ref !== 'string')\n ) {\n throw new Error('Ownership entity refs must be an array of strings');\n }\n\n return { userEntityRef, ownershipEntityRefs };\n }\n}\n"],"names":["toInternalBackstageCredentials","decodeJwt","ResponseError"],"mappings":";;;;;;AA8BO,MAAM,sBAAA,CAAkD;AAAA,EAC5C,SAAA;AAAA,EAEjB,YAAY,OAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,YACJ,WAAA,EAC4B;AAC5B,IAAA,MAAM,mBAAA,GAAsBA,uCAA+B,WAAW,CAAA;AACtE,IAAA,IAAI,mBAAA,CAAoB,SAAA,CAAU,IAAA,KAAS,MAAA,EAAQ;AACjD,MAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,IACvD;AACA,IAAA,IAAI,CAAC,oBAAoB,KAAA,EAAO;AAC9B,MAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,IAClE;AACA,IAAA,MAAM,EAAE,GAAA,EAAK,aAAA,EAAe,GAAA,EAAK,UAAS,GAAIC,cAAA;AAAA,MAC5C,mBAAA,CAAoB;AAAA,KACtB;AAEA,IAAA,IAAI,OAAO,kBAAkB,QAAA,EAAU;AACrC,MAAA,MAAM,IAAI,MAAM,kCAAkC,CAAA;AAAA,IACpD;AAEA,IAAA,IAAI,mBAAA,GAAsB,QAAA;AAE1B,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,MAAM,eAAe,MAAM,KAAA;AAAA,QACzB,GAAG,MAAM,IAAA,CAAK,SAAA,CAAU,UAAA,CAAW,MAAM,CAAC,CAAA,YAAA,CAAA;AAAA,QAC1C;AAAA,UACE,OAAA,EAAS;AAAA,YACP,aAAA,EAAe,CAAA,OAAA,EAAU,mBAAA,CAAoB,KAAK,CAAA;AAAA;AACpD;AACF,OACF;AAEA,MAAA,IAAI,CAAC,aAAa,EAAA,EAAI;AACpB,QAAA,MAAM,MAAMC,oBAAA,CAAc,YAAA,CAAa,YAAY,CAAA;AAAA,MACrD;AAEA,MAAA,MAAM;AAAA,QACJ,MAAA,EAAQ,EAAE,GAAA;AAAI,OAChB,GAAI,MAAM,YAAA,CAAa,IAAA,EAAK;AAC5B,MAAA,mBAAA,GAAsB,GAAA;AAAA,IACxB;AAEA,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,IAC/D,CAAA,MAAA,IACE,CAAC,KAAA,CAAM,OAAA,CAAQ,mBAAmB,CAAA,IAClC,mBAAA,CAAoB,IAAA,CAAK,CAAA,GAAA,KAAO,OAAO,GAAA,KAAQ,QAAQ,CAAA,EACvD;AACA,MAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,IACrE;AAEA,IAAA,OAAO,EAAE,eAAe,mBAAA,EAAoB;AAAA,EAC9C;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"userInfoServiceFactory.cjs.js","sources":["../../../src/entrypoints/userInfo/userInfoServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 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 createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport {\n CachedUserInfoService,\n UserInfoCacheEntry,\n} from './CachedUserInfoService';\nimport { DefaultUserInfoService } from './DefaultUserInfoService';\n\n/**\n * Authenticated user information retrieval.\n *\n * See {@link @backstage/code-plugin-api#UserInfoService}\n * and {@link https://backstage.io/docs/backend-system/core-services/user-info | the service docs}\n * for more information.\n *\n * @public\n */\nexport const userInfoServiceFactory = createServiceFactory({\n service: coreServices.userInfo,\n deps: {\n discovery: coreServices.discovery,\n },\n createRootContext() {\n return new Map<string, UserInfoCacheEntry>();\n },\n async factory({ discovery }, entries) {\n return new CachedUserInfoService(\n new DefaultUserInfoService({ discovery }),\n { entries },\n );\n },\n});\n"],"names":["createServiceFactory","coreServices","CachedUserInfoService","DefaultUserInfoService"],"mappings":";;;;;;AAmCO,MAAM,yBAAyBA,qCAAA,CAAqB;AAAA,EACzD,SAASC,6BAAA,CAAa,QAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,WAAWA,6BAAA,CAAa;AAAA,GAC1B;AAAA,EACA,iBAAA,GAAoB;AAClB,IAAA,2BAAW,GAAA,EAAgC;AAAA,EAC7C,CAAA;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,SAAA,IAAa,OAAA,EAAS;AACpC,IAAA,OAAO,IAAIC,2CAAA;AAAA,MACT,IAAIC,6CAAA,CAAuB,EAAE,SAAA,EAAW,CAAA;AAAA,MACxC,EAAE,OAAA;AAAQ,KACZ;AAAA,EACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"userInfoServiceFactory.cjs.js","sources":["../../../src/entrypoints/userInfo/userInfoServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 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 createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport {\n CachedUserInfoService,\n UserInfoCacheEntry,\n} from './CachedUserInfoService';\nimport { DefaultUserInfoService } from './DefaultUserInfoService';\n\n/**\n * Authenticated user information retrieval.\n *\n * See {@link @backstage/code-plugin-api#UserInfoService}\n * and {@link https://backstage.io/docs/backend-system/core-services/user-info | the service docs}\n * for more information.\n *\n * @public\n */\nexport const userInfoServiceFactory = createServiceFactory({\n service: coreServices.userInfo,\n deps: {\n discovery: coreServices.discovery,\n },\n createRootContext() {\n return new Map<string, UserInfoCacheEntry>();\n },\n async factory({ discovery }, entries) {\n return new CachedUserInfoService(\n new DefaultUserInfoService({ discovery }),\n { entries },\n );\n },\n});\n"],"names":["createServiceFactory","coreServices","CachedUserInfoService","DefaultUserInfoService"],"mappings":";;;;;;AAmCO,MAAM,yBAAyBA,qCAAA,CAAqB;AAAA,EACzD,SAASC,6BAAA,CAAa,QAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,WAAWA,6BAAA,CAAa;AAAA,GAC1B;AAAA,EACA,iBAAA,GAAoB;AAClB,IAAA,2BAAW,GAAA,EAAgC;AAAA,EAC7C,CAAA;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,SAAA,IAAa,OAAA,EAAS;AACpC,IAAA,OAAO,IAAIC,2CAAA;AAAA,MACT,IAAIC,6CAAA,CAAuB,EAAE,SAAA,EAAW,CAAA;AAAA,MACxC,EAAE,OAAA;AAAQ,KACZ;AAAA,EACF;AACF,CAAC;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"RateLimitStoreFactory.cjs.js","sources":["../../src/lib/RateLimitStoreFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { Config } from '@backstage/config';\nimport type { Store } from 'express-rate-limit';\nimport { RedisStore } from 'rate-limit-redis';\n\n/**\n * Creates a store for `express-rate-limit` based on the configuration.\n *\n * @internal\n */\nexport class RateLimitStoreFactory {\n static create(options: {\n config: Config;\n prefix?: string;\n }): Store | undefined {\n const { config, prefix } = options;\n const store = config.getOptionalConfig('backend.rateLimit.store');\n if (!store) {\n return undefined;\n }\n const type = store.getString('type');\n switch (type) {\n case 'redis':\n return this.redis({ store, prefix });\n case 'memory':\n default:\n return undefined;\n }\n }\n\n private static redis(options: { store: Config; prefix?: string }): Store {\n const { store, prefix } = options;\n const connectionString = store.getString('connection');\n const KeyvRedis = require('@keyv/redis').default;\n const keyv = new KeyvRedis(connectionString);\n return new RedisStore({\n prefix,\n sendCommand: async (...args: string[]) => {\n const client = await keyv.getClient();\n return client.sendCommand(args);\n },\n });\n }\n}\n"],"names":["RedisStore"],"mappings":";;;;AAwBO,MAAM,qBAAA,CAAsB;AAAA,EACjC,OAAO,OAAO,OAAA,EAGQ;AACpB,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAO,GAAI,OAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,yBAAyB,CAAA;AAChE,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,SAAA,CAAU,MAAM,CAAA;AACnC,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,OAAA;AACH,QAAA,OAAO,IAAA,CAAK,KAAA,CAAM,EAAE,KAAA,EAAO,QAAQ,CAAA;AAAA,MACrC,KAAK,QAAA;AAAA,MACL;AACE,QAAA,OAAO,MAAA;AAAA;AACX,EACF;AAAA,EAEA,OAAe,MAAM,OAAA,EAAoD;AACvE,IAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAO,GAAI,OAAA;AAC1B,IAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,SAAA,CAAU,YAAY,CAAA;AACrD,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,aAAa,CAAA,CAAE,OAAA;AACzC,IAAA,MAAM,IAAA,GAAO,IAAI,SAAA,CAAU,gBAAgB,CAAA;AAC3C,IAAA,OAAO,IAAIA,yBAAA,CAAW;AAAA,MACpB,MAAA;AAAA,MACA,WAAA,EAAa,UAAU,IAAA,KAAmB;AACxC,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,EAAU;AACpC,QAAA,OAAO,MAAA,CAAO,YAAY,IAAI,CAAA;AAAA,MAChC;AAAA,KACD,CAAA;AAAA,EACH;AACF;;;;"}
1
+ {"version":3,"file":"RateLimitStoreFactory.cjs.js","sources":["../../src/lib/RateLimitStoreFactory.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { Config } from '@backstage/config';\nimport type { Store } from 'express-rate-limit';\nimport { RedisStore } from 'rate-limit-redis';\n\n/**\n * Creates a store for `express-rate-limit` based on the configuration.\n *\n * @internal\n */\nexport class RateLimitStoreFactory {\n static create(options: {\n config: Config;\n prefix?: string;\n }): Store | undefined {\n const { config, prefix } = options;\n const store = config.getOptionalConfig('backend.rateLimit.store');\n if (!store) {\n return undefined;\n }\n const type = store.getString('type');\n switch (type) {\n case 'redis':\n return this.redis({ store, prefix });\n case 'memory':\n default:\n return undefined;\n }\n }\n\n private static redis(options: { store: Config; prefix?: string }): Store {\n const { store, prefix } = options;\n const connectionString = store.getString('connection');\n const KeyvRedis = require('@keyv/redis').default;\n const keyv = new KeyvRedis(connectionString);\n return new RedisStore({\n prefix,\n sendCommand: async (...args: string[]) => {\n const client = await keyv.getClient();\n return client.sendCommand(args);\n },\n });\n }\n}\n"],"names":["RedisStore"],"mappings":";;;;AAwBO,MAAM,qBAAA,CAAsB;AAAA,EACjC,OAAO,OAAO,OAAA,EAGQ;AACpB,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAO,GAAI,OAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,yBAAyB,CAAA;AAChE,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,SAAA,CAAU,MAAM,CAAA;AACnC,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,OAAA;AACH,QAAA,OAAO,IAAA,CAAK,KAAA,CAAM,EAAE,KAAA,EAAO,QAAQ,CAAA;AAAA,MACrC,KAAK,QAAA;AAAA,MACL;AACE,QAAA,OAAO,MAAA;AAAA;AACX,EACF;AAAA,EAEA,OAAe,MAAM,OAAA,EAAoD;AACvE,IAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAO,GAAI,OAAA;AAC1B,IAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,SAAA,CAAU,YAAY,CAAA;AACrD,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,aAAa,CAAA,CAAE,OAAA;AACzC,IAAA,MAAM,IAAA,GAAO,IAAI,SAAA,CAAU,gBAAgB,CAAA;AAC3C,IAAA,OAAO,IAAIA,yBAAA,CAAW;AAAA,MACpB,MAAA;AAAA,MACA,WAAA,EAAa,UAAU,IAAA,KAAmB;AACxC,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,EAAU;AACpC,QAAA,OAAO,MAAA,CAAO,YAAY,IAAI,CAAA;AAAA,MAChC;AAAA,KACD,CAAA;AAAA,EACH;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"escapeRegExp.cjs.js","sources":["../../src/lib/escapeRegExp.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 * Escapes a given string to be used inside a RegExp.\n *\n * Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nexport const escapeRegExp = (text: string) => {\n return text.replace(/[.*+?^${}(\\)|[\\]\\\\]/g, '\\\\$&');\n};\n"],"names":[],"mappings":";;AAqBO,MAAM,YAAA,GAAe,CAAC,IAAA,KAAiB;AAC5C,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,sBAAA,EAAwB,MAAM,CAAA;AACpD;;;;"}
1
+ {"version":3,"file":"escapeRegExp.cjs.js","sources":["../../src/lib/escapeRegExp.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 * Escapes a given string to be used inside a RegExp.\n *\n * Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nexport const escapeRegExp = (text: string) => {\n return text.replace(/[.*+?^${}(\\)|[\\]\\\\]/g, '\\\\$&');\n};\n"],"names":[],"mappings":";;AAqBO,MAAM,YAAA,GAAe,CAAC,IAAA,KAAiB;AAC5C,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,sBAAA,EAAwB,MAAM,CAAA;AACpD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"rateLimitMiddleware.cjs.js","sources":["../../src/lib/rateLimitMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { RequestHandler } from 'express';\nimport { ipKeyGenerator, rateLimit, Store } from 'express-rate-limit';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\n\nexport const rateLimitMiddleware = (options: {\n store?: Store;\n config?: Config;\n}): RequestHandler => {\n const { store, config } = options;\n let windowMs: number = 60000;\n if (config && config.has('window')) {\n const windowDuration = readDurationFromConfig(config, {\n key: 'window',\n });\n windowMs = durationToMilliseconds(windowDuration);\n }\n const limit = config?.getOptionalNumber('incomingRequestLimit');\n const ipAllowList = config?.getOptionalStringArray('ipAllowList') ?? [\n '127.0.0.1',\n '0:0:0:0:0:0:0:1',\n '::1',\n ];\n const skipSuccessfulRequests = config?.getOptionalBoolean(\n 'skipSuccessfulRequests',\n );\n const skipFailedRequests = config?.getOptionalBoolean('skipFailedRequests');\n const passOnStoreError = config?.getOptionalBoolean('passOnStoreError');\n\n return rateLimit({\n windowMs,\n limit,\n skipSuccessfulRequests,\n message: {\n error: {\n name: 'Error',\n message: `Too many requests, please try again later`,\n },\n response: {\n statusCode: 429,\n },\n },\n statusCode: 429,\n skipFailedRequests,\n passOnStoreError: passOnStoreError,\n keyGenerator(req, _res): string {\n // `ipKeyGenerator` normalizes the address before it is used as a rate\n // limiting key. This is required by express-rate-limit 8.x, which rejects\n // key generators that reference `req.ip` directly, as a naive IPv6 key\n // would let clients trivially bypass the limit by rotating addresses\n // within their allotted block.\n const ip = req.ip ?? req.socket.remoteAddress;\n return ip ? ipKeyGenerator(ip) : '';\n },\n skip: (req, _res) => {\n return (\n Boolean(req.ip && ipAllowList.includes(req.ip)) ||\n Boolean(\n req.socket.remoteAddress &&\n ipAllowList.includes(req.socket.remoteAddress),\n )\n );\n },\n validate: {\n trustProxy: false,\n },\n store,\n });\n};\n"],"names":["config","readDurationFromConfig","durationToMilliseconds","rateLimit","ipKeyGenerator"],"mappings":";;;;;;AAoBO,MAAM,mBAAA,GAAsB,CAAC,OAAA,KAGd;AACpB,EAAA,MAAM,EAAE,KAAA,UAAOA,QAAA,EAAO,GAAI,OAAA;AAC1B,EAAA,IAAI,QAAA,GAAmB,GAAA;AACvB,EAAA,IAAIA,QAAA,IAAUA,QAAA,CAAO,GAAA,CAAI,QAAQ,CAAA,EAAG;AAClC,IAAA,MAAM,cAAA,GAAiBC,8BAAuBD,QAAA,EAAQ;AAAA,MACpD,GAAA,EAAK;AAAA,KACN,CAAA;AACD,IAAA,QAAA,GAAWE,6BAAuB,cAAc,CAAA;AAAA,EAClD;AACA,EAAA,MAAM,KAAA,GAAQF,QAAA,EAAQ,iBAAA,CAAkB,sBAAsB,CAAA;AAC9D,EAAA,MAAM,WAAA,GAAcA,QAAA,EAAQ,sBAAA,CAAuB,aAAa,CAAA,IAAK;AAAA,IACnE,WAAA;AAAA,IACA,iBAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,yBAAyBA,QAAA,EAAQ,kBAAA;AAAA,IACrC;AAAA,GACF;AACA,EAAA,MAAM,kBAAA,GAAqBA,QAAA,EAAQ,kBAAA,CAAmB,oBAAoB,CAAA;AAC1E,EAAA,MAAM,gBAAA,GAAmBA,QAAA,EAAQ,kBAAA,CAAmB,kBAAkB,CAAA;AAEtE,EAAA,OAAOG,0BAAA,CAAU;AAAA,IACf,QAAA;AAAA,IACA,KAAA;AAAA,IACA,sBAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACP,KAAA,EAAO;AAAA,QACL,IAAA,EAAM,OAAA;AAAA,QACN,OAAA,EAAS,CAAA,yCAAA;AAAA,OACX;AAAA,MACA,QAAA,EAAU;AAAA,QACR,UAAA,EAAY;AAAA;AACd,KACF;AAAA,IACA,UAAA,EAAY,GAAA;AAAA,IACZ,kBAAA;AAAA,IACA,gBAAA;AAAA,IACA,YAAA,CAAa,KAAK,IAAA,EAAc;AAM9B,MAAA,MAAM,EAAA,GAAK,GAAA,CAAI,EAAA,IAAM,GAAA,CAAI,MAAA,CAAO,aAAA;AAChC,MAAA,OAAO,EAAA,GAAKC,+BAAA,CAAe,EAAE,CAAA,GAAI,EAAA;AAAA,IACnC,CAAA;AAAA,IACA,IAAA,EAAM,CAAC,GAAA,EAAK,IAAA,KAAS;AACnB,MAAA,OACE,OAAA,CAAQ,IAAI,EAAA,IAAM,WAAA,CAAY,SAAS,GAAA,CAAI,EAAE,CAAC,CAAA,IAC9C,OAAA;AAAA,QACE,IAAI,MAAA,CAAO,aAAA,IACT,YAAY,QAAA,CAAS,GAAA,CAAI,OAAO,aAAa;AAAA,OACjD;AAAA,IAEJ,CAAA;AAAA,IACA,QAAA,EAAU;AAAA,MACR,UAAA,EAAY;AAAA,KACd;AAAA,IACA;AAAA,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"rateLimitMiddleware.cjs.js","sources":["../../src/lib/rateLimitMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { RequestHandler } from 'express';\nimport { ipKeyGenerator, rateLimit, Store } from 'express-rate-limit';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\n\nexport const rateLimitMiddleware = (options: {\n store?: Store;\n config?: Config;\n}): RequestHandler => {\n const { store, config } = options;\n let windowMs: number = 60000;\n if (config && config.has('window')) {\n const windowDuration = readDurationFromConfig(config, {\n key: 'window',\n });\n windowMs = durationToMilliseconds(windowDuration);\n }\n const limit = config?.getOptionalNumber('incomingRequestLimit');\n const ipAllowList = config?.getOptionalStringArray('ipAllowList') ?? [\n '127.0.0.1',\n '0:0:0:0:0:0:0:1',\n '::1',\n ];\n const skipSuccessfulRequests = config?.getOptionalBoolean(\n 'skipSuccessfulRequests',\n );\n const skipFailedRequests = config?.getOptionalBoolean('skipFailedRequests');\n const passOnStoreError = config?.getOptionalBoolean('passOnStoreError');\n\n return rateLimit({\n windowMs,\n limit,\n skipSuccessfulRequests,\n message: {\n error: {\n name: 'Error',\n message: `Too many requests, please try again later`,\n },\n response: {\n statusCode: 429,\n },\n },\n statusCode: 429,\n skipFailedRequests,\n passOnStoreError: passOnStoreError,\n keyGenerator(req, _res): string {\n // `ipKeyGenerator` normalizes the address before it is used as a rate\n // limiting key. This is required by express-rate-limit 8.x, which rejects\n // key generators that reference `req.ip` directly, as a naive IPv6 key\n // would let clients trivially bypass the limit by rotating addresses\n // within their allotted block.\n const ip = req.ip ?? req.socket.remoteAddress;\n return ip ? ipKeyGenerator(ip) : '';\n },\n skip: (req, _res) => {\n return (\n Boolean(req.ip && ipAllowList.includes(req.ip)) ||\n Boolean(\n req.socket.remoteAddress &&\n ipAllowList.includes(req.socket.remoteAddress),\n )\n );\n },\n validate: {\n trustProxy: false,\n },\n store,\n });\n};\n"],"names":["config","readDurationFromConfig","durationToMilliseconds","rateLimit","ipKeyGenerator"],"mappings":";;;;;;AAoBO,MAAM,mBAAA,GAAsB,CAAC,OAAA,KAGd;AACpB,EAAA,MAAM,EAAE,KAAA,UAAOA,QAAA,EAAO,GAAI,OAAA;AAC1B,EAAA,IAAI,QAAA,GAAmB,GAAA;AACvB,EAAA,IAAIA,QAAA,IAAUA,QAAA,CAAO,GAAA,CAAI,QAAQ,CAAA,EAAG;AAClC,IAAA,MAAM,cAAA,GAAiBC,8BAAuBD,QAAA,EAAQ;AAAA,MACpD,GAAA,EAAK;AAAA,KACN,CAAA;AACD,IAAA,QAAA,GAAWE,6BAAuB,cAAc,CAAA;AAAA,EAClD;AACA,EAAA,MAAM,KAAA,GAAQF,QAAA,EAAQ,iBAAA,CAAkB,sBAAsB,CAAA;AAC9D,EAAA,MAAM,WAAA,GAAcA,QAAA,EAAQ,sBAAA,CAAuB,aAAa,CAAA,IAAK;AAAA,IACnE,WAAA;AAAA,IACA,iBAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,yBAAyBA,QAAA,EAAQ,kBAAA;AAAA,IACrC;AAAA,GACF;AACA,EAAA,MAAM,kBAAA,GAAqBA,QAAA,EAAQ,kBAAA,CAAmB,oBAAoB,CAAA;AAC1E,EAAA,MAAM,gBAAA,GAAmBA,QAAA,EAAQ,kBAAA,CAAmB,kBAAkB,CAAA;AAEtE,EAAA,OAAOG,0BAAA,CAAU;AAAA,IACf,QAAA;AAAA,IACA,KAAA;AAAA,IACA,sBAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACP,KAAA,EAAO;AAAA,QACL,IAAA,EAAM,OAAA;AAAA,QACN,OAAA,EAAS,CAAA,yCAAA;AAAA,OACX;AAAA,MACA,QAAA,EAAU;AAAA,QACR,UAAA,EAAY;AAAA;AACd,KACF;AAAA,IACA,UAAA,EAAY,GAAA;AAAA,IACZ,kBAAA;AAAA,IACA,gBAAA;AAAA,IACA,YAAA,CAAa,KAAK,IAAA,EAAc;AAM9B,MAAA,MAAM,EAAA,GAAK,GAAA,CAAI,EAAA,IAAM,GAAA,CAAI,MAAA,CAAO,aAAA;AAChC,MAAA,OAAO,EAAA,GAAKC,+BAAA,CAAe,EAAE,CAAA,GAAI,EAAA;AAAA,IACnC,CAAA;AAAA,IACA,IAAA,EAAM,CAAC,GAAA,EAAK,IAAA,KAAS;AACnB,MAAA,OACE,OAAA,CAAQ,IAAI,EAAA,IAAM,WAAA,CAAY,SAAS,GAAA,CAAI,EAAE,CAAC,CAAA,IAC9C,OAAA;AAAA,QACE,IAAI,MAAA,CAAO,aAAA,IACT,YAAY,QAAA,CAAS,GAAA,CAAI,OAAO,aAAa;AAAA,OACjD;AAAA,IAEJ,CAAA;AAAA,IACA,QAAA,EAAU;AAAA,MACR,UAAA,EAAY;AAAA,KACd;AAAA,IACA;AAAA,GACD,CAAA;AACH;;"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = "0.17.9-next.1";
5
+ var version = "0.18.1-next.0";
6
6
  var packageinfo = {
7
7
  version: version};
8
8
 
@@ -1 +1 @@
1
- {"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
1
+ {"version":3,"file":"package.json.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-defaults",
3
- "version": "0.17.9-next.1",
3
+ "version": "0.18.1-next.0",
4
4
  "description": "Backend defaults used by Backstage backend apps",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -226,19 +226,19 @@
226
226
  "@aws-sdk/types": "^3.347.0",
227
227
  "@azure/identity": "^4.0.0",
228
228
  "@azure/storage-blob": "^12.5.0",
229
- "@backstage/backend-app-api": "1.7.4-next.1",
229
+ "@backstage/backend-app-api": "1.7.5-next.0",
230
230
  "@backstage/backend-dev-utils": "0.1.7",
231
- "@backstage/backend-plugin-api": "1.10.1-next.1",
232
- "@backstage/cli-node": "0.3.4",
233
- "@backstage/config": "1.3.9-next.0",
234
- "@backstage/config-loader": "1.11.3-next.0",
235
- "@backstage/errors": "1.3.1",
236
- "@backstage/integration": "2.1.2-next.1",
237
- "@backstage/integration-aws-node": "0.2.2-next.0",
238
- "@backstage/plugin-auth-node": "0.7.5-next.1",
239
- "@backstage/plugin-events-node": "0.4.26-next.0",
240
- "@backstage/plugin-permission-common": "0.9.11-next.0",
241
- "@backstage/plugin-permission-node": "0.11.4-next.1",
231
+ "@backstage/backend-plugin-api": "1.10.2-next.0",
232
+ "@backstage/cli-node": "0.3.5-next.0",
233
+ "@backstage/config": "1.3.10-next.0",
234
+ "@backstage/config-loader": "1.11.4-next.0",
235
+ "@backstage/errors": "1.3.2-next.0",
236
+ "@backstage/integration": "2.1.3-next.0",
237
+ "@backstage/integration-aws-node": "0.2.3-next.0",
238
+ "@backstage/plugin-auth-node": "0.7.7-next.0",
239
+ "@backstage/plugin-events-node": "0.4.27-next.0",
240
+ "@backstage/plugin-permission-common": "0.9.12-next.0",
241
+ "@backstage/plugin-permission-node": "0.11.5-next.0",
242
242
  "@backstage/types": "1.2.2",
243
243
  "@google-cloud/storage": "^7.0.0",
244
244
  "@keyv/memcache": "^2.0.1",
@@ -294,13 +294,14 @@
294
294
  },
295
295
  "devDependencies": {
296
296
  "@aws-sdk/util-stream-node": "^3.350.0",
297
- "@backstage/backend-test-utils": "1.11.7-next.1",
298
- "@backstage/cli": "0.36.6-next.1",
297
+ "@backstage/backend-test-utils": "1.11.8-next.0",
298
+ "@backstage/cli": "0.36.7-next.0",
299
299
  "@google-cloud/cloud-sql-connector": "^1.4.0",
300
300
  "@types/archiver": "^7.0.0",
301
301
  "@types/base64-stream": "^1.0.2",
302
302
  "@types/compression": "^1.7.5",
303
303
  "@types/concat-stream": "^2.0.0",
304
+ "@types/cookie": "^0.6.0",
304
305
  "@types/http-errors": "^2.0.0",
305
306
  "@types/is-glob": "^4.0.2",
306
307
  "@types/node-forge": "^1.3.0",