Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@backstage/config-loader

Package Overview
Dependencies
Maintainers
4
Versions
864
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@backstage/config-loader - npm Package Compare versions

Comparing version 0.0.0-nightly-20217521743 to 0.0.0-nightly-202182821947

28

CHANGELOG.md
# @backstage/config-loader
## 0.0.0-nightly-20217521743
## 0.0.0-nightly-202182821947
### Patch Changes
- ee7a1a4b64: Add option to collect configuration schemas from explicit package paths in addition to by package name.
## 0.6.8
### Patch Changes
- d1da88a19: Properly export all used types.
- Updated dependencies
- @backstage/cli-common@0.1.3
- @backstage/config@0.1.9
## 0.6.7
### Patch Changes
- 0ade9d02b: Include `devDependencies` and `optionalDependencies` in the detection of Backstage packages when collecting configuration schema.
- 9b8cec063: Add support for config file watching through a new group of `watch` options to `loadConfig`.
- Updated dependencies
- @backstage/config@0.1.7
## 0.6.6
### Patch Changes
- e9d3983ee: Add option to populate the `filteredKeys` property when processing configuration with a schema.
- Updated dependencies
- @backstage/config@0.0.0-nightly-20217521743
- @backstage/config@0.1.6

@@ -11,0 +35,0 @@ ## 0.6.5

87

dist/index.cjs.js

@@ -12,2 +12,3 @@ 'use strict';

var typescriptJsonSchema = require('typescript-json-schema');
var chokidar = require('chokidar');

@@ -20,2 +21,3 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
var chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar);

@@ -312,3 +314,3 @@ const ENV_PREFIX = "APP_CONFIG_";

const req = typeof __non_webpack_require__ === "undefined" ? require : __non_webpack_require__;
async function collectConfigSchemas(packageNames) {
async function collectConfigSchemas(packageNames, packagePaths) {
const visitedPackages = new Set();

@@ -318,14 +320,24 @@ const schemas = Array();

const currentDir = await fs__default['default'].realpath(process.cwd());
async function processItem({name, parentPath}) {
var _a, _b;
if (visitedPackages.has(name)) {
return;
async function processItem(item) {
var _a, _b, _c, _d;
let pkgPath = item.packagePath;
if (pkgPath) {
const pkgExists = await fs__default['default'].pathExists(pkgPath);
if (!pkgExists) {
return;
}
} else if (item.name) {
const {name, parentPath} = item;
if (visitedPackages.has(name)) {
return;
}
visitedPackages.add(name);
try {
pkgPath = req.resolve(`${name}/package.json`, parentPath && {
paths: [parentPath]
});
} catch {
}
}
visitedPackages.add(name);
let pkgPath;
try {
pkgPath = req.resolve(`${name}/package.json`, parentPath && {
paths: [parentPath]
});
} catch {
if (!pkgPath) {
return;

@@ -336,3 +348,5 @@ }

...Object.keys((_a = pkg.dependencies) != null ? _a : {}),
...Object.keys((_b = pkg.peerDependencies) != null ? _b : {})
...Object.keys((_b = pkg.devDependencies) != null ? _b : {}),
...Object.keys((_c = pkg.optionalDependencies) != null ? _c : {}),
...Object.keys((_d = pkg.peerDependencies) != null ? _d : {})
];

@@ -370,3 +384,6 @@ const hasSchema = "configSchema" in pkg;

}
await Promise.all(packageNames.map((name) => processItem({name, parentPath: currentDir})));
await Promise.all([
...packageNames.map((name) => processItem({name, parentPath: currentDir})),
...packagePaths.map((path) => processItem({name: path, packagePath: path}))
]);
const tsSchemas = compileTsSchemas(tsSchemaPaths);

@@ -468,5 +485,6 @@ return schemas.concat(tsSchemas);

async function loadConfigSchema(options) {
var _a;
let schemas;
if ("dependencies" in options) {
schemas = await collectConfigSchemas(options.dependencies);
schemas = await collectConfigSchemas(options.dependencies, (_a = options.packagePaths) != null ? _a : []);
} else {

@@ -512,4 +530,3 @@ const {serialized} = options;

async function loadConfig(options) {
const configs = [];
const {configRoot, experimentalEnvFunc: envFunc} = options;
const {configRoot, experimentalEnvFunc: envFunc, watch} = options;
const configPaths = options.configPaths.slice();

@@ -524,3 +541,4 @@ if (configPaths.length === 0) {

const env = envFunc != null ? envFunc : async (name) => process.env[name];
try {
const loadConfigFiles = async () => {
const configs = [];
for (const configPath of configPaths) {

@@ -540,7 +558,36 @@ if (!path.isAbsolute(configPath)) {

}
return configs;
};
let fileConfigs;
try {
fileConfigs = await loadConfigFiles();
} catch (error) {
throw new Error(`Failed to read static configuration file, ${error.message}`);
}
configs.push(...readEnvConfig(process.env));
return configs;
const envConfigs = await readEnvConfig(process.env);
if (watch) {
let currentSerializedConfig = JSON.stringify(fileConfigs);
const watcher = chokidar__default['default'].watch(configPaths, {
usePolling: process.env.NODE_ENV === "test"
});
watcher.on("change", async () => {
try {
const newConfigs = await loadConfigFiles();
const newSerializedConfig = JSON.stringify(newConfigs);
if (currentSerializedConfig === newSerializedConfig) {
return;
}
currentSerializedConfig = newSerializedConfig;
watch.onChange([...newConfigs, ...envConfigs]);
} catch (error) {
console.error(`Failed to reload configuration files, ${error}`);
}
});
if (watch.stopSignal) {
watch.stopSignal.then(() => {
watcher.close();
});
}
}
return [...fileConfigs, ...envConfigs];
}

@@ -547,0 +594,0 @@

@@ -21,2 +21,4 @@ import { AppConfig, JsonObject } from '@backstage/config';

* APP_CONFIG_app_title='"My Title"'
*
* @public
*/

@@ -27,14 +29,15 @@ declare function readEnvConfig(env: {

/** @public */
declare type EnvFunc = (name: string) => Promise<string | undefined>;
/**
* A list of all possible configuration value visibilities.
*/
declare const CONFIG_VISIBILITIES: readonly ["frontend", "backend", "secret"];
/**
* A type representing the possible configuration value visibilities
*
* @public
*/
declare type ConfigVisibility = typeof CONFIG_VISIBILITIES[number];
declare type ConfigVisibility = 'frontend' | 'backend' | 'secret';
/**
* A function used to transform primitive configuration values.
*
* @public
*/

@@ -46,4 +49,6 @@ declare type TransformFunc<T extends number | string | boolean> = (value: T, context: {

* Options used to process configuration data with a schema.
*
* @public
*/
declare type ConfigProcessingOptions = {
declare type ConfigSchemaProcessingOptions = {
/**

@@ -70,5 +75,7 @@ * The visibilities that should be included in the output data.

* A loaded configuration schema that is ready to process configuration data.
*
* @public
*/
declare type ConfigSchema = {
process(appConfigs: AppConfig[], options?: ConfigProcessingOptions): AppConfig[];
process(appConfigs: AppConfig[], options?: ConfigSchemaProcessingOptions): AppConfig[];
serialize(): JsonObject;

@@ -80,7 +87,11 @@ };

* into a single json schema.
*
* @public
*/
declare function mergeConfigSchemas(schemas: JSONSchema7[]): JSONSchema7;
declare type Options = {
/** @public */
declare type LoadConfigSchemaOptions = {
dependencies: string[];
packagePaths?: string[];
} | {

@@ -91,5 +102,8 @@ serialized: JsonObject;

* Loads config schema for a Backstage instance.
*
* @public
*/
declare function loadConfigSchema(options: Options): Promise<ConfigSchema>;
declare function loadConfigSchema(options: LoadConfigSchemaOptions): Promise<ConfigSchema>;
/** @public */
declare type LoadConfigOptions = {

@@ -106,5 +120,23 @@ configRoot: string;

experimentalEnvFunc?: EnvFunc;
/**
* An optional configuration that enables watching of config files.
*/
watch?: {
/**
* A listener that is called when a config file is changed.
*/
onChange: (configs: AppConfig[]) => void;
/**
* An optional signal that stops the watcher once the promise resolves.
*/
stopSignal?: Promise<void>;
};
};
/**
* Load configuration data.
*
* @public
*/
declare function loadConfig(options: LoadConfigOptions): Promise<AppConfig[]>;
export { ConfigSchema, ConfigVisibility, LoadConfigOptions, loadConfig, loadConfigSchema, mergeConfigSchemas, readEnvConfig };
export { ConfigSchema, ConfigSchemaProcessingOptions, ConfigVisibility, EnvFunc, LoadConfigOptions, LoadConfigSchemaOptions, TransformFunc, loadConfig, loadConfigSchema, mergeConfigSchemas, readEnvConfig };

@@ -8,2 +8,3 @@ import yaml from 'yaml';

import { getProgramFromFiles, generateSchema } from 'typescript-json-schema';
import chokidar from 'chokidar';

@@ -300,3 +301,3 @@ const ENV_PREFIX = "APP_CONFIG_";

const req = typeof __non_webpack_require__ === "undefined" ? require : __non_webpack_require__;
async function collectConfigSchemas(packageNames) {
async function collectConfigSchemas(packageNames, packagePaths) {
const visitedPackages = new Set();

@@ -306,14 +307,24 @@ const schemas = Array();

const currentDir = await fs.realpath(process.cwd());
async function processItem({name, parentPath}) {
var _a, _b;
if (visitedPackages.has(name)) {
return;
async function processItem(item) {
var _a, _b, _c, _d;
let pkgPath = item.packagePath;
if (pkgPath) {
const pkgExists = await fs.pathExists(pkgPath);
if (!pkgExists) {
return;
}
} else if (item.name) {
const {name, parentPath} = item;
if (visitedPackages.has(name)) {
return;
}
visitedPackages.add(name);
try {
pkgPath = req.resolve(`${name}/package.json`, parentPath && {
paths: [parentPath]
});
} catch {
}
}
visitedPackages.add(name);
let pkgPath;
try {
pkgPath = req.resolve(`${name}/package.json`, parentPath && {
paths: [parentPath]
});
} catch {
if (!pkgPath) {
return;

@@ -324,3 +335,5 @@ }

...Object.keys((_a = pkg.dependencies) != null ? _a : {}),
...Object.keys((_b = pkg.peerDependencies) != null ? _b : {})
...Object.keys((_b = pkg.devDependencies) != null ? _b : {}),
...Object.keys((_c = pkg.optionalDependencies) != null ? _c : {}),
...Object.keys((_d = pkg.peerDependencies) != null ? _d : {})
];

@@ -358,3 +371,6 @@ const hasSchema = "configSchema" in pkg;

}
await Promise.all(packageNames.map((name) => processItem({name, parentPath: currentDir})));
await Promise.all([
...packageNames.map((name) => processItem({name, parentPath: currentDir})),
...packagePaths.map((path) => processItem({name: path, packagePath: path}))
]);
const tsSchemas = compileTsSchemas(tsSchemaPaths);

@@ -456,5 +472,6 @@ return schemas.concat(tsSchemas);

async function loadConfigSchema(options) {
var _a;
let schemas;
if ("dependencies" in options) {
schemas = await collectConfigSchemas(options.dependencies);
schemas = await collectConfigSchemas(options.dependencies, (_a = options.packagePaths) != null ? _a : []);
} else {

@@ -500,4 +517,3 @@ const {serialized} = options;

async function loadConfig(options) {
const configs = [];
const {configRoot, experimentalEnvFunc: envFunc} = options;
const {configRoot, experimentalEnvFunc: envFunc, watch} = options;
const configPaths = options.configPaths.slice();

@@ -512,3 +528,4 @@ if (configPaths.length === 0) {

const env = envFunc != null ? envFunc : async (name) => process.env[name];
try {
const loadConfigFiles = async () => {
const configs = [];
for (const configPath of configPaths) {

@@ -528,7 +545,36 @@ if (!isAbsolute(configPath)) {

}
return configs;
};
let fileConfigs;
try {
fileConfigs = await loadConfigFiles();
} catch (error) {
throw new Error(`Failed to read static configuration file, ${error.message}`);
}
configs.push(...readEnvConfig(process.env));
return configs;
const envConfigs = await readEnvConfig(process.env);
if (watch) {
let currentSerializedConfig = JSON.stringify(fileConfigs);
const watcher = chokidar.watch(configPaths, {
usePolling: process.env.NODE_ENV === "test"
});
watcher.on("change", async () => {
try {
const newConfigs = await loadConfigFiles();
const newSerializedConfig = JSON.stringify(newConfigs);
if (currentSerializedConfig === newSerializedConfig) {
return;
}
currentSerializedConfig = newSerializedConfig;
watch.onChange([...newConfigs, ...envConfigs]);
} catch (error) {
console.error(`Failed to reload configuration files, ${error}`);
}
});
if (watch.stopSignal) {
watch.stopSignal.then(() => {
watcher.close();
});
}
}
return [...fileConfigs, ...envConfigs];
}

@@ -535,0 +581,0 @@

{
"name": "@backstage/config-loader",
"description": "Config loading functionality used by Backstage backend, and CLI",
"version": "0.0.0-nightly-20217521743",
"version": "0.0.0-nightly-202182821947",
"private": false,

@@ -33,6 +33,7 @@ "publishConfig": {

"dependencies": {
"@backstage/cli-common": "^0.1.1",
"@backstage/config": "^0.0.0-nightly-20217521743",
"@backstage/cli-common": "^0.1.3",
"@backstage/config": "^0.1.9",
"@types/json-schema": "^7.0.6",
"ajv": "^7.0.3",
"chokidar": "^3.5.2",
"fs-extra": "9.1.0",

@@ -51,3 +52,3 @@ "json-schema": "^0.3.0",

"@types/yup": "^0.29.8",
"mock-fs": "^4.13.0"
"mock-fs": "^5.1.0"
},

@@ -54,0 +55,0 @@ "files": [

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc