@backstage/backend-defaults 0.17.9-next.1 → 0.18.1-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/config.schema.json +5 -0
  3. package/dist/CreateBackend.cjs.js.map +1 -1
  4. package/dist/PackageDiscoveryService.cjs.js.map +1 -1
  5. package/dist/alpha/entrypoints/actions/DefaultActionsService.cjs.js.map +1 -1
  6. package/dist/alpha/entrypoints/actions/actionsServiceFactory.cjs.js.map +1 -1
  7. package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +1 -1
  8. package/dist/alpha/entrypoints/actionsRegistry/actionFilters.cjs.js.map +1 -1
  9. package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +1 -1
  10. package/dist/alpha/entrypoints/instanceMetadata/instanceMetadataServiceFactory.cjs.js.map +1 -1
  11. package/dist/alpha/entrypoints/metrics/DefaultMetricsService.cjs.js.map +1 -1
  12. package/dist/alpha/entrypoints/metrics/metricsServiceFactory.cjs.js.map +1 -1
  13. package/dist/alpha/entrypoints/tracing/DefaultTracingService.cjs.js.map +1 -1
  14. package/dist/alpha/entrypoints/tracing/tracingServiceFactory.cjs.js.map +1 -1
  15. package/dist/discoveryFeatureLoader.cjs.js.map +1 -1
  16. package/dist/entrypoints/auditor/DefaultAuditorService.cjs.js.map +1 -1
  17. package/dist/entrypoints/auditor/WinstonRootAuditorService.cjs.js.map +1 -1
  18. package/dist/entrypoints/auditor/auditorServiceFactory.cjs.js.map +1 -1
  19. package/dist/entrypoints/auditor/utils.cjs.js.map +1 -1
  20. package/dist/entrypoints/auth/DefaultAuthService.cjs.js.map +1 -1
  21. package/dist/entrypoints/auth/JwksClient.cjs.js.map +1 -1
  22. package/dist/entrypoints/auth/authServiceFactory.cjs.js.map +1 -1
  23. package/dist/entrypoints/auth/external/ExternalAuthTokenHandler.cjs.js.map +1 -1
  24. package/dist/entrypoints/auth/external/helpers.cjs.js.map +1 -1
  25. package/dist/entrypoints/auth/external/jwks.cjs.js.map +1 -1
  26. package/dist/entrypoints/auth/external/legacy.cjs.js.map +1 -1
  27. package/dist/entrypoints/auth/external/static.cjs.js.map +1 -1
  28. package/dist/entrypoints/auth/helpers.cjs.js.map +1 -1
  29. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js +5 -5
  30. package/dist/entrypoints/auth/plugin/PluginTokenHandler.cjs.js.map +1 -1
  31. package/dist/entrypoints/auth/plugin/keys/DatabaseKeyStore.cjs.js.map +1 -1
  32. package/dist/entrypoints/auth/plugin/keys/DatabasePluginKeySource.cjs.js.map +1 -1
  33. package/dist/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.cjs.js.map +1 -1
  34. package/dist/entrypoints/auth/plugin/keys/createPluginKeySource.cjs.js.map +1 -1
  35. package/dist/entrypoints/auth/user/UserTokenHandler.cjs.js.map +1 -1
  36. package/dist/entrypoints/cache/CacheClient.cjs.js.map +1 -1
  37. package/dist/entrypoints/cache/CacheManager.cjs.js.map +1 -1
  38. package/dist/entrypoints/cache/cacheServiceFactory.cjs.js.map +1 -1
  39. package/dist/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.cjs.js.map +1 -1
  40. package/dist/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.cjs.js.map +1 -1
  41. package/dist/entrypoints/cache/types.cjs.js.map +1 -1
  42. package/dist/entrypoints/database/DatabaseManager.cjs.js +7 -1
  43. package/dist/entrypoints/database/DatabaseManager.cjs.js.map +1 -1
  44. package/dist/entrypoints/database/connectors/defaultNameOverride.cjs.js.map +1 -1
  45. package/dist/entrypoints/database/connectors/mergeDatabaseConfig.cjs.js.map +1 -1
  46. package/dist/entrypoints/database/connectors/mysql.cjs.js.map +1 -1
  47. package/dist/entrypoints/database/connectors/postgres.cjs.js +18 -5
  48. package/dist/entrypoints/database/connectors/postgres.cjs.js.map +1 -1
  49. package/dist/entrypoints/database/connectors/sqlite3.cjs.js.map +1 -1
  50. package/dist/entrypoints/database/databaseServiceFactory.cjs.js.map +1 -1
  51. package/dist/entrypoints/discovery/HostDiscovery.cjs.js.map +1 -1
  52. package/dist/entrypoints/discovery/SrvResolvers.cjs.js.map +1 -1
  53. package/dist/entrypoints/discovery/discoveryServiceFactory.cjs.js.map +1 -1
  54. package/dist/entrypoints/discovery/parsing.cjs.js.map +1 -1
  55. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js +14 -4
  56. package/dist/entrypoints/httpAuth/httpAuthServiceFactory.cjs.js.map +1 -1
  57. package/dist/entrypoints/httpRouter/http/createAuthIntegrationRouter.cjs.js.map +1 -1
  58. package/dist/entrypoints/httpRouter/http/createCookieAuthRefreshMiddleware.cjs.js.map +1 -1
  59. package/dist/entrypoints/httpRouter/http/createCredentialsBarrier.cjs.js.map +1 -1
  60. package/dist/entrypoints/httpRouter/http/createLifecycleMiddleware.cjs.js.map +1 -1
  61. package/dist/entrypoints/httpRouter/http/createRateLimitMiddleware.cjs.js.map +1 -1
  62. package/dist/entrypoints/httpRouter/httpRouterServiceFactory.cjs.js.map +1 -1
  63. package/dist/entrypoints/lifecycle/lifecycleServiceFactory.cjs.js.map +1 -1
  64. package/dist/entrypoints/logger/loggerServiceFactory.cjs.js.map +1 -1
  65. package/dist/entrypoints/permissions/permissionsServiceFactory.cjs.js.map +1 -1
  66. package/dist/entrypoints/permissionsRegistry/permissionsRegistryServiceFactory.cjs.js.map +1 -1
  67. package/dist/entrypoints/rootConfig/createConfigSecretEnumerator.cjs.js.map +1 -1
  68. package/dist/entrypoints/rootConfig/rootConfigServiceFactory.cjs.js.map +1 -1
  69. package/dist/entrypoints/rootHealth/rootHealthServiceFactory.cjs.js.map +1 -1
  70. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js +1 -1
  71. package/dist/entrypoints/rootHttpRouter/DefaultRootHttpRouter.cjs.js.map +1 -1
  72. package/dist/entrypoints/rootHttpRouter/createHealthRouter.cjs.js.map +1 -1
  73. package/dist/entrypoints/rootHttpRouter/http/MiddlewareFactory.cjs.js.map +1 -1
  74. package/dist/entrypoints/rootHttpRouter/http/applyInternalErrorFilter.cjs.js.map +1 -1
  75. package/dist/entrypoints/rootHttpRouter/http/config.cjs.js.map +1 -1
  76. package/dist/entrypoints/rootHttpRouter/http/createHttpServer.cjs.js.map +1 -1
  77. package/dist/entrypoints/rootHttpRouter/http/getGeneratedCertificate.cjs.js.map +1 -1
  78. package/dist/entrypoints/rootHttpRouter/http/readCorsOptions.cjs.js.map +1 -1
  79. package/dist/entrypoints/rootHttpRouter/http/readHelmetOptions.cjs.js.map +1 -1
  80. package/dist/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.cjs.js.map +1 -1
  81. package/dist/entrypoints/rootLifecycle/rootLifecycleServiceFactory.cjs.js.map +1 -1
  82. package/dist/entrypoints/rootLogger/WinstonLogger.cjs.js.map +1 -1
  83. package/dist/entrypoints/rootLogger/config.cjs.js.map +1 -1
  84. package/dist/entrypoints/rootLogger/rootLoggerServiceFactory.cjs.js.map +1 -1
  85. package/dist/entrypoints/rootLogger/types.cjs.js.map +1 -1
  86. package/dist/entrypoints/rootLogger/utils.cjs.js.map +1 -1
  87. package/dist/entrypoints/rootSystemMetadata/lib/DefaultRootSystemMetadataService.cjs.js.map +1 -1
  88. package/dist/entrypoints/rootSystemMetadata/rootSystemMetadataServiceFactory.cjs.js.map +1 -1
  89. package/dist/entrypoints/scheduler/database/migrateBackendTasks.cjs.js.map +1 -1
  90. package/dist/entrypoints/scheduler/database/tables.cjs.js.map +1 -1
  91. package/dist/entrypoints/scheduler/lib/DefaultSchedulerService.cjs.js.map +1 -1
  92. package/dist/entrypoints/scheduler/lib/LocalTaskWorker.cjs.js.map +1 -1
  93. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.cjs.js.map +1 -1
  94. package/dist/entrypoints/scheduler/lib/PluginTaskSchedulerJanitor.cjs.js.map +1 -1
  95. package/dist/entrypoints/scheduler/lib/TaskStatePoller.cjs.js.map +1 -1
  96. package/dist/entrypoints/scheduler/lib/TaskWorker.cjs.js.map +1 -1
  97. package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
  98. package/dist/entrypoints/scheduler/lib/util.cjs.js.map +1 -1
  99. package/dist/entrypoints/scheduler/schedulerServiceFactory.cjs.js.map +1 -1
  100. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js +22 -7
  101. package/dist/entrypoints/urlReader/lib/AwsCodeCommitUrlReader.cjs.js.map +1 -1
  102. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js +22 -7
  103. package/dist/entrypoints/urlReader/lib/AwsS3UrlReader.cjs.js.map +1 -1
  104. package/dist/entrypoints/urlReader/lib/AzureBlobStorageUrlReader.cjs.js.map +1 -1
  105. package/dist/entrypoints/urlReader/lib/AzureUrlReader.cjs.js.map +1 -1
  106. package/dist/entrypoints/urlReader/lib/BitbucketCloudUrlReader.cjs.js.map +1 -1
  107. package/dist/entrypoints/urlReader/lib/BitbucketServerUrlReader.cjs.js.map +1 -1
  108. package/dist/entrypoints/urlReader/lib/FetchUrlReader.cjs.js.map +1 -1
  109. package/dist/entrypoints/urlReader/lib/GerritUrlReader.cjs.js.map +1 -1
  110. package/dist/entrypoints/urlReader/lib/GiteaUrlReader.cjs.js.map +1 -1
  111. package/dist/entrypoints/urlReader/lib/GithubUrlReader.cjs.js.map +1 -1
  112. package/dist/entrypoints/urlReader/lib/GitlabUrlReader.cjs.js.map +1 -1
  113. package/dist/entrypoints/urlReader/lib/GoogleGcsUrlReader.cjs.js.map +1 -1
  114. package/dist/entrypoints/urlReader/lib/HarnessUrlReader.cjs.js.map +1 -1
  115. package/dist/entrypoints/urlReader/lib/ReadUrlResponseFactory.cjs.js.map +1 -1
  116. package/dist/entrypoints/urlReader/lib/UrlReaderPredicateMux.cjs.js.map +1 -1
  117. package/dist/entrypoints/urlReader/lib/UrlReaders.cjs.js.map +1 -1
  118. package/dist/entrypoints/urlReader/lib/tree/ReadTreeResponseFactory.cjs.js.map +1 -1
  119. package/dist/entrypoints/urlReader/lib/tree/ReadableArrayResponse.cjs.js.map +1 -1
  120. package/dist/entrypoints/urlReader/lib/tree/TarArchiveResponse.cjs.js.map +1 -1
  121. package/dist/entrypoints/urlReader/lib/tree/ZipArchiveResponse.cjs.js.map +1 -1
  122. package/dist/entrypoints/urlReader/lib/tree/util.cjs.js.map +1 -1
  123. package/dist/entrypoints/urlReader/lib/util.cjs.js.map +1 -1
  124. package/dist/entrypoints/urlReader/urlReaderServiceFactory.cjs.js.map +1 -1
  125. package/dist/entrypoints/userInfo/CachedUserInfoService.cjs.js.map +1 -1
  126. package/dist/entrypoints/userInfo/DefaultUserInfoService.cjs.js.map +1 -1
  127. package/dist/entrypoints/userInfo/userInfoServiceFactory.cjs.js.map +1 -1
  128. package/dist/lib/RateLimitStoreFactory.cjs.js.map +1 -1
  129. package/dist/lib/escapeRegExp.cjs.js.map +1 -1
  130. package/dist/lib/rateLimitMiddleware.cjs.js.map +1 -1
  131. package/dist/package.json.cjs.js +1 -1
  132. package/dist/package.json.cjs.js.map +1 -1
  133. package/package.json +16 -15
