@backstage/backend-defaults 0.18.0 → 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 (126) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/CreateBackend.cjs.js.map +1 -1
  3. package/dist/PackageDiscoveryService.cjs.js.map +1 -1
  4. package/dist/alpha/entrypoints/actions/DefaultActionsService.cjs.js.map +1 -1
  5. package/dist/alpha/entrypoints/actions/actionsServiceFactory.cjs.js.map +1 -1
  6. package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +1 -1
  7. package/dist/alpha/entrypoints/actionsRegistry/actionFilters.cjs.js.map +1 -1
  8. package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +1 -1
  9. package/dist/alpha/entrypoints/instanceMetadata/instanceMetadataServiceFactory.cjs.js.map +1 -1
  10. package/dist/alpha/entrypoints/metrics/DefaultMetricsService.cjs.js.map +1 -1
  11. package/dist/alpha/entrypoints/metrics/metricsServiceFactory.cjs.js.map +1 -1
  12. package/dist/alpha/entrypoints/tracing/DefaultTracingService.cjs.js.map +1 -1
  13. package/dist/alpha/entrypoints/tracing/tracingServiceFactory.cjs.js.map +1 -1
  14. package/dist/discoveryFeatureLoader.cjs.js.map +1 -1
  15. package/dist/entrypoints/auditor/DefaultAuditorService.cjs.js.map +1 -1
  16. package/dist/entrypoints/auditor/WinstonRootAuditorService.cjs.js.map +1 -1
  17. package/dist/entrypoints/auditor/auditorServiceFactory.cjs.js.map +1 -1
  18. package/dist/entrypoints/auditor/utils.cjs.js.map +1 -1
  19. package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -1
  20. package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -1
  21. package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -1
  22. package/dist/entrypoints/auth/external/ExternalAuthTokenHandler.cjs.js.map +1 -1
  23. package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -1
  24. package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -1
  25. package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -1
  26. package/dist/entrypoints/auth/external/static.cjs.js.map +1 -1
  27. package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
  28. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -1
  29. package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -1
  30. package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -1
  31. package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -1
  32. package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -1
  33. package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -1
  34. package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -1
  35. package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -1
  36. package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -1
  37. package/dist/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.cjs.js.map +1 -1
  38. package/dist/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.cjs.js.map +1 -1
  39. package/dist/entrypoints/cache/types.cjs.js.map +1 -1
  40. package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -1
  41. package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -1
  42. package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -1
  43. package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -1
  44. package/dist/entrypoints/database/connectors/postgres.cjs.js +2 -0
  45. package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
  46. package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -1
  47. package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -1
  48. package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -1
  49. package/dist/entrypoints/discovery/SrvResolvers.cjs.js.map +1 -1
  50. package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -1
  51. package/dist/entrypoints/discovery/parsing.cjs.js.map +1 -1
  52. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -1
  53. package/dist/entrypoints/httpRouter/http/createAuthIntegrationRouter.cjs.js.map +1 -1
  54. package/dist/entrypoints/httpRouter/http/createCookieAuthRefreshMiddleware.cjs.js.map +1 -1
  55. package/dist/entrypoints/httpRouter/http/createCredentialsBarrier.cjs.js.map +1 -1
  56. package/dist/entrypoints/httpRouter/http/createLifecycleMiddleware.cjs.js.map +1 -1
  57. package/dist/entrypoints/httpRouter/http/createRateLimitMiddleware.cjs.js.map +1 -1
  58. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
  59. package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -1
  60. package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -1
  61. package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -1
  62. package/dist/entrypoints/permissionsRegistry/permissionsRegistryServiceFactory.cjs.js.map +1 -1
  63. package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -1
  64. package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -1
  65. package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -1
  66. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -1
  67. package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -1
  68. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -1
  69. package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -1
  70. package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -1
  71. package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -1
  72. package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -1
  73. package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -1
  74. package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -1
  75. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
  76. package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -1
  77. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -1
  78. package/dist/entrypoints/rootLogger/config.cjs.js.map +1 -1
  79. package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -1
  80. package/dist/entrypoints/rootLogger/types.cjs.js.map +1 -1
  81. package/dist/entrypoints/rootLogger/utils.cjs.js.map +1 -1
  82. package/dist/entrypoints/rootSystemMetadata/lib/DefaultRootSystemMetadataService.cjs.js.map +1 -1
  83. package/dist/entrypoints/rootSystemMetadata/rootSystemMetadataServiceFactory.cjs.js.map +1 -1
  84. package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -1
  85. package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -1
  86. package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -1
  87. package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -1
  88. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -1
  89. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -1
  90. package/dist/entrypoints/scheduler/lib/TaskStatePoller.cjs.js.map +1 -1
  91. package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -1
  92. package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
  93. package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -1
  94. package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -1
  95. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -1
  96. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -1
  97. package/dist/entrypoints/urlReader/lib/AzureBlobStorageUrlReader.cjs.js.map +1 -1
  98. package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -1
  99. package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -1
  100. package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -1
  101. package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -1
  102. package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -1
  103. package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -1
  104. package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -1
  105. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
  106. package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -1
  107. package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -1
  108. package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -1
  109. package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -1
  110. package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -1
  111. package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -1
  112. package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -1
  113. package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -1
  114. package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -1
  115. package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -1
  116. package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
  117. package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -1
  118. package/dist/entrypoints/userInfo/CachedUserInfoService.cjs.js.map +1 -1
  119. package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -1
  120. package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -1
  121. package/dist/lib/RateLimitStoreFactory.cjs.js.map +1 -1
  122. package/dist/lib/escapeRegExp.cjs.js.map +1 -1
  123. package/dist/lib/rateLimitMiddleware.cjs.js.map +1 -1
  124. package/dist/package.json.cjs.js +1 -1
  125. package/dist/package.json.cjs.js.map +1 -1
  126. package/package.json +17 -17
@@ -1 +1 @@
1
- {"version":3,"file":"createHttpServer.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/createHttpServer.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 * as http from 'node:http';\nimport * as https from 'node:https';\nimport { RequestListener } from 'node:http';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { HttpServerOptions, ExtendedHttpServer } from './types';\nimport { getGeneratedCertificate } from './getGeneratedCertificate';\n\n/**\n * Creates a Node.js HTTP or HTTPS server instance.\n *\n * @public\n */\nexport async function createHttpServer(\n listener: RequestListener,\n options: HttpServerOptions,\n deps: { logger: LoggerService },\n): Promise<ExtendedHttpServer> {\n const server = await createServer(listener, options, deps);\n return Object.assign(server, {\n start() {\n return new Promise<void>((resolve, reject) => {\n const handleStartupError = (error: Error) => {\n server.close();\n reject(error);\n };\n\n server.on('error', handleStartupError);\n\n const { host, port } = options.listen;\n server.listen(port, host, () => {\n server.off('error', handleStartupError);\n deps.logger.info(`Listening on ${host}:${port}`);\n resolve();\n });\n });\n },\n\n stop() {\n return new Promise<void>((resolve, reject) => {\n if (process.env.NODE_ENV === 'development') {\n // Ensure that various polling connections are shut down fast in development\n server.closeAllConnections();\n } else {\n server.closeIdleConnections();\n }\n server.close(error => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n },\n\n port() {\n const address = server.address();\n if (typeof address === 'string' || address === null) {\n throw new Error(`Unexpected server address '${address}'`);\n }\n return address.port;\n },\n });\n}\n\nasync function createServer(\n listener: RequestListener,\n options: HttpServerOptions,\n deps: { logger: LoggerService },\n): Promise<http.Server> {\n if (options.https) {\n const { certificate } = options.https;\n if (certificate.type === 'generated') {\n const credentials = await getGeneratedCertificate(\n certificate.hostname,\n deps.logger,\n );\n return https.createServer(credentials, listener);\n }\n return https.createServer(certificate, listener);\n }\n\n return http.createServer(listener);\n}\n"],"names":["getGeneratedCertificate","https","http"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,eAAsB,gBAAA,CACpB,QAAA,EACA,OAAA,EACA,IAAA,EAC6B;AAC7B,EAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,QAAA,EAAU,SAAS,IAAI,CAAA;AACzD,EAAA,OAAO,MAAA,CAAO,OAAO,MAAA,EAAQ;AAAA,IAC3B,KAAA,GAAQ;AACN,MAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC5C,QAAA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAAiB;AAC3C,UAAA,MAAA,CAAO,KAAA,EAAM;AACb,UAAA,MAAA,CAAO,KAAK,CAAA;AAAA,QACd,CAAA;AAEA,QAAA,MAAA,CAAO,EAAA,CAAG,SAAS,kBAAkB,CAAA;AAErC,QAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,OAAA,CAAQ,MAAA;AAC/B,QAAA,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,MAAM;AAC9B,UAAA,MAAA,CAAO,GAAA,CAAI,SAAS,kBAAkB,CAAA;AACtC,UAAA,IAAA,CAAK,OAAO,IAAA,CAAK,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AAC/C,UAAA,OAAA,EAAQ;AAAA,QACV,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC5C,QAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,EAAe;AAE1C,UAAA,MAAA,CAAO,mBAAA,EAAoB;AAAA,QAC7B,CAAA,MAAO;AACL,UAAA,MAAA,CAAO,oBAAA,EAAqB;AAAA,QAC9B;AACA,QAAA,MAAA,CAAO,MAAM,CAAA,KAAA,KAAS;AACpB,UAAA,IAAI,KAAA,EAAO;AACT,YAAA,MAAA,CAAO,KAAK,CAAA;AAAA,UACd,CAAA,MAAO;AACL,YAAA,OAAA,EAAQ;AAAA,UACV;AAAA,QACF,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,MAAM,OAAA,GAAU,OAAO,OAAA,EAAQ;AAC/B,MAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,EAAM;AACnD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,MAC1D;AACA,MAAA,OAAO,OAAA,CAAQ,IAAA;AAAA,IACjB;AAAA,GACD,CAAA;AACH;AAEA,eAAe,YAAA,CACb,QAAA,EACA,OAAA,EACA,IAAA,EACsB;AACtB,EAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,IAAA,MAAM,EAAE,WAAA,EAAY,GAAI,OAAA,CAAQ,KAAA;AAChC,IAAA,IAAI,WAAA,CAAY,SAAS,WAAA,EAAa;AACpC,MAAA,MAAM,cAAc,MAAMA,+CAAA;AAAA,QACxB,WAAA,CAAY,QAAA;AAAA,QACZ,IAAA,CAAK;AAAA,OACP;AACA,MAAA,OAAOC,gBAAA,CAAM,YAAA,CAAa,WAAA,EAAa,QAAQ,CAAA;AAAA,IACjD;AACA,IAAA,OAAOA,gBAAA,CAAM,YAAA,CAAa,WAAA,EAAa,QAAQ,CAAA;AAAA,EACjD;AAEA,EAAA,OAAOC,eAAA,CAAK,aAAa,QAAQ,CAAA;AACnC;;;;"}
1
+ {"version":3,"file":"createHttpServer.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/createHttpServer.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 * as http from 'node:http';\nimport * as https from 'node:https';\nimport { RequestListener } from 'node:http';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { HttpServerOptions, ExtendedHttpServer } from './types';\nimport { getGeneratedCertificate } from './getGeneratedCertificate';\n\n/**\n * Creates a Node.js HTTP or HTTPS server instance.\n *\n * @public\n */\nexport async function createHttpServer(\n listener: RequestListener,\n options: HttpServerOptions,\n deps: { logger: LoggerService },\n): Promise<ExtendedHttpServer> {\n const server = await createServer(listener, options, deps);\n return Object.assign(server, {\n start() {\n return new Promise<void>((resolve, reject) => {\n const handleStartupError = (error: Error) => {\n server.close();\n reject(error);\n };\n\n server.on('error', handleStartupError);\n\n const { host, port } = options.listen;\n server.listen(port, host, () => {\n server.off('error', handleStartupError);\n deps.logger.info(`Listening on ${host}:${port}`);\n resolve();\n });\n });\n },\n\n stop() {\n return new Promise<void>((resolve, reject) => {\n if (process.env.NODE_ENV === 'development') {\n // Ensure that various polling connections are shut down fast in development\n server.closeAllConnections();\n } else {\n server.closeIdleConnections();\n }\n server.close(error => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n },\n\n port() {\n const address = server.address();\n if (typeof address === 'string' || address === null) {\n throw new Error(`Unexpected server address '${address}'`);\n }\n return address.port;\n },\n });\n}\n\nasync function createServer(\n listener: RequestListener,\n options: HttpServerOptions,\n deps: { logger: LoggerService },\n): Promise<http.Server> {\n if (options.https) {\n const { certificate } = options.https;\n if (certificate.type === 'generated') {\n const credentials = await getGeneratedCertificate(\n certificate.hostname,\n deps.logger,\n );\n return https.createServer(credentials, listener);\n }\n return https.createServer(certificate, listener);\n }\n\n return http.createServer(listener);\n}\n"],"names":["getGeneratedCertificate","https","http"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,eAAsB,gBAAA,CACpB,QAAA,EACA,OAAA,EACA,IAAA,EAC6B;AAC7B,EAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,QAAA,EAAU,SAAS,IAAI,CAAA;AACzD,EAAA,OAAO,MAAA,CAAO,OAAO,MAAA,EAAQ;AAAA,IAC3B,KAAA,GAAQ;AACN,MAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC5C,QAAA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAAiB;AAC3C,UAAA,MAAA,CAAO,KAAA,EAAM;AACb,UAAA,MAAA,CAAO,KAAK,CAAA;AAAA,QACd,CAAA;AAEA,QAAA,MAAA,CAAO,EAAA,CAAG,SAAS,kBAAkB,CAAA;AAErC,QAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,OAAA,CAAQ,MAAA;AAC/B,QAAA,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,MAAM;AAC9B,UAAA,MAAA,CAAO,GAAA,CAAI,SAAS,kBAAkB,CAAA;AACtC,UAAA,IAAA,CAAK,OAAO,IAAA,CAAK,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AAC/C,UAAA,OAAA,EAAQ;AAAA,QACV,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC5C,QAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,aAAA,EAAe;AAE1C,UAAA,MAAA,CAAO,mBAAA,EAAoB;AAAA,QAC7B,CAAA,MAAO;AACL,UAAA,MAAA,CAAO,oBAAA,EAAqB;AAAA,QAC9B;AACA,QAAA,MAAA,CAAO,MAAM,CAAA,KAAA,KAAS;AACpB,UAAA,IAAI,KAAA,EAAO;AACT,YAAA,MAAA,CAAO,KAAK,CAAA;AAAA,UACd,CAAA,MAAO;AACL,YAAA,OAAA,EAAQ;AAAA,UACV;AAAA,QACF,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,MAAM,OAAA,GAAU,OAAO,OAAA,EAAQ;AAC/B,MAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,EAAM;AACnD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,MAC1D;AACA,MAAA,OAAO,OAAA,CAAQ,IAAA;AAAA,IACjB;AAAA,GACD,CAAA;AACH;AAEA,eAAe,YAAA,CACb,QAAA,EACA,OAAA,EACA,IAAA,EACsB;AACtB,EAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,IAAA,MAAM,EAAE,WAAA,EAAY,GAAI,OAAA,CAAQ,KAAA;AAChC,IAAA,IAAI,WAAA,CAAY,SAAS,WAAA,EAAa;AACpC,MAAA,MAAM,cAAc,MAAMA,+CAAA;AAAA,QACxB,WAAA,CAAY,QAAA;AAAA,QACZ,IAAA,CAAK;AAAA,OACP;AACA,MAAA,OAAOC,gBAAA,CAAM,YAAA,CAAa,WAAA,EAAa,QAAQ,CAAA;AAAA,IACjD;AACA,IAAA,OAAOA,gBAAA,CAAM,YAAA,CAAa,WAAA,EAAa,QAAQ,CAAA;AAAA,EACjD;AAEA,EAAA,OAAOC,eAAA,CAAK,aAAa,QAAQ,CAAA;AACnC;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"getGeneratedCertificate.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/getGeneratedCertificate.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 fs from 'fs-extra';\nimport { resolve as resolvePath, dirname } from 'node:path';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport forge from 'node-forge';\n\nconst FIVE_DAYS_IN_MS = 5 * 24 * 60 * 60 * 1000;\n\nconst IP_HOSTNAME_REGEX = /:|^\\d+\\.\\d+\\.\\d+\\.\\d+$/;\n\nexport async function getGeneratedCertificate(\n hostname: string,\n logger: LoggerService,\n) {\n const hasModules = await fs.pathExists('node_modules');\n let certPath;\n if (hasModules) {\n certPath = resolvePath(\n 'node_modules/.cache/backstage-backend/dev-cert.pem',\n );\n await fs.ensureDir(dirname(certPath));\n } else {\n certPath = resolvePath('.dev-cert.pem');\n }\n\n if (await fs.pathExists(certPath)) {\n try {\n const cert = await fs.readFile(certPath);\n\n const crt = forge.pki.certificateFromPem(cert.toString());\n const remainingMs = crt.validity.notAfter.getTime() - Date.now();\n if (remainingMs > FIVE_DAYS_IN_MS) {\n logger.info('Using existing self-signed certificate');\n return {\n key: cert,\n cert,\n };\n }\n } catch (error) {\n logger.warn(`Unable to use existing self-signed certificate, ${error}`);\n }\n }\n\n logger.info('Generating new self-signed certificate');\n const newCert = await generateCertificate(hostname);\n await fs.writeFile(certPath, newCert.cert + newCert.key, 'utf8');\n return newCert;\n}\n\nasync function generateCertificate(hostname: string) {\n const attributes = [\n {\n name: 'commonName',\n value: 'dev-cert',\n },\n ];\n\n const sans = [\n {\n type: 2, // DNS\n value: 'localhost',\n },\n {\n type: 2,\n value: 'localhost.localdomain',\n },\n {\n type: 2,\n value: '[::1]',\n },\n {\n type: 7, // IP\n ip: '127.0.0.1',\n },\n {\n type: 7,\n ip: 'fe80::1',\n },\n ];\n\n // Add hostname from backend.baseUrl if it doesn't already exist in our list of SANs\n if (!sans.find(({ value, ip }) => value === hostname || ip === hostname)) {\n sans.push(\n IP_HOSTNAME_REGEX.test(hostname)\n ? {\n type: 7,\n ip: hostname,\n }\n : {\n type: 2,\n value: hostname,\n },\n );\n }\n\n const params = {\n algorithm: 'sha256',\n keySize: 2048,\n days: 30,\n extensions: [\n {\n name: 'keyUsage',\n keyCertSign: true,\n digitalSignature: true,\n nonRepudiation: true,\n keyEncipherment: true,\n dataEncipherment: true,\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n clientAuth: true,\n codeSigning: true,\n timeStamping: true,\n },\n {\n name: 'subjectAltName',\n altNames: sans,\n },\n ],\n };\n\n return new Promise<{ key: string; cert: string }>((resolve, reject) =>\n require('selfsigned').generate(\n attributes,\n params,\n (err: Error, bundle: { private: string; cert: string }) => {\n if (err) {\n reject(err);\n } else {\n resolve({ key: bundle.private, cert: bundle.cert });\n }\n },\n ),\n );\n}\n"],"names":["fs","resolvePath","dirname","forge"],"mappings":"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"}
1
+ {"version":3,"file":"getGeneratedCertificate.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/getGeneratedCertificate.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 fs from 'fs-extra';\nimport { resolve as resolvePath, dirname } from 'node:path';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport forge from 'node-forge';\n\nconst FIVE_DAYS_IN_MS = 5 * 24 * 60 * 60 * 1000;\n\nconst IP_HOSTNAME_REGEX = /:|^\\d+\\.\\d+\\.\\d+\\.\\d+$/;\n\nexport async function getGeneratedCertificate(\n hostname: string,\n logger: LoggerService,\n) {\n const hasModules = await fs.pathExists('node_modules');\n let certPath;\n if (hasModules) {\n certPath = resolvePath(\n 'node_modules/.cache/backstage-backend/dev-cert.pem',\n );\n await fs.ensureDir(dirname(certPath));\n } else {\n certPath = resolvePath('.dev-cert.pem');\n }\n\n if (await fs.pathExists(certPath)) {\n try {\n const cert = await fs.readFile(certPath);\n\n const crt = forge.pki.certificateFromPem(cert.toString());\n const remainingMs = crt.validity.notAfter.getTime() - Date.now();\n if (remainingMs > FIVE_DAYS_IN_MS) {\n logger.info('Using existing self-signed certificate');\n return {\n key: cert,\n cert,\n };\n }\n } catch (error) {\n logger.warn(`Unable to use existing self-signed certificate, ${error}`);\n }\n }\n\n logger.info('Generating new self-signed certificate');\n const newCert = await generateCertificate(hostname);\n await fs.writeFile(certPath, newCert.cert + newCert.key, 'utf8');\n return newCert;\n}\n\nasync function generateCertificate(hostname: string) {\n const attributes = [\n {\n name: 'commonName',\n value: 'dev-cert',\n },\n ];\n\n const sans = [\n {\n type: 2, // DNS\n value: 'localhost',\n },\n {\n type: 2,\n value: 'localhost.localdomain',\n },\n {\n type: 2,\n value: '[::1]',\n },\n {\n type: 7, // IP\n ip: '127.0.0.1',\n },\n {\n type: 7,\n ip: 'fe80::1',\n },\n ];\n\n // Add hostname from backend.baseUrl if it doesn't already exist in our list of SANs\n if (!sans.find(({ value, ip }) => value === hostname || ip === hostname)) {\n sans.push(\n IP_HOSTNAME_REGEX.test(hostname)\n ? {\n type: 7,\n ip: hostname,\n }\n : {\n type: 2,\n value: hostname,\n },\n );\n }\n\n const params = {\n algorithm: 'sha256',\n keySize: 2048,\n days: 30,\n extensions: [\n {\n name: 'keyUsage',\n keyCertSign: true,\n digitalSignature: true,\n nonRepudiation: true,\n keyEncipherment: true,\n dataEncipherment: true,\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n clientAuth: true,\n codeSigning: true,\n timeStamping: true,\n },\n {\n name: 'subjectAltName',\n altNames: sans,\n },\n ],\n };\n\n return new Promise<{ key: string; cert: string }>((resolve, reject) =>\n require('selfsigned').generate(\n attributes,\n params,\n (err: Error, bundle: { private: string; cert: string }) => {\n if (err) {\n reject(err);\n } else {\n resolve({ key: bundle.private, cert: bundle.cert });\n }\n },\n ),\n );\n}\n"],"names":["fs","resolvePath","dirname","forge"],"mappings":";;;;;;;;;;;AAqBA,MAAM,eAAA,GAAkB,CAAA,GAAI,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAE3C,MAAM,iBAAA,GAAoB,wBAAA;AAE1B,eAAsB,uBAAA,CACpB,UACA,MAAA,EACA;AACA,EAAA,MAAM,UAAA,GAAa,MAAMA,mBAAA,CAAG,UAAA,CAAW,cAAc,CAAA;AACrD,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,QAAA,GAAWC,oBAAA;AAAA,MACT;AAAA,KACF;AACA,IAAA,MAAMD,mBAAA,CAAG,SAAA,CAAUE,oBAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,EACtC,CAAA,MAAO;AACL,IAAA,QAAA,GAAWD,qBAAY,eAAe,CAAA;AAAA,EACxC;AAEA,EAAA,IAAI,MAAMD,mBAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AACjC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAMA,mBAAA,CAAG,QAAA,CAAS,QAAQ,CAAA;AAEvC,MAAA,MAAM,MAAMG,sBAAA,CAAM,GAAA,CAAI,kBAAA,CAAmB,IAAA,CAAK,UAAU,CAAA;AACxD,MAAA,MAAM,cAAc,GAAA,CAAI,QAAA,CAAS,SAAS,OAAA,EAAQ,GAAI,KAAK,GAAA,EAAI;AAC/D,MAAA,IAAI,cAAc,eAAA,EAAiB;AACjC,QAAA,MAAA,CAAO,KAAK,wCAAwC,CAAA;AACpD,QAAA,OAAO;AAAA,UACL,GAAA,EAAK,IAAA;AAAA,UACL;AAAA,SACF;AAAA,MACF;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,gDAAA,EAAmD,KAAK,CAAA,CAAE,CAAA;AAAA,IACxE;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,KAAK,wCAAwC,CAAA;AACpD,EAAA,MAAM,OAAA,GAAU,MAAM,mBAAA,CAAoB,QAAQ,CAAA;AAClD,EAAA,MAAMH,oBAAG,SAAA,CAAU,QAAA,EAAU,QAAQ,IAAA,GAAO,OAAA,CAAQ,KAAK,MAAM,CAAA;AAC/D,EAAA,OAAO,OAAA;AACT;AAEA,eAAe,oBAAoB,QAAA,EAAkB;AACnD,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB;AAAA,MACE,IAAA,EAAM,YAAA;AAAA,MACN,KAAA,EAAO;AAAA;AACT,GACF;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA,IACX;AAAA,MACE,IAAA,EAAM,CAAA;AAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACT;AAAA,IACA;AAAA,MACE,IAAA,EAAM,CAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACT;AAAA,IACA;AAAA,MACE,IAAA,EAAM,CAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACT;AAAA,IACA;AAAA,MACE,IAAA,EAAM,CAAA;AAAA;AAAA,MACN,EAAA,EAAI;AAAA,KACN;AAAA,IACA;AAAA,MACE,IAAA,EAAM,CAAA;AAAA,MACN,EAAA,EAAI;AAAA;AACN,GACF;AAGA,EAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,CAAC,EAAE,KAAA,EAAO,EAAA,EAAG,KAAM,KAAA,KAAU,QAAA,IAAY,EAAA,KAAO,QAAQ,CAAA,EAAG;AACxE,IAAA,IAAA,CAAK,IAAA;AAAA,MACH,iBAAA,CAAkB,IAAA,CAAK,QAAQ,CAAA,GAC3B;AAAA,QACE,IAAA,EAAM,CAAA;AAAA,QACN,EAAA,EAAI;AAAA,OACN,GACA;AAAA,QACE,IAAA,EAAM,CAAA;AAAA,QACN,KAAA,EAAO;AAAA;AACT,KACN;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,SAAA,EAAW,QAAA;AAAA,IACX,OAAA,EAAS,IAAA;AAAA,IACT,IAAA,EAAM,EAAA;AAAA,IACN,UAAA,EAAY;AAAA,MACV;AAAA,QACE,IAAA,EAAM,UAAA;AAAA,QACN,WAAA,EAAa,IAAA;AAAA,QACb,gBAAA,EAAkB,IAAA;AAAA,QAClB,cAAA,EAAgB,IAAA;AAAA,QAChB,eAAA,EAAiB,IAAA;AAAA,QACjB,gBAAA,EAAkB;AAAA,OACpB;AAAA,MACA;AAAA,QACE,IAAA,EAAM,aAAA;AAAA,QACN,UAAA,EAAY,IAAA;AAAA,QACZ,UAAA,EAAY,IAAA;AAAA,QACZ,WAAA,EAAa,IAAA;AAAA,QACb,YAAA,EAAc;AAAA,OAChB;AAAA,MACA;AAAA,QACE,IAAA,EAAM,gBAAA;AAAA,QACN,QAAA,EAAU;AAAA;AACZ;AACF,GACF;AAEA,EAAA,OAAO,IAAI,OAAA;AAAA,IAAuC,CAAC,OAAA,EAAS,MAAA,KAC1D,OAAA,CAAQ,YAAY,CAAA,CAAE,QAAA;AAAA,MACpB,UAAA;AAAA,MACA,MAAA;AAAA,MACA,CAAC,KAAY,MAAA,KAA8C;AACzD,QAAA,IAAI,GAAA,EAAK;AACP,UAAA,MAAA,CAAO,GAAG,CAAA;AAAA,QACZ,CAAA,MAAO;AACL,UAAA,OAAA,CAAQ,EAAE,GAAA,EAAK,MAAA,CAAO,SAAS,IAAA,EAAM,MAAA,CAAO,MAAM,CAAA;AAAA,QACpD;AAAA,MACF;AAAA;AACF,GACF;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"readCorsOptions.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/readCorsOptions.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { CorsOptions } from 'cors';\nimport { Minimatch } from 'minimatch';\n\n/**\n * Attempts to read a CORS options object from the backend configuration object.\n *\n * @public\n * @param config - The backend configuration object.\n * @returns A CORS options object, or undefined if no cors configuration is present.\n *\n * @example\n * ```ts\n * const corsOptions = readCorsOptions(config.getConfig('backend'));\n * ```\n */\nexport function readCorsOptions(config?: Config): CorsOptions {\n const cc = config?.getOptionalConfig('cors');\n if (!cc) {\n return { origin: false }; // Disable CORS\n }\n\n return removeUnknown({\n origin: createCorsOriginMatcher(readStringArray(cc, 'origin')),\n methods: readStringArray(cc, 'methods'),\n allowedHeaders: readStringArray(cc, 'allowedHeaders'),\n exposedHeaders: readStringArray(cc, 'exposedHeaders'),\n credentials: cc.getOptionalBoolean('credentials'),\n maxAge: cc.getOptionalNumber('maxAge'),\n preflightContinue: cc.getOptionalBoolean('preflightContinue'),\n optionsSuccessStatus: cc.getOptionalNumber('optionsSuccessStatus'),\n });\n}\n\nfunction removeUnknown<T extends object>(obj: T): T {\n return Object.fromEntries(\n Object.entries(obj).filter(([, v]) => v !== undefined),\n ) as T;\n}\n\nfunction readStringArray(config: Config, key: string): string[] | undefined {\n const value = config.getOptional(key);\n if (typeof value === 'string') {\n return [value];\n } else if (!value) {\n return undefined;\n }\n return config.getStringArray(key);\n}\n\nfunction createCorsOriginMatcher(allowedOriginPatterns: string[] | undefined) {\n if (!allowedOriginPatterns) {\n return undefined;\n }\n\n const allowedOriginMatchers = allowedOriginPatterns.map(\n pattern => new Minimatch(pattern, { nocase: true, noglobstar: true }),\n );\n\n return (\n origin: string | undefined,\n callback: (\n err: Error | null,\n origin: boolean | string | RegExp | (boolean | string | RegExp)[],\n ) => void,\n ) => {\n return callback(\n null,\n allowedOriginMatchers.some(pattern => pattern.match(origin ?? '')),\n );\n };\n}\n"],"names":["Minimatch"],"mappings":";;;;AAgCO,SAAS,gBAAgB,MAAA,EAA8B;AAC5D,EAAA,MAAM,EAAA,GAAK,MAAA,EAAQ,iBAAA,CAAkB,MAAM,CAAA;AAC3C,EAAA,IAAI,CAAC,EAAA,EAAI;AACP,IAAA,OAAO,EAAE,QAAQ,KAAA,EAAM;AAAA,EACzB;AAEA,EAAA,OAAO,aAAA,CAAc;AAAA,IACnB,MAAA,EAAQ,uBAAA,CAAwB,eAAA,CAAgB,EAAA,EAAI,QAAQ,CAAC,CAAA;AAAA,IAC7D,OAAA,EAAS,eAAA,CAAgB,EAAA,EAAI,SAAS,CAAA;AAAA,IACtC,cAAA,EAAgB,eAAA,CAAgB,EAAA,EAAI,gBAAgB,CAAA;AAAA,IACpD,cAAA,EAAgB,eAAA,CAAgB,EAAA,EAAI,gBAAgB,CAAA;AAAA,IACpD,WAAA,EAAa,EAAA,CAAG,kBAAA,CAAmB,aAAa,CAAA;AAAA,IAChD,MAAA,EAAQ,EAAA,CAAG,iBAAA,CAAkB,QAAQ,CAAA;AAAA,IACrC,iBAAA,EAAmB,EAAA,CAAG,kBAAA,CAAmB,mBAAmB,CAAA;AAAA,IAC5D,oBAAA,EAAsB,EAAA,CAAG,iBAAA,CAAkB,sBAAsB;AAAA,GAClE,CAAA;AACH;AAEA,SAAS,cAAgC,GAAA,EAAW;AAClD,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,KAAM,MAAS;AAAA,GACvD;AACF;AAEA,SAAS,eAAA,CAAgB,QAAgB,GAAA,EAAmC;AAC1E,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,WAAA,CAAY,GAAG,CAAA;AACpC,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,CAAC,KAAK,CAAA;AAAA,EACf,CAAA,MAAA,IAAW,CAAC,KAAA,EAAO;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,eAAe,GAAG,CAAA;AAClC;AAEA,SAAS,wBAAwB,qBAAA,EAA6C;AAC5E,EAAA,IAAI,CAAC,qBAAA,EAAuB;AAC1B,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,wBAAwB,qBAAA,CAAsB,GAAA;AAAA,IAClD,CAAA,OAAA,KAAW,IAAIA,mBAAA,CAAU,OAAA,EAAS,EAAE,MAAA,EAAQ,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM;AAAA,GACtE;AAEA,EAAA,OAAO,CACL,QACA,QAAA,KAIG;AACH,IAAA,OAAO,QAAA;AAAA,MACL,IAAA;AAAA,MACA,sBAAsB,IAAA,CAAK,CAAA,OAAA,KAAW,QAAQ,KAAA,CAAM,MAAA,IAAU,EAAE,CAAC;AAAA,KACnE;AAAA,EACF,CAAA;AACF;;;;"}
1
+ {"version":3,"file":"readCorsOptions.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/readCorsOptions.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { CorsOptions } from 'cors';\nimport { Minimatch } from 'minimatch';\n\n/**\n * Attempts to read a CORS options object from the backend configuration object.\n *\n * @public\n * @param config - The backend configuration object.\n * @returns A CORS options object, or undefined if no cors configuration is present.\n *\n * @example\n * ```ts\n * const corsOptions = readCorsOptions(config.getConfig('backend'));\n * ```\n */\nexport function readCorsOptions(config?: Config): CorsOptions {\n const cc = config?.getOptionalConfig('cors');\n if (!cc) {\n return { origin: false }; // Disable CORS\n }\n\n return removeUnknown({\n origin: createCorsOriginMatcher(readStringArray(cc, 'origin')),\n methods: readStringArray(cc, 'methods'),\n allowedHeaders: readStringArray(cc, 'allowedHeaders'),\n exposedHeaders: readStringArray(cc, 'exposedHeaders'),\n credentials: cc.getOptionalBoolean('credentials'),\n maxAge: cc.getOptionalNumber('maxAge'),\n preflightContinue: cc.getOptionalBoolean('preflightContinue'),\n optionsSuccessStatus: cc.getOptionalNumber('optionsSuccessStatus'),\n });\n}\n\nfunction removeUnknown<T extends object>(obj: T): T {\n return Object.fromEntries(\n Object.entries(obj).filter(([, v]) => v !== undefined),\n ) as T;\n}\n\nfunction readStringArray(config: Config, key: string): string[] | undefined {\n const value = config.getOptional(key);\n if (typeof value === 'string') {\n return [value];\n } else if (!value) {\n return undefined;\n }\n return config.getStringArray(key);\n}\n\nfunction createCorsOriginMatcher(allowedOriginPatterns: string[] | undefined) {\n if (!allowedOriginPatterns) {\n return undefined;\n }\n\n const allowedOriginMatchers = allowedOriginPatterns.map(\n pattern => new Minimatch(pattern, { nocase: true, noglobstar: true }),\n );\n\n return (\n origin: string | undefined,\n callback: (\n err: Error | null,\n origin: boolean | string | RegExp | (boolean | string | RegExp)[],\n ) => void,\n ) => {\n return callback(\n null,\n allowedOriginMatchers.some(pattern => pattern.match(origin ?? '')),\n );\n };\n}\n"],"names":["Minimatch"],"mappings":";;;;AAgCO,SAAS,gBAAgB,MAAA,EAA8B;AAC5D,EAAA,MAAM,EAAA,GAAK,MAAA,EAAQ,iBAAA,CAAkB,MAAM,CAAA;AAC3C,EAAA,IAAI,CAAC,EAAA,EAAI;AACP,IAAA,OAAO,EAAE,QAAQ,KAAA,EAAM;AAAA,EACzB;AAEA,EAAA,OAAO,aAAA,CAAc;AAAA,IACnB,MAAA,EAAQ,uBAAA,CAAwB,eAAA,CAAgB,EAAA,EAAI,QAAQ,CAAC,CAAA;AAAA,IAC7D,OAAA,EAAS,eAAA,CAAgB,EAAA,EAAI,SAAS,CAAA;AAAA,IACtC,cAAA,EAAgB,eAAA,CAAgB,EAAA,EAAI,gBAAgB,CAAA;AAAA,IACpD,cAAA,EAAgB,eAAA,CAAgB,EAAA,EAAI,gBAAgB,CAAA;AAAA,IACpD,WAAA,EAAa,EAAA,CAAG,kBAAA,CAAmB,aAAa,CAAA;AAAA,IAChD,MAAA,EAAQ,EAAA,CAAG,iBAAA,CAAkB,QAAQ,CAAA;AAAA,IACrC,iBAAA,EAAmB,EAAA,CAAG,kBAAA,CAAmB,mBAAmB,CAAA;AAAA,IAC5D,oBAAA,EAAsB,EAAA,CAAG,iBAAA,CAAkB,sBAAsB;AAAA,GAClE,CAAA;AACH;AAEA,SAAS,cAAgC,GAAA,EAAW;AAClD,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,KAAM,MAAS;AAAA,GACvD;AACF;AAEA,SAAS,eAAA,CAAgB,QAAgB,GAAA,EAAmC;AAC1E,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,WAAA,CAAY,GAAG,CAAA;AACpC,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,CAAC,KAAK,CAAA;AAAA,EACf,CAAA,MAAA,IAAW,CAAC,KAAA,EAAO;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,eAAe,GAAG,CAAA;AAClC;AAEA,SAAS,wBAAwB,qBAAA,EAA6C;AAC5E,EAAA,IAAI,CAAC,qBAAA,EAAuB;AAC1B,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,wBAAwB,qBAAA,CAAsB,GAAA;AAAA,IAClD,CAAA,OAAA,KAAW,IAAIA,mBAAA,CAAU,OAAA,EAAS,EAAE,MAAA,EAAQ,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM;AAAA,GACtE;AAEA,EAAA,OAAO,CACL,QACA,QAAA,KAIG;AACH,IAAA,OAAO,QAAA;AAAA,MACL,IAAA;AAAA,MACA,sBAAsB,IAAA,CAAK,CAAA,OAAA,KAAW,QAAQ,KAAA,CAAM,MAAA,IAAU,EAAE,CAAC;AAAA,KACnE;AAAA,EACF,CAAA;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"readHelmetOptions.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/readHelmetOptions.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 { Config } from '@backstage/config';\nimport helmet from 'helmet';\nimport { HelmetOptions } from 'helmet';\nimport kebabCase from 'lodash/kebabCase';\n\n/**\n * Attempts to read Helmet options from the backend configuration object.\n *\n * @public\n * @param config - The backend configuration object.\n * @returns A Helmet options object, or undefined if no Helmet configuration is present.\n *\n * @example\n * ```ts\n * const helmetOptions = readHelmetOptions(config.getConfig('backend'));\n * ```\n */\nexport function readHelmetOptions(config?: Config): HelmetOptions {\n const cspOptions = readCspDirectives(config);\n return {\n contentSecurityPolicy: {\n useDefaults: false,\n directives: applyCspDirectives(cspOptions),\n },\n // These are all disabled in order to maintain backwards compatibility\n // when bumping helmet v5. We can't enable these by default because\n // there is no way for users to configure them.\n // TODO(Rugvip): We should give control of this setup to consumers\n crossOriginEmbedderPolicy: false,\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false,\n originAgentCluster: false,\n referrerPolicy: readReferrerPolicy(config),\n };\n}\n\ntype CspDirectives = Record<string, string[] | false> | undefined;\n\n/**\n * Attempts to read a CSP directives from the backend configuration object.\n *\n * @example\n * ```yaml\n * backend:\n * csp:\n * connect-src: [\"'self'\", 'http:', 'https:']\n * upgrade-insecure-requests: false\n * ```\n */\nfunction readCspDirectives(config?: Config): CspDirectives {\n const cc = config?.getOptionalConfig('csp');\n if (!cc) {\n return undefined;\n }\n\n const result: Record<string, string[] | false> = {};\n for (const key of cc.keys()) {\n if (cc.get(key) === false) {\n result[key] = false;\n } else {\n result[key] = cc.getStringArray(key);\n }\n }\n\n return result;\n}\n\ntype ContentSecurityPolicyDirectives = Exclude<\n HelmetOptions['contentSecurityPolicy'],\n boolean | undefined\n>['directives'];\n\nexport function applyCspDirectives(\n directives: CspDirectives,\n): ContentSecurityPolicyDirectives {\n const result: ContentSecurityPolicyDirectives =\n helmet.contentSecurityPolicy.getDefaultDirectives();\n\n // TODO(Rugvip): We currently use non-precompiled AJV for validation in the frontend, which uses eval.\n // It should be replaced by any other solution that doesn't require unsafe-eval.\n result['script-src'] = [\"'self'\", \"'unsafe-eval'\"];\n\n // TODO(Rugvip): This is removed so that we maintained backwards compatibility\n // when bumping to helmet v5, we could remove this as well as\n // skip setting `useDefaults: false` in the future.\n delete result['form-action'];\n\n if (directives) {\n for (const [key, value] of Object.entries(directives)) {\n const kebabCaseKey = kebabCase(key);\n if (value === false) {\n delete result[kebabCaseKey];\n } else {\n result[kebabCaseKey] = value;\n }\n }\n }\n\n return result;\n}\n\ntype ReferrerPolicy = Record<string, string[]> | undefined;\n\n/**\n * Attempts to read the ReferrerPolicy from the backend configuration object.\n *\n * @example\n * ```yaml\n * backend:\n * referrer:\n * policy: [\"strict-origin-when-cross-origin\"]\n * ```\n */\nfunction readReferrerPolicy(config?: Config): ReferrerPolicy {\n const cc = config?.getOptionalConfig('referrer');\n const result: Record<string, string[]> = {};\n\n if (!cc) {\n result.policy = ['no-referrer'];\n } else {\n for (const key of cc.keys()) {\n result[key] = cc.getStringArray(key);\n }\n }\n\n return result;\n}\n"],"names":["helmet","kebabCase"],"mappings":";;;;;;;;;;AAiCO,SAAS,kBAAkB,MAAA,EAAgC;AAChE,EAAA,MAAM,UAAA,GAAa,kBAAkB,MAAM,CAAA;AAC3C,EAAA,OAAO;AAAA,IACL,qBAAA,EAAuB;AAAA,MACrB,WAAA,EAAa,KAAA;AAAA,MACb,UAAA,EAAY,mBAAmB,UAAU;AAAA,KAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,yBAAA,EAA2B,KAAA;AAAA,IAC3B,uBAAA,EAAyB,KAAA;AAAA,IACzB,yBAAA,EAA2B,KAAA;AAAA,IAC3B,kBAAA,EAAoB,KAAA;AAAA,IACpB,cAAA,EAAgB,mBAAmB,MAAM;AAAA,GAC3C;AACF;AAeA,SAAS,kBAAkB,MAAA,EAAgC;AACzD,EAAA,MAAM,EAAA,GAAK,MAAA,EAAQ,iBAAA,CAAkB,KAAK,CAAA;AAC1C,EAAA,IAAI,CAAC,EAAA,EAAI;AACP,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAA2C,EAAC;AAClD,EAAA,KAAA,MAAW,GAAA,IAAO,EAAA,CAAG,IAAA,EAAK,EAAG;AAC3B,IAAA,IAAI,EAAA,CAAG,GAAA,CAAI,GAAG,CAAA,KAAM,KAAA,EAAO;AACzB,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,EAAA,CAAG,cAAA,CAAe,GAAG,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,mBACd,UAAA,EACiC;AACjC,EAAA,MAAM,MAAA,GACJA,uBAAA,CAAO,qBAAA,CAAsB,oBAAA,EAAqB;AAIpD,EAAA,MAAA,CAAO,YAAY,CAAA,GAAI,CAAC,QAAA,EAAU,eAAe,CAAA;AAKjD,EAAA,OAAO,OAAO,aAAa,CAAA;AAE3B,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACrD,MAAA,MAAM,YAAA,GAAeC,2BAAU,GAAG,CAAA;AAClC,MAAA,IAAI,UAAU,KAAA,EAAO;AACnB,QAAA,OAAO,OAAO,YAAY,CAAA;AAAA,MAC5B,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,YAAY,CAAA,GAAI,KAAA;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAcA,SAAS,mBAAmB,MAAA,EAAiC;AAC3D,EAAA,MAAM,EAAA,GAAK,MAAA,EAAQ,iBAAA,CAAkB,UAAU,CAAA;AAC/C,EAAA,MAAM,SAAmC,EAAC;AAE1C,EAAA,IAAI,CAAC,EAAA,EAAI;AACP,IAAA,MAAA,CAAO,MAAA,GAAS,CAAC,aAAa,CAAA;AAAA,EAChC,CAAA,MAAO;AACL,IAAA,KAAA,MAAW,GAAA,IAAO,EAAA,CAAG,IAAA,EAAK,EAAG;AAC3B,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,EAAA,CAAG,cAAA,CAAe,GAAG,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;;;;;"}
1
+ {"version":3,"file":"readHelmetOptions.cjs.js","sources":["../../../../src/entrypoints/rootHttpRouter/http/readHelmetOptions.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 { Config } from '@backstage/config';\nimport helmet from 'helmet';\nimport { HelmetOptions } from 'helmet';\nimport kebabCase from 'lodash/kebabCase';\n\n/**\n * Attempts to read Helmet options from the backend configuration object.\n *\n * @public\n * @param config - The backend configuration object.\n * @returns A Helmet options object, or undefined if no Helmet configuration is present.\n *\n * @example\n * ```ts\n * const helmetOptions = readHelmetOptions(config.getConfig('backend'));\n * ```\n */\nexport function readHelmetOptions(config?: Config): HelmetOptions {\n const cspOptions = readCspDirectives(config);\n return {\n contentSecurityPolicy: {\n useDefaults: false,\n directives: applyCspDirectives(cspOptions),\n },\n // These are all disabled in order to maintain backwards compatibility\n // when bumping helmet v5. We can't enable these by default because\n // there is no way for users to configure them.\n // TODO(Rugvip): We should give control of this setup to consumers\n crossOriginEmbedderPolicy: false,\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false,\n originAgentCluster: false,\n referrerPolicy: readReferrerPolicy(config),\n };\n}\n\ntype CspDirectives = Record<string, string[] | false> | undefined;\n\n/**\n * Attempts to read a CSP directives from the backend configuration object.\n *\n * @example\n * ```yaml\n * backend:\n * csp:\n * connect-src: [\"'self'\", 'http:', 'https:']\n * upgrade-insecure-requests: false\n * ```\n */\nfunction readCspDirectives(config?: Config): CspDirectives {\n const cc = config?.getOptionalConfig('csp');\n if (!cc) {\n return undefined;\n }\n\n const result: Record<string, string[] | false> = {};\n for (const key of cc.keys()) {\n if (cc.get(key) === false) {\n result[key] = false;\n } else {\n result[key] = cc.getStringArray(key);\n }\n }\n\n return result;\n}\n\ntype ContentSecurityPolicyDirectives = Exclude<\n HelmetOptions['contentSecurityPolicy'],\n boolean | undefined\n>['directives'];\n\nexport function applyCspDirectives(\n directives: CspDirectives,\n): ContentSecurityPolicyDirectives {\n const result: ContentSecurityPolicyDirectives =\n helmet.contentSecurityPolicy.getDefaultDirectives();\n\n // TODO(Rugvip): We currently use non-precompiled AJV for validation in the frontend, which uses eval.\n // It should be replaced by any other solution that doesn't require unsafe-eval.\n result['script-src'] = [\"'self'\", \"'unsafe-eval'\"];\n\n // TODO(Rugvip): This is removed so that we maintained backwards compatibility\n // when bumping to helmet v5, we could remove this as well as\n // skip setting `useDefaults: false` in the future.\n delete result['form-action'];\n\n if (directives) {\n for (const [key, value] of Object.entries(directives)) {\n const kebabCaseKey = kebabCase(key);\n if (value === false) {\n delete result[kebabCaseKey];\n } else {\n result[kebabCaseKey] = value;\n }\n }\n }\n\n return result;\n}\n\ntype ReferrerPolicy = Record<string, string[]> | undefined;\n\n/**\n * Attempts to read the ReferrerPolicy from the backend configuration object.\n *\n * @example\n * ```yaml\n * backend:\n * referrer:\n * policy: [\"strict-origin-when-cross-origin\"]\n * ```\n */\nfunction readReferrerPolicy(config?: Config): ReferrerPolicy {\n const cc = config?.getOptionalConfig('referrer');\n const result: Record<string, string[]> = {};\n\n if (!cc) {\n result.policy = ['no-referrer'];\n } else {\n for (const key of cc.keys()) {\n result[key] = cc.getStringArray(key);\n }\n }\n\n return result;\n}\n"],"names":["helmet","kebabCase"],"mappings":";;;;;;;;;;AAiCO,SAAS,kBAAkB,MAAA,EAAgC;AAChE,EAAA,MAAM,UAAA,GAAa,kBAAkB,MAAM,CAAA;AAC3C,EAAA,OAAO;AAAA,IACL,qBAAA,EAAuB;AAAA,MACrB,WAAA,EAAa,KAAA;AAAA,MACb,UAAA,EAAY,mBAAmB,UAAU;AAAA,KAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,yBAAA,EAA2B,KAAA;AAAA,IAC3B,uBAAA,EAAyB,KAAA;AAAA,IACzB,yBAAA,EAA2B,KAAA;AAAA,IAC3B,kBAAA,EAAoB,KAAA;AAAA,IACpB,cAAA,EAAgB,mBAAmB,MAAM;AAAA,GAC3C;AACF;AAeA,SAAS,kBAAkB,MAAA,EAAgC;AACzD,EAAA,MAAM,EAAA,GAAK,MAAA,EAAQ,iBAAA,CAAkB,KAAK,CAAA;AAC1C,EAAA,IAAI,CAAC,EAAA,EAAI;AACP,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAA2C,EAAC;AAClD,EAAA,KAAA,MAAW,GAAA,IAAO,EAAA,CAAG,IAAA,EAAK,EAAG;AAC3B,IAAA,IAAI,EAAA,CAAG,GAAA,CAAI,GAAG,CAAA,KAAM,KAAA,EAAO;AACzB,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,EAAA,CAAG,cAAA,CAAe,GAAG,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,mBACd,UAAA,EACiC;AACjC,EAAA,MAAM,MAAA,GACJA,uBAAA,CAAO,qBAAA,CAAsB,oBAAA,EAAqB;AAIpD,EAAA,MAAA,CAAO,YAAY,CAAA,GAAI,CAAC,QAAA,EAAU,eAAe,CAAA;AAKjD,EAAA,OAAO,OAAO,aAAa,CAAA;AAE3B,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACrD,MAAA,MAAM,YAAA,GAAeC,2BAAU,GAAG,CAAA;AAClC,MAAA,IAAI,UAAU,KAAA,EAAO;AACnB,QAAA,OAAO,OAAO,YAAY,CAAA;AAAA,MAC5B,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,YAAY,CAAA,GAAI,KAAA;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAcA,SAAS,mBAAmB,MAAA,EAAiC;AAC3D,EAAA,MAAM,EAAA,GAAK,MAAA,EAAQ,iBAAA,CAAkB,UAAU,CAAA;AAC/C,EAAA,MAAM,SAAmC,EAAC;AAE1C,EAAA,IAAI,CAAC,EAAA,EAAI;AACP,IAAA,MAAA,CAAO,MAAA,GAAS,CAAC,aAAa,CAAA;AAAA,EAChC,CAAA,MAAO;AACL,IAAA,KAAA,MAAW,GAAA,IAAO,EAAA,CAAG,IAAA,EAAK,EAAG;AAC3B,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,EAAA,CAAG,cAAA,CAAe,GAAG,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"rootHttpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.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 {\n coreServices,\n createServiceFactory,\n LifecycleService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport express, { Express, RequestHandler } from 'express';\nimport type { Server } from 'node:http';\nimport {\n createHttpServer,\n MiddlewareFactory,\n readHttpServerOptions,\n} from './http';\nimport { DefaultRootHttpRouter } from './DefaultRootHttpRouter';\nimport { createHealthRouter } from './createHealthRouter';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { readDurationFromConfig } from '@backstage/config';\n\n/**\n * @public\n */\nexport interface RootHttpRouterConfigureContext {\n app: Express;\n server: Server;\n middleware: MiddlewareFactory;\n routes: RequestHandler;\n config: RootConfigService;\n logger: LoggerService;\n lifecycle: LifecycleService;\n healthRouter: RequestHandler;\n applyDefaults: () => void;\n}\n\n/**\n * HTTP route registration for root services.\n *\n * See {@link @backstage/code-plugin-api#RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport type RootHttpRouterFactoryOptions = {\n /**\n * The path to forward all unmatched requests to. Defaults to '/api/app' if\n * not given. Disables index path behavior if false is given.\n */\n indexPath?: string | false;\n\n configure?(context: RootHttpRouterConfigureContext): void;\n};\n\nfunction defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) {\n applyDefaults();\n}\n\nconst rootHttpRouterServiceFactoryWithOptions = (\n options?: RootHttpRouterFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n rootLogger: coreServices.rootLogger,\n lifecycle: coreServices.rootLifecycle,\n health: coreServices.rootHealth,\n },\n async factory({ config, rootLogger, lifecycle, health }) {\n const { indexPath, configure = defaultConfigure } = options ?? {};\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n const app = express();\n\n const trustProxy = config.getOptional('backend.trustProxy');\n\n const router = DefaultRootHttpRouter.create({ indexPath });\n const middleware = MiddlewareFactory.create({ config, logger });\n const routes = router.handler();\n\n const healthRouter = createHealthRouter({ config, health });\n\n const server = await createHttpServer(\n app,\n readHttpServerOptions(config.getOptionalConfig('backend')),\n { logger },\n );\n\n configure({\n app,\n server,\n routes,\n middleware,\n config,\n logger,\n lifecycle,\n healthRouter,\n applyDefaults() {\n if (process.env.NODE_ENV === 'development') {\n app.set('json spaces', 2);\n }\n if (trustProxy !== undefined) {\n app.set('trust proxy', trustProxy);\n }\n\n // Apply server-level HTTP options from config\n const backendConfig = config.getOptionalConfig('backend');\n const serverConfig = backendConfig?.getOptionalConfig('server');\n\n if (serverConfig) {\n // Helper function to read duration values (supporting number, string, or HumanDuration)\n const readDurationValue = (key: string): number | undefined => {\n if (!serverConfig.has(key)) {\n return undefined;\n }\n\n const value = serverConfig.getOptional(key);\n if (typeof value === 'number') {\n return value;\n }\n\n // If it's not a number, try to read it as a duration\n try {\n const duration = readDurationFromConfig(serverConfig, { key });\n return durationToMilliseconds(duration);\n } catch (error) {\n // Log warning for parsing failures\n logger.warn(\n `Failed to parse backend.server.${key} as duration: ${error}. ` +\n `Expected a number (milliseconds), duration string (e.g., '30s'), ` +\n `ISO duration (e.g., 'PT30S'), or duration object (e.g., {seconds: 30}). ` +\n `Falling back to number parsing.`,\n );\n return undefined;\n }\n };\n\n // Apply timeout settings\n const headersTimeout = readDurationValue('headersTimeout');\n if (headersTimeout !== undefined) {\n server.headersTimeout = headersTimeout;\n }\n\n const requestTimeout = readDurationValue('requestTimeout');\n if (requestTimeout !== undefined) {\n server.requestTimeout = requestTimeout;\n }\n\n const keepAliveTimeout = readDurationValue('keepAliveTimeout');\n if (keepAliveTimeout !== undefined) {\n server.keepAliveTimeout = keepAliveTimeout;\n }\n\n const timeout = readDurationValue('timeout');\n if (timeout !== undefined) {\n server.timeout = timeout;\n }\n\n // Apply numeric settings\n const maxHeadersCount =\n serverConfig.getOptionalNumber('maxHeadersCount');\n if (maxHeadersCount !== undefined) {\n server.maxHeadersCount = maxHeadersCount;\n }\n\n const maxRequestsPerSocket = serverConfig.getOptionalNumber(\n 'maxRequestsPerSocket',\n );\n if (maxRequestsPerSocket !== undefined) {\n server.maxRequestsPerSocket = maxRequestsPerSocket;\n }\n }\n\n app.use(middleware.helmet());\n app.use(middleware.cors());\n app.use(middleware.compression());\n app.use(middleware.logging());\n app.use(middleware.rateLimit());\n app.use(healthRouter);\n app.use(routes);\n app.use(middleware.notFound());\n app.use(middleware.error());\n },\n });\n\n if (config.has('backend.lifecycle.serverShutdownDelay')) {\n const serverShutdownDelay = readDurationFromConfig(config, {\n key: 'backend.lifecycle.serverShutdownDelay',\n });\n lifecycle.addBeforeShutdownHook(async () => {\n const timeoutMs = durationToMilliseconds(serverShutdownDelay);\n return await new Promise(resolve => {\n setTimeout(resolve, timeoutMs);\n });\n });\n }\n\n lifecycle.addShutdownHook(() => server.stop());\n\n await server.start();\n\n return router;\n },\n });\n\n/** @public */\nexport const rootHttpRouterServiceFactory = Object.assign(\n rootHttpRouterServiceFactoryWithOptions,\n rootHttpRouterServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","config","express","DefaultRootHttpRouter","MiddlewareFactory","createHealthRouter","createHttpServer","readHttpServerOptions","readDurationFromConfig","durationToMilliseconds"],"mappings":"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"}
1
+ {"version":3,"file":"rootHttpRouterServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.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 {\n coreServices,\n createServiceFactory,\n LifecycleService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport express, { Express, RequestHandler } from 'express';\nimport type { Server } from 'node:http';\nimport {\n createHttpServer,\n MiddlewareFactory,\n readHttpServerOptions,\n} from './http';\nimport { DefaultRootHttpRouter } from './DefaultRootHttpRouter';\nimport { createHealthRouter } from './createHealthRouter';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { readDurationFromConfig } from '@backstage/config';\n\n/**\n * @public\n */\nexport interface RootHttpRouterConfigureContext {\n app: Express;\n server: Server;\n middleware: MiddlewareFactory;\n routes: RequestHandler;\n config: RootConfigService;\n logger: LoggerService;\n lifecycle: LifecycleService;\n healthRouter: RequestHandler;\n applyDefaults: () => void;\n}\n\n/**\n * HTTP route registration for root services.\n *\n * See {@link @backstage/code-plugin-api#RootHttpRouterService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-http-router | the service docs}\n * for more information.\n *\n * @public\n */\nexport type RootHttpRouterFactoryOptions = {\n /**\n * The path to forward all unmatched requests to. Defaults to '/api/app' if\n * not given. Disables index path behavior if false is given.\n */\n indexPath?: string | false;\n\n configure?(context: RootHttpRouterConfigureContext): void;\n};\n\nfunction defaultConfigure({ applyDefaults }: RootHttpRouterConfigureContext) {\n applyDefaults();\n}\n\nconst rootHttpRouterServiceFactoryWithOptions = (\n options?: RootHttpRouterFactoryOptions,\n) =>\n createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n rootLogger: coreServices.rootLogger,\n lifecycle: coreServices.rootLifecycle,\n health: coreServices.rootHealth,\n },\n async factory({ config, rootLogger, lifecycle, health }) {\n const { indexPath, configure = defaultConfigure } = options ?? {};\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n const app = express();\n\n const trustProxy = config.getOptional('backend.trustProxy');\n\n const router = DefaultRootHttpRouter.create({ indexPath });\n const middleware = MiddlewareFactory.create({ config, logger });\n const routes = router.handler();\n\n const healthRouter = createHealthRouter({ config, health });\n\n const server = await createHttpServer(\n app,\n readHttpServerOptions(config.getOptionalConfig('backend')),\n { logger },\n );\n\n configure({\n app,\n server,\n routes,\n middleware,\n config,\n logger,\n lifecycle,\n healthRouter,\n applyDefaults() {\n if (process.env.NODE_ENV === 'development') {\n app.set('json spaces', 2);\n }\n if (trustProxy !== undefined) {\n app.set('trust proxy', trustProxy);\n }\n\n // Apply server-level HTTP options from config\n const backendConfig = config.getOptionalConfig('backend');\n const serverConfig = backendConfig?.getOptionalConfig('server');\n\n if (serverConfig) {\n // Helper function to read duration values (supporting number, string, or HumanDuration)\n const readDurationValue = (key: string): number | undefined => {\n if (!serverConfig.has(key)) {\n return undefined;\n }\n\n const value = serverConfig.getOptional(key);\n if (typeof value === 'number') {\n return value;\n }\n\n // If it's not a number, try to read it as a duration\n try {\n const duration = readDurationFromConfig(serverConfig, { key });\n return durationToMilliseconds(duration);\n } catch (error) {\n // Log warning for parsing failures\n logger.warn(\n `Failed to parse backend.server.${key} as duration: ${error}. ` +\n `Expected a number (milliseconds), duration string (e.g., '30s'), ` +\n `ISO duration (e.g., 'PT30S'), or duration object (e.g., {seconds: 30}). ` +\n `Falling back to number parsing.`,\n );\n return undefined;\n }\n };\n\n // Apply timeout settings\n const headersTimeout = readDurationValue('headersTimeout');\n if (headersTimeout !== undefined) {\n server.headersTimeout = headersTimeout;\n }\n\n const requestTimeout = readDurationValue('requestTimeout');\n if (requestTimeout !== undefined) {\n server.requestTimeout = requestTimeout;\n }\n\n const keepAliveTimeout = readDurationValue('keepAliveTimeout');\n if (keepAliveTimeout !== undefined) {\n server.keepAliveTimeout = keepAliveTimeout;\n }\n\n const timeout = readDurationValue('timeout');\n if (timeout !== undefined) {\n server.timeout = timeout;\n }\n\n // Apply numeric settings\n const maxHeadersCount =\n serverConfig.getOptionalNumber('maxHeadersCount');\n if (maxHeadersCount !== undefined) {\n server.maxHeadersCount = maxHeadersCount;\n }\n\n const maxRequestsPerSocket = serverConfig.getOptionalNumber(\n 'maxRequestsPerSocket',\n );\n if (maxRequestsPerSocket !== undefined) {\n server.maxRequestsPerSocket = maxRequestsPerSocket;\n }\n }\n\n app.use(middleware.helmet());\n app.use(middleware.cors());\n app.use(middleware.compression());\n app.use(middleware.logging());\n app.use(middleware.rateLimit());\n app.use(healthRouter);\n app.use(routes);\n app.use(middleware.notFound());\n app.use(middleware.error());\n },\n });\n\n if (config.has('backend.lifecycle.serverShutdownDelay')) {\n const serverShutdownDelay = readDurationFromConfig(config, {\n key: 'backend.lifecycle.serverShutdownDelay',\n });\n lifecycle.addBeforeShutdownHook(async () => {\n const timeoutMs = durationToMilliseconds(serverShutdownDelay);\n return await new Promise(resolve => {\n setTimeout(resolve, timeoutMs);\n });\n });\n }\n\n lifecycle.addShutdownHook(() => server.stop());\n\n await server.start();\n\n return router;\n },\n });\n\n/** @public */\nexport const rootHttpRouterServiceFactory = Object.assign(\n rootHttpRouterServiceFactoryWithOptions,\n rootHttpRouterServiceFactoryWithOptions(),\n);\n"],"names":["createServiceFactory","coreServices","config","express","DefaultRootHttpRouter","MiddlewareFactory","createHealthRouter","createHttpServer","readHttpServerOptions","readDurationFromConfig","durationToMilliseconds"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"rootLifecycleServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.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 {\n createServiceFactory,\n coreServices,\n LifecycleServiceStartupHook,\n LifecycleServiceStartupOptions,\n LifecycleServiceShutdownHook,\n LifecycleServiceShutdownOptions,\n RootLifecycleService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class BackendLifecycleImpl implements RootLifecycleService {\n private readonly logger: LoggerService;\n\n constructor(logger: LoggerService) {\n this.logger = logger;\n }\n\n #hasStarted = false;\n #startupTasks: Array<{\n hook: LifecycleServiceStartupHook;\n options?: LifecycleServiceStartupOptions;\n }> = [];\n\n addStartupHook(\n hook: LifecycleServiceStartupHook,\n options?: LifecycleServiceStartupOptions,\n ): void {\n if (this.#hasStarted) {\n throw new Error('Attempted to add startup hook after startup');\n }\n this.#startupTasks.push({ hook, options });\n }\n\n async startup(): Promise<void> {\n if (this.#hasStarted) {\n return;\n }\n this.#hasStarted = true;\n\n this.logger.debug(`Running ${this.#startupTasks.length} startup tasks...`);\n await Promise.all(\n this.#startupTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Startup hook succeeded`);\n } catch (error) {\n logger.error(`Startup hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasBeforeShutdown = false;\n #beforeShutdownTasks: Array<{ hook: () => void | Promise<void> }> = [];\n\n addBeforeShutdownHook(hook: () => void): void {\n if (this.#hasBeforeShutdown) {\n throw new Error(\n 'Attempt to add before shutdown hook after shutdown has started',\n );\n }\n this.#beforeShutdownTasks.push({ hook });\n }\n\n async beforeShutdown(): Promise<void> {\n if (this.#hasBeforeShutdown) {\n return;\n }\n this.#hasBeforeShutdown = true;\n\n this.logger.debug(\n `Running ${this.#beforeShutdownTasks.length} before shutdown tasks...`,\n );\n await Promise.all(\n this.#beforeShutdownTasks.map(async ({ hook }) => {\n try {\n await hook();\n this.logger.debug(`Before shutdown hook succeeded`);\n } catch (error) {\n this.logger.error(`Before shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasShutdown = false;\n #shutdownTasks: Array<{\n hook: LifecycleServiceShutdownHook;\n options?: LifecycleServiceShutdownOptions;\n }> = [];\n\n addShutdownHook(\n hook: LifecycleServiceShutdownHook,\n options?: LifecycleServiceShutdownOptions,\n ): void {\n if (this.#hasShutdown) {\n throw new Error('Attempted to add shutdown hook after shutdown');\n }\n this.#shutdownTasks.push({ hook, options });\n }\n\n async shutdown(): Promise<void> {\n if (this.#hasShutdown) {\n return;\n }\n this.#hasShutdown = true;\n\n this.logger.debug(\n `Running ${this.#shutdownTasks.length} shutdown tasks...`,\n );\n await Promise.all(\n this.#shutdownTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Shutdown hook succeeded`);\n } catch (error) {\n logger.error(`Shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n}\n\n/**\n * Registration of backend startup and shutdown lifecycle hooks.\n *\n * See {@link @backstage/code-plugin-api#RootLifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLifecycleServiceFactory = createServiceFactory({\n service: coreServices.rootLifecycle,\n deps: {\n logger: coreServices.rootLogger,\n },\n async factory({ logger }) {\n return new BackendLifecycleImpl(logger);\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":"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"}
1
+ {"version":3,"file":"rootLifecycleServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLifecycle/rootLifecycleServiceFactory.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 {\n createServiceFactory,\n coreServices,\n LifecycleServiceStartupHook,\n LifecycleServiceStartupOptions,\n LifecycleServiceShutdownHook,\n LifecycleServiceShutdownOptions,\n RootLifecycleService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport class BackendLifecycleImpl implements RootLifecycleService {\n private readonly logger: LoggerService;\n\n constructor(logger: LoggerService) {\n this.logger = logger;\n }\n\n #hasStarted = false;\n #startupTasks: Array<{\n hook: LifecycleServiceStartupHook;\n options?: LifecycleServiceStartupOptions;\n }> = [];\n\n addStartupHook(\n hook: LifecycleServiceStartupHook,\n options?: LifecycleServiceStartupOptions,\n ): void {\n if (this.#hasStarted) {\n throw new Error('Attempted to add startup hook after startup');\n }\n this.#startupTasks.push({ hook, options });\n }\n\n async startup(): Promise<void> {\n if (this.#hasStarted) {\n return;\n }\n this.#hasStarted = true;\n\n this.logger.debug(`Running ${this.#startupTasks.length} startup tasks...`);\n await Promise.all(\n this.#startupTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Startup hook succeeded`);\n } catch (error) {\n logger.error(`Startup hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasBeforeShutdown = false;\n #beforeShutdownTasks: Array<{ hook: () => void | Promise<void> }> = [];\n\n addBeforeShutdownHook(hook: () => void): void {\n if (this.#hasBeforeShutdown) {\n throw new Error(\n 'Attempt to add before shutdown hook after shutdown has started',\n );\n }\n this.#beforeShutdownTasks.push({ hook });\n }\n\n async beforeShutdown(): Promise<void> {\n if (this.#hasBeforeShutdown) {\n return;\n }\n this.#hasBeforeShutdown = true;\n\n this.logger.debug(\n `Running ${this.#beforeShutdownTasks.length} before shutdown tasks...`,\n );\n await Promise.all(\n this.#beforeShutdownTasks.map(async ({ hook }) => {\n try {\n await hook();\n this.logger.debug(`Before shutdown hook succeeded`);\n } catch (error) {\n this.logger.error(`Before shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n\n #hasShutdown = false;\n #shutdownTasks: Array<{\n hook: LifecycleServiceShutdownHook;\n options?: LifecycleServiceShutdownOptions;\n }> = [];\n\n addShutdownHook(\n hook: LifecycleServiceShutdownHook,\n options?: LifecycleServiceShutdownOptions,\n ): void {\n if (this.#hasShutdown) {\n throw new Error('Attempted to add shutdown hook after shutdown');\n }\n this.#shutdownTasks.push({ hook, options });\n }\n\n async shutdown(): Promise<void> {\n if (this.#hasShutdown) {\n return;\n }\n this.#hasShutdown = true;\n\n this.logger.debug(\n `Running ${this.#shutdownTasks.length} shutdown tasks...`,\n );\n await Promise.all(\n this.#shutdownTasks.map(async ({ hook, options }) => {\n const logger = options?.logger ?? this.logger;\n try {\n await hook();\n logger.debug(`Shutdown hook succeeded`);\n } catch (error) {\n logger.error(`Shutdown hook failed, ${error}`);\n }\n }),\n );\n }\n}\n\n/**\n * Registration of backend startup and shutdown lifecycle hooks.\n *\n * See {@link @backstage/code-plugin-api#RootLifecycleService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLifecycleServiceFactory = createServiceFactory({\n service: coreServices.rootLifecycle,\n deps: {\n logger: coreServices.rootLogger,\n },\n async factory({ logger }) {\n return new BackendLifecycleImpl(logger);\n },\n});\n"],"names":["createServiceFactory","coreServices"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"WinstonLogger.cjs.js","sources":["../../../src/entrypoints/rootLogger/WinstonLogger.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { Format, TransformableInfo } from 'logform';\nimport {\n Logger,\n format,\n createLogger,\n transports,\n transport as Transport,\n config as winstonConfig,\n} from 'winston';\nimport { MESSAGE } from 'triple-beam';\nimport { escapeRegExp } from '../../lib/escapeRegExp';\nimport { winstonLevels, WinstonLoggerLevelOverride } from './types';\nimport { createLogMatcher } from './utils';\n\n/**\n * @public\n */\nexport interface WinstonLoggerOptions {\n meta?: JsonObject;\n level?: string;\n format?: Format;\n transports?: Transport[];\n}\n\n/**\n * A {@link @backstage/backend-plugin-api#LoggerService} implementation based on winston.\n *\n * @public\n */\nexport class WinstonLogger implements RootLoggerService {\n #winston: Logger;\n #addRedactions?: (redactions: Iterable<string>) => void;\n #setLevelOverrides?: (overrides: WinstonLoggerLevelOverride[]) => void;\n\n /**\n * Creates a {@link WinstonLogger} instance.\n */\n static create(options: WinstonLoggerOptions): WinstonLogger {\n const defaultLogLevel = process.env.LOG_LEVEL || options.level || 'info';\n\n const redacter = WinstonLogger.redacter();\n const logLevelFilter = WinstonLogger.logLevelFilter(defaultLogLevel);\n\n const defaultFormatter =\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat();\n\n let logger = createLogger({\n // Lowest level possible as we let the logLevelFilter do the filtering\n level: 'silly',\n format: format.combine(\n logLevelFilter.format,\n options.format ?? defaultFormatter,\n redacter.format,\n ),\n transports: options.transports ?? new transports.Console(),\n });\n\n if (options.meta) {\n logger = logger.child(options.meta);\n }\n\n return new WinstonLogger(logger, redacter.add, logLevelFilter.setOverrides);\n }\n\n /**\n * Creates a winston log formatter for redacting secrets.\n */\n static redacter(): {\n format: Format;\n add: (redactions: Iterable<string>) => void;\n } {\n const redactionSet = new Set<string>();\n\n let redactionPattern: RegExp | undefined = undefined;\n\n return {\n format: format((obj: TransformableInfo) => {\n if (!redactionPattern || !obj) {\n return obj;\n }\n\n if (typeof obj[MESSAGE] === 'string') {\n obj[MESSAGE] = obj[MESSAGE].replace(redactionPattern, '***');\n }\n\n return obj;\n })(),\n add(newRedactions) {\n let added = 0;\n for (const redactionToTrim of newRedactions) {\n // Skip null or undefined values\n if (redactionToTrim === null || redactionToTrim === undefined) {\n continue;\n }\n // Trimming the string ensures that we don't accdentally get extra\n // newlines or other whitespace interfering with the redaction; this\n // can happen for example when using string literals in yaml\n const redaction = redactionToTrim.trim();\n // Exclude secrets that are empty or just one character in length. These\n // typically mean that you are running local dev or tests, or using the\n // --lax flag which sets things to just 'x'.\n if (redaction.length <= 1) {\n continue;\n }\n if (!redactionSet.has(redaction)) {\n redactionSet.add(redaction);\n added += 1;\n }\n }\n if (added > 0) {\n const redactions = Array.from(redactionSet)\n .map(r => escapeRegExp(r))\n .join('|');\n redactionPattern = new RegExp(`(${redactions})`, 'g');\n }\n },\n };\n }\n\n /**\n * Creates a pretty printed winston log formatter.\n */\n static colorFormat(): Format {\n const colorizer = format.colorize();\n\n return format.combine(\n format.timestamp(),\n format.colorize({\n colors: {\n timestamp: 'dim',\n prefix: 'blue',\n field: 'cyan',\n debug: 'grey',\n },\n }),\n format.printf((info: TransformableInfo) => {\n const { timestamp, level, message, plugin, service, ...fields } = info;\n const prefix = plugin || service;\n const timestampColor = colorizer.colorize(\n 'timestamp',\n String(timestamp),\n );\n const prefixColor = colorizer.colorize('prefix', String(prefix));\n\n const extraFields = Object.entries(fields)\n .map(([key, value]) => {\n let stringValue = '';\n\n try {\n stringValue = JSON.stringify(value);\n } catch (e) {\n stringValue = '[field value not castable to string]';\n }\n\n return `${colorizer.colorize('field', `${key}`)}=${stringValue}`;\n })\n .join(' ');\n\n return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;\n }),\n );\n }\n\n /**\n * Formatter that filters log levels using overrides, falling back to the default level when no criteria match.\n */\n static logLevelFilter(\n defaultLogLevel: keyof winstonConfig.NpmConfigSetLevels,\n ): {\n format: Format;\n setOverrides: (overrides: WinstonLoggerLevelOverride[]) => void;\n } {\n const overrides: {\n predicate: (log: TransformableInfo) => boolean;\n level: string;\n }[] = [];\n\n return {\n format: format(log => {\n for (const override of overrides) {\n if (override.predicate(log)) {\n // Discard the log if the log level is below the override\n // eg, if the override level is 'warn' (1) and the log is 'debug' (5)\n if (winstonLevels[log.level] > winstonLevels[override.level]) {\n return false;\n }\n\n return log;\n }\n }\n\n // Ignore logs that are below the global level\n // eg, if the global level is 'warn' (1) and the log level is 'debug' (5)\n if (winstonLevels[log.level] > winstonLevels[defaultLogLevel]) {\n return false;\n }\n\n return log;\n })(),\n setOverrides: newOverrides => {\n const newOverridesPredicates = newOverrides.map(o => ({\n predicate: createLogMatcher(o.matchers),\n level: o.level,\n }));\n // Replace the content while preserving the reference to support live config updates\n overrides.splice(0, overrides.length, ...newOverridesPredicates);\n },\n };\n }\n\n private constructor(\n winston: Logger,\n addRedactions?: (redactions: Iterable<string>) => void,\n setLevelOverrides?: (overrides: WinstonLoggerLevelOverride[]) => void,\n ) {\n this.#winston = winston;\n this.#addRedactions = addRedactions;\n this.#setLevelOverrides = setLevelOverrides;\n }\n\n error(message: string, meta?: JsonObject): void {\n this.#winston.error(message, meta);\n }\n\n warn(message: string, meta?: JsonObject): void {\n this.#winston.warn(message, meta);\n }\n\n info(message: string, meta?: JsonObject): void {\n this.#winston.info(message, meta);\n }\n\n debug(message: string, meta?: JsonObject): void {\n this.#winston.debug(message, meta);\n }\n\n child(meta: JsonObject): LoggerService {\n return new WinstonLogger(this.#winston.child(meta));\n }\n\n addRedactions(redactions: Iterable<string>) {\n this.#addRedactions?.(redactions);\n }\n\n setLevelOverrides(overrides: WinstonLoggerLevelOverride[]) {\n this.#setLevelOverrides?.(overrides);\n }\n}\n"],"names":["format","createLogger","transports","MESSAGE","escapeRegExp","winstonLevels","createLogMatcher"],"mappings":"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"}
1
+ {"version":3,"file":"WinstonLogger.cjs.js","sources":["../../../src/entrypoints/rootLogger/WinstonLogger.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { Format, TransformableInfo } from 'logform';\nimport {\n Logger,\n format,\n createLogger,\n transports,\n transport as Transport,\n config as winstonConfig,\n} from 'winston';\nimport { MESSAGE } from 'triple-beam';\nimport { escapeRegExp } from '../../lib/escapeRegExp';\nimport { winstonLevels, WinstonLoggerLevelOverride } from './types';\nimport { createLogMatcher } from './utils';\n\n/**\n * @public\n */\nexport interface WinstonLoggerOptions {\n meta?: JsonObject;\n level?: string;\n format?: Format;\n transports?: Transport[];\n}\n\n/**\n * A {@link @backstage/backend-plugin-api#LoggerService} implementation based on winston.\n *\n * @public\n */\nexport class WinstonLogger implements RootLoggerService {\n #winston: Logger;\n #addRedactions?: (redactions: Iterable<string>) => void;\n #setLevelOverrides?: (overrides: WinstonLoggerLevelOverride[]) => void;\n\n /**\n * Creates a {@link WinstonLogger} instance.\n */\n static create(options: WinstonLoggerOptions): WinstonLogger {\n const defaultLogLevel = process.env.LOG_LEVEL || options.level || 'info';\n\n const redacter = WinstonLogger.redacter();\n const logLevelFilter = WinstonLogger.logLevelFilter(defaultLogLevel);\n\n const defaultFormatter =\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat();\n\n let logger = createLogger({\n // Lowest level possible as we let the logLevelFilter do the filtering\n level: 'silly',\n format: format.combine(\n logLevelFilter.format,\n options.format ?? defaultFormatter,\n redacter.format,\n ),\n transports: options.transports ?? new transports.Console(),\n });\n\n if (options.meta) {\n logger = logger.child(options.meta);\n }\n\n return new WinstonLogger(logger, redacter.add, logLevelFilter.setOverrides);\n }\n\n /**\n * Creates a winston log formatter for redacting secrets.\n */\n static redacter(): {\n format: Format;\n add: (redactions: Iterable<string>) => void;\n } {\n const redactionSet = new Set<string>();\n\n let redactionPattern: RegExp | undefined = undefined;\n\n return {\n format: format((obj: TransformableInfo) => {\n if (!redactionPattern || !obj) {\n return obj;\n }\n\n if (typeof obj[MESSAGE] === 'string') {\n obj[MESSAGE] = obj[MESSAGE].replace(redactionPattern, '***');\n }\n\n return obj;\n })(),\n add(newRedactions) {\n let added = 0;\n for (const redactionToTrim of newRedactions) {\n // Skip null or undefined values\n if (redactionToTrim === null || redactionToTrim === undefined) {\n continue;\n }\n // Trimming the string ensures that we don't accidentally get extra\n // newlines or other whitespace interfering with the redaction; this\n // can happen for example when using string literals in yaml\n const redaction = redactionToTrim.trim();\n // Exclude secrets that are empty or just one character in length. These\n // typically mean that you are running local dev or tests, or using the\n // --lax flag which sets things to just 'x'.\n if (redaction.length <= 1) {\n continue;\n }\n if (!redactionSet.has(redaction)) {\n redactionSet.add(redaction);\n added += 1;\n }\n }\n if (added > 0) {\n const redactions = Array.from(redactionSet)\n .map(r => escapeRegExp(r))\n .join('|');\n redactionPattern = new RegExp(`(${redactions})`, 'g');\n }\n },\n };\n }\n\n /**\n * Creates a pretty printed winston log formatter.\n */\n static colorFormat(): Format {\n const colorizer = format.colorize();\n\n return format.combine(\n format.timestamp(),\n format.colorize({\n colors: {\n timestamp: 'dim',\n prefix: 'blue',\n field: 'cyan',\n debug: 'grey',\n },\n }),\n format.printf((info: TransformableInfo) => {\n const { timestamp, level, message, plugin, service, ...fields } = info;\n const prefix = plugin || service;\n const timestampColor = colorizer.colorize(\n 'timestamp',\n String(timestamp),\n );\n const prefixColor = colorizer.colorize('prefix', String(prefix));\n\n const extraFields = Object.entries(fields)\n .map(([key, value]) => {\n let stringValue = '';\n\n try {\n stringValue = JSON.stringify(value);\n } catch (e) {\n stringValue = '[field value not castable to string]';\n }\n\n return `${colorizer.colorize('field', `${key}`)}=${stringValue}`;\n })\n .join(' ');\n\n return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;\n }),\n );\n }\n\n /**\n * Formatter that filters log levels using overrides, falling back to the default level when no criteria match.\n */\n static logLevelFilter(\n defaultLogLevel: keyof winstonConfig.NpmConfigSetLevels,\n ): {\n format: Format;\n setOverrides: (overrides: WinstonLoggerLevelOverride[]) => void;\n } {\n const overrides: {\n predicate: (log: TransformableInfo) => boolean;\n level: string;\n }[] = [];\n\n return {\n format: format(log => {\n for (const override of overrides) {\n if (override.predicate(log)) {\n // Discard the log if the log level is below the override\n // eg, if the override level is 'warn' (1) and the log is 'debug' (5)\n if (winstonLevels[log.level] > winstonLevels[override.level]) {\n return false;\n }\n\n return log;\n }\n }\n\n // Ignore logs that are below the global level\n // eg, if the global level is 'warn' (1) and the log level is 'debug' (5)\n if (winstonLevels[log.level] > winstonLevels[defaultLogLevel]) {\n return false;\n }\n\n return log;\n })(),\n setOverrides: newOverrides => {\n const newOverridesPredicates = newOverrides.map(o => ({\n predicate: createLogMatcher(o.matchers),\n level: o.level,\n }));\n // Replace the content while preserving the reference to support live config updates\n overrides.splice(0, overrides.length, ...newOverridesPredicates);\n },\n };\n }\n\n private constructor(\n winston: Logger,\n addRedactions?: (redactions: Iterable<string>) => void,\n setLevelOverrides?: (overrides: WinstonLoggerLevelOverride[]) => void,\n ) {\n this.#winston = winston;\n this.#addRedactions = addRedactions;\n this.#setLevelOverrides = setLevelOverrides;\n }\n\n error(message: string, meta?: JsonObject): void {\n this.#winston.error(message, meta);\n }\n\n warn(message: string, meta?: JsonObject): void {\n this.#winston.warn(message, meta);\n }\n\n info(message: string, meta?: JsonObject): void {\n this.#winston.info(message, meta);\n }\n\n debug(message: string, meta?: JsonObject): void {\n this.#winston.debug(message, meta);\n }\n\n child(meta: JsonObject): LoggerService {\n return new WinstonLogger(this.#winston.child(meta));\n }\n\n addRedactions(redactions: Iterable<string>) {\n this.#addRedactions?.(redactions);\n }\n\n setLevelOverrides(overrides: WinstonLoggerLevelOverride[]) {\n this.#setLevelOverrides?.(overrides);\n }\n}\n"],"names":["format","createLogger","transports","MESSAGE","escapeRegExp","winstonLevels","createLogMatcher"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.cjs.js","sources":["../../../src/entrypoints/rootLogger/config.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 { RootConfigService } from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport {\n RootLoggerConfig,\n winstonLevels,\n WinstonLoggerLevelOverrideMatchers,\n} from './types';\n\nexport const getRootLoggerConfig = (\n config: RootConfigService,\n): RootLoggerConfig => {\n const level = config.getOptionalString('backend.logger.level');\n const meta = config\n .getOptionalConfig('backend.logger.meta')\n ?.get<JsonObject>();\n\n const overridesConfig = config.getOptionalConfigArray(\n 'backend.logger.overrides',\n );\n const overrides = overridesConfig?.map((override, i) => {\n const overrideLevel = override.getString('level');\n if (winstonLevels[overrideLevel] === undefined) {\n throw new Error(\n `Invalid config at backend.logger.overrides[${i}].level, '${overrideLevel}' is not a valid logging level, must be one of 'error', 'warn', 'info' or 'debug'.`,\n );\n }\n\n const matchers = override\n .getConfig('matchers')\n .get<WinstonLoggerLevelOverrideMatchers>();\n\n return {\n matchers,\n level: overrideLevel,\n };\n });\n\n return {\n meta,\n level,\n overrides,\n };\n};\n"],"names":["winstonLevels"],"mappings":";;;;AAuBO,MAAM,mBAAA,GAAsB,CACjC,MAAA,KACqB;AACrB,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,sBAAsB,CAAA;AAC7D,EAAA,MAAM,IAAA,GAAO,MAAA,CACV,iBAAA,CAAkB,qBAAqB,GACtC,GAAA,EAAgB;AAEpB,EAAA,MAAM,kBAAkB,MAAA,CAAO,sBAAA;AAAA,IAC7B;AAAA,GACF;AACA,EAAA,MAAM,SAAA,GAAY,eAAA,EAAiB,GAAA,CAAI,CAAC,UAAU,CAAA,KAAM;AACtD,IAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,SAAA,CAAU,OAAO,CAAA;AAChD,IAAA,IAAIA,mBAAA,CAAc,aAAa,CAAA,KAAM,MAAA,EAAW;AAC9C,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,2CAAA,EAA8C,CAAC,CAAA,UAAA,EAAa,aAAa,CAAA,kFAAA;AAAA,OAC3E;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,QAAA,CACd,SAAA,CAAU,UAAU,EACpB,GAAA,EAAwC;AAE3C,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACT;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"config.cjs.js","sources":["../../../src/entrypoints/rootLogger/config.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 { RootConfigService } from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport {\n RootLoggerConfig,\n winstonLevels,\n WinstonLoggerLevelOverrideMatchers,\n} from './types';\n\nexport const getRootLoggerConfig = (\n config: RootConfigService,\n): RootLoggerConfig => {\n const level = config.getOptionalString('backend.logger.level');\n const meta = config\n .getOptionalConfig('backend.logger.meta')\n ?.get<JsonObject>();\n\n const overridesConfig = config.getOptionalConfigArray(\n 'backend.logger.overrides',\n );\n const overrides = overridesConfig?.map((override, i) => {\n const overrideLevel = override.getString('level');\n if (winstonLevels[overrideLevel] === undefined) {\n throw new Error(\n `Invalid config at backend.logger.overrides[${i}].level, '${overrideLevel}' is not a valid logging level, must be one of 'error', 'warn', 'info' or 'debug'.`,\n );\n }\n\n const matchers = override\n .getConfig('matchers')\n .get<WinstonLoggerLevelOverrideMatchers>();\n\n return {\n matchers,\n level: overrideLevel,\n };\n });\n\n return {\n meta,\n level,\n overrides,\n };\n};\n"],"names":["winstonLevels"],"mappings":";;;;AAuBO,MAAM,mBAAA,GAAsB,CACjC,MAAA,KACqB;AACrB,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,sBAAsB,CAAA;AAC7D,EAAA,MAAM,IAAA,GAAO,MAAA,CACV,iBAAA,CAAkB,qBAAqB,GACtC,GAAA,EAAgB;AAEpB,EAAA,MAAM,kBAAkB,MAAA,CAAO,sBAAA;AAAA,IAC7B;AAAA,GACF;AACA,EAAA,MAAM,SAAA,GAAY,eAAA,EAAiB,GAAA,CAAI,CAAC,UAAU,CAAA,KAAM;AACtD,IAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,SAAA,CAAU,OAAO,CAAA;AAChD,IAAA,IAAIA,mBAAA,CAAc,aAAa,CAAA,KAAM,MAAA,EAAW;AAC9C,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,2CAAA,EAA8C,CAAC,CAAA,UAAA,EAAa,aAAa,CAAA,kFAAA;AAAA,OAC3E;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,QAAA,CACd,SAAA,CAAU,UAAU,EACpB,GAAA,EAAwC;AAE3C,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACT;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"rootLoggerServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLogger/rootLoggerServiceFactory.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 {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { format, transports } from 'winston';\nimport { createConfigSecretEnumerator } from '../rootConfig/createConfigSecretEnumerator';\nimport { WinstonLogger } from '../rootLogger/WinstonLogger';\nimport { getRootLoggerConfig } from './config';\n\n/**\n * Root-level logging.\n *\n * See {@link @backstage/backend-plugin-api#RootLoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLoggerServiceFactory = createServiceFactory({\n service: coreServices.rootLogger,\n deps: {\n config: coreServices.rootConfig,\n },\n async factory({ config }) {\n const rootLoggerConfig = getRootLoggerConfig(config);\n\n const logger = WinstonLogger.create({\n meta: {\n service: 'backstage',\n ...rootLoggerConfig.meta,\n },\n level: process.env.LOG_LEVEL || rootLoggerConfig.level || 'info',\n format:\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat(),\n transports: [new transports.Console()],\n });\n\n const secretEnumerator = await createConfigSecretEnumerator({ logger });\n logger.addRedactions(secretEnumerator(config));\n config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));\n\n logger.setLevelOverrides(rootLoggerConfig.overrides ?? []);\n config.subscribe?.(() =>\n logger.setLevelOverrides(getRootLoggerConfig(config).overrides ?? []),\n );\n\n return logger;\n },\n});\n"],"names":["createServiceFactory","coreServices","config","getRootLoggerConfig","WinstonLogger","format","transports","createConfigSecretEnumerator"],"mappings":";;;;;;;;AAkCO,MAAM,2BAA2BA,qCAAA,CAAqB;AAAA,EAC3D,SAASC,6BAAA,CAAa,UAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa;AAAA,GACvB;AAAA,EACA,MAAM,OAAA,CAAQ,UAAEC,QAAA,EAAO,EAAG;AACxB,IAAA,MAAM,gBAAA,GAAmBC,2BAAoBD,QAAM,CAAA;AAEnD,IAAA,MAAM,MAAA,GAASE,4BAAc,MAAA,CAAO;AAAA,MAClC,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS,WAAA;AAAA,QACT,GAAG,gBAAA,CAAiB;AAAA,OACtB;AAAA,MACA,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,SAAA,IAAa,iBAAiB,KAAA,IAAS,MAAA;AAAA,MAC1D,MAAA,EACE,QAAQ,GAAA,CAAI,QAAA,KAAa,eACrBC,cAAA,CAAO,IAAA,EAAK,GACZD,2BAAA,CAAc,WAAA,EAAY;AAAA,MAChC,UAAA,EAAY,CAAC,IAAIE,kBAAA,CAAW,SAAS;AAAA,KACtC,CAAA;AAED,IAAA,MAAM,gBAAA,GAAmB,MAAMC,yDAAA,CAA6B,EAAE,QAAQ,CAAA;AACtE,IAAA,MAAA,CAAO,aAAA,CAAc,gBAAA,CAAiBL,QAAM,CAAC,CAAA;AAC7C,IAAAA,QAAA,CAAO,YAAY,MAAM,MAAA,CAAO,cAAc,gBAAA,CAAiBA,QAAM,CAAC,CAAC,CAAA;AAEvE,IAAA,MAAA,CAAO,iBAAA,CAAkB,gBAAA,CAAiB,SAAA,IAAa,EAAE,CAAA;AACzD,IAAAA,QAAA,CAAO,SAAA;AAAA,MAAY,MACjB,OAAO,iBAAA,CAAkBC,0BAAA,CAAoBD,QAAM,CAAA,CAAE,SAAA,IAAa,EAAE;AAAA,KACtE;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"rootLoggerServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootLogger/rootLoggerServiceFactory.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 {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { format, transports } from 'winston';\nimport { createConfigSecretEnumerator } from '../rootConfig/createConfigSecretEnumerator';\nimport { WinstonLogger } from '../rootLogger/WinstonLogger';\nimport { getRootLoggerConfig } from './config';\n\n/**\n * Root-level logging.\n *\n * See {@link @backstage/backend-plugin-api#RootLoggerService}\n * and {@link https://backstage.io/docs/backend-system/core-services/root-logger | the service docs}\n * for more information.\n *\n * @public\n */\nexport const rootLoggerServiceFactory = createServiceFactory({\n service: coreServices.rootLogger,\n deps: {\n config: coreServices.rootConfig,\n },\n async factory({ config }) {\n const rootLoggerConfig = getRootLoggerConfig(config);\n\n const logger = WinstonLogger.create({\n meta: {\n service: 'backstage',\n ...rootLoggerConfig.meta,\n },\n level: process.env.LOG_LEVEL || rootLoggerConfig.level || 'info',\n format:\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat(),\n transports: [new transports.Console()],\n });\n\n const secretEnumerator = await createConfigSecretEnumerator({ logger });\n logger.addRedactions(secretEnumerator(config));\n config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));\n\n logger.setLevelOverrides(rootLoggerConfig.overrides ?? []);\n config.subscribe?.(() =>\n logger.setLevelOverrides(getRootLoggerConfig(config).overrides ?? []),\n );\n\n return logger;\n },\n});\n"],"names":["createServiceFactory","coreServices","config","getRootLoggerConfig","WinstonLogger","format","transports","createConfigSecretEnumerator"],"mappings":";;;;;;;;AAkCO,MAAM,2BAA2BA,qCAAA,CAAqB;AAAA,EAC3D,SAASC,6BAAA,CAAa,UAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa;AAAA,GACvB;AAAA,EACA,MAAM,OAAA,CAAQ,UAAEC,QAAA,EAAO,EAAG;AACxB,IAAA,MAAM,gBAAA,GAAmBC,2BAAoBD,QAAM,CAAA;AAEnD,IAAA,MAAM,MAAA,GAASE,4BAAc,MAAA,CAAO;AAAA,MAClC,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS,WAAA;AAAA,QACT,GAAG,gBAAA,CAAiB;AAAA,OACtB;AAAA,MACA,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,SAAA,IAAa,iBAAiB,KAAA,IAAS,MAAA;AAAA,MAC1D,MAAA,EACE,QAAQ,GAAA,CAAI,QAAA,KAAa,eACrBC,cAAA,CAAO,IAAA,EAAK,GACZD,2BAAA,CAAc,WAAA,EAAY;AAAA,MAChC,UAAA,EAAY,CAAC,IAAIE,kBAAA,CAAW,SAAS;AAAA,KACtC,CAAA;AAED,IAAA,MAAM,gBAAA,GAAmB,MAAMC,yDAAA,CAA6B,EAAE,QAAQ,CAAA;AACtE,IAAA,MAAA,CAAO,aAAA,CAAc,gBAAA,CAAiBL,QAAM,CAAC,CAAA;AAC7C,IAAAA,QAAA,CAAO,YAAY,MAAM,MAAA,CAAO,cAAc,gBAAA,CAAiBA,QAAM,CAAC,CAAC,CAAA;AAEvE,IAAA,MAAA,CAAO,iBAAA,CAAkB,gBAAA,CAAiB,SAAA,IAAa,EAAE,CAAA;AACzD,IAAAA,QAAA,CAAO,SAAA;AAAA,MAAY,MACjB,OAAO,iBAAA,CAAkBC,0BAAA,CAAoBD,QAAM,CAAA,CAAE,SAAA,IAAa,EAAE;AAAA,KACtE;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAC;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs.js","sources":["../../../src/entrypoints/rootLogger/types.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 { JsonObject, JsonPrimitive } from '@backstage/types';\nimport { config as winstonConfig } from 'winston';\n\n/**\n * @public\n */\nexport type WinstonLoggerLevelOverrideMatchers = {\n [key: string]: JsonPrimitive | JsonPrimitive[] | undefined;\n};\n\n/**\n * @public\n */\nexport type WinstonLoggerLevelOverride = {\n matchers: WinstonLoggerLevelOverrideMatchers;\n level: string;\n};\n\nexport type RootLoggerConfig = {\n level?: string;\n meta?: JsonObject;\n overrides?: WinstonLoggerLevelOverride[];\n};\n\nexport const winstonLevels = winstonConfig.npm.levels;\n"],"names":["winstonConfig"],"mappings":";;;;AAuCO,MAAM,aAAA,GAAgBA,eAAc,GAAA,CAAI;;;;"}
1
+ {"version":3,"file":"types.cjs.js","sources":["../../../src/entrypoints/rootLogger/types.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 { JsonObject, JsonPrimitive } from '@backstage/types';\nimport { config as winstonConfig } from 'winston';\n\n/**\n * @public\n */\nexport type WinstonLoggerLevelOverrideMatchers = {\n [key: string]: JsonPrimitive | JsonPrimitive[] | undefined;\n};\n\n/**\n * @public\n */\nexport type WinstonLoggerLevelOverride = {\n matchers: WinstonLoggerLevelOverrideMatchers;\n level: string;\n};\n\nexport type RootLoggerConfig = {\n level?: string;\n meta?: JsonObject;\n overrides?: WinstonLoggerLevelOverride[];\n};\n\nexport const winstonLevels = winstonConfig.npm.levels;\n"],"names":["winstonConfig"],"mappings":";;;;AAuCO,MAAM,aAAA,GAAgBA,eAAc,GAAA,CAAI;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs.js","sources":["../../../src/entrypoints/rootLogger/utils.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 */\n\nimport { TransformableInfo } from 'logform';\nimport { WinstonLoggerLevelOverrideMatchers } from './types';\n\n/** Parse a slash-delimited regex like `/pattern/flags` into a RegExp, or null if not a regex-string */\nconst parseRegex = (s: string): RegExp | null => {\n if (!s.startsWith('/')) return null;\n const lastSlash = s.lastIndexOf('/');\n if (lastSlash <= 0) return null;\n\n const pattern = s.slice(1, lastSlash);\n const flags = s.slice(lastSlash + 1);\n\n try {\n return new RegExp(pattern, flags);\n } catch {\n return null; // fall back to treating it as a plain string\n }\n};\n\n/**\n * Create a predicate function that determines whether a log field matches a given matcher.\n *\n * The matcher can be:\n * - A string (exact match or regex pattern delimited by slashes, e.g. `/pattern/`)\n * - A non-string value (compared by strict equality)\n * - An array of matchers (returns true if any matcher matches)\n *\n * @param matcher - The matcher or array of matchers to compare against the log field.\n * @returns A function that takes a log field and returns `true` if it matches the matcher, otherwise `false`.\n */\nconst createLogFieldMatcher = (\n matcher: WinstonLoggerLevelOverrideMatchers[0],\n): ((logField: unknown) => boolean) => {\n // Array of matchers: create predicates for each element and OR them together\n if (Array.isArray(matcher)) {\n const fns = matcher.map(m => createLogFieldMatcher(m));\n return (logField: unknown) => fns.some(fn => fn(logField));\n }\n\n // Non-string matcher: strict equality\n if (typeof matcher !== 'string') {\n return (logField: unknown) => logField === matcher;\n }\n\n // String matcher: maybe a slash-delimited regex (/pattern/flags)\n const regex = parseRegex(matcher);\n if (regex) {\n return (logField: unknown) =>\n typeof logField === 'string' && regex.test(logField);\n }\n\n // Plain string matcher: strict equality\n return (logField: unknown) => logField === matcher;\n};\n\n/**\n * Create a predicate function that determines whether a log entry matches\n * all specified override matchers.\n *\n * Iterates over each key-matcher pair in the provided `matchers` object,\n * retrieves the corresponding field from the `log` object, and checks if\n * the field matches the matcher using `isLogFieldMatching`. Returns `true`\n * only if all matchers are satisfied.\n *\n * @param matchers - An object where each key corresponds to a log field and each value is a matcher to test against that field.\n * @returns A function that takes a log entry and returns `true` if it matches all specified matchers, otherwise `false`.\n */\nexport const createLogMatcher = (\n matchers: WinstonLoggerLevelOverrideMatchers,\n): ((log: TransformableInfo) => boolean) => {\n const logFieldMatchers = Object.entries(matchers).map(([key, m]) => {\n const fn = createLogFieldMatcher(m);\n return [key, fn] as const;\n });\n\n return (log: TransformableInfo) =>\n logFieldMatchers.every(([key, fn]) => fn(log[key]));\n};\n"],"names":[],"mappings":";;AAoBA,MAAM,UAAA,GAAa,CAAC,CAAA,KAA6B;AAC/C,EAAA,IAAI,CAAC,CAAA,CAAE,UAAA,CAAW,GAAG,GAAG,OAAO,IAAA;AAC/B,EAAA,MAAM,SAAA,GAAY,CAAA,CAAE,WAAA,CAAY,GAAG,CAAA;AACnC,EAAA,IAAI,SAAA,IAAa,GAAG,OAAO,IAAA;AAE3B,EAAA,MAAM,OAAA,GAAU,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,KAAA,CAAM,SAAA,GAAY,CAAC,CAAA;AAEnC,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,MAAA,CAAO,OAAA,EAAS,KAAK,CAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF,CAAA;AAaA,MAAM,qBAAA,GAAwB,CAC5B,OAAA,KACqC;AAErC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1B,IAAA,MAAM,MAAM,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,qBAAA,CAAsB,CAAC,CAAC,CAAA;AACrD,IAAA,OAAO,CAAC,QAAA,KAAsB,GAAA,CAAI,KAAK,CAAA,EAAA,KAAM,EAAA,CAAG,QAAQ,CAAC,CAAA;AAAA,EAC3D;AAGA,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,OAAO,CAAC,aAAsB,QAAA,KAAa,OAAA;AAAA,EAC7C;AAGA,EAAA,MAAM,KAAA,GAAQ,WAAW,OAAO,CAAA;AAChC,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAO,CAAC,QAAA,KACN,OAAO,aAAa,QAAA,IAAY,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,EACvD;AAGA,EAAA,OAAO,CAAC,aAAsB,QAAA,KAAa,OAAA;AAC7C,CAAA;AAcO,MAAM,gBAAA,GAAmB,CAC9B,QAAA,KAC0C;AAC1C,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAI,CAAC,CAAC,GAAA,EAAK,CAAC,CAAA,KAAM;AAClE,IAAA,MAAM,EAAA,GAAK,sBAAsB,CAAC,CAAA;AAClC,IAAA,OAAO,CAAC,KAAK,EAAE,CAAA;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,OAAO,CAAC,GAAA,KACN,gBAAA,CAAiB,KAAA,CAAM,CAAC,CAAC,GAAA,EAAK,EAAE,CAAA,KAAM,EAAA,CAAG,GAAA,CAAI,GAAG,CAAC,CAAC,CAAA;AACtD;;;;"}
1
+ {"version":3,"file":"utils.cjs.js","sources":["../../../src/entrypoints/rootLogger/utils.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 */\n\nimport { TransformableInfo } from 'logform';\nimport { WinstonLoggerLevelOverrideMatchers } from './types';\n\n/** Parse a slash-delimited regex like `/pattern/flags` into a RegExp, or null if not a regex-string */\nconst parseRegex = (s: string): RegExp | null => {\n if (!s.startsWith('/')) return null;\n const lastSlash = s.lastIndexOf('/');\n if (lastSlash <= 0) return null;\n\n const pattern = s.slice(1, lastSlash);\n const flags = s.slice(lastSlash + 1);\n\n try {\n return new RegExp(pattern, flags);\n } catch {\n return null; // fall back to treating it as a plain string\n }\n};\n\n/**\n * Create a predicate function that determines whether a log field matches a given matcher.\n *\n * The matcher can be:\n * - A string (exact match or regex pattern delimited by slashes, e.g. `/pattern/`)\n * - A non-string value (compared by strict equality)\n * - An array of matchers (returns true if any matcher matches)\n *\n * @param matcher - The matcher or array of matchers to compare against the log field.\n * @returns A function that takes a log field and returns `true` if it matches the matcher, otherwise `false`.\n */\nconst createLogFieldMatcher = (\n matcher: WinstonLoggerLevelOverrideMatchers[0],\n): ((logField: unknown) => boolean) => {\n // Array of matchers: create predicates for each element and OR them together\n if (Array.isArray(matcher)) {\n const fns = matcher.map(m => createLogFieldMatcher(m));\n return (logField: unknown) => fns.some(fn => fn(logField));\n }\n\n // Non-string matcher: strict equality\n if (typeof matcher !== 'string') {\n return (logField: unknown) => logField === matcher;\n }\n\n // String matcher: maybe a slash-delimited regex (/pattern/flags)\n const regex = parseRegex(matcher);\n if (regex) {\n return (logField: unknown) =>\n typeof logField === 'string' && regex.test(logField);\n }\n\n // Plain string matcher: strict equality\n return (logField: unknown) => logField === matcher;\n};\n\n/**\n * Create a predicate function that determines whether a log entry matches\n * all specified override matchers.\n *\n * Iterates over each key-matcher pair in the provided `matchers` object,\n * retrieves the corresponding field from the `log` object, and checks if\n * the field matches the matcher using `isLogFieldMatching`. Returns `true`\n * only if all matchers are satisfied.\n *\n * @param matchers - An object where each key corresponds to a log field and each value is a matcher to test against that field.\n * @returns A function that takes a log entry and returns `true` if it matches all specified matchers, otherwise `false`.\n */\nexport const createLogMatcher = (\n matchers: WinstonLoggerLevelOverrideMatchers,\n): ((log: TransformableInfo) => boolean) => {\n const logFieldMatchers = Object.entries(matchers).map(([key, m]) => {\n const fn = createLogFieldMatcher(m);\n return [key, fn] as const;\n });\n\n return (log: TransformableInfo) =>\n logFieldMatchers.every(([key, fn]) => fn(log[key]));\n};\n"],"names":[],"mappings":";;AAoBA,MAAM,UAAA,GAAa,CAAC,CAAA,KAA6B;AAC/C,EAAA,IAAI,CAAC,CAAA,CAAE,UAAA,CAAW,GAAG,GAAG,OAAO,IAAA;AAC/B,EAAA,MAAM,SAAA,GAAY,CAAA,CAAE,WAAA,CAAY,GAAG,CAAA;AACnC,EAAA,IAAI,SAAA,IAAa,GAAG,OAAO,IAAA;AAE3B,EAAA,MAAM,OAAA,GAAU,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,KAAA,CAAM,SAAA,GAAY,CAAC,CAAA;AAEnC,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,MAAA,CAAO,OAAA,EAAS,KAAK,CAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF,CAAA;AAaA,MAAM,qBAAA,GAAwB,CAC5B,OAAA,KACqC;AAErC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1B,IAAA,MAAM,MAAM,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,qBAAA,CAAsB,CAAC,CAAC,CAAA;AACrD,IAAA,OAAO,CAAC,QAAA,KAAsB,GAAA,CAAI,KAAK,CAAA,EAAA,KAAM,EAAA,CAAG,QAAQ,CAAC,CAAA;AAAA,EAC3D;AAGA,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,OAAO,CAAC,aAAsB,QAAA,KAAa,OAAA;AAAA,EAC7C;AAGA,EAAA,MAAM,KAAA,GAAQ,WAAW,OAAO,CAAA;AAChC,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAO,CAAC,QAAA,KACN,OAAO,aAAa,QAAA,IAAY,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,EACvD;AAGA,EAAA,OAAO,CAAC,aAAsB,QAAA,KAAa,OAAA;AAC7C,CAAA;AAcO,MAAM,gBAAA,GAAmB,CAC9B,QAAA,KAC0C;AAC1C,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAI,CAAC,CAAC,GAAA,EAAK,CAAC,CAAA,KAAM;AAClE,IAAA,MAAM,EAAA,GAAK,sBAAsB,CAAC,CAAA;AAClC,IAAA,OAAO,CAAC,KAAK,EAAE,CAAA;AAAA,EACjB,CAAC,CAAA;AAED,EAAA,OAAO,CAAC,GAAA,KACN,gBAAA,CAAiB,KAAA,CAAM,CAAC,CAAC,GAAA,EAAK,EAAE,CAAA,KAAM,EAAA,CAAG,GAAA,CAAI,GAAG,CAAC,CAAC,CAAA;AACtD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultRootSystemMetadataService.cjs.js","sources":["../../../../src/entrypoints/rootSystemMetadata/lib/DefaultRootSystemMetadataService.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 LoggerService,\n RootConfigService,\n RootInstanceMetadataService,\n RootSystemMetadataService,\n RootSystemMetadataServicePluginInfo,\n} from '@backstage/backend-plugin-api';\nimport { getEndpoints } from '../../discovery/parsing';\nimport { Config } from '@backstage/config';\n\nfunction getPlugins(config: Config): string[] {\n const endpoints = getEndpoints(config);\n return Array.from(new Set(endpoints.flatMap(endpoint => endpoint.plugins)));\n}\n\n/**\n * @public\n */\nexport class DefaultRootSystemMetadataService\n implements RootSystemMetadataService\n{\n #plugins: string[];\n #instanceMetadata: RootInstanceMetadataService;\n constructor(options: {\n logger: LoggerService;\n config: RootConfigService;\n instanceMetadata: RootInstanceMetadataService;\n }) {\n const { config } = options;\n this.#plugins = getPlugins(config);\n config.subscribe?.(() => {\n this.#plugins = getPlugins(config);\n });\n this.#instanceMetadata = options.instanceMetadata;\n }\n\n public static create(pluginEnv: {\n logger: LoggerService;\n config: RootConfigService;\n instanceMetadata: RootInstanceMetadataService;\n }) {\n return new DefaultRootSystemMetadataService(pluginEnv);\n }\n\n public async getInstalledPlugins(): Promise<\n RootSystemMetadataServicePluginInfo[]\n > {\n const plugins = this.#plugins.map(pluginId => ({ pluginId }));\n\n for (const plugin of await this.#instanceMetadata.getInstalledPlugins()) {\n plugins.push({ pluginId: plugin.pluginId });\n }\n\n return plugins;\n }\n}\n"],"names":["getEndpoints"],"mappings":";;;;AA0BA,SAAS,WAAW,MAAA,EAA0B;AAC5C,EAAA,MAAM,SAAA,GAAYA,qBAAa,MAAM,CAAA;AACrC,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,SAAA,CAAU,QAAQ,CAAA,QAAA,KAAY,QAAA,CAAS,OAAO,CAAC,CAAC,CAAA;AAC5E;AAKO,MAAM,gCAAA,CAEb;AAAA,EACE,QAAA;AAAA,EACA,iBAAA;AAAA,EACA,YAAY,OAAA,EAIT;AACD,IAAA,MAAM,EAAE,QAAO,GAAI,OAAA;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,WAAW,MAAM,CAAA;AACjC,IAAA,MAAA,CAAO,YAAY,MAAM;AACvB,MAAA,IAAA,CAAK,QAAA,GAAW,WAAW,MAAM,CAAA;AAAA,IACnC,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,oBAAoB,OAAA,CAAQ,gBAAA;AAAA,EACnC;AAAA,EAEA,OAAc,OAAO,SAAA,EAIlB;AACD,IAAA,OAAO,IAAI,iCAAiC,SAAS,CAAA;AAAA,EACvD;AAAA,EAEA,MAAa,mBAAA,GAEX;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,QAAA,MAAa,EAAE,UAAS,CAAE,CAAA;AAE5D,IAAA,KAAA,MAAW,MAAA,IAAU,MAAM,IAAA,CAAK,iBAAA,CAAkB,qBAAoB,EAAG;AACvE,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,QAAA,EAAU,MAAA,CAAO,UAAU,CAAA;AAAA,IAC5C;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"DefaultRootSystemMetadataService.cjs.js","sources":["../../../../src/entrypoints/rootSystemMetadata/lib/DefaultRootSystemMetadataService.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 LoggerService,\n RootConfigService,\n RootInstanceMetadataService,\n RootSystemMetadataService,\n RootSystemMetadataServicePluginInfo,\n} from '@backstage/backend-plugin-api';\nimport { getEndpoints } from '../../discovery/parsing';\nimport { Config } from '@backstage/config';\n\nfunction getPlugins(config: Config): string[] {\n const endpoints = getEndpoints(config);\n return Array.from(new Set(endpoints.flatMap(endpoint => endpoint.plugins)));\n}\n\n/**\n * @public\n */\nexport class DefaultRootSystemMetadataService\n implements RootSystemMetadataService\n{\n #plugins: string[];\n #instanceMetadata: RootInstanceMetadataService;\n constructor(options: {\n logger: LoggerService;\n config: RootConfigService;\n instanceMetadata: RootInstanceMetadataService;\n }) {\n const { config } = options;\n this.#plugins = getPlugins(config);\n config.subscribe?.(() => {\n this.#plugins = getPlugins(config);\n });\n this.#instanceMetadata = options.instanceMetadata;\n }\n\n public static create(pluginEnv: {\n logger: LoggerService;\n config: RootConfigService;\n instanceMetadata: RootInstanceMetadataService;\n }) {\n return new DefaultRootSystemMetadataService(pluginEnv);\n }\n\n public async getInstalledPlugins(): Promise<\n RootSystemMetadataServicePluginInfo[]\n > {\n const plugins = this.#plugins.map(pluginId => ({ pluginId }));\n\n for (const plugin of await this.#instanceMetadata.getInstalledPlugins()) {\n plugins.push({ pluginId: plugin.pluginId });\n }\n\n return plugins;\n }\n}\n"],"names":["getEndpoints"],"mappings":";;;;AA0BA,SAAS,WAAW,MAAA,EAA0B;AAC5C,EAAA,MAAM,SAAA,GAAYA,qBAAa,MAAM,CAAA;AACrC,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,SAAA,CAAU,QAAQ,CAAA,QAAA,KAAY,QAAA,CAAS,OAAO,CAAC,CAAC,CAAA;AAC5E;AAKO,MAAM,gCAAA,CAEb;AAAA,EACE,QAAA;AAAA,EACA,iBAAA;AAAA,EACA,YAAY,OAAA,EAIT;AACD,IAAA,MAAM,EAAE,QAAO,GAAI,OAAA;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,WAAW,MAAM,CAAA;AACjC,IAAA,MAAA,CAAO,YAAY,MAAM;AACvB,MAAA,IAAA,CAAK,QAAA,GAAW,WAAW,MAAM,CAAA;AAAA,IACnC,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,oBAAoB,OAAA,CAAQ,gBAAA;AAAA,EACnC;AAAA,EAEA,OAAc,OAAO,SAAA,EAIlB;AACD,IAAA,OAAO,IAAI,iCAAiC,SAAS,CAAA;AAAA,EACvD;AAAA,EAEA,MAAa,mBAAA,GAEX;AACA,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,QAAA,MAAa,EAAE,UAAS,CAAE,CAAA;AAE5D,IAAA,KAAA,MAAW,MAAA,IAAU,MAAM,IAAA,CAAK,iBAAA,CAAkB,qBAAoB,EAAG;AACvE,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,QAAA,EAAU,MAAA,CAAO,UAAU,CAAA;AAAA,IAC5C;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"rootSystemMetadataServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootSystemMetadata/rootSystemMetadataServiceFactory.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 { DefaultRootSystemMetadataService } from './lib/DefaultRootSystemMetadataService';\n\n/**\n * Metadata about an entire Backstage system, a collection of Backstage instances.\n *\n * @public\n */\nexport const rootSystemMetadataServiceFactory = createServiceFactory({\n service: coreServices.rootSystemMetadata,\n deps: {\n logger: coreServices.rootLogger,\n config: coreServices.rootConfig,\n instanceMetadata: coreServices.rootInstanceMetadata,\n },\n async factory({ logger, config, instanceMetadata }) {\n return DefaultRootSystemMetadataService.create({\n logger,\n config,\n instanceMetadata,\n });\n },\n});\n"],"names":["createServiceFactory","coreServices","DefaultRootSystemMetadataService"],"mappings":";;;;;AA2BO,MAAM,mCAAmCA,qCAAA,CAAqB;AAAA,EACnE,SAASC,6BAAA,CAAa,kBAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,kBAAkBA,6BAAA,CAAa;AAAA,GACjC;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,kBAAiB,EAAG;AAClD,IAAA,OAAOC,kEAAiC,MAAA,CAAO;AAAA,MAC7C,MAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"rootSystemMetadataServiceFactory.cjs.js","sources":["../../../src/entrypoints/rootSystemMetadata/rootSystemMetadataServiceFactory.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 { DefaultRootSystemMetadataService } from './lib/DefaultRootSystemMetadataService';\n\n/**\n * Metadata about an entire Backstage system, a collection of Backstage instances.\n *\n * @public\n */\nexport const rootSystemMetadataServiceFactory = createServiceFactory({\n service: coreServices.rootSystemMetadata,\n deps: {\n logger: coreServices.rootLogger,\n config: coreServices.rootConfig,\n instanceMetadata: coreServices.rootInstanceMetadata,\n },\n async factory({ logger, config, instanceMetadata }) {\n return DefaultRootSystemMetadataService.create({\n logger,\n config,\n instanceMetadata,\n });\n },\n});\n"],"names":["createServiceFactory","coreServices","DefaultRootSystemMetadataService"],"mappings":";;;;;AA2BO,MAAM,mCAAmCA,qCAAA,CAAqB;AAAA,EACnE,SAASC,6BAAA,CAAa,kBAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,kBAAkBA,6BAAA,CAAa;AAAA,GACjC;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,kBAAiB,EAAG;AAClD,IAAA,OAAOC,kEAAiC,MAAA,CAAO;AAAA,MAC7C,MAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrateBackendTasks.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/migrateBackendTasks.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 { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Knex } from 'knex';\nimport { DB_MIGRATIONS_TABLE } from './tables';\n\nexport const migrationsDir = resolvePackagePath(\n '@backstage/backend-defaults',\n 'migrations/scheduler',\n);\n\nexport async function migrateBackendTasks(knex: Knex): Promise<void> {\n await knex.migrate.latest({\n directory: migrationsDir,\n tableName: DB_MIGRATIONS_TABLE,\n });\n}\n"],"names":["resolvePackagePath","DB_MIGRATIONS_TABLE"],"mappings":";;;;;AAoBO,MAAM,aAAA,GAAgBA,mCAAA;AAAA,EAC3B,6BAAA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB,IAAA,EAA2B;AACnE,EAAA,MAAM,IAAA,CAAK,QAAQ,MAAA,CAAO;AAAA,IACxB,SAAA,EAAW,aAAA;AAAA,IACX,SAAA,EAAWC;AAAA,GACZ,CAAA;AACH;;;;;"}
1
+ {"version":3,"file":"migrateBackendTasks.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/migrateBackendTasks.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 { resolvePackagePath } from '@backstage/backend-plugin-api';\nimport { Knex } from 'knex';\nimport { DB_MIGRATIONS_TABLE } from './tables';\n\nexport const migrationsDir = resolvePackagePath(\n '@backstage/backend-defaults',\n 'migrations/scheduler',\n);\n\nexport async function migrateBackendTasks(knex: Knex): Promise<void> {\n await knex.migrate.latest({\n directory: migrationsDir,\n tableName: DB_MIGRATIONS_TABLE,\n });\n}\n"],"names":["resolvePackagePath","DB_MIGRATIONS_TABLE"],"mappings":";;;;;AAoBO,MAAM,aAAA,GAAgBA,mCAAA;AAAA,EAC3B,6BAAA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB,IAAA,EAA2B;AACnE,EAAA,MAAM,IAAA,CAAK,QAAQ,MAAA,CAAO;AAAA,IACxB,SAAA,EAAW,aAAA;AAAA,IACX,SAAA,EAAWC;AAAA,GACZ,CAAA;AACH;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"tables.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/tables.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\nexport const DB_MIGRATIONS_TABLE = 'backstage_backend_tasks__knex_migrations';\nexport const DB_TASKS_TABLE = 'backstage_backend_tasks__tasks';\n\nexport type DbTasksRow = {\n id: string;\n settings_json: string;\n next_run_start_at?: Date | string; // This can be null when in manual trigger mode\n current_run_ticket?: string;\n current_run_started_at?: Date | string;\n current_run_expires_at?: Date | string;\n last_run_error_json?: string;\n last_run_ended_at?: Date | string;\n};\n"],"names":[],"mappings":";;AAgBO,MAAM,mBAAA,GAAsB;AAC5B,MAAM,cAAA,GAAiB;;;;;"}
1
+ {"version":3,"file":"tables.cjs.js","sources":["../../../../src/entrypoints/scheduler/database/tables.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\nexport const DB_MIGRATIONS_TABLE = 'backstage_backend_tasks__knex_migrations';\nexport const DB_TASKS_TABLE = 'backstage_backend_tasks__tasks';\n\nexport type DbTasksRow = {\n id: string;\n settings_json: string;\n next_run_start_at?: Date | string; // This can be null when in manual trigger mode\n current_run_ticket?: string;\n current_run_started_at?: Date | string;\n current_run_expires_at?: Date | string;\n last_run_error_json?: string;\n last_run_ended_at?: Date | string;\n};\n"],"names":[],"mappings":";;AAgBO,MAAM,mBAAA,GAAsB;AAC5B,MAAM,cAAA,GAAiB;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultSchedulerService.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/DefaultSchedulerService.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DatabaseService,\n HttpRouterService,\n LoggerService,\n PluginMetadataService,\n RootLifecycleService,\n SchedulerService,\n} from '@backstage/backend-plugin-api';\nimport { once } from 'lodash';\nimport { Duration } from 'luxon';\nimport { migrateBackendTasks } from '../database/migrateBackendTasks';\nimport { PluginTaskSchedulerImpl } from './PluginTaskSchedulerImpl';\nimport { PluginTaskSchedulerJanitor } from './PluginTaskSchedulerJanitor';\nimport { MetricsService } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * Default implementation of the task scheduler service.\n *\n * @public\n */\nexport class DefaultSchedulerService {\n static create(options: {\n database: DatabaseService;\n logger: LoggerService;\n metrics: MetricsService;\n rootLifecycle: RootLifecycleService;\n httpRouter: HttpRouterService;\n pluginMetadata: PluginMetadataService;\n }): SchedulerService {\n const databaseFactory = once(async () => {\n const knex = await options.database.getClient();\n\n if (!options.database.migrations?.skip) {\n await migrateBackendTasks(knex);\n }\n\n if (process.env.NODE_ENV !== 'test') {\n const abortController = new AbortController();\n const janitor = new PluginTaskSchedulerJanitor({\n knex,\n waitBetweenRuns: Duration.fromObject({ minutes: 1 }),\n logger: options.logger,\n });\n\n options.rootLifecycle.addShutdownHook(() => abortController.abort());\n janitor.start(abortController.signal);\n }\n\n return knex;\n });\n\n const scheduler = new PluginTaskSchedulerImpl(\n options.pluginMetadata.getId(),\n databaseFactory,\n options.logger,\n options.metrics,\n options.rootLifecycle,\n );\n\n options.httpRouter.use(scheduler.getRouter());\n\n return scheduler;\n }\n}\n"],"names":["once","migrateBackendTasks","PluginTaskSchedulerJanitor","Duration","PluginTaskSchedulerImpl"],"mappings":";;;;;;;;AAoCO,MAAM,uBAAA,CAAwB;AAAA,EACnC,OAAO,OAAO,OAAA,EAOO;AACnB,IAAA,MAAM,eAAA,GAAkBA,YAAK,YAAY;AACvC,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,QAAA,CAAS,SAAA,EAAU;AAE9C,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,UAAA,EAAY,IAAA,EAAM;AACtC,QAAA,MAAMC,wCAAoB,IAAI,CAAA;AAAA,MAChC;AAEA,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,MAAA,EAAQ;AACnC,QAAA,MAAM,eAAA,GAAkB,IAAI,eAAA,EAAgB;AAC5C,QAAA,MAAM,OAAA,GAAU,IAAIC,qDAAA,CAA2B;AAAA,UAC7C,IAAA;AAAA,UACA,iBAAiBC,cAAA,CAAS,UAAA,CAAW,EAAE,OAAA,EAAS,GAAG,CAAA;AAAA,UACnD,QAAQ,OAAA,CAAQ;AAAA,SACjB,CAAA;AAED,QAAA,OAAA,CAAQ,aAAA,CAAc,eAAA,CAAgB,MAAM,eAAA,CAAgB,OAAO,CAAA;AACnE,QAAA,OAAA,CAAQ,KAAA,CAAM,gBAAgB,MAAM,CAAA;AAAA,MACtC;AAEA,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,MAAM,YAAY,IAAIC,+CAAA;AAAA,MACpB,OAAA,CAAQ,eAAe,KAAA,EAAM;AAAA,MAC7B,eAAA;AAAA,MACA,OAAA,CAAQ,MAAA;AAAA,MACR,OAAA,CAAQ,OAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACV;AAEA,IAAA,OAAA,CAAQ,UAAA,CAAW,GAAA,CAAI,SAAA,CAAU,SAAA,EAAW,CAAA;AAE5C,IAAA,OAAO,SAAA;AAAA,EACT;AACF;;;;"}
1
+ {"version":3,"file":"DefaultSchedulerService.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/DefaultSchedulerService.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DatabaseService,\n HttpRouterService,\n LoggerService,\n PluginMetadataService,\n RootLifecycleService,\n SchedulerService,\n} from '@backstage/backend-plugin-api';\nimport { once } from 'lodash';\nimport { Duration } from 'luxon';\nimport { migrateBackendTasks } from '../database/migrateBackendTasks';\nimport { PluginTaskSchedulerImpl } from './PluginTaskSchedulerImpl';\nimport { PluginTaskSchedulerJanitor } from './PluginTaskSchedulerJanitor';\nimport { MetricsService } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * Default implementation of the task scheduler service.\n *\n * @public\n */\nexport class DefaultSchedulerService {\n static create(options: {\n database: DatabaseService;\n logger: LoggerService;\n metrics: MetricsService;\n rootLifecycle: RootLifecycleService;\n httpRouter: HttpRouterService;\n pluginMetadata: PluginMetadataService;\n }): SchedulerService {\n const databaseFactory = once(async () => {\n const knex = await options.database.getClient();\n\n if (!options.database.migrations?.skip) {\n await migrateBackendTasks(knex);\n }\n\n if (process.env.NODE_ENV !== 'test') {\n const abortController = new AbortController();\n const janitor = new PluginTaskSchedulerJanitor({\n knex,\n waitBetweenRuns: Duration.fromObject({ minutes: 1 }),\n logger: options.logger,\n });\n\n options.rootLifecycle.addShutdownHook(() => abortController.abort());\n janitor.start(abortController.signal);\n }\n\n return knex;\n });\n\n const scheduler = new PluginTaskSchedulerImpl(\n options.pluginMetadata.getId(),\n databaseFactory,\n options.logger,\n options.metrics,\n options.rootLifecycle,\n );\n\n options.httpRouter.use(scheduler.getRouter());\n\n return scheduler;\n }\n}\n"],"names":["once","migrateBackendTasks","PluginTaskSchedulerJanitor","Duration","PluginTaskSchedulerImpl"],"mappings":";;;;;;;;AAoCO,MAAM,uBAAA,CAAwB;AAAA,EACnC,OAAO,OAAO,OAAA,EAOO;AACnB,IAAA,MAAM,eAAA,GAAkBA,YAAK,YAAY;AACvC,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,QAAA,CAAS,SAAA,EAAU;AAE9C,MAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,UAAA,EAAY,IAAA,EAAM;AACtC,QAAA,MAAMC,wCAAoB,IAAI,CAAA;AAAA,MAChC;AAEA,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,MAAA,EAAQ;AACnC,QAAA,MAAM,eAAA,GAAkB,IAAI,eAAA,EAAgB;AAC5C,QAAA,MAAM,OAAA,GAAU,IAAIC,qDAAA,CAA2B;AAAA,UAC7C,IAAA;AAAA,UACA,iBAAiBC,cAAA,CAAS,UAAA,CAAW,EAAE,OAAA,EAAS,GAAG,CAAA;AAAA,UACnD,QAAQ,OAAA,CAAQ;AAAA,SACjB,CAAA;AAED,QAAA,OAAA,CAAQ,aAAA,CAAc,eAAA,CAAgB,MAAM,eAAA,CAAgB,OAAO,CAAA;AACnE,QAAA,OAAA,CAAQ,KAAA,CAAM,gBAAgB,MAAM,CAAA;AAAA,MACtC;AAEA,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,MAAM,YAAY,IAAIC,+CAAA;AAAA,MACpB,OAAA,CAAQ,eAAe,KAAA,EAAM;AAAA,MAC7B,eAAA;AAAA,MACA,OAAA,CAAQ,MAAA;AAAA,MACR,OAAA,CAAQ,OAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACV;AAEA,IAAA,OAAA,CAAQ,UAAA,CAAW,GAAA,CAAI,SAAA,CAAU,SAAA,EAAW,CAAA;AAE5C,IAAA,OAAO,SAAA;AAAA,EACT;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"LocalTaskWorker.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/LocalTaskWorker.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 { LoggerService } from '@backstage/backend-plugin-api';\nimport { SchedulerServiceTaskFunction } from '@backstage/backend-plugin-api';\nimport { ConflictError } from '@backstage/errors';\nimport { CronTime } from 'cron';\nimport { DateTime, Duration } from 'luxon';\nimport { TaskSettingsV2, TaskApiTasksResponse } from './types';\nimport { delegateAbortController, serializeError, sleep } from './util';\n\n/**\n * Implements tasks that run locally without cross-host collaboration.\n *\n * @private\n */\nexport class LocalTaskWorker {\n private abortWait: AbortController | undefined;\n private taskAbortController: AbortController | undefined;\n #taskState: Exclude<TaskApiTasksResponse['taskState'], null> = {\n status: 'idle',\n };\n #workerState: TaskApiTasksResponse['workerState'] = {\n status: 'idle',\n };\n\n private readonly taskId: string;\n private readonly fn: SchedulerServiceTaskFunction;\n private readonly logger: LoggerService;\n\n constructor(\n taskId: string,\n fn: SchedulerServiceTaskFunction,\n logger: LoggerService,\n ) {\n this.taskId = taskId;\n this.fn = fn;\n this.logger = logger;\n }\n\n start(settings: TaskSettingsV2, options: { signal: AbortSignal }) {\n this.logger.info(\n `Registered scheduled task: ${this.taskId}, ${JSON.stringify(settings)}`,\n );\n\n (async () => {\n let attemptNum = 1;\n for (;;) {\n try {\n await this.performInitialWait(settings, options.signal);\n\n while (!options.signal.aborted) {\n const startTime = process.hrtime();\n await this.runOnce(settings, options.signal);\n const timeTaken = process.hrtime(startTime);\n await this.waitUntilNext(\n settings,\n (timeTaken[0] + timeTaken[1] / 1e9) * 1000,\n options.signal,\n );\n }\n\n this.logger.info(`Task worker finished: ${this.taskId}`);\n attemptNum = 0;\n break;\n } catch (e) {\n if (options.signal.aborted) {\n break;\n }\n attemptNum += 1;\n this.logger.warn(\n `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`,\n );\n await sleep(Duration.fromObject({ seconds: 1 }), options.signal);\n }\n }\n })();\n }\n\n trigger(): void {\n if (!this.abortWait) {\n throw new ConflictError(`Task ${this.taskId} is currently running`);\n }\n this.abortWait.abort();\n }\n\n cancel(): void {\n if (!this.taskAbortController) {\n throw new ConflictError(`Task ${this.taskId} is not running`);\n }\n this.taskAbortController.abort();\n }\n\n taskState(): TaskApiTasksResponse['taskState'] {\n return this.#taskState;\n }\n\n workerState(): TaskApiTasksResponse['workerState'] {\n return this.#workerState;\n }\n\n /**\n * Does the once-at-startup initial wait, if configured.\n */\n private async performInitialWait(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n if (settings.initialDelayDuration) {\n const parsedDuration = Duration.fromISO(settings.initialDelayDuration);\n\n this.#taskState = {\n status: 'idle',\n startsAt: DateTime.utc().plus(parsedDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'initial-wait',\n };\n\n await this.sleep(parsedDuration, signal);\n }\n }\n\n /**\n * Makes a single attempt at running the task to completion.\n */\n private async runOnce(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n // Abort the task execution either if the worker is stopped, or if the\n // task timeout is hit\n this.taskAbortController = delegateAbortController(signal);\n const timeoutDuration = Duration.fromISO(settings.timeoutAfterDuration);\n const timeoutHandle = setTimeout(() => {\n this.taskAbortController?.abort();\n }, timeoutDuration.as('milliseconds'));\n\n this.#taskState = {\n status: 'running',\n startedAt: DateTime.utc().toISO()!,\n timesOutAt: DateTime.utc().plus(timeoutDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'running',\n };\n\n try {\n await this.fn(this.taskAbortController.signal);\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = undefined;\n } catch (e) {\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = serializeError(e);\n }\n\n // release resources\n clearTimeout(timeoutHandle);\n this.taskAbortController.abort();\n this.taskAbortController = undefined;\n }\n\n /**\n * Sleeps until it's time to run the task again.\n */\n private async waitUntilNext(\n settings: TaskSettingsV2,\n lastRunMillis: number,\n signal: AbortSignal,\n ) {\n if (signal.aborted) {\n return;\n }\n\n const isCron = !settings.cadence.startsWith('P');\n let dt: number;\n\n if (isCron) {\n const nextRun = +new CronTime(settings.cadence).sendAt().toJSDate();\n dt = nextRun - Date.now();\n } else {\n dt =\n Duration.fromISO(settings.cadence).as('milliseconds') - lastRunMillis;\n }\n\n dt = Math.max(dt, 0);\n const startsAt = DateTime.now().plus(Duration.fromMillis(dt));\n\n this.#taskState = {\n status: 'idle',\n startsAt: startsAt.toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'idle',\n };\n\n this.logger.debug(\n `task: ${this.taskId} will next occur around ${startsAt}`,\n );\n\n await this.sleep(Duration.fromMillis(dt), signal);\n }\n\n private async sleep(\n duration: Duration,\n abortSignal: AbortSignal,\n ): Promise<void> {\n this.abortWait = delegateAbortController(abortSignal);\n await sleep(duration, this.abortWait.signal);\n this.abortWait.abort(); // cleans up resources\n this.abortWait = undefined;\n }\n}\n"],"names":["sleep","Duration","ConflictError","DateTime","delegateAbortController","serializeError","CronTime"],"mappings":";;;;;;;AA6BO,MAAM,eAAA,CAAgB;AAAA,EACnB,SAAA;AAAA,EACA,mBAAA;AAAA,EACR,UAAA,GAA+D;AAAA,IAC7D,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,YAAA,GAAoD;AAAA,IAClD,MAAA,EAAQ;AAAA,GACV;AAAA,EAEiB,MAAA;AAAA,EACA,EAAA;AAAA,EACA,MAAA;AAAA,EAEjB,WAAA,CACE,MAAA,EACA,EAAA,EACA,MAAA,EACA;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,EAAA,GAAK,EAAA;AACV,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,KAAA,CAAM,UAA0B,OAAA,EAAkC;AAChE,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,MACV,8BAA8B,IAAA,CAAK,MAAM,KAAK,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAC,CAAA;AAAA,KACxE;AAEA,IAAA,CAAC,YAAY;AACX,MAAA,IAAI,UAAA,GAAa,CAAA;AACjB,MAAA,WAAS;AACP,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,CAAK,kBAAA,CAAmB,QAAA,EAAU,OAAA,CAAQ,MAAM,CAAA;AAEtD,UAAA,OAAO,CAAC,OAAA,CAAQ,MAAA,CAAO,OAAA,EAAS;AAC9B,YAAA,MAAM,SAAA,GAAY,QAAQ,MAAA,EAAO;AACjC,YAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,OAAA,CAAQ,MAAM,CAAA;AAC3C,YAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA;AAC1C,YAAA,MAAM,IAAA,CAAK,aAAA;AAAA,cACT,QAAA;AAAA,cAAA,CACC,UAAU,CAAC,CAAA,GAAI,SAAA,CAAU,CAAC,IAAI,GAAA,IAAO,GAAA;AAAA,cACtC,OAAA,CAAQ;AAAA,aACV;AAAA,UACF;AAEA,UAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA,sBAAA,EAAyB,IAAA,CAAK,MAAM,CAAA,CAAE,CAAA;AACvD,UAAA,UAAA,GAAa,CAAA;AACb,UAAA;AAAA,QACF,SAAS,CAAA,EAAG;AACV,UAAA,IAAI,OAAA,CAAQ,OAAO,OAAA,EAAS;AAC1B,YAAA;AAAA,UACF;AACA,UAAA,UAAA,IAAc,CAAA;AACd,UAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,YACV,CAAA,gDAAA,EAAmD,UAAU,CAAA,EAAA,EAAK,CAAC,CAAA;AAAA,WACrE;AACA,UAAA,MAAMA,UAAA,CAAMC,eAAS,UAAA,CAAW,EAAE,SAAS,CAAA,EAAG,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA;AAAA,QACjE;AAAA,MACF;AAAA,IACF,CAAA,GAAG;AAAA,EACL;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,MAAA,MAAM,IAAIC,oBAAA,CAAc,CAAA,KAAA,EAAQ,IAAA,CAAK,MAAM,CAAA,qBAAA,CAAuB,CAAA;AAAA,IACpE;AACA,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACvB;AAAA,EAEA,MAAA,GAAe;AACb,IAAA,IAAI,CAAC,KAAK,mBAAA,EAAqB;AAC7B,MAAA,MAAM,IAAIA,oBAAA,CAAc,CAAA,KAAA,EAAQ,IAAA,CAAK,MAAM,CAAA,eAAA,CAAiB,CAAA;AAAA,IAC9D;AACA,IAAA,IAAA,CAAK,oBAAoB,KAAA,EAAM;AAAA,EACjC;AAAA,EAEA,SAAA,GAA+C;AAC7C,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA,EAEA,WAAA,GAAmD;AACjD,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,kBAAA,CACZ,QAAA,EACA,MAAA,EACe;AACf,IAAA,IAAI,SAAS,oBAAA,EAAsB;AACjC,MAAA,MAAM,cAAA,GAAiBD,cAAA,CAAS,OAAA,CAAQ,QAAA,CAAS,oBAAoB,CAAA;AAErE,MAAA,IAAA,CAAK,UAAA,GAAa;AAAA,QAChB,MAAA,EAAQ,MAAA;AAAA,QACR,UAAUE,cAAA,CAAS,GAAA,GAAM,IAAA,CAAK,cAAc,EAAE,KAAA,EAAM;AAAA,QACpD,cAAA,EAAgB,KAAK,UAAA,CAAW,cAAA;AAAA,QAChC,YAAA,EAAc,KAAK,UAAA,CAAW;AAAA,OAChC;AACA,MAAA,IAAA,CAAK,YAAA,GAAe;AAAA,QAClB,MAAA,EAAQ;AAAA,OACV;AAEA,MAAA,MAAM,IAAA,CAAK,KAAA,CAAM,cAAA,EAAgB,MAAM,CAAA;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,OAAA,CACZ,QAAA,EACA,MAAA,EACe;AAGf,IAAA,IAAA,CAAK,mBAAA,GAAsBC,6BAAwB,MAAM,CAAA;AACzD,IAAA,MAAM,eAAA,GAAkBH,cAAA,CAAS,OAAA,CAAQ,QAAA,CAAS,oBAAoB,CAAA;AACtE,IAAA,MAAM,aAAA,GAAgB,WAAW,MAAM;AACrC,MAAA,IAAA,CAAK,qBAAqB,KAAA,EAAM;AAAA,IAClC,CAAA,EAAG,eAAA,CAAgB,EAAA,CAAG,cAAc,CAAC,CAAA;AAErC,IAAA,IAAA,CAAK,UAAA,GAAa;AAAA,MAChB,MAAA,EAAQ,SAAA;AAAA,MACR,SAAA,EAAWE,cAAA,CAAS,GAAA,EAAI,CAAE,KAAA,EAAM;AAAA,MAChC,YAAYA,cAAA,CAAS,GAAA,GAAM,IAAA,CAAK,eAAe,EAAE,KAAA,EAAM;AAAA,MACvD,cAAA,EAAgB,KAAK,UAAA,CAAW,cAAA;AAAA,MAChC,YAAA,EAAc,KAAK,UAAA,CAAW;AAAA,KAChC;AACA,IAAA,IAAA,CAAK,YAAA,GAAe;AAAA,MAClB,MAAA,EAAQ;AAAA,KACV;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,EAAA,CAAG,IAAA,CAAK,mBAAA,CAAoB,MAAM,CAAA;AAC7C,MAAA,IAAA,CAAK,UAAA,CAAW,cAAA,GAAiBA,cAAA,CAAS,GAAA,GAAM,KAAA,EAAM;AACtD,MAAA,IAAA,CAAK,WAAW,YAAA,GAAe,KAAA,CAAA;AAAA,IACjC,SAAS,CAAA,EAAG;AACV,MAAA,IAAA,CAAK,UAAA,CAAW,cAAA,GAAiBA,cAAA,CAAS,GAAA,GAAM,KAAA,EAAM;AACtD,MAAA,IAAA,CAAK,UAAA,CAAW,YAAA,GAAeE,mBAAA,CAAe,CAAC,CAAA;AAAA,IACjD;AAGA,IAAA,YAAA,CAAa,aAAa,CAAA;AAC1B,IAAA,IAAA,CAAK,oBAAoB,KAAA,EAAM;AAC/B,IAAA,IAAA,CAAK,mBAAA,GAAsB,MAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aAAA,CACZ,QAAA,EACA,aAAA,EACA,MAAA,EACA;AACA,IAAA,IAAI,OAAO,OAAA,EAAS;AAClB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,CAAC,QAAA,CAAS,OAAA,CAAQ,WAAW,GAAG,CAAA;AAC/C,IAAA,IAAI,EAAA;AAEJ,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,OAAA,GAAU,CAAC,IAAIC,aAAA,CAAS,SAAS,OAAO,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAClE,MAAA,EAAA,GAAK,OAAA,GAAU,KAAK,GAAA,EAAI;AAAA,IAC1B,CAAA,MAAO;AACL,MAAA,EAAA,GACEL,eAAS,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA,CAAE,EAAA,CAAG,cAAc,CAAA,GAAI,aAAA;AAAA,IAC5D;AAEA,IAAA,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,CAAC,CAAA;AACnB,IAAA,MAAM,QAAA,GAAWE,eAAS,GAAA,EAAI,CAAE,KAAKF,cAAA,CAAS,UAAA,CAAW,EAAE,CAAC,CAAA;AAE5D,IAAA,IAAA,CAAK,UAAA,GAAa;AAAA,MAChB,MAAA,EAAQ,MAAA;AAAA,MACR,QAAA,EAAU,SAAS,KAAA,EAAM;AAAA,MACzB,cAAA,EAAgB,KAAK,UAAA,CAAW,cAAA;AAAA,MAChC,YAAA,EAAc,KAAK,UAAA,CAAW;AAAA,KAChC;AACA,IAAA,IAAA,CAAK,YAAA,GAAe;AAAA,MAClB,MAAA,EAAQ;AAAA,KACV;AAEA,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA;AAAA,MACV,CAAA,MAAA,EAAS,IAAA,CAAK,MAAM,CAAA,wBAAA,EAA2B,QAAQ,CAAA;AAAA,KACzD;AAEA,IAAA,MAAM,KAAK,KAAA,CAAMA,cAAA,CAAS,UAAA,CAAW,EAAE,GAAG,MAAM,CAAA;AAAA,EAClD;AAAA,EAEA,MAAc,KAAA,CACZ,QAAA,EACA,WAAA,EACe;AACf,IAAA,IAAA,CAAK,SAAA,GAAYG,6BAAwB,WAAW,CAAA;AACpD,IAAA,MAAMJ,UAAA,CAAM,QAAA,EAAU,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAC3C,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AACrB,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AAAA,EACnB;AACF;;;;"}
1
+ {"version":3,"file":"LocalTaskWorker.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/LocalTaskWorker.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 { LoggerService } from '@backstage/backend-plugin-api';\nimport { SchedulerServiceTaskFunction } from '@backstage/backend-plugin-api';\nimport { ConflictError } from '@backstage/errors';\nimport { CronTime } from 'cron';\nimport { DateTime, Duration } from 'luxon';\nimport { TaskSettingsV2, TaskApiTasksResponse } from './types';\nimport { delegateAbortController, serializeError, sleep } from './util';\n\n/**\n * Implements tasks that run locally without cross-host collaboration.\n *\n * @private\n */\nexport class LocalTaskWorker {\n private abortWait: AbortController | undefined;\n private taskAbortController: AbortController | undefined;\n #taskState: Exclude<TaskApiTasksResponse['taskState'], null> = {\n status: 'idle',\n };\n #workerState: TaskApiTasksResponse['workerState'] = {\n status: 'idle',\n };\n\n private readonly taskId: string;\n private readonly fn: SchedulerServiceTaskFunction;\n private readonly logger: LoggerService;\n\n constructor(\n taskId: string,\n fn: SchedulerServiceTaskFunction,\n logger: LoggerService,\n ) {\n this.taskId = taskId;\n this.fn = fn;\n this.logger = logger;\n }\n\n start(settings: TaskSettingsV2, options: { signal: AbortSignal }) {\n this.logger.info(\n `Registered scheduled task: ${this.taskId}, ${JSON.stringify(settings)}`,\n );\n\n (async () => {\n let attemptNum = 1;\n for (;;) {\n try {\n await this.performInitialWait(settings, options.signal);\n\n while (!options.signal.aborted) {\n const startTime = process.hrtime();\n await this.runOnce(settings, options.signal);\n const timeTaken = process.hrtime(startTime);\n await this.waitUntilNext(\n settings,\n (timeTaken[0] + timeTaken[1] / 1e9) * 1000,\n options.signal,\n );\n }\n\n this.logger.info(`Task worker finished: ${this.taskId}`);\n attemptNum = 0;\n break;\n } catch (e) {\n if (options.signal.aborted) {\n break;\n }\n attemptNum += 1;\n this.logger.warn(\n `Task worker failed unexpectedly, attempt number ${attemptNum}, ${e}`,\n );\n await sleep(Duration.fromObject({ seconds: 1 }), options.signal);\n }\n }\n })();\n }\n\n trigger(): void {\n if (!this.abortWait) {\n throw new ConflictError(`Task ${this.taskId} is currently running`);\n }\n this.abortWait.abort();\n }\n\n cancel(): void {\n if (!this.taskAbortController) {\n throw new ConflictError(`Task ${this.taskId} is not running`);\n }\n this.taskAbortController.abort();\n }\n\n taskState(): TaskApiTasksResponse['taskState'] {\n return this.#taskState;\n }\n\n workerState(): TaskApiTasksResponse['workerState'] {\n return this.#workerState;\n }\n\n /**\n * Does the once-at-startup initial wait, if configured.\n */\n private async performInitialWait(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n if (settings.initialDelayDuration) {\n const parsedDuration = Duration.fromISO(settings.initialDelayDuration);\n\n this.#taskState = {\n status: 'idle',\n startsAt: DateTime.utc().plus(parsedDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'initial-wait',\n };\n\n await this.sleep(parsedDuration, signal);\n }\n }\n\n /**\n * Makes a single attempt at running the task to completion.\n */\n private async runOnce(\n settings: TaskSettingsV2,\n signal: AbortSignal,\n ): Promise<void> {\n // Abort the task execution either if the worker is stopped, or if the\n // task timeout is hit\n this.taskAbortController = delegateAbortController(signal);\n const timeoutDuration = Duration.fromISO(settings.timeoutAfterDuration);\n const timeoutHandle = setTimeout(() => {\n this.taskAbortController?.abort();\n }, timeoutDuration.as('milliseconds'));\n\n this.#taskState = {\n status: 'running',\n startedAt: DateTime.utc().toISO()!,\n timesOutAt: DateTime.utc().plus(timeoutDuration).toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'running',\n };\n\n try {\n await this.fn(this.taskAbortController.signal);\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = undefined;\n } catch (e) {\n this.#taskState.lastRunEndedAt = DateTime.utc().toISO()!;\n this.#taskState.lastRunError = serializeError(e);\n }\n\n // release resources\n clearTimeout(timeoutHandle);\n this.taskAbortController.abort();\n this.taskAbortController = undefined;\n }\n\n /**\n * Sleeps until it's time to run the task again.\n */\n private async waitUntilNext(\n settings: TaskSettingsV2,\n lastRunMillis: number,\n signal: AbortSignal,\n ) {\n if (signal.aborted) {\n return;\n }\n\n const isCron = !settings.cadence.startsWith('P');\n let dt: number;\n\n if (isCron) {\n const nextRun = +new CronTime(settings.cadence).sendAt().toJSDate();\n dt = nextRun - Date.now();\n } else {\n dt =\n Duration.fromISO(settings.cadence).as('milliseconds') - lastRunMillis;\n }\n\n dt = Math.max(dt, 0);\n const startsAt = DateTime.now().plus(Duration.fromMillis(dt));\n\n this.#taskState = {\n status: 'idle',\n startsAt: startsAt.toISO()!,\n lastRunEndedAt: this.#taskState.lastRunEndedAt,\n lastRunError: this.#taskState.lastRunError,\n };\n this.#workerState = {\n status: 'idle',\n };\n\n this.logger.debug(\n `task: ${this.taskId} will next occur around ${startsAt}`,\n );\n\n await this.sleep(Duration.fromMillis(dt), signal);\n }\n\n private async sleep(\n duration: Duration,\n abortSignal: AbortSignal,\n ): Promise<void> {\n this.abortWait = delegateAbortController(abortSignal);\n await sleep(duration, this.abortWait.signal);\n this.abortWait.abort(); // cleans up resources\n this.abortWait = undefined;\n }\n}\n"],"names":["sleep","Duration","ConflictError","DateTime","delegateAbortController","serializeError","CronTime"],"mappings":"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"}