@backstage/config-loader 1.10.11 → 1.11.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage/config-loader
|
|
2
2
|
|
|
3
|
+
## 1.11.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
|
|
9
|
+
## 1.10.12
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 02c4e8a: Removed unused `json-schema` runtime dependency. The package was only used for TypeScript types from `@types/json-schema`; affected imports have been converted to `import type` to allow safe removal.
|
|
14
|
+
|
|
3
15
|
## 1.10.11
|
|
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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.cjs.js","sources":["../../src/schema/compile.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Ajv from 'ajv';\nimport { JSONSchema7 as JSONSchema } from 'json-schema';\nimport mergeAllOf, { Resolvers } from 'json-schema-merge-allof';\nimport traverse from 'json-schema-traverse';\nimport { ConfigReader } from '@backstage/config';\nimport {\n ConfigSchemaPackageEntry,\n ValidationFunc,\n CONFIG_VISIBILITIES,\n ConfigVisibility,\n} from './types';\nimport { SchemaObject } from 'json-schema-traverse';\nimport { normalizeAjvPath } from './utils';\n\n// Used to keep track of the internal deepVisibility inherited through the schema.\nconst inheritedVisibility = Symbol('inherited-visibility');\n\n/**\n * This takes a collection of Backstage configuration schemas from various\n * sources and compiles them down into a single schema validation function.\n *\n * It also handles the implementation of the custom \"visibility\" keyword used\n * to specify the scope of different config paths.\n */\nexport function compileConfigSchemas(\n schemas: ConfigSchemaPackageEntry[],\n options?: {\n noUndeclaredProperties?: boolean;\n },\n): ValidationFunc {\n // The ajv instance below is stateful and doesn't really allow for additional\n // output during validation. We work around this by having this extra piece\n // of state that we reset before each validation.\n const visibilityByDataPath = new Map<string, ConfigVisibility>();\n const deepVisibilityByDataPath = new Map<string, ConfigVisibility>();\n const deprecationByDataPath = new Map<string, string>();\n\n const ajv = new Ajv({\n allErrors: true,\n allowUnionTypes: true,\n coerceTypes: true,\n schemas: {\n 'https://backstage.io/schema/config-v1': true,\n },\n })\n .addKeyword({\n keyword: 'visibility',\n metaSchema: {\n type: 'string',\n enum: CONFIG_VISIBILITIES,\n },\n compile(visibility: ConfigVisibility) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility && visibility !== 'backend') {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n visibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .addKeyword({\n keyword: 'deepVisibility',\n metaSchema: {\n type: 'string',\n /**\n * Disallow 'backend' deepVisibility to prevent cases of permission escaping.\n *\n * Something like:\n * - deepVisibility secret -> backend -> frontend.\n * - deepVisibility secret -> backend -> visibility frontend.\n */\n enum: ['frontend', 'secret'],\n },\n compile(visibility: 'frontend' | 'secret') {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility) {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n deepVisibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .removeKeyword('deprecated') // remove `deprecated` keyword so that we can implement our own compiler\n .addKeyword({\n keyword: 'deprecated',\n metaSchema: { type: 'string' },\n compile(deprecationDescription: string) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n const normalizedPath = normalizeAjvPath(context.instancePath);\n // create mapping of deprecation description and data path of property\n deprecationByDataPath.set(normalizedPath, deprecationDescription);\n return true;\n };\n },\n });\n\n for (const schema of schemas) {\n try {\n ajv.compile(schema.value);\n } catch (error) {\n throw new Error(`Schema at ${schema.path} is invalid, ${error}`);\n }\n }\n\n const merged = mergeConfigSchemas(schemas.map(_ => _.value));\n\n traverse(\n merged,\n (\n schema: SchemaObject & { [inheritedVisibility]?: ConfigVisibility },\n jsonPtr: string,\n _1: any,\n _2: any,\n _3?: any,\n parentSchema?: SchemaObject & {\n [inheritedVisibility]?: ConfigVisibility;\n },\n ) => {\n // Inherit parent deepVisibility if we don't define one ourselves.\n // This is used to detect situations where conflicting deep visibilities are set.\n schema[inheritedVisibility] ??=\n schema?.deepVisibility ?? parentSchema?.[inheritedVisibility];\n\n if (schema[inheritedVisibility]) {\n // Validate that we're not trying to set a conflicting visibility. This can be done\n // either by setting a conflicting visibility directly or deep visibility\n const values = [\n schema.visibility,\n schema[inheritedVisibility],\n parentSchema?.[inheritedVisibility],\n ];\n const hasFrontend = values.some(e => e === 'frontend');\n const hasSecret = values.some(e => e === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${jsonPtr}`,\n );\n }\n }\n\n if (options?.noUndeclaredProperties) {\n /**\n * The `additionalProperties` key can only be applied to `type: object` in the JSON\n * schema.\n */\n if (schema?.type === 'object') {\n schema.additionalProperties ||= false;\n }\n }\n },\n );\n\n const validate = ajv.compile(merged);\n\n const visibilityBySchemaPath = new Map<string, ConfigVisibility>();\n traverse(merged, (schema, path) => {\n if (schema.visibility && schema.visibility !== 'backend') {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.visibility);\n }\n if (schema.deepVisibility) {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.deepVisibility);\n }\n });\n\n return configs => {\n const config = ConfigReader.fromConfigs(configs).getOptional();\n\n visibilityByDataPath.clear();\n deepVisibilityByDataPath.clear();\n\n const valid = validate(config);\n\n if (!valid) {\n return {\n errors: validate.errors ?? [],\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n }\n\n return {\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n };\n}\n\n/**\n * Given a list of configuration schemas from packages, merge them\n * into a single json schema.\n *\n * @public\n */\nexport function mergeConfigSchemas(schemas: JSONSchema[]): JSONSchema {\n const merged = mergeAllOf(\n { allOf: schemas },\n {\n // JSONSchema is typically subtractive, as in it always reduces the set of allowed\n // inputs through constraints. This changes the object property merging to be additive\n // rather than subtractive.\n ignoreAdditionalProperties: true,\n resolvers: {\n // This ensures that the visibilities across different schemas are sound, and\n // selects the most specific visibility for each path.\n visibility(values: string[], path: string[]) {\n const hasFrontend = values.some(_ => _ === 'frontend');\n const hasSecret = values.some(_ => _ === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${path.join(\n '/',\n )}`,\n );\n } else if (hasFrontend) {\n return 'frontend';\n } else if (hasSecret) {\n return 'secret';\n }\n\n return 'backend';\n },\n } as Partial<Resolvers<JSONSchema>>,\n },\n );\n return merged;\n}\n"],"names":["Ajv","CONFIG_VISIBILITIES","normalizeAjvPath","traverse","config","ConfigReader","mergeAllOf"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compile.cjs.js","sources":["../../src/schema/compile.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Ajv from 'ajv';\nimport type { JSONSchema7 as JSONSchema } from 'json-schema';\nimport mergeAllOf, { Resolvers } from 'json-schema-merge-allof';\nimport traverse from 'json-schema-traverse';\nimport { ConfigReader } from '@backstage/config';\nimport {\n ConfigSchemaPackageEntry,\n ValidationFunc,\n CONFIG_VISIBILITIES,\n ConfigVisibility,\n} from './types';\nimport { SchemaObject } from 'json-schema-traverse';\nimport { normalizeAjvPath } from './utils';\n\n// Used to keep track of the internal deepVisibility inherited through the schema.\nconst inheritedVisibility = Symbol('inherited-visibility');\n\n/**\n * This takes a collection of Backstage configuration schemas from various\n * sources and compiles them down into a single schema validation function.\n *\n * It also handles the implementation of the custom \"visibility\" keyword used\n * to specify the scope of different config paths.\n */\nexport function compileConfigSchemas(\n schemas: ConfigSchemaPackageEntry[],\n options?: {\n noUndeclaredProperties?: boolean;\n },\n): ValidationFunc {\n // The ajv instance below is stateful and doesn't really allow for additional\n // output during validation. We work around this by having this extra piece\n // of state that we reset before each validation.\n const visibilityByDataPath = new Map<string, ConfigVisibility>();\n const deepVisibilityByDataPath = new Map<string, ConfigVisibility>();\n const deprecationByDataPath = new Map<string, string>();\n\n const ajv = new Ajv({\n allErrors: true,\n allowUnionTypes: true,\n coerceTypes: true,\n schemas: {\n 'https://backstage.io/schema/config-v1': true,\n },\n })\n .addKeyword({\n keyword: 'visibility',\n metaSchema: {\n type: 'string',\n enum: CONFIG_VISIBILITIES,\n },\n compile(visibility: ConfigVisibility) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility && visibility !== 'backend') {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n visibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .addKeyword({\n keyword: 'deepVisibility',\n metaSchema: {\n type: 'string',\n /**\n * Disallow 'backend' deepVisibility to prevent cases of permission escaping.\n *\n * Something like:\n * - deepVisibility secret -> backend -> frontend.\n * - deepVisibility secret -> backend -> visibility frontend.\n */\n enum: ['frontend', 'secret'],\n },\n compile(visibility: 'frontend' | 'secret') {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n if (visibility) {\n const normalizedPath = normalizeAjvPath(context.instancePath);\n deepVisibilityByDataPath.set(normalizedPath, visibility);\n }\n return true;\n };\n },\n })\n .removeKeyword('deprecated') // remove `deprecated` keyword so that we can implement our own compiler\n .addKeyword({\n keyword: 'deprecated',\n metaSchema: { type: 'string' },\n compile(deprecationDescription: string) {\n return (_data, context) => {\n if (context?.instancePath === undefined) {\n return false;\n }\n const normalizedPath = normalizeAjvPath(context.instancePath);\n // create mapping of deprecation description and data path of property\n deprecationByDataPath.set(normalizedPath, deprecationDescription);\n return true;\n };\n },\n });\n\n for (const schema of schemas) {\n try {\n ajv.compile(schema.value);\n } catch (error) {\n throw new Error(`Schema at ${schema.path} is invalid, ${error}`);\n }\n }\n\n const merged = mergeConfigSchemas(schemas.map(_ => _.value));\n\n traverse(\n merged,\n (\n schema: SchemaObject & { [inheritedVisibility]?: ConfigVisibility },\n jsonPtr: string,\n _1: any,\n _2: any,\n _3?: any,\n parentSchema?: SchemaObject & {\n [inheritedVisibility]?: ConfigVisibility;\n },\n ) => {\n // Inherit parent deepVisibility if we don't define one ourselves.\n // This is used to detect situations where conflicting deep visibilities are set.\n schema[inheritedVisibility] ??=\n schema?.deepVisibility ?? parentSchema?.[inheritedVisibility];\n\n if (schema[inheritedVisibility]) {\n // Validate that we're not trying to set a conflicting visibility. This can be done\n // either by setting a conflicting visibility directly or deep visibility\n const values = [\n schema.visibility,\n schema[inheritedVisibility],\n parentSchema?.[inheritedVisibility],\n ];\n const hasFrontend = values.some(e => e === 'frontend');\n const hasSecret = values.some(e => e === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${jsonPtr}`,\n );\n }\n }\n\n if (options?.noUndeclaredProperties) {\n /**\n * The `additionalProperties` key can only be applied to `type: object` in the JSON\n * schema.\n */\n if (schema?.type === 'object') {\n schema.additionalProperties ||= false;\n }\n }\n },\n );\n\n const validate = ajv.compile(merged);\n\n const visibilityBySchemaPath = new Map<string, ConfigVisibility>();\n traverse(merged, (schema, path) => {\n if (schema.visibility && schema.visibility !== 'backend') {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.visibility);\n }\n if (schema.deepVisibility) {\n visibilityBySchemaPath.set(normalizeAjvPath(path), schema.deepVisibility);\n }\n });\n\n return configs => {\n const config = ConfigReader.fromConfigs(configs).getOptional();\n\n visibilityByDataPath.clear();\n deepVisibilityByDataPath.clear();\n\n const valid = validate(config);\n\n if (!valid) {\n return {\n errors: validate.errors ?? [],\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n }\n\n return {\n visibilityByDataPath: new Map(visibilityByDataPath),\n deepVisibilityByDataPath: new Map(deepVisibilityByDataPath),\n visibilityBySchemaPath,\n deprecationByDataPath,\n };\n };\n}\n\n/**\n * Given a list of configuration schemas from packages, merge them\n * into a single json schema.\n *\n * @public\n */\nexport function mergeConfigSchemas(schemas: JSONSchema[]): JSONSchema {\n const merged = mergeAllOf(\n { allOf: schemas },\n {\n // JSONSchema is typically subtractive, as in it always reduces the set of allowed\n // inputs through constraints. This changes the object property merging to be additive\n // rather than subtractive.\n ignoreAdditionalProperties: true,\n resolvers: {\n // This ensures that the visibilities across different schemas are sound, and\n // selects the most specific visibility for each path.\n visibility(values: string[], path: string[]) {\n const hasFrontend = values.some(_ => _ === 'frontend');\n const hasSecret = values.some(_ => _ === 'secret');\n if (hasFrontend && hasSecret) {\n throw new Error(\n `Config schema visibility is both 'frontend' and 'secret' for ${path.join(\n '/',\n )}`,\n );\n } else if (hasFrontend) {\n return 'frontend';\n } else if (hasSecret) {\n return 'secret';\n }\n\n return 'backend';\n },\n } as Partial<Resolvers<JSONSchema>>,\n },\n );\n return merged;\n}\n"],"names":["Ajv","CONFIG_VISIBILITIES","normalizeAjvPath","traverse","config","ConfigReader","mergeAllOf"],"mappings":"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"}
|
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":"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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.0",
|
|
4
4
|
"description": "Config loading functionality used by Backstage backend, and CLI",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -36,25 +36,25 @@
|
|
|
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",
|
|
46
46
|
"fs-extra": "^11.2.0",
|
|
47
|
-
"json-schema": "^0.4.0",
|
|
48
47
|
"json-schema-merge-allof": "^0.8.1",
|
|
49
48
|
"json-schema-traverse": "^1.0.0",
|
|
50
49
|
"lodash": "^4.17.21",
|
|
51
50
|
"minimist": "^1.2.5",
|
|
52
|
-
"
|
|
51
|
+
"ts-json-schema-generator": "^2.9.0",
|
|
52
|
+
"typescript": "^5.9.3",
|
|
53
53
|
"yaml": "^2.0.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@backstage/backend-test-utils": "
|
|
57
|
-
"@backstage/cli": "
|
|
56
|
+
"@backstage/backend-test-utils": "1.11.5-next.0",
|
|
57
|
+
"@backstage/cli": "0.36.4-next.0",
|
|
58
58
|
"@types/json-schema-merge-allof": "^0.6.0",
|
|
59
59
|
"@types/minimist": "^1.2.5",
|
|
60
60
|
"msw": "^2.0.0",
|