@@ -1 +1 @@
1
- {"version":3,"file":"StaticConfigPluginKeySource.cjs.js","sources":["../../../../../src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.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 { Config } from '@backstage/config';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport { promises as fs } from 'node:fs';\nimport { JWK, exportJWK, importPKCS8, importSPKI } from 'jose';\nimport { KeyLike } from 'jose';\nimport { KeyPayload } from './types';\nimport { PluginKeySource } from './types';\n\nexport type KeyPair = {\n publicKey: JWK;\n privateKey?: JWK;\n keyId: string;\n};\n\nexport type StaticKeyConfig = {\n publicKeyFile: string;\n privateKeyFile?: string;\n keyId: string;\n algorithm: string;\n};\n\nconst DEFAULT_ALGORITHM = 'ES256';\n\nconst SECONDS_IN_MS = 1000;\n\n/**\n * Key source that loads predefined public/private key pairs from disk.\n *\n * The private key should be represented using the PKCS#8 format,\n * while the public key should be in the SPKI format.\n *\n * @remarks\n *\n * You can generate a public and private key pair, using\n * openssl:\n *\n * Generate a private key using the ES256 algorithm\n * ```sh\n * openssl ecparam -name prime256v1 -genkey -out private.ec.key\n * ```\n * Convert it to PKCS#8 format\n * ```sh\n * openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private.ec.key -out private.key\n * ```\n * Extract the public key\n * ```sh\n * openssl ec -inform PEM -outform PEM -pubout -in private.key -out public.key\n * ```\n *\n * Provide the paths to private.key and public.key as the respective\n * private and public key paths in the `create` method.\n */\nexport class StaticConfigPluginKeySource implements PluginKeySource {\n private readonly keyPairs: KeyPair[];\n private readonly keyDurationSeconds: number;\n\n private constructor(keyPairs: KeyPair[], keyDurationSeconds: number) {\n this.keyPairs = keyPairs;\n this.keyDurationSeconds = keyDurationSeconds;\n }\n\n public static async create(options: {\n sourceConfig: Config;\n keyDuration: HumanDuration;\n }): Promise<PluginKeySource> {\n const keyConfigs = options.sourceConfig\n .getConfigArray('static.keys')\n .map(c => {\n const staticKeyConfig: StaticKeyConfig = {\n publicKeyFile: c.getString('publicKeyFile'),\n privateKeyFile: c.getOptionalString('privateKeyFile'),\n keyId: c.getString('keyId'),\n algorithm: c.getOptionalString('algorithm') ?? DEFAULT_ALGORITHM,\n };\n\n return staticKeyConfig;\n });\n\n const keyPairs = await Promise.all(\n keyConfigs.map(async k => await this.loadKeyPair(k)),\n );\n\n if (keyPairs.length < 1) {\n throw new Error(\n 'At least one key pair must be provided in static.keys, when the static key store type is used',\n );\n } else if (!keyPairs[0].privateKey) {\n throw new Error(\n 'Private key for signing must be provided in the first key pair in static.keys, when the static key store type is used',\n );\n }\n\n return new StaticConfigPluginKeySource(\n keyPairs,\n durationToMilliseconds(options.keyDuration) / SECONDS_IN_MS,\n );\n }\n\n async getPrivateSigningKey(): Promise<JWK> {\n return this.keyPairs[0].privateKey!;\n }\n\n async listKeys(): Promise<{ keys: KeyPayload[] }> {\n const keys = this.keyPairs.map(k => this.keyPairToStoredKey(k));\n return { keys };\n }\n\n private static async loadKeyPair(options: StaticKeyConfig): Promise<KeyPair> {\n const algorithm = options.algorithm;\n const keyId = options.keyId;\n const publicKey = await this.loadPublicKeyFromFile(\n options.publicKeyFile,\n keyId,\n algorithm,\n );\n const privateKey = options.privateKeyFile\n ? await this.loadPrivateKeyFromFile(\n options.privateKeyFile,\n keyId,\n algorithm,\n )\n : undefined;\n\n return { publicKey, privateKey, keyId };\n }\n\n private static async loadPublicKeyFromFile(\n path: string,\n keyId: string,\n algorithm: string,\n ): Promise<JWK> {\n return this.loadKeyFromFile(path, keyId, algorithm, importSPKI);\n }\n\n private static async loadPrivateKeyFromFile(\n path: string,\n keyId: string,\n algorithm: string,\n ): Promise<JWK> {\n return this.loadKeyFromFile(path, keyId, algorithm, importPKCS8);\n }\n\n private static async loadKeyFromFile(\n path: string,\n keyId: string,\n algorithm: string,\n importer: (content: string, algorithm: string) => Promise<KeyLike>,\n ): Promise<JWK> {\n const content = await fs.readFile(path, { encoding: 'utf8', flag: 'r' });\n const key = await importer(content, algorithm);\n const jwk = await exportJWK(key);\n jwk.kid = keyId;\n jwk.alg = algorithm;\n\n return jwk;\n }\n\n private keyPairToStoredKey(keyPair: KeyPair): KeyPayload {\n const publicKey = {\n ...keyPair.publicKey,\n kid: keyPair.keyId,\n };\n\n return {\n key: publicKey,\n id: keyPair.keyId,\n expiresAt: new Date(Date.now() + this.keyDurationSeconds * SECONDS_IN_MS),\n };\n }\n}\n"],"names":["durationToMilliseconds","importSPKI","importPKCS8","fs","exportJWK"],"mappings":"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"}
1
+ {"version":3,"file":"StaticConfigPluginKeySource.cjs.js","sources":["../../../../../src/entrypoints/auth/plugin/keys/StaticConfigPluginKeySource.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 { Config } from '@backstage/config';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport { promises as fs } from 'node:fs';\nimport { JWK, exportJWK, importPKCS8, importSPKI } from 'jose';\nimport { KeyLike } from 'jose';\nimport { KeyPayload } from './types';\nimport { PluginKeySource } from './types';\n\nexport type KeyPair = {\n publicKey: JWK;\n privateKey?: JWK;\n keyId: string;\n};\n\nexport type StaticKeyConfig = {\n publicKeyFile: string;\n privateKeyFile?: string;\n keyId: string;\n algorithm: string;\n};\n\nconst DEFAULT_ALGORITHM = 'ES256';\n\nconst SECONDS_IN_MS = 1000;\n\n/**\n * Key source that loads predefined public/private key pairs from disk.\n *\n * The private key should be represented using the PKCS#8 format,\n * while the public key should be in the SPKI format.\n *\n * @remarks\n *\n * You can generate a public and private key pair, using\n * openssl:\n *\n * Generate a private key using the ES256 algorithm\n * ```sh\n * openssl ecparam -name prime256v1 -genkey -out private.ec.key\n * ```\n * Convert it to PKCS#8 format\n * ```sh\n * openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private.ec.key -out private.key\n * ```\n * Extract the public key\n * ```sh\n * openssl ec -inform PEM -outform PEM -pubout -in private.key -out public.key\n * ```\n *\n * Provide the paths to private.key and public.key as the respective\n * private and public key paths in the `create` method.\n */\nexport class StaticConfigPluginKeySource implements PluginKeySource {\n private readonly keyPairs: KeyPair[];\n private readonly keyDurationSeconds: number;\n\n private constructor(keyPairs: KeyPair[], keyDurationSeconds: number) {\n this.keyPairs = keyPairs;\n this.keyDurationSeconds = keyDurationSeconds;\n }\n\n public static async create(options: {\n sourceConfig: Config;\n keyDuration: HumanDuration;\n }): Promise<PluginKeySource> {\n const keyConfigs = options.sourceConfig\n .getConfigArray('static.keys')\n .map(c => {\n const staticKeyConfig: StaticKeyConfig = {\n publicKeyFile: c.getString('publicKeyFile'),\n privateKeyFile: c.getOptionalString('privateKeyFile'),\n keyId: c.getString('keyId'),\n algorithm: c.getOptionalString('algorithm') ?? DEFAULT_ALGORITHM,\n };\n\n return staticKeyConfig;\n });\n\n const keyPairs = await Promise.all(\n keyConfigs.map(async k => await this.loadKeyPair(k)),\n );\n\n if (keyPairs.length < 1) {\n throw new Error(\n 'At least one key pair must be provided in static.keys, when the static key store type is used',\n );\n } else if (!keyPairs[0].privateKey) {\n throw new Error(\n 'Private key for signing must be provided in the first key pair in static.keys, when the static key store type is used',\n );\n }\n\n return new StaticConfigPluginKeySource(\n keyPairs,\n durationToMilliseconds(options.keyDuration) / SECONDS_IN_MS,\n );\n }\n\n async getPrivateSigningKey(): Promise<JWK> {\n return this.keyPairs[0].privateKey!;\n }\n\n async listKeys(): Promise<{ keys: KeyPayload[] }> {\n const keys = this.keyPairs.map(k => this.keyPairToStoredKey(k));\n return { keys };\n }\n\n private static async loadKeyPair(options: StaticKeyConfig): Promise<KeyPair> {\n const algorithm = options.algorithm;\n const keyId = options.keyId;\n const publicKey = await this.loadPublicKeyFromFile(\n options.publicKeyFile,\n keyId,\n algorithm,\n );\n const privateKey = options.privateKeyFile\n ? await this.loadPrivateKeyFromFile(\n options.privateKeyFile,\n keyId,\n algorithm,\n )\n : undefined;\n\n return { publicKey, privateKey, keyId };\n }\n\n private static async loadPublicKeyFromFile(\n path: string,\n keyId: string,\n algorithm: string,\n ): Promise<JWK> {\n return this.loadKeyFromFile(path, keyId, algorithm, importSPKI);\n }\n\n private static async loadPrivateKeyFromFile(\n path: string,\n keyId: string,\n algorithm: string,\n ): Promise<JWK> {\n return this.loadKeyFromFile(path, keyId, algorithm, importPKCS8);\n }\n\n private static async loadKeyFromFile(\n path: string,\n keyId: string,\n algorithm: string,\n importer: (content: string, algorithm: string) => Promise<KeyLike>,\n ): Promise<JWK> {\n const content = await fs.readFile(path, { encoding: 'utf8', flag: 'r' });\n const key = await importer(content, algorithm);\n const jwk = await exportJWK(key);\n jwk.kid = keyId;\n jwk.alg = algorithm;\n\n return jwk;\n }\n\n private keyPairToStoredKey(keyPair: KeyPair): KeyPayload {\n const publicKey = {\n ...keyPair.publicKey,\n kid: keyPair.keyId,\n };\n\n return {\n key: publicKey,\n id: keyPair.keyId,\n expiresAt: new Date(Date.now() + this.keyDurationSeconds * SECONDS_IN_MS),\n };\n }\n}\n"],"names":["durationToMilliseconds","importSPKI","importPKCS8","fs","exportJWK"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"createPluginKeySource.cjs.js","sources":["../../../../../src/entrypoints/auth/plugin/keys/createPluginKeySource.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 DatabaseService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { HumanDuration } from '@backstage/types';\nimport { DatabasePluginKeySource } from './DatabasePluginKeySource';\nimport { StaticConfigPluginKeySource } from './StaticConfigPluginKeySource';\nimport { PluginKeySource } from './types';\n\nconst CONFIG_ROOT_KEY = 'backend.auth.pluginKeyStore';\n\nexport async function createPluginKeySource(options: {\n config: RootConfigService;\n database: DatabaseService;\n logger: LoggerService;\n keyDuration: HumanDuration;\n algorithm?: string;\n}): Promise<PluginKeySource> {\n const keyStoreConfig = options.config.getOptionalConfig(CONFIG_ROOT_KEY);\n const type = keyStoreConfig?.getOptionalString('type') ?? 'database';\n\n if (!keyStoreConfig || type === 'database') {\n return DatabasePluginKeySource.create({\n database: options.database,\n logger: options.logger,\n keyDuration: options.keyDuration,\n algorithm: options.algorithm,\n });\n } else if (type === 'static') {\n return StaticConfigPluginKeySource.create({\n sourceConfig: keyStoreConfig,\n keyDuration: options.keyDuration,\n });\n }\n\n throw new Error(\n `Unsupported config value ${CONFIG_ROOT_KEY}.type '${type}'; expected one of 'database', 'static'`,\n );\n}\n"],"names":["DatabasePluginKeySource","StaticConfigPluginKeySource"],"mappings":";;;;;AA0BA,MAAM,eAAA,GAAkB,6BAAA;AAExB,eAAsB,sBAAsB,OAAA,EAMf;AAC3B,EAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,MAAA,CAAO,iBAAA,CAAkB,eAAe,CAAA;AACvE,EAAA,MAAM,IAAA,GAAO,cAAA,EAAgB,iBAAA,CAAkB,MAAM,CAAA,IAAK,UAAA;AAE1D,EAAA,IAAI,CAAC,cAAA,IAAkB,IAAA,KAAS,UAAA,EAAY;AAC1C,IAAA,OAAOA,gDAAwB,MAAA,CAAO;AAAA,MACpC,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,WAAW,OAAA,CAAQ;AAAA,KACpB,CAAA;AAAA,EACH,CAAA,MAAA,IAAW,SAAS,QAAA,EAAU;AAC5B,IAAA,OAAOC,wDAA4B,MAAA,CAAO;AAAA,MACxC,YAAA,EAAc,cAAA;AAAA,MACd,aAAa,OAAA,CAAQ;AAAA,KACtB,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,yBAAA,EAA4B,eAAe,CAAA,OAAA,EAAU,IAAI,CAAA,uCAAA;AAAA,GAC3D;AACF;;;;"}
1
+ {"version":3,"file":"createPluginKeySource.cjs.js","sources":["../../../../../src/entrypoints/auth/plugin/keys/createPluginKeySource.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 DatabaseService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { HumanDuration } from '@backstage/types';\nimport { DatabasePluginKeySource } from './DatabasePluginKeySource';\nimport { StaticConfigPluginKeySource } from './StaticConfigPluginKeySource';\nimport { PluginKeySource } from './types';\n\nconst CONFIG_ROOT_KEY = 'backend.auth.pluginKeyStore';\n\nexport async function createPluginKeySource(options: {\n config: RootConfigService;\n database: DatabaseService;\n logger: LoggerService;\n keyDuration: HumanDuration;\n algorithm?: string;\n}): Promise<PluginKeySource> {\n const keyStoreConfig = options.config.getOptionalConfig(CONFIG_ROOT_KEY);\n const type = keyStoreConfig?.getOptionalString('type') ?? 'database';\n\n if (!keyStoreConfig || type === 'database') {\n return DatabasePluginKeySource.create({\n database: options.database,\n logger: options.logger,\n keyDuration: options.keyDuration,\n algorithm: options.algorithm,\n });\n } else if (type === 'static') {\n return StaticConfigPluginKeySource.create({\n sourceConfig: keyStoreConfig,\n keyDuration: options.keyDuration,\n });\n }\n\n throw new Error(\n `Unsupported config value ${CONFIG_ROOT_KEY}.type '${type}'; expected one of 'database', 'static'`,\n );\n}\n"],"names":["DatabasePluginKeySource","StaticConfigPluginKeySource"],"mappings":";;;;;AA0BA,MAAM,eAAA,GAAkB,6BAAA;AAExB,eAAsB,sBAAsB,OAAA,EAMf;AAC3B,EAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,MAAA,CAAO,iBAAA,CAAkB,eAAe,CAAA;AACvE,EAAA,MAAM,IAAA,GAAO,cAAA,EAAgB,iBAAA,CAAkB,MAAM,CAAA,IAAK,UAAA;AAE1D,EAAA,IAAI,CAAC,cAAA,IAAkB,IAAA,KAAS,UAAA,EAAY;AAC1C,IAAA,OAAOA,gDAAwB,MAAA,CAAO;AAAA,MACpC,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,WAAW,OAAA,CAAQ;AAAA,KACpB,CAAA;AAAA,EACH,CAAA,MAAA,IAAW,SAAS,QAAA,EAAU;AAC5B,IAAA,OAAOC,wDAA4B,MAAA,CAAO;AAAA,MACxC,YAAA,EAAc,cAAA;AAAA,MACd,aAAa,OAAA,CAAQ;AAAA,KACtB,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,yBAAA,EAA4B,eAAe,CAAA,OAAA,EAAU,IAAI,CAAA,uCAAA;AAAA,GAC3D;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"UserTokenHandler.cjs.js","sources":["../../../../src/entrypoints/auth/user/UserTokenHandler.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 { DiscoveryService, LoggerService } from '@backstage/backend-plugin-api';\nimport { AuthenticationError } from '@backstage/errors';\nimport { tokenTypes } from '@backstage/plugin-auth-node';\nimport {\n base64url,\n decodeJwt,\n decodeProtectedHeader,\n jwtVerify,\n JWTVerifyOptions,\n} from 'jose';\nimport { JwksClient } from '../JwksClient';\n\n/**\n * An identity client to interact with auth-backend and authenticate Backstage\n * tokens\n *\n * @internal\n */\nexport class UserTokenHandler {\n static create(options: {\n discovery: DiscoveryService;\n logger: LoggerService;\n }): UserTokenHandler {\n const jwksClient = new JwksClient(async () => {\n const url = await options.discovery.getBaseUrl('auth');\n return new URL(`${url}/.well-known/jwks.json`);\n });\n return new UserTokenHandler(jwksClient, options.logger);\n }\n\n private readonly jwksClient: JwksClient;\n private readonly logger: LoggerService;\n\n constructor(jwksClient: JwksClient, logger: LoggerService) {\n this.jwksClient = jwksClient;\n this.logger = logger;\n }\n\n async verifyToken(token: string) {\n const verifyOpts = this.#getTokenVerificationOptions(token);\n if (!verifyOpts) {\n return undefined;\n }\n\n // Verify a limited token, ensuring the necessarily claims are present and token type is correct\n const { payload } = await jwtVerify(\n token,\n this.jwksClient.getKey,\n verifyOpts,\n ).catch(e => {\n this.logger.warn('Failed to verify incoming user token', e);\n throw new AuthenticationError('Failed user token verification');\n });\n\n const userEntityRef = payload.sub;\n\n if (!userEntityRef) {\n throw new AuthenticationError('No user sub found in token');\n }\n\n return { userEntityRef };\n }\n\n #getTokenVerificationOptions(token: string): JWTVerifyOptions | undefined {\n try {\n const { typ } = decodeProtectedHeader(token);\n\n if (typ === tokenTypes.user.typParam) {\n return {\n requiredClaims: ['iat', 'exp', 'sub'],\n typ: tokenTypes.user.typParam,\n };\n }\n\n if (typ === tokenTypes.limitedUser.typParam) {\n return {\n requiredClaims: ['iat', 'exp', 'sub'],\n typ: tokenTypes.limitedUser.typParam,\n };\n }\n\n const { aud } = decodeJwt(token);\n if (aud === tokenTypes.user.audClaim) {\n return {\n audience: tokenTypes.user.audClaim,\n };\n }\n } catch {\n /* ignore */\n }\n\n return undefined;\n }\n\n createLimitedUserToken(backstageToken: string) {\n const [headerRaw, payloadRaw] = backstageToken.split('.');\n const header = JSON.parse(\n new TextDecoder().decode(base64url.decode(headerRaw)),\n );\n const payload = JSON.parse(\n new TextDecoder().decode(base64url.decode(payloadRaw)),\n );\n\n const tokenType = header.typ;\n\n // Only new user tokens can be used to create a limited user token. If we\n // can't create a limited token, or the token is already a limited one, we\n // return the original token\n if (!tokenType || tokenType === tokenTypes.limitedUser.typParam) {\n return { token: backstageToken, expiresAt: new Date(payload.exp * 1000) };\n }\n\n if (tokenType !== tokenTypes.user.typParam) {\n throw new AuthenticationError(\n 'Failed to create limited user token, invalid token type',\n );\n }\n\n if (!payload.uip) {\n throw new AuthenticationError(\n 'Failed to create limited user token, missing user identity proof',\n );\n }\n\n // NOTE: The order and properties in both the header and payload must match\n // the usage in plugins/auth-backend/src/identity/TokenFactory.ts\n const limitedUserToken = [\n base64url.encode(\n JSON.stringify({\n typ: tokenTypes.limitedUser.typParam,\n alg: header.alg,\n kid: header.kid,\n }),\n ),\n base64url.encode(\n JSON.stringify({\n sub: payload.sub,\n iat: payload.iat,\n exp: payload.exp,\n }),\n ),\n payload.uip,\n ].join('.');\n\n return { token: limitedUserToken, expiresAt: new Date(payload.exp * 1000) };\n }\n\n isLimitedUserToken(token: string): boolean {\n try {\n const { typ } = decodeProtectedHeader(token);\n return typ === tokenTypes.limitedUser.typParam;\n } catch {\n return false;\n }\n }\n}\n"],"names":["JwksClient","jwtVerify","AuthenticationError","decodeProtectedHeader","tokenTypes","decodeJwt","base64url"],"mappings":"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"}
1
+ {"version":3,"file":"UserTokenHandler.cjs.js","sources":["../../../../src/entrypoints/auth/user/UserTokenHandler.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 { DiscoveryService, LoggerService } from '@backstage/backend-plugin-api';\nimport { AuthenticationError } from '@backstage/errors';\nimport { tokenTypes } from '@backstage/plugin-auth-node';\nimport {\n base64url,\n decodeJwt,\n decodeProtectedHeader,\n jwtVerify,\n JWTVerifyOptions,\n} from 'jose';\nimport { JwksClient } from '../JwksClient';\n\n/**\n * An identity client to interact with auth-backend and authenticate Backstage\n * tokens\n *\n * @internal\n */\nexport class UserTokenHandler {\n static create(options: {\n discovery: DiscoveryService;\n logger: LoggerService;\n }): UserTokenHandler {\n const jwksClient = new JwksClient(async () => {\n const url = await options.discovery.getBaseUrl('auth');\n return new URL(`${url}/.well-known/jwks.json`);\n });\n return new UserTokenHandler(jwksClient, options.logger);\n }\n\n private readonly jwksClient: JwksClient;\n private readonly logger: LoggerService;\n\n constructor(jwksClient: JwksClient, logger: LoggerService) {\n this.jwksClient = jwksClient;\n this.logger = logger;\n }\n\n async verifyToken(token: string) {\n const verifyOpts = this.#getTokenVerificationOptions(token);\n if (!verifyOpts) {\n return undefined;\n }\n\n // Verify a limited token, ensuring the necessarily claims are present and token type is correct\n const { payload } = await jwtVerify(\n token,\n this.jwksClient.getKey,\n verifyOpts,\n ).catch(e => {\n this.logger.warn('Failed to verify incoming user token', e);\n throw new AuthenticationError('Failed user token verification');\n });\n\n const userEntityRef = payload.sub;\n\n if (!userEntityRef) {\n throw new AuthenticationError('No user sub found in token');\n }\n\n return { userEntityRef };\n }\n\n #getTokenVerificationOptions(token: string): JWTVerifyOptions | undefined {\n try {\n const { typ } = decodeProtectedHeader(token);\n\n if (typ === tokenTypes.user.typParam) {\n return {\n requiredClaims: ['iat', 'exp', 'sub'],\n typ: tokenTypes.user.typParam,\n };\n }\n\n if (typ === tokenTypes.limitedUser.typParam) {\n return {\n requiredClaims: ['iat', 'exp', 'sub'],\n typ: tokenTypes.limitedUser.typParam,\n };\n }\n\n const { aud } = decodeJwt(token);\n if (aud === tokenTypes.user.audClaim) {\n return {\n audience: tokenTypes.user.audClaim,\n };\n }\n } catch {\n /* ignore */\n }\n\n return undefined;\n }\n\n createLimitedUserToken(backstageToken: string) {\n const [headerRaw, payloadRaw] = backstageToken.split('.');\n const header = JSON.parse(\n new TextDecoder().decode(base64url.decode(headerRaw)),\n );\n const payload = JSON.parse(\n new TextDecoder().decode(base64url.decode(payloadRaw)),\n );\n\n const tokenType = header.typ;\n\n // Only new user tokens can be used to create a limited user token. If we\n // can't create a limited token, or the token is already a limited one, we\n // return the original token\n if (!tokenType || tokenType === tokenTypes.limitedUser.typParam) {\n return { token: backstageToken, expiresAt: new Date(payload.exp * 1000) };\n }\n\n if (tokenType !== tokenTypes.user.typParam) {\n throw new AuthenticationError(\n 'Failed to create limited user token, invalid token type',\n );\n }\n\n if (!payload.uip) {\n throw new AuthenticationError(\n 'Failed to create limited user token, missing user identity proof',\n );\n }\n\n // NOTE: The order and properties in both the header and payload must match\n // the usage in plugins/auth-backend/src/identity/TokenFactory.ts\n const limitedUserToken = [\n base64url.encode(\n JSON.stringify({\n typ: tokenTypes.limitedUser.typParam,\n alg: header.alg,\n kid: header.kid,\n }),\n ),\n base64url.encode(\n JSON.stringify({\n sub: payload.sub,\n iat: payload.iat,\n exp: payload.exp,\n }),\n ),\n payload.uip,\n ].join('.');\n\n return { token: limitedUserToken, expiresAt: new Date(payload.exp * 1000) };\n }\n\n isLimitedUserToken(token: string): boolean {\n try {\n const { typ } = decodeProtectedHeader(token);\n return typ === tokenTypes.limitedUser.typParam;\n } catch {\n return false;\n }\n }\n}\n"],"names":["JwksClient","jwtVerify","AuthenticationError","decodeProtectedHeader","tokenTypes","decodeJwt","base64url"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CacheClient.cjs.js","sources":["../../../src/entrypoints/cache/CacheClient.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 CacheService,\n CacheServiceOptions,\n CacheServiceSetOptions,\n} from '@backstage/backend-plugin-api';\nimport { JsonValue } from '@backstage/types';\nimport { createHash } from 'node:crypto';\nimport Keyv from 'keyv';\nimport { ttlToMilliseconds } from './types';\n\nexport type CacheClientFactory = (options: CacheServiceOptions) => Keyv;\n\n/**\n * A basic, concrete implementation of the CacheService, suitable for almost\n * all uses in Backstage.\n */\nexport class DefaultCacheClient implements CacheService {\n #client: Keyv;\n #clientFactory: CacheClientFactory;\n #options: CacheServiceOptions;\n\n constructor(\n client: Keyv,\n clientFactory: CacheClientFactory,\n options: CacheServiceOptions,\n ) {\n this.#client = client;\n this.#clientFactory = clientFactory;\n this.#options = options;\n }\n\n async get<TValue extends JsonValue>(\n key: string,\n ): Promise<TValue | undefined> {\n const k = this.getNormalizedKey(key);\n const value = await this.#client.get(k);\n return value as TValue | undefined;\n }\n\n async set(\n key: string,\n value: JsonValue,\n opts: CacheServiceSetOptions = {},\n ): Promise<void> {\n const k = this.getNormalizedKey(key);\n const ttl =\n opts.ttl !== undefined ? ttlToMilliseconds(opts.ttl) : undefined;\n await this.#client.set(k, value, ttl);\n }\n\n async delete(key: string): Promise<void> {\n const k = this.getNormalizedKey(key);\n await this.#client.delete(k);\n }\n\n withOptions(options: CacheServiceOptions): CacheService {\n const newOptions = { ...this.#options, ...options };\n return new DefaultCacheClient(\n this.#clientFactory(newOptions),\n this.#clientFactory,\n newOptions,\n );\n }\n\n /**\n * Ensures keys are well-formed for any/all cache stores.\n */\n private getNormalizedKey(candidateKey: string): string {\n // Remove potentially invalid characters.\n const wellFormedKey = Buffer.from(candidateKey).toString('base64');\n\n // Memcache in particular doesn't do well with keys > 250 bytes.\n // Padded because a plugin ID is also prepended to the key.\n if (wellFormedKey.length < 200) {\n return wellFormedKey;\n }\n\n return createHash('sha256').update(candidateKey).digest('base64');\n }\n}\n"],"names":["ttlToMilliseconds","createHash"],"mappings":";;;;;AAgCO,MAAM,kBAAA,CAA2C;AAAA,EACtD,OAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EAEA,WAAA,CACE,MAAA,EACA,aAAA,EACA,OAAA,EACA;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,cAAA,GAAiB,aAAA;AACtB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAAA,EAClB;AAAA,EAEA,MAAM,IACJ,GAAA,EAC6B;AAC7B,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA;AACnC,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAC,CAAA;AACtC,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAM,GAAA,CACJ,GAAA,EACA,KAAA,EACA,IAAA,GAA+B,EAAC,EACjB;AACf,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA;AACnC,IAAA,MAAM,MACJ,IAAA,CAAK,GAAA,KAAQ,SAAYA,uBAAA,CAAkB,IAAA,CAAK,GAAG,CAAA,GAAI,MAAA;AACzD,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,OAAO,GAAG,CAAA;AAAA,EACtC;AAAA,EAEA,MAAM,OAAO,GAAA,EAA4B;AACvC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA;AACnC,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA;AAAA,EAC7B;AAAA,EAEA,YAAY,OAAA,EAA4C;AACtD,IAAA,MAAM,aAAa,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,GAAG,OAAA,EAAQ;AAClD,IAAA,OAAO,IAAI,kBAAA;AAAA,MACT,IAAA,CAAK,eAAe,UAAU,CAAA;AAAA,MAC9B,IAAA,CAAK,cAAA;AAAA,MACL;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,YAAA,EAA8B;AAErD,IAAA,MAAM,gBAAgB,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,CAAE,SAAS,QAAQ,CAAA;AAIjE,IAAA,IAAI,aAAA,CAAc,SAAS,GAAA,EAAK;AAC9B,MAAA,OAAO,aAAA;AAAA,IACT;AAEA,IAAA,OAAOC,uBAAW,QAAQ,CAAA,CAAE,OAAO,YAAY,CAAA,CAAE,OAAO,QAAQ,CAAA;AAAA,EAClE;AACF;;;;"}
1
+ {"version":3,"file":"CacheClient.cjs.js","sources":["../../../src/entrypoints/cache/CacheClient.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 CacheService,\n CacheServiceOptions,\n CacheServiceSetOptions,\n} from '@backstage/backend-plugin-api';\nimport { JsonValue } from '@backstage/types';\nimport { createHash } from 'node:crypto';\nimport Keyv from 'keyv';\nimport { ttlToMilliseconds } from './types';\n\nexport type CacheClientFactory = (options: CacheServiceOptions) => Keyv;\n\n/**\n * A basic, concrete implementation of the CacheService, suitable for almost\n * all uses in Backstage.\n */\nexport class DefaultCacheClient implements CacheService {\n #client: Keyv;\n #clientFactory: CacheClientFactory;\n #options: CacheServiceOptions;\n\n constructor(\n client: Keyv,\n clientFactory: CacheClientFactory,\n options: CacheServiceOptions,\n ) {\n this.#client = client;\n this.#clientFactory = clientFactory;\n this.#options = options;\n }\n\n async get<TValue extends JsonValue>(\n key: string,\n ): Promise<TValue | undefined> {\n const k = this.getNormalizedKey(key);\n const value = await this.#client.get(k);\n return value as TValue | undefined;\n }\n\n async set(\n key: string,\n value: JsonValue,\n opts: CacheServiceSetOptions = {},\n ): Promise<void> {\n const k = this.getNormalizedKey(key);\n const ttl =\n opts.ttl !== undefined ? ttlToMilliseconds(opts.ttl) : undefined;\n await this.#client.set(k, value, ttl);\n }\n\n async delete(key: string): Promise<void> {\n const k = this.getNormalizedKey(key);\n await this.#client.delete(k);\n }\n\n withOptions(options: CacheServiceOptions): CacheService {\n const newOptions = { ...this.#options, ...options };\n return new DefaultCacheClient(\n this.#clientFactory(newOptions),\n this.#clientFactory,\n newOptions,\n );\n }\n\n /**\n * Ensures keys are well-formed for any/all cache stores.\n */\n private getNormalizedKey(candidateKey: string): string {\n // Remove potentially invalid characters.\n const wellFormedKey = Buffer.from(candidateKey).toString('base64');\n\n // Memcache in particular doesn't do well with keys > 250 bytes.\n // Padded because a plugin ID is also prepended to the key.\n if (wellFormedKey.length < 200) {\n return wellFormedKey;\n }\n\n return createHash('sha256').update(candidateKey).digest('base64');\n }\n}\n"],"names":["ttlToMilliseconds","createHash"],"mappings":";;;;;AAgCO,MAAM,kBAAA,CAA2C;AAAA,EACtD,OAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EAEA,WAAA,CACE,MAAA,EACA,aAAA,EACA,OAAA,EACA;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,cAAA,GAAiB,aAAA;AACtB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAAA,EAClB;AAAA,EAEA,MAAM,IACJ,GAAA,EAC6B;AAC7B,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA;AACnC,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAC,CAAA;AACtC,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAM,GAAA,CACJ,GAAA,EACA,KAAA,EACA,IAAA,GAA+B,EAAC,EACjB;AACf,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA;AACnC,IAAA,MAAM,MACJ,IAAA,CAAK,GAAA,KAAQ,SAAYA,uBAAA,CAAkB,IAAA,CAAK,GAAG,CAAA,GAAI,MAAA;AACzD,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,OAAO,GAAG,CAAA;AAAA,EACtC;AAAA,EAEA,MAAM,OAAO,GAAA,EAA4B;AACvC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA;AACnC,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA;AAAA,EAC7B;AAAA,EAEA,YAAY,OAAA,EAA4C;AACtD,IAAA,MAAM,aAAa,EAAE,GAAG,IAAA,CAAK,QAAA,EAAU,GAAG,OAAA,EAAQ;AAClD,IAAA,OAAO,IAAI,kBAAA;AAAA,MACT,IAAA,CAAK,eAAe,UAAU,CAAA;AAAA,MAC9B,IAAA,CAAK,cAAA;AAAA,MACL;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,YAAA,EAA8B;AAErD,IAAA,MAAM,gBAAgB,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,CAAE,SAAS,QAAQ,CAAA;AAIjE,IAAA,IAAI,aAAA,CAAc,SAAS,GAAA,EAAK;AAC9B,MAAA,OAAO,aAAA;AAAA,IACT;AAEA,IAAA,OAAOC,uBAAW,QAAQ,CAAA,CAAE,OAAO,YAAY,CAAA,CAAE,OAAO,QAAQ,CAAA;AAAA,EAClE;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CacheManager.cjs.js","sources":["../../../src/entrypoints/cache/CacheManager.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 CacheService,\n CacheServiceOptions,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport Keyv from 'keyv';\nimport { DefaultCacheClient } from './CacheClient';\nimport {\n CacheManagerOptions,\n ttlToMilliseconds,\n CacheStoreOptions,\n CacheStoreConnection,\n CacheStoreConnectionObject,\n CacheStoreConfiguration,\n CacheStoreDeps,\n RedisCacheStoreConfiguration,\n RedisCacheStoreOptions,\n InfinispanClientBehaviorOptions,\n InfinispanServerConfig,\n ValkeyCacheStoreOptions,\n} from './types';\nimport { InfinispanOptionsMapper } from './providers/infinispan/InfinispanOptionsMapper';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { ConfigReader, readDurationFromConfig } from '@backstage/config';\nimport {\n InfinispanClientCacheInterface,\n InfinispanKeyvStore,\n} from './providers/infinispan/InfinispanKeyvStore';\nimport type { KeyvRedisOptions, RedisClusterOptions } from '@keyv/redis';\n\ntype StoreFactory = (pluginId: string, defaultTtl: number | undefined) => Keyv;\n\n/**\n * Implements a Cache Manager which will automatically create new cache clients\n * for plugins when requested. All requested cache clients are created with the\n * connection details provided.\n *\n * @public\n */\nexport class CacheManager {\n /**\n * Keys represent supported `backend.cache.store` values, mapped to factories\n * that return Keyv instances appropriate to the store.\n */\n private readonly storeFactories = {\n redis: this.createRedisStoreFactory(),\n valkey: this.createValkeyStoreFactory(),\n memcache: this.createMemcacheStoreFactory(),\n memory: this.createMemoryStoreFactory(),\n infinispan: this.createInfinispanStoreFactory(),\n };\n\n private readonly logger?: LoggerService;\n private readonly store: keyof CacheManager['storeFactories'];\n private readonly connection: CacheStoreConnection;\n private readonly errorHandler: CacheManagerOptions['onError'];\n private readonly defaultTtl?: number;\n private readonly storeOptions?: CacheStoreOptions;\n\n /**\n * Creates a new {@link CacheManager} instance by reading from the `backend`\n * config section, specifically the `.cache` key.\n *\n * @param config - The loaded application configuration.\n * @param options - Optional configuration for the CacheManager.\n * @returns A new CacheManager instance.\n */\n static fromConfig(\n config: RootConfigService,\n options: CacheManagerOptions = {},\n ): CacheManager {\n // If no `backend.cache` config is provided, instantiate the CacheManager\n // with an in-memory cache client.\n const store = config.getOptionalString('backend.cache.store') || 'memory';\n const defaultTtlConfig = config.getOptional('backend.cache.defaultTtl');\n const connection = CacheManager.parseConnection(config);\n const logger = options.logger?.child({\n type: 'cacheManager',\n });\n\n if (config.has('backend.cache.useRedisSets')) {\n logger?.warn(\n \"The 'backend.cache.useRedisSets' configuration key is deprecated and no longer has any effect. The underlying '@keyv/redis' and '@keyv/valkey' libraries no longer support redis sets.\",\n );\n }\n\n let defaultTtl: number | undefined;\n if (defaultTtlConfig !== undefined) {\n if (typeof defaultTtlConfig === 'number') {\n defaultTtl = defaultTtlConfig;\n } else {\n defaultTtl = durationToMilliseconds(\n readDurationFromConfig(config, { key: 'backend.cache.defaultTtl' }),\n );\n }\n }\n\n // Read store-specific options from config\n const storeOptions = CacheManager.parseStoreOptions(\n { store, connection },\n { config, logger },\n );\n\n return new CacheManager(\n store,\n connection,\n options.onError,\n logger,\n defaultTtl,\n storeOptions,\n );\n }\n\n /**\n * Parse the connection config, which can be either a plain URL string\n * or an object with connection options (e.g. `{ url, pingInterval }`)\n * passed through to the underlying store client.\n *\n * @param config - The configuration service\n * @returns The parsed connection config, either a string or an object depending on how it was configured\n */\n private static parseConnection(\n config: RootConfigService,\n ): CacheStoreConnection {\n const raw = config.getOptional('backend.cache.connection');\n const store = config.getOptionalString('backend.cache.store') || 'memory';\n\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n if (store !== 'redis') {\n throw new Error(\n \"backend.cache.connection object form is only supported when backend.cache.store is 'redis'\",\n );\n }\n\n const url = (raw as { url?: unknown }).url;\n if (typeof url !== 'string' || url.length === 0) {\n throw new Error(\n \"backend.cache.connection object must include a non-empty 'url' string\",\n );\n }\n\n return raw as CacheStoreConnectionObject;\n }\n\n if (raw !== undefined && typeof raw !== 'string') {\n throw new Error(\n `backend.cache.connection must be a string or object, got ${typeof raw}`,\n );\n }\n\n return config.getOptionalString('backend.cache.connection') ?? '';\n }\n\n /**\n * Parse store-specific options from configuration.\n *\n * @param store - The cache store type ('redis', 'valkey', 'memcache', 'infinispan', or 'memory')\n * @param config - The configuration service\n * @param logger - Optional logger for warnings\n * @returns The parsed store options\n */\n private static parseStoreOptions(\n config: { store: string; connection: CacheStoreConnection },\n deps: CacheStoreDeps,\n ): CacheStoreOptions | undefined {\n const { store, connection } = config;\n const storeConfigPath = `backend.cache.${store}`;\n\n if (store !== 'memory' && !deps.config.has(storeConfigPath)) {\n deps.logger?.warn(\n `No configuration found for cache store '${store}' at '${storeConfigPath}'.`,\n );\n }\n\n switch (store) {\n case 'redis':\n return CacheManager.parseRedisOptions(\n { storeConfigPath, connection },\n deps,\n );\n case 'valkey':\n return CacheManager.parseValkeyOptions({ storeConfigPath }, deps);\n case 'infinispan':\n return InfinispanOptionsMapper.parseInfinispanOptions(\n { storeConfigPath },\n deps,\n );\n default:\n return undefined;\n }\n }\n\n /**\n * Parse Redis-specific options from configuration.\n */\n private static parseRedisOptions(\n config: RedisCacheStoreConfiguration,\n deps: CacheStoreDeps,\n ): RedisCacheStoreOptions {\n const redisOptions: RedisCacheStoreOptions = {\n type: 'redis',\n };\n\n const redisConfig =\n deps.config.getOptionalConfig(config.storeConfigPath) ??\n new ConfigReader({});\n\n redisOptions.client = {\n namespace: redisConfig.getOptionalString('client.namespace'),\n keyPrefixSeparator:\n redisConfig.getOptionalString('client.keyPrefixSeparator') || ':',\n clearBatchSize: redisConfig.getOptionalNumber('client.clearBatchSize'),\n useUnlink: redisConfig.getOptionalBoolean('client.useUnlink'),\n noNamespaceAffectsAll: redisConfig.getOptionalBoolean(\n 'client.noNamespaceAffectsAll',\n ),\n };\n\n if (redisConfig.has('cluster')) {\n const clusterConfig = redisConfig.getConfig('cluster');\n\n if (!clusterConfig.has('rootNodes')) {\n deps.logger?.warn(\n `Redis cluster config has no 'rootNodes' key, defaulting to non-clustered mode`,\n );\n return redisOptions;\n }\n\n // When connection is an object, merge its properties into cluster\n // defaults so every node inherits those options (e.g. pingInterval).\n let defaults: RedisClusterOptions['defaults'] =\n clusterConfig.getOptional('defaults');\n\n if (typeof config.connection === 'object') {\n const { url: _url, ...connectionDefaults } = config.connection;\n defaults = { ...defaults, ...connectionDefaults };\n }\n\n redisOptions.cluster = {\n rootNodes: clusterConfig.get('rootNodes'),\n defaults,\n minimizeConnections: clusterConfig.getOptionalBoolean(\n 'minimizeConnections',\n ),\n useReplicas: clusterConfig.getOptionalBoolean('useReplicas'),\n maxCommandRedirections: clusterConfig.getOptionalNumber(\n 'maxCommandRedirections',\n ),\n };\n }\n\n return redisOptions;\n }\n\n /**\n * Parse Valkey-specific options from configuration.\n */\n private static parseValkeyOptions(\n config: CacheStoreConfiguration,\n deps: CacheStoreDeps,\n ): ValkeyCacheStoreOptions {\n const valkeyOptions: ValkeyCacheStoreOptions = {\n type: 'valkey',\n };\n\n const valkeyConfig =\n deps.config.getOptionalConfig(config.storeConfigPath) ??\n new ConfigReader({});\n\n valkeyOptions.client = {\n keyPrefix: valkeyConfig.getOptionalString('client.keyPrefix'),\n };\n\n if (valkeyConfig.has('cluster')) {\n const clusterConfig = valkeyConfig.getConfig('cluster');\n\n if (!clusterConfig.has('rootNodes')) {\n deps.logger?.warn(\n `Valkey cluster config has no 'rootNodes' key, defaulting to non-clustered mode`,\n );\n return valkeyOptions;\n }\n\n valkeyOptions.cluster = {\n rootNodes: clusterConfig.get('rootNodes'),\n options: {\n redisOptions: clusterConfig.getOptional('defaults'),\n scaleReads: clusterConfig.getOptionalBoolean('useReplicas')\n ? 'slave'\n : undefined,\n maxRedirections: clusterConfig.getOptionalNumber(\n 'maxCommandRedirections',\n ),\n lazyConnect: clusterConfig.getOptionalBoolean('minimizeConnections'),\n },\n };\n }\n\n return valkeyOptions;\n }\n\n /**\n * Construct the full namespace based on the options and pluginId.\n *\n * @param pluginId - The plugin ID to namespace\n * @param storeOptions - Optional cache store configuration options\n * @returns The constructed namespace string combining the configured namespace with pluginId\n */\n private static constructNamespace(\n pluginId: string,\n storeOptions: RedisCacheStoreOptions | ValkeyCacheStoreOptions | undefined,\n ): string {\n let prefix: string;\n switch (storeOptions?.type) {\n case 'redis':\n prefix = storeOptions?.client?.namespace\n ? `${storeOptions.client.namespace}${\n storeOptions.client.keyPrefixSeparator ?? ':'\n }`\n : '';\n break;\n case 'valkey':\n prefix = storeOptions.client?.keyPrefix ?? '';\n break;\n default:\n prefix = '';\n }\n\n return `${prefix}${pluginId}`;\n }\n\n /** @internal */\n constructor(\n store: string,\n connection: CacheStoreConnection,\n errorHandler: CacheManagerOptions['onError'],\n logger?: LoggerService,\n defaultTtl?: number,\n storeOptions?: CacheStoreOptions,\n ) {\n if (!this.storeFactories.hasOwnProperty(store)) {\n throw new Error(`Unknown cache store: ${store}`);\n }\n this.logger = logger;\n this.store = store as keyof CacheManager['storeFactories'];\n this.connection = connection;\n this.errorHandler = errorHandler;\n this.defaultTtl = defaultTtl;\n this.storeOptions = storeOptions;\n }\n\n /**\n * Generates a PluginCacheManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the cache manager should be created for.\n * Plugin names should be unique.\n */\n forPlugin(pluginId: string): CacheService {\n const clientFactory = (options: CacheServiceOptions) => {\n const ttl = options.defaultTtl ?? this.defaultTtl;\n return this.getClientWithTtl(\n pluginId,\n ttl !== undefined ? ttlToMilliseconds(ttl) : undefined,\n );\n };\n\n return new DefaultCacheClient(clientFactory({}), clientFactory, {});\n }\n\n private getClientWithTtl(pluginId: string, ttl: number | undefined): Keyv {\n return this.storeFactories[this.store](pluginId, ttl);\n }\n\n private createRedisStoreFactory(): StoreFactory {\n const keyvRedis = require('@keyv/redis') as typeof import('@keyv/redis');\n const KeyvRedis = keyvRedis.default;\n const { createCluster } = keyvRedis;\n const stores: Record<string, InstanceType<typeof KeyvRedis>> = {};\n\n return (pluginId, defaultTtl) => {\n if (this.storeOptions?.type !== 'redis') {\n throw new Error(\n `Internal error: Wrong config type passed to redis factory: ${this.storeOptions?.type}`,\n );\n }\n if (!stores[pluginId]) {\n const redisOptions: KeyvRedisOptions = this.storeOptions?.client || {\n keyPrefixSeparator: ':',\n };\n if (this.storeOptions?.cluster) {\n // Create a Redis cluster\n const cluster = createCluster(this.storeOptions.cluster);\n stores[pluginId] = new KeyvRedis(cluster, redisOptions);\n } else {\n // Create a regular Redis connection\n stores[pluginId] = new KeyvRedis(this.connection, redisOptions);\n }\n\n // Always provide an error handler to avoid stopping the process\n stores[pluginId].on('error', (err: Error) => {\n this.logger?.error('Failed to create redis cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: CacheManager.constructNamespace(pluginId, this.storeOptions),\n ttl: defaultTtl,\n store: stores[pluginId],\n emitErrors: false,\n useKeyPrefix: false,\n });\n };\n }\n\n private createValkeyStoreFactory(): StoreFactory {\n const KeyvValkey = require('@keyv/valkey').default;\n const { Cluster } = require('iovalkey');\n const stores: Record<string, typeof KeyvValkey> = {};\n\n return (pluginId, defaultTtl) => {\n if (this.storeOptions?.type !== 'valkey') {\n throw new Error(\n `Internal error: Wrong config type passed to valkey factory: ${this.storeOptions?.type}`,\n );\n }\n if (!stores[pluginId]) {\n const valkeyOptions = this.storeOptions?.client;\n if (this.storeOptions?.cluster) {\n // Create an iovalkey Cluster instance, which is the type that @keyv/valkey expects\n const cluster = new Cluster(\n this.storeOptions.cluster.rootNodes,\n this.storeOptions.cluster.options,\n );\n stores[pluginId] = new KeyvValkey(cluster, valkeyOptions);\n } else {\n // Create a regular Valkey connection\n stores[pluginId] = new KeyvValkey(this.connection, valkeyOptions);\n }\n\n // Always provide an error handler to avoid stopping the process\n stores[pluginId].on('error', (err: Error) => {\n this.logger?.error('Failed to create valkey cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: CacheManager.constructNamespace(pluginId, this.storeOptions),\n ttl: defaultTtl,\n store: stores[pluginId],\n emitErrors: false,\n useKeyPrefix: false,\n });\n };\n }\n\n private createMemcacheStoreFactory(): StoreFactory {\n const KeyvMemcache = require('@keyv/memcache').default;\n const stores: Record<string, typeof KeyvMemcache> = {};\n\n return (pluginId, defaultTtl) => {\n if (!stores[pluginId]) {\n stores[pluginId] = new KeyvMemcache(this.connection);\n // Always provide an error handler to avoid stopping the process\n stores[pluginId].on('error', (err: Error) => {\n this.logger?.error('Failed to create memcache cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store: stores[pluginId],\n });\n };\n }\n\n private createMemoryStoreFactory(): StoreFactory {\n const store = new Map();\n return (pluginId, defaultTtl) =>\n new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store,\n });\n }\n\n private createInfinispanStoreFactory(): StoreFactory {\n const stores: Record<string, InfinispanKeyvStore> = {};\n\n return (pluginId, defaultTtl) => {\n if (this.storeOptions?.type !== 'infinispan') {\n throw new Error(\n `Internal error: Wrong config type passed to infinispan factory: ${this.storeOptions?.type}`,\n );\n }\n\n if (!stores[pluginId]) {\n // Use sync version for testing environments\n const isTest =\n process.env.NODE_ENV === 'test' || typeof jest !== 'undefined';\n\n // Create the client promise ONCE and reuse it\n const clientPromise: Promise<InfinispanClientCacheInterface> = isTest\n ? this.createInfinispanClientSync()\n : this.createInfinispanClientAsync();\n\n this.logger?.info(\n `Creating Infinispan cache client for plugin ${pluginId} isTest = ${isTest}`,\n );\n const storeInstance = new InfinispanKeyvStore({\n clientPromise,\n logger: this.logger!,\n });\n\n stores[pluginId] = storeInstance;\n\n // Always provide an error handler to avoid stopping the process\n storeInstance.on('error', (err: Error) => {\n this.logger?.error('Failed to create infinispan cache client', err);\n this.errorHandler?.(err);\n });\n }\n\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n store: stores[pluginId],\n emitErrors: false,\n });\n };\n }\n\n /**\n * Creates an Infinispan client using dynamic import (production use).\n * @returns Promise that resolves to an Infinispan client\n */\n private async createInfinispanClientAsync(): Promise<InfinispanClientCacheInterface> {\n return this.createInfinispanClient(false);\n }\n\n /**\n * Creates an Infinispan client using synchronous import (testing purposes).\n * @returns Promise that resolves to an Infinispan client\n */\n private createInfinispanClientSync(): Promise<InfinispanClientCacheInterface> {\n return this.createInfinispanClient(true);\n }\n\n /**\n * Creates an Infinispan client based on the provided configuration.\n * @param useSync - Whether to use synchronous import (for testing) or dynamic import\n * @returns Promise that resolves to an Infinispan client\n */\n private async createInfinispanClient(\n useSync: boolean = false,\n ): Promise<InfinispanClientCacheInterface> {\n try {\n this.logger?.info('Creating Infinispan client');\n\n if (this.storeOptions?.type === 'infinispan') {\n // Import infinispan based on the useSync parameter\n const infinispan = useSync\n ? require('infinispan')\n : await import('infinispan');\n\n const client = await infinispan.client(\n this.storeOptions.servers as InfinispanServerConfig[],\n this.storeOptions.options as InfinispanClientBehaviorOptions,\n );\n\n this.logger?.info('Infinispan client created successfully');\n return client;\n }\n throw new Error('Infinispan store options are not defined');\n } catch (error: any) {\n this.logger?.error('Failed to create Infinispan client', {\n error: error.message,\n });\n throw error;\n }\n }\n}\n"],"names":["config","durationToMilliseconds","readDurationFromConfig","InfinispanOptionsMapper","ConfigReader","ttlToMilliseconds","DefaultCacheClient","Keyv","InfinispanKeyvStore"],"mappings":";;;;;;;;;;;;;;AAwDO,MAAM,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKP,cAAA,GAAiB;AAAA,IAChC,KAAA,EAAO,KAAK,uBAAA,EAAwB;AAAA,IACpC,MAAA,EAAQ,KAAK,wBAAA,EAAyB;AAAA,IACtC,QAAA,EAAU,KAAK,0BAAA,EAA2B;AAAA,IAC1C,MAAA,EAAQ,KAAK,wBAAA,EAAyB;AAAA,IACtC,UAAA,EAAY,KAAK,4BAAA;AAA6B,GAChD;AAAA,EAEiB,MAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUjB,OAAO,UAAA,CACLA,QAAA,EACA,OAAA,GAA+B,EAAC,EAClB;AAGd,IAAA,MAAM,KAAA,GAAQA,QAAA,CAAO,iBAAA,CAAkB,qBAAqB,CAAA,IAAK,QAAA;AACjE,IAAA,MAAM,gBAAA,GAAmBA,QAAA,CAAO,WAAA,CAAY,0BAA0B,CAAA;AACtE,IAAA,MAAM,UAAA,GAAa,YAAA,CAAa,eAAA,CAAgBA,QAAM,CAAA;AACtD,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,EAAQ,KAAA,CAAM;AAAA,MACnC,IAAA,EAAM;AAAA,KACP,CAAA;AAED,IAAA,IAAIA,QAAA,CAAO,GAAA,CAAI,4BAA4B,CAAA,EAAG;AAC5C,MAAA,MAAA,EAAQ,IAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,UAAA;AACJ,IAAA,IAAI,qBAAqB,MAAA,EAAW;AAClC,MAAA,IAAI,OAAO,qBAAqB,QAAA,EAAU;AACxC,QAAA,UAAA,GAAa,gBAAA;AAAA,MACf,CAAA,MAAO;AACL,QAAA,UAAA,GAAaC,4BAAA;AAAA,UACXC,6BAAA,CAAuBF,QAAA,EAAQ,EAAE,GAAA,EAAK,4BAA4B;AAAA,SACpE;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,eAAe,YAAA,CAAa,iBAAA;AAAA,MAChC,EAAE,OAAO,UAAA,EAAW;AAAA,MACpB,UAAEA,UAAQ,MAAA;AAAO,KACnB;AAEA,IAAA,OAAO,IAAI,YAAA;AAAA,MACT,KAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA,CAAQ,OAAA;AAAA,MACR,MAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAe,gBACb,MAAA,EACsB;AACtB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,WAAA,CAAY,0BAA0B,CAAA;AACzD,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,qBAAqB,CAAA,IAAK,QAAA;AAEjE,IAAA,IAAI,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACzD,MAAA,IAAI,UAAU,OAAA,EAAS;AACrB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,MAAM,MAAO,GAAA,CAA0B,GAAA;AACvC,MAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,WAAW,CAAA,EAAG;AAC/C,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,OAAO,GAAA;AAAA,IACT;AAEA,IAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,OAAO,GAAA,KAAQ,QAAA,EAAU;AAChD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yDAAA,EAA4D,OAAO,GAAG,CAAA;AAAA,OACxE;AAAA,IACF;AAEA,IAAA,OAAO,MAAA,CAAO,iBAAA,CAAkB,0BAA0B,CAAA,IAAK,EAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAe,iBAAA,CACb,MAAA,EACA,IAAA,EAC+B;AAC/B,IAAA,MAAM,EAAE,KAAA,EAAO,UAAA,EAAW,GAAI,MAAA;AAC9B,IAAA,MAAM,eAAA,GAAkB,iBAAiB,KAAK,CAAA,CAAA;AAE9C,IAAA,IAAI,UAAU,QAAA,IAAY,CAAC,KAAK,MAAA,CAAO,GAAA,CAAI,eAAe,CAAA,EAAG;AAC3D,MAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,QACX,CAAA,wCAAA,EAA2C,KAAK,CAAA,MAAA,EAAS,eAAe,CAAA,EAAA;AAAA,OAC1E;AAAA,IACF;AAEA,IAAA,QAAQ,KAAA;AAAO,MACb,KAAK,OAAA;AACH,QAAA,OAAO,YAAA,CAAa,iBAAA;AAAA,UAClB,EAAE,iBAAiB,UAAA,EAAW;AAAA,UAC9B;AAAA,SACF;AAAA,MACF,KAAK,QAAA;AACH,QAAA,OAAO,YAAA,CAAa,kBAAA,CAAmB,EAAE,eAAA,IAAmB,IAAI,CAAA;AAAA,MAClE,KAAK,YAAA;AACH,QAAA,OAAOG,+CAAA,CAAwB,sBAAA;AAAA,UAC7B,EAAE,eAAA,EAAgB;AAAA,UAClB;AAAA,SACF;AAAA,MACF;AACE,QAAA,OAAO,MAAA;AAAA;AACX,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,iBAAA,CACbH,QAAA,EACA,IAAA,EACwB;AACxB,IAAA,MAAM,YAAA,GAAuC;AAAA,MAC3C,IAAA,EAAM;AAAA,KACR;AAEA,IAAA,MAAM,WAAA,GACJ,IAAA,CAAK,MAAA,CAAO,iBAAA,CAAkBA,QAAA,CAAO,eAAe,CAAA,IACpD,IAAII,mBAAA,CAAa,EAAE,CAAA;AAErB,IAAA,YAAA,CAAa,MAAA,GAAS;AAAA,MACpB,SAAA,EAAW,WAAA,CAAY,iBAAA,CAAkB,kBAAkB,CAAA;AAAA,MAC3D,kBAAA,EACE,WAAA,CAAY,iBAAA,CAAkB,2BAA2B,CAAA,IAAK,GAAA;AAAA,MAChE,cAAA,EAAgB,WAAA,CAAY,iBAAA,CAAkB,uBAAuB,CAAA;AAAA,MACrE,SAAA,EAAW,WAAA,CAAY,kBAAA,CAAmB,kBAAkB,CAAA;AAAA,MAC5D,uBAAuB,WAAA,CAAY,kBAAA;AAAA,QACjC;AAAA;AACF,KACF;AAEA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AAC9B,MAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,SAAA,CAAU,SAAS,CAAA;AAErD,MAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA,EAAG;AACnC,QAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,UACX,CAAA,6EAAA;AAAA,SACF;AACA,QAAA,OAAO,YAAA;AAAA,MACT;AAIA,MAAA,IAAI,QAAA,GACF,aAAA,CAAc,WAAA,CAAY,UAAU,CAAA;AAEtC,MAAA,IAAI,OAAOJ,QAAA,CAAO,UAAA,KAAe,QAAA,EAAU;AACzC,QAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAM,GAAG,kBAAA,KAAuBA,QAAA,CAAO,UAAA;AACpD,QAAA,QAAA,GAAW,EAAE,GAAG,QAAA,EAAU,GAAG,kBAAA,EAAmB;AAAA,MAClD;AAEA,MAAA,YAAA,CAAa,OAAA,GAAU;AAAA,QACrB,SAAA,EAAW,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA;AAAA,QACxC,QAAA;AAAA,QACA,qBAAqB,aAAA,CAAc,kBAAA;AAAA,UACjC;AAAA,SACF;AAAA,QACA,WAAA,EAAa,aAAA,CAAc,kBAAA,CAAmB,aAAa,CAAA;AAAA,QAC3D,wBAAwB,aAAA,CAAc,iBAAA;AAAA,UACpC;AAAA;AACF,OACF;AAAA,IACF;AAEA,IAAA,OAAO,YAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,kBAAA,CACbA,QAAA,EACA,IAAA,EACyB;AACzB,IAAA,MAAM,aAAA,GAAyC;AAAA,MAC7C,IAAA,EAAM;AAAA,KACR;AAEA,IAAA,MAAM,YAAA,GACJ,IAAA,CAAK,MAAA,CAAO,iBAAA,CAAkBA,QAAA,CAAO,eAAe,CAAA,IACpD,IAAII,mBAAA,CAAa,EAAE,CAAA;AAErB,IAAA,aAAA,CAAc,MAAA,GAAS;AAAA,MACrB,SAAA,EAAW,YAAA,CAAa,iBAAA,CAAkB,kBAAkB;AAAA,KAC9D;AAEA,IAAA,IAAI,YAAA,CAAa,GAAA,CAAI,SAAS,CAAA,EAAG;AAC/B,MAAA,MAAM,aAAA,GAAgB,YAAA,CAAa,SAAA,CAAU,SAAS,CAAA;AAEtD,MAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA,EAAG;AACnC,QAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,UACX,CAAA,8EAAA;AAAA,SACF;AACA,QAAA,OAAO,aAAA;AAAA,MACT;AAEA,MAAA,aAAA,CAAc,OAAA,GAAU;AAAA,QACtB,SAAA,EAAW,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA;AAAA,QACxC,OAAA,EAAS;AAAA,UACP,YAAA,EAAc,aAAA,CAAc,WAAA,CAAY,UAAU,CAAA;AAAA,UAClD,UAAA,EAAY,aAAA,CAAc,kBAAA,CAAmB,aAAa,IACtD,OAAA,GACA,MAAA;AAAA,UACJ,iBAAiB,aAAA,CAAc,iBAAA;AAAA,YAC7B;AAAA,WACF;AAAA,UACA,WAAA,EAAa,aAAA,CAAc,kBAAA,CAAmB,qBAAqB;AAAA;AACrE,OACF;AAAA,IACF;AAEA,IAAA,OAAO,aAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAe,kBAAA,CACb,QAAA,EACA,YAAA,EACQ;AACR,IAAA,IAAI,MAAA;AACJ,IAAA,QAAQ,cAAc,IAAA;AAAM,MAC1B,KAAK,OAAA;AACH,QAAA,MAAA,GAAS,YAAA,EAAc,MAAA,EAAQ,SAAA,GAC3B,CAAA,EAAG,YAAA,CAAa,MAAA,CAAO,SAAS,CAAA,EAC9B,YAAA,CAAa,MAAA,CAAO,kBAAA,IAAsB,GAC5C,CAAA,CAAA,GACA,EAAA;AACJ,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,MAAA,GAAS,YAAA,CAAa,QAAQ,SAAA,IAAa,EAAA;AAC3C,QAAA;AAAA,MACF;AACE,QAAA,MAAA,GAAS,EAAA;AAAA;AAGb,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,QAAQ,CAAA,CAAA;AAAA,EAC7B;AAAA;AAAA,EAGA,YACE,KAAA,EACA,UAAA,EACA,YAAA,EACA,MAAA,EACA,YACA,YAAA,EACA;AACA,IAAA,IAAI,CAAC,IAAA,CAAK,cAAA,CAAe,cAAA,CAAe,KAAK,CAAA,EAAG;AAC9C,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,KAAK,CAAA,CAAE,CAAA;AAAA,IACjD;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,QAAA,EAAgC;AACxC,IAAA,MAAM,aAAA,GAAgB,CAAC,OAAA,KAAiC;AACtD,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,UAAA,IAAc,IAAA,CAAK,UAAA;AACvC,MAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,QACV,QAAA;AAAA,QACA,GAAA,KAAQ,MAAA,GAAYC,yBAAA,CAAkB,GAAG,CAAA,GAAI;AAAA,OAC/C;AAAA,IACF,CAAA;AAEA,IAAA,OAAO,IAAIC,+BAAmB,aAAA,CAAc,EAAE,CAAA,EAAG,aAAA,EAAe,EAAE,CAAA;AAAA,EACpE;AAAA,EAEQ,gBAAA,CAAiB,UAAkB,GAAA,EAA+B;AACxE,IAAA,OAAO,KAAK,cAAA,CAAe,IAAA,CAAK,KAAK,CAAA,CAAE,UAAU,GAAG,CAAA;AAAA,EACtD;AAAA,EAEQ,uBAAA,GAAwC;AAC9C,IAAA,MAAM,SAAA,GAAY,QAAQ,aAAa,CAAA;AACvC,IAAA,MAAM,YAAY,SAAA,CAAU,OAAA;AAC5B,IAAA,MAAM,EAAE,eAAc,GAAI,SAAA;AAC1B,IAAA,MAAM,SAAyD,EAAC;AAEhE,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,OAAA,EAAS;AACvC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,2DAAA,EAA8D,IAAA,CAAK,YAAA,EAAc,IAAI,CAAA;AAAA,SACvF;AAAA,MACF;AACA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AACrB,QAAA,MAAM,YAAA,GAAiC,IAAA,CAAK,YAAA,EAAc,MAAA,IAAU;AAAA,UAClE,kBAAA,EAAoB;AAAA,SACtB;AACA,QAAA,IAAI,IAAA,CAAK,cAAc,OAAA,EAAS;AAE9B,UAAA,MAAM,OAAA,GAAU,aAAA,CAAc,IAAA,CAAK,YAAA,CAAa,OAAO,CAAA;AACvD,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,SAAA,CAAU,SAAS,YAAY,CAAA;AAAA,QACxD,CAAA,MAAO;AAEL,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,SAAA,CAAU,IAAA,CAAK,YAAY,YAAY,CAAA;AAAA,QAChE;AAGA,QAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AAC3C,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,qCAAA,EAAuC,GAAG,CAAA;AAC7D,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAIC,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,YAAA,CAAa,kBAAA,CAAmB,QAAA,EAAU,KAAK,YAAY,CAAA;AAAA,QACtE,GAAA,EAAK,UAAA;AAAA,QACL,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,QACtB,UAAA,EAAY,KAAA;AAAA,QACZ,YAAA,EAAc;AAAA,OACf,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA,EAEQ,wBAAA,GAAyC;AAC/C,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,cAAc,CAAA,CAAE,OAAA;AAC3C,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,OAAA,CAAQ,UAAU,CAAA;AACtC,IAAA,MAAM,SAA4C,EAAC;AAEnD,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,QAAA,EAAU;AACxC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,4DAAA,EAA+D,IAAA,CAAK,YAAA,EAAc,IAAI,CAAA;AAAA,SACxF;AAAA,MACF;AACA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AACrB,QAAA,MAAM,aAAA,GAAgB,KAAK,YAAA,EAAc,MAAA;AACzC,QAAA,IAAI,IAAA,CAAK,cAAc,OAAA,EAAS;AAE9B,UAAA,MAAM,UAAU,IAAI,OAAA;AAAA,YAClB,IAAA,CAAK,aAAa,OAAA,CAAQ,SAAA;AAAA,YAC1B,IAAA,CAAK,aAAa,OAAA,CAAQ;AAAA,WAC5B;AACA,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,UAAA,CAAW,SAAS,aAAa,CAAA;AAAA,QAC1D,CAAA,MAAO;AAEL,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,UAAA,CAAW,IAAA,CAAK,YAAY,aAAa,CAAA;AAAA,QAClE;AAGA,QAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AAC3C,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,sCAAA,EAAwC,GAAG,CAAA;AAC9D,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAIA,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,YAAA,CAAa,kBAAA,CAAmB,QAAA,EAAU,KAAK,YAAY,CAAA;AAAA,QACtE,GAAA,EAAK,UAAA;AAAA,QACL,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,QACtB,UAAA,EAAY,KAAA;AAAA,QACZ,YAAA,EAAc;AAAA,OACf,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA,EAEQ,0BAAA,GAA2C;AACjD,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,gBAAgB,CAAA,CAAE,OAAA;AAC/C,IAAA,MAAM,SAA8C,EAAC;AAErD,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AACrB,QAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,YAAA,CAAa,KAAK,UAAU,CAAA;AAEnD,QAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AAC3C,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,wCAAA,EAA0C,GAAG,CAAA;AAChE,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAIA,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,QAAA;AAAA,QACX,GAAA,EAAK,UAAA;AAAA,QACL,UAAA,EAAY,KAAA;AAAA,QACZ,KAAA,EAAO,OAAO,QAAQ;AAAA,OACvB,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA,EAEQ,wBAAA,GAAyC;AAC/C,IAAA,MAAM,KAAA,uBAAY,GAAA,EAAI;AACtB,IAAA,OAAO,CAAC,QAAA,EAAU,UAAA,KAChB,IAAIA,qBAAA,CAAK;AAAA,MACP,SAAA,EAAW,QAAA;AAAA,MACX,GAAA,EAAK,UAAA;AAAA,MACL,UAAA,EAAY,KAAA;AAAA,MACZ;AAAA,KACD,CAAA;AAAA,EACL;AAAA,EAEQ,4BAAA,GAA6C;AACnD,IAAA,MAAM,SAA8C,EAAC;AAErD,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,YAAA,EAAc;AAC5C,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,gEAAA,EAAmE,IAAA,CAAK,YAAA,EAAc,IAAI,CAAA;AAAA,SAC5F;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AAErB,QAAA,MAAM,SACJ,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,MAAA,IAAU,OAAO,IAAA,KAAS,WAAA;AAGrD,QAAA,MAAM,gBAAyD,MAAA,GAC3D,IAAA,CAAK,0BAAA,EAA2B,GAChC,KAAK,2BAAA,EAA4B;AAErC,QAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,UACX,CAAA,4CAAA,EAA+C,QAAQ,CAAA,UAAA,EAAa,MAAM,CAAA;AAAA,SAC5E;AACA,QAAA,MAAM,aAAA,GAAgB,IAAIC,uCAAA,CAAoB;AAAA,UAC5C,aAAA;AAAA,UACA,QAAQ,IAAA,CAAK;AAAA,SACd,CAAA;AAED,QAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,aAAA;AAGnB,QAAA,aAAA,CAAc,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AACxC,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,0CAAA,EAA4C,GAAG,CAAA;AAClE,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,IAAID,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,QAAA;AAAA,QACX,GAAA,EAAK,UAAA;AAAA,QACL,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,QACtB,UAAA,EAAY;AAAA,OACb,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,2BAAA,GAAuE;AACnF,IAAA,OAAO,IAAA,CAAK,uBAAuB,KAAK,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAAA,GAAsE;AAC5E,IAAA,OAAO,IAAA,CAAK,uBAAuB,IAAI,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,sBAAA,CACZ,OAAA,GAAmB,KAAA,EACsB;AACzC,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,EAAQ,KAAK,4BAA4B,CAAA;AAE9C,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,YAAA,EAAc;AAE5C,QAAA,MAAM,aAAa,OAAA,GACf,OAAA,CAAQ,YAAY,CAAA,GACpB,MAAM,OAAO,YAAY,CAAA;AAE7B,QAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,MAAA;AAAA,UAC9B,KAAK,YAAA,CAAa,OAAA;AAAA,UAClB,KAAK,YAAA,CAAa;AAAA,SACpB;AAEA,QAAA,IAAA,CAAK,MAAA,EAAQ,KAAK,wCAAwC,CAAA;AAC1D,QAAA,OAAO,MAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D,SAAS,KAAA,EAAY;AACnB,MAAA,IAAA,CAAK,MAAA,EAAQ,MAAM,oCAAA,EAAsC;AAAA,QACvD,OAAO,KAAA,CAAM;AAAA,OACd,CAAA;AACD,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AACF;;;;"}
1
+ {"version":3,"file":"CacheManager.cjs.js","sources":["../../../src/entrypoints/cache/CacheManager.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 CacheService,\n CacheServiceOptions,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport Keyv from 'keyv';\nimport { DefaultCacheClient } from './CacheClient';\nimport {\n CacheManagerOptions,\n ttlToMilliseconds,\n CacheStoreOptions,\n CacheStoreConnection,\n CacheStoreConnectionObject,\n CacheStoreConfiguration,\n CacheStoreDeps,\n RedisCacheStoreConfiguration,\n RedisCacheStoreOptions,\n InfinispanClientBehaviorOptions,\n InfinispanServerConfig,\n ValkeyCacheStoreOptions,\n} from './types';\nimport { InfinispanOptionsMapper } from './providers/infinispan/InfinispanOptionsMapper';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { ConfigReader, readDurationFromConfig } from '@backstage/config';\nimport {\n InfinispanClientCacheInterface,\n InfinispanKeyvStore,\n} from './providers/infinispan/InfinispanKeyvStore';\nimport type { KeyvRedisOptions, RedisClusterOptions } from '@keyv/redis';\n\ntype StoreFactory = (pluginId: string, defaultTtl: number | undefined) => Keyv;\n\n/**\n * Implements a Cache Manager which will automatically create new cache clients\n * for plugins when requested. All requested cache clients are created with the\n * connection details provided.\n *\n * @public\n */\nexport class CacheManager {\n /**\n * Keys represent supported `backend.cache.store` values, mapped to factories\n * that return Keyv instances appropriate to the store.\n */\n private readonly storeFactories = {\n redis: this.createRedisStoreFactory(),\n valkey: this.createValkeyStoreFactory(),\n memcache: this.createMemcacheStoreFactory(),\n memory: this.createMemoryStoreFactory(),\n infinispan: this.createInfinispanStoreFactory(),\n };\n\n private readonly logger?: LoggerService;\n private readonly store: keyof CacheManager['storeFactories'];\n private readonly connection: CacheStoreConnection;\n private readonly errorHandler: CacheManagerOptions['onError'];\n private readonly defaultTtl?: number;\n private readonly storeOptions?: CacheStoreOptions;\n\n /**\n * Creates a new {@link CacheManager} instance by reading from the `backend`\n * config section, specifically the `.cache` key.\n *\n * @param config - The loaded application configuration.\n * @param options - Optional configuration for the CacheManager.\n * @returns A new CacheManager instance.\n */\n static fromConfig(\n config: RootConfigService,\n options: CacheManagerOptions = {},\n ): CacheManager {\n // If no `backend.cache` config is provided, instantiate the CacheManager\n // with an in-memory cache client.\n const store = config.getOptionalString('backend.cache.store') || 'memory';\n const defaultTtlConfig = config.getOptional('backend.cache.defaultTtl');\n const connection = CacheManager.parseConnection(config);\n const logger = options.logger?.child({\n type: 'cacheManager',\n });\n\n if (config.has('backend.cache.useRedisSets')) {\n logger?.warn(\n \"The 'backend.cache.useRedisSets' configuration key is deprecated and no longer has any effect. The underlying '@keyv/redis' and '@keyv/valkey' libraries no longer support redis sets.\",\n );\n }\n\n let defaultTtl: number | undefined;\n if (defaultTtlConfig !== undefined) {\n if (typeof defaultTtlConfig === 'number') {\n defaultTtl = defaultTtlConfig;\n } else {\n defaultTtl = durationToMilliseconds(\n readDurationFromConfig(config, { key: 'backend.cache.defaultTtl' }),\n );\n }\n }\n\n // Read store-specific options from config\n const storeOptions = CacheManager.parseStoreOptions(\n { store, connection },\n { config, logger },\n );\n\n return new CacheManager(\n store,\n connection,\n options.onError,\n logger,\n defaultTtl,\n storeOptions,\n );\n }\n\n /**\n * Parse the connection config, which can be either a plain URL string\n * or an object with connection options (e.g. `{ url, pingInterval }`)\n * passed through to the underlying store client.\n *\n * @param config - The configuration service\n * @returns The parsed connection config, either a string or an object depending on how it was configured\n */\n private static parseConnection(\n config: RootConfigService,\n ): CacheStoreConnection {\n const raw = config.getOptional('backend.cache.connection');\n const store = config.getOptionalString('backend.cache.store') || 'memory';\n\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n if (store !== 'redis') {\n throw new Error(\n \"backend.cache.connection object form is only supported when backend.cache.store is 'redis'\",\n );\n }\n\n const url = (raw as { url?: unknown }).url;\n if (typeof url !== 'string' || url.length === 0) {\n throw new Error(\n \"backend.cache.connection object must include a non-empty 'url' string\",\n );\n }\n\n return raw as CacheStoreConnectionObject;\n }\n\n if (raw !== undefined && typeof raw !== 'string') {\n throw new Error(\n `backend.cache.connection must be a string or object, got ${typeof raw}`,\n );\n }\n\n return config.getOptionalString('backend.cache.connection') ?? '';\n }\n\n /**\n * Parse store-specific options from configuration.\n *\n * @param store - The cache store type ('redis', 'valkey', 'memcache', 'infinispan', or 'memory')\n * @param config - The configuration service\n * @param logger - Optional logger for warnings\n * @returns The parsed store options\n */\n private static parseStoreOptions(\n config: { store: string; connection: CacheStoreConnection },\n deps: CacheStoreDeps,\n ): CacheStoreOptions | undefined {\n const { store, connection } = config;\n const storeConfigPath = `backend.cache.${store}`;\n\n if (store !== 'memory' && !deps.config.has(storeConfigPath)) {\n deps.logger?.warn(\n `No configuration found for cache store '${store}' at '${storeConfigPath}'.`,\n );\n }\n\n switch (store) {\n case 'redis':\n return CacheManager.parseRedisOptions(\n { storeConfigPath, connection },\n deps,\n );\n case 'valkey':\n return CacheManager.parseValkeyOptions({ storeConfigPath }, deps);\n case 'infinispan':\n return InfinispanOptionsMapper.parseInfinispanOptions(\n { storeConfigPath },\n deps,\n );\n default:\n return undefined;\n }\n }\n\n /**\n * Parse Redis-specific options from configuration.\n */\n private static parseRedisOptions(\n config: RedisCacheStoreConfiguration,\n deps: CacheStoreDeps,\n ): RedisCacheStoreOptions {\n const redisOptions: RedisCacheStoreOptions = {\n type: 'redis',\n };\n\n const redisConfig =\n deps.config.getOptionalConfig(config.storeConfigPath) ??\n new ConfigReader({});\n\n redisOptions.client = {\n namespace: redisConfig.getOptionalString('client.namespace'),\n keyPrefixSeparator:\n redisConfig.getOptionalString('client.keyPrefixSeparator') || ':',\n clearBatchSize: redisConfig.getOptionalNumber('client.clearBatchSize'),\n useUnlink: redisConfig.getOptionalBoolean('client.useUnlink'),\n noNamespaceAffectsAll: redisConfig.getOptionalBoolean(\n 'client.noNamespaceAffectsAll',\n ),\n };\n\n if (redisConfig.has('cluster')) {\n const clusterConfig = redisConfig.getConfig('cluster');\n\n if (!clusterConfig.has('rootNodes')) {\n deps.logger?.warn(\n `Redis cluster config has no 'rootNodes' key, defaulting to non-clustered mode`,\n );\n return redisOptions;\n }\n\n // When connection is an object, merge its properties into cluster\n // defaults so every node inherits those options (e.g. pingInterval).\n let defaults: RedisClusterOptions['defaults'] =\n clusterConfig.getOptional('defaults');\n\n if (typeof config.connection === 'object') {\n const { url: _url, ...connectionDefaults } = config.connection;\n defaults = { ...defaults, ...connectionDefaults };\n }\n\n redisOptions.cluster = {\n rootNodes: clusterConfig.get('rootNodes'),\n defaults,\n minimizeConnections: clusterConfig.getOptionalBoolean(\n 'minimizeConnections',\n ),\n useReplicas: clusterConfig.getOptionalBoolean('useReplicas'),\n maxCommandRedirections: clusterConfig.getOptionalNumber(\n 'maxCommandRedirections',\n ),\n };\n }\n\n return redisOptions;\n }\n\n /**\n * Parse Valkey-specific options from configuration.\n */\n private static parseValkeyOptions(\n config: CacheStoreConfiguration,\n deps: CacheStoreDeps,\n ): ValkeyCacheStoreOptions {\n const valkeyOptions: ValkeyCacheStoreOptions = {\n type: 'valkey',\n };\n\n const valkeyConfig =\n deps.config.getOptionalConfig(config.storeConfigPath) ??\n new ConfigReader({});\n\n valkeyOptions.client = {\n keyPrefix: valkeyConfig.getOptionalString('client.keyPrefix'),\n };\n\n if (valkeyConfig.has('cluster')) {\n const clusterConfig = valkeyConfig.getConfig('cluster');\n\n if (!clusterConfig.has('rootNodes')) {\n deps.logger?.warn(\n `Valkey cluster config has no 'rootNodes' key, defaulting to non-clustered mode`,\n );\n return valkeyOptions;\n }\n\n valkeyOptions.cluster = {\n rootNodes: clusterConfig.get('rootNodes'),\n options: {\n redisOptions: clusterConfig.getOptional('defaults'),\n scaleReads: clusterConfig.getOptionalBoolean('useReplicas')\n ? 'slave'\n : undefined,\n maxRedirections: clusterConfig.getOptionalNumber(\n 'maxCommandRedirections',\n ),\n lazyConnect: clusterConfig.getOptionalBoolean('minimizeConnections'),\n },\n };\n }\n\n return valkeyOptions;\n }\n\n /**\n * Construct the full namespace based on the options and pluginId.\n *\n * @param pluginId - The plugin ID to namespace\n * @param storeOptions - Optional cache store configuration options\n * @returns The constructed namespace string combining the configured namespace with pluginId\n */\n private static constructNamespace(\n pluginId: string,\n storeOptions: RedisCacheStoreOptions | ValkeyCacheStoreOptions | undefined,\n ): string {\n let prefix: string;\n switch (storeOptions?.type) {\n case 'redis':\n prefix = storeOptions?.client?.namespace\n ? `${storeOptions.client.namespace}${\n storeOptions.client.keyPrefixSeparator ?? ':'\n }`\n : '';\n break;\n case 'valkey':\n prefix = storeOptions.client?.keyPrefix ?? '';\n break;\n default:\n prefix = '';\n }\n\n return `${prefix}${pluginId}`;\n }\n\n /** @internal */\n constructor(\n store: string,\n connection: CacheStoreConnection,\n errorHandler: CacheManagerOptions['onError'],\n logger?: LoggerService,\n defaultTtl?: number,\n storeOptions?: CacheStoreOptions,\n ) {\n if (!this.storeFactories.hasOwnProperty(store)) {\n throw new Error(`Unknown cache store: ${store}`);\n }\n this.logger = logger;\n this.store = store as keyof CacheManager['storeFactories'];\n this.connection = connection;\n this.errorHandler = errorHandler;\n this.defaultTtl = defaultTtl;\n this.storeOptions = storeOptions;\n }\n\n /**\n * Generates a PluginCacheManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the cache manager should be created for.\n * Plugin names should be unique.\n */\n forPlugin(pluginId: string): CacheService {\n const clientFactory = (options: CacheServiceOptions) => {\n const ttl = options.defaultTtl ?? this.defaultTtl;\n return this.getClientWithTtl(\n pluginId,\n ttl !== undefined ? ttlToMilliseconds(ttl) : undefined,\n );\n };\n\n return new DefaultCacheClient(clientFactory({}), clientFactory, {});\n }\n\n private getClientWithTtl(pluginId: string, ttl: number | undefined): Keyv {\n return this.storeFactories[this.store](pluginId, ttl);\n }\n\n private createRedisStoreFactory(): StoreFactory {\n const keyvRedis = require('@keyv/redis') as typeof import('@keyv/redis');\n const KeyvRedis = keyvRedis.default;\n const { createCluster } = keyvRedis;\n const stores: Record<string, InstanceType<typeof KeyvRedis>> = {};\n\n return (pluginId, defaultTtl) => {\n if (this.storeOptions?.type !== 'redis') {\n throw new Error(\n `Internal error: Wrong config type passed to redis factory: ${this.storeOptions?.type}`,\n );\n }\n if (!stores[pluginId]) {\n const redisOptions: KeyvRedisOptions = this.storeOptions?.client || {\n keyPrefixSeparator: ':',\n };\n if (this.storeOptions?.cluster) {\n // Create a Redis cluster\n const cluster = createCluster(this.storeOptions.cluster);\n stores[pluginId] = new KeyvRedis(cluster, redisOptions);\n } else {\n // Create a regular Redis connection\n stores[pluginId] = new KeyvRedis(this.connection, redisOptions);\n }\n\n // Always provide an error handler to avoid stopping the process\n stores[pluginId].on('error', (err: Error) => {\n this.logger?.error('Failed to create redis cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: CacheManager.constructNamespace(pluginId, this.storeOptions),\n ttl: defaultTtl,\n store: stores[pluginId],\n emitErrors: false,\n useKeyPrefix: false,\n });\n };\n }\n\n private createValkeyStoreFactory(): StoreFactory {\n const KeyvValkey = require('@keyv/valkey').default;\n const { Cluster } = require('iovalkey');\n const stores: Record<string, typeof KeyvValkey> = {};\n\n return (pluginId, defaultTtl) => {\n if (this.storeOptions?.type !== 'valkey') {\n throw new Error(\n `Internal error: Wrong config type passed to valkey factory: ${this.storeOptions?.type}`,\n );\n }\n if (!stores[pluginId]) {\n const valkeyOptions = this.storeOptions?.client;\n if (this.storeOptions?.cluster) {\n // Create an iovalkey Cluster instance, which is the type that @keyv/valkey expects\n const cluster = new Cluster(\n this.storeOptions.cluster.rootNodes,\n this.storeOptions.cluster.options,\n );\n stores[pluginId] = new KeyvValkey(cluster, valkeyOptions);\n } else {\n // Create a regular Valkey connection\n stores[pluginId] = new KeyvValkey(this.connection, valkeyOptions);\n }\n\n // Always provide an error handler to avoid stopping the process\n stores[pluginId].on('error', (err: Error) => {\n this.logger?.error('Failed to create valkey cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: CacheManager.constructNamespace(pluginId, this.storeOptions),\n ttl: defaultTtl,\n store: stores[pluginId],\n emitErrors: false,\n useKeyPrefix: false,\n });\n };\n }\n\n private createMemcacheStoreFactory(): StoreFactory {\n const KeyvMemcache = require('@keyv/memcache').default;\n const stores: Record<string, typeof KeyvMemcache> = {};\n\n return (pluginId, defaultTtl) => {\n if (!stores[pluginId]) {\n stores[pluginId] = new KeyvMemcache(this.connection);\n // Always provide an error handler to avoid stopping the process\n stores[pluginId].on('error', (err: Error) => {\n this.logger?.error('Failed to create memcache cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store: stores[pluginId],\n });\n };\n }\n\n private createMemoryStoreFactory(): StoreFactory {\n const store = new Map();\n return (pluginId, defaultTtl) =>\n new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store,\n });\n }\n\n private createInfinispanStoreFactory(): StoreFactory {\n const stores: Record<string, InfinispanKeyvStore> = {};\n\n return (pluginId, defaultTtl) => {\n if (this.storeOptions?.type !== 'infinispan') {\n throw new Error(\n `Internal error: Wrong config type passed to infinispan factory: ${this.storeOptions?.type}`,\n );\n }\n\n if (!stores[pluginId]) {\n // Use sync version for testing environments\n const isTest =\n process.env.NODE_ENV === 'test' || typeof jest !== 'undefined';\n\n // Create the client promise ONCE and reuse it\n const clientPromise: Promise<InfinispanClientCacheInterface> = isTest\n ? this.createInfinispanClientSync()\n : this.createInfinispanClientAsync();\n\n this.logger?.info(\n `Creating Infinispan cache client for plugin ${pluginId} isTest = ${isTest}`,\n );\n const storeInstance = new InfinispanKeyvStore({\n clientPromise,\n logger: this.logger!,\n });\n\n stores[pluginId] = storeInstance;\n\n // Always provide an error handler to avoid stopping the process\n storeInstance.on('error', (err: Error) => {\n this.logger?.error('Failed to create infinispan cache client', err);\n this.errorHandler?.(err);\n });\n }\n\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n store: stores[pluginId],\n emitErrors: false,\n });\n };\n }\n\n /**\n * Creates an Infinispan client using dynamic import (production use).\n * @returns Promise that resolves to an Infinispan client\n */\n private async createInfinispanClientAsync(): Promise<InfinispanClientCacheInterface> {\n return this.createInfinispanClient(false);\n }\n\n /**\n * Creates an Infinispan client using synchronous import (testing purposes).\n * @returns Promise that resolves to an Infinispan client\n */\n private createInfinispanClientSync(): Promise<InfinispanClientCacheInterface> {\n return this.createInfinispanClient(true);\n }\n\n /**\n * Creates an Infinispan client based on the provided configuration.\n * @param useSync - Whether to use synchronous import (for testing) or dynamic import\n * @returns Promise that resolves to an Infinispan client\n */\n private async createInfinispanClient(\n useSync: boolean = false,\n ): Promise<InfinispanClientCacheInterface> {\n try {\n this.logger?.info('Creating Infinispan client');\n\n if (this.storeOptions?.type === 'infinispan') {\n // Import infinispan based on the useSync parameter\n const infinispan = useSync\n ? require('infinispan')\n : await import('infinispan');\n\n const client = await infinispan.client(\n this.storeOptions.servers as InfinispanServerConfig[],\n this.storeOptions.options as InfinispanClientBehaviorOptions,\n );\n\n this.logger?.info('Infinispan client created successfully');\n return client;\n }\n throw new Error('Infinispan store options are not defined');\n } catch (error: any) {\n this.logger?.error('Failed to create Infinispan client', {\n error: error.message,\n });\n throw error;\n }\n }\n}\n"],"names":["config","durationToMilliseconds","readDurationFromConfig","InfinispanOptionsMapper","ConfigReader","ttlToMilliseconds","DefaultCacheClient","Keyv","InfinispanKeyvStore"],"mappings":";;;;;;;;;;;;;;AAwDO,MAAM,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKP,cAAA,GAAiB;AAAA,IAChC,KAAA,EAAO,KAAK,uBAAA,EAAwB;AAAA,IACpC,MAAA,EAAQ,KAAK,wBAAA,EAAyB;AAAA,IACtC,QAAA,EAAU,KAAK,0BAAA,EAA2B;AAAA,IAC1C,MAAA,EAAQ,KAAK,wBAAA,EAAyB;AAAA,IACtC,UAAA,EAAY,KAAK,4BAAA;AAA6B,GAChD;AAAA,EAEiB,MAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUjB,OAAO,UAAA,CACLA,QAAA,EACA,OAAA,GAA+B,EAAC,EAClB;AAGd,IAAA,MAAM,KAAA,GAAQA,QAAA,CAAO,iBAAA,CAAkB,qBAAqB,CAAA,IAAK,QAAA;AACjE,IAAA,MAAM,gBAAA,GAAmBA,QAAA,CAAO,WAAA,CAAY,0BAA0B,CAAA;AACtE,IAAA,MAAM,UAAA,GAAa,YAAA,CAAa,eAAA,CAAgBA,QAAM,CAAA;AACtD,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,EAAQ,KAAA,CAAM;AAAA,MACnC,IAAA,EAAM;AAAA,KACP,CAAA;AAED,IAAA,IAAIA,QAAA,CAAO,GAAA,CAAI,4BAA4B,CAAA,EAAG;AAC5C,MAAA,MAAA,EAAQ,IAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,UAAA;AACJ,IAAA,IAAI,qBAAqB,MAAA,EAAW;AAClC,MAAA,IAAI,OAAO,qBAAqB,QAAA,EAAU;AACxC,QAAA,UAAA,GAAa,gBAAA;AAAA,MACf,CAAA,MAAO;AACL,QAAA,UAAA,GAAaC,4BAAA;AAAA,UACXC,6BAAA,CAAuBF,QAAA,EAAQ,EAAE,GAAA,EAAK,4BAA4B;AAAA,SACpE;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,eAAe,YAAA,CAAa,iBAAA;AAAA,MAChC,EAAE,OAAO,UAAA,EAAW;AAAA,MACpB,UAAEA,UAAQ,MAAA;AAAO,KACnB;AAEA,IAAA,OAAO,IAAI,YAAA;AAAA,MACT,KAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA,CAAQ,OAAA;AAAA,MACR,MAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAe,gBACb,MAAA,EACsB;AACtB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,WAAA,CAAY,0BAA0B,CAAA;AACzD,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,iBAAA,CAAkB,qBAAqB,CAAA,IAAK,QAAA;AAEjE,IAAA,IAAI,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACzD,MAAA,IAAI,UAAU,OAAA,EAAS;AACrB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,MAAM,MAAO,GAAA,CAA0B,GAAA;AACvC,MAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,WAAW,CAAA,EAAG;AAC/C,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,OAAO,GAAA;AAAA,IACT;AAEA,IAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,OAAO,GAAA,KAAQ,QAAA,EAAU;AAChD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,yDAAA,EAA4D,OAAO,GAAG,CAAA;AAAA,OACxE;AAAA,IACF;AAEA,IAAA,OAAO,MAAA,CAAO,iBAAA,CAAkB,0BAA0B,CAAA,IAAK,EAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAe,iBAAA,CACb,MAAA,EACA,IAAA,EAC+B;AAC/B,IAAA,MAAM,EAAE,KAAA,EAAO,UAAA,EAAW,GAAI,MAAA;AAC9B,IAAA,MAAM,eAAA,GAAkB,iBAAiB,KAAK,CAAA,CAAA;AAE9C,IAAA,IAAI,UAAU,QAAA,IAAY,CAAC,KAAK,MAAA,CAAO,GAAA,CAAI,eAAe,CAAA,EAAG;AAC3D,MAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,QACX,CAAA,wCAAA,EAA2C,KAAK,CAAA,MAAA,EAAS,eAAe,CAAA,EAAA;AAAA,OAC1E;AAAA,IACF;AAEA,IAAA,QAAQ,KAAA;AAAO,MACb,KAAK,OAAA;AACH,QAAA,OAAO,YAAA,CAAa,iBAAA;AAAA,UAClB,EAAE,iBAAiB,UAAA,EAAW;AAAA,UAC9B;AAAA,SACF;AAAA,MACF,KAAK,QAAA;AACH,QAAA,OAAO,YAAA,CAAa,kBAAA,CAAmB,EAAE,eAAA,IAAmB,IAAI,CAAA;AAAA,MAClE,KAAK,YAAA;AACH,QAAA,OAAOG,+CAAA,CAAwB,sBAAA;AAAA,UAC7B,EAAE,eAAA,EAAgB;AAAA,UAClB;AAAA,SACF;AAAA,MACF;AACE,QAAA,OAAO,MAAA;AAAA;AACX,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,iBAAA,CACbH,QAAA,EACA,IAAA,EACwB;AACxB,IAAA,MAAM,YAAA,GAAuC;AAAA,MAC3C,IAAA,EAAM;AAAA,KACR;AAEA,IAAA,MAAM,WAAA,GACJ,IAAA,CAAK,MAAA,CAAO,iBAAA,CAAkBA,QAAA,CAAO,eAAe,CAAA,IACpD,IAAII,mBAAA,CAAa,EAAE,CAAA;AAErB,IAAA,YAAA,CAAa,MAAA,GAAS;AAAA,MACpB,SAAA,EAAW,WAAA,CAAY,iBAAA,CAAkB,kBAAkB,CAAA;AAAA,MAC3D,kBAAA,EACE,WAAA,CAAY,iBAAA,CAAkB,2BAA2B,CAAA,IAAK,GAAA;AAAA,MAChE,cAAA,EAAgB,WAAA,CAAY,iBAAA,CAAkB,uBAAuB,CAAA;AAAA,MACrE,SAAA,EAAW,WAAA,CAAY,kBAAA,CAAmB,kBAAkB,CAAA;AAAA,MAC5D,uBAAuB,WAAA,CAAY,kBAAA;AAAA,QACjC;AAAA;AACF,KACF;AAEA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA,EAAG;AAC9B,MAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,SAAA,CAAU,SAAS,CAAA;AAErD,MAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA,EAAG;AACnC,QAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,UACX,CAAA,6EAAA;AAAA,SACF;AACA,QAAA,OAAO,YAAA;AAAA,MACT;AAIA,MAAA,IAAI,QAAA,GACF,aAAA,CAAc,WAAA,CAAY,UAAU,CAAA;AAEtC,MAAA,IAAI,OAAOJ,QAAA,CAAO,UAAA,KAAe,QAAA,EAAU;AACzC,QAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAM,GAAG,kBAAA,KAAuBA,QAAA,CAAO,UAAA;AACpD,QAAA,QAAA,GAAW,EAAE,GAAG,QAAA,EAAU,GAAG,kBAAA,EAAmB;AAAA,MAClD;AAEA,MAAA,YAAA,CAAa,OAAA,GAAU;AAAA,QACrB,SAAA,EAAW,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA;AAAA,QACxC,QAAA;AAAA,QACA,qBAAqB,aAAA,CAAc,kBAAA;AAAA,UACjC;AAAA,SACF;AAAA,QACA,WAAA,EAAa,aAAA,CAAc,kBAAA,CAAmB,aAAa,CAAA;AAAA,QAC3D,wBAAwB,aAAA,CAAc,iBAAA;AAAA,UACpC;AAAA;AACF,OACF;AAAA,IACF;AAEA,IAAA,OAAO,YAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,kBAAA,CACbA,QAAA,EACA,IAAA,EACyB;AACzB,IAAA,MAAM,aAAA,GAAyC;AAAA,MAC7C,IAAA,EAAM;AAAA,KACR;AAEA,IAAA,MAAM,YAAA,GACJ,IAAA,CAAK,MAAA,CAAO,iBAAA,CAAkBA,QAAA,CAAO,eAAe,CAAA,IACpD,IAAII,mBAAA,CAAa,EAAE,CAAA;AAErB,IAAA,aAAA,CAAc,MAAA,GAAS;AAAA,MACrB,SAAA,EAAW,YAAA,CAAa,iBAAA,CAAkB,kBAAkB;AAAA,KAC9D;AAEA,IAAA,IAAI,YAAA,CAAa,GAAA,CAAI,SAAS,CAAA,EAAG;AAC/B,MAAA,MAAM,aAAA,GAAgB,YAAA,CAAa,SAAA,CAAU,SAAS,CAAA;AAEtD,MAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA,EAAG;AACnC,QAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,UACX,CAAA,8EAAA;AAAA,SACF;AACA,QAAA,OAAO,aAAA;AAAA,MACT;AAEA,MAAA,aAAA,CAAc,OAAA,GAAU;AAAA,QACtB,SAAA,EAAW,aAAA,CAAc,GAAA,CAAI,WAAW,CAAA;AAAA,QACxC,OAAA,EAAS;AAAA,UACP,YAAA,EAAc,aAAA,CAAc,WAAA,CAAY,UAAU,CAAA;AAAA,UAClD,UAAA,EAAY,aAAA,CAAc,kBAAA,CAAmB,aAAa,IACtD,OAAA,GACA,MAAA;AAAA,UACJ,iBAAiB,aAAA,CAAc,iBAAA;AAAA,YAC7B;AAAA,WACF;AAAA,UACA,WAAA,EAAa,aAAA,CAAc,kBAAA,CAAmB,qBAAqB;AAAA;AACrE,OACF;AAAA,IACF;AAEA,IAAA,OAAO,aAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAe,kBAAA,CACb,QAAA,EACA,YAAA,EACQ;AACR,IAAA,IAAI,MAAA;AACJ,IAAA,QAAQ,cAAc,IAAA;AAAM,MAC1B,KAAK,OAAA;AACH,QAAA,MAAA,GAAS,YAAA,EAAc,MAAA,EAAQ,SAAA,GAC3B,CAAA,EAAG,YAAA,CAAa,MAAA,CAAO,SAAS,CAAA,EAC9B,YAAA,CAAa,MAAA,CAAO,kBAAA,IAAsB,GAC5C,CAAA,CAAA,GACA,EAAA;AACJ,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,MAAA,GAAS,YAAA,CAAa,QAAQ,SAAA,IAAa,EAAA;AAC3C,QAAA;AAAA,MACF;AACE,QAAA,MAAA,GAAS,EAAA;AAAA;AAGb,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,QAAQ,CAAA,CAAA;AAAA,EAC7B;AAAA;AAAA,EAGA,YACE,KAAA,EACA,UAAA,EACA,YAAA,EACA,MAAA,EACA,YACA,YAAA,EACA;AACA,IAAA,IAAI,CAAC,IAAA,CAAK,cAAA,CAAe,cAAA,CAAe,KAAK,CAAA,EAAG;AAC9C,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,KAAK,CAAA,CAAE,CAAA;AAAA,IACjD;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,QAAA,EAAgC;AACxC,IAAA,MAAM,aAAA,GAAgB,CAAC,OAAA,KAAiC;AACtD,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,UAAA,IAAc,IAAA,CAAK,UAAA;AACvC,MAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,QACV,QAAA;AAAA,QACA,GAAA,KAAQ,MAAA,GAAYC,yBAAA,CAAkB,GAAG,CAAA,GAAI;AAAA,OAC/C;AAAA,IACF,CAAA;AAEA,IAAA,OAAO,IAAIC,+BAAmB,aAAA,CAAc,EAAE,CAAA,EAAG,aAAA,EAAe,EAAE,CAAA;AAAA,EACpE;AAAA,EAEQ,gBAAA,CAAiB,UAAkB,GAAA,EAA+B;AACxE,IAAA,OAAO,KAAK,cAAA,CAAe,IAAA,CAAK,KAAK,CAAA,CAAE,UAAU,GAAG,CAAA;AAAA,EACtD;AAAA,EAEQ,uBAAA,GAAwC;AAC9C,IAAA,MAAM,SAAA,GAAY,QAAQ,aAAa,CAAA;AACvC,IAAA,MAAM,YAAY,SAAA,CAAU,OAAA;AAC5B,IAAA,MAAM,EAAE,eAAc,GAAI,SAAA;AAC1B,IAAA,MAAM,SAAyD,EAAC;AAEhE,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,OAAA,EAAS;AACvC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,2DAAA,EAA8D,IAAA,CAAK,YAAA,EAAc,IAAI,CAAA;AAAA,SACvF;AAAA,MACF;AACA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AACrB,QAAA,MAAM,YAAA,GAAiC,IAAA,CAAK,YAAA,EAAc,MAAA,IAAU;AAAA,UAClE,kBAAA,EAAoB;AAAA,SACtB;AACA,QAAA,IAAI,IAAA,CAAK,cAAc,OAAA,EAAS;AAE9B,UAAA,MAAM,OAAA,GAAU,aAAA,CAAc,IAAA,CAAK,YAAA,CAAa,OAAO,CAAA;AACvD,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,SAAA,CAAU,SAAS,YAAY,CAAA;AAAA,QACxD,CAAA,MAAO;AAEL,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,SAAA,CAAU,IAAA,CAAK,YAAY,YAAY,CAAA;AAAA,QAChE;AAGA,QAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AAC3C,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,qCAAA,EAAuC,GAAG,CAAA;AAC7D,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAIC,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,YAAA,CAAa,kBAAA,CAAmB,QAAA,EAAU,KAAK,YAAY,CAAA;AAAA,QACtE,GAAA,EAAK,UAAA;AAAA,QACL,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,QACtB,UAAA,EAAY,KAAA;AAAA,QACZ,YAAA,EAAc;AAAA,OACf,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA,EAEQ,wBAAA,GAAyC;AAC/C,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,cAAc,CAAA,CAAE,OAAA;AAC3C,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,OAAA,CAAQ,UAAU,CAAA;AACtC,IAAA,MAAM,SAA4C,EAAC;AAEnD,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,QAAA,EAAU;AACxC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,4DAAA,EAA+D,IAAA,CAAK,YAAA,EAAc,IAAI,CAAA;AAAA,SACxF;AAAA,MACF;AACA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AACrB,QAAA,MAAM,aAAA,GAAgB,KAAK,YAAA,EAAc,MAAA;AACzC,QAAA,IAAI,IAAA,CAAK,cAAc,OAAA,EAAS;AAE9B,UAAA,MAAM,UAAU,IAAI,OAAA;AAAA,YAClB,IAAA,CAAK,aAAa,OAAA,CAAQ,SAAA;AAAA,YAC1B,IAAA,CAAK,aAAa,OAAA,CAAQ;AAAA,WAC5B;AACA,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,UAAA,CAAW,SAAS,aAAa,CAAA;AAAA,QAC1D,CAAA,MAAO;AAEL,UAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,UAAA,CAAW,IAAA,CAAK,YAAY,aAAa,CAAA;AAAA,QAClE;AAGA,QAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AAC3C,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,sCAAA,EAAwC,GAAG,CAAA;AAC9D,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAIA,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,YAAA,CAAa,kBAAA,CAAmB,QAAA,EAAU,KAAK,YAAY,CAAA;AAAA,QACtE,GAAA,EAAK,UAAA;AAAA,QACL,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,QACtB,UAAA,EAAY,KAAA;AAAA,QACZ,YAAA,EAAc;AAAA,OACf,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA,EAEQ,0BAAA,GAA2C;AACjD,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,gBAAgB,CAAA,CAAE,OAAA;AAC/C,IAAA,MAAM,SAA8C,EAAC;AAErD,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AACrB,QAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,IAAI,YAAA,CAAa,KAAK,UAAU,CAAA;AAEnD,QAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AAC3C,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,wCAAA,EAA0C,GAAG,CAAA;AAChE,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAIA,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,QAAA;AAAA,QACX,GAAA,EAAK,UAAA;AAAA,QACL,UAAA,EAAY,KAAA;AAAA,QACZ,KAAA,EAAO,OAAO,QAAQ;AAAA,OACvB,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA,EAEQ,wBAAA,GAAyC;AAC/C,IAAA,MAAM,KAAA,uBAAY,GAAA,EAAI;AACtB,IAAA,OAAO,CAAC,QAAA,EAAU,UAAA,KAChB,IAAIA,qBAAA,CAAK;AAAA,MACP,SAAA,EAAW,QAAA;AAAA,MACX,GAAA,EAAK,UAAA;AAAA,MACL,UAAA,EAAY,KAAA;AAAA,MACZ;AAAA,KACD,CAAA;AAAA,EACL;AAAA,EAEQ,4BAAA,GAA6C;AACnD,IAAA,MAAM,SAA8C,EAAC;AAErD,IAAA,OAAO,CAAC,UAAU,UAAA,KAAe;AAC/B,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,YAAA,EAAc;AAC5C,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,gEAAA,EAAmE,IAAA,CAAK,YAAA,EAAc,IAAI,CAAA;AAAA,SAC5F;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAQ,CAAA,EAAG;AAErB,QAAA,MAAM,SACJ,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,MAAA,IAAU,OAAO,IAAA,KAAS,WAAA;AAGrD,QAAA,MAAM,gBAAyD,MAAA,GAC3D,IAAA,CAAK,0BAAA,EAA2B,GAChC,KAAK,2BAAA,EAA4B;AAErC,QAAA,IAAA,CAAK,MAAA,EAAQ,IAAA;AAAA,UACX,CAAA,4CAAA,EAA+C,QAAQ,CAAA,UAAA,EAAa,MAAM,CAAA;AAAA,SAC5E;AACA,QAAA,MAAM,aAAA,GAAgB,IAAIC,uCAAA,CAAoB;AAAA,UAC5C,aAAA;AAAA,UACA,QAAQ,IAAA,CAAK;AAAA,SACd,CAAA;AAED,QAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,aAAA;AAGnB,QAAA,aAAA,CAAc,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AACxC,UAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,0CAAA,EAA4C,GAAG,CAAA;AAClE,UAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,QACzB,CAAC,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,IAAID,qBAAA,CAAK;AAAA,QACd,SAAA,EAAW,QAAA;AAAA,QACX,GAAA,EAAK,UAAA;AAAA,QACL,KAAA,EAAO,OAAO,QAAQ,CAAA;AAAA,QACtB,UAAA,EAAY;AAAA,OACb,CAAA;AAAA,IACH,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,2BAAA,GAAuE;AACnF,IAAA,OAAO,IAAA,CAAK,uBAAuB,KAAK,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,0BAAA,GAAsE;AAC5E,IAAA,OAAO,IAAA,CAAK,uBAAuB,IAAI,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,sBAAA,CACZ,OAAA,GAAmB,KAAA,EACsB;AACzC,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,EAAQ,KAAK,4BAA4B,CAAA;AAE9C,MAAA,IAAI,IAAA,CAAK,YAAA,EAAc,IAAA,KAAS,YAAA,EAAc;AAE5C,QAAA,MAAM,aAAa,OAAA,GACf,OAAA,CAAQ,YAAY,CAAA,GACpB,MAAM,OAAO,YAAY,CAAA;AAE7B,QAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,MAAA;AAAA,UAC9B,KAAK,YAAA,CAAa,OAAA;AAAA,UAClB,KAAK,YAAA,CAAa;AAAA,SACpB;AAEA,QAAA,IAAA,CAAK,MAAA,EAAQ,KAAK,wCAAwC,CAAA;AAC1D,QAAA,OAAO,MAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D,SAAS,KAAA,EAAY;AACnB,MAAA,IAAA,CAAK,MAAA,EAAQ,MAAM,oCAAA,EAAsC;AAAA,QACvD,OAAO,KAAA,CAAM;AAAA,OACd,CAAA;AACD,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"cacheServiceFactory.cjs.js","sources":["../../../src/entrypoints/cache/cacheServiceFactory.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 { CacheManager } from './CacheManager';\n\n/**\n * Key-value store for caching data.\n *\n * See {@link @backstage/code-plugin-api#CacheService}\n * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs}\n * for more information.\n *\n * @public\n */\nexport const cacheServiceFactory = createServiceFactory({\n service: coreServices.cache,\n deps: {\n config: coreServices.rootConfig,\n plugin: coreServices.pluginMetadata,\n logger: coreServices.rootLogger,\n },\n async createRootContext({ config, logger }) {\n return CacheManager.fromConfig(config, { logger });\n },\n async factory({ plugin }, manager) {\n return manager.forPlugin(plugin.getId());\n },\n});\n"],"names":["createServiceFactory","coreServices","CacheManager"],"mappings":";;;;;AA+BO,MAAM,sBAAsBA,qCAAA,CAAqB;AAAA,EACtD,SAASC,6BAAA,CAAa,KAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa,cAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa;AAAA,GACvB;AAAA,EACA,MAAM,iBAAA,CAAkB,EAAE,MAAA,EAAQ,QAAO,EAAG;AAC1C,IAAA,OAAOC,yBAAA,CAAa,UAAA,CAAW,MAAA,EAAQ,EAAE,QAAQ,CAAA;AAAA,EACnD,CAAA;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,IAAU,OAAA,EAAS;AACjC,IAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,CAAA;AAAA,EACzC;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"cacheServiceFactory.cjs.js","sources":["../../../src/entrypoints/cache/cacheServiceFactory.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 { CacheManager } from './CacheManager';\n\n/**\n * Key-value store for caching data.\n *\n * See {@link @backstage/code-plugin-api#CacheService}\n * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs}\n * for more information.\n *\n * @public\n */\nexport const cacheServiceFactory = createServiceFactory({\n service: coreServices.cache,\n deps: {\n config: coreServices.rootConfig,\n plugin: coreServices.pluginMetadata,\n logger: coreServices.rootLogger,\n },\n async createRootContext({ config, logger }) {\n return CacheManager.fromConfig(config, { logger });\n },\n async factory({ plugin }, manager) {\n return manager.forPlugin(plugin.getId());\n },\n});\n"],"names":["createServiceFactory","coreServices","CacheManager"],"mappings":";;;;;AA+BO,MAAM,sBAAsBA,qCAAA,CAAqB;AAAA,EACtD,SAASC,6BAAA,CAAa,KAAA;AAAA,EACtB,IAAA,EAAM;AAAA,IACJ,QAAQA,6BAAA,CAAa,UAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa,cAAA;AAAA,IACrB,QAAQA,6BAAA,CAAa;AAAA,GACvB;AAAA,EACA,MAAM,iBAAA,CAAkB,EAAE,MAAA,EAAQ,QAAO,EAAG;AAC1C,IAAA,OAAOC,yBAAA,CAAa,UAAA,CAAW,MAAA,EAAQ,EAAE,QAAQ,CAAA;AAAA,EACnD,CAAA;AAAA,EACA,MAAM,OAAA,CAAQ,EAAE,MAAA,IAAU,OAAA,EAAS;AACjC,IAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,MAAA,CAAO,KAAA,EAAO,CAAA;AAAA,EACzC;AACF,CAAC;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"InfinispanKeyvStore.cjs.js","sources":["../../../../../src/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.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 { EventEmitter } from 'node:events';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { InfinispanPutOptions } from '../../types';\n\n/**\n * Interface defining the required methods for an Infinispan client.\n * @public\n */\nexport interface InfinispanClientCacheInterface {\n get(key: string): Promise<string | null | undefined>;\n put(key: string, value: string, options?: InfinispanPutOptions): Promise<any>;\n remove(key: string): Promise<boolean>;\n clear(): Promise<void>;\n disconnect(): Promise<void>;\n on?(event: 'error' | string, listener: (...args: any[]) => void): this;\n connect?(): Promise<any>;\n query?(query: string): Promise<any[] | null>;\n containsKey?(key: string): Promise<boolean>;\n}\n\n/**\n * Options for creating an InfinispanKeyvStore instance.\n */\nexport interface InfinispanKeyvStoreOptions {\n clientPromise: Promise<InfinispanClientCacheInterface>;\n logger: LoggerService;\n defaultTtl?: number; // TTL in milliseconds\n}\n\n/**\n * A Keyv store implementation that uses Infinispan as the backend.\n * This store implements the Keyv store interface and provides caching functionality\n * using Infinispan's distributed cache capabilities.\n */\nexport class InfinispanKeyvStore extends EventEmitter {\n private readonly clientPromise: Promise<InfinispanClientCacheInterface>;\n private readonly logger: LoggerService;\n private readonly defaultTtl?: number;\n private resolvedClient: InfinispanClientCacheInterface | null = null;\n\n public readonly namespace?: string; // Keyv expects this\n\n constructor(options: InfinispanKeyvStoreOptions) {\n super();\n this.clientPromise = options.clientPromise;\n this.logger = options.logger.child({ class: InfinispanKeyvStore.name });\n this.defaultTtl = options.defaultTtl;\n\n // Eagerly try to resolve the client to attach error listeners early\n // and to have it ready for disconnect if resolved.\n this.clientPromise\n .then(client => {\n this.resolvedClient = client;\n if (typeof client.on === 'function') {\n client.on('error', (error: Error) => {\n this.logger.error('Native Infinispan client reported an error.', {\n error: error.message,\n });\n this.emit('error', error);\n });\n } else {\n this.logger.warn(\n 'Native Infinispan client does not appear to support .on(\"error\") event listening.',\n );\n }\n })\n .catch(err => {\n this.logger.error(\n 'Failed to resolve Infinispan client promise in constructor.',\n { error: err.message },\n );\n // Errors from operations will also be emitted when clientPromise is awaited and rejects.\n this.emit('error', err);\n });\n }\n\n private async getClient(): Promise<InfinispanClientCacheInterface> {\n if (this.resolvedClient) {\n return this.resolvedClient;\n }\n // If not yet resolved (e.g. called very quickly or promise rejected and retrying implicitly)\n // Await the promise. This will throw if the promise is rejected.\n this.resolvedClient = await this.clientPromise;\n return this.resolvedClient;\n }\n\n async get(key: string): Promise<string | undefined> {\n this.logger.debug(`Getting key: ${key}`);\n try {\n const client = await this.getClient();\n const value = await client.get(key);\n if (value === null || value === undefined) {\n this.logger.debug(`Key not found or value is null/undefined: ${key}`);\n return undefined;\n }\n this.logger.debug(`Successfully retrieved key: ${key}`);\n return value;\n } catch (error: any) {\n this.logger.error(`Error getting key '${key}' from Infinispan.`, {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n async set(key: string, value: string, ttl?: number): Promise<void> {\n this.logger.debug(`Setting key: ${key}`, { ttl });\n this.logger.debug(`Setting key: ${key}`, { ttlInput: ttl });\n const currentTtl = ttl ?? this.defaultTtl;\n this.logger.debug(`Calculated currentTtl for key ${key}: ${currentTtl}ms`); // Log do TTL calculado\n const storeOptions: InfinispanPutOptions = {};\n\n if (typeof currentTtl === 'number' && currentTtl > 0) {\n storeOptions.lifespan = `${currentTtl}ms`; // Ensure time unit is passed as string\n // Ensure this matches client expectations. If client expects string '10s', convert here.\n // For now, assuming number in ms is fine or string like '10000ms'.\n // The PutOptions defines lifespan as string | number | null.\n } else if (typeof currentTtl === 'string') {\n storeOptions.lifespan = currentTtl;\n }\n\n try {\n const client = await this.getClient();\n await client.put(key, value, storeOptions);\n this.logger.debug(`Successfully set key: ${key}`);\n } catch (error: any) {\n this.logger.error(`Error setting key '${key}' in Infinispan.`, {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n async delete(key: string): Promise<boolean> {\n this.logger.debug(`Deleting key: ${key}`);\n try {\n const client = await this.getClient();\n const deleted = await client.remove(key);\n this.logger.debug(`Key deletion status for '${key}': ${deleted}`);\n return deleted;\n } catch (error: any) {\n this.logger.error(`Error deleting key '${key}' from Infinispan.`, {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n async clear(): Promise<void> {\n this.logger.info('Clearing all entries from Infinispan cache.');\n try {\n const client = await this.getClient();\n await client.clear();\n this.logger.info('Infinispan cache cleared successfully.');\n } catch (error: any) {\n this.logger.error('Error clearing Infinispan cache.', {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n // This disconnect is for the Keyv store instance, but the actual client is shared.\n // The CacheManager should handle the shared client's disconnection.\n // However, if Keyv calls this, we shouldn't error.\n async disconnect(): Promise<void> {\n this.logger.info(\n 'InfinispanKeyvStore disconnect called. Shared client managed by CacheManager.',\n );\n // No-op for this store instance as the actual client is managed externally by CacheManager.\n // The CacheManager's stop() method will disconnect the shared native client.\n return Promise.resolve();\n }\n}\n"],"names":["EventEmitter"],"mappings":"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"}
1
+ {"version":3,"file":"InfinispanKeyvStore.cjs.js","sources":["../../../../../src/entrypoints/cache/providers/infinispan/InfinispanKeyvStore.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 { EventEmitter } from 'node:events';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { InfinispanPutOptions } from '../../types';\n\n/**\n * Interface defining the required methods for an Infinispan client.\n * @public\n */\nexport interface InfinispanClientCacheInterface {\n get(key: string): Promise<string | null | undefined>;\n put(key: string, value: string, options?: InfinispanPutOptions): Promise<any>;\n remove(key: string): Promise<boolean>;\n clear(): Promise<void>;\n disconnect(): Promise<void>;\n on?(event: 'error' | string, listener: (...args: any[]) => void): this;\n connect?(): Promise<any>;\n query?(query: string): Promise<any[] | null>;\n containsKey?(key: string): Promise<boolean>;\n}\n\n/**\n * Options for creating an InfinispanKeyvStore instance.\n */\nexport interface InfinispanKeyvStoreOptions {\n clientPromise: Promise<InfinispanClientCacheInterface>;\n logger: LoggerService;\n defaultTtl?: number; // TTL in milliseconds\n}\n\n/**\n * A Keyv store implementation that uses Infinispan as the backend.\n * This store implements the Keyv store interface and provides caching functionality\n * using Infinispan's distributed cache capabilities.\n */\nexport class InfinispanKeyvStore extends EventEmitter {\n private readonly clientPromise: Promise<InfinispanClientCacheInterface>;\n private readonly logger: LoggerService;\n private readonly defaultTtl?: number;\n private resolvedClient: InfinispanClientCacheInterface | null = null;\n\n public readonly namespace?: string; // Keyv expects this\n\n constructor(options: InfinispanKeyvStoreOptions) {\n super();\n this.clientPromise = options.clientPromise;\n this.logger = options.logger.child({ class: InfinispanKeyvStore.name });\n this.defaultTtl = options.defaultTtl;\n\n // Eagerly try to resolve the client to attach error listeners early\n // and to have it ready for disconnect if resolved.\n this.clientPromise\n .then(client => {\n this.resolvedClient = client;\n if (typeof client.on === 'function') {\n client.on('error', (error: Error) => {\n this.logger.error('Native Infinispan client reported an error.', {\n error: error.message,\n });\n this.emit('error', error);\n });\n } else {\n this.logger.warn(\n 'Native Infinispan client does not appear to support .on(\"error\") event listening.',\n );\n }\n })\n .catch(err => {\n this.logger.error(\n 'Failed to resolve Infinispan client promise in constructor.',\n { error: err.message },\n );\n // Errors from operations will also be emitted when clientPromise is awaited and rejects.\n this.emit('error', err);\n });\n }\n\n private async getClient(): Promise<InfinispanClientCacheInterface> {\n if (this.resolvedClient) {\n return this.resolvedClient;\n }\n // If not yet resolved (e.g. called very quickly or promise rejected and retrying implicitly)\n // Await the promise. This will throw if the promise is rejected.\n this.resolvedClient = await this.clientPromise;\n return this.resolvedClient;\n }\n\n async get(key: string): Promise<string | undefined> {\n this.logger.debug(`Getting key: ${key}`);\n try {\n const client = await this.getClient();\n const value = await client.get(key);\n if (value === null || value === undefined) {\n this.logger.debug(`Key not found or value is null/undefined: ${key}`);\n return undefined;\n }\n this.logger.debug(`Successfully retrieved key: ${key}`);\n return value;\n } catch (error: any) {\n this.logger.error(`Error getting key '${key}' from Infinispan.`, {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n async set(key: string, value: string, ttl?: number): Promise<void> {\n this.logger.debug(`Setting key: ${key}`, { ttl });\n this.logger.debug(`Setting key: ${key}`, { ttlInput: ttl });\n const currentTtl = ttl ?? this.defaultTtl;\n this.logger.debug(`Calculated currentTtl for key ${key}: ${currentTtl}ms`); // Log do TTL calculado\n const storeOptions: InfinispanPutOptions = {};\n\n if (typeof currentTtl === 'number' && currentTtl > 0) {\n storeOptions.lifespan = `${currentTtl}ms`; // Ensure time unit is passed as string\n // Ensure this matches client expectations. If client expects string '10s', convert here.\n // For now, assuming number in ms is fine or string like '10000ms'.\n // The PutOptions defines lifespan as string | number | null.\n } else if (typeof currentTtl === 'string') {\n storeOptions.lifespan = currentTtl;\n }\n\n try {\n const client = await this.getClient();\n await client.put(key, value, storeOptions);\n this.logger.debug(`Successfully set key: ${key}`);\n } catch (error: any) {\n this.logger.error(`Error setting key '${key}' in Infinispan.`, {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n async delete(key: string): Promise<boolean> {\n this.logger.debug(`Deleting key: ${key}`);\n try {\n const client = await this.getClient();\n const deleted = await client.remove(key);\n this.logger.debug(`Key deletion status for '${key}': ${deleted}`);\n return deleted;\n } catch (error: any) {\n this.logger.error(`Error deleting key '${key}' from Infinispan.`, {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n async clear(): Promise<void> {\n this.logger.info('Clearing all entries from Infinispan cache.');\n try {\n const client = await this.getClient();\n await client.clear();\n this.logger.info('Infinispan cache cleared successfully.');\n } catch (error: any) {\n this.logger.error('Error clearing Infinispan cache.', {\n error: error.message,\n });\n this.emit(\n 'error',\n error instanceof Error ? error : new Error(String(error)),\n );\n throw error;\n }\n }\n\n // This disconnect is for the Keyv store instance, but the actual client is shared.\n // The CacheManager should handle the shared client's disconnection.\n // However, if Keyv calls this, we shouldn't error.\n async disconnect(): Promise<void> {\n this.logger.info(\n 'InfinispanKeyvStore disconnect called. Shared client managed by CacheManager.',\n );\n // No-op for this store instance as the actual client is managed externally by CacheManager.\n // The CacheManager's stop() method will disconnect the shared native client.\n return Promise.resolve();\n }\n}\n"],"names":["EventEmitter"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"InfinispanOptionsMapper.cjs.js","sources":["../../../../../src/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.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 {\n CacheStoreConfiguration,\n CacheStoreDeps,\n DataFormatOptions,\n InfinispanAuthOptions,\n InfinispanCacheStoreOptions,\n InfinispanClientAuthOptions,\n InfinispanClientBehaviorOptions,\n InfinispanClusterConfig,\n InfinispanServerConfig,\n InfinispanSslOptions,\n} from '../../types';\n\nexport class InfinispanOptionsMapper {\n /**\n * Parses Infinispan options from the provided configuration path.\n *\n * @param config - The store configuration.\n * @param deps - Service dependencies.\n * @returns Parsed Infinispan cache store options.\n */\n public static parseInfinispanOptions(\n config: CacheStoreConfiguration,\n deps: CacheStoreDeps,\n ): InfinispanCacheStoreOptions {\n const infinispanConfig = deps.config.getConfig(config.storeConfigPath);\n const parsedOptions: Partial<InfinispanCacheStoreOptions> = {\n type: 'infinispan',\n };\n\n // Parse Servers & Clusters Configurations\n if (infinispanConfig.has('servers')) {\n const serversConfig = infinispanConfig.get('servers');\n if (Array.isArray(serversConfig)) {\n parsedOptions.servers = infinispanConfig.getConfigArray('servers').map(\n serverConf =>\n ({\n host: serverConf.getString('host'),\n port: serverConf.getOptionalNumber('port') ?? 11222,\n } as InfinispanServerConfig),\n );\n } else if (typeof serversConfig === 'object' && serversConfig !== null) {\n const serverConf = infinispanConfig.getConfig('servers');\n parsedOptions.servers = {\n host: serverConf.getOptionalString('host') ?? '127.0.0.1',\n port: serverConf.getOptionalString('port') ?? 11222,\n } as InfinispanServerConfig;\n } else {\n throw new Error(\n `Infinispan 'servers' configuration at ${config.storeConfigPath} is invalid, must be an object or an array.`,\n );\n }\n } else {\n deps.logger?.warn(\n `Infinispan configuration at ${config.storeConfigPath} is missing the 'servers' definition, will use client defaults.`,\n );\n }\n\n // The parsed options block to send to the Infinispan client\n // This will be used to configure the Infinispan client behavior.\n const behaviorOptions: Partial<InfinispanClientBehaviorOptions> = {};\n\n behaviorOptions.clusters = infinispanConfig\n .getOptionalConfigArray('clusters')\n ?.map(clusterConf => {\n const name = clusterConf.getOptionalString('name');\n return {\n ...(name && { name }),\n servers: clusterConf.getConfigArray('servers').map(serverConf => ({\n host: serverConf.getString('host'),\n port: serverConf.getOptionalNumber('port') ?? 11222,\n })),\n } as InfinispanClusterConfig;\n });\n\n // Parse Default Options Start...\n const clientVersion =\n infinispanConfig.getOptionalString('version') ?? '2.9';\n if (\n clientVersion === '2.9' ||\n clientVersion === '2.5' ||\n clientVersion === '2.2'\n ) {\n behaviorOptions.version = clientVersion;\n } else if (clientVersion !== null && clientVersion !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan client version \"${clientVersion}\" in config at ${config.storeConfigPath}.version. Must be \"2.9\", \"2.5\", or \"2.2\". It will be ignored, and the client may use a default or fail.`,\n );\n }\n\n behaviorOptions.cacheName =\n infinispanConfig.getOptionalString('cacheName') ?? 'cache';\n\n const mediaType = infinispanConfig.getOptionalString('mediaType');\n if (mediaType === 'text/plain' || mediaType === 'application/json') {\n behaviorOptions.mediaType = mediaType;\n } else if (mediaType !== null && mediaType !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan mediaType \"${mediaType}\" in config at ${config.storeConfigPath}.mediaType. Must be \"text/plain\" | \"application/json\". It will be ignored, and the client may use a default or fail.`,\n );\n }\n\n behaviorOptions.maxRetries =\n infinispanConfig.getOptionalNumber('maxRetries');\n\n behaviorOptions.topologyUpdates =\n infinispanConfig.getOptionalBoolean('topologyUpdates') ?? true;\n\n // Default Options End...\n\n // Parse Authentication and SSL Options\n const authConfig = infinispanConfig.getOptionalConfig('authentication');\n const auth: Partial<InfinispanAuthOptions> = {};\n\n auth.enabled = authConfig?.getOptionalBoolean('enabled');\n auth.saslMechanism = authConfig?.getOptionalString('saslMechanism');\n auth.userName = authConfig?.getOptionalString('userName');\n auth.password = authConfig?.getOptionalString('password');\n auth.token = authConfig?.getOptionalString('token');\n auth.authzid = authConfig?.getOptionalString('authzid');\n\n behaviorOptions.authentication = auth as InfinispanAuthOptions;\n\n const sslConfig = infinispanConfig.getOptionalConfig('ssl');\n const ssl: Partial<InfinispanSslOptions> = {};\n\n ssl.enabled = sslConfig?.getOptionalBoolean('enabled');\n ssl.secureProtocol = sslConfig?.getOptionalString('secureProtocol');\n ssl.trustCerts = sslConfig?.getOptionalStringArray('trustCerts');\n ssl.sniHostName = sslConfig?.getOptionalString('sniHostname');\n\n const clientAuth = infinispanConfig.getOptionalConfig('clientAuth');\n const clientAuthOpts: Partial<InfinispanClientAuthOptions> = {};\n\n clientAuthOpts.key = clientAuth?.getOptionalString('key');\n clientAuthOpts.passphrase = clientAuth?.getOptionalString('passphrase');\n clientAuthOpts.cert = clientAuth?.getOptionalString('cert');\n\n ssl.clientAuth = clientAuthOpts as InfinispanClientAuthOptions;\n\n const cryptoStore = infinispanConfig.getOptionalConfig('cryptoStore');\n const cryptoStoreOpts: Partial<InfinispanClientAuthOptions> = {};\n\n cryptoStoreOpts.key = cryptoStore?.getOptionalString('path');\n cryptoStoreOpts.passphrase = cryptoStore?.getOptionalString('passphrase');\n\n ssl.cryptoStore = cryptoStoreOpts as InfinispanClientAuthOptions;\n\n behaviorOptions.ssl = ssl as InfinispanSslOptions;\n\n const dataFormat = infinispanConfig.getOptionalConfig('dataFormat');\n const dataFormatOpts: Partial<DataFormatOptions> = {};\n\n const keyType = dataFormat?.getOptionalString('keyType') ?? 'text/plain';\n const valueType =\n dataFormat?.getOptionalString('valueType') ?? 'text/plain';\n\n if (keyType === 'text/plain' || keyType === 'application/json') {\n dataFormatOpts.keyType = keyType;\n } else if (keyType !== null && keyType !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan dataFormat.keyType \"${keyType}\" in config at ${config.storeConfigPath}.dataFormat.keyType. Must be \"text/plain\" | \"application/json\". Not mapped, client will use default 'text/plain'.`,\n );\n }\n\n if (valueType === 'text/plain' || valueType === 'application/json') {\n dataFormatOpts.valueType = valueType;\n } else if (valueType !== null && valueType !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan dataFormat.valueType \"${valueType}\" in config at ${config.storeConfigPath}.dataFormat.valueType. Must be \"text/plain\" | \"application/json\". Not mapped, client will use default 'text/plain'.`,\n );\n }\n behaviorOptions.dataFormat = dataFormatOpts as DataFormatOptions;\n parsedOptions.options = behaviorOptions as InfinispanClientBehaviorOptions;\n\n deps.logger?.debug(\n `Parsed Infinispan options from config at ${\n config.storeConfigPath\n }: ${JSON.stringify(parsedOptions)}`,\n );\n return parsedOptions as InfinispanCacheStoreOptions;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"InfinispanOptionsMapper.cjs.js","sources":["../../../../../src/entrypoints/cache/providers/infinispan/InfinispanOptionsMapper.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 {\n CacheStoreConfiguration,\n CacheStoreDeps,\n DataFormatOptions,\n InfinispanAuthOptions,\n InfinispanCacheStoreOptions,\n InfinispanClientAuthOptions,\n InfinispanClientBehaviorOptions,\n InfinispanClusterConfig,\n InfinispanServerConfig,\n InfinispanSslOptions,\n} from '../../types';\n\nexport class InfinispanOptionsMapper {\n /**\n * Parses Infinispan options from the provided configuration path.\n *\n * @param config - The store configuration.\n * @param deps - Service dependencies.\n * @returns Parsed Infinispan cache store options.\n */\n public static parseInfinispanOptions(\n config: CacheStoreConfiguration,\n deps: CacheStoreDeps,\n ): InfinispanCacheStoreOptions {\n const infinispanConfig = deps.config.getConfig(config.storeConfigPath);\n const parsedOptions: Partial<InfinispanCacheStoreOptions> = {\n type: 'infinispan',\n };\n\n // Parse Servers & Clusters Configurations\n if (infinispanConfig.has('servers')) {\n const serversConfig = infinispanConfig.get('servers');\n if (Array.isArray(serversConfig)) {\n parsedOptions.servers = infinispanConfig.getConfigArray('servers').map(\n serverConf =>\n ({\n host: serverConf.getString('host'),\n port: serverConf.getOptionalNumber('port') ?? 11222,\n } as InfinispanServerConfig),\n );\n } else if (typeof serversConfig === 'object' && serversConfig !== null) {\n const serverConf = infinispanConfig.getConfig('servers');\n parsedOptions.servers = {\n host: serverConf.getOptionalString('host') ?? '127.0.0.1',\n port: serverConf.getOptionalString('port') ?? 11222,\n } as InfinispanServerConfig;\n } else {\n throw new Error(\n `Infinispan 'servers' configuration at ${config.storeConfigPath} is invalid, must be an object or an array.`,\n );\n }\n } else {\n deps.logger?.warn(\n `Infinispan configuration at ${config.storeConfigPath} is missing the 'servers' definition, will use client defaults.`,\n );\n }\n\n // The parsed options block to send to the Infinispan client\n // This will be used to configure the Infinispan client behavior.\n const behaviorOptions: Partial<InfinispanClientBehaviorOptions> = {};\n\n behaviorOptions.clusters = infinispanConfig\n .getOptionalConfigArray('clusters')\n ?.map(clusterConf => {\n const name = clusterConf.getOptionalString('name');\n return {\n ...(name && { name }),\n servers: clusterConf.getConfigArray('servers').map(serverConf => ({\n host: serverConf.getString('host'),\n port: serverConf.getOptionalNumber('port') ?? 11222,\n })),\n } as InfinispanClusterConfig;\n });\n\n // Parse Default Options Start...\n const clientVersion =\n infinispanConfig.getOptionalString('version') ?? '2.9';\n if (\n clientVersion === '2.9' ||\n clientVersion === '2.5' ||\n clientVersion === '2.2'\n ) {\n behaviorOptions.version = clientVersion;\n } else if (clientVersion !== null && clientVersion !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan client version \"${clientVersion}\" in config at ${config.storeConfigPath}.version. Must be \"2.9\", \"2.5\", or \"2.2\". It will be ignored, and the client may use a default or fail.`,\n );\n }\n\n behaviorOptions.cacheName =\n infinispanConfig.getOptionalString('cacheName') ?? 'cache';\n\n const mediaType = infinispanConfig.getOptionalString('mediaType');\n if (mediaType === 'text/plain' || mediaType === 'application/json') {\n behaviorOptions.mediaType = mediaType;\n } else if (mediaType !== null && mediaType !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan mediaType \"${mediaType}\" in config at ${config.storeConfigPath}.mediaType. Must be \"text/plain\" | \"application/json\". It will be ignored, and the client may use a default or fail.`,\n );\n }\n\n behaviorOptions.maxRetries =\n infinispanConfig.getOptionalNumber('maxRetries');\n\n behaviorOptions.topologyUpdates =\n infinispanConfig.getOptionalBoolean('topologyUpdates') ?? true;\n\n // Default Options End...\n\n // Parse Authentication and SSL Options\n const authConfig = infinispanConfig.getOptionalConfig('authentication');\n const auth: Partial<InfinispanAuthOptions> = {};\n\n auth.enabled = authConfig?.getOptionalBoolean('enabled');\n auth.saslMechanism = authConfig?.getOptionalString('saslMechanism');\n auth.userName = authConfig?.getOptionalString('userName');\n auth.password = authConfig?.getOptionalString('password');\n auth.token = authConfig?.getOptionalString('token');\n auth.authzid = authConfig?.getOptionalString('authzid');\n\n behaviorOptions.authentication = auth as InfinispanAuthOptions;\n\n const sslConfig = infinispanConfig.getOptionalConfig('ssl');\n const ssl: Partial<InfinispanSslOptions> = {};\n\n ssl.enabled = sslConfig?.getOptionalBoolean('enabled');\n ssl.secureProtocol = sslConfig?.getOptionalString('secureProtocol');\n ssl.trustCerts = sslConfig?.getOptionalStringArray('trustCerts');\n ssl.sniHostName = sslConfig?.getOptionalString('sniHostname');\n\n const clientAuth = infinispanConfig.getOptionalConfig('clientAuth');\n const clientAuthOpts: Partial<InfinispanClientAuthOptions> = {};\n\n clientAuthOpts.key = clientAuth?.getOptionalString('key');\n clientAuthOpts.passphrase = clientAuth?.getOptionalString('passphrase');\n clientAuthOpts.cert = clientAuth?.getOptionalString('cert');\n\n ssl.clientAuth = clientAuthOpts as InfinispanClientAuthOptions;\n\n const cryptoStore = infinispanConfig.getOptionalConfig('cryptoStore');\n const cryptoStoreOpts: Partial<InfinispanClientAuthOptions> = {};\n\n cryptoStoreOpts.key = cryptoStore?.getOptionalString('path');\n cryptoStoreOpts.passphrase = cryptoStore?.getOptionalString('passphrase');\n\n ssl.cryptoStore = cryptoStoreOpts as InfinispanClientAuthOptions;\n\n behaviorOptions.ssl = ssl as InfinispanSslOptions;\n\n const dataFormat = infinispanConfig.getOptionalConfig('dataFormat');\n const dataFormatOpts: Partial<DataFormatOptions> = {};\n\n const keyType = dataFormat?.getOptionalString('keyType') ?? 'text/plain';\n const valueType =\n dataFormat?.getOptionalString('valueType') ?? 'text/plain';\n\n if (keyType === 'text/plain' || keyType === 'application/json') {\n dataFormatOpts.keyType = keyType;\n } else if (keyType !== null && keyType !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan dataFormat.keyType \"${keyType}\" in config at ${config.storeConfigPath}.dataFormat.keyType. Must be \"text/plain\" | \"application/json\". Not mapped, client will use default 'text/plain'.`,\n );\n }\n\n if (valueType === 'text/plain' || valueType === 'application/json') {\n dataFormatOpts.valueType = valueType;\n } else if (valueType !== null && valueType !== undefined) {\n deps.logger?.warn(\n `Invalid Infinispan dataFormat.valueType \"${valueType}\" in config at ${config.storeConfigPath}.dataFormat.valueType. Must be \"text/plain\" | \"application/json\". Not mapped, client will use default 'text/plain'.`,\n );\n }\n behaviorOptions.dataFormat = dataFormatOpts as DataFormatOptions;\n parsedOptions.options = behaviorOptions as InfinispanClientBehaviorOptions;\n\n deps.logger?.debug(\n `Parsed Infinispan options from config at ${\n config.storeConfigPath\n }: ${JSON.stringify(parsedOptions)}`,\n );\n return parsedOptions as InfinispanCacheStoreOptions;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs.js","sources":["../../../src/entrypoints/cache/types.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 type {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { durationToMilliseconds, type HumanDuration } from '@backstage/types';\nimport type { RedisClusterOptions, KeyvRedisOptions } from '@keyv/redis';\nimport type { KeyvValkeyOptions } from '@keyv/valkey';\nimport type { ClusterNode, ClusterOptions } from 'iovalkey';\n\n/**\n * An object form of a cache store connection, with a URL and additional\n * connection options passed through to the underlying client.\n *\n * @public\n */\nexport type CacheStoreConnectionObject = { url: string } & Record<\n string,\n unknown\n>;\n\n/**\n * A cache store connection, either a URL string or an object with\n * connection options passed through to the underlying client.\n *\n * @public\n */\nexport type CacheStoreConnection = string | CacheStoreConnectionObject;\n\n/**\n * Common config options passed to store-specific config parsers.\n *\n * @public\n */\nexport type CacheStoreConfiguration = {\n storeConfigPath: string;\n};\n\n/**\n * Service dependencies required by cache store config parsers.\n *\n * @public\n */\nexport type CacheStoreDeps = {\n config: RootConfigService;\n logger?: LoggerService;\n};\n\n/**\n * Parse options for the Redis cache store\n *\n * @public\n */\nexport type RedisCacheStoreConfiguration = CacheStoreConfiguration & {\n connection: CacheStoreConnection;\n};\n\n/**\n * Options for Redis cache store.\n *\n * @public\n */\nexport type RedisCacheStoreOptions = {\n type: 'redis';\n client?: KeyvRedisOptions;\n cluster?: RedisClusterOptions;\n};\n\n/**\n * Options for Valkey cache store.\n *\n * @public\n */\nexport type ValkeyCacheStoreOptions = {\n type: 'valkey';\n client?: KeyvValkeyOptions;\n cluster?: {\n rootNodes: Array<ClusterNode>;\n options?: ClusterOptions;\n };\n};\n\n/**\n * Union type of all cache store options.\n *\n * @public\n */\nexport type CacheStoreOptions =\n | RedisCacheStoreOptions\n | ValkeyCacheStoreOptions\n | InfinispanCacheStoreOptions;\n\n/**\n * Options given when constructing a {@link CacheManager}.\n *\n * @public\n */\nexport type CacheManagerOptions = {\n /**\n * An optional logger for use by the PluginCacheManager.\n */\n logger?: LoggerService;\n\n /**\n * An optional handler for connection errors emitted from the underlying data\n * store.\n */\n onError?: (err: Error) => void;\n};\n\nexport function ttlToMilliseconds(ttl: number | HumanDuration): number {\n return typeof ttl === 'number' ? ttl : durationToMilliseconds(ttl);\n}\n\n/**\n * Configuration for a single Infinispan server.\n */\nexport type InfinispanServerConfig = {\n host: string;\n port: number;\n};\n\n/**\n * Options for putting values into Infinispan cache.\n */\nexport type InfinispanPutOptions = {\n lifespan?: string;\n maxIdle?: string;\n previous?: boolean;\n flags?: string[];\n};\n/**\n * SSL/TLS options for the Infinispan client.\n */\nexport type InfinispanSslOptions = {\n enabled: boolean;\n secureProtocol?: string;\n trustCerts?: string[]; // Array of trusted CA certificates\n clientAuth?: InfinispanClientAuthOptions;\n cryptoStore?: InfinispanCryptoStoreOptions;\n sniHostName?: string;\n};\n\n/**\n * Authentication options for the Infinispan client.\n * This is used for client-side authentication with the Infinispan server.\n */\nexport type InfinispanClientAuthOptions = {\n key?: string;\n passphrase?: string;\n cert?: string;\n};\n\n/**\n * Options for the Infinispan client crypto store.\n * This is used for storing keys and certificates securely.\n */\nexport type InfinispanCryptoStoreOptions = {\n path?: string;\n passphrase?: string;\n};\n\n/**\n * Authentication options for the Infinispan client.\n */\nexport type InfinispanAuthOptions = {\n enabled: boolean;\n saslMechanism?: string;\n userName?: string;\n password?: string;\n token?: string;\n authzid?: string;\n};\n\n/**\n * Options for the Infinispan cache store, designed to be configured\n * in app-config.yaml under `backend.cache.infinispan`.\n */\nexport type InfinispanCacheStoreOptions = {\n type: 'infinispan';\n servers: InfinispanServerConfig | InfinispanServerConfig[];\n options?: InfinispanClientBehaviorOptions;\n};\n\nexport type InfinispanClusterConfig = {\n name?: string;\n servers: InfinispanServerConfig[];\n};\n\nexport type DataFormatOptions = {\n keyType: 'text/plain' | 'application/json';\n valueType: 'text/plain' | 'application/json';\n};\n\n/**\n * Detailed client behavior options for the Infinispan client.\n * @public\n */\nexport type InfinispanClientBehaviorOptions = {\n version?: '2.9' | '2.5' | '2.2';\n cacheName?: string;\n maxRetries?: number;\n connectionTimeout?: number;\n socketTimeout?: number;\n authentication?: InfinispanAuthOptions;\n ssl?: InfinispanSslOptions;\n mediaType?: 'text/plain' | 'application/json';\n topologyUpdates?: boolean;\n clusters?: InfinispanClusterConfig[];\n dataFormat: DataFormatOptions;\n};\n"],"names":["durationToMilliseconds"],"mappings":";;;;AA6HO,SAAS,kBAAkB,GAAA,EAAqC;AACrE,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,GAAW,GAAA,GAAMA,6BAAuB,GAAG,CAAA;AACnE;;;;"}
1
+ {"version":3,"file":"types.cjs.js","sources":["../../../src/entrypoints/cache/types.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 type {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { durationToMilliseconds, type HumanDuration } from '@backstage/types';\nimport type { RedisClusterOptions, KeyvRedisOptions } from '@keyv/redis';\nimport type { KeyvValkeyOptions } from '@keyv/valkey';\nimport type { ClusterNode, ClusterOptions } from 'iovalkey';\n\n/**\n * An object form of a cache store connection, with a URL and additional\n * connection options passed through to the underlying client.\n *\n * @public\n */\nexport type CacheStoreConnectionObject = { url: string } & Record<\n string,\n unknown\n>;\n\n/**\n * A cache store connection, either a URL string or an object with\n * connection options passed through to the underlying client.\n *\n * @public\n */\nexport type CacheStoreConnection = string | CacheStoreConnectionObject;\n\n/**\n * Common config options passed to store-specific config parsers.\n *\n * @public\n */\nexport type CacheStoreConfiguration = {\n storeConfigPath: string;\n};\n\n/**\n * Service dependencies required by cache store config parsers.\n *\n * @public\n */\nexport type CacheStoreDeps = {\n config: RootConfigService;\n logger?: LoggerService;\n};\n\n/**\n * Parse options for the Redis cache store\n *\n * @public\n */\nexport type RedisCacheStoreConfiguration = CacheStoreConfiguration & {\n connection: CacheStoreConnection;\n};\n\n/**\n * Options for Redis cache store.\n *\n * @public\n */\nexport type RedisCacheStoreOptions = {\n type: 'redis';\n client?: KeyvRedisOptions;\n cluster?: RedisClusterOptions;\n};\n\n/**\n * Options for Valkey cache store.\n *\n * @public\n */\nexport type ValkeyCacheStoreOptions = {\n type: 'valkey';\n client?: KeyvValkeyOptions;\n cluster?: {\n rootNodes: Array<ClusterNode>;\n options?: ClusterOptions;\n };\n};\n\n/**\n * Union type of all cache store options.\n *\n * @public\n */\nexport type CacheStoreOptions =\n | RedisCacheStoreOptions\n | ValkeyCacheStoreOptions\n | InfinispanCacheStoreOptions;\n\n/**\n * Options given when constructing a {@link CacheManager}.\n *\n * @public\n */\nexport type CacheManagerOptions = {\n /**\n * An optional logger for use by the PluginCacheManager.\n */\n logger?: LoggerService;\n\n /**\n * An optional handler for connection errors emitted from the underlying data\n * store.\n */\n onError?: (err: Error) => void;\n};\n\nexport function ttlToMilliseconds(ttl: number | HumanDuration): number {\n return typeof ttl === 'number' ? ttl : durationToMilliseconds(ttl);\n}\n\n/**\n * Configuration for a single Infinispan server.\n */\nexport type InfinispanServerConfig = {\n host: string;\n port: number;\n};\n\n/**\n * Options for putting values into Infinispan cache.\n */\nexport type InfinispanPutOptions = {\n lifespan?: string;\n maxIdle?: string;\n previous?: boolean;\n flags?: string[];\n};\n/**\n * SSL/TLS options for the Infinispan client.\n */\nexport type InfinispanSslOptions = {\n enabled: boolean;\n secureProtocol?: string;\n trustCerts?: string[]; // Array of trusted CA certificates\n clientAuth?: InfinispanClientAuthOptions;\n cryptoStore?: InfinispanCryptoStoreOptions;\n sniHostName?: string;\n};\n\n/**\n * Authentication options for the Infinispan client.\n * This is used for client-side authentication with the Infinispan server.\n */\nexport type InfinispanClientAuthOptions = {\n key?: string;\n passphrase?: string;\n cert?: string;\n};\n\n/**\n * Options for the Infinispan client crypto store.\n * This is used for storing keys and certificates securely.\n */\nexport type InfinispanCryptoStoreOptions = {\n path?: string;\n passphrase?: string;\n};\n\n/**\n * Authentication options for the Infinispan client.\n */\nexport type InfinispanAuthOptions = {\n enabled: boolean;\n saslMechanism?: string;\n userName?: string;\n password?: string;\n token?: string;\n authzid?: string;\n};\n\n/**\n * Options for the Infinispan cache store, designed to be configured\n * in app-config.yaml under `backend.cache.infinispan`.\n */\nexport type InfinispanCacheStoreOptions = {\n type: 'infinispan';\n servers: InfinispanServerConfig | InfinispanServerConfig[];\n options?: InfinispanClientBehaviorOptions;\n};\n\nexport type InfinispanClusterConfig = {\n name?: string;\n servers: InfinispanServerConfig[];\n};\n\nexport type DataFormatOptions = {\n keyType: 'text/plain' | 'application/json';\n valueType: 'text/plain' | 'application/json';\n};\n\n/**\n * Detailed client behavior options for the Infinispan client.\n * @public\n */\nexport type InfinispanClientBehaviorOptions = {\n version?: '2.9' | '2.5' | '2.2';\n cacheName?: string;\n maxRetries?: number;\n connectionTimeout?: number;\n socketTimeout?: number;\n authentication?: InfinispanAuthOptions;\n ssl?: InfinispanSslOptions;\n mediaType?: 'text/plain' | 'application/json';\n topologyUpdates?: boolean;\n clusters?: InfinispanClusterConfig[];\n dataFormat: DataFormatOptions;\n};\n"],"names":["durationToMilliseconds"],"mappings":";;;;AA6HO,SAAS,kBAAkB,GAAA,EAAqC;AACrE,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,GAAW,GAAA,GAAMA,6BAAuB,GAAG,CAAA;AACnE;;"}
@@ -157,11 +157,17 @@ class DatabaseManager {
157
157
  static fromConfig(config, options) {
158
158
  const databaseConfig = config.getConfig("backend.database");
159
159
  const prefix = databaseConfig.getOptionalString("prefix") || "backstage_plugin_";
160
+ const schemaPrefix = databaseConfig.getOptionalString("schemaPrefix") || "";
161
+ if (schemaPrefix && !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(schemaPrefix)) {
162
+ throw new Error(
163
+ `Invalid schemaPrefix "${schemaPrefix}". Schema prefix must start with a letter or underscore and contain only letters, numbers, and underscores.`
164
+ );
165
+ }
160
166
  return new DatabaseManager(
161
167
  new DatabaseManagerImpl(
162
168
  databaseConfig,
163
169
  {
164
- pg: new postgres.PgConnector(databaseConfig, prefix),
170
+ pg: new postgres.PgConnector(databaseConfig, prefix, schemaPrefix),
165
171
  sqlite3: new sqlite3.Sqlite3Connector(databaseConfig),
166
172
  "better-sqlite3": new sqlite3.Sqlite3Connector(databaseConfig),
167
173
  mysql: new mysql.MysqlConnector(databaseConfig, prefix),
@@ -1 +1 @@
1
- {"version":3,"file":"DatabaseManager.cjs.js","sources":["../../../src/entrypoints/database/DatabaseManager.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 LifecycleService,\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { stringifyError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { MysqlConnector } from './connectors/mysql';\nimport { PgConnector } from './connectors/postgres';\nimport { Sqlite3Connector } from './connectors/sqlite3';\nimport { Connector } from './types';\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\n/**\n * Creation options for {@link DatabaseManager}.\n *\n * @public\n */\nexport type DatabaseManagerOptions = {\n migrations?: DatabaseService['migrations'];\n rootLogger?: RootLoggerService;\n rootLifecycle?: RootLifecycleService;\n};\n\n/**\n * Testable implementation class for {@link DatabaseManager} below.\n */\nexport class DatabaseManagerImpl {\n private readonly config: Config;\n private readonly connectors: Record<string, Connector>;\n private readonly options?: DatabaseManagerOptions;\n private readonly databaseCache: Map<string, Promise<Knex>>;\n private readonly keepaliveIntervals: Map<string, NodeJS.Timeout>;\n\n constructor(\n config: Config,\n connectors: Record<string, Connector>,\n options?: DatabaseManagerOptions,\n databaseCache: Map<string, Promise<Knex>> = new Map(),\n keepaliveIntervals: Map<string, NodeJS.Timeout> = new Map(),\n ) {\n this.config = config;\n this.connectors = connectors;\n this.options = options;\n this.databaseCache = databaseCache;\n this.keepaliveIntervals = keepaliveIntervals;\n // If a rootLifecycle service was provided, register a shutdown hook to\n // clean up any database connections.\n if (options?.rootLifecycle !== undefined) {\n options.rootLifecycle.addShutdownHook(async () => {\n await this.shutdown({ logger: options.rootLogger });\n });\n }\n }\n\n /**\n * Generates a DatabaseService for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): DatabaseService {\n const client = this.getClientType(pluginId).client;\n const connector = this.connectors[client];\n if (!connector) {\n throw new Error(\n `Unsupported database client type '${client}' specified for plugin '${pluginId}'`,\n );\n }\n const getClient = () => this.getDatabase(pluginId, connector, deps);\n\n const skip =\n this.options?.migrations?.skip ??\n this.config.getOptionalBoolean(`plugin.${pluginId}.skipMigrations`) ??\n this.config.getOptionalBoolean('skipMigrations') ??\n false;\n\n return { getClient, migrations: { skip } };\n }\n\n /**\n * Destroys all known connections.\n */\n private async shutdown(deps?: { logger?: LoggerService }): Promise<void> {\n const pluginIds = Array.from(this.databaseCache.keys());\n await Promise.allSettled(\n pluginIds.map(async pluginId => {\n // We no longer need to keep connections alive.\n clearInterval(this.keepaliveIntervals.get(pluginId));\n\n const connection = await this.databaseCache.get(pluginId);\n if (connection) {\n if (connection.client.config.includes('sqlite3')) {\n return; // sqlite3 does not support destroy, it hangs\n }\n await connection.destroy().catch((error: unknown) => {\n deps?.logger?.error(\n `Problem closing database connection for ${pluginId}: ${stringifyError(\n error,\n )}`,\n );\n });\n }\n }),\n );\n\n const connectors = new Set(Object.values(this.connectors));\n await Promise.all(\n Array.from(connectors, async connector => {\n try {\n await connector.shutdown?.();\n } catch (error) {\n deps?.logger?.error(\n `Problem closing database connector: ${stringifyError(error)}`,\n );\n }\n }),\n );\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n /**\n * Provides a scoped Knex client for a plugin as per application config.\n *\n * @param pluginId - Plugin to get a Knex client for\n * @returns Promise which resolves to a scoped Knex database client for a\n * plugin\n */\n private async getDatabase(\n pluginId: string,\n connector: Connector,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n if (this.databaseCache.has(pluginId)) {\n return this.databaseCache.get(pluginId)!;\n }\n\n const clientPromise = connector.getClient(pluginId, deps);\n this.databaseCache.set(pluginId, clientPromise);\n\n if (process.env.NODE_ENV !== 'test') {\n clientPromise.then(client =>\n this.startKeepaliveLoop(pluginId, client, deps.logger),\n );\n }\n\n return clientPromise;\n }\n\n private startKeepaliveLoop(\n pluginId: string,\n client: Knex,\n logger: LoggerService,\n ): void {\n let lastKeepaliveFailed = false;\n\n this.keepaliveIntervals.set(\n pluginId,\n setInterval(() => {\n // During testing it can happen that the environment is torn down and\n // this client is `undefined`, but this interval is still run.\n client?.raw('select 1').then(\n () => {\n lastKeepaliveFailed = false;\n },\n (error: unknown) => {\n if (!lastKeepaliveFailed) {\n lastKeepaliveFailed = true;\n logger.warn(\n `Database keepalive failed for plugin ${pluginId}, ${stringifyError(\n error,\n )}`,\n );\n }\n },\n );\n }, 60 * 1000),\n );\n }\n}\n\n// NOTE: This class looks odd but is kept around for API compatibility reasons\n/**\n * Manages database connections for Backstage backend plugins.\n *\n * @public\n * @remarks\n *\n * The database manager allows the user to set connection and client settings on\n * a per pluginId basis by defining a database config block under\n * `plugin.<pluginId>` in addition to top level defaults. Optionally, a user may\n * set `prefix` which is used to prefix generated database names if config is\n * not provided.\n */\nexport class DatabaseManager {\n /**\n * Creates a {@link DatabaseManager} from `backend.database` config.\n *\n * @param config - The loaded application configuration.\n * @param options - An optional configuration object.\n */\n static fromConfig(\n config: RootConfigService,\n options?: DatabaseManagerOptions,\n ): DatabaseManager {\n const databaseConfig = config.getConfig('backend.database');\n const prefix =\n databaseConfig.getOptionalString('prefix') || 'backstage_plugin_';\n return new DatabaseManager(\n new DatabaseManagerImpl(\n databaseConfig,\n {\n pg: new PgConnector(databaseConfig, prefix),\n sqlite3: new Sqlite3Connector(databaseConfig),\n 'better-sqlite3': new Sqlite3Connector(databaseConfig),\n mysql: new MysqlConnector(databaseConfig, prefix),\n mysql2: new MysqlConnector(databaseConfig, prefix),\n },\n options,\n ),\n );\n }\n\n private readonly impl: DatabaseManagerImpl;\n\n private constructor(impl: DatabaseManagerImpl) {\n this.impl = impl;\n }\n\n /**\n * Generates a DatabaseService for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): DatabaseService {\n return this.impl.forPlugin(pluginId, deps);\n }\n}\n"],"names":["stringifyError","PgConnector","Sqlite3Connector","MysqlConnector"],"mappings":"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"}
1
+ {"version":3,"file":"DatabaseManager.cjs.js","sources":["../../../src/entrypoints/database/DatabaseManager.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 LifecycleService,\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n RootLoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { stringifyError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { MysqlConnector } from './connectors/mysql';\nimport { PgConnector } from './connectors/postgres';\nimport { Sqlite3Connector } from './connectors/sqlite3';\nimport { Connector } from './types';\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\n/**\n * Creation options for {@link DatabaseManager}.\n *\n * @public\n */\nexport type DatabaseManagerOptions = {\n migrations?: DatabaseService['migrations'];\n rootLogger?: RootLoggerService;\n rootLifecycle?: RootLifecycleService;\n};\n\n/**\n * Testable implementation class for {@link DatabaseManager} below.\n */\nexport class DatabaseManagerImpl {\n private readonly config: Config;\n private readonly connectors: Record<string, Connector>;\n private readonly options?: DatabaseManagerOptions;\n private readonly databaseCache: Map<string, Promise<Knex>>;\n private readonly keepaliveIntervals: Map<string, NodeJS.Timeout>;\n\n constructor(\n config: Config,\n connectors: Record<string, Connector>,\n options?: DatabaseManagerOptions,\n databaseCache: Map<string, Promise<Knex>> = new Map(),\n keepaliveIntervals: Map<string, NodeJS.Timeout> = new Map(),\n ) {\n this.config = config;\n this.connectors = connectors;\n this.options = options;\n this.databaseCache = databaseCache;\n this.keepaliveIntervals = keepaliveIntervals;\n // If a rootLifecycle service was provided, register a shutdown hook to\n // clean up any database connections.\n if (options?.rootLifecycle !== undefined) {\n options.rootLifecycle.addShutdownHook(async () => {\n await this.shutdown({ logger: options.rootLogger });\n });\n }\n }\n\n /**\n * Generates a DatabaseService for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): DatabaseService {\n const client = this.getClientType(pluginId).client;\n const connector = this.connectors[client];\n if (!connector) {\n throw new Error(\n `Unsupported database client type '${client}' specified for plugin '${pluginId}'`,\n );\n }\n const getClient = () => this.getDatabase(pluginId, connector, deps);\n\n const skip =\n this.options?.migrations?.skip ??\n this.config.getOptionalBoolean(`plugin.${pluginId}.skipMigrations`) ??\n this.config.getOptionalBoolean('skipMigrations') ??\n false;\n\n return { getClient, migrations: { skip } };\n }\n\n /**\n * Destroys all known connections.\n */\n private async shutdown(deps?: { logger?: LoggerService }): Promise<void> {\n const pluginIds = Array.from(this.databaseCache.keys());\n await Promise.allSettled(\n pluginIds.map(async pluginId => {\n // We no longer need to keep connections alive.\n clearInterval(this.keepaliveIntervals.get(pluginId));\n\n const connection = await this.databaseCache.get(pluginId);\n if (connection) {\n if (connection.client.config.includes('sqlite3')) {\n return; // sqlite3 does not support destroy, it hangs\n }\n await connection.destroy().catch((error: unknown) => {\n deps?.logger?.error(\n `Problem closing database connection for ${pluginId}: ${stringifyError(\n error,\n )}`,\n );\n });\n }\n }),\n );\n\n const connectors = new Set(Object.values(this.connectors));\n await Promise.all(\n Array.from(connectors, async connector => {\n try {\n await connector.shutdown?.();\n } catch (error) {\n deps?.logger?.error(\n `Problem closing database connector: ${stringifyError(error)}`,\n );\n }\n }),\n );\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n /**\n * Provides a scoped Knex client for a plugin as per application config.\n *\n * @param pluginId - Plugin to get a Knex client for\n * @returns Promise which resolves to a scoped Knex database client for a\n * plugin\n */\n private async getDatabase(\n pluginId: string,\n connector: Connector,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): Promise<Knex> {\n if (this.databaseCache.has(pluginId)) {\n return this.databaseCache.get(pluginId)!;\n }\n\n const clientPromise = connector.getClient(pluginId, deps);\n this.databaseCache.set(pluginId, clientPromise);\n\n if (process.env.NODE_ENV !== 'test') {\n clientPromise.then(client =>\n this.startKeepaliveLoop(pluginId, client, deps.logger),\n );\n }\n\n return clientPromise;\n }\n\n private startKeepaliveLoop(\n pluginId: string,\n client: Knex,\n logger: LoggerService,\n ): void {\n let lastKeepaliveFailed = false;\n\n this.keepaliveIntervals.set(\n pluginId,\n setInterval(() => {\n // During testing it can happen that the environment is torn down and\n // this client is `undefined`, but this interval is still run.\n client?.raw('select 1').then(\n () => {\n lastKeepaliveFailed = false;\n },\n (error: unknown) => {\n if (!lastKeepaliveFailed) {\n lastKeepaliveFailed = true;\n logger.warn(\n `Database keepalive failed for plugin ${pluginId}, ${stringifyError(\n error,\n )}`,\n );\n }\n },\n );\n }, 60 * 1000),\n );\n }\n}\n\n// NOTE: This class looks odd but is kept around for API compatibility reasons\n/**\n * Manages database connections for Backstage backend plugins.\n *\n * @public\n * @remarks\n *\n * The database manager allows the user to set connection and client settings on\n * a per pluginId basis by defining a database config block under\n * `plugin.<pluginId>` in addition to top level defaults. Optionally, a user may\n * set `prefix` which is used to prefix generated database names if config is\n * not provided.\n */\nexport class DatabaseManager {\n /**\n * Creates a {@link DatabaseManager} from `backend.database` config.\n *\n * @param config - The loaded application configuration.\n * @param options - An optional configuration object.\n */\n static fromConfig(\n config: RootConfigService,\n options?: DatabaseManagerOptions,\n ): DatabaseManager {\n const databaseConfig = config.getConfig('backend.database');\n const prefix =\n databaseConfig.getOptionalString('prefix') || 'backstage_plugin_';\n const schemaPrefix = databaseConfig.getOptionalString('schemaPrefix') || '';\n\n // Validate schemaPrefix contains only safe PostgreSQL identifier characters\n if (schemaPrefix && !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(schemaPrefix)) {\n throw new Error(\n `Invalid schemaPrefix \"${schemaPrefix}\". ` +\n `Schema prefix must start with a letter or underscore and contain only letters, numbers, and underscores.`,\n );\n }\n\n return new DatabaseManager(\n new DatabaseManagerImpl(\n databaseConfig,\n {\n pg: new PgConnector(databaseConfig, prefix, schemaPrefix),\n sqlite3: new Sqlite3Connector(databaseConfig),\n 'better-sqlite3': new Sqlite3Connector(databaseConfig),\n mysql: new MysqlConnector(databaseConfig, prefix),\n mysql2: new MysqlConnector(databaseConfig, prefix),\n },\n options,\n ),\n );\n }\n\n private readonly impl: DatabaseManagerImpl;\n\n private constructor(impl: DatabaseManagerImpl) {\n this.impl = impl;\n }\n\n /**\n * Generates a DatabaseService for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps: {\n logger: LoggerService;\n lifecycle: LifecycleService;\n },\n ): DatabaseService {\n return this.impl.forPlugin(pluginId, deps);\n }\n}\n"],"names":["stringifyError","PgConnector","Sqlite3Connector","MysqlConnector"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"defaultNameOverride.cjs.js","sources":["../../../../src/entrypoints/database/connectors/defaultNameOverride.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 { Knex } from 'knex';\n\n/**\n * Provides a partial knex config with database name override.\n *\n * Default override for knex database drivers which accept ConnectionConfig\n * with `connection.database` as the database name field.\n *\n * @param name - database name to get config override for\n */\nexport default function defaultNameOverride(\n name: string,\n): Partial<Knex.Config> {\n return {\n connection: {\n database: name,\n },\n };\n}\n"],"names":[],"mappings":";;;;AA0BA,SAAwB,oBACtB,IAAA,EACsB;AACtB,EAAA,OAAO;AAAA,IACL,UAAA,EAAY;AAAA,MACV,QAAA,EAAU;AAAA;AACZ,GACF;AACF;;;;"}
1
+ {"version":3,"file":"defaultNameOverride.cjs.js","sources":["../../../../src/entrypoints/database/connectors/defaultNameOverride.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 { Knex } from 'knex';\n\n/**\n * Provides a partial knex config with database name override.\n *\n * Default override for knex database drivers which accept ConnectionConfig\n * with `connection.database` as the database name field.\n *\n * @param name - database name to get config override for\n */\nexport default function defaultNameOverride(\n name: string,\n): Partial<Knex.Config> {\n return {\n connection: {\n database: name,\n },\n };\n}\n"],"names":[],"mappings":";;;;AA0BA,SAAwB,oBACtB,IAAA,EACsB;AACtB,EAAA,OAAO;AAAA,IACL,UAAA,EAAY;AAAA,MACV,QAAA,EAAU;AAAA;AACZ,GACF;AACF;;"}