@backstage/config-loader 1.11.0 → 1.11.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 +6 -0
- package/dist/index.cjs.js +2 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +29 -3
- package/dist/schema/ConfigSchemaError.cjs.js +21 -0
- package/dist/schema/ConfigSchemaError.cjs.js.map +1 -0
- package/dist/schema/collect.cjs.js +81 -30
- package/dist/schema/collect.cjs.js.map +1 -1
- package/dist/schema/load.cjs.js +2 -1
- package/dist/schema/load.cjs.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @backstage/config-loader
|
|
2
2
|
|
|
3
|
+
## 1.11.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 60d2b50: Added an `onSchemaError` callback that allows callers to report TypeScript configuration schema errors and continue loading. The callback receives a `ConfigSchemaError` containing the source package and underlying cause. Without a handler, schema errors are thrown.
|
|
8
|
+
|
|
3
9
|
## 1.11.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var compile = require('./schema/compile.cjs.js');
|
|
4
4
|
var load = require('./schema/load.cjs.js');
|
|
5
|
+
var ConfigSchemaError = require('./schema/ConfigSchemaError.cjs.js');
|
|
5
6
|
var loader = require('./loader.cjs.js');
|
|
6
7
|
var ConfigSources = require('./sources/ConfigSources.cjs.js');
|
|
7
8
|
var EnvConfigSource = require('./sources/EnvConfigSource.cjs.js');
|
|
@@ -14,6 +15,7 @@ var StaticConfigSource = require('./sources/StaticConfigSource.cjs.js');
|
|
|
14
15
|
|
|
15
16
|
exports.mergeConfigSchemas = compile.mergeConfigSchemas;
|
|
16
17
|
exports.loadConfigSchema = load.loadConfigSchema;
|
|
18
|
+
exports.ConfigSchemaError = ConfigSchemaError.ConfigSchemaError;
|
|
17
19
|
exports.loadConfig = loader.loadConfig;
|
|
18
20
|
exports.ConfigSources = ConfigSources.ConfigSources;
|
|
19
21
|
exports.EnvConfigSource = EnvConfigSource.EnvConfigSource;
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -81,12 +81,29 @@ type ConfigSchema = {
|
|
|
81
81
|
*/
|
|
82
82
|
declare function mergeConfigSchemas(schemas: JSONSchema7[]): JSONSchema7;
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* An error encountered while loading a TypeScript configuration schema.
|
|
86
|
+
*
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
declare class ConfigSchemaError extends Error {
|
|
90
|
+
name: "ConfigSchemaError";
|
|
91
|
+
/** The package that provided the configuration schema. */
|
|
92
|
+
readonly source: string;
|
|
93
|
+
/** The underlying error that caused schema loading to fail. */
|
|
94
|
+
readonly cause: Error;
|
|
95
|
+
constructor(options: {
|
|
96
|
+
source: string;
|
|
97
|
+
cause: Error;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
84
101
|
/**
|
|
85
102
|
* Options that control the loading of configuration schema files in the backend.
|
|
86
103
|
*
|
|
87
104
|
* @public
|
|
88
105
|
*/
|
|
89
|
-
type LoadConfigSchemaOptions = ({
|
|
106
|
+
type LoadConfigSchemaOptions = (({
|
|
90
107
|
dependencies: string[];
|
|
91
108
|
packagePaths?: string[];
|
|
92
109
|
/**
|
|
@@ -95,11 +112,20 @@ type LoadConfigSchemaOptions = ({
|
|
|
95
112
|
* Defaults to `false`.
|
|
96
113
|
*/
|
|
97
114
|
excludePackageDependencies?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Receives `ConfigSchemaError` instances and allows TypeScript schema
|
|
117
|
+
* loading to continue. Unresolved types are treated as unconstrained
|
|
118
|
+
* values, while schemas that cannot be generated are omitted.
|
|
119
|
+
*
|
|
120
|
+
* Without this callback, TypeScript configuration schema errors are
|
|
121
|
+
* thrown.
|
|
122
|
+
*/
|
|
123
|
+
onSchemaError?: (error: ConfigSchemaError) => void;
|
|
98
124
|
} | {
|
|
99
125
|
serialized: JsonObject;
|
|
100
126
|
}) & {
|
|
101
127
|
noUndeclaredProperties?: boolean;
|
|
102
|
-
};
|
|
128
|
+
});
|
|
103
129
|
/**
|
|
104
130
|
* Loads config schema for a Backstage instance.
|
|
105
131
|
*
|
|
@@ -641,5 +667,5 @@ declare class StaticConfigSource implements ConfigSource {
|
|
|
641
667
|
toString(): string;
|
|
642
668
|
}
|
|
643
669
|
|
|
644
|
-
export { ConfigSources, EnvConfigSource, FileConfigSource, MutableConfigSource, RemoteConfigSource, StaticConfigSource, loadConfig, loadConfigSchema, mergeConfigSchemas, readEnvConfig };
|
|
670
|
+
export { ConfigSchemaError, ConfigSources, EnvConfigSource, FileConfigSource, MutableConfigSource, RemoteConfigSource, StaticConfigSource, loadConfig, loadConfigSchema, mergeConfigSchemas, readEnvConfig };
|
|
645
671
|
export type { AsyncConfigSourceGenerator, BaseConfigSourcesOptions, ClosableConfig, ConfigSchema, ConfigSchemaProcessingOptions, ConfigSource, ConfigSourceData, ConfigSourceTarget, ConfigSourcesDefaultForTargetsOptions, ConfigSourcesDefaultOptions, ConfigTarget, ConfigVisibility, EnvConfigSourceOptions, SubstitutionFunc as EnvFunc, FileConfigSourceOptions, LoadConfigOptions, LoadConfigOptionsRemote, LoadConfigOptionsWatch, LoadConfigResult, LoadConfigSchemaOptions, MutableConfigSourceOptions, Parser, ReadConfigDataOptions, RemoteConfigSourceOptions, StaticConfigSourceOptions, TransformFunc };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
class ConfigSchemaError extends Error {
|
|
4
|
+
name = "ConfigSchemaError";
|
|
5
|
+
/** The package that provided the configuration schema. */
|
|
6
|
+
source;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
const { source, cause } = options;
|
|
9
|
+
const causeMessage = cause.message.replace(/\s*\r?\n\s*/g, " ").trim();
|
|
10
|
+
super(
|
|
11
|
+
`The TypeScript configuration schema for package '${source}' contains an error - ${causeMessage}`,
|
|
12
|
+
{ cause }
|
|
13
|
+
);
|
|
14
|
+
this.source = source;
|
|
15
|
+
this.cause = cause;
|
|
16
|
+
Error.captureStackTrace?.(this, this.constructor);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.ConfigSchemaError = ConfigSchemaError;
|
|
21
|
+
//# sourceMappingURL=ConfigSchemaError.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigSchemaError.cjs.js","sources":["../../src/schema/ConfigSchemaError.ts"],"sourcesContent":["/*\n * Copyright 2026 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\n/**\n * An error encountered while loading a TypeScript configuration schema.\n *\n * @public\n */\nexport class ConfigSchemaError extends Error {\n name = 'ConfigSchemaError' as const;\n\n /** The package that provided the configuration schema. */\n readonly source: string;\n\n /** The underlying error that caused schema loading to fail. */\n declare readonly cause: Error;\n\n constructor(options: { source: string; cause: Error }) {\n const { source, cause } = options;\n const causeMessage = cause.message.replace(/\\s*\\r?\\n\\s*/g, ' ').trim();\n super(\n `The TypeScript configuration schema for package '${source}' contains an error - ${causeMessage}`,\n { cause },\n );\n\n this.source = source;\n this.cause = cause;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\n"],"names":[],"mappings":";;AAqBO,MAAM,0BAA0B,KAAA,CAAM;AAAA,EAC3C,IAAA,GAAO,mBAAA;AAAA;AAAA,EAGE,MAAA;AAAA,EAKT,YAAY,OAAA,EAA2C;AACrD,IAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,OAAA;AAC1B,IAAA,MAAM,eAAe,KAAA,CAAM,OAAA,CAAQ,QAAQ,cAAA,EAAgB,GAAG,EAAE,IAAA,EAAK;AACrE,IAAA,KAAA;AAAA,MACE,CAAA,iDAAA,EAAoD,MAAM,CAAA,sBAAA,EAAyB,YAAY,CAAA,CAAA;AAAA,MAC/F,EAAE,KAAA;AAAM,KACV;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,KAAA,CAAM,iBAAA,GAAoB,IAAA,EAAM,IAAA,CAAK,WAAW,CAAA;AAAA,EAClD;AACF;;;;"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var fs = require('fs-extra');
|
|
4
|
+
var errors = require('@backstage/errors');
|
|
4
5
|
var node_crypto = require('node:crypto');
|
|
5
6
|
var node_path = require('node:path');
|
|
7
|
+
var ConfigSchemaError = require('./ConfigSchemaError.cjs.js');
|
|
6
8
|
|
|
7
9
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
8
10
|
|
|
@@ -106,7 +108,7 @@ async function collectConfigSchemas(packageNames, packagePaths, options) {
|
|
|
106
108
|
...packageNames.map((name) => processItem({ name, parentPath: currentDir })),
|
|
107
109
|
...packagePaths.map((path) => processItem({ name: path, packagePath: path }))
|
|
108
110
|
]);
|
|
109
|
-
const tsSchemas = await compileTsSchemas(tsSchemaPaths);
|
|
111
|
+
const tsSchemas = await compileTsSchemas(tsSchemaPaths, options);
|
|
110
112
|
const allSchemas = schemas.concat(tsSchemas);
|
|
111
113
|
const hasBackendDefaults = allSchemas.some(
|
|
112
114
|
({ packageName }) => packageName === "@backstage/backend-defaults"
|
|
@@ -173,13 +175,20 @@ function parseNestedSchemaAnnotation(annotation) {
|
|
|
173
175
|
}
|
|
174
176
|
return { key, value };
|
|
175
177
|
}
|
|
176
|
-
|
|
178
|
+
function handleSchemaError(options, error) {
|
|
179
|
+
if (!options?.onSchemaError) {
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
options.onSchemaError(error);
|
|
183
|
+
}
|
|
184
|
+
async function compileTsSchemas(entries, options) {
|
|
177
185
|
if (entries.length === 0) {
|
|
178
186
|
return [];
|
|
179
187
|
}
|
|
180
188
|
const ts = require("typescript");
|
|
181
189
|
const {
|
|
182
190
|
AnnotatedTypeFormatter,
|
|
191
|
+
AnyType,
|
|
183
192
|
createFormatter,
|
|
184
193
|
createParser,
|
|
185
194
|
DEFAULT_CONFIG,
|
|
@@ -201,26 +210,36 @@ async function compileTsSchemas(entries) {
|
|
|
201
210
|
types: []
|
|
202
211
|
};
|
|
203
212
|
const program = ts.createProgram(rootNames, compilerOptions);
|
|
204
|
-
const
|
|
213
|
+
const sharedDiagnostics = [
|
|
205
214
|
...program.getOptionsDiagnostics(),
|
|
206
|
-
...program.getGlobalDiagnostics()
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
215
|
+
...program.getGlobalDiagnostics()
|
|
216
|
+
];
|
|
217
|
+
entries.forEach(({ packageName }, index) => {
|
|
218
|
+
const sourceFile = program.getSourceFile(rootNames[index]);
|
|
219
|
+
const diagnostics = [
|
|
220
|
+
...index === 0 ? sharedDiagnostics : [],
|
|
221
|
+
...sourceFile ? [
|
|
210
222
|
...program.getSyntacticDiagnostics(sourceFile),
|
|
211
223
|
...program.getSemanticDiagnostics(sourceFile)
|
|
212
|
-
] : []
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
+
] : []
|
|
225
|
+
];
|
|
226
|
+
if (diagnostics.length === 0) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
for (const diagnostic of diagnostics) {
|
|
230
|
+
const cause = new Error(
|
|
231
|
+
ts.formatDiagnostics([diagnostic], {
|
|
232
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
233
|
+
getCurrentDirectory: () => currentDir,
|
|
234
|
+
getNewLine: () => "\n"
|
|
235
|
+
}).trimEnd()
|
|
236
|
+
);
|
|
237
|
+
handleSchemaError(
|
|
238
|
+
options,
|
|
239
|
+
new ConfigSchemaError.ConfigSchemaError({ source: packageName, cause })
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
224
243
|
const generatorConfig = {
|
|
225
244
|
...DEFAULT_CONFIG,
|
|
226
245
|
additionalProperties: true,
|
|
@@ -231,7 +250,24 @@ ${message}`);
|
|
|
231
250
|
topRef: false,
|
|
232
251
|
tsProgram: program
|
|
233
252
|
};
|
|
234
|
-
const
|
|
253
|
+
const typeChecker = program.getTypeChecker();
|
|
254
|
+
const parser = createParser(program, generatorConfig, (mutableParser) => {
|
|
255
|
+
if (!options?.onSchemaError) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
mutableParser.addNodeParser({
|
|
259
|
+
supportsNode(node) {
|
|
260
|
+
if (!ts.isTypeReferenceNode(node)) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
const symbol = typeChecker.getSymbolAtLocation(node.typeName);
|
|
264
|
+
return !symbol?.declarations?.length;
|
|
265
|
+
},
|
|
266
|
+
createType() {
|
|
267
|
+
return new AnyType();
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
});
|
|
235
271
|
class NestedAnnotationsFormatter extends AnnotatedTypeFormatter {
|
|
236
272
|
getDefinition(type) {
|
|
237
273
|
const annotations = type.getAnnotations();
|
|
@@ -267,25 +303,40 @@ ${message}`);
|
|
|
267
303
|
formatter,
|
|
268
304
|
generatorConfig
|
|
269
305
|
);
|
|
270
|
-
const tsSchemas = entries.
|
|
306
|
+
const tsSchemas = entries.flatMap(({ path, packageName }, index) => {
|
|
271
307
|
const sourceFile = program.getSourceFile(rootNames[index]);
|
|
272
308
|
if (!sourceFile) {
|
|
273
|
-
throw new
|
|
309
|
+
throw new ConfigSchemaError.ConfigSchemaError({
|
|
310
|
+
source: packageName,
|
|
311
|
+
cause: new Error("The schema source file could not be loaded")
|
|
312
|
+
});
|
|
274
313
|
}
|
|
275
314
|
const configNode = sourceFile.statements.find(
|
|
276
315
|
(statement) => (ts.isInterfaceDeclaration(statement) || ts.isTypeAliasDeclaration(statement)) && statement.name.text === "Config"
|
|
277
316
|
);
|
|
278
317
|
if (!configNode) {
|
|
279
|
-
throw new
|
|
318
|
+
throw new ConfigSchemaError.ConfigSchemaError({
|
|
319
|
+
source: packageName,
|
|
320
|
+
cause: new Error("The schema does not export a Config type")
|
|
321
|
+
});
|
|
280
322
|
}
|
|
281
323
|
const namespace = node_crypto.createHash("sha256").update(packageName).update("\0").update(path.split(node_path.sep).join("/")).digest("hex");
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
324
|
+
try {
|
|
325
|
+
const value = namespaceSchemaDefinitions(
|
|
326
|
+
structuredClone(
|
|
327
|
+
generator.createSchemaFromNodes([configNode])
|
|
328
|
+
),
|
|
329
|
+
namespace
|
|
330
|
+
);
|
|
331
|
+
return [{ path, value, packageName }];
|
|
332
|
+
} catch (error) {
|
|
333
|
+
const cause = errors.toError(error);
|
|
334
|
+
handleSchemaError(
|
|
335
|
+
options,
|
|
336
|
+
new ConfigSchemaError.ConfigSchemaError({ source: packageName, cause })
|
|
337
|
+
);
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
289
340
|
});
|
|
290
341
|
return tsSchemas;
|
|
291
342
|
}
|
|
@@ -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 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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"}
|
|
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 { toError } from '@backstage/errors';\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';\nimport { ConfigSchemaError } from './ConfigSchemaError';\n\ntype Item = {\n name?: string;\n parentPath?: string;\n packagePath?: string;\n};\n\ntype CollectConfigSchemasOptions = {\n excludePackageDependencies?: boolean;\n onSchemaError?: (error: ConfigSchemaError) => void;\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?: CollectConfigSchemasOptions,\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, options);\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\nfunction handleSchemaError(\n options: CollectConfigSchemasOptions | undefined,\n error: ConfigSchemaError,\n) {\n if (!options?.onSchemaError) {\n throw error;\n }\n options.onSchemaError(error);\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 options?: CollectConfigSchemasOptions,\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 AnyType,\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 sharedDiagnostics = [\n ...program.getOptionsDiagnostics(),\n ...program.getGlobalDiagnostics(),\n ];\n entries.forEach(({ packageName }, index) => {\n const sourceFile = program.getSourceFile(rootNames[index]);\n const diagnostics = [\n ...(index === 0 ? sharedDiagnostics : []),\n ...(sourceFile\n ? [\n ...program.getSyntacticDiagnostics(sourceFile),\n ...program.getSemanticDiagnostics(sourceFile),\n ]\n : []),\n ];\n if (diagnostics.length === 0) {\n return;\n }\n\n for (const diagnostic of diagnostics) {\n const cause = new Error(\n ts\n .formatDiagnostics([diagnostic], {\n getCanonicalFileName: fileName => fileName,\n getCurrentDirectory: () => currentDir,\n getNewLine: () => '\\n',\n })\n .trimEnd(),\n );\n handleSchemaError(\n options,\n new ConfigSchemaError({ source: packageName, cause }),\n );\n }\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 typeChecker = program.getTypeChecker();\n const parser = createParser(program, generatorConfig, mutableParser => {\n if (!options?.onSchemaError) {\n return;\n }\n\n // Preserve the rest of a schema by treating unresolved references as unconstrained values.\n mutableParser.addNodeParser({\n supportsNode(node) {\n if (!ts.isTypeReferenceNode(node)) {\n return false;\n }\n const symbol = typeChecker.getSymbolAtLocation(node.typeName);\n return !symbol?.declarations?.length;\n },\n createType() {\n return new AnyType();\n },\n });\n });\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.flatMap(({ path, packageName }, index) => {\n const sourceFile = program.getSourceFile(rootNames[index]);\n if (!sourceFile) {\n throw new ConfigSchemaError({\n source: packageName,\n cause: new Error('The schema source file could not be loaded'),\n });\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 ConfigSchemaError({\n source: packageName,\n cause: new Error('The schema does not export a Config type'),\n });\n }\n\n const namespace = createHash('sha256')\n .update(packageName)\n .update('\\0')\n .update(path.split(sep).join('/'))\n .digest('hex');\n try {\n const value = namespaceSchemaDefinitions(\n structuredClone(\n generator.createSchemaFromNodes([configNode]),\n ) as JsonObject,\n namespace,\n );\n\n return [{ path, value, packageName }];\n } catch (error) {\n const cause = toError(error);\n handleSchemaError(\n options,\n new ConfigSchemaError({ source: packageName, cause }),\n );\n return [];\n }\n });\n\n return tsSchemas;\n}\n"],"names":["fs","relativePath","resolvePath","dirname","ConfigSchemaError","createHash","sep","toError"],"mappings":"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"}
|
package/dist/schema/load.cjs.js
CHANGED
|
@@ -24,7 +24,8 @@ async function loadConfigSchema(options) {
|
|
|
24
24
|
options.dependencies,
|
|
25
25
|
options.packagePaths ?? [],
|
|
26
26
|
{
|
|
27
|
-
excludePackageDependencies: options.excludePackageDependencies
|
|
27
|
+
excludePackageDependencies: options.excludePackageDependencies,
|
|
28
|
+
onSchemaError: options.onSchemaError
|
|
28
29
|
}
|
|
29
30
|
);
|
|
30
31
|
} else {
|
|
@@ -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 * 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":";;;;;;;;
|
|
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';\nimport type { ConfigSchemaError } from './ConfigSchemaError';\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 * Receives `ConfigSchemaError` instances and allows TypeScript schema\n * loading to continue. Unresolved types are treated as unconstrained\n * values, while schemas that cannot be generated are omitted.\n *\n * Without this callback, TypeScript configuration schema errors are\n * thrown.\n */\n onSchemaError?: (error: ConfigSchemaError) => void;\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 onSchemaError: options.onSchemaError,\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":"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"}
|