@backstage/config-loader 1.10.7 → 1.10.8-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @backstage/config-loader
2
2
 
3
+ ## 1.10.8-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 7455dae: Use node prefix on native imports
8
+ - Updated dependencies
9
+ - @backstage/cli-common@0.1.18-next.0
10
+ - @backstage/config@1.3.6
11
+ - @backstage/errors@1.2.7
12
+ - @backstage/types@1.2.2
13
+
3
14
  ## 1.10.7
4
15
 
5
16
  ### Patch Changes
@@ -4,7 +4,7 @@ var ConfigSources = require('./sources/ConfigSources.cjs.js');
4
4
  require('@backstage/errors');
5
5
  require('chokidar');
6
6
  require('fs-extra');
7
- require('path');
7
+ require('node:path');
8
8
  require('yaml');
9
9
  require('@backstage/types');
10
10
  require('lodash/isEqual');
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var fs = require('fs-extra');
4
- var os = require('os');
5
- var path = require('path');
4
+ var node_os = require('node:os');
5
+ var node_path = require('node:path');
6
6
  var errors = require('@backstage/errors');
7
7
 
8
8
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
@@ -72,26 +72,26 @@ async function collectConfigSchemas(packageNames, packagePaths) {
72
72
  }
73
73
  if (isDts) {
74
74
  tsSchemaPaths.push({
75
- path: path.relative(
75
+ path: node_path.relative(
76
76
  currentDir,
77
- path.resolve(path.dirname(pkgPath), pkg.configSchema)
77
+ node_path.resolve(node_path.dirname(pkgPath), pkg.configSchema)
78
78
  ),
79
79
  packageName: pkg.name
80
80
  });
81
81
  } else {
82
- const path$1 = path.resolve(path.dirname(pkgPath), pkg.configSchema);
83
- const value = await fs__default.default.readJson(path$1);
82
+ const path = node_path.resolve(node_path.dirname(pkgPath), pkg.configSchema);
83
+ const value = await fs__default.default.readJson(path);
84
84
  schemas.push({
85
85
  packageName: pkg.name,
86
86
  value,
87
- path: path.relative(currentDir, path$1)
87
+ path: node_path.relative(currentDir, path)
88
88
  });
89
89
  }
90
90
  } else {
91
91
  schemas.push({
92
92
  packageName: pkg.name,
93
93
  value: pkg.configSchema,
94
- path: path.relative(currentDir, pkgPath)
94
+ path: node_path.relative(currentDir, pkgPath)
95
95
  });
96
96
  }
97
97
  }
@@ -140,7 +140,7 @@ async function compileTsSchemas(entries) {
140
140
  types: []
141
141
  }
142
142
  );
143
- const tsSchemas = entries.map(({ path: path$1, packageName }) => {
143
+ const tsSchemas = entries.map(({ path, packageName }) => {
144
144
  let value;
145
145
  try {
146
146
  const generator = buildGenerator(
@@ -150,7 +150,7 @@ async function compileTsSchemas(entries) {
150
150
  required: true,
151
151
  validationKeywords: ["visibility", "deepVisibility", "deprecated"]
152
152
  },
153
- [path$1.split(path.sep).join("/")]
153
+ [path.split(node_path.sep).join("/")]
154
154
  // Unix paths are expected for all OSes here
155
155
  );
156
156
  value = generator?.getSchemaForSymbol("Config");
@@ -159,14 +159,14 @@ async function compileTsSchemas(entries) {
159
159
  if (userSymbols.size !== 0) {
160
160
  const names = Array.from(userSymbols).join("', '");
161
161
  throw new Error(
162
- `Invalid configuration schema in ${path$1}, additional symbol definitions are not allowed, found '${names}'`
162
+ `Invalid configuration schema in ${path}, additional symbol definitions are not allowed, found '${names}'`
163
163
  );
164
164
  }
165
165
  const reffedDefs = Object.keys(generator?.ReffedDefinitions ?? {});
166
166
  if (reffedDefs.length !== 0) {
167
- const lines = reffedDefs.join(`${os.EOL} `);
167
+ const lines = reffedDefs.join(`${node_os.EOL} `);
168
168
  throw new Error(
169
- `Invalid configuration schema in ${path$1}, the following definitions are not supported:${os.EOL}${os.EOL} ${lines}`
169
+ `Invalid configuration schema in ${path}, the following definitions are not supported:${node_os.EOL}${node_os.EOL} ${lines}`
170
170
  );
171
171
  }
172
172
  } catch (error) {
@@ -176,9 +176,9 @@ async function compileTsSchemas(entries) {
176
176
  }
177
177
  }
178
178
  if (!value) {
179
- throw new Error(`Invalid schema in ${path$1}, missing Config export`);
179
+ throw new Error(`Invalid schema in ${path}, missing Config export`);
180
180
  }
181
- return { path: path$1, value, packageName };
181
+ return { path, value, packageName };
182
182
  });
183
183
  return tsSchemas;
184
184
  }
@@ -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 'os';\nimport {\n resolve as resolvePath,\n relative as relativePath,\n dirname,\n sep,\n} from '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","path","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 { 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,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
3
+ var node_path = require('node:path');
4
4
  var fs = require('fs-extra');
5
5
  var config = require('@backstage/config');
6
6
  var parseArgs = require('minimist');
@@ -69,18 +69,18 @@ class ConfigSources {
69
69
  }
70
70
  return FileConfigSource.FileConfigSource.create({
71
71
  watch: options.watch,
72
- path: path.resolve(arg.target),
72
+ path: node_path.resolve(arg.target),
73
73
  substitutionFunc: options.substitutionFunc
74
74
  });
75
75
  });
76
76
  if (argSources.length === 0) {
77
- const defaultPath = path.resolve(rootDir, "app-config.yaml");
78
- const localPath = path.resolve(rootDir, "app-config.local.yaml");
79
- const envPath = path.resolve(
77
+ const defaultPath = node_path.resolve(rootDir, "app-config.yaml");
78
+ const localPath = node_path.resolve(rootDir, "app-config.local.yaml");
79
+ const envPath = node_path.resolve(
80
80
  rootDir,
81
81
  `app-config.${process.env.BACKSTAGE_ENV}.yaml`
82
82
  );
83
- const envLocalPath = path.resolve(
83
+ const envLocalPath = node_path.resolve(
84
84
  rootDir,
85
85
  `app-config.${process.env.BACKSTAGE_ENV}.local.yaml`
86
86
  );
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigSources.cjs.js","sources":["../../src/sources/ConfigSources.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 { resolve as resolvePath } from 'path';\nimport fs from 'fs-extra';\nimport { Config, ConfigReader } from '@backstage/config';\nimport parseArgs from 'minimist';\nimport { EnvConfigSource } from './EnvConfigSource';\nimport { FileConfigSource } from './FileConfigSource';\nimport { MergedConfigSource } from './MergedConfigSource';\nimport {\n RemoteConfigSource,\n RemoteConfigSourceOptions,\n} from './RemoteConfigSource';\nimport { ConfigSource, SubstitutionFunc } from './types';\nimport { ObservableConfigProxy } from './ObservableConfigProxy';\nimport { findPaths } from '@backstage/cli-common';\n\n/**\n * A target to read configuration from.\n *\n * @public\n */\nexport type ConfigSourceTarget =\n | {\n type: 'path';\n target: string;\n }\n | {\n type: 'url';\n target: string;\n };\n\n/**\n * A config implementation that can be closed.\n *\n * @remarks\n *\n * Closing the configuration instance will stop the reading from the underlying source.\n *\n * @public\n */\nexport interface ClosableConfig extends Config {\n /**\n * Closes the configuration instance.\n *\n * @remarks\n *\n * The configuration instance will still be usable after closing, but it will\n * no longer be updated with new values from the underlying source.\n */\n close(): void;\n}\n\n/**\n * Common options for the default Backstage configuration sources.\n *\n * @public\n */\nexport interface BaseConfigSourcesOptions {\n watch?: boolean;\n rootDir?: string;\n remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;\n /**\n * Allow the default app-config.yaml to be missing, in which case the source\n * will not be created.\n */\n allowMissingDefaultConfig?: boolean;\n\n /**\n * A custom substitution function that overrides the default one.\n *\n * @remarks\n * The substitution function handles syntax like `${MY_ENV_VAR}` in configuration values.\n * The default substitution will read the value from the environment and trim whitespace.\n */\n substitutionFunc?: SubstitutionFunc;\n}\n\n/**\n * Options for {@link ConfigSources.defaultForTargets}.\n *\n * @public\n */\nexport interface ConfigSourcesDefaultForTargetsOptions\n extends BaseConfigSourcesOptions {\n targets: ConfigSourceTarget[];\n}\n\n/**\n * Options for {@link ConfigSources.default}.\n *\n * @public\n */\nexport interface ConfigSourcesDefaultOptions extends BaseConfigSourcesOptions {\n argv?: string[];\n env?: Record<string, string | undefined>;\n}\n\n/**\n * A collection of utilities for working with and creating {@link ConfigSource}s.\n *\n * @public\n */\nexport class ConfigSources {\n /**\n * Parses command line arguments and returns the config targets.\n *\n * @param argv - The command line arguments to parse. Defaults to `process.argv`\n * @returns A list of config targets\n */\n static parseArgs(argv: string[] = process.argv): ConfigSourceTarget[] {\n const args: string[] = [parseArgs(argv).config].flat().filter(Boolean);\n return args.map(target => {\n try {\n const url = new URL(target);\n\n // Some file paths are valid relative URLs, so check if the host is empty too\n if (!url.host) {\n return { type: 'path', target };\n }\n return { type: 'url', target };\n } catch {\n return { type: 'path', target };\n }\n });\n }\n\n /**\n * Creates the default config sources for the provided targets.\n *\n * @remarks\n *\n * This will create {@link FileConfigSource}s and {@link RemoteConfigSource}s\n * for the provided targets, and merge them together to a single source.\n * If no targets are provided it will fall back to `app-config.yaml` and\n * `app-config.local.yaml`.\n *\n * URL targets are only supported if the `remote` option is provided.\n *\n * @param options - Options\n * @returns A config source for the provided targets\n */\n static defaultForTargets(\n options: ConfigSourcesDefaultForTargetsOptions,\n ): ConfigSource {\n const rootDir = options.rootDir ?? findPaths(process.cwd()).targetRoot;\n\n const argSources = options.targets.map(arg => {\n if (arg.type === 'url') {\n if (!options.remote) {\n throw new Error(\n `Config argument \"${arg.target}\" looks like a URL but remote configuration is not enabled. Enable it by passing the \\`remote\\` option`,\n );\n }\n return RemoteConfigSource.create({\n url: arg.target,\n substitutionFunc: options.substitutionFunc,\n reloadInterval: options.remote.reloadInterval,\n });\n }\n return FileConfigSource.create({\n watch: options.watch,\n path: resolvePath(arg.target),\n substitutionFunc: options.substitutionFunc,\n });\n });\n\n if (argSources.length === 0) {\n const defaultPath = resolvePath(rootDir, 'app-config.yaml');\n const localPath = resolvePath(rootDir, 'app-config.local.yaml');\n const envPath = resolvePath(\n rootDir,\n `app-config.${process.env.BACKSTAGE_ENV}.yaml`,\n );\n const envLocalPath = resolvePath(\n rootDir,\n `app-config.${process.env.BACKSTAGE_ENV}.local.yaml`,\n );\n const alwaysIncludeDefaultConfigSource =\n !options.allowMissingDefaultConfig;\n\n if (alwaysIncludeDefaultConfigSource || fs.pathExistsSync(defaultPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: defaultPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n\n if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: envPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n\n if (fs.pathExistsSync(localPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: localPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n\n if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envLocalPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: envLocalPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n }\n\n return this.merge(argSources);\n }\n\n /**\n * Creates the default config source for Backstage.\n *\n * @remarks\n *\n * This will read from `app-config.yaml` and `app-config.local.yaml` by\n * default, as well as environment variables prefixed with `APP_CONFIG_`.\n * If `--config <path|url>` command line arguments are passed, these will\n * override the default configuration file paths. URLs are only supported\n * if the `remote` option is provided.\n *\n * @param options - Options\n * @returns The default Backstage config source\n */\n static default(options: ConfigSourcesDefaultOptions): ConfigSource {\n const argSource = this.defaultForTargets({\n ...options,\n targets: this.parseArgs(options.argv),\n });\n\n const envSource = EnvConfigSource.create({\n env: options.env,\n });\n\n return this.merge([argSource, envSource]);\n }\n\n /**\n * Merges multiple config sources into a single source that reads from all\n * sources and concatenates the result.\n *\n * @param sources - The config sources to merge\n * @returns A single config source that concatenates the data from the given sources\n */\n static merge(sources: ConfigSource[]): ConfigSource {\n return MergedConfigSource.from(sources);\n }\n\n /**\n * Creates an observable {@link @backstage/config#Config} implementation from a {@link ConfigSource}.\n *\n * @remarks\n *\n * If you only want to read the config once you can close the returned config immediately.\n *\n * @example\n *\n * ```ts\n * const sources = ConfigSources.default(...)\n * const config = await ConfigSources.toConfig(source)\n * config.close()\n * const example = config.getString(...)\n * ```\n *\n * @param source - The config source to read from\n * @returns A promise that resolves to a closable config\n */\n static toConfig(source: ConfigSource): Promise<ClosableConfig> {\n return new Promise(async (resolve, reject) => {\n let config: ObservableConfigProxy | undefined = undefined;\n try {\n const abortController = new AbortController();\n for await (const { configs } of source.readConfigData({\n signal: abortController.signal,\n })) {\n if (config) {\n config.setConfig(ConfigReader.fromConfigs(configs));\n } else {\n config = ObservableConfigProxy.create(abortController);\n config!.setConfig(ConfigReader.fromConfigs(configs));\n resolve(config);\n }\n }\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n"],"names":["parseArgs","findPaths","RemoteConfigSource","FileConfigSource","resolvePath","fs","EnvConfigSource","MergedConfigSource","config","ConfigReader","ObservableConfigProxy"],"mappings":"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"}
1
+ {"version":3,"file":"ConfigSources.cjs.js","sources":["../../src/sources/ConfigSources.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 { resolve as resolvePath } from 'node:path';\nimport fs from 'fs-extra';\nimport { Config, ConfigReader } from '@backstage/config';\nimport parseArgs from 'minimist';\nimport { EnvConfigSource } from './EnvConfigSource';\nimport { FileConfigSource } from './FileConfigSource';\nimport { MergedConfigSource } from './MergedConfigSource';\nimport {\n RemoteConfigSource,\n RemoteConfigSourceOptions,\n} from './RemoteConfigSource';\nimport { ConfigSource, SubstitutionFunc } from './types';\nimport { ObservableConfigProxy } from './ObservableConfigProxy';\nimport { findPaths } from '@backstage/cli-common';\n\n/**\n * A target to read configuration from.\n *\n * @public\n */\nexport type ConfigSourceTarget =\n | {\n type: 'path';\n target: string;\n }\n | {\n type: 'url';\n target: string;\n };\n\n/**\n * A config implementation that can be closed.\n *\n * @remarks\n *\n * Closing the configuration instance will stop the reading from the underlying source.\n *\n * @public\n */\nexport interface ClosableConfig extends Config {\n /**\n * Closes the configuration instance.\n *\n * @remarks\n *\n * The configuration instance will still be usable after closing, but it will\n * no longer be updated with new values from the underlying source.\n */\n close(): void;\n}\n\n/**\n * Common options for the default Backstage configuration sources.\n *\n * @public\n */\nexport interface BaseConfigSourcesOptions {\n watch?: boolean;\n rootDir?: string;\n remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;\n /**\n * Allow the default app-config.yaml to be missing, in which case the source\n * will not be created.\n */\n allowMissingDefaultConfig?: boolean;\n\n /**\n * A custom substitution function that overrides the default one.\n *\n * @remarks\n * The substitution function handles syntax like `${MY_ENV_VAR}` in configuration values.\n * The default substitution will read the value from the environment and trim whitespace.\n */\n substitutionFunc?: SubstitutionFunc;\n}\n\n/**\n * Options for {@link ConfigSources.defaultForTargets}.\n *\n * @public\n */\nexport interface ConfigSourcesDefaultForTargetsOptions\n extends BaseConfigSourcesOptions {\n targets: ConfigSourceTarget[];\n}\n\n/**\n * Options for {@link ConfigSources.default}.\n *\n * @public\n */\nexport interface ConfigSourcesDefaultOptions extends BaseConfigSourcesOptions {\n argv?: string[];\n env?: Record<string, string | undefined>;\n}\n\n/**\n * A collection of utilities for working with and creating {@link ConfigSource}s.\n *\n * @public\n */\nexport class ConfigSources {\n /**\n * Parses command line arguments and returns the config targets.\n *\n * @param argv - The command line arguments to parse. Defaults to `process.argv`\n * @returns A list of config targets\n */\n static parseArgs(argv: string[] = process.argv): ConfigSourceTarget[] {\n const args: string[] = [parseArgs(argv).config].flat().filter(Boolean);\n return args.map(target => {\n try {\n const url = new URL(target);\n\n // Some file paths are valid relative URLs, so check if the host is empty too\n if (!url.host) {\n return { type: 'path', target };\n }\n return { type: 'url', target };\n } catch {\n return { type: 'path', target };\n }\n });\n }\n\n /**\n * Creates the default config sources for the provided targets.\n *\n * @remarks\n *\n * This will create {@link FileConfigSource}s and {@link RemoteConfigSource}s\n * for the provided targets, and merge them together to a single source.\n * If no targets are provided it will fall back to `app-config.yaml` and\n * `app-config.local.yaml`.\n *\n * URL targets are only supported if the `remote` option is provided.\n *\n * @param options - Options\n * @returns A config source for the provided targets\n */\n static defaultForTargets(\n options: ConfigSourcesDefaultForTargetsOptions,\n ): ConfigSource {\n const rootDir = options.rootDir ?? findPaths(process.cwd()).targetRoot;\n\n const argSources = options.targets.map(arg => {\n if (arg.type === 'url') {\n if (!options.remote) {\n throw new Error(\n `Config argument \"${arg.target}\" looks like a URL but remote configuration is not enabled. Enable it by passing the \\`remote\\` option`,\n );\n }\n return RemoteConfigSource.create({\n url: arg.target,\n substitutionFunc: options.substitutionFunc,\n reloadInterval: options.remote.reloadInterval,\n });\n }\n return FileConfigSource.create({\n watch: options.watch,\n path: resolvePath(arg.target),\n substitutionFunc: options.substitutionFunc,\n });\n });\n\n if (argSources.length === 0) {\n const defaultPath = resolvePath(rootDir, 'app-config.yaml');\n const localPath = resolvePath(rootDir, 'app-config.local.yaml');\n const envPath = resolvePath(\n rootDir,\n `app-config.${process.env.BACKSTAGE_ENV}.yaml`,\n );\n const envLocalPath = resolvePath(\n rootDir,\n `app-config.${process.env.BACKSTAGE_ENV}.local.yaml`,\n );\n const alwaysIncludeDefaultConfigSource =\n !options.allowMissingDefaultConfig;\n\n if (alwaysIncludeDefaultConfigSource || fs.pathExistsSync(defaultPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: defaultPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n\n if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: envPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n\n if (fs.pathExistsSync(localPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: localPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n\n if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envLocalPath)) {\n argSources.push(\n FileConfigSource.create({\n watch: options.watch,\n path: envLocalPath,\n substitutionFunc: options.substitutionFunc,\n }),\n );\n }\n }\n\n return this.merge(argSources);\n }\n\n /**\n * Creates the default config source for Backstage.\n *\n * @remarks\n *\n * This will read from `app-config.yaml` and `app-config.local.yaml` by\n * default, as well as environment variables prefixed with `APP_CONFIG_`.\n * If `--config <path|url>` command line arguments are passed, these will\n * override the default configuration file paths. URLs are only supported\n * if the `remote` option is provided.\n *\n * @param options - Options\n * @returns The default Backstage config source\n */\n static default(options: ConfigSourcesDefaultOptions): ConfigSource {\n const argSource = this.defaultForTargets({\n ...options,\n targets: this.parseArgs(options.argv),\n });\n\n const envSource = EnvConfigSource.create({\n env: options.env,\n });\n\n return this.merge([argSource, envSource]);\n }\n\n /**\n * Merges multiple config sources into a single source that reads from all\n * sources and concatenates the result.\n *\n * @param sources - The config sources to merge\n * @returns A single config source that concatenates the data from the given sources\n */\n static merge(sources: ConfigSource[]): ConfigSource {\n return MergedConfigSource.from(sources);\n }\n\n /**\n * Creates an observable {@link @backstage/config#Config} implementation from a {@link ConfigSource}.\n *\n * @remarks\n *\n * If you only want to read the config once you can close the returned config immediately.\n *\n * @example\n *\n * ```ts\n * const sources = ConfigSources.default(...)\n * const config = await ConfigSources.toConfig(source)\n * config.close()\n * const example = config.getString(...)\n * ```\n *\n * @param source - The config source to read from\n * @returns A promise that resolves to a closable config\n */\n static toConfig(source: ConfigSource): Promise<ClosableConfig> {\n return new Promise(async (resolve, reject) => {\n let config: ObservableConfigProxy | undefined = undefined;\n try {\n const abortController = new AbortController();\n for await (const { configs } of source.readConfigData({\n signal: abortController.signal,\n })) {\n if (config) {\n config.setConfig(ConfigReader.fromConfigs(configs));\n } else {\n config = ObservableConfigProxy.create(abortController);\n config!.setConfig(ConfigReader.fromConfigs(configs));\n resolve(config);\n }\n }\n } catch (error) {\n reject(error);\n }\n });\n }\n}\n"],"names":["parseArgs","findPaths","RemoteConfigSource","FileConfigSource","resolvePath","fs","EnvConfigSource","MergedConfigSource","config","ConfigReader","ObservableConfigProxy"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var chokidar = require('chokidar');
4
4
  var fs = require('fs-extra');
5
- var path = require('path');
5
+ var node_path = require('node:path');
6
6
  var apply = require('./transform/apply.cjs.js');
7
7
  var errors = require('@backstage/errors');
8
8
  var utils = require('./utils.cjs.js');
@@ -39,7 +39,7 @@ class FileConfigSource {
39
39
  * @returns A new config source that loads from the given path.
40
40
  */
41
41
  static create(options) {
42
- if (!path.isAbsolute(options.path)) {
42
+ if (!node_path.isAbsolute(options.path)) {
43
43
  throw new Error(`Config load path is not absolute: "${options.path}"`);
44
44
  }
45
45
  return new FileConfigSource(options);
@@ -59,7 +59,7 @@ class FileConfigSource {
59
59
  // changes it might be worth refactoring this to avoid duplicate work.
60
60
  async *readConfigData(options) {
61
61
  const signal = options?.signal;
62
- const configFileName = path.basename(this.#path);
62
+ const configFileName = node_path.basename(this.#path);
63
63
  let watchedPaths = null;
64
64
  let watcher = null;
65
65
  if (this.#watch) {
@@ -68,11 +68,11 @@ class FileConfigSource {
68
68
  usePolling: process.env.NODE_ENV === "test"
69
69
  });
70
70
  }
71
- const dir = path.dirname(this.#path);
71
+ const dir = node_path.dirname(this.#path);
72
72
  const transformer = apply.createConfigTransformer({
73
73
  substitutionFunc: this.#substitutionFunc,
74
- readFile: async (path$1) => {
75
- const fullPath = path.resolve(dir, path$1);
74
+ readFile: async (path) => {
75
+ const fullPath = node_path.resolve(dir, path);
76
76
  if (watcher && watchedPaths) {
77
77
  watcher.add(fullPath);
78
78
  watchedPaths.push(fullPath);
@@ -1 +1 @@
1
- {"version":3,"file":"FileConfigSource.cjs.js","sources":["../../src/sources/FileConfigSource.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 chokidar, { FSWatcher } from 'chokidar';\nimport fs from 'fs-extra';\nimport { basename, dirname, isAbsolute, resolve as resolvePath } from 'path';\nimport {\n AsyncConfigSourceGenerator,\n ConfigSource,\n ConfigSourceData,\n SubstitutionFunc,\n Parser,\n ReadConfigDataOptions,\n} from './types';\nimport { createConfigTransformer } from './transform';\nimport { NotFoundError } from '@backstage/errors';\nimport { parseYamlContent } from './utils';\n\n/**\n * Options for {@link FileConfigSource.create}.\n *\n * @public\n */\nexport interface FileConfigSourceOptions {\n /**\n * The path to the config file that should be loaded.\n */\n path: string;\n\n /**\n * Set to `false` to disable file watching, defaults to `true`.\n */\n watch?: boolean;\n\n /**\n * A substitution function to use instead of the default environment substitution.\n */\n substitutionFunc?: SubstitutionFunc;\n\n /**\n * A content parsing function to transform string content to configuration values.\n */\n parser?: Parser;\n}\n\nasync function readFile(path: string): Promise<string | undefined> {\n try {\n const content = await fs.readFile(path, 'utf8');\n // During watching we may sometimes read files too early before the file content has been written.\n // We never expect the writing to take a long time, but if we encounter an empty file then check\n // again after a short delay for safety.\n if (content === '') {\n await new Promise(resolve => setTimeout(resolve, 10));\n return await fs.readFile(path, 'utf8');\n }\n return content;\n } catch (error) {\n if (error.code === 'ENOENT') {\n return undefined;\n }\n throw error;\n }\n}\n\n/**\n * A config source that loads configuration from a local file.\n *\n * @public\n */\nexport class FileConfigSource implements ConfigSource {\n /**\n * Creates a new config source that loads configuration from the given path.\n *\n * @remarks\n *\n * The source will watch the file for changes, as well as any referenced files.\n *\n * @param options - Options for the config source.\n * @returns A new config source that loads from the given path.\n */\n static create(options: FileConfigSourceOptions): ConfigSource {\n if (!isAbsolute(options.path)) {\n throw new Error(`Config load path is not absolute: \"${options.path}\"`);\n }\n return new FileConfigSource(options);\n }\n\n readonly #path: string;\n readonly #substitutionFunc?: SubstitutionFunc;\n readonly #watch?: boolean;\n readonly #parser: Parser;\n\n private constructor(options: FileConfigSourceOptions) {\n this.#path = options.path;\n this.#substitutionFunc = options.substitutionFunc;\n this.#watch = options.watch ?? true;\n this.#parser = options.parser ?? parseYamlContent;\n }\n\n // Work is duplicated across each read, in practice that should not\n // have any impact since there won't be multiple consumers. If that\n // changes it might be worth refactoring this to avoid duplicate work.\n async *readConfigData(\n options?: ReadConfigDataOptions,\n ): AsyncConfigSourceGenerator {\n const signal = options?.signal;\n const configFileName = basename(this.#path);\n\n let watchedPaths: Array<string> | null = null;\n let watcher: FSWatcher | null = null;\n\n if (this.#watch) {\n // Keep track of watched paths, since this is simpler than resetting the watcher\n watchedPaths = new Array<string>();\n watcher = chokidar.watch(this.#path, {\n usePolling: process.env.NODE_ENV === 'test',\n });\n }\n\n const dir = dirname(this.#path);\n const transformer = createConfigTransformer({\n substitutionFunc: this.#substitutionFunc,\n readFile: async path => {\n const fullPath = resolvePath(dir, path);\n if (watcher && watchedPaths) {\n // Any files discovered while reading this config should be watched too\n watcher.add(fullPath);\n watchedPaths.push(fullPath);\n }\n\n const data = await readFile(fullPath);\n if (data === undefined) {\n throw new NotFoundError(\n `failed to include \"${fullPath}\", file does not exist`,\n );\n }\n return data;\n },\n });\n\n // This is the entry point for reading the file, called initially and on change\n const readConfigFile = async (): Promise<ConfigSourceData[]> => {\n if (watcher && watchedPaths) {\n // We clear the watched files every time we initiate a new read\n watcher.unwatch(watchedPaths);\n watchedPaths.length = 0;\n\n watcher.add(this.#path);\n watchedPaths.push(this.#path);\n }\n\n const contents = await readFile(this.#path);\n if (contents === undefined) {\n throw new NotFoundError(`Config file \"${this.#path}\" does not exist`);\n }\n const { result: parsed } = await this.#parser({ contents });\n if (parsed === undefined) {\n return [];\n }\n try {\n const data = await transformer(parsed, { dir });\n return [{ data, context: configFileName, path: this.#path }];\n } catch (error) {\n throw new Error(\n `Failed to read config file at \"${this.#path}\", ${error.message}`,\n );\n }\n };\n\n const onAbort = () => {\n signal?.removeEventListener('abort', onAbort);\n if (watcher) watcher.close();\n };\n signal?.addEventListener('abort', onAbort);\n\n yield { configs: await readConfigFile() };\n\n if (watcher) {\n for (;;) {\n const event = await this.#waitForEvent(watcher, signal);\n if (event === 'abort') {\n return;\n }\n yield { configs: await readConfigFile() };\n }\n }\n }\n\n toString() {\n return `FileConfigSource{path=\"${this.#path}\"}`;\n }\n\n #waitForEvent(\n watcher: FSWatcher,\n signal?: AbortSignal,\n ): Promise<'change' | 'abort'> {\n return new Promise(resolve => {\n function onChange() {\n resolve('change');\n onDone();\n }\n function onAbort() {\n resolve('abort');\n onDone();\n }\n function onDone() {\n watcher.removeListener('change', onChange);\n signal?.removeEventListener('abort', onAbort);\n }\n watcher.addListener('change', onChange);\n signal?.addEventListener('abort', onAbort);\n });\n }\n}\n"],"names":["fs","isAbsolute","parseYamlContent","basename","chokidar","dirname","createConfigTransformer","path","resolvePath","NotFoundError"],"mappings":"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"}
1
+ {"version":3,"file":"FileConfigSource.cjs.js","sources":["../../src/sources/FileConfigSource.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 chokidar, { FSWatcher } from 'chokidar';\nimport fs from 'fs-extra';\nimport {\n basename,\n dirname,\n isAbsolute,\n resolve as resolvePath,\n} from 'node:path';\nimport {\n AsyncConfigSourceGenerator,\n ConfigSource,\n ConfigSourceData,\n SubstitutionFunc,\n Parser,\n ReadConfigDataOptions,\n} from './types';\nimport { createConfigTransformer } from './transform';\nimport { NotFoundError } from '@backstage/errors';\nimport { parseYamlContent } from './utils';\n\n/**\n * Options for {@link FileConfigSource.create}.\n *\n * @public\n */\nexport interface FileConfigSourceOptions {\n /**\n * The path to the config file that should be loaded.\n */\n path: string;\n\n /**\n * Set to `false` to disable file watching, defaults to `true`.\n */\n watch?: boolean;\n\n /**\n * A substitution function to use instead of the default environment substitution.\n */\n substitutionFunc?: SubstitutionFunc;\n\n /**\n * A content parsing function to transform string content to configuration values.\n */\n parser?: Parser;\n}\n\nasync function readFile(path: string): Promise<string | undefined> {\n try {\n const content = await fs.readFile(path, 'utf8');\n // During watching we may sometimes read files too early before the file content has been written.\n // We never expect the writing to take a long time, but if we encounter an empty file then check\n // again after a short delay for safety.\n if (content === '') {\n await new Promise(resolve => setTimeout(resolve, 10));\n return await fs.readFile(path, 'utf8');\n }\n return content;\n } catch (error) {\n if (error.code === 'ENOENT') {\n return undefined;\n }\n throw error;\n }\n}\n\n/**\n * A config source that loads configuration from a local file.\n *\n * @public\n */\nexport class FileConfigSource implements ConfigSource {\n /**\n * Creates a new config source that loads configuration from the given path.\n *\n * @remarks\n *\n * The source will watch the file for changes, as well as any referenced files.\n *\n * @param options - Options for the config source.\n * @returns A new config source that loads from the given path.\n */\n static create(options: FileConfigSourceOptions): ConfigSource {\n if (!isAbsolute(options.path)) {\n throw new Error(`Config load path is not absolute: \"${options.path}\"`);\n }\n return new FileConfigSource(options);\n }\n\n readonly #path: string;\n readonly #substitutionFunc?: SubstitutionFunc;\n readonly #watch?: boolean;\n readonly #parser: Parser;\n\n private constructor(options: FileConfigSourceOptions) {\n this.#path = options.path;\n this.#substitutionFunc = options.substitutionFunc;\n this.#watch = options.watch ?? true;\n this.#parser = options.parser ?? parseYamlContent;\n }\n\n // Work is duplicated across each read, in practice that should not\n // have any impact since there won't be multiple consumers. If that\n // changes it might be worth refactoring this to avoid duplicate work.\n async *readConfigData(\n options?: ReadConfigDataOptions,\n ): AsyncConfigSourceGenerator {\n const signal = options?.signal;\n const configFileName = basename(this.#path);\n\n let watchedPaths: Array<string> | null = null;\n let watcher: FSWatcher | null = null;\n\n if (this.#watch) {\n // Keep track of watched paths, since this is simpler than resetting the watcher\n watchedPaths = new Array<string>();\n watcher = chokidar.watch(this.#path, {\n usePolling: process.env.NODE_ENV === 'test',\n });\n }\n\n const dir = dirname(this.#path);\n const transformer = createConfigTransformer({\n substitutionFunc: this.#substitutionFunc,\n readFile: async path => {\n const fullPath = resolvePath(dir, path);\n if (watcher && watchedPaths) {\n // Any files discovered while reading this config should be watched too\n watcher.add(fullPath);\n watchedPaths.push(fullPath);\n }\n\n const data = await readFile(fullPath);\n if (data === undefined) {\n throw new NotFoundError(\n `failed to include \"${fullPath}\", file does not exist`,\n );\n }\n return data;\n },\n });\n\n // This is the entry point for reading the file, called initially and on change\n const readConfigFile = async (): Promise<ConfigSourceData[]> => {\n if (watcher && watchedPaths) {\n // We clear the watched files every time we initiate a new read\n watcher.unwatch(watchedPaths);\n watchedPaths.length = 0;\n\n watcher.add(this.#path);\n watchedPaths.push(this.#path);\n }\n\n const contents = await readFile(this.#path);\n if (contents === undefined) {\n throw new NotFoundError(`Config file \"${this.#path}\" does not exist`);\n }\n const { result: parsed } = await this.#parser({ contents });\n if (parsed === undefined) {\n return [];\n }\n try {\n const data = await transformer(parsed, { dir });\n return [{ data, context: configFileName, path: this.#path }];\n } catch (error) {\n throw new Error(\n `Failed to read config file at \"${this.#path}\", ${error.message}`,\n );\n }\n };\n\n const onAbort = () => {\n signal?.removeEventListener('abort', onAbort);\n if (watcher) watcher.close();\n };\n signal?.addEventListener('abort', onAbort);\n\n yield { configs: await readConfigFile() };\n\n if (watcher) {\n for (;;) {\n const event = await this.#waitForEvent(watcher, signal);\n if (event === 'abort') {\n return;\n }\n yield { configs: await readConfigFile() };\n }\n }\n }\n\n toString() {\n return `FileConfigSource{path=\"${this.#path}\"}`;\n }\n\n #waitForEvent(\n watcher: FSWatcher,\n signal?: AbortSignal,\n ): Promise<'change' | 'abort'> {\n return new Promise(resolve => {\n function onChange() {\n resolve('change');\n onDone();\n }\n function onAbort() {\n resolve('abort');\n onDone();\n }\n function onDone() {\n watcher.removeListener('change', onChange);\n signal?.removeEventListener('abort', onAbort);\n }\n watcher.addListener('change', onChange);\n signal?.addEventListener('abort', onAbort);\n });\n }\n}\n"],"names":["fs","isAbsolute","parseYamlContent","basename","chokidar","dirname","createConfigTransformer","resolvePath","NotFoundError"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var yaml = require('yaml');
4
- var path = require('path');
4
+ var node_path = require('node:path');
5
5
  var utils = require('./utils.cjs.js');
6
6
 
7
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
@@ -47,7 +47,7 @@ function createIncludeTransform(env, readFile, substitute) {
47
47
  switch (includeKey) {
48
48
  case "$file":
49
49
  try {
50
- const value = await readFile(path.resolve(dir, includeValue));
50
+ const value = await readFile(node_path.resolve(dir, includeValue));
51
51
  return { applied: true, value: value.trimEnd() };
52
52
  } catch (error) {
53
53
  throw new Error(`failed to read file ${includeValue}, ${error}`);
@@ -60,16 +60,16 @@ function createIncludeTransform(env, readFile, substitute) {
60
60
  }
61
61
  case "$include": {
62
62
  const [filePath, dataPath] = includeValue.split(/#(.*)/);
63
- const ext = path.extname(filePath);
63
+ const ext = node_path.extname(filePath);
64
64
  const parser = includeFileParser[ext];
65
65
  if (!parser) {
66
66
  throw new Error(
67
67
  `no configuration parser available for included file ${filePath}`
68
68
  );
69
69
  }
70
- const path$1 = path.resolve(dir, filePath);
71
- const content = await readFile(path$1);
72
- const newDir = path.dirname(path$1);
70
+ const path = node_path.resolve(dir, filePath);
71
+ const content = await readFile(path);
72
+ const newDir = node_path.dirname(path);
73
73
  const parts = dataPath ? dataPath.split(".") : [];
74
74
  let value;
75
75
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"include.cjs.js","sources":["../../../src/sources/transform/include.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 yaml from 'yaml';\nimport { extname, dirname, resolve as resolvePath } from 'path';\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { isObject } from './utils';\nimport { TransformFunc, ReadFileFunc } from './types';\nimport { SubstitutionFunc } from '../types';\n\nconst INCLUDE_KEYS = ['$file', '$env', '$include'];\n\n// Parsers for each type of included file\nconst includeFileParser: {\n [ext in string]: (content: string) => Promise<JsonObject>;\n} = {\n '.json': async content => JSON.parse(content),\n '.yaml': async content => yaml.parse(content),\n '.yml': async content => yaml.parse(content),\n};\n\n/**\n * Transforms a include description into the actual included value.\n */\nexport function createIncludeTransform(\n env: SubstitutionFunc,\n readFile: ReadFileFunc,\n substitute: TransformFunc,\n): TransformFunc {\n return async (input, context) => {\n const { dir } = context;\n if (!dir) {\n throw new Error('Include transform requires a base directory');\n }\n if (!isObject(input)) {\n return { applied: false };\n }\n // Check if there's any key that starts with a '$', in that case we treat\n // this entire object as an include description.\n const [includeKey] = Object.keys(input).filter(key =>\n INCLUDE_KEYS.includes(key),\n );\n if (includeKey) {\n if (Object.keys(input).length !== 1) {\n throw new Error(\n `include key ${includeKey} should not have adjacent keys`,\n );\n }\n } else {\n return { applied: false };\n }\n\n const rawIncludedValue = input[includeKey];\n if (typeof rawIncludedValue !== 'string') {\n throw new Error(`${includeKey} include value is not a string`);\n }\n\n const substituteResults = await substitute(rawIncludedValue, { dir });\n const includeValue = substituteResults.applied\n ? substituteResults.value\n : rawIncludedValue;\n\n // The second string check is needed for Typescript to know this is a string.\n if (includeValue === undefined || typeof includeValue !== 'string') {\n throw new Error(`${includeKey} substitution value was undefined`);\n }\n\n switch (includeKey) {\n case '$file':\n try {\n const value = await readFile(resolvePath(dir, includeValue));\n return { applied: true, value: value.trimEnd() };\n } catch (error) {\n throw new Error(`failed to read file ${includeValue}, ${error}`);\n }\n case '$env':\n try {\n return { applied: true, value: await env(includeValue) };\n } catch (error) {\n throw new Error(`failed to read env ${includeValue}, ${error}`);\n }\n\n case '$include': {\n const [filePath, dataPath] = includeValue.split(/#(.*)/);\n\n const ext = extname(filePath);\n const parser = includeFileParser[ext];\n if (!parser) {\n throw new Error(\n `no configuration parser available for included file ${filePath}`,\n );\n }\n\n const path = resolvePath(dir, filePath);\n const content = await readFile(path);\n const newDir = dirname(path);\n\n const parts = dataPath ? dataPath.split('.') : [];\n\n let value: JsonValue | undefined;\n try {\n value = await parser(content);\n } catch (error) {\n throw new Error(\n `failed to parse included file ${filePath}, ${error}`,\n );\n }\n\n // This bit handles selecting a subtree in the included file, if a path was provided after a #\n for (const [index, part] of parts.entries()) {\n if (!isObject(value)) {\n const errPath = parts.slice(0, index).join('.');\n throw new Error(\n `value at '${errPath}' in included file ${filePath} is not an object`,\n );\n }\n value = value[part];\n }\n\n if (typeof value === 'string') {\n const substituted = await substitute(value, { dir: newDir });\n if (substituted.applied) {\n value = substituted.value;\n }\n }\n\n return {\n applied: true,\n value,\n newDir: newDir !== dir ? newDir : undefined,\n };\n }\n\n default:\n throw new Error(`unknown include ${includeKey}`);\n }\n };\n}\n"],"names":["yaml","isObject","resolvePath","extname","path","dirname"],"mappings":"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"}
1
+ {"version":3,"file":"include.cjs.js","sources":["../../../src/sources/transform/include.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 yaml from 'yaml';\nimport { extname, dirname, resolve as resolvePath } from 'node:path';\nimport { JsonObject, JsonValue } from '@backstage/types';\nimport { isObject } from './utils';\nimport { TransformFunc, ReadFileFunc } from './types';\nimport { SubstitutionFunc } from '../types';\n\nconst INCLUDE_KEYS = ['$file', '$env', '$include'];\n\n// Parsers for each type of included file\nconst includeFileParser: {\n [ext in string]: (content: string) => Promise<JsonObject>;\n} = {\n '.json': async content => JSON.parse(content),\n '.yaml': async content => yaml.parse(content),\n '.yml': async content => yaml.parse(content),\n};\n\n/**\n * Transforms a include description into the actual included value.\n */\nexport function createIncludeTransform(\n env: SubstitutionFunc,\n readFile: ReadFileFunc,\n substitute: TransformFunc,\n): TransformFunc {\n return async (input, context) => {\n const { dir } = context;\n if (!dir) {\n throw new Error('Include transform requires a base directory');\n }\n if (!isObject(input)) {\n return { applied: false };\n }\n // Check if there's any key that starts with a '$', in that case we treat\n // this entire object as an include description.\n const [includeKey] = Object.keys(input).filter(key =>\n INCLUDE_KEYS.includes(key),\n );\n if (includeKey) {\n if (Object.keys(input).length !== 1) {\n throw new Error(\n `include key ${includeKey} should not have adjacent keys`,\n );\n }\n } else {\n return { applied: false };\n }\n\n const rawIncludedValue = input[includeKey];\n if (typeof rawIncludedValue !== 'string') {\n throw new Error(`${includeKey} include value is not a string`);\n }\n\n const substituteResults = await substitute(rawIncludedValue, { dir });\n const includeValue = substituteResults.applied\n ? substituteResults.value\n : rawIncludedValue;\n\n // The second string check is needed for Typescript to know this is a string.\n if (includeValue === undefined || typeof includeValue !== 'string') {\n throw new Error(`${includeKey} substitution value was undefined`);\n }\n\n switch (includeKey) {\n case '$file':\n try {\n const value = await readFile(resolvePath(dir, includeValue));\n return { applied: true, value: value.trimEnd() };\n } catch (error) {\n throw new Error(`failed to read file ${includeValue}, ${error}`);\n }\n case '$env':\n try {\n return { applied: true, value: await env(includeValue) };\n } catch (error) {\n throw new Error(`failed to read env ${includeValue}, ${error}`);\n }\n\n case '$include': {\n const [filePath, dataPath] = includeValue.split(/#(.*)/);\n\n const ext = extname(filePath);\n const parser = includeFileParser[ext];\n if (!parser) {\n throw new Error(\n `no configuration parser available for included file ${filePath}`,\n );\n }\n\n const path = resolvePath(dir, filePath);\n const content = await readFile(path);\n const newDir = dirname(path);\n\n const parts = dataPath ? dataPath.split('.') : [];\n\n let value: JsonValue | undefined;\n try {\n value = await parser(content);\n } catch (error) {\n throw new Error(\n `failed to parse included file ${filePath}, ${error}`,\n );\n }\n\n // This bit handles selecting a subtree in the included file, if a path was provided after a #\n for (const [index, part] of parts.entries()) {\n if (!isObject(value)) {\n const errPath = parts.slice(0, index).join('.');\n throw new Error(\n `value at '${errPath}' in included file ${filePath} is not an object`,\n );\n }\n value = value[part];\n }\n\n if (typeof value === 'string') {\n const substituted = await substitute(value, { dir: newDir });\n if (substituted.applied) {\n value = substituted.value;\n }\n }\n\n return {\n applied: true,\n value,\n newDir: newDir !== dir ? newDir : undefined,\n };\n }\n\n default:\n throw new Error(`unknown include ${includeKey}`);\n }\n };\n}\n"],"names":["yaml","isObject","resolvePath","extname","dirname"],"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.7",
3
+ "version": "1.10.8-next.0",
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.16",
40
- "@backstage/config": "^1.3.6",
41
- "@backstage/errors": "^1.2.7",
42
- "@backstage/types": "^1.2.2",
39
+ "@backstage/cli-common": "0.1.18-next.0",
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",
@@ -53,8 +53,8 @@
53
53
  "yaml": "^2.0.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@backstage/backend-test-utils": "^1.10.2",
57
- "@backstage/cli": "^0.35.0",
56
+ "@backstage/backend-test-utils": "1.10.4-next.0",
57
+ "@backstage/cli": "0.35.3-next.0",
58
58
  "@types/json-schema-merge-allof": "^0.6.0",
59
59
  "@types/minimist": "^1.2.5",
60
60
  "msw": "^2.0.0",