Skip to content

Commit

Permalink
feat: add --env-path option to load env file
Browse files Browse the repository at this point in the history
  • Loading branch information
nwtgck committed Aug 29, 2023
1 parent 23e6dd0 commit a6640ef
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 56 deletions.
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"dependencies": {
"basic-auth": "^2.0.1",
"cookie": "^0.5.0",
"dotenv": "^16.3.1",
"js-yaml": "^4.1.0",
"log4js": "^6.9.1",
"openid-client": "^5.4.3",
Expand Down
6 changes: 4 additions & 2 deletions src/command/migrate-config-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import * as fs from "fs";
import {configV1Schema, migrateToConfigV1} from "../config/v1";
import {configWihtoutVersionSchema} from "../config/without-version";
import * as yaml from "js-yaml";
import * as dotenv from "dotenv";

export function migrateConfigCommand(configPath: string) {
const configYaml = customYamlLoad(fs.readFileSync(configPath, 'utf8'));
export function migrateConfigCommand(envFilePath: string | undefined, configPath: string) {
const extraEnv = envFilePath == undefined ? {} : dotenv.parse(fs.readFileSync(envFilePath));
const configYaml = customYamlLoad({ extraEnv, yamlString: fs.readFileSync(configPath, 'utf8') });
if (configV1Schema.safeParse(configYaml).success) {
console.log("The config is already a valid config v1");
return;
Expand Down
96 changes: 51 additions & 45 deletions src/custom-yaml-load.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,58 @@
import * as yaml from "js-yaml";

export function customYamlLoad(str: string) {
return yaml.load(str, { schema: customYamlSchema });
}
export function customYamlLoad({extraEnv, yamlString}: {extraEnv: { [name: string]: string }, yamlString: string}) {
const concatYamlType = new yaml.Type('!concat', {
kind: 'sequence',
resolve(data) {
return Array.isArray(data);
},
construct(data) {
return data.join("");
},
});

const concatYamlType = new yaml.Type('!concat', {
kind: 'sequence',
resolve(data) {
return Array.isArray(data);
},
construct(data) {
return data.join("");
},
});
const envYamlType = new yaml.Type('!env', {
kind: 'scalar',
resolve(data) {
return typeof data === "string";
},
construct(data) {
// if env[data] is undefined, the config validation will occur an error.
const env = {
...process.env,
// override
...extraEnv,
}
return env[data];
},
});

const envYamlType = new yaml.Type('!env', {
kind: 'scalar',
resolve(data) {
return typeof data === "string";
},
construct(data) {
return process.env[data];
},
});
const jsonDecodeYamlType = new yaml.Type('!json_decode', {
kind: 'scalar',
resolve(data) {
return typeof data === "string";
},
construct(data) {
return JSON.parse(data);
},
});

const jsonDecodeYamlType = new yaml.Type('!json_decode', {
kind: 'scalar',
resolve(data) {
return typeof data === "string";
},
construct(data) {
return JSON.parse(data);
},
});
const unrecommendedJsYamlType = new yaml.Type('!unrecommended_js', {
kind: 'scalar',
resolve(data) {
return typeof data === "string";
},
construct(data) {
return new Function("require", data)(require);
},
});

const unrecommendedJsYamlType = new yaml.Type('!unrecommended_js', {
kind: 'scalar',
resolve(data) {
return typeof data === "string";
},
construct(data) {
return new Function("require", data)(require);
},
});
const customYamlSchema = yaml.DEFAULT_SCHEMA.extend([
concatYamlType,
envYamlType,
jsonDecodeYamlType,
unrecommendedJsYamlType,
]);

const customYamlSchema = yaml.DEFAULT_SCHEMA.extend([
concatYamlType,
envYamlType,
jsonDecodeYamlType,
unrecommendedJsYamlType,
]);
return yaml.load(yamlString, { schema: customYamlSchema });
}
28 changes: 21 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as log4js from "log4js";
import * as yargs from "yargs";
import { z } from "zod";
import * as piping from "piping-server";
import * as dotenv from "dotenv";

import {generateHandler} from "./rich-piping-server";
import {configWihtoutVersionSchema} from "./config/without-version";
Expand Down Expand Up @@ -46,6 +47,10 @@ const parser = yargs
describe: "Certification path",
type: "string"
})
.option('env-path', {
describe: ".env file path",
type: "string",
})
.option('config-path', {
describe: "Config YAML path",
type: "string",
Expand All @@ -63,7 +68,7 @@ https://github.com/nwtgck/rich-piping-server#readme
})
.command("migrate-config", "Print migrated config", (yargs) => {
}, (argv) => {
migrateConfigCommand(argv.configPath);
migrateConfigCommand(argv.envPath, argv.configPath);
});


Expand All @@ -82,6 +87,7 @@ if (args._.length === 0) {
httpsPort: args["https-port"],
serverKeyPath: args["key-path"],
serverCrtPath: args["crt-path"],
envFilePath: args["env-path"],
configYamlPath: args["config-yaml-path"],
printConfigJson: args["debug-config"],
});
Expand All @@ -104,11 +110,12 @@ function logZodError<T>(zodError: z.ZodError<T>) {
}
}

