@backstage/backend-defaults 0.14.0-next.1 → 0.14.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,73 @@
1
1
  # @backstage/backend-defaults
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fa43826: Move `better-sqlite3` from dependencies to peer dependencies
8
+ - 2bc4e02: **BREAKING** The correct configuration options for Valkey are now being used.
9
+
10
+ These changes are **required** to `app-config.yaml`:
11
+
12
+ ```diff
13
+ backend:
14
+ cache:
15
+ store: valkey
16
+ connection: ...
17
+ client:
18
+ - namespace: 'my-app'
19
+ - keyPrefixSeparator: ':'
20
+ + keyPrefix: 'my-app:'
21
+ - clearBatchSize: 1000
22
+ - useUnlink: false
23
+ ```
24
+
25
+ In comparison to Redis, Valkey requires the full `keyPrefix` including the separator to be specified instead of separate `namespace` and `keyPrefixSeparator` options. Also, Valkey does not support the `clearBatchSize` and `useUnlink` options.
26
+
27
+ ### Patch Changes
28
+
29
+ - 37fba1d: Added support for Bitbucket Cloud OAuth. This introduces an alternative authentication method using a workspace OAuth consumer, alongside App Passwords (deprecated) and API tokens. OAuth does not require a bot or service account and avoids token expiry issues.
30
+
31
+ **BREAKING CHANGES**
32
+
33
+ - **@backstage/integration** (`src/bitbucketCloud/core.ts`)
34
+
35
+ - `getBitbucketCloudRequestOptions` now returns a `Promise` and **must** be awaited.
36
+
37
+ - **@backstage/plugin-scaffolder-backend-module-bitbucket-cloud** (`src/actions/helpers.ts`)
38
+ - `getBitbucketClient` now returns a `Promise` and **must** be awaited.
39
+ - `getAuthorizationHeader` now returns a `Promise` and **must** be awaited.
40
+
41
+ **OAuth usage example**
42
+
43
+ ```yaml
44
+ integrations:
45
+ bitbucketCloud:
46
+ - clientId: client-id
47
+ clientSecret: client-secret
48
+ ```
49
+
50
+ - de96a60: chore(deps): bump `express` from 4.21.2 to 4.22.0
51
+ - aa79251: build(deps): bump `node-forge` from 1.3.1 to 1.3.2
52
+ - f96edff: Allow configuration of the `referrerPolicy`
53
+ - fb029b6: Updated luxon types
54
+ - d9759a1: **BREAKING ALPHA**: The old `instanceMetadataService` has been removed from alpha. Please switch over to using the stable `coreServices.rootInstanceMetadata` and related types instead, available from `@backstage/backend-plugin-api`.
55
+ - 847a330: Fix for `jose` types
56
+ - 25b560e: Internal change to support new versions of the `logform` library
57
+ - 2a0c4b0: Adds a new experimental `RootSystemMetadataService` for tracking the collection of Backstage instances that may be deployed at any one time. It currently offers a single API, `getInstalledPlugins` that returns a list of installed plugins based on config you have set up in `discovery.endpoints` as well as the plugins installed on the instance you're calling the API with. It does not handle wildcard values or fallback values. The intention is for this plugin to provide plugin authors with a simple interface to fetch a trustworthy list of all installed plugins.
58
+ - 3016a79: Updated dependency `@types/archiver` to `^7.0.0`.
59
+ - 42db6a6: Don't warn when parsing `storeOptions` for `memory` cache
60
+ - Updated dependencies
61
+ - @backstage/cli-node@0.2.16
62
+ - @backstage/integration@1.19.0
63
+ - @backstage/plugin-auth-node@0.6.10
64
+ - @backstage/plugin-events-node@0.4.18
65
+ - @backstage/plugin-permission-node@0.10.7
66
+ - @backstage/backend-app-api@1.4.0
67
+ - @backstage/backend-plugin-api@1.6.0
68
+ - @backstage/config-loader@1.10.7
69
+ - @backstage/backend-dev-utils@0.1.6
70
+
3
71
  ## 0.14.0-next.1
4
72
 
5
73
  ### Patch Changes
