mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 05:43:41 +00:00
Feature/put serve behind feature flag (#455)
* Add build-time feature flag capabilities * Toggle `bw serve` command with `serve` flag * Run linter and prettier
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
node_modules
|
node_modules
|
||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
|
|
||||||
|
config/local.json
|
||||||
|
|||||||
30
config/config.js
Normal file
30
config/config.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
function load(envName) {
|
||||||
|
return {
|
||||||
|
...loadConfig(envName),
|
||||||
|
...loadConfig("local"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function log(configObj) {
|
||||||
|
const repeatNum = 50;
|
||||||
|
console.log(`${"=".repeat(repeatNum)}\nenvConfig`);
|
||||||
|
console.log(JSON.stringify(configObj, null, 2));
|
||||||
|
console.log(`${"=".repeat(repeatNum)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadConfig(configName) {
|
||||||
|
try {
|
||||||
|
return require(`./${configName}.json`);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Error && e.code === "MODULE_NOT_FOUND") {
|
||||||
|
return {};
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
load,
|
||||||
|
log,
|
||||||
|
};
|
||||||
5
config/development.json
Normal file
5
config/development.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"flags": {
|
||||||
|
"serve": true
|
||||||
|
}
|
||||||
|
}
|
||||||
5
config/production.json
Normal file
5
config/production.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"flags": {
|
||||||
|
"serve": false
|
||||||
|
}
|
||||||
|
}
|
||||||
27
spec/utils.spec.ts
Normal file
27
spec/utils.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { FlagName } from "../src/flags";
|
||||||
|
import { CliUtils } from "../src/utils";
|
||||||
|
describe("flagEnabled", () => {
|
||||||
|
it("is true if flag is null", () => {
|
||||||
|
process.env.FLAGS = JSON.stringify({ test: null });
|
||||||
|
|
||||||
|
expect(CliUtils.flagEnabled("test" as FlagName)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is true if flag is undefined", () => {
|
||||||
|
process.env.FLAGS = JSON.stringify({});
|
||||||
|
|
||||||
|
expect(CliUtils.flagEnabled("test" as FlagName)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is true if flag is true", () => {
|
||||||
|
process.env.FLAGS = JSON.stringify({ test: true });
|
||||||
|
|
||||||
|
expect(CliUtils.flagEnabled("test" as FlagName)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is false if flag is false", () => {
|
||||||
|
process.env.FLAGS = JSON.stringify({ test: false });
|
||||||
|
|
||||||
|
expect(CliUtils.flagEnabled("test" as FlagName)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
5
src/flags.ts
Normal file
5
src/flags.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export type Flags = {
|
||||||
|
serve?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FlagName = keyof Flags;
|
||||||
@@ -468,22 +468,24 @@ export class Program extends BaseProgram {
|
|||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
if (CliUtils.flagEnabled("serve")) {
|
||||||
.command("serve")
|
program
|
||||||
.description("Start a RESTful API webserver.")
|
.command("serve")
|
||||||
.option("--port <port>", "The port to run your API webserver on. Default port is 8087.")
|
.description("Start a RESTful API webserver.")
|
||||||
.on("--help", () => {
|
.option("--port <port>", "The port to run your API webserver on. Default port is 8087.")
|
||||||
writeLn("\n Examples:");
|
.on("--help", () => {
|
||||||
writeLn("");
|
writeLn("\n Examples:");
|
||||||
writeLn(" bw serve");
|
writeLn("");
|
||||||
writeLn(" bw serve --port 8080");
|
writeLn(" bw serve");
|
||||||
writeLn("", true);
|
writeLn(" bw serve --port 8080");
|
||||||
})
|
writeLn("", true);
|
||||||
.action(async (cmd) => {
|
})
|
||||||
await this.exitIfNotAuthed();
|
.action(async (cmd) => {
|
||||||
const command = new ServeCommand(this.main);
|
await this.exitIfNotAuthed();
|
||||||
await command.run(cmd);
|
const command = new ServeCommand(this.main);
|
||||||
});
|
await command.run(cmd);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected processResponse(response: Response, exitImmediately = false) {
|
protected processResponse(response: Response, exitImmediately = false) {
|
||||||
|
|||||||
15
src/utils.ts
15
src/utils.ts
@@ -9,6 +9,7 @@ import { CollectionView } from "jslib-common/models/view/collectionView";
|
|||||||
import { FolderView } from "jslib-common/models/view/folderView";
|
import { FolderView } from "jslib-common/models/view/folderView";
|
||||||
|
|
||||||
import { NodeUtils } from "jslib-common/misc/nodeUtils";
|
import { NodeUtils } from "jslib-common/misc/nodeUtils";
|
||||||
|
import { FlagName, Flags } from "./flags";
|
||||||
|
|
||||||
export class CliUtils {
|
export class CliUtils {
|
||||||
static writeLn(s: string, finalLine: boolean = false, error: boolean = false) {
|
static writeLn(s: string, finalLine: boolean = false, error: boolean = false) {
|
||||||
@@ -174,4 +175,18 @@ export class CliUtils {
|
|||||||
static convertBooleanOption(optionValue: any) {
|
static convertBooleanOption(optionValue: any) {
|
||||||
return optionValue || optionValue === "" ? true : false;
|
return optionValue || optionValue === "" ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static flagEnabled(flag: FlagName) {
|
||||||
|
return this.flags[flag] == null || this.flags[flag];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static get flags(): Flags {
|
||||||
|
const envFlags = process.env.FLAGS;
|
||||||
|
|
||||||
|
if (typeof envFlags === "string") {
|
||||||
|
return JSON.parse(envFlags) as Flags;
|
||||||
|
} else {
|
||||||
|
return envFlags as Flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ const { CleanWebpackPlugin } = require("clean-webpack-plugin");
|
|||||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
const nodeExternals = require("webpack-node-externals");
|
const nodeExternals = require("webpack-node-externals");
|
||||||
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
|
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
|
||||||
|
const config = require("./config/config");
|
||||||
|
|
||||||
if (process.env.NODE_ENV == null) {
|
if (process.env.NODE_ENV == null) {
|
||||||
process.env.NODE_ENV = "development";
|
process.env.NODE_ENV = "development";
|
||||||
}
|
}
|
||||||
const ENV = (process.env.ENV = process.env.NODE_ENV);
|
const ENV = (process.env.ENV = process.env.NODE_ENV);
|
||||||
|
|
||||||
|
const envConfig = config.load(ENV);
|
||||||
|
config.log(envConfig);
|
||||||
|
|
||||||
const moduleRules = [
|
const moduleRules = [
|
||||||
{
|
{
|
||||||
test: /\.ts$/,
|
test: /\.ts$/,
|
||||||
@@ -39,9 +43,13 @@ const plugins = [
|
|||||||
resourceRegExp: /^encoding$/,
|
resourceRegExp: /^encoding$/,
|
||||||
contextRegExp: /node-fetch/,
|
contextRegExp: /node-fetch/,
|
||||||
}),
|
}),
|
||||||
|
new webpack.EnvironmentPlugin({
|
||||||
|
BWCLI_ENV: ENV,
|
||||||
|
FLAGS: envConfig.flags,
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
const config = {
|
const webpackConfig = {
|
||||||
mode: ENV,
|
mode: ENV,
|
||||||
target: "node",
|
target: "node",
|
||||||
devtool: ENV === "development" ? "eval-source-map" : "source-map",
|
devtool: ENV === "development" ? "eval-source-map" : "source-map",
|
||||||
@@ -70,4 +78,4 @@ const config = {
|
|||||||
externals: [nodeExternals()],
|
externals: [nodeExternals()],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = webpackConfig;
|
||||||
|
|||||||
Reference in New Issue
Block a user