@backstage/config-loader 1.10.12 → 1.11.0-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 +12 -0
- package/dist/index.d.ts +6 -0
- package/dist/schema/collect.cjs.js +167 -60
- package/dist/schema/collect.cjs.js.map +1 -1
- package/dist/schema/load.cjs.js +4 -1
- package/dist/schema/load.cjs.js.map +1 -1
- package/dist/sources/ConfigSources.cjs.js +25 -23
- package/dist/sources/ConfigSources.cjs.js.map +1 -1
- package/package.json +9 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage/config-loader
|
|
2
2
|
|
|
3
|
+
## 1.11.0-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 005458a: Added support for comma-separated values in the `BACKSTAGE_ENV` environment variable, allowing multiple environment-specific configuration files to be loaded and stacked at startup. For example, setting `BACKSTAGE_ENV=e2e-test,production` will load `app-config.e2e-test.yaml` and `app-config.production.yaml` in addition to the base `app-config.yaml`, with later environments taking priority. Local override files (`.local.yaml`) are always loaded after all non-local files.
|
|
8
|
+
|
|
9
|
+
## 1.11.0-next.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 4a7240b: Configuration schemas declared in TypeScript now resolve and validate imported types instead of treating them as unconstrained values. Invalid imports now cause schema loading to fail.
|
|
14
|
+
|
|
3
15
|
## 1.10.12
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -89,6 +89,12 @@ declare function mergeConfigSchemas(schemas: JSONSchema7[]): JSONSchema7;
|
|
|
89
89
|
type LoadConfigSchemaOptions = ({
|
|
90
90
|
dependencies: string[];
|
|
91
91
|
packagePaths?: string[];
|
|
92
|
+
/**
|
|
93
|
+
* Whether to exclude schemas from package dependencies.
|
|
94
|
+
*
|
|
95
|
+
* Defaults to `false`.
|
|
96
|
+
*/
|
|
97
|
+
excludePackageDependencies?: boolean;
|
|
92
98
|
} | {
|
|
93
99
|
serialized: JsonObject;
|
|
94
100
|
}) & {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var fs = require('fs-extra');
|
|
4
|
-
var
|
|
4
|
+
var node_crypto = require('node:crypto');
|
|
5
5
|
var node_path = require('node:path');
|
|
6
|
-
var errors = require('@backstage/errors');
|
|
7
6
|
|
|
8
7
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
9
8
|
|
|
@@ -15,7 +14,7 @@ const internal = {
|
|
|
15
14
|
return req.resolve(name, options);
|
|
16
15
|
}
|
|
17
16
|
};
|
|
18
|
-
async function collectConfigSchemas(packageNames, packagePaths) {
|
|
17
|
+
async function collectConfigSchemas(packageNames, packagePaths, options) {
|
|
19
18
|
const schemas = new Array();
|
|
20
19
|
const tsSchemaPaths = new Array();
|
|
21
20
|
const visitedPackageVersions = /* @__PURE__ */ new Map();
|
|
@@ -95,11 +94,13 @@ async function collectConfigSchemas(packageNames, packagePaths) {
|
|
|
95
94
|
});
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
(
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
if (!options?.excludePackageDependencies) {
|
|
98
|
+
await Promise.all(
|
|
99
|
+
depNames.map(
|
|
100
|
+
(depName) => processItem({ name: depName, parentPath: pkgPath })
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
103
104
|
}
|
|
104
105
|
await Promise.all([
|
|
105
106
|
...packageNames.map((name) => processItem({ name, parentPath: currentDir })),
|
|
@@ -117,67 +118,173 @@ async function collectConfigSchemas(packageNames, packagePaths) {
|
|
|
117
118
|
}
|
|
118
119
|
return allSchemas;
|
|
119
120
|
}
|
|
121
|
+
function namespaceSchemaDefinitions(schema, namespace) {
|
|
122
|
+
const definitions = schema.definitions;
|
|
123
|
+
if (!definitions || typeof definitions !== "object" || Array.isArray(definitions) || Object.keys(definitions).length === 0) {
|
|
124
|
+
delete schema.definitions;
|
|
125
|
+
return schema;
|
|
126
|
+
}
|
|
127
|
+
const renamedDefinitions = Object.fromEntries(
|
|
128
|
+
Object.entries(definitions).map(([name, definition]) => [
|
|
129
|
+
`${namespace}-${name}`,
|
|
130
|
+
definition
|
|
131
|
+
])
|
|
132
|
+
);
|
|
133
|
+
const renamedRefs = /* @__PURE__ */ new Map();
|
|
134
|
+
for (const name of Object.keys(definitions)) {
|
|
135
|
+
const renamed = `${namespace}-${name}`;
|
|
136
|
+
renamedRefs.set(`#/definitions/${name}`, `#/definitions/${renamed}`);
|
|
137
|
+
renamedRefs.set(
|
|
138
|
+
`#/definitions/${encodeURIComponent(name)}`,
|
|
139
|
+
`#/definitions/${encodeURIComponent(renamed)}`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
function rewriteRefs(value) {
|
|
143
|
+
if (Array.isArray(value)) {
|
|
144
|
+
value.forEach(rewriteRefs);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (!value || typeof value !== "object") {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const object = value;
|
|
151
|
+
if (typeof object.$ref === "string") {
|
|
152
|
+
object.$ref = renamedRefs.get(object.$ref) ?? object.$ref;
|
|
153
|
+
}
|
|
154
|
+
Object.values(object).forEach(rewriteRefs);
|
|
155
|
+
}
|
|
156
|
+
schema.definitions = renamedDefinitions;
|
|
157
|
+
rewriteRefs(schema);
|
|
158
|
+
return schema;
|
|
159
|
+
}
|
|
160
|
+
function parseNestedSchemaAnnotation(annotation) {
|
|
161
|
+
if (typeof annotation !== "string") {
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
const match = annotation.match(/^\.([\w-]+)\s+([\s\S]+)$/);
|
|
165
|
+
if (!match) {
|
|
166
|
+
return void 0;
|
|
167
|
+
}
|
|
168
|
+
const [, key, text] = match;
|
|
169
|
+
let value = text.trim();
|
|
170
|
+
try {
|
|
171
|
+
value = JSON.parse(value);
|
|
172
|
+
} catch {
|
|
173
|
+
}
|
|
174
|
+
return { key, value };
|
|
175
|
+
}
|
|
120
176
|
async function compileTsSchemas(entries) {
|
|
121
177
|
if (entries.length === 0) {
|
|
122
178
|
return [];
|
|
123
179
|
}
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
180
|
+
const ts = require("typescript");
|
|
181
|
+
const {
|
|
182
|
+
AnnotatedTypeFormatter,
|
|
183
|
+
createFormatter,
|
|
184
|
+
createParser,
|
|
185
|
+
DEFAULT_CONFIG,
|
|
186
|
+
SchemaGenerator
|
|
187
|
+
} = require("ts-json-schema-generator");
|
|
188
|
+
const currentDir = process.cwd();
|
|
189
|
+
const rootNames = entries.map(({ path }) => node_path.resolve(currentDir, path));
|
|
190
|
+
const compilerOptions = {
|
|
191
|
+
incremental: false,
|
|
192
|
+
jsx: ts.JsxEmit.Preserve,
|
|
193
|
+
module: ts.ModuleKind.ESNext,
|
|
194
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
195
|
+
noEmit: true,
|
|
196
|
+
noResolve: false,
|
|
197
|
+
skipDefaultLibCheck: true,
|
|
198
|
+
skipLibCheck: false,
|
|
199
|
+
strict: true,
|
|
200
|
+
target: ts.ScriptTarget.ES2022,
|
|
201
|
+
types: []
|
|
202
|
+
};
|
|
203
|
+
const program = ts.createProgram(rootNames, compilerOptions);
|
|
204
|
+
const diagnostics = [
|
|
205
|
+
...program.getOptionsDiagnostics(),
|
|
206
|
+
...program.getGlobalDiagnostics(),
|
|
207
|
+
...rootNames.flatMap((rootName) => {
|
|
208
|
+
const sourceFile = program.getSourceFile(rootName);
|
|
209
|
+
return sourceFile ? [
|
|
210
|
+
...program.getSyntacticDiagnostics(sourceFile),
|
|
211
|
+
...program.getSemanticDiagnostics(sourceFile)
|
|
212
|
+
] : [];
|
|
213
|
+
})
|
|
214
|
+
];
|
|
215
|
+
if (diagnostics.length > 0) {
|
|
216
|
+
const message = ts.formatDiagnostics(diagnostics, {
|
|
217
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
218
|
+
getCurrentDirectory: () => currentDir,
|
|
219
|
+
getNewLine: () => "\n"
|
|
220
|
+
});
|
|
221
|
+
throw new Error(`Invalid TypeScript configuration schema:
|
|
222
|
+
${message}`);
|
|
223
|
+
}
|
|
224
|
+
const generatorConfig = {
|
|
225
|
+
...DEFAULT_CONFIG,
|
|
226
|
+
additionalProperties: true,
|
|
227
|
+
expose: "none",
|
|
228
|
+
extraTags: ["visibility", "deepVisibility", "deprecated", "items"],
|
|
229
|
+
jsDoc: "extended",
|
|
230
|
+
skipTypeCheck: true,
|
|
231
|
+
topRef: false,
|
|
232
|
+
tsProgram: program
|
|
233
|
+
};
|
|
234
|
+
const parser = createParser(program, generatorConfig);
|
|
235
|
+
class NestedAnnotationsFormatter extends AnnotatedTypeFormatter {
|
|
236
|
+
getDefinition(type) {
|
|
237
|
+
const annotations = type.getAnnotations();
|
|
238
|
+
const itemsAnnotation = annotations.items;
|
|
239
|
+
const nestedItems = parseNestedSchemaAnnotation(itemsAnnotation);
|
|
240
|
+
if (!nestedItems) {
|
|
241
|
+
return super.getDefinition(type);
|
|
171
242
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
243
|
+
delete annotations.items;
|
|
244
|
+
try {
|
|
245
|
+
const definition = super.getDefinition(type);
|
|
246
|
+
const items = definition.items;
|
|
247
|
+
if (items && typeof items === "object" && !Array.isArray(items)) {
|
|
248
|
+
Object.assign(items, { [nestedItems.key]: nestedItems.value });
|
|
249
|
+
}
|
|
250
|
+
return definition;
|
|
251
|
+
} finally {
|
|
252
|
+
annotations.items = itemsAnnotation;
|
|
176
253
|
}
|
|
177
254
|
}
|
|
178
|
-
|
|
255
|
+
}
|
|
256
|
+
const formatter = createFormatter(
|
|
257
|
+
generatorConfig,
|
|
258
|
+
(chainFormatter, circularReferenceFormatter) => {
|
|
259
|
+
chainFormatter.addTypeFormatter(
|
|
260
|
+
new NestedAnnotationsFormatter(circularReferenceFormatter)
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
const generator = new SchemaGenerator(
|
|
265
|
+
program,
|
|
266
|
+
parser,
|
|
267
|
+
formatter,
|
|
268
|
+
generatorConfig
|
|
269
|
+
);
|
|
270
|
+
const tsSchemas = entries.map(({ path, packageName }, index) => {
|
|
271
|
+
const sourceFile = program.getSourceFile(rootNames[index]);
|
|
272
|
+
if (!sourceFile) {
|
|
179
273
|
throw new Error(`Invalid schema in ${path}, missing Config export`);
|
|
180
274
|
}
|
|
275
|
+
const configNode = sourceFile.statements.find(
|
|
276
|
+
(statement) => (ts.isInterfaceDeclaration(statement) || ts.isTypeAliasDeclaration(statement)) && statement.name.text === "Config"
|
|
277
|
+
);
|
|
278
|
+
if (!configNode) {
|
|
279
|
+
throw new Error(`Invalid schema in ${path}, missing Config export`);
|
|
280
|
+
}
|
|
281
|
+
const namespace = node_crypto.createHash("sha256").update(packageName).update("\0").update(path.split(node_path.sep).join("/")).digest("hex");
|
|
282
|
+
const value = namespaceSchemaDefinitions(
|
|
283
|
+
structuredClone(
|
|
284
|
+
generator.createSchemaFromNodes([configNode])
|
|
285
|
+
),
|
|
286
|
+
namespace
|
|
287
|
+
);
|
|
181
288
|
return { path, value, packageName };
|
|
182
289
|
});
|
|
183
290
|
return tsSchemas;
|
|
@@ -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 { 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":"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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 type * as TsJsonSchemaGenerator from 'ts-json-schema-generator';\nimport type * as TypeScript from 'typescript';\nimport { createHash } from 'node:crypto';\nimport {\n resolve as resolvePath,\n relative as relativePath,\n dirname,\n sep,\n} from 'node:path';\nimport { ConfigSchemaPackageEntry } from './types';\nimport type { JsonObject } from '@backstage/types';\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 options?: { excludePackageDependencies?: boolean },\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 if (!options?.excludePackageDependencies) {\n await Promise.all(\n depNames.map(depName =>\n processItem({ name: depName, parentPath: pkgPath }),\n ),\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\nfunction namespaceSchemaDefinitions(\n schema: JsonObject,\n namespace: string,\n): JsonObject {\n const definitions = schema.definitions;\n if (\n !definitions ||\n typeof definitions !== 'object' ||\n Array.isArray(definitions) ||\n Object.keys(definitions).length === 0\n ) {\n delete schema.definitions;\n return schema;\n }\n\n const renamedDefinitions = Object.fromEntries(\n Object.entries(definitions).map(([name, definition]) => [\n `${namespace}-${name}`,\n definition,\n ]),\n );\n const renamedRefs = new Map<string, string>();\n for (const name of Object.keys(definitions)) {\n const renamed = `${namespace}-${name}`;\n renamedRefs.set(`#/definitions/${name}`, `#/definitions/${renamed}`);\n renamedRefs.set(\n `#/definitions/${encodeURIComponent(name)}`,\n `#/definitions/${encodeURIComponent(renamed)}`,\n );\n }\n\n function rewriteRefs(value: unknown): void {\n if (Array.isArray(value)) {\n value.forEach(rewriteRefs);\n return;\n }\n if (!value || typeof value !== 'object') {\n return;\n }\n\n const object = value as Record<string, unknown>;\n if (typeof object.$ref === 'string') {\n object.$ref = renamedRefs.get(object.$ref) ?? object.$ref;\n }\n Object.values(object).forEach(rewriteRefs);\n }\n\n schema.definitions = renamedDefinitions;\n rewriteRefs(schema);\n return schema;\n}\n\nfunction parseNestedSchemaAnnotation(annotation: unknown) {\n if (typeof annotation !== 'string') {\n return undefined;\n }\n\n const match = annotation.match(/^\\.([\\w-]+)\\s+([\\s\\S]+)$/);\n if (!match) {\n return undefined;\n }\n\n const [, key, text] = match;\n let value: unknown = text.trim();\n try {\n value = JSON.parse(value as string);\n } catch {\n // Plain strings such as visibility values are not JSON encoded.\n }\n return { key, value };\n}\n\n// This handles the support of TypeScript .d.ts config schema declarations.\n// We collect all TypeScript schema definitions and compile them in one shared\n// program, which avoids repeatedly resolving and parsing imported types.\nasync function compileTsSchemas(\n entries: { path: string; packageName: string }[],\n) {\n if (entries.length === 0) {\n return [];\n }\n\n // Lazy loaded, because these bring up all of TypeScript and we don't want\n // that eagerly loaded when collecting JSON schemas.\n const ts: typeof TypeScript = require('typescript');\n const {\n AnnotatedTypeFormatter,\n createFormatter,\n createParser,\n DEFAULT_CONFIG,\n SchemaGenerator,\n }: typeof TsJsonSchemaGenerator = require('ts-json-schema-generator');\n\n const currentDir = process.cwd();\n const rootNames = entries.map(({ path }) => resolvePath(currentDir, path));\n const compilerOptions: TypeScript.CompilerOptions = {\n incremental: false,\n jsx: ts.JsxEmit.Preserve,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n noEmit: true,\n noResolve: false,\n skipDefaultLibCheck: true,\n skipLibCheck: false,\n strict: true,\n target: ts.ScriptTarget.ES2022,\n types: [],\n };\n\n const program = ts.createProgram(rootNames, compilerOptions);\n const diagnostics = [\n ...program.getOptionsDiagnostics(),\n ...program.getGlobalDiagnostics(),\n ...rootNames.flatMap(rootName => {\n const sourceFile = program.getSourceFile(rootName);\n return sourceFile\n ? [\n ...program.getSyntacticDiagnostics(sourceFile),\n ...program.getSemanticDiagnostics(sourceFile),\n ]\n : [];\n }),\n ];\n if (diagnostics.length > 0) {\n const message = ts.formatDiagnostics(diagnostics, {\n getCanonicalFileName: fileName => fileName,\n getCurrentDirectory: () => currentDir,\n getNewLine: () => '\\n',\n });\n throw new Error(`Invalid TypeScript configuration schema:\\n${message}`);\n }\n\n const generatorConfig = {\n ...DEFAULT_CONFIG,\n additionalProperties: true,\n expose: 'none' as const,\n extraTags: ['visibility', 'deepVisibility', 'deprecated', 'items'],\n jsDoc: 'extended' as const,\n skipTypeCheck: true,\n topRef: false,\n tsProgram: program,\n };\n const parser = createParser(program, generatorConfig);\n class NestedAnnotationsFormatter extends AnnotatedTypeFormatter {\n override getDefinition(type: TsJsonSchemaGenerator.AnnotatedType) {\n const annotations = type.getAnnotations();\n const itemsAnnotation = annotations.items;\n const nestedItems = parseNestedSchemaAnnotation(itemsAnnotation);\n if (!nestedItems) {\n return super.getDefinition(type);\n }\n\n delete annotations.items;\n try {\n const definition = super.getDefinition(type);\n const items = definition.items;\n if (items && typeof items === 'object' && !Array.isArray(items)) {\n Object.assign(items, { [nestedItems.key]: nestedItems.value });\n }\n return definition;\n } finally {\n annotations.items = itemsAnnotation;\n }\n }\n }\n const formatter = createFormatter(\n generatorConfig,\n (chainFormatter, circularReferenceFormatter) => {\n chainFormatter.addTypeFormatter(\n new NestedAnnotationsFormatter(circularReferenceFormatter),\n );\n },\n );\n const generator = new SchemaGenerator(\n program,\n parser,\n formatter,\n generatorConfig,\n );\n\n const tsSchemas = entries.map(({ path, packageName }, index) => {\n const sourceFile = program.getSourceFile(rootNames[index]);\n if (!sourceFile) {\n throw new Error(`Invalid schema in ${path}, missing Config export`);\n }\n const configNode = sourceFile.statements.find(\n statement =>\n (ts.isInterfaceDeclaration(statement) ||\n ts.isTypeAliasDeclaration(statement)) &&\n statement.name.text === 'Config',\n );\n if (!configNode) {\n throw new Error(`Invalid schema in ${path}, missing Config export`);\n }\n\n const namespace = createHash('sha256')\n .update(packageName)\n .update('\\0')\n .update(path.split(sep).join('/'))\n .digest('hex');\n const value = namespaceSchemaDefinitions(\n structuredClone(\n generator.createSchemaFromNodes([configNode]),\n ) as JsonObject,\n namespace,\n );\n\n return { path, value, packageName };\n });\n\n return tsSchemas;\n}\n"],"names":["fs","relativePath","resolvePath","dirname","createHash","sep"],"mappings":"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"}
|
package/dist/schema/load.cjs.js
CHANGED
|
@@ -22,7 +22,10 @@ async function loadConfigSchema(options) {
|
|
|
22
22
|
if ("dependencies" in options) {
|
|
23
23
|
schemas = await collect.collectConfigSchemas(
|
|
24
24
|
options.dependencies,
|
|
25
|
-
options.packagePaths ?? []
|
|
25
|
+
options.packagePaths ?? [],
|
|
26
|
+
{
|
|
27
|
+
excludePackageDependencies: options.excludePackageDependencies
|
|
28
|
+
}
|
|
26
29
|
);
|
|
27
30
|
} else {
|
|
28
31
|
const { serialized } = options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load.cjs.js","sources":["../../src/schema/load.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 { AppConfig } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { compileConfigSchemas } from './compile';\nimport { collectConfigSchemas } from './collect';\nimport { filterByVisibility, filterErrorsByVisibility } from './filtering';\nimport {\n ValidationError,\n ConfigSchema,\n ConfigSchemaPackageEntry,\n CONFIG_VISIBILITIES,\n} from './types';\nimport { normalizeAjvPath } from './utils';\n\n/**\n * Options that control the loading of configuration schema files in the backend.\n *\n * @public\n */\nexport type LoadConfigSchemaOptions =\n | (\n | {\n dependencies: string[];\n packagePaths?: string[];\n }\n | {\n serialized: JsonObject;\n }\n ) & {\n noUndeclaredProperties?: boolean;\n };\n\nfunction errorsToError(errors: ValidationError[]): Error {\n const messages = errors.map(({ instancePath, message, params }) => {\n const paramStr = Object.entries(params)\n .map(([name, value]) => `${name}=${value}`)\n .join(' ');\n return `Config ${message || ''} { ${paramStr} } at ${normalizeAjvPath(\n instancePath,\n )}`;\n });\n const error = new Error(`Config validation failed, ${messages.join('; ')}`);\n (error as any).messages = messages;\n return error;\n}\n\n/**\n * Loads config schema for a Backstage instance.\n *\n * @public\n */\nexport async function loadConfigSchema(\n options: LoadConfigSchemaOptions,\n): Promise<ConfigSchema> {\n let schemas: ConfigSchemaPackageEntry[];\n\n if ('dependencies' in options) {\n schemas = await collectConfigSchemas(\n options.dependencies,\n options.packagePaths ?? [],\n );\n } else {\n const { serialized } = options;\n if (serialized?.backstageConfigSchemaVersion !== 1) {\n throw new Error(\n 'Serialized configuration schema is invalid or has an invalid version number',\n );\n }\n schemas = serialized.schemas as ConfigSchemaPackageEntry[];\n }\n\n const validate = compileConfigSchemas(schemas, {\n noUndeclaredProperties: options.noUndeclaredProperties,\n });\n\n return {\n process(\n configs: AppConfig[],\n {\n visibility,\n valueTransform,\n withFilteredKeys,\n withDeprecatedKeys,\n ignoreSchemaErrors,\n } = {},\n ): AppConfig[] {\n const result = validate(configs);\n\n if (!ignoreSchemaErrors) {\n const visibleErrors = filterErrorsByVisibility(\n result.errors,\n visibility,\n result.visibilityByDataPath,\n result.visibilityBySchemaPath,\n );\n if (visibleErrors.length > 0) {\n throw errorsToError(visibleErrors);\n }\n }\n\n let processedConfigs = configs;\n\n if (visibility) {\n processedConfigs = processedConfigs.map(({ data, context }) => ({\n context,\n ...filterByVisibility(\n data,\n visibility,\n result.visibilityByDataPath,\n result.deepVisibilityByDataPath,\n result.deprecationByDataPath,\n valueTransform,\n withFilteredKeys,\n withDeprecatedKeys,\n ),\n }));\n } else if (valueTransform) {\n processedConfigs = processedConfigs.map(({ data, context }) => ({\n context,\n ...filterByVisibility(\n data,\n Array.from(CONFIG_VISIBILITIES),\n result.visibilityByDataPath,\n result.deepVisibilityByDataPath,\n result.deprecationByDataPath,\n valueTransform,\n withFilteredKeys,\n withDeprecatedKeys,\n ),\n }));\n }\n\n return processedConfigs;\n },\n serialize(): JsonObject {\n return {\n schemas,\n backstageConfigSchemaVersion: 1,\n };\n },\n };\n}\n"],"names":["normalizeAjvPath","collectConfigSchemas","compileConfigSchemas","filterErrorsByVisibility","filterByVisibility","CONFIG_VISIBILITIES"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"load.cjs.js","sources":["../../src/schema/load.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 { AppConfig } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { compileConfigSchemas } from './compile';\nimport { collectConfigSchemas } from './collect';\nimport { filterByVisibility, filterErrorsByVisibility } from './filtering';\nimport {\n ValidationError,\n ConfigSchema,\n ConfigSchemaPackageEntry,\n CONFIG_VISIBILITIES,\n} from './types';\nimport { normalizeAjvPath } from './utils';\n\n/**\n * Options that control the loading of configuration schema files in the backend.\n *\n * @public\n */\nexport type LoadConfigSchemaOptions =\n | (\n | {\n dependencies: string[];\n packagePaths?: string[];\n /**\n * Whether to exclude schemas from package dependencies.\n *\n * Defaults to `false`.\n */\n excludePackageDependencies?: boolean;\n }\n | {\n serialized: JsonObject;\n }\n ) & {\n noUndeclaredProperties?: boolean;\n };\n\nfunction errorsToError(errors: ValidationError[]): Error {\n const messages = errors.map(({ instancePath, message, params }) => {\n const paramStr = Object.entries(params)\n .map(([name, value]) => `${name}=${value}`)\n .join(' ');\n return `Config ${message || ''} { ${paramStr} } at ${normalizeAjvPath(\n instancePath,\n )}`;\n });\n const error = new Error(`Config validation failed, ${messages.join('; ')}`);\n (error as any).messages = messages;\n return error;\n}\n\n/**\n * Loads config schema for a Backstage instance.\n *\n * @public\n */\nexport async function loadConfigSchema(\n options: LoadConfigSchemaOptions,\n): Promise<ConfigSchema> {\n let schemas: ConfigSchemaPackageEntry[];\n\n if ('dependencies' in options) {\n schemas = await collectConfigSchemas(\n options.dependencies,\n options.packagePaths ?? [],\n {\n excludePackageDependencies: options.excludePackageDependencies,\n },\n );\n } else {\n const { serialized } = options;\n if (serialized?.backstageConfigSchemaVersion !== 1) {\n throw new Error(\n 'Serialized configuration schema is invalid or has an invalid version number',\n );\n }\n schemas = serialized.schemas as ConfigSchemaPackageEntry[];\n }\n\n const validate = compileConfigSchemas(schemas, {\n noUndeclaredProperties: options.noUndeclaredProperties,\n });\n\n return {\n process(\n configs: AppConfig[],\n {\n visibility,\n valueTransform,\n withFilteredKeys,\n withDeprecatedKeys,\n ignoreSchemaErrors,\n } = {},\n ): AppConfig[] {\n const result = validate(configs);\n\n if (!ignoreSchemaErrors) {\n const visibleErrors = filterErrorsByVisibility(\n result.errors,\n visibility,\n result.visibilityByDataPath,\n result.visibilityBySchemaPath,\n );\n if (visibleErrors.length > 0) {\n throw errorsToError(visibleErrors);\n }\n }\n\n let processedConfigs = configs;\n\n if (visibility) {\n processedConfigs = processedConfigs.map(({ data, context }) => ({\n context,\n ...filterByVisibility(\n data,\n visibility,\n result.visibilityByDataPath,\n result.deepVisibilityByDataPath,\n result.deprecationByDataPath,\n valueTransform,\n withFilteredKeys,\n withDeprecatedKeys,\n ),\n }));\n } else if (valueTransform) {\n processedConfigs = processedConfigs.map(({ data, context }) => ({\n context,\n ...filterByVisibility(\n data,\n Array.from(CONFIG_VISIBILITIES),\n result.visibilityByDataPath,\n result.deepVisibilityByDataPath,\n result.deprecationByDataPath,\n valueTransform,\n withFilteredKeys,\n withDeprecatedKeys,\n ),\n }));\n }\n\n return processedConfigs;\n },\n serialize(): JsonObject {\n return {\n schemas,\n backstageConfigSchemaVersion: 1,\n };\n },\n };\n}\n"],"names":["normalizeAjvPath","collectConfigSchemas","compileConfigSchemas","filterErrorsByVisibility","filterByVisibility","CONFIG_VISIBILITIES"],"mappings":";;;;;;;;AAqDA,SAAS,cAAc,MAAA,EAAkC;AACvD,EAAA,MAAM,QAAA,GAAW,OAAO,GAAA,CAAI,CAAC,EAAE,YAAA,EAAc,OAAA,EAAS,QAAO,KAAM;AACjE,IAAA,MAAM,WAAW,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CACnC,GAAA,CAAI,CAAC,CAAC,IAAA,EAAM,KAAK,CAAA,KAAM,GAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAE,CAAA,CACzC,KAAK,GAAG,CAAA;AACX,IAAA,OAAO,CAAA,OAAA,EAAU,OAAA,IAAW,EAAE,CAAA,GAAA,EAAM,QAAQ,CAAA,MAAA,EAASA,sBAAA;AAAA,MACnD;AAAA,KACD,CAAA,CAAA;AAAA,EACH,CAAC,CAAA;AACD,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,SAAS,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAC1E,EAAC,MAAc,QAAA,GAAW,QAAA;AAC1B,EAAA,OAAO,KAAA;AACT;AAOA,eAAsB,iBACpB,OAAA,EACuB;AACvB,EAAA,IAAI,OAAA;AAEJ,EAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,IAAA,OAAA,GAAU,MAAMC,4BAAA;AAAA,MACd,OAAA,CAAQ,YAAA;AAAA,MACR,OAAA,CAAQ,gBAAgB,EAAC;AAAA,MACzB;AAAA,QACE,4BAA4B,OAAA,CAAQ;AAAA;AACtC,KACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,MAAM,EAAE,YAAW,GAAI,OAAA;AACvB,IAAA,IAAI,UAAA,EAAY,iCAAiC,CAAA,EAAG;AAClD,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAA,GAAU,UAAA,CAAW,OAAA;AAAA,EACvB;AAEA,EAAA,MAAM,QAAA,GAAWC,6BAAqB,OAAA,EAAS;AAAA,IAC7C,wBAAwB,OAAA,CAAQ;AAAA,GACjC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,QACE,OAAA,EACA;AAAA,MACE,UAAA;AAAA,MACA,cAAA;AAAA,MACA,gBAAA;AAAA,MACA,kBAAA;AAAA,MACA;AAAA,KACF,GAAI,EAAC,EACQ;AACb,MAAA,MAAM,MAAA,GAAS,SAAS,OAAO,CAAA;AAE/B,MAAA,IAAI,CAAC,kBAAA,EAAoB;AACvB,QAAA,MAAM,aAAA,GAAgBC,kCAAA;AAAA,UACpB,MAAA,CAAO,MAAA;AAAA,UACP,UAAA;AAAA,UACA,MAAA,CAAO,oBAAA;AAAA,UACP,MAAA,CAAO;AAAA,SACT;AACA,QAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAAG;AAC5B,UAAA,MAAM,cAAc,aAAa,CAAA;AAAA,QACnC;AAAA,MACF;AAEA,MAAA,IAAI,gBAAA,GAAmB,OAAA;AAEvB,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,gBAAA,GAAmB,iBAAiB,GAAA,CAAI,CAAC,EAAE,IAAA,EAAM,SAAQ,MAAO;AAAA,UAC9D,OAAA;AAAA,UACA,GAAGC,4BAAA;AAAA,YACD,IAAA;AAAA,YACA,UAAA;AAAA,YACA,MAAA,CAAO,oBAAA;AAAA,YACP,MAAA,CAAO,wBAAA;AAAA,YACP,MAAA,CAAO,qBAAA;AAAA,YACP,cAAA;AAAA,YACA,gBAAA;AAAA,YACA;AAAA;AACF,SACF,CAAE,CAAA;AAAA,MACJ,WAAW,cAAA,EAAgB;AACzB,QAAA,gBAAA,GAAmB,iBAAiB,GAAA,CAAI,CAAC,EAAE,IAAA,EAAM,SAAQ,MAAO;AAAA,UAC9D,OAAA;AAAA,UACA,GAAGA,4BAAA;AAAA,YACD,IAAA;AAAA,YACA,KAAA,CAAM,KAAKC,yBAAmB,CAAA;AAAA,YAC9B,MAAA,CAAO,oBAAA;AAAA,YACP,MAAA,CAAO,wBAAA;AAAA,YACP,MAAA,CAAO,qBAAA;AAAA,YACP,cAAA;AAAA,YACA,gBAAA;AAAA,YACA;AAAA;AACF,SACF,CAAE,CAAA;AAAA,MACJ;AAEA,MAAA,OAAO,gBAAA;AAAA,IACT,CAAA;AAAA,IACA,SAAA,GAAwB;AACtB,MAAA,OAAO;AAAA,QACL,OAAA;AAAA,QACA,4BAAA,EAA8B;AAAA,OAChC;AAAA,IACF;AAAA,GACF;AACF;;;;"}
|
|
@@ -76,15 +76,8 @@ class ConfigSources {
|
|
|
76
76
|
if (argSources.length === 0) {
|
|
77
77
|
const defaultPath = node_path.resolve(rootDir, "app-config.yaml");
|
|
78
78
|
const localPath = node_path.resolve(rootDir, "app-config.local.yaml");
|
|
79
|
-
const envPath = node_path.resolve(
|
|
80
|
-
rootDir,
|
|
81
|
-
`app-config.${process.env.BACKSTAGE_ENV}.yaml`
|
|
82
|
-
);
|
|
83
|
-
const envLocalPath = node_path.resolve(
|
|
84
|
-
rootDir,
|
|
85
|
-
`app-config.${process.env.BACKSTAGE_ENV}.local.yaml`
|
|
86
|
-
);
|
|
87
79
|
const alwaysIncludeDefaultConfigSource = !options.allowMissingDefaultConfig;
|
|
80
|
+
const envs = (process.env.BACKSTAGE_ENV ?? "").split(",").map((e) => e.trim()).filter(Boolean);
|
|
88
81
|
if (alwaysIncludeDefaultConfigSource || fs__default.default.pathExistsSync(defaultPath)) {
|
|
89
82
|
argSources.push(
|
|
90
83
|
FileConfigSource.FileConfigSource.create({
|
|
@@ -94,14 +87,17 @@ class ConfigSources {
|
|
|
94
87
|
})
|
|
95
88
|
);
|
|
96
89
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
90
|
+
for (const env of envs) {
|
|
91
|
+
const envPath = node_path.resolve(rootDir, `app-config.${env}.yaml`);
|
|
92
|
+
if (fs__default.default.pathExistsSync(envPath)) {
|
|
93
|
+
argSources.push(
|
|
94
|
+
FileConfigSource.FileConfigSource.create({
|
|
95
|
+
watch: options.watch,
|
|
96
|
+
path: envPath,
|
|
97
|
+
substitutionFunc: options.substitutionFunc
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
}
|
|
105
101
|
}
|
|
106
102
|
if (fs__default.default.pathExistsSync(localPath)) {
|
|
107
103
|
argSources.push(
|
|
@@ -112,14 +108,20 @@ class ConfigSources {
|
|
|
112
108
|
})
|
|
113
109
|
);
|
|
114
110
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
path: envLocalPath,
|
|
120
|
-
substitutionFunc: options.substitutionFunc
|
|
121
|
-
})
|
|
111
|
+
for (const env of envs) {
|
|
112
|
+
const envLocalPath = node_path.resolve(
|
|
113
|
+
rootDir,
|
|
114
|
+
`app-config.${env}.local.yaml`
|
|
122
115
|
);
|
|
116
|
+
if (fs__default.default.pathExistsSync(envLocalPath)) {
|
|
117
|
+
argSources.push(
|
|
118
|
+
FileConfigSource.FileConfigSource.create({
|
|
119
|
+
watch: options.watch,
|
|
120
|
+
path: envLocalPath,
|
|
121
|
+
substitutionFunc: options.substitutionFunc
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
}
|
|
123
125
|
}
|
|
124
126
|
}
|
|
125
127
|
return this.merge(argSources);
|
|
@@ -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 '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 { targetPaths } 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 ?? targetPaths.rootDir;\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","targetPaths","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 { targetPaths } 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 ?? targetPaths.rootDir;\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 alwaysIncludeDefaultConfigSource =\n !options.allowMissingDefaultConfig;\n\n const envs = (process.env.BACKSTAGE_ENV ?? '')\n .split(',')\n .map(e => e.trim())\n .filter(Boolean);\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 for (const env of envs) {\n const envPath = resolvePath(rootDir, `app-config.${env}.yaml`);\n if (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\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 for (const env of envs) {\n const envLocalPath = resolvePath(\n rootDir,\n `app-config.${env}.local.yaml`,\n );\n if (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\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","targetPaths","RemoteConfigSource","FileConfigSource","resolvePath","fs","EnvConfigSource","MergedConfigSource","config","ConfigReader","ObservableConfigProxy"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/config-loader",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0-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": "
|
|
40
|
-
"@backstage/config": "
|
|
41
|
-
"@backstage/errors": "
|
|
42
|
-
"@backstage/types": "
|
|
39
|
+
"@backstage/cli-common": "0.2.2",
|
|
40
|
+
"@backstage/config": "1.3.8",
|
|
41
|
+
"@backstage/errors": "1.3.1",
|
|
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",
|
|
@@ -48,12 +48,13 @@
|
|
|
48
48
|
"json-schema-traverse": "^1.0.0",
|
|
49
49
|
"lodash": "^4.17.21",
|
|
50
50
|
"minimist": "^1.2.5",
|
|
51
|
-
"
|
|
51
|
+
"ts-json-schema-generator": "^2.9.0",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
52
53
|
"yaml": "^2.0.0"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
|
-
"@backstage/backend-test-utils": "
|
|
56
|
-
"@backstage/cli": "
|
|
56
|
+
"@backstage/backend-test-utils": "1.11.5-next.0",
|
|
57
|
+
"@backstage/cli": "0.36.4-next.1",
|
|
57
58
|
"@types/json-schema-merge-allof": "^0.6.0",
|
|
58
59
|
"@types/minimist": "^1.2.5",
|
|
59
60
|
"msw": "^2.0.0",
|