@backstage/config-loader 1.10.9 → 1.10.10-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,25 @@
1
1
  # @backstage/config-loader
2
2
 
3
+ ## 1.10.10-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 482ceed: Migrated from `assertError` to `toError` for error handling.
8
+ - Updated dependencies
9
+ - @backstage/errors@1.3.0-next.0
10
+ - @backstage/cli-common@0.2.1-next.1
11
+ - @backstage/config@1.3.7-next.0
12
+
13
+ ## 1.10.10-next.0
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies
18
+ - @backstage/cli-common@0.2.1-next.0
19
+ - @backstage/config@1.3.6
20
+ - @backstage/errors@1.2.7
21
+ - @backstage/types@1.2.2
22
+
3
23
  ## 1.10.9
4
24
 
5
25
  ### Patch Changes
@@ -170,9 +170,9 @@ async function compileTsSchemas(entries) {
170
170
  );
171
171
  }
172
172
  } catch (error) {
173
- errors.assertError(error);
174
- if (error.message !== "type Config not found") {
175
- throw error;
173
+ const err = errors.toError(error);
174
+ if (err.message !== "type Config not found") {
175
+ throw err;
176
176
  }
177
177
  }
178
178
  if (!value) {
@@ -1 +1 @@
1
- {"version":3,"file":"collect.cjs.js","sources":["../../src/schema/collect.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport { EOL } from 'node:os';\nimport {\n resolve as resolvePath,\n relative as relativePath,\n dirname,\n sep,\n} from 'node:path';\nimport { ConfigSchemaPackageEntry } from './types';\nimport { JsonObject } from '@backstage/types';\nimport { assertError } from '@backstage/errors';\n\ntype Item = {\n name?: string;\n parentPath?: string;\n packagePath?: string;\n};\n\nconst req =\n typeof __non_webpack_require__ === 'undefined'\n ? require\n : __non_webpack_require__;\n\n/**\n * Exported for test mocking. Jest 30's module resolver has issues with\n * nested node_modules, requiring tests to use an alternative resolution strategy.\n * @internal\n */\nexport const internal = {\n resolvePackagePath(name: string, options?: { paths: string[] }): string {\n return req.resolve(name, options);\n },\n};\n\n/**\n * This collects all known config schemas across all dependencies of the app.\n */\nexport async function collectConfigSchemas(\n packageNames: string[],\n packagePaths: string[],\n): Promise<ConfigSchemaPackageEntry[]> {\n const schemas = new Array<ConfigSchemaPackageEntry>();\n const tsSchemaPaths = new Array<{ packageName: string; path: string }>();\n const visitedPackageVersions = new Map<string, Set<string>>(); // pkgName: [versions...]\n\n const currentDir = await fs.realpath(process.cwd());\n\n async function processItem(item: Item) {\n let pkgPath = item.packagePath;\n\n if (pkgPath) {\n const pkgExists = await fs.pathExists(pkgPath);\n if (!pkgExists) {\n return;\n }\n } else if (item.name) {\n const { name, parentPath } = item;\n\n try {\n pkgPath = internal.resolvePackagePath(\n `${name}/package.json`,\n parentPath ? { paths: [parentPath] } : undefined,\n );\n } catch {\n // We can somewhat safely ignore packages that don't export package.json,\n // as they are likely not part of the Backstage ecosystem anyway.\n }\n }\n if (!pkgPath) {\n return;\n }\n\n const pkg = await fs.readJson(pkgPath);\n\n // Ensures that we only process the same version of each package once.\n let versions = visitedPackageVersions.get(pkg.name);\n if (versions?.has(pkg.version)) {\n return;\n }\n if (!versions) {\n versions = new Set();\n visitedPackageVersions.set(pkg.name, versions);\n }\n versions.add(pkg.version);\n\n const depNames = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ...Object.keys(pkg.optionalDependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ];\n\n // TODO(Rugvip): Trying this out to avoid having to traverse the full dependency graph,\n // since that's pretty slow. We probably need a better way to determine when\n // we've left the Backstage ecosystem, but this will do for now.\n const hasSchema = 'configSchema' in pkg;\n const hasBackstageDep = depNames.some(_ => _.startsWith('@backstage/'));\n if (!hasSchema && !hasBackstageDep) {\n return;\n }\n if (hasSchema) {\n if (typeof pkg.configSchema === 'string') {\n const isJson = pkg.configSchema.endsWith('.json');\n const isDts = pkg.configSchema.endsWith('.d.ts');\n if (!isJson && !isDts) {\n throw new Error(\n `Config schema files must be .json or .d.ts, got ${pkg.configSchema}`,\n );\n }\n if (isDts) {\n tsSchemaPaths.push({\n path: relativePath(\n currentDir,\n resolvePath(dirname(pkgPath), pkg.configSchema),\n ),\n packageName: pkg.name,\n });\n } else {\n const path = resolvePath(dirname(pkgPath), pkg.configSchema);\n const value = await fs.readJson(path);\n schemas.push({\n packageName: pkg.name,\n value,\n path: relativePath(currentDir, path),\n });\n }\n } else {\n schemas.push({\n packageName: pkg.name,\n value: pkg.configSchema,\n path: relativePath(currentDir, pkgPath),\n });\n }\n }\n\n await Promise.all(\n depNames.map(depName =>\n processItem({ name: depName, parentPath: pkgPath }),\n ),\n );\n }\n\n await Promise.all([\n ...packageNames.map(name => processItem({ name, parentPath: currentDir })),\n ...packagePaths.map(path => processItem({ name: path, packagePath: path })),\n ]);\n\n const tsSchemas = await compileTsSchemas(tsSchemaPaths);\n const allSchemas = schemas.concat(tsSchemas);\n\n const hasBackendDefaults = allSchemas.some(\n ({ packageName }) => packageName === '@backstage/backend-defaults',\n );\n\n if (hasBackendDefaults) {\n // We filter out backend-common schemas here to avoid issues with\n // schema merging over different versions of the same schema.\n // led to issues such as https://github.com/backstage/backstage/issues/28170\n return allSchemas.filter(\n ({ packageName }) => packageName !== '@backstage/backend-common',\n );\n }\n\n return allSchemas;\n}\n\n// This handles the support of TypeScript .d.ts config schema declarations.\n// We collect all typescript schema definition and compile them all in one go.\n// This is much faster than compiling them separately.\nasync function compileTsSchemas(\n entries: { path: string; packageName: string }[],\n) {\n if (entries.length === 0) {\n return [];\n }\n\n // Lazy loaded, because this brings up all of TypeScript and we don't\n // want that eagerly loaded in tests\n const { getProgramFromFiles, buildGenerator } =\n require('typescript-json-schema') as typeof import('typescript-json-schema');\n\n const program = getProgramFromFiles(\n entries.map(({ path }) => path),\n {\n incremental: false,\n isolatedModules: true,\n lib: ['ES5'], // Skipping most libs speeds processing up a lot, we just need the primitive types anyway\n noEmit: true,\n noResolve: true,\n skipLibCheck: true, // Skipping lib checks speeds things up\n skipDefaultLibCheck: true,\n strict: true,\n typeRoots: [], // Do not include any additional types\n types: [],\n },\n );\n\n const tsSchemas = entries.map(({ path, packageName }) => {\n let value;\n try {\n const generator = buildGenerator(\n program,\n // This enables the use of these tags in TSDoc comments\n {\n required: true,\n validationKeywords: ['visibility', 'deepVisibility', 'deprecated'],\n },\n [path.split(sep).join('/')], // Unix paths are expected for all OSes here\n );\n\n // All schemas should export a `Config` symbol\n value = generator?.getSchemaForSymbol('Config') as JsonObject | null;\n\n // This makes sure that no additional symbols are defined in the schema. We don't allow\n // this because they share a global namespace and will be merged together, leading to\n // unpredictable behavior.\n const userSymbols = new Set(generator?.getUserSymbols());\n userSymbols.delete('Config');\n if (userSymbols.size !== 0) {\n const names = Array.from(userSymbols).join(\"', '\");\n throw new Error(\n `Invalid configuration schema in ${path}, additional symbol definitions are not allowed, found '${names}'`,\n );\n }\n\n // This makes sure that no unsupported types are used in the schema, for example `Record<,>`.\n // The generator will extract these as a schema reference, which will in turn be broken for our usage.\n const reffedDefs = Object.keys(generator?.ReffedDefinitions ?? {});\n if (reffedDefs.length !== 0) {\n const lines = reffedDefs.join(`${EOL} `);\n throw new Error(\n `Invalid configuration schema in ${path}, the following definitions are not supported:${EOL}${EOL} ${lines}`,\n );\n }\n } catch (error) {\n assertError(error);\n if (error.message !== 'type Config not found') {\n throw error;\n }\n }\n\n if (!value) {\n throw new Error(`Invalid schema in ${path}, missing Config export`);\n }\n return { path, value, packageName };\n });\n\n return tsSchemas;\n}\n"],"names":["fs","relativePath","resolvePath","dirname","sep","EOL","assertError"],"mappings":"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"}
1
+ {"version":3,"file":"collect.cjs.js","sources":["../../src/schema/collect.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport { EOL } from 'node:os';\nimport {\n resolve as resolvePath,\n relative as relativePath,\n dirname,\n sep,\n} from 'node:path';\nimport { ConfigSchemaPackageEntry } from './types';\nimport { JsonObject } from '@backstage/types';\nimport { toError } from '@backstage/errors';\n\ntype Item = {\n name?: string;\n parentPath?: string;\n packagePath?: string;\n};\n\nconst req =\n typeof __non_webpack_require__ === 'undefined'\n ? require\n : __non_webpack_require__;\n\n/**\n * Exported for test mocking. Jest 30's module resolver has issues with\n * nested node_modules, requiring tests to use an alternative resolution strategy.\n * @internal\n */\nexport const internal = {\n resolvePackagePath(name: string, options?: { paths: string[] }): string {\n return req.resolve(name, options);\n },\n};\n\n/**\n * This collects all known config schemas across all dependencies of the app.\n */\nexport async function collectConfigSchemas(\n packageNames: string[],\n packagePaths: string[],\n): Promise<ConfigSchemaPackageEntry[]> {\n const schemas = new Array<ConfigSchemaPackageEntry>();\n const tsSchemaPaths = new Array<{ packageName: string; path: string }>();\n const visitedPackageVersions = new Map<string, Set<string>>(); // pkgName: [versions...]\n\n const currentDir = await fs.realpath(process.cwd());\n\n async function processItem(item: Item) {\n let pkgPath = item.packagePath;\n\n if (pkgPath) {\n const pkgExists = await fs.pathExists(pkgPath);\n if (!pkgExists) {\n return;\n }\n } else if (item.name) {\n const { name, parentPath } = item;\n\n try {\n pkgPath = internal.resolvePackagePath(\n `${name}/package.json`,\n parentPath ? { paths: [parentPath] } : undefined,\n );\n } catch {\n // We can somewhat safely ignore packages that don't export package.json,\n // as they are likely not part of the Backstage ecosystem anyway.\n }\n }\n if (!pkgPath) {\n return;\n }\n\n const pkg = await fs.readJson(pkgPath);\n\n // Ensures that we only process the same version of each package once.\n let versions = visitedPackageVersions.get(pkg.name);\n if (versions?.has(pkg.version)) {\n return;\n }\n if (!versions) {\n versions = new Set();\n visitedPackageVersions.set(pkg.name, versions);\n }\n versions.add(pkg.version);\n\n const depNames = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ...Object.keys(pkg.optionalDependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ];\n\n // TODO(Rugvip): Trying this out to avoid having to traverse the full dependency graph,\n // since that's pretty slow. We probably need a better way to determine when\n // we've left the Backstage ecosystem, but this will do for now.\n const hasSchema = 'configSchema' in pkg;\n const hasBackstageDep = depNames.some(_ => _.startsWith('@backstage/'));\n if (!hasSchema && !hasBackstageDep) {\n return;\n }\n if (hasSchema) {\n if (typeof pkg.configSchema === 'string') {\n const isJson = pkg.configSchema.endsWith('.json');\n const isDts = pkg.configSchema.endsWith('.d.ts');\n if (!isJson && !isDts) {\n throw new Error(\n `Config schema files must be .json or .d.ts, got ${pkg.configSchema}`,\n );\n }\n if (isDts) {\n tsSchemaPaths.push({\n path: relativePath(\n currentDir,\n resolvePath(dirname(pkgPath), pkg.configSchema),\n ),\n packageName: pkg.name,\n });\n } else {\n const path = resolvePath(dirname(pkgPath), pkg.configSchema);\n const value = await fs.readJson(path);\n schemas.push({\n packageName: pkg.name,\n value,\n path: relativePath(currentDir, path),\n });\n }\n } else {\n schemas.push({\n packageName: pkg.name,\n value: pkg.configSchema,\n path: relativePath(currentDir, pkgPath),\n });\n }\n }\n\n await Promise.all(\n depNames.map(depName =>\n processItem({ name: depName, parentPath: pkgPath }),\n ),\n );\n }\n\n await Promise.all([\n ...packageNames.map(name => processItem({ name, parentPath: currentDir })),\n ...packagePaths.map(path => processItem({ name: path, packagePath: path })),\n ]);\n\n const tsSchemas = await compileTsSchemas(tsSchemaPaths);\n const allSchemas = schemas.concat(tsSchemas);\n\n const hasBackendDefaults = allSchemas.some(\n ({ packageName }) => packageName === '@backstage/backend-defaults',\n );\n\n if (hasBackendDefaults) {\n // We filter out backend-common schemas here to avoid issues with\n // schema merging over different versions of the same schema.\n // led to issues such as https://github.com/backstage/backstage/issues/28170\n return allSchemas.filter(\n ({ packageName }) => packageName !== '@backstage/backend-common',\n );\n }\n\n return allSchemas;\n}\n\n// This handles the support of TypeScript .d.ts config schema declarations.\n// We collect all typescript schema definition and compile them all in one go.\n// This is much faster than compiling them separately.\nasync function compileTsSchemas(\n entries: { path: string; packageName: string }[],\n) {\n if (entries.length === 0) {\n return [];\n }\n\n // Lazy loaded, because this brings up all of TypeScript and we don't\n // want that eagerly loaded in tests\n const { getProgramFromFiles, buildGenerator } =\n require('typescript-json-schema') as typeof import('typescript-json-schema');\n\n const program = getProgramFromFiles(\n entries.map(({ path }) => path),\n {\n incremental: false,\n isolatedModules: true,\n lib: ['ES5'], // Skipping most libs speeds processing up a lot, we just need the primitive types anyway\n noEmit: true,\n noResolve: true,\n skipLibCheck: true, // Skipping lib checks speeds things up\n skipDefaultLibCheck: true,\n strict: true,\n typeRoots: [], // Do not include any additional types\n types: [],\n },\n );\n\n const tsSchemas = entries.map(({ path, packageName }) => {\n let value;\n try {\n const generator = buildGenerator(\n program,\n // This enables the use of these tags in TSDoc comments\n {\n required: true,\n validationKeywords: ['visibility', 'deepVisibility', 'deprecated'],\n },\n [path.split(sep).join('/')], // Unix paths are expected for all OSes here\n );\n\n // All schemas should export a `Config` symbol\n value = generator?.getSchemaForSymbol('Config') as JsonObject | null;\n\n // This makes sure that no additional symbols are defined in the schema. We don't allow\n // this because they share a global namespace and will be merged together, leading to\n // unpredictable behavior.\n const userSymbols = new Set(generator?.getUserSymbols());\n userSymbols.delete('Config');\n if (userSymbols.size !== 0) {\n const names = Array.from(userSymbols).join(\"', '\");\n throw new Error(\n `Invalid configuration schema in ${path}, additional symbol definitions are not allowed, found '${names}'`,\n );\n }\n\n // This makes sure that no unsupported types are used in the schema, for example `Record<,>`.\n // The generator will extract these as a schema reference, which will in turn be broken for our usage.\n const reffedDefs = Object.keys(generator?.ReffedDefinitions ?? {});\n if (reffedDefs.length !== 0) {\n const lines = reffedDefs.join(`${EOL} `);\n throw new Error(\n `Invalid configuration schema in ${path}, the following definitions are not supported:${EOL}${EOL} ${lines}`,\n );\n }\n } catch (error) {\n const err = toError(error);\n if (err.message !== 'type Config not found') {\n throw err;\n }\n }\n\n if (!value) {\n throw new Error(`Invalid schema in ${path}, missing Config export`);\n }\n return { path, value, packageName };\n });\n\n return tsSchemas;\n}\n"],"names":["fs","relativePath","resolvePath","dirname","sep","EOL","toError"],"mappings":";;;;;;;;;;;AAkCA,MAAM,GAAA,GACJ,OAAO,uBAAA,KAA4B,WAAA,GAC/B,OAAA,GACA,uBAAA;AAOC,MAAM,QAAA,GAAW;AAAA,EACtB,kBAAA,CAAmB,MAAc,OAAA,EAAuC;AACtE,IAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,OAAO,CAAA;AAAA,EAClC;AACF;AAKA,eAAsB,oBAAA,CACpB,cACA,YAAA,EACqC;AACrC,EAAA,MAAM,OAAA,GAAU,IAAI,KAAA,EAAgC;AACpD,EAAA,MAAM,aAAA,GAAgB,IAAI,KAAA,EAA6C;AACvE,EAAA,MAAM,sBAAA,uBAA6B,GAAA,EAAyB;AAE5D,EAAA,MAAM,aAAa,MAAMA,mBAAA,CAAG,QAAA,CAAS,OAAA,CAAQ,KAAK,CAAA;AAElD,EAAA,eAAe,YAAY,IAAA,EAAY;AACrC,IAAA,IAAI,UAAU,IAAA,CAAK,WAAA;AAEnB,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,SAAA,GAAY,MAAMA,mBAAA,CAAG,UAAA,CAAW,OAAO,CAAA;AAC7C,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA;AAAA,MACF;AAAA,IACF,CAAA,MAAA,IAAW,KAAK,IAAA,EAAM;AACpB,MAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAW,GAAI,IAAA;AAE7B,MAAA,IAAI;AACF,QAAA,OAAA,GAAU,QAAA,CAAS,kBAAA;AAAA,UACjB,GAAG,IAAI,CAAA,aAAA,CAAA;AAAA,UACP,aAAa,EAAE,KAAA,EAAO,CAAC,UAAU,GAAE,GAAI,KAAA;AAAA,SACzC;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAGR;AAAA,IACF;AACA,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,MAAMA,mBAAA,CAAG,QAAA,CAAS,OAAO,CAAA;AAGrC,IAAA,IAAI,QAAA,GAAW,sBAAA,CAAuB,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA;AAClD,IAAA,IAAI,QAAA,EAAU,GAAA,CAAI,GAAA,CAAI,OAAO,CAAA,EAAG;AAC9B,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,QAAA,uBAAe,GAAA,EAAI;AACnB,MAAA,sBAAA,CAAuB,GAAA,CAAI,GAAA,CAAI,IAAA,EAAM,QAAQ,CAAA;AAAA,IAC/C;AACA,IAAA,QAAA,CAAS,GAAA,CAAI,IAAI,OAAO,CAAA;AAExB,IAAA,MAAM,QAAA,GAAW;AAAA,MACf,GAAG,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,YAAA,IAAgB,EAAE,CAAA;AAAA,MACrC,GAAG,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,eAAA,IAAmB,EAAE,CAAA;AAAA,MACxC,GAAG,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,oBAAA,IAAwB,EAAE,CAAA;AAAA,MAC7C,GAAG,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,gBAAA,IAAoB,EAAE;AAAA,KAC3C;AAKA,IAAA,MAAM,YAAY,cAAA,IAAkB,GAAA;AACpC,IAAA,MAAM,kBAAkB,QAAA,CAAS,IAAA,CAAK,OAAK,CAAA,CAAE,UAAA,CAAW,aAAa,CAAC,CAAA;AACtE,IAAA,IAAI,CAAC,SAAA,IAAa,CAAC,eAAA,EAAiB;AAClC,MAAA;AAAA,IACF;AACA,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,IAAI,OAAO,GAAA,CAAI,YAAA,KAAiB,QAAA,EAAU;AACxC,QAAA,MAAM,MAAA,GAAS,GAAA,CAAI,YAAA,CAAa,QAAA,CAAS,OAAO,CAAA;AAChD,QAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,YAAA,CAAa,QAAA,CAAS,OAAO,CAAA;AAC/C,QAAA,IAAI,CAAC,MAAA,IAAU,CAAC,KAAA,EAAO;AACrB,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,gDAAA,EAAmD,IAAI,YAAY,CAAA;AAAA,WACrE;AAAA,QACF;AACA,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,aAAA,CAAc,IAAA,CAAK;AAAA,YACjB,IAAA,EAAMC,kBAAA;AAAA,cACJ,UAAA;AAAA,cACAC,iBAAA,CAAYC,iBAAA,CAAQ,OAAO,CAAA,EAAG,IAAI,YAAY;AAAA,aAChD;AAAA,YACA,aAAa,GAAA,CAAI;AAAA,WAClB,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,MAAM,OAAOD,iBAAA,CAAYC,iBAAA,CAAQ,OAAO,CAAA,EAAG,IAAI,YAAY,CAAA;AAC3D,UAAA,MAAM,KAAA,GAAQ,MAAMH,mBAAA,CAAG,QAAA,CAAS,IAAI,CAAA;AACpC,UAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,YACX,aAAa,GAAA,CAAI,IAAA;AAAA,YACjB,KAAA;AAAA,YACA,IAAA,EAAMC,kBAAA,CAAa,UAAA,EAAY,IAAI;AAAA,WACpC,CAAA;AAAA,QACH;AAAA,MACF,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,aAAa,GAAA,CAAI,IAAA;AAAA,UACjB,OAAO,GAAA,CAAI,YAAA;AAAA,UACX,IAAA,EAAMA,kBAAA,CAAa,UAAA,EAAY,OAAO;AAAA,SACvC,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,MACZ,QAAA,CAAS,GAAA;AAAA,QAAI,aACX,WAAA,CAAY,EAAE,MAAM,OAAA,EAAS,UAAA,EAAY,SAAS;AAAA;AACpD,KACF;AAAA,EACF;AAEA,EAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,IAChB,GAAG,YAAA,CAAa,GAAA,CAAI,CAAA,IAAA,KAAQ,WAAA,CAAY,EAAE,IAAA,EAAM,UAAA,EAAY,UAAA,EAAY,CAAC,CAAA;AAAA,IACzE,GAAG,YAAA,CAAa,GAAA,CAAI,CAAA,IAAA,KAAQ,WAAA,CAAY,EAAE,IAAA,EAAM,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,CAAC;AAAA,GAC3E,CAAA;AAED,EAAA,MAAM,SAAA,GAAY,MAAM,gBAAA,CAAiB,aAAa,CAAA;AACtD,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA;AAE3C,EAAA,MAAM,qBAAqB,UAAA,CAAW,IAAA;AAAA,IACpC,CAAC,EAAE,WAAA,EAAY,KAAM,WAAA,KAAgB;AAAA,GACvC;AAEA,EAAA,IAAI,kBAAA,EAAoB;AAItB,IAAA,OAAO,UAAA,CAAW,MAAA;AAAA,MAChB,CAAC,EAAE,WAAA,EAAY,KAAM,WAAA,KAAgB;AAAA,KACvC;AAAA,EACF;AAEA,EAAA,OAAO,UAAA;AACT;AAKA,eAAe,iBACb,OAAA,EACA;AACA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAC;AAAA,EACV;AAIA,EAAA,MAAM,EAAE,mBAAA,EAAqB,cAAA,EAAe,GAC1C,QAAQ,wBAAwB,CAAA;AAElC,EAAA,MAAM,OAAA,GAAU,mBAAA;AAAA,IACd,QAAQ,GAAA,CAAI,CAAC,EAAE,IAAA,OAAW,IAAI,CAAA;AAAA,IAC9B;AAAA,MACE,WAAA,EAAa,KAAA;AAAA,MACb,eAAA,EAAiB,IAAA;AAAA,MACjB,GAAA,EAAK,CAAC,KAAK,CAAA;AAAA;AAAA,MACX,MAAA,EAAQ,IAAA;AAAA,MACR,SAAA,EAAW,IAAA;AAAA,MACX,YAAA,EAAc,IAAA;AAAA;AAAA,MACd,mBAAA,EAAqB,IAAA;AAAA,MACrB,MAAA,EAAQ,IAAA;AAAA,MACR,WAAW,EAAC;AAAA;AAAA,MACZ,OAAO;AAAC;AACV,GACF;AAEA,EAAA,MAAM,YAAY,OAAA,CAAQ,GAAA,CAAI,CAAC,EAAE,IAAA,EAAM,aAAY,KAAM;AACvD,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAY,cAAA;AAAA,QAChB,OAAA;AAAA;AAAA,QAEA;AAAA,UACE,QAAA,EAAU,IAAA;AAAA,UACV,kBAAA,EAAoB,CAAC,YAAA,EAAc,gBAAA,EAAkB,YAAY;AAAA,SACnE;AAAA,QACA,CAAC,IAAA,CAAK,KAAA,CAAMG,aAAG,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC;AAAA;AAAA,OAC5B;AAGA,MAAA,KAAA,GAAQ,SAAA,EAAW,mBAAmB,QAAQ,CAAA;AAK9C,MAAA,MAAM,WAAA,GAAc,IAAI,GAAA,CAAI,SAAA,EAAW,gBAAgB,CAAA;AACvD,MAAA,WAAA,CAAY,OAAO,QAAQ,CAAA;AAC3B,MAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC1B,QAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA,CAAE,KAAK,MAAM,CAAA;AACjD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,gCAAA,EAAmC,IAAI,CAAA,wDAAA,EAA2D,KAAK,CAAA,CAAA;AAAA,SACzG;AAAA,MACF;AAIA,MAAA,MAAM,aAAa,MAAA,CAAO,IAAA,CAAK,SAAA,EAAW,iBAAA,IAAqB,EAAE,CAAA;AACjE,MAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,QAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,CAAK,CAAA,EAAGC,WAAG,CAAA,EAAA,CAAI,CAAA;AACxC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,mCAAmC,IAAI,CAAA,8CAAA,EAAiDA,WAAG,CAAA,EAAGA,WAAG,KAAK,KAAK,CAAA;AAAA,SAC7G;AAAA,MACF;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,GAAA,GAAMC,eAAQ,KAAK,CAAA;AACzB,MAAA,IAAI,GAAA,CAAI,YAAY,uBAAA,EAAyB;AAC3C,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,IAAI,CAAA,uBAAA,CAAyB,CAAA;AAAA,IACpE;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,WAAA,EAAY;AAAA,EACpC,CAAC,CAAA;AAED,EAAA,OAAO,SAAA;AACT;;;;;"}
@@ -78,8 +78,7 @@ function safeJsonParse(str) {
78
78
  try {
79
79
  return [null, JSON.parse(str)];
80
80
  } catch (err) {
81
- errors.assertError(err);
82
- return [err, str];
81
+ return [errors.toError(err), str];
83
82
  }
84
83
  }
85
84
 
@@ -1 +1 @@
1
- {"version":3,"file":"EnvConfigSource.cjs.js","sources":["../../src/sources/EnvConfigSource.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 { AppConfig } from '@backstage/config';\nimport { assertError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport { AsyncConfigSourceGenerator, ConfigSource } from './types';\n\n/**\n * Options for {@link EnvConfigSource.create}.\n *\n * @public\n */\nexport interface EnvConfigSourceOptions {\n /**\n * The environment variables to use, defaults to `process.env`.\n */\n env?: Record<string, string | undefined>;\n}\n\n/**\n * A config source that reads configuration from the environment.\n *\n * @remarks\n *\n * Only environment variables prefixed with APP_CONFIG_ will be considered.\n *\n * For each variable, the prefix will be removed, and rest of the key will\n * be split by '_'. Each part will then be used as keys to build up a nested\n * config object structure. The treatment of the entire environment variable\n * is case-sensitive.\n *\n * The value of the variable should be JSON serialized, as it will be parsed\n * and the type will be kept intact. For example \"true\" and true are treated\n * differently, as well as \"42\" and 42.\n *\n * For example, to set the config app.title to \"My Title\", use the following:\n *\n * APP_CONFIG_app_title='\"My Title\"'\n *\n * @public\n */\nexport class EnvConfigSource implements ConfigSource {\n /**\n * Creates a new config source that reads from the environment.\n *\n * @param options - Options for the config source.\n * @returns A new config source that reads from the environment.\n */\n static create(options: EnvConfigSourceOptions): ConfigSource {\n return new EnvConfigSource(options?.env ?? process.env);\n }\n\n private constructor(\n private readonly env: { [name: string]: string | undefined },\n ) {}\n\n async *readConfigData(): AsyncConfigSourceGenerator {\n const configs = readEnvConfig(this.env);\n yield { configs };\n return;\n }\n\n toString() {\n const keys = Object.keys(this.env).filter(key =>\n key.startsWith('APP_CONFIG_'),\n );\n return `EnvConfigSource{count=${keys.length}}`;\n }\n}\n\nconst ENV_PREFIX = 'APP_CONFIG_';\n\n// Update the same pattern in config package if this is changed\nconst CONFIG_KEY_PART_PATTERN = /^[a-z][a-z0-9]*(?:[-_:][a-z0-9]+)*$/i;\n\n/**\n * Read runtime configuration from the environment.\n *\n * @remarks\n *\n * Only environment variables prefixed with APP_CONFIG_ will be considered.\n *\n * For each variable, the prefix will be removed, and rest of the key will\n * be split by '_'. Each part will then be used as keys to build up a nested\n * config object structure. The treatment of the entire environment variable\n * is case-sensitive.\n *\n * The value of the variable should be JSON serialized, as it will be parsed\n * and the type will be kept intact. For example \"true\" and true are treated\n * differently, as well as \"42\" and 42.\n *\n * For example, to set the config app.title to \"My Title\", use the following:\n *\n * APP_CONFIG_app_title='\"My Title\"'\n *\n * @public\n * @deprecated Use {@link EnvConfigSource} instead\n */\nexport function readEnvConfig(env: {\n [name: string]: string | undefined;\n}): AppConfig[] {\n let data: JsonObject | undefined = undefined;\n\n for (const [name, value] of Object.entries(env)) {\n if (!value) {\n continue;\n }\n if (name.startsWith(ENV_PREFIX)) {\n const key = name.replace(ENV_PREFIX, '');\n const keyParts = key.split('_');\n\n let obj = (data = data ?? {});\n for (const [index, part] of keyParts.entries()) {\n if (!CONFIG_KEY_PART_PATTERN.test(part)) {\n throw new TypeError(`Invalid env config key '${key}'`);\n }\n if (index < keyParts.length - 1) {\n obj = (obj[part] = obj[part] ?? {}) as JsonObject;\n if (typeof obj !== 'object' || Array.isArray(obj)) {\n const subKey = keyParts.slice(0, index + 1).join('_');\n throw new TypeError(\n `Could not nest config for key '${key}' under existing value '${subKey}'`,\n );\n }\n } else {\n if (part in obj) {\n throw new TypeError(\n `Refusing to override existing config at key '${key}'`,\n );\n }\n try {\n const [, parsedValue] = safeJsonParse(value);\n if (parsedValue === null) {\n throw new Error('value may not be null');\n }\n obj[part] = parsedValue;\n } catch (error) {\n throw new TypeError(\n `Failed to parse JSON-serialized config value for key '${key}', ${error}`,\n );\n }\n }\n }\n }\n }\n\n return data ? [{ data, context: 'env' }] : [];\n}\n\nfunction safeJsonParse(str: string): [Error | null, any] {\n try {\n return [null, JSON.parse(str)];\n } catch (err) {\n assertError(err);\n return [err, str];\n }\n}\n"],"names":["assertError"],"mappings":"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"}
1
+ {"version":3,"file":"EnvConfigSource.cjs.js","sources":["../../src/sources/EnvConfigSource.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 { AppConfig } from '@backstage/config';\nimport { toError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport { AsyncConfigSourceGenerator, ConfigSource } from './types';\n\n/**\n * Options for {@link EnvConfigSource.create}.\n *\n * @public\n */\nexport interface EnvConfigSourceOptions {\n /**\n * The environment variables to use, defaults to `process.env`.\n */\n env?: Record<string, string | undefined>;\n}\n\n/**\n * A config source that reads configuration from the environment.\n *\n * @remarks\n *\n * Only environment variables prefixed with APP_CONFIG_ will be considered.\n *\n * For each variable, the prefix will be removed, and rest of the key will\n * be split by '_'. Each part will then be used as keys to build up a nested\n * config object structure. The treatment of the entire environment variable\n * is case-sensitive.\n *\n * The value of the variable should be JSON serialized, as it will be parsed\n * and the type will be kept intact. For example \"true\" and true are treated\n * differently, as well as \"42\" and 42.\n *\n * For example, to set the config app.title to \"My Title\", use the following:\n *\n * APP_CONFIG_app_title='\"My Title\"'\n *\n * @public\n */\nexport class EnvConfigSource implements ConfigSource {\n /**\n * Creates a new config source that reads from the environment.\n *\n * @param options - Options for the config source.\n * @returns A new config source that reads from the environment.\n */\n static create(options: EnvConfigSourceOptions): ConfigSource {\n return new EnvConfigSource(options?.env ?? process.env);\n }\n\n private constructor(\n private readonly env: { [name: string]: string | undefined },\n ) {}\n\n async *readConfigData(): AsyncConfigSourceGenerator {\n const configs = readEnvConfig(this.env);\n yield { configs };\n return;\n }\n\n toString() {\n const keys = Object.keys(this.env).filter(key =>\n key.startsWith('APP_CONFIG_'),\n );\n return `EnvConfigSource{count=${keys.length}}`;\n }\n}\n\nconst ENV_PREFIX = 'APP_CONFIG_';\n\n// Update the same pattern in config package if this is changed\nconst CONFIG_KEY_PART_PATTERN = /^[a-z][a-z0-9]*(?:[-_:][a-z0-9]+)*$/i;\n\n/**\n * Read runtime configuration from the environment.\n *\n * @remarks\n *\n * Only environment variables prefixed with APP_CONFIG_ will be considered.\n *\n * For each variable, the prefix will be removed, and rest of the key will\n * be split by '_'. Each part will then be used as keys to build up a nested\n * config object structure. The treatment of the entire environment variable\n * is case-sensitive.\n *\n * The value of the variable should be JSON serialized, as it will be parsed\n * and the type will be kept intact. For example \"true\" and true are treated\n * differently, as well as \"42\" and 42.\n *\n * For example, to set the config app.title to \"My Title\", use the following:\n *\n * APP_CONFIG_app_title='\"My Title\"'\n *\n * @public\n * @deprecated Use {@link EnvConfigSource} instead\n */\nexport function readEnvConfig(env: {\n [name: string]: string | undefined;\n}): AppConfig[] {\n let data: JsonObject | undefined = undefined;\n\n for (const [name, value] of Object.entries(env)) {\n if (!value) {\n continue;\n }\n if (name.startsWith(ENV_PREFIX)) {\n const key = name.replace(ENV_PREFIX, '');\n const keyParts = key.split('_');\n\n let obj = (data = data ?? {});\n for (const [index, part] of keyParts.entries()) {\n if (!CONFIG_KEY_PART_PATTERN.test(part)) {\n throw new TypeError(`Invalid env config key '${key}'`);\n }\n if (index < keyParts.length - 1) {\n obj = (obj[part] = obj[part] ?? {}) as JsonObject;\n if (typeof obj !== 'object' || Array.isArray(obj)) {\n const subKey = keyParts.slice(0, index + 1).join('_');\n throw new TypeError(\n `Could not nest config for key '${key}' under existing value '${subKey}'`,\n );\n }\n } else {\n if (part in obj) {\n throw new TypeError(\n `Refusing to override existing config at key '${key}'`,\n );\n }\n try {\n const [, parsedValue] = safeJsonParse(value);\n if (parsedValue === null) {\n throw new Error('value may not be null');\n }\n obj[part] = parsedValue;\n } catch (error) {\n throw new TypeError(\n `Failed to parse JSON-serialized config value for key '${key}', ${error}`,\n );\n }\n }\n }\n }\n }\n\n return data ? [{ data, context: 'env' }] : [];\n}\n\nfunction safeJsonParse(str: string): [Error | null, any] {\n try {\n return [null, JSON.parse(str)];\n } catch (err) {\n return [toError(err), str];\n }\n}\n"],"names":["toError"],"mappings":"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"}
@@ -21,8 +21,7 @@ async function applyConfigTransforms(input, context, transforms) {
21
21
  break;
22
22
  }
23
23
  } catch (error) {
24
- errors.assertError(error);
25
- throw new Error(`error at ${path}, ${error.message}`);
24
+ throw new Error(`error at ${path}, ${errors.toError(error).message}`);
26
25
  }
27
26
  }
