@backstage/config-loader 1.10.6 → 1.10.7-next.1

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,26 @@
1
1
  # @backstage/config-loader
2
2
 
3
+ ## 1.10.7-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 741c47a: Updated dependency `typescript-json-schema` to `^0.67.0`.
8
+ - Updated dependencies
9
+ - @backstage/cli-common@0.1.16-next.2
10
+ - @backstage/config@1.3.6
11
+ - @backstage/errors@1.2.7
12
+ - @backstage/types@1.2.2
13
+
14
+ ## 1.10.7-next.0
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+ - @backstage/cli-common@0.1.16-next.0
20
+ - @backstage/config@1.3.6
21
+ - @backstage/errors@1.2.7
22
+ - @backstage/types@1.2.2
23
+
3
24
  ## 1.10.6
4
25
 
5
26
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -635,4 +635,5 @@ declare class StaticConfigSource implements ConfigSource {
635
635
  toString(): string;
636
636
  }
637
637
 
638
- export { type AsyncConfigSourceGenerator, type BaseConfigSourcesOptions, type ClosableConfig, type ConfigSchema, type ConfigSchemaProcessingOptions, type ConfigSource, type ConfigSourceData, type ConfigSourceTarget, ConfigSources, type ConfigSourcesDefaultForTargetsOptions, type ConfigSourcesDefaultOptions, type ConfigTarget, type ConfigVisibility, EnvConfigSource, type EnvConfigSourceOptions, type SubstitutionFunc as EnvFunc, FileConfigSource, type FileConfigSourceOptions, type LoadConfigOptions, type LoadConfigOptionsRemote, type LoadConfigOptionsWatch, type LoadConfigResult, type LoadConfigSchemaOptions, MutableConfigSource, type MutableConfigSourceOptions, type Parser, type ReadConfigDataOptions, RemoteConfigSource, type RemoteConfigSourceOptions, StaticConfigSource, type StaticConfigSourceOptions, type TransformFunc, loadConfig, loadConfigSchema, mergeConfigSchemas, readEnvConfig };
638
+ export { ConfigSources, EnvConfigSource, FileConfigSource, MutableConfigSource, RemoteConfigSource, StaticConfigSource, loadConfig, loadConfigSchema, mergeConfigSchemas, readEnvConfig };
639
+ export type { AsyncConfigSourceGenerator, BaseConfigSourcesOptions, ClosableConfig, ConfigSchema, ConfigSchemaProcessingOptions, ConfigSource, ConfigSourceData, ConfigSourceTarget, ConfigSourcesDefaultForTargetsOptions, ConfigSourcesDefaultOptions, ConfigTarget, ConfigVisibility, EnvConfigSourceOptions, SubstitutionFunc as EnvFunc, FileConfigSourceOptions, LoadConfigOptions, LoadConfigOptionsRemote, LoadConfigOptionsWatch, LoadConfigResult, LoadConfigSchemaOptions, MutableConfigSourceOptions, Parser, ReadConfigDataOptions, RemoteConfigSourceOptions, StaticConfigSourceOptions, TransformFunc };
@@ -13,7 +13,7 @@ var Ajv__default = /*#__PURE__*/_interopDefaultCompat(Ajv);
13
13
  var mergeAllOf__default = /*#__PURE__*/_interopDefaultCompat(mergeAllOf);
14
14
  var traverse__default = /*#__PURE__*/_interopDefaultCompat(traverse);
15
15
 
16
- const inheritedVisibility = Symbol("inherited-visibility");
16
+ const inheritedVisibility = /* @__PURE__ */ Symbol("inherited-visibility");
17
17
  function compileConfigSchemas(schemas, options) {
18
18
  const visibilityByDataPath = /* @__PURE__ */ new Map();
19
19
  const deepVisibilityByDataPath = /* @__PURE__ */ new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"compile.cjs.js","sources":["../../src/schema/compile.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 Ajv from 'ajv';\nimport { JSONSchema7 as JSONSchema } from 'json-schema';\nimport mergeAllOf, { Resolvers } from 'json-schema-merge-allof';\nimport traverse from 'json-schema-traverse';\nimport { ConfigReader } from '@backstage/config';\nimport {\n ConfigSchemaPackageEntry,\n ValidationFunc,\n CONFIG_VISIBILITIES,\n ConfigVisibility,\n} from './types';\nimport { SchemaObject } from 'json-schema-traverse';\nimport { normalizeAjvPath } from './utils';\n\n// Used to keep track of the internal deepVisibility inherited through the schema.\nconst inheritedVisibility = Symbol('inherited-visibility');\n\n/**\n * This takes a collection of Backstage configuration schemas from various\n * sources and compiles them down into a single schema validation function.\n *\n * It also handles the implementation of the custom \"visibility\" keyword used\n * to specify the scope of different config paths.\n */\nexport function compileConfigSchemas(\n schemas: ConfigSchemaPackageEntry[],\n options?: {\n noUndeclaredProperties?: boolean;\n },\n): ValidationFunc {\n // The ajv instance below is stateful and doesn't really allow for additional\n // output during validation. We work around this by having this extra piece\n // of state that we reset before each validation.\n const visibilityByDataPath = new Map<string, ConfigVisibility>();\n const deepVisibilityByDataPath = new Map<string, ConfigVisibility>();\n const deprecationByDataPath = new Map<string, string>();\n\n const ajv = new Ajv({\n allErrors: true,\n allowUnionTypes: true,\n coerceTypes: true,\n schemas: {\n 'https://backstage.io/schema/config-v1': true,\n },\n })\n .addKeyword({\n keyword: 'visibility',\n metaSchema: {\n type: 'string',\n enum: CONFIG_VISIBILITIES,\n },\n compile(visibility: ConfigVisibility) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility && visibility !== 'backend') {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n visibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .addKeyword({\n keyword: 'deepVisibility',\n metaSchema: {\n type: 'string',\n /**\n * Disallow 'backend' deepVisibility to prevent cases of permission escaping.\n *\n * Something like:\n * - deepVisibility secret -> backend -> frontend.\n * - deepVisibility secret -> backend -> visibility frontend.\n */\n enum: ['frontend', 'secret'],\n },\n compile(visibility: 'frontend' | 'secret') {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility) {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n deepVisibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .removeKeyword('deprecated') // remove `deprecated` keyword so that we can implement our own compiler\n .addKeyword({\n keyword: 'deprecated',\n metaSchema: { type: 'string' },\n compile(deprecationDescription: string) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n const normalizedPath = normalizeAjvPath(context.instancePath);\n // create mapping of deprecation description and data path of property\n deprecationByDataPath.set(normalizedPath, deprecationDescription);\n return true;\n };\n },\n });\n\n for (const schema of schemas) {\n try {\n ajv.compile(schema.value);\n } catch (error) {\n throw new Error(`Schema at ${schema.path} is invalid, ${error}`);\n }\n }\n\n const merged = mergeConfigSchemas(schemas.map(_ => _.value));\n\n traverse(\n merged,\n (\n schema: SchemaObject & { [inheritedVisibility]?: ConfigVisibility },\n jsonPtr: string,\n _1: any,\n _2: any,\n _3?: any,\n parentSchema?: SchemaObject & {\n [inheritedVisibility]?: ConfigVisibility;\n },\n ) => {\n // Inherit parent deepVisibility if we don't define one ourselves.\n // This is used to detect situations where conflicting deep visibilities are set.\n schema[inheritedVisibility] ??=\n schema?.deepVisibility ?? parentSchema?.[inheritedVisibility];\n\n if (schema[inheritedVisibility]) {\n // Validate that we're not trying to set a conflicting visibility. This can be done\n // either by setting a conflicting visibility directly or deep visibility\n const values = [\n schema.visibility,\n schema[inheritedVisibility],\n parentSchema?.[inheritedVisibility],\n ];\n const hasFrontend = values.some(e => e === 'frontend');\n const hasSecret = values.some(e => e === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${jsonPtr}`,\n );\n }\n }\n\n if (options?.noUndeclaredProperties) {\n /**\n * The `additionalProperties` key can only be applied to `type: object` in the JSON\n * schema.\n */\n if (schema?.type === 'object') {\n schema.additionalProperties ||= false;\n }\n }\n },\n );\n\n const validate = ajv.compile(merged);\n\n const visibilityBySchemaPath = new Map<string, ConfigVisibility>();\n traverse(merged, (schema, path) => {\n if (schema.visibility && schema.visibility !== 'backend') {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.visibility);\n }\n if (schema.deepVisibility) {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.deepVisibility);\n }\n });\n\n return configs => {\n const config = ConfigReader.fromConfigs(configs).getOptional();\n\n visibilityByDataPath.clear();\n deepVisibilityByDataPath.clear();\n\n const valid = validate(config);\n\n if (!valid) {\n return {\n errors: validate.errors ?? [],\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n }\n\n return {\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n };\n}\n\n/**\n * Given a list of configuration schemas from packages, merge them\n * into a single json schema.\n *\n * @public\n */\nexport function mergeConfigSchemas(schemas: JSONSchema[]): JSONSchema {\n const merged = mergeAllOf(\n { allOf: schemas },\n {\n // JSONSchema is typically subtractive, as in it always reduces the set of allowed\n // inputs through constraints. This changes the object property merging to be additive\n // rather than subtractive.\n ignoreAdditionalProperties: true,\n resolvers: {\n // This ensures that the visibilities across different schemas are sound, and\n // selects the most specific visibility for each path.\n visibility(values: string[], path: string[]) {\n const hasFrontend = values.some(_ => _ === 'frontend');\n const hasSecret = values.some(_ => _ === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${path.join(\n '/',\n )}`,\n );\n } else if (hasFrontend) {\n return 'frontend';\n } else if (hasSecret) {\n return 'secret';\n }\n\n return 'backend';\n },\n } as Partial<Resolvers<JSONSchema>>,\n },\n );\n return merged;\n}\n"],"names":["Ajv","CONFIG_VISIBILITIES","normalizeAjvPath","traverse","config","ConfigReader","mergeAllOf"],"mappings":"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"}
1
+ {"version":3,"file":"compile.cjs.js","sources":["../../src/schema/compile.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 Ajv from 'ajv';\nimport { JSONSchema7 as JSONSchema } from 'json-schema';\nimport mergeAllOf, { Resolvers } from 'json-schema-merge-allof';\nimport traverse from 'json-schema-traverse';\nimport { ConfigReader } from '@backstage/config';\nimport {\n ConfigSchemaPackageEntry,\n ValidationFunc,\n CONFIG_VISIBILITIES,\n ConfigVisibility,\n} from './types';\nimport { SchemaObject } from 'json-schema-traverse';\nimport { normalizeAjvPath } from './utils';\n\n// Used to keep track of the internal deepVisibility inherited through the schema.\nconst inheritedVisibility = Symbol('inherited-visibility');\n\n/**\n * This takes a collection of Backstage configuration schemas from various\n * sources and compiles them down into a single schema validation function.\n *\n * It also handles the implementation of the custom \"visibility\" keyword used\n * to specify the scope of different config paths.\n */\nexport function compileConfigSchemas(\n schemas: ConfigSchemaPackageEntry[],\n options?: {\n noUndeclaredProperties?: boolean;\n },\n): ValidationFunc {\n // The ajv instance below is stateful and doesn't really allow for additional\n // output during validation. We work around this by having this extra piece\n // of state that we reset before each validation.\n const visibilityByDataPath = new Map<string, ConfigVisibility>();\n const deepVisibilityByDataPath = new Map<string, ConfigVisibility>();\n const deprecationByDataPath = new Map<string, string>();\n\n const ajv = new Ajv({\n allErrors: true,\n allowUnionTypes: true,\n coerceTypes: true,\n schemas: {\n 'https://backstage.io/schema/config-v1': true,\n },\n })\n .addKeyword({\n keyword: 'visibility',\n metaSchema: {\n type: 'string',\n enum: CONFIG_VISIBILITIES,\n },\n compile(visibility: ConfigVisibility) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility && visibility !== 'backend') {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n visibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .addKeyword({\n keyword: 'deepVisibility',\n metaSchema: {\n type: 'string',\n /**\n * Disallow 'backend' deepVisibility to prevent cases of permission escaping.\n *\n * Something like:\n * - deepVisibility secret -> backend -> frontend.\n * - deepVisibility secret -> backend -> visibility frontend.\n */\n enum: ['frontend', 'secret'],\n },\n compile(visibility: 'frontend' | 'secret') {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility) {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n deepVisibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .removeKeyword('deprecated') // remove `deprecated` keyword so that we can implement our own compiler\n .addKeyword({\n keyword: 'deprecated',\n metaSchema: { type: 'string' },\n compile(deprecationDescription: string) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n const normalizedPath = normalizeAjvPath(context.instancePath);\n // create mapping of deprecation description and data path of property\n deprecationByDataPath.set(normalizedPath, deprecationDescription);\n return true;\n };\n },\n });\n\n for (const schema of schemas) {\n try {\n ajv.compile(schema.value);\n } catch (error) {\n throw new Error(`Schema at ${schema.path} is invalid, ${error}`);\n }\n }\n\n const merged = mergeConfigSchemas(schemas.map(_ => _.value));\n\n traverse(\n merged,\n (\n schema: SchemaObject & { [inheritedVisibility]?: ConfigVisibility },\n jsonPtr: string,\n _1: any,\n _2: any,\n _3?: any,\n parentSchema?: SchemaObject & {\n [inheritedVisibility]?: ConfigVisibility;\n },\n ) => {\n // Inherit parent deepVisibility if we don't define one ourselves.\n // This is used to detect situations where conflicting deep visibilities are set.\n schema[inheritedVisibility] ??=\n schema?.deepVisibility ?? parentSchema?.[inheritedVisibility];\n\n if (schema[inheritedVisibility]) {\n // Validate that we're not trying to set a conflicting visibility. This can be done\n // either by setting a conflicting visibility directly or deep visibility\n const values = [\n schema.visibility,\n schema[inheritedVisibility],\n parentSchema?.[inheritedVisibility],\n ];\n const hasFrontend = values.some(e => e === 'frontend');\n const hasSecret = values.some(e => e === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${jsonPtr}`,\n );\n }\n }\n\n if (options?.noUndeclaredProperties) {\n /**\n * The `additionalProperties` key can only be applied to `type: object` in the JSON\n * schema.\n */\n if (schema?.type === 'object') {\n schema.additionalProperties ||= false;\n }\n }\n },\n );\n\n const validate = ajv.compile(merged);\n\n const visibilityBySchemaPath = new Map<string, ConfigVisibility>();\n traverse(merged, (schema, path) => {\n if (schema.visibility && schema.visibility !== 'backend') {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.visibility);\n }\n if (schema.deepVisibility) {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.deepVisibility);\n }\n });\n\n return configs => {\n const config = ConfigReader.fromConfigs(configs).getOptional();\n\n visibilityByDataPath.clear();\n deepVisibilityByDataPath.clear();\n\n const valid = validate(config);\n\n if (!valid) {\n return {\n errors: validate.errors ?? [],\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n }\n\n return {\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n };\n}\n\n/**\n * Given a list of configuration schemas from packages, merge them\n * into a single json schema.\n *\n * @public\n */\nexport function mergeConfigSchemas(schemas: JSONSchema[]): JSONSchema {\n const merged = mergeAllOf(\n { allOf: schemas },\n {\n // JSONSchema is typically subtractive, as in it always reduces the set of allowed\n // inputs through constraints. This changes the object property merging to be additive\n // rather than subtractive.\n ignoreAdditionalProperties: true,\n resolvers: {\n // This ensures that the visibilities across different schemas are sound, and\n // selects the most specific visibility for each path.\n visibility(values: string[], path: string[]) {\n const hasFrontend = values.some(_ => _ === 'frontend');\n const hasSecret = values.some(_ => _ === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${path.join(\n '/',\n )}`,\n );\n } else if (hasFrontend) {\n return 'frontend';\n } else if (hasSecret) {\n return 'secret';\n }\n\n return 'backend';\n },\n } as Partial<Resolvers<JSONSchema>>,\n },\n );\n return merged;\n}\n"],"names":["Ajv","CONFIG_VISIBILITIES","normalizeAjvPath","traverse","config","ConfigReader","mergeAllOf"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const sourcesSymbol = Symbol.for(
3
+ const sourcesSymbol = /* @__PURE__ */ Symbol.for(
4
4
  "@backstage/config-loader#MergedConfigSource.sources"
5
5
  );
6
6
  class MergedConfigSource {
@@ -1 +1 @@
1
- {"version":3,"file":"MergedConfigSource.cjs.js","sources":["../../src/sources/MergedConfigSource.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AsyncConfigSourceGenerator,\n ConfigSource,\n ConfigSourceData,\n ReadConfigDataOptions,\n} from './types';\n\nconst sourcesSymbol = Symbol.for(\n '@backstage/config-loader#MergedConfigSource.sources',\n);\n\n/** @internal */\nexport class MergedConfigSource implements ConfigSource {\n // An optimization to flatten nested merged sources to avid unnecessary microtasks\n static #flattenSources(sources: ConfigSource[]): ConfigSource[] {\n return sources.flatMap(source => {\n if (\n sourcesSymbol in source &&\n Array.isArray((source as any)[sourcesSymbol])\n ) {\n return this.#flattenSources(\n (source as any)[sourcesSymbol] as ConfigSource[],\n );\n }\n return source;\n });\n }\n\n static from(sources: ConfigSource[]): ConfigSource {\n return new MergedConfigSource(this.#flattenSources(sources));\n }\n\n [sourcesSymbol]: ConfigSource[];\n\n private constructor(private readonly sources: ConfigSource[]) {\n this[sourcesSymbol] = this.sources;\n }\n\n async *readConfigData(\n options?: ReadConfigDataOptions,\n ): AsyncConfigSourceGenerator {\n const its = this.sources.map(source => source.readConfigData(options));\n const initialResults = await Promise.all(its.map(it => it.next()));\n const configs = initialResults.map((result, i) => {\n if (result.done) {\n throw new Error(\n `Config source ${String(this.sources[i])} returned no data`,\n );\n }\n return result.value.configs;\n });\n\n yield { configs: configs.flat(1) };\n\n const results: Array<\n | Promise<\n readonly [\n number,\n IteratorResult<{ configs: ConfigSourceData[] }, void>,\n ]\n >\n | undefined\n > = its.map((it, i) => nextWithIndex(it, i));\n\n while (results.some(Boolean)) {\n try {\n const [i, result] = (await Promise.race(results.filter(Boolean)))!;\n if (result.done) {\n results[i] = undefined;\n } else {\n results[i] = nextWithIndex(its[i], i);\n configs[i] = result.value.configs;\n yield { configs: configs.flat(1) };\n }\n } catch (error) {\n const source = this.sources[error.index];\n if (source) {\n throw new Error(`Config source ${String(source)} failed: ${error}`);\n }\n throw error;\n }\n }\n }\n\n toString() {\n return `MergedConfigSource{${this.sources.map(String).join(', ')}}`;\n }\n}\n\n// Helper to wait for the next value of the iterator, while decorating the value\n// or error with the index of the iterator.\nfunction nextWithIndex<T>(\n iterator: AsyncIterator<T, void, void>,\n index: number,\n): Promise<readonly [index: number, result: IteratorResult<T, void>]> {\n return iterator.next().then(\n r => [index, r] as const,\n e => {\n throw Object.assign(e, { index });\n },\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MergedConfigSource.cjs.js","sources":["../../src/sources/MergedConfigSource.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AsyncConfigSourceGenerator,\n ConfigSource,\n ConfigSourceData,\n ReadConfigDataOptions,\n} from './types';\n\nconst sourcesSymbol = Symbol.for(\n '@backstage/config-loader#MergedConfigSource.sources',\n);\n\n/** @internal */\nexport class MergedConfigSource implements ConfigSource {\n // An optimization to flatten nested merged sources to avid unnecessary microtasks\n static #flattenSources(sources: ConfigSource[]): ConfigSource[] {\n return sources.flatMap(source => {\n if (\n sourcesSymbol in source &&\n Array.isArray((source as any)[sourcesSymbol])\n ) {\n return this.#flattenSources(\n (source as any)[sourcesSymbol] as ConfigSource[],\n );\n }\n return source;\n });\n }\n\n static from(sources: ConfigSource[]): ConfigSource {\n return new MergedConfigSource(this.#flattenSources(sources));\n }\n\n [sourcesSymbol]: ConfigSource[];\n\n private constructor(private readonly sources: ConfigSource[]) {\n this[sourcesSymbol] = this.sources;\n }\n\n async *readConfigData(\n options?: ReadConfigDataOptions,\n ): AsyncConfigSourceGenerator {\n const its = this.sources.map(source => source.readConfigData(options));\n const initialResults = await Promise.all(its.map(it => it.next()));\n const configs = initialResults.map((result, i) => {\n if (result.done) {\n throw new Error(\n `Config source ${String(this.sources[i])} returned no data`,\n );\n }\n return result.value.configs;\n });\n\n yield { configs: configs.flat(1) };\n\n const results: Array<\n | Promise<\n readonly [\n number,\n IteratorResult<{ configs: ConfigSourceData[] }, void>,\n ]\n >\n | undefined\n > = its.map((it, i) => nextWithIndex(it, i));\n\n while (results.some(Boolean)) {\n try {\n const [i, result] = (await Promise.race(results.filter(Boolean)))!;\n if (result.done) {\n results[i] = undefined;\n } else {\n results[i] = nextWithIndex(its[i], i);\n configs[i] = result.value.configs;\n yield { configs: configs.flat(1) };\n }\n } catch (error) {\n const source = this.sources[error.index];\n if (source) {\n throw new Error(`Config source ${String(source)} failed: ${error}`);\n }\n throw error;\n }\n }\n }\n\n toString() {\n return `MergedConfigSource{${this.sources.map(String).join(', ')}}`;\n }\n}\n\n// Helper to wait for the next value of the iterator, while decorating the value\n// or error with the index of the iterator.\nfunction nextWithIndex<T>(\n iterator: AsyncIterator<T, void, void>,\n index: number,\n): Promise<readonly [index: number, result: IteratorResult<T, void>]> {\n return iterator.next().then(\n r => [index, r] as const,\n e => {\n throw Object.assign(e, { index });\n },\n );\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/config-loader",
3
- "version": "1.10.6",
3
+ "version": "1.10.7-next.1",
4
4
  "description": "Config loading functionality used by Backstage backend, and CLI",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -36,10 +36,10 @@
36
36
  "test": "backstage-cli package test"
37
37
  },
38
38
  "dependencies": {
39
- "@backstage/cli-common": "^0.1.15",
40
- "@backstage/config": "^1.3.6",
41
- "@backstage/errors": "^1.2.7",
42
- "@backstage/types": "^1.2.2",
39
+ "@backstage/cli-common": "0.1.16-next.2",
40
+ "@backstage/config": "1.3.6",
41
+ "@backstage/errors": "1.2.7",
42
+ "@backstage/types": "1.2.2",
43
43
  "@types/json-schema": "^7.0.6",
44
44
  "ajv": "^8.10.0",
45
45
  "chokidar": "^3.5.2",
@@ -49,12 +49,12 @@
49
49
  "json-schema-traverse": "^1.0.0",
50
50
  "lodash": "^4.17.21",
51
51
  "minimist": "^1.2.5",
52
- "typescript-json-schema": "^0.65.0",
52
+ "typescript-json-schema": "^0.67.0",
53
53
  "yaml": "^2.0.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@backstage/backend-test-utils": "^1.10.0",
57
- "@backstage/cli": "^0.34.5",
56
+ "@backstage/backend-test-utils": "1.10.2-next.1",
57
+ "@backstage/cli": "0.35.0-next.2",
58
58
  "@types/json-schema-merge-allof": "^0.6.0",
59
59
  "@types/minimist": "^1.2.5",
60
60
  "msw": "^1.0.0",