package/config.d.ts CHANGED
@@ -710,27 +710,9 @@ export interface Config {
710
710
  */
711
711
  client?: {
712
712
  /**
713
- * Namespace for the current instance.
714
- */
715
- namespace?: string;
716
- /**
717
- * Separator to use between namespace and key.
718
- */
719
- keyPrefixSeparator?: string;
720
- /**
721
- * Number of keys to delete in a single batch.
722
- */
723
- clearBatchSize?: number;
724
- /**
725
- * Enable Unlink instead of using Del for clearing keys. This is more performant but may not be supported by all Redis versions.
726
- */
727
- useUnlink?: boolean;
728
- /**
729
- * Whether to allow clearing all keys when no namespace is set.
730
- * If set to true and no namespace is set, iterate() will return all keys.
731
- * Defaults to `false`.
713
+ * Namespace and separator used for prefixing keys.
732
714
  */
733
- noNamespaceAffectsAll?: boolean;
715
+ keyPrefix?: string;
734
716
  };
735
717
  /**
736
718
  * An optional Valkey cluster (redis cluster under the hood) configuration.
package/dist/cache.d.ts CHANGED
@@ -70,6 +70,10 @@ declare class CacheManager {
70
70
  * Parse Redis-specific options from configuration.
71
71
  */
72
72
  private static parseRedisOptions;
73
+ /**
74
+ * Parse Valkey-specific options from configuration.
75
+ */
76
+ private static parseValkeyOptions;
73
77
  /**
74
78
  * Construct the full namespace based on the options and pluginId.
75
79
  *
@@ -80,34 +80,32 @@ class CacheManager {
80
80
  */
81
81
  static parseStoreOptions(store, config, logger) {
82
82
  const storeConfigPath = `backend.cache.${store}`;
83
- if (!config.has(storeConfigPath)) {
83
+ if (store !== "memory" && !config.has(storeConfigPath)) {
84
84
  logger?.warn(
85
85
  `No configuration found for cache store '${store}' at '${storeConfigPath}'.`
86
86
  );
87
87
  }
88
- if (store === "redis" || store === "valkey") {
89
- return CacheManager.parseRedisOptions(
90
- store,
91
- storeConfigPath,
92
- config,
93
- logger
94
- );
95
- }
96
- if (store === "infinispan") {
97
- return InfinispanOptionsMapper.InfinispanOptionsMapper.parseInfinispanOptions(
98
- storeConfigPath,
99
- config,
100
- logger
101
- );
88
+ switch (store) {
89
+ case "redis":
90
+ return CacheManager.parseRedisOptions(storeConfigPath, config, logger);
91
+ case "valkey":
92
+ return CacheManager.parseValkeyOptions(storeConfigPath, config, logger);
93
+ case "infinispan":
94
+ return InfinispanOptionsMapper.InfinispanOptionsMapper.parseInfinispanOptions(
95
+ storeConfigPath,
96
+ config,
97
+ logger
98
+ );
99
+ default:
100
+ return void 0;
102
101
  }
103
- return void 0;
104
102
  }
105
103
  /**
106
104
  * Parse Redis-specific options from configuration.
107
105
  */
108
- static parseRedisOptions(store, storeConfigPath, config$1, logger) {
106
+ static parseRedisOptions(storeConfigPath, config$1, logger) {
109
107
  const redisOptions = {
110
- type: store
108
+ type: "redis"
111
109
  };
112
110
  const redisConfig = config$1.getOptionalConfig(storeConfigPath) ?? new config.ConfigReader({});
113
111
  redisOptions.client = {
@@ -141,6 +139,39 @@ class CacheManager {
141
139
  }
142
140
  return redisOptions;
143
141
  }
142
+ /**
143
+ * Parse Valkey-specific options from configuration.
144
+ */
145
+ static parseValkeyOptions(storeConfigPath, config$1, logger) {
146
+ const valkeyOptions = {
147
+ type: "valkey"
148
+ };
149
+ const valkeyConfig = config$1.getOptionalConfig(storeConfigPath) ?? new config.ConfigReader({});
150
+ valkeyOptions.client = {
151
+ keyPrefix: valkeyConfig.getOptionalString("client.keyPrefix")
152
+ };
153
+ if (valkeyConfig.has("cluster")) {
154
+ const clusterConfig = valkeyConfig.getConfig("cluster");
155
+ if (!clusterConfig.has("rootNodes")) {
156
+ logger?.warn(
157
+ `Valkey cluster config has no 'rootNodes' key, defaulting to non-clustered mode`
158
+ );
159
+ return valkeyOptions;
160
+ }
161
+ valkeyOptions.cluster = {
162
+ rootNodes: clusterConfig.get("rootNodes"),
163
+ defaults: clusterConfig.getOptional("defaults"),
164
+ minimizeConnections: clusterConfig.getOptionalBoolean(
165
+ "minimizeConnections"
166
+ ),
167
+ useReplicas: clusterConfig.getOptionalBoolean("useReplicas"),
168
+ maxCommandRedirections: clusterConfig.getOptionalNumber(
169
+ "maxCommandRedirections"
170
+ )
171
+ };
172
+ }
173
+ return valkeyOptions;
174
+ }
144
175
  /**
145
176
  * Construct the full namespace based on the options and pluginId.
146
177
  *
@@ -149,7 +180,17 @@ class CacheManager {
149
180
  * @returns The constructed namespace string combining the configured namespace with pluginId
150
181
  */
151
182
  static constructNamespace(pluginId, storeOptions) {
152
- const prefix = storeOptions?.client?.namespace ? `${storeOptions.client.namespace}${storeOptions.client.keyPrefixSeparator ?? ":"}` : "";
183
+ let prefix;
184
+ switch (storeOptions?.type) {
185
+ case "redis":
186
+ prefix = storeOptions?.client?.namespace ? `${storeOptions.client.namespace}${storeOptions.client.keyPrefixSeparator ?? ":"}` : "";
187
+ break;
188
+ case "valkey":
189
+ prefix = storeOptions.client?.keyPrefix ?? "";
190
+ break;
191
+ default:
192
+ prefix = "";
193
+ }
153
194
  return `${prefix}${pluginId}`;
154
195
  }
155
196
  /** @internal */
@@ -219,7 +260,7 @@ class CacheManager {
219
260
  }
220
261
  createValkeyStoreFactory() {
221
262
  const KeyvValkey = require("@keyv/valkey").default;
222
- const { createCluster } = require("@keyv/valkey");
263
+ const { createCluster } = require("@keyv/redis");
223
264
  const stores = {};
224
265
  return (pluginId, defaultTtl) => {
225
266
  if (this.storeOptions?.type !== "valkey") {
@@ -228,9 +269,7 @@ class CacheManager {
228
269
  );
229
270
  }
230
271
  if (!stores[pluginId]) {
231
- const valkeyOptions = this.storeOptions?.client || {
232
- keyPrefixSeparator: ":"
233
- };
272
+ const valkeyOptions = this.storeOptions?.client;
234
273
  if (this.storeOptions?.cluster) {
235
274
  const cluster = createCluster(this.storeOptions?.cluster);
236
275
  stores[pluginId] = new KeyvValkey(cluster, valkeyOptions);
@@ -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 RedisCacheStoreOptions,\n InfinispanClientBehaviorOptions,\n InfinispanServerConfig,\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';\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: string;\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 connectionString =\n config.getOptionalString('backend.cache.connection') || '';\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(store, config, logger);\n\n return new CacheManager(\n store,\n connectionString,\n options.onError,\n logger,\n defaultTtl,\n storeOptions,\n );\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 store: string,\n config: RootConfigService,\n logger?: LoggerService,\n ): CacheStoreOptions | undefined {\n const storeConfigPath = `backend.cache.${store}`;\n\n if (!config.has(storeConfigPath)) {\n logger?.warn(\n `No configuration found for cache store '${store}' at '${storeConfigPath}'.`,\n );\n }\n\n if (store === 'redis' || store === 'valkey') {\n return CacheManager.parseRedisOptions(\n store,\n storeConfigPath,\n config,\n logger,\n );\n }\n\n if (store === 'infinispan') {\n return InfinispanOptionsMapper.parseInfinispanOptions(\n storeConfigPath,\n config,\n logger,\n );\n }\n\n return undefined;\n }\n\n /**\n * Parse Redis-specific options from configuration.\n */\n private static parseRedisOptions(\n store: string,\n storeConfigPath: string,\n config: RootConfigService,\n logger?: LoggerService,\n ): RedisCacheStoreOptions {\n const redisOptions: RedisCacheStoreOptions = {\n type: store as 'redis' | 'valkey',\n };\n\n const redisConfig =\n config.getOptionalConfig(storeConfigPath) ?? 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 logger?.warn(\n `Redis cluster config has no 'rootNodes' key, defaulting to non-clustered mode`,\n );\n return redisOptions;\n }\n\n redisOptions.cluster = {\n rootNodes: clusterConfig.get('rootNodes'),\n defaults: clusterConfig.getOptional('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 * 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 | undefined,\n ): string {\n const prefix = storeOptions?.client?.namespace\n ? `${storeOptions.client.namespace}${\n storeOptions.client.keyPrefixSeparator ?? ':'\n }`\n : '';\n\n return `${prefix}${pluginId}`;\n }\n\n /** @internal */\n constructor(\n store: string,\n connectionString: string,\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 = connectionString;\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').default;\n const { createCluster } = require('@keyv/redis');\n const stores: Record<string, 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 = 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 { createCluster } = require('@keyv/valkey');\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 keyPrefixSeparator: ':',\n };\n if (this.storeOptions?.cluster) {\n // Create a Valkey cluster (Redis cluster under the hood)\n const cluster = createCluster(this.storeOptions?.cluster);\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":"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"}
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 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';\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: string;\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 connectionString =\n config.getOptionalString('backend.cache.connection') || '';\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(store, config, logger);\n\n return new CacheManager(\n store,\n connectionString,\n options.onError,\n logger,\n defaultTtl,\n storeOptions,\n );\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 store: string,\n config: RootConfigService,\n logger?: LoggerService,\n ): CacheStoreOptions | undefined {\n const storeConfigPath = `backend.cache.${store}`;\n\n if (store !== 'memory' && !config.has(storeConfigPath)) {\n 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(storeConfigPath, config, logger);\n case 'valkey':\n return CacheManager.parseValkeyOptions(storeConfigPath, config, logger);\n case 'infinispan':\n return InfinispanOptionsMapper.parseInfinispanOptions(\n storeConfigPath,\n config,\n logger,\n );\n default:\n return undefined;\n }\n }\n\n /**\n * Parse Redis-specific options from configuration.\n */\n private static parseRedisOptions(\n storeConfigPath: string,\n config: RootConfigService,\n logger?: LoggerService,\n ): RedisCacheStoreOptions {\n const redisOptions: RedisCacheStoreOptions = {\n type: 'redis',\n };\n\n const redisConfig =\n config.getOptionalConfig(storeConfigPath) ?? 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 logger?.warn(\n `Redis cluster config has no 'rootNodes' key, defaulting to non-clustered mode`,\n );\n return redisOptions;\n }\n\n redisOptions.cluster = {\n rootNodes: clusterConfig.get('rootNodes'),\n defaults: clusterConfig.getOptional('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 storeConfigPath: string,\n config: RootConfigService,\n logger?: LoggerService,\n ): ValkeyCacheStoreOptions {\n const valkeyOptions: ValkeyCacheStoreOptions = {\n type: 'valkey',\n };\n\n const valkeyConfig =\n config.getOptionalConfig(storeConfigPath) ?? 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 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 defaults: clusterConfig.getOptional('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 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 connectionString: string,\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 = connectionString;\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').default;\n const { createCluster } = require('@keyv/redis');\n const stores: Record<string, 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 = 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 // `@keyv/valkey` doesn't export a `createCluster` function, but is compatible with the one from `@keyv/redis`\n // See https://keyv.org/docs/storage-adapters/valkey\n const { createCluster } = require('@keyv/redis');\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 a Valkey cluster (Redis cluster under the hood)\n const cluster = createCluster(this.storeOptions?.cluster);\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":"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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 { LoggerService } from '@backstage/backend-plugin-api';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport { RedisClusterOptions, KeyvRedisOptions } from '@keyv/redis';\n\n/**\n * Options for Redis cache store.\n *\n * @public\n */\nexport type RedisCacheStoreOptions = {\n type: 'redis' | 'valkey';\n client?: KeyvRedisOptions;\n cluster?: RedisClusterOptions;\n};\n\n/**\n * Union type of all cache store options.\n *\n * @public\n */\nexport type CacheStoreOptions =\n | RedisCacheStoreOptions\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":";;;;AA0DO,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 { LoggerService } from '@backstage/backend-plugin-api';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport { RedisClusterOptions, KeyvRedisOptions } from '@keyv/redis';\nimport { KeyvValkeyOptions } from '@keyv/valkey';\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?: RedisClusterOptions;\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":";;;;AAuEO,SAAS,kBAAkB,GAAA,EAAqC;AACrE,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,GAAW,GAAA,GAAMA,6BAAuB,GAAG,CAAA;AACnE;;;;"}
@@ -27,7 +27,12 @@ class BitbucketCloudUrlReader {
27
27
  constructor(integration, deps) {
28
28
  this.integration = integration;
29
29
  this.deps = deps;
30
- const { host, username, appPassword, token } = integration.config;
30
+ const { host, username, appPassword, token, clientId, clientSecret } = integration.config;
31
+ if (clientId && !clientSecret || clientSecret && !clientId) {
32
+ throw new Error(
33
+ `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`
34
+ );
35
+ }
31
36
  if (username && !token && !appPassword) {
32
37
  throw new Error(
33
38
  `Bitbucket Cloud integration for '${host}' has configured a username but is missing a required token or appPassword.`
@@ -44,7 +49,7 @@ class BitbucketCloudUrlReader {
44
49
  url,
45
50
  this.integration.config
46
51
  );
47
- const requestOptions = integration.getBitbucketCloudRequestOptions(
52
+ const requestOptions = await integration.getBitbucketCloudRequestOptions(
48
53
  this.integration.config
49
54
  );
50
55
  let response;
@@ -92,7 +97,7 @@ class BitbucketCloudUrlReader {
92
97
  );
93
98
  const archiveResponse = await fetch(
94
99
  downloadUrl,
95
- integration.getBitbucketCloudRequestOptions(this.integration.config)
100
+ await integration.getBitbucketCloudRequestOptions(this.integration.config)
96
101
  );
97
102
  if (!archiveResponse.ok) {
98
103
  const message = `Failed to read tree from ${url}, ${archiveResponse.status} ${archiveResponse.statusText}`;
@@ -170,7 +175,7 @@ class BitbucketCloudUrlReader {
170
175
  const commitsApiUrl = `${this.integration.config.apiBaseUrl}/repositories/${project}/${repoName}/commits/${branch}`;
171
176
  const commitsResponse = await fetch(
172
177
  commitsApiUrl,
173
- integration.getBitbucketCloudRequestOptions(this.integration.config)
178
+ await integration.getBitbucketCloudRequestOptions(this.integration.config)
174
179
  );
175
180
  if (!commitsResponse.ok) {
176
181
  const message = `Failed to retrieve commits from ${commitsApiUrl}, ${commitsResponse.status} ${commitsResponse.statusText}`;
@@ -1 +1 @@
1
- {"version":3,"file":"BitbucketCloudUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport {\n assertError,\n NotFoundError,\n NotModifiedError,\n} from '@backstage/errors';\nimport {\n BitbucketCloudIntegration,\n getBitbucketCloudDefaultBranch,\n getBitbucketCloudDownloadUrl,\n getBitbucketCloudFileFetchUrl,\n getBitbucketCloudRequestOptions,\n ScmIntegrations,\n} from '@backstage/integration';\nimport parseGitUrl from 'git-url-parse';\nimport { trimEnd } from 'lodash';\nimport { Minimatch } from 'minimatch';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files from Bitbucket Cloud.\n *\n * @public\n */\nexport class BitbucketCloudUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n return integrations.bitbucketCloud.list().map(integration => {\n const reader = new BitbucketCloudUrlReader(integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) => url.host === integration.config.host;\n return { reader, predicate };\n });\n };\n\n private readonly integration: BitbucketCloudIntegration;\n private readonly deps: { treeResponseFactory: ReadTreeResponseFactory };\n\n constructor(\n integration: BitbucketCloudIntegration,\n deps: { treeResponseFactory: ReadTreeResponseFactory },\n ) {\n this.integration = integration;\n this.deps = deps;\n const { host, username, appPassword, token } = integration.config;\n\n if (username && !token && !appPassword) {\n throw new Error(\n `Bitbucket Cloud integration for '${host}' has configured a username but is missing a required token or appPassword.`,\n );\n }\n }\n\n async read(url: string): Promise<Buffer> {\n const response = await this.readUrl(url);\n return response.buffer();\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const { etag, lastModifiedAfter, signal } = options ?? {};\n const bitbucketUrl = getBitbucketCloudFileFetchUrl(\n url,\n this.integration.config,\n );\n const requestOptions = getBitbucketCloudRequestOptions(\n this.integration.config,\n );\n\n let response: Response;\n try {\n response = await fetch(bitbucketUrl.toString(), {\n headers: {\n ...requestOptions.headers,\n ...(etag && { 'If-None-Match': etag }),\n ...(lastModifiedAfter && {\n 'If-Modified-Since': lastModifiedAfter.toUTCString(),\n }),\n },\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can be\n // removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n });\n } catch (e) {\n throw new Error(`Unable to read ${url}, ${e}`);\n }\n\n if (response.status === 304) {\n throw new NotModifiedError();\n }\n\n if (response.ok) {\n return ReadUrlResponseFactory.fromResponse(response);\n }\n\n const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`;\n if (response.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const { filepath } = parseGitUrl(url);\n\n const lastCommitShortHash = await this.getLastCommitShortHash(url);\n if (options?.etag && options.etag === lastCommitShortHash) {\n throw new NotModifiedError();\n }\n\n const downloadUrl = await getBitbucketCloudDownloadUrl(\n url,\n this.integration.config,\n );\n const archiveResponse = await fetch(\n downloadUrl,\n getBitbucketCloudRequestOptions(this.integration.config),\n );\n if (!archiveResponse.ok) {\n const message = `Failed to read tree from ${url}, ${archiveResponse.status} ${archiveResponse.statusText}`;\n if (archiveResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n return await this.deps.treeResponseFactory.fromTarArchive({\n response: archiveResponse,\n subpath: filepath,\n etag: lastCommitShortHash,\n filter: options?.filter,\n });\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { filepath } = parseGitUrl(url);\n\n // If it's a direct URL we use readUrl instead\n if (!filepath?.match(/[*?]/)) {\n try {\n const data = await this.readUrl(url, options);\n\n return {\n files: [\n {\n url: url,\n content: data.buffer,\n lastModifiedAt: data.lastModifiedAt,\n },\n ],\n etag: data.etag ?? '',\n };\n } catch (error) {\n assertError(error);\n if (error.name === 'NotFoundError') {\n return {\n files: [],\n etag: '',\n };\n }\n throw error;\n }\n }\n\n const matcher = new Minimatch(filepath);\n\n // TODO(freben): For now, read the entire repo and filter through that. In\n // a future improvement, we could be smart and try to deduce that non-glob\n // prefixes (like for filepaths such as some-prefix/**/a.yaml) can be used\n // to get just that part of the repo.\n const treeUrl = trimEnd(url.replace(filepath, ''), '/');\n\n const tree = await this.readTree(treeUrl, {\n etag: options?.etag,\n filter: path => matcher.match(path),\n });\n const files = await tree.files();\n\n return {\n etag: tree.etag,\n files: files.map(file => ({\n url: this.integration.resolveUrl({\n url: `/${file.path}`,\n base: url,\n }),\n content: file.content,\n lastModifiedAt: file.lastModifiedAt,\n })),\n };\n }\n\n toString() {\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n const { host, username, appPassword, token } = this.integration.config;\n const authed = Boolean(username && (token ?? appPassword));\n return `bitbucketCloud{host=${host},authed=${authed}}`;\n }\n\n private async getLastCommitShortHash(url: string): Promise<string> {\n const { name: repoName, owner: project, ref } = parseGitUrl(url);\n\n let branch = ref;\n if (!branch) {\n branch = await getBitbucketCloudDefaultBranch(\n url,\n this.integration.config,\n );\n }\n\n const commitsApiUrl = `${this.integration.config.apiBaseUrl}/repositories/${project}/${repoName}/commits/${branch}`;\n\n const commitsResponse = await fetch(\n commitsApiUrl,\n getBitbucketCloudRequestOptions(this.integration.config),\n );\n if (!commitsResponse.ok) {\n const message = `Failed to retrieve commits from ${commitsApiUrl}, ${commitsResponse.status} ${commitsResponse.statusText}`;\n if (commitsResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n const commits = await commitsResponse.json();\n if (\n commits &&\n commits.values &&\n commits.values.length > 0 &&\n commits.values[0].hash\n ) {\n return commits.values[0].hash.substring(0, 12);\n }\n\n throw new Error(`Failed to read response from ${commitsApiUrl}`);\n }\n}\n"],"names":["ScmIntegrations","getBitbucketCloudFileFetchUrl","getBitbucketCloudRequestOptions","NotModifiedError","ReadUrlResponseFactory","NotFoundError","parseGitUrl","getBitbucketCloudDownloadUrl","assertError","Minimatch","trimEnd","getBitbucketCloudDefaultBranch"],"mappings":"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"}
1
+ {"version":3,"file":"BitbucketCloudUrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/BitbucketCloudUrlReader.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport {\n assertError,\n NotFoundError,\n NotModifiedError,\n} from '@backstage/errors';\nimport {\n BitbucketCloudIntegration,\n getBitbucketCloudDefaultBranch,\n getBitbucketCloudDownloadUrl,\n getBitbucketCloudFileFetchUrl,\n getBitbucketCloudRequestOptions,\n ScmIntegrations,\n} from '@backstage/integration';\nimport parseGitUrl from 'git-url-parse';\nimport { trimEnd } from 'lodash';\nimport { Minimatch } from 'minimatch';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files from Bitbucket Cloud.\n *\n * @public\n */\nexport class BitbucketCloudUrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n return integrations.bitbucketCloud.list().map(integration => {\n const reader = new BitbucketCloudUrlReader(integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) => url.host === integration.config.host;\n return { reader, predicate };\n });\n };\n\n private readonly integration: BitbucketCloudIntegration;\n private readonly deps: { treeResponseFactory: ReadTreeResponseFactory };\n\n constructor(\n integration: BitbucketCloudIntegration,\n deps: { treeResponseFactory: ReadTreeResponseFactory },\n ) {\n this.integration = integration;\n this.deps = deps;\n const { host, username, appPassword, token, clientId, clientSecret } =\n integration.config;\n\n // Validate: OAuth requires both clientId and clientSecret\n if ((clientId && !clientSecret) || (clientSecret && !clientId)) {\n throw new Error(\n `Bitbucket Cloud integration has incomplete OAuth configuration. Both clientId and clientSecret are required.`,\n );\n }\n\n if (username && !token && !appPassword) {\n throw new Error(\n `Bitbucket Cloud integration for '${host}' has configured a username but is missing a required token or appPassword.`,\n );\n }\n }\n\n async read(url: string): Promise<Buffer> {\n const response = await this.readUrl(url);\n return response.buffer();\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const { etag, lastModifiedAfter, signal } = options ?? {};\n const bitbucketUrl = getBitbucketCloudFileFetchUrl(\n url,\n this.integration.config,\n );\n const requestOptions = await getBitbucketCloudRequestOptions(\n this.integration.config,\n );\n\n let response: Response;\n try {\n response = await fetch(bitbucketUrl.toString(), {\n headers: {\n ...requestOptions.headers,\n ...(etag && { 'If-None-Match': etag }),\n ...(lastModifiedAfter && {\n 'If-Modified-Since': lastModifiedAfter.toUTCString(),\n }),\n },\n // TODO(freben): The signal cast is there because pre-3.x versions of\n // node-fetch have a very slightly deviating AbortSignal type signature.\n // The difference does not affect us in practice however. The cast can be\n // removed after we support ESM for CLI dependencies and migrate to\n // version 3 of node-fetch.\n // https://github.com/backstage/backstage/issues/8242\n ...(signal && { signal: signal as any }),\n });\n } catch (e) {\n throw new Error(`Unable to read ${url}, ${e}`);\n }\n\n if (response.status === 304) {\n throw new NotModifiedError();\n }\n\n if (response.ok) {\n return ReadUrlResponseFactory.fromResponse(response);\n }\n\n const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`;\n if (response.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n const { filepath } = parseGitUrl(url);\n\n const lastCommitShortHash = await this.getLastCommitShortHash(url);\n if (options?.etag && options.etag === lastCommitShortHash) {\n throw new NotModifiedError();\n }\n\n const downloadUrl = await getBitbucketCloudDownloadUrl(\n url,\n this.integration.config,\n );\n const archiveResponse = await fetch(\n downloadUrl,\n await getBitbucketCloudRequestOptions(this.integration.config),\n );\n if (!archiveResponse.ok) {\n const message = `Failed to read tree from ${url}, ${archiveResponse.status} ${archiveResponse.statusText}`;\n if (archiveResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n return await this.deps.treeResponseFactory.fromTarArchive({\n response: archiveResponse,\n subpath: filepath,\n etag: lastCommitShortHash,\n filter: options?.filter,\n });\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { filepath } = parseGitUrl(url);\n\n // If it's a direct URL we use readUrl instead\n if (!filepath?.match(/[*?]/)) {\n try {\n const data = await this.readUrl(url, options);\n\n return {\n files: [\n {\n url: url,\n content: data.buffer,\n lastModifiedAt: data.lastModifiedAt,\n },\n ],\n etag: data.etag ?? '',\n };\n } catch (error) {\n assertError(error);\n if (error.name === 'NotFoundError') {\n return {\n files: [],\n etag: '',\n };\n }\n throw error;\n }\n }\n\n const matcher = new Minimatch(filepath);\n\n // TODO(freben): For now, read the entire repo and filter through that. In\n // a future improvement, we could be smart and try to deduce that non-glob\n // prefixes (like for filepaths such as some-prefix/**/a.yaml) can be used\n // to get just that part of the repo.\n const treeUrl = trimEnd(url.replace(filepath, ''), '/');\n\n const tree = await this.readTree(treeUrl, {\n etag: options?.etag,\n filter: path => matcher.match(path),\n });\n const files = await tree.files();\n\n return {\n etag: tree.etag,\n files: files.map(file => ({\n url: this.integration.resolveUrl({\n url: `/${file.path}`,\n base: url,\n }),\n content: file.content,\n lastModifiedAt: file.lastModifiedAt,\n })),\n };\n }\n\n toString() {\n // TODO: appPassword can be removed once fully\n // deprecated by BitBucket on 9th June 2026.\n const { host, username, appPassword, token } = this.integration.config;\n const authed = Boolean(username && (token ?? appPassword));\n return `bitbucketCloud{host=${host},authed=${authed}}`;\n }\n\n private async getLastCommitShortHash(url: string): Promise<string> {\n const { name: repoName, owner: project, ref } = parseGitUrl(url);\n\n let branch = ref;\n if (!branch) {\n branch = await getBitbucketCloudDefaultBranch(\n url,\n this.integration.config,\n );\n }\n\n const commitsApiUrl = `${this.integration.config.apiBaseUrl}/repositories/${project}/${repoName}/commits/${branch}`;\n\n const commitsResponse = await fetch(\n commitsApiUrl,\n await getBitbucketCloudRequestOptions(this.integration.config),\n );\n if (!commitsResponse.ok) {\n const message = `Failed to retrieve commits from ${commitsApiUrl}, ${commitsResponse.status} ${commitsResponse.statusText}`;\n if (commitsResponse.status === 404) {\n throw new NotFoundError(message);\n }\n throw new Error(message);\n }\n\n const commits = await commitsResponse.json();\n if (\n commits &&\n commits.values &&\n commits.values.length > 0 &&\n commits.values[0].hash\n ) {\n return commits.values[0].hash.substring(0, 12);\n }\n\n throw new Error(`Failed to read response from ${commitsApiUrl}`);\n }\n}\n"],"names":["ScmIntegrations","getBitbucketCloudFileFetchUrl","getBitbucketCloudRequestOptions","NotModifiedError","ReadUrlResponseFactory","NotFoundError","parseGitUrl","getBitbucketCloudDownloadUrl","assertError","Minimatch","trimEnd","getBitbucketCloudDefaultBranch"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = "0.14.0-next.1";
5
+ var version = "0.14.0";
6
6
  var packageinfo = {
7
7
  version: version};
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-defaults",
3
- "version": "0.14.0-next.1",
3
+ "version": "0.14.0",
4
4
  "description": "Backend defaults used by Backstage backend apps",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -216,19 +216,19 @@
216
216
  "@aws-sdk/credential-providers": "^3.350.0",
217
217
  "@aws-sdk/types": "^3.347.0",
218
218
  "@azure/storage-blob": "^12.5.0",
219
- "@backstage/backend-app-api": "1.4.0-next.1",
220
- "@backstage/backend-dev-utils": "0.1.6-next.0",
221
- "@backstage/backend-plugin-api": "1.6.0-next.1",
222
- "@backstage/cli-node": "0.2.16-next.1",
223
- "@backstage/config": "1.3.6",
224
- "@backstage/config-loader": "1.10.7-next.1",
225
- "@backstage/errors": "1.2.7",
226
- "@backstage/integration": "1.18.3-next.1",
227
- "@backstage/integration-aws-node": "0.1.19",
228
- "@backstage/plugin-auth-node": "0.6.10-next.1",
229
- "@backstage/plugin-events-node": "0.4.18-next.1",
230
- "@backstage/plugin-permission-node": "0.10.7-next.1",
231
- "@backstage/types": "1.2.2",
219
+ "@backstage/backend-app-api": "^1.4.0",
220
+ "@backstage/backend-dev-utils": "^0.1.6",
221
+ "@backstage/backend-plugin-api": "^1.6.0",
222
+ "@backstage/cli-node": "^0.2.16",
223
+ "@backstage/config": "^1.3.6",
224
+ "@backstage/config-loader": "^1.10.7",
225
+ "@backstage/errors": "^1.2.7",
226
+ "@backstage/integration": "^1.19.0",
227
+ "@backstage/integration-aws-node": "^0.1.19",
228
+ "@backstage/plugin-auth-node": "^0.6.10",
229
+ "@backstage/plugin-events-node": "^0.4.18",
230
+ "@backstage/plugin-permission-node": "^0.10.7",
231
+ "@backstage/types": "^1.2.2",
232
232
  "@google-cloud/storage": "^7.0.0",
233
233
  "@keyv/memcache": "^2.0.1",
234
234
  "@keyv/redis": "^4.0.1",
@@ -283,9 +283,9 @@
283
283
  },
284
284
  "devDependencies": {
285
285
  "@aws-sdk/util-stream-node": "^3.350.0",
286
- "@backstage/backend-plugin-api": "1.6.0-next.1",
287
- "@backstage/backend-test-utils": "1.10.2-next.1",
288
- "@backstage/cli": "0.35.0-next.2",
286
+ "@backstage/backend-plugin-api": "^1.6.0",
287
+ "@backstage/backend-test-utils": "^1.10.2",
288
+ "@backstage/cli": "^0.35.0",
289
289
  "@google-cloud/cloud-sql-connector": "^1.4.0",
290
290
  "@types/archiver": "^7.0.0",
291
291
  "@types/base64-stream": "^1.0.2",