Skip to content

Commit

Permalink
add watch mode to start server cli command (#37)
Browse files Browse the repository at this point in the history
* add watch mode to start server cli command

* update tests

* add changeset
  • Loading branch information
gladwindos committed Mar 21, 2024
1 parent a57a1e8 commit 682012a
Show file tree
Hide file tree
Showing 29 changed files with 219 additions and 163 deletions.
7 changes: 7 additions & 0 deletions .changeset/stale-turtles-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@gateweaver/policies": patch
"@gateweaver/server": patch
"@gateweaver/cli": patch
---

Update CLI and server with watch config
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"description": "",
"scripts": {
"dev": "turbo build:watch & nodemon packages/server/src/index.ts",
"dev": "turbo build:watch & nodemon packages/server/src/main.ts",
"build": "turbo build",
"build:watch": "turbo build:watch",
"test": "turbo test",
Expand Down
22 changes: 0 additions & 22 deletions packages/cli/src/actions/generate-api-key.ts

This file was deleted.

3 changes: 0 additions & 3 deletions packages/cli/src/actions/index.ts

This file was deleted.

9 changes: 0 additions & 9 deletions packages/cli/src/actions/start.ts

This file was deleted.

17 changes: 0 additions & 17 deletions packages/cli/src/actions/validate.ts

This file was deleted.

23 changes: 23 additions & 0 deletions packages/cli/src/commands/generate-api-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Command } from "commander";
import { generateApiKey, hashApiKey } from "@gateweaver/policies";

export const generateApiKeyCommand = (program: Command) => {
program
.command("generate-api-key")
.description("Generate a new API key and hash")
.action(() => {
try {
const apiKey = generateApiKey();
const apiKeyHash = hashApiKey(apiKey);

console.log("API Key:", apiKey);
console.log("\nHashed API Key:", apiKeyHash);

console.log(
"\nPlease store the API Key securely and add the hashed API Key to your config file.", // TODO: add link to docs
);
} catch (error) {
console.error(error);
}
});
};
3 changes: 3 additions & 0 deletions packages/cli/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { startServerCommand } from "./start";
export { validateConfigCommand } from "./validate";
export { generateApiKeyCommand } from "./generate-api-key";
24 changes: 24 additions & 0 deletions packages/cli/src/commands/start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Command } from "commander";
import { startServer } from "@gateweaver/server";

export const startServerCommand = (program: Command) => {
program
.command("start")
.description("Start the gateweaver server")
.option(
"-c, --config <configPath>",
"Path to the config file",
"gateweaver",
)
.option(
"-w, --watch",
"Watch the config file for changes and restart the server",
)
.action((options) => {
try {
startServer(options.config, options.watch);
} catch (error) {
console.error(error);
}
});
};
28 changes: 28 additions & 0 deletions packages/cli/src/commands/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Command } from "commander";
import { parseConfig, InvalidConfigError } from "@gateweaver/server";

export const validateConfigCommand = (program: Command) => {
program
.command("validate")
.description("Validate a gateweaver config file")
.option(
"-c, --config <configPath>",
"Path to the config file",
"gateweaver",
)
.action((options) => {
try {
parseConfig(options.config);
console.log("✅ Config file is valid");
} catch (error) {
if (error instanceof InvalidConfigError) {
const validationErrors = error.message.split("\n");

console.log("❌ Config file validation errors:");
validationErrors.forEach((error) => console.log(`- ${error}`));
} else {
console.log(error);
}
}
});
};
23 changes: 8 additions & 15 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
import { config } from "dotenv";
config({ path: ".env.gateweaver" });
import { program } from "commander";
import { startAction, validateAction, generateApiKeyAction } from "./actions";
import {
startServerCommand,
validateConfigCommand,
generateApiKeyCommand,
} from "./commands";