28
27
  if (typeof obj !== "object") {
@@ -1 +1 @@
1
- {"version":3,"file":"apply.cjs.js","sources":["../../../src/sources/transform/apply.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 { JsonObject, JsonValue } from '@backstage/types';\nimport { assertError } from '@backstage/errors';\nimport { TransformContext, TransformFunc } from './types';\nimport { isObject } from './utils';\nimport { createSubstitutionTransform } from './substitution';\nimport { createIncludeTransform } from './include';\nimport { SubstitutionFunc } from '../types';\n\n/**\n * Applies a set of transforms to raw configuration data.\n */\nexport async function applyConfigTransforms(\n input: JsonValue,\n context: { dir?: string },\n transforms: TransformFunc[],\n): Promise<JsonObject> {\n async function transform(\n inputObj: JsonValue,\n path: string,\n baseDir?: string,\n ): Promise<JsonValue | undefined> {\n let obj = inputObj;\n let dir = baseDir;\n\n for (const tf of transforms) {\n try {\n const result = await tf(inputObj, { dir });\n if (result.applied) {\n if (result.value === undefined) {\n return undefined;\n }\n obj = result.value;\n dir = result?.newDir ?? dir;\n break;\n }\n } catch (error) {\n assertError(error);\n throw new Error(`error at ${path}, ${error.message}`);\n }\n }\n\n if (typeof obj !== 'object') {\n return obj;\n } else if (obj === null) {\n return null;\n } else if (Array.isArray(obj)) {\n const arr = new Array<JsonValue>();\n\n for (const [index, value] of obj.entries()) {\n const out = await transform(value, `${path}[${index}]`, dir);\n if (out !== undefined) {\n arr.push(out);\n }\n }\n\n return arr;\n }\n\n const out: JsonObject = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // undefined covers optional fields\n if (value !== undefined) {\n const result = await transform(value, `${path}.${key}`, dir);\n if (result !== undefined) {\n out[key] = result;\n }\n }\n }\n\n return out;\n }\n\n const finalData = await transform(input, '', context?.dir);\n if (!isObject(finalData)) {\n throw new TypeError('expected object at config root');\n }\n return finalData;\n}\n\n/** @internal */\nexport type ConfigTransformer = (\n input: JsonObject,\n context?: TransformContext,\n) => Promise<JsonObject>;\n\n/** @internal */\nexport function createConfigTransformer(options: {\n substitutionFunc?: SubstitutionFunc;\n readFile?(path: string): Promise<string>;\n}): ConfigTransformer {\n const {\n substitutionFunc = async name => process.env[name]?.trim(),\n readFile,\n } = options;\n const substitutionTransform = createSubstitutionTransform(substitutionFunc);\n const transforms = [substitutionTransform];\n if (readFile) {\n const includeTransform = createIncludeTransform(\n substitutionFunc,\n readFile,\n substitutionTransform,\n );\n transforms.push(includeTransform);\n }\n\n return async (input, ctx) =>\n applyConfigTransforms(input, ctx ?? {}, transforms);\n}\n"],"names":["assertError","out","isObject","createSubstitutionTransform","createIncludeTransform"],"mappings":"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"}
1
+ {"version":3,"file":"apply.cjs.js","sources":["../../../src/sources/transform/apply.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 { JsonObject, JsonValue } from '@backstage/types';\nimport { toError } from '@backstage/errors';\nimport { TransformContext, TransformFunc } from './types';\nimport { isObject } from './utils';\nimport { createSubstitutionTransform } from './substitution';\nimport { createIncludeTransform } from './include';\nimport { SubstitutionFunc } from '../types';\n\n/**\n * Applies a set of transforms to raw configuration data.\n */\nexport async function applyConfigTransforms(\n input: JsonValue,\n context: { dir?: string },\n transforms: TransformFunc[],\n): Promise<JsonObject> {\n async function transform(\n inputObj: JsonValue,\n path: string,\n baseDir?: string,\n ): Promise<JsonValue | undefined> {\n let obj = inputObj;\n let dir = baseDir;\n\n for (const tf of transforms) {\n try {\n const result = await tf(inputObj, { dir });\n if (result.applied) {\n if (result.value === undefined) {\n return undefined;\n }\n obj = result.value;\n dir = result?.newDir ?? dir;\n break;\n }\n } catch (error) {\n throw new Error(`error at ${path}, ${toError(error).message}`);\n }\n }\n\n if (typeof obj !== 'object') {\n return obj;\n } else if (obj === null) {\n return null;\n } else if (Array.isArray(obj)) {\n const arr = new Array<JsonValue>();\n\n for (const [index, value] of obj.entries()) {\n const out = await transform(value, `${path}[${index}]`, dir);\n if (out !== undefined) {\n arr.push(out);\n }\n }\n\n return arr;\n }\n\n const out: JsonObject = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // undefined covers optional fields\n if (value !== undefined) {\n const result = await transform(value, `${path}.${key}`, dir);\n if (result !== undefined) {\n out[key] = result;\n }\n }\n }\n\n return out;\n }\n\n const finalData = await transform(input, '', context?.dir);\n if (!isObject(finalData)) {\n throw new TypeError('expected object at config root');\n }\n return finalData;\n}\n\n/** @internal */\nexport type ConfigTransformer = (\n input: JsonObject,\n context?: TransformContext,\n) => Promise<JsonObject>;\n\n/** @internal */\nexport function createConfigTransformer(options: {\n substitutionFunc?: SubstitutionFunc;\n readFile?(path: string): Promise<string>;\n}): ConfigTransformer {\n const {\n substitutionFunc = async name => process.env[name]?.trim(),\n readFile,\n } = options;\n const substitutionTransform = createSubstitutionTransform(substitutionFunc);\n const transforms = [substitutionTransform];\n if (readFile) {\n const includeTransform = createIncludeTransform(\n substitutionFunc,\n readFile,\n substitutionTransform,\n );\n transforms.push(includeTransform);\n }\n\n return async (input, ctx) =>\n applyConfigTransforms(input, ctx ?? {}, transforms);\n}\n"],"names":["toError","out","isObject","createSubstitutionTransform","createIncludeTransform"],"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.9",
3
+ "version": "1.10.10-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.2.0",
40
- "@backstage/config": "^1.3.6",
41
- "@backstage/errors": "^1.2.7",
42
- "@backstage/types": "^1.2.2",
39
+ "@backstage/cli-common": "0.2.1-next.1",
40
+ "@backstage/config": "1.3.7-next.0",
41
+ "@backstage/errors": "1.3.0-next.0",
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",
@@ -53,8 +53,8 @@
53
53
  "yaml": "^2.0.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@backstage/backend-test-utils": "^1.11.1",
57
- "@backstage/cli": "^0.36.0",
56
+ "@backstage/backend-test-utils": "1.11.2-next.2",
57
+ "@backstage/cli": "0.36.1-next.2",
58
58
  "@types/json-schema-merge-allof": "^0.6.0",
59
59
  "@types/minimist": "^1.2.5",
60
60
  "msw": "^2.0.0",