@backstage/config-loader 1.10.11-next.0 → 1.10.12

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,20 @@
1
1
  # @backstage/config-loader
2
2
 
3
+ ## 1.10.12
4
+
5
+ ### Patch Changes
6
+
7
+ - 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.
8
+
9
+ ## 1.10.11
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+ - @backstage/errors@1.3.1
15
+ - @backstage/cli-common@0.2.2
16
+ - @backstage/config@1.3.8
17
+
3
18
  ## 1.10.11-next.0
4
19
 
5
20
  ### Patch Changes
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/config-loader",
3
- "version": "1.10.11-next.0",
3
+ "version": "1.10.12",
4
4
  "description": "Config loading functionality used by Backstage backend, and CLI",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -36,15 +36,14 @@
36
36
  "test": "backstage-cli package test"
37
37
  },
38
38
  "dependencies": {
39
- "@backstage/cli-common": "0.2.2-next.0",
40
- "@backstage/config": "1.3.8-next.0",
41
- "@backstage/errors": "1.3.1-next.0",
42
- "@backstage/types": "1.2.2",
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",
@@ -53,8 +52,8 @@
53
52
  "yaml": "^2.0.0"
54
53
  },
55
54
  "devDependencies": {
56
- "@backstage/backend-test-utils": "1.11.3-next.0",
57
- "@backstage/cli": "0.36.2-next.0",
55
+ "@backstage/backend-test-utils": "^1.11.4",
56
+ "@backstage/cli": "^0.36.3",
58
57
  "@types/json-schema-merge-allof": "^0.6.0",
59
58
  "@types/minimist": "^1.2.5",
60
59
  "msw": "^2.0.0",