function loadAndUpdateConfig(logger: log4js.Logger, configYamlPath: string, printConfigJson: boolean): void {
function loadAndUpdateConfig(logger: log4js.Logger, envFilePath: string | undefined, configYamlPath: string, printConfigJson: boolean): void {
// Load config
logger.info(`Loading ${JSON.stringify(configYamlPath)}...`);
logger.info(`Loading ${ envFilePath === undefined ? "" : `${JSON.stringify(envFilePath)} and ` }${JSON.stringify(configYamlPath)}...`);
try {
const configYaml = customYamlLoad(fs.readFileSync(configYamlPath, 'utf8'));
const extraEnv = envFilePath == undefined ? {} : dotenv.parse(fs.readFileSync(envFilePath));
const configYaml = customYamlLoad({ extraEnv, yamlString: fs.readFileSync(configYamlPath, 'utf8') });
// NOTE: using configBasicSchema makes error message better
const configBasicParsed = configBasicSchema.safeParse(configYaml);
if (!configBasicParsed.success) {
Expand Down Expand Up @@ -142,22 +149,29 @@ function loadAndUpdateConfig(logger: log4js.Logger, configYamlPath: string, prin
}
}

async function serve({ host, httpPort, enableHttps, httpsPort, serverKeyPath, serverCrtPath, configYamlPath, printConfigJson }: {
async function serve({ host, httpPort, enableHttps, httpsPort, serverKeyPath, serverCrtPath, envFilePath, configYamlPath, printConfigJson }: {
host: string | undefined,
httpPort: number,
enableHttps: boolean,
httpsPort: number | undefined,
serverKeyPath: string | undefined,
envFilePath: string | undefined,
serverCrtPath: string | undefined,
configYamlPath: string,
printConfigJson: boolean,
}) {
// Load config
loadAndUpdateConfig(logger, configYamlPath, printConfigJson);
loadAndUpdateConfig(logger, envFilePath, configYamlPath, printConfigJson);

// Watch env file
if (envFilePath !== undefined) {
fs.watch(envFilePath, () => {
loadAndUpdateConfig(logger, envFilePath, configYamlPath, printConfigJson);
});
}
// Watch config yaml
fs.watch(configYamlPath, () => {
loadAndUpdateConfig(logger, configYamlPath, printConfigJson);
loadAndUpdateConfig(logger, envFilePath, configYamlPath, printConfigJson);
});

// Create a piping server
Expand Down
4 changes: 2 additions & 2 deletions test/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ export function createTransferAssertions({getPipingUrl}: { getPipingUrl: () => s
}

export function readConfigWithoutVersionAndMigrateToV1AndNormalize(yamlString: string): NormalizedConfig {
const configYaml = customYamlLoad(yamlString);
const configYaml = customYamlLoad({extraEnv: {}, yamlString});
const configWithoutVersion = configWihtoutVersionSchema.parse(configYaml);
return normalizeConfigV1(undefined, migrateToConfigV1(configWithoutVersion));
}

export function readConfigV1AndNormalize(yamlString: string): NormalizedConfig {
const configYaml = customYamlLoad(yamlString);
const configYaml = customYamlLoad({extraEnv: {}, yamlString});
return normalizeConfigV1(undefined, configV1Schema.parse(configYaml));
}

0 comments on commit a6640ef

Please sign in to comment.