const setupCLI = async () => {
const packageJson = await import("../package.json", {
Expand All @@ -14,22 +18,11 @@ const setupCLI = async () => {
.description("A CLI tool for managing gateweaver gateways")
.version(packageJson.default.version);

program
.command("start")
.description("Start the gateweaver server")
.argument("[configPath]", "Path to the config file", "gateweaver")
.action(startAction);
startServerCommand(program);

program
.command("validate")
.description("Validate a gateweaver config file")
.argument("[configPath]", "Path to the config file", "gateweaver")
.action(validateAction);
validateConfigCommand(program);

program
.command("generate-api-key")
.description("Generate a new API key and hash")
.action(generateApiKeyAction);
generateApiKeyCommand(program);

program.parse();
};
Expand Down
7 changes: 2 additions & 5 deletions packages/policies/src/api-key/api-key.middleware.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { Request, Response } from "express";
import {
apiKeyMiddleware,
hashApiKey,
isValidApiKey,
} from "./api-key.middleware";
import { apiKeyMiddleware } from "./api-key.middleware";
import { hashApiKey, isValidApiKey } from "./utils";

describe("isValidApiKey", () => {
it("returns true for a valid API key", () => {
Expand Down
16 changes: 1 addition & 15 deletions packages/policies/src/api-key/api-key.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
import crypto from "crypto";
import { Request, Response, NextFunction, RequestHandler } from "express";
import { ApiKeyPolicy } from "./api-key.schema";

export const hashApiKey = (apiKey: string): string => {
return crypto.createHash("sha256").update(apiKey).digest("hex");
};

export const isValidApiKey = (
apiKey: string | string[],
apiKeyHashes: string[],
) => {
if (typeof apiKey !== "string") return false;

const apiKeyHash = hashApiKey(apiKey);
return apiKeyHashes.includes(apiKeyHash);
};
import { isValidApiKey } from "./utils";

export const apiKeyMiddleware = (policy: ApiKeyPolicy): RequestHandler => {
return (req: Request, res: Response, next: NextFunction) => {
Expand Down
1 change: 1 addition & 0 deletions packages/policies/src/api-key/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./api-key.schema";
export * from "./api-key.middleware";
export * from "./utils";
19 changes: 19 additions & 0 deletions packages/policies/src/api-key/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import crypto from "crypto";

export const generateApiKey = (): string => {
return crypto.randomUUID().replace(/-/g, "");
};

export const hashApiKey = (apiKey: string): string => {
return crypto.createHash("sha256").update(apiKey).digest("hex");
};

export const isValidApiKey = (
apiKey: string | string[],
apiKeyHashes: string[],
) => {
if (typeof apiKey !== "string") return false;

const apiKeyHash = hashApiKey(apiKey);
return apiKeyHashes.includes(apiKeyHash);
};
17 changes: 4 additions & 13 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,10 @@
"version": "0.0.17",
"description": "",
"main": "./dist/index.js",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./utils": {
"import": "./dist/utils/index.mjs",
"require": "./dist/utils/index.js",
"types": "./dist/utils/index.d.ts"
}
},
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"scripts": {
"start": "node ./dist/index.js",
"start": "node ./dist/main.js",
"build": "tsup",
"build:watch": "pnpm build --watch",
"lint": "eslint .",
Expand All @@ -30,6 +20,7 @@
"@gateweaver/policies": "workspace:*",
"ajv": "^8.12.0",
"ajv-formats": "^2.1.1",
"chokidar": "^3.6.0",
"dotenv": "^16.4.5",
"express": "^4.18.3",
"express-jwt": "^8.4.1",
Expand Down
20 changes: 4 additions & 16 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,4 @@
import { config } from "dotenv";
config({ path: ".env.gateweaver" });
import { startServer, logger, InvalidConfigError } from "./utils";

try {
startServer();
} catch (error) {
if (error instanceof InvalidConfigError) {
const validationErrors = error.message.split("\n");

logger.error("Invalid config file");
logger.error(validationErrors);
} else {
logger.error(error);
}
}
export { logger } from "./logger";
export { startServer } from "./server";
export { parseConfig } from "./config/parse-config";
export { InvalidConfigError } from "./config/validate-config";
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ const options =
? {
transport: {
target: "pino-pretty",
options: {
ignore: "time,pid,hostname,level",
messageFormat: "[gateweaver]: {msg}",
},
},
}
: {};
Expand Down
9 changes: 9 additions & 0 deletions packages/server/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { config } from "dotenv";
config({ path: ".env.gateweaver" });
import { logger, startServer } from ".";

try {
startServer();
} catch (error) {
logger.error(error);
}
2 changes: 1 addition & 1 deletion packages/server/src/middleware/error-handler.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextFunction, Request, Response } from "express";
import { UnauthorizedError } from "express-jwt";
import { RateLimitUnauthorizedError } from "@gateweaver/policies";
import { logger } from "../utils/logger";
import { logger } from "../logger";

export const errorHandler = (
err: Error,
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/middleware/http-logger.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Request, Response, NextFunction } from "express";
import { logger } from "../utils";
import { logger } from "../logger";

export const httpLogger = (req: Request, res: Response, next: NextFunction) => {
const query = Object.keys(req.query).length ? req.query : undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/router/setup/setup-endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Router } from "express";
import { Config } from "../../config/config.types";
import { setupProxy } from "./setup-proxy";
import { setupPolicies } from "./setup-policies";
import { logger } from "../../utils";
import { logger } from "../../logger";

export const setupEndpoints = (router: Router, config: Config) => {
const { endpoints, policyDefinitions } = config;
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/router/setup/setup-policies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from "@gateweaver/policies";
import { Router } from "express";
import { Endpoint } from "../../config/config.types";
import { logger } from "../../utils";
import { logger } from "../../logger";

export const setupPolicies = (
router: Router,
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/router/setup/setup-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Request, Response, Router } from "express";
import { createProxyMiddleware, type Options } from "http-proxy-middleware";
import { PolicyOption } from "@gateweaver/policies";
import { Endpoint } from "../../config/config.types";
import { logger } from "../../utils";
import { logger } from "../../logger";

const deleteHeaders = (res: IncomingMessage, headers: string[]) => {
headers.forEach((header) => {
Expand Down
Loading

0 comments on commit 682012a

Please sign in to comment.