@smplcty/dev-backend 0.1.1 → 0.2.0

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/README.md CHANGED
@@ -22,17 +22,17 @@ pnpm add -D @smplcty/dev-backend
22
22
  dev-backend [config-path]
23
23
  ```
24
24
 
25
- Default config path is `back-end.routes.json` in the current
25
+ Default config path is `backend.routes.json` in the current
26
26
  directory.
27
27
 
28
28
  ## Config
29
29
 
30
- `back-end.routes.json` — committed to your frontend repo:
30
+ `backend.routes.json` — committed to your frontend repo:
31
31
 
32
32
  ```json
33
33
  {
34
34
  "port": 4000,
35
- "envFile": ".env.back-end",
35
+ "envFile": ".env.backend",
36
36
  "routes": {
37
37
  "/graphql": "../handle-graphql/dist/index.js",
38
38
  "/sign-in": {
@@ -74,7 +74,7 @@ All paths are resolved relative to the config file's location.
74
74
 
75
75
  ### Env files
76
76
 
77
- `.env.back-end` — shared variables (gitignored):
77
+ `.env.backend` — shared variables (gitignored):
78
78
 
79
79
  ```
80
80
  DATABASE_URL=postgresql://...
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import { loadConfig } from './config.js';
3
3
  import { loadEnvFile } from './env.js';
4
4
  import { loadHandlers } from './handlers.js';
5
5
  import { startServer } from './server.js';
6
- const configPath = process.argv[2] ?? 'back-end.routes.json';
6
+ const configPath = process.argv[2] ?? 'backend.routes.json';
7
7
  console.log(`Loading config from ${configPath}`);
8
8
  const config = loadConfig(configPath);
9
9
  console.log(`Loading env from ${config.envFile}`);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,sBAAsB,CAAC;AAE7D,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;AACjD,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;AAEtC,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AAClD,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAE5B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACjC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAEnD,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACvC,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,qBAAqB,CAAC;AAE5D,OAAO,CAAC,GAAG,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;AACjD,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;AAEtC,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AAClD,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAE5B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACjC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAEnD,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACvC,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC"}
package/dist/config.d.ts CHANGED
@@ -5,6 +5,10 @@ export interface RouteConfig {
5
5
  * Overrides values from the base envFile. Useful when handlers
6
6
  * need different DATABASE_URL values. */
7
7
  envFile?: string;
8
+ /** Optional authorizer module path. If set, the authorizer is
9
+ * called before the handler on every request. If it returns
10
+ * `{ isAuthorized: false }`, the request is rejected with 403. */
11
+ authorizer?: string;
8
12
  }
9
13
  export interface Config {
10
14
  /** HTTP port. Default 4000. */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB;;8CAE0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACrC;AAUD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAiCrD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB;;8CAE0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;uEAEmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,MAAM;IACrB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACrC;AAUD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAkCrD"}
package/dist/config.js CHANGED
@@ -27,12 +27,13 @@ export function loadConfig(configPath) {
27
27
  routes[path] = {
28
28
  handler: resolve(dir, entry.handler),
29
29
  envFile: entry.envFile ? resolve(dir, entry.envFile) : undefined,
30
+ authorizer: entry.authorizer ? resolve(dir, entry.authorizer) : undefined,
30
31
  };
31
32
  }
32
33
  }
33
34
  return {
34
35
  port: raw.port ?? 4000,
35
- envFile: resolve(dir, raw.envFile ?? '.env.back-end'),
36
+ envFile: resolve(dir, raw.envFile ?? '.env.backend'),
36
37
  routes,
37
38
  };
38
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4B7C;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE7B,IAAI,GAAc,CAAC;IACnB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAc,CAAC;IAChE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,KAAK,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,MAAM,GAAgC,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,GAAG;gBACb,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;aACjE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI;QACtB,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,IAAI,eAAe,CAAC;QACrD,MAAM;KACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgC7C;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,UAAkB;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE7B,IAAI,GAAc,CAAC;IACnB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAc,CAAC;IAChE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,KAAK,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,MAAM,GAAgC,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,GAAG;gBACb,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;gBAChE,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;aAC1E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI;QACtB,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,IAAI,cAAc,CAAC;QACpD,MAAM;KACP,CAAC;AACJ,CAAC"}
@@ -1,13 +1,20 @@
1
1
  import type { RouteConfig } from './config.js';
2
2
  export type Handler = (event: Record<string, unknown>) => Promise<{
3
3
  statusCode: number;
4
- body?: string;
4
+ body?: string | Record<string, unknown>;
5
5
  headers?: Record<string, string>;
6
6
  }>;
7
+ export type Authorizer = (event: Record<string, unknown>) => Promise<{
8
+ isAuthorized: boolean;
9
+ }>;
10
+ export interface LoadedRoute {
11
+ handler: Handler;
12
+ authorizer?: Authorizer;
13
+ }
7
14
  /**
8
- * Import all handler modules. For routes with a per-route envFile,
9
- * temporarily override process.env before importing so the handler's
10
- * module-level init (e.g. Pool creation) picks up the right values.
15
+ * Import all handler modules (and optional authorizers). For routes
16
+ * with a per-route envFile, temporarily override process.env before
17
+ * importing so the handler's module-level init picks up the right values.
11
18
  */
12
- export declare function loadHandlers(routes: Record<string, RouteConfig>): Promise<Record<string, Handler>>;
19
+ export declare function loadHandlers(routes: Record<string, RouteConfig>): Promise<Record<string, LoadedRoute>>;
13
20
  //# sourceMappingURL=handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC,CAAC;AAEH;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA6ClC"}
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;IACnE,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CA4DtC"}
package/dist/handlers.js CHANGED
@@ -2,14 +2,13 @@ import { readFileSync, existsSync } from 'node:fs';
2
2
  import { pathToFileURL } from 'node:url';
3
3
  import { loadEnvFile } from './env.js';
4
4
  /**
5
- * Import all handler modules. For routes with a per-route envFile,
6
- * temporarily override process.env before importing so the handler's
7
- * module-level init (e.g. Pool creation) picks up the right values.
5
+ * Import all handler modules (and optional authorizers). For routes
6
+ * with a per-route envFile, temporarily override process.env before
7
+ * importing so the handler's module-level init picks up the right values.
8
8
  */
9
9
  export async function loadHandlers(routes) {
10
- const handlers = {};
10
+ const loaded = {};
11
11
  for (const [path, route] of Object.entries(routes)) {
12
- // Snapshot env vars that the route's envFile might override
13
12
  const overrides = new Map();
14
13
  if (route.envFile) {
15
14
  const keys = readEnvKeys(route.envFile);
@@ -26,8 +25,18 @@ export async function loadHandlers(routes) {
26
25
  console.error(` ${path}: ${route.handler} does not export a handler function — skipping`);
27
26
  continue;
28
27
  }
29
- handlers[path] = handler;
30
- console.log(` ${path} → ${route.handler}`);
28
+ let authorizer;
29
+ if (route.authorizer) {
30
+ const authMod = (await import(pathToFileURL(route.authorizer).href));
31
+ authorizer = authMod.handler;
32
+ if (typeof authorizer !== 'function') {
33
+ console.error(` ${path}: ${route.authorizer} does not export a handler function — skipping authorizer`);
34
+ authorizer = undefined;
35
+ }
36
+ }
37
+ loaded[path] = { handler, authorizer };
38
+ const suffix = authorizer ? ' (with authorizer)' : '';
39
+ console.log(` ${path} → ${route.handler}${suffix}`);
31
40
  }
32
41
  catch (err) {
33
42
  console.error(` ${path}: failed to import ${route.handler}:`, err);
@@ -44,7 +53,7 @@ export async function loadHandlers(routes) {
44
53
  }
45
54
  }
46
55
  }
47
- return handlers;
56
+ return loaded;
48
57
  }
49
58
  /**
50
59
  * Parse an env file to extract just the key names.
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAkBvC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAmC;IAEnC,MAAM,MAAM,GAAgC,EAAE,CAAC;IAE/C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,MAAM,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;QAExD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACxC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBACrC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YACD,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CACvB,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAClC,CAA4B,CAAC;YAE9B,MAAM,OAAO,GAAG,GAAG,CAAC,OAA8B,CAAC;YACnD,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;gBAClC,OAAO,CAAC,KAAK,CACX,KAAK,IAAI,KAAK,KAAK,CAAC,OAAO,gDAAgD,CAC5E,CAAC;gBACF,SAAS;YACX,CAAC;YAED,IAAI,UAAkC,CAAC;YACvC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,MAAM,OAAO,GAAG,CAAC,MAAM,MAAM,CAC3B,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CACrC,CAA4B,CAAC;gBAC9B,UAAU,GAAG,OAAO,CAAC,OAAiC,CAAC;gBACvD,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;oBACrC,OAAO,CAAC,KAAK,CACX,KAAK,IAAI,KAAK,KAAK,CAAC,UAAU,2DAA2D,CAC1F,CAAC;oBACF,UAAU,GAAG,SAAS,CAAC;gBACzB,CAAC;YACH,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,MAAM,KAAK,CAAC,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,sBAAsB,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;YACpE,SAAS;QACX,CAAC;gBAAS,CAAC;YACT,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,SAAS,EAAE,CAAC;gBACxC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,QAAgB;IACnC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,CAAC,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { loadConfig, type Config, type RouteConfig } from './config.js';
2
2
  export { loadEnvFile } from './env.js';
3
- export { loadHandlers, type Handler } from './handlers.js';
3
+ export { loadHandlers, type Handler, type Authorizer, type LoadedRoute } from './handlers.js';
4
4
  export { startServer } from './server.js';
5
5
  export { buildEvent, decompressResponse } from './event.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAiC,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAgB,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAiC,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAmD,MAAM,eAAe,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
package/dist/server.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { Handler } from './handlers.js';
1
+ import type { LoadedRoute } from './handlers.js';
2
2
  /**
3
3
  * Start the HTTP server that routes requests to Lambda handlers.
4
4
  */
5
- export declare function startServer(handlers: Record<string, Handler>, port: number): void;
5
+ export declare function startServer(routes: Record<string, LoadedRoute>, port: number): void;
6
6
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,IAAI,EAAE,MAAM,GACX,IAAI,CAkDN"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD;;GAEG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,IAAI,EAAE,MAAM,GACX,IAAI,CAsEN"}
package/dist/server.js CHANGED
@@ -3,7 +3,7 @@ import { buildEvent, decompressResponse } from './event.js';
3
3
  /**
4
4
  * Start the HTTP server that routes requests to Lambda handlers.
5
5
  */
6
- export function startServer(handlers, port) {
6
+ export function startServer(routes, port) {
7
7
  const server = createServer(async (req, res) => {
8
8
  const url = req.url ?? '/';
9
9
  const [rawPath, query] = url.replace('//', '/').split('?');
@@ -15,8 +15,8 @@ export function startServer(handlers, port) {
15
15
  res.end();
16
16
  return;
17
17
  }
18
- const handler = handlers[rawPath];
19
- if (!handler) {
18
+ const route = routes[rawPath];
19
+ if (!route) {
20
20
  setCorsHeaders(res);
21
21
  res.statusCode = 404;
22
22
  res.setHeader('Content-Type', 'application/json');
@@ -25,11 +25,27 @@ export function startServer(handlers, port) {
25
25
  }
26
26
  try {
27
27
  const event = await buildEvent(req, rawPath, query);
28
- const response = await handler(event);
28
+ // Run authorizer if configured
29
+ if (route.authorizer) {
30
+ const { isAuthorized } = await route.authorizer(event);
31
+ if (!isAuthorized) {
32
+ setCorsHeaders(res);
33
+ res.statusCode = 403;
34
+ res.setHeader('Content-Type', 'application/json');
35
+ res.end(JSON.stringify({ message: 'Forbidden' }));
36
+ return;
37
+ }
38
+ }
39
+ const response = await route.handler(event);
29
40
  setCorsHeaders(res);
30
41
  res.statusCode = response.statusCode;
31
42
  res.setHeader('Content-Type', 'application/json');
32
43
  let body = response.body ?? '';
44
+ // Auto-stringify object bodies — some handlers return body as
45
+ // an object expecting API Gateway to serialize it.
46
+ if (typeof body !== 'string') {
47
+ body = JSON.stringify(body);
48
+ }
33
49
  if (response.headers?.['Content-Encoding'] === 'gzip') {
34
50
  body = decompressResponse(body);
35
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAG5D;;GAEG;AACH,MAAM,UAAU,WAAW,CACzB,MAAmC,EACnC,IAAY;IAEZ,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAE,EAAE;QAC9E,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;QAC3B,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAiC,CAAC;QAE3F,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEnE,iBAAiB;QACjB,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,cAAc,CAAC,GAAG,CAAC,CAAC;YACpB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,cAAc,CAAC,GAAG,CAAC,CAAC;YACpB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YAClD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,kBAAkB,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YAEpD,+BAA+B;YAC/B,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACrB,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;gBACvD,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,cAAc,CAAC,GAAG,CAAC,CAAC;oBACpB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;oBACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;oBAClD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;oBAClD,OAAO;gBACT,CAAC;YACH,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAE5C,cAAc,CAAC,GAAG,CAAC,CAAC;YACpB,GAAG,CAAC,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;YACrC,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YAElD,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;YAE/B,8DAA8D;YAC9D,mDAAmD;YACnD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7B,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;YAED,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,kBAAkB,CAAC,KAAK,MAAM,EAAE,CAAC;gBACtD,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;YAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,kBAAkB,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,cAAc,CAAC,GAAG,CAAC,CAAC;YACpB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YAClD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACvB,OAAO,CAAC,GAAG,CAAC,+CAA+C,IAAI,GAAG,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,GAAmB;IACzC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,wCAAwC,CAAC,CAAC;IACxF,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,6BAA6B,CAAC,CAAC;AAC/E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smplcty/dev-backend",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Local Lambda dev server — reads a routes config, loads .env, serves Lambda handlers over HTTP with API Gateway v2 event translation.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -41,7 +41,8 @@
41
41
  "lint": "eslint src",
42
42
  "typecheck": "tsc --noEmit",
43
43
  "test": "vitest run",
44
- "test:watch": "vitest"
44
+ "test:watch": "vitest",
45
+ "release": "git push origin main --follow-tags && gh release create v$(node -p \"require('./package.json').version\") --generate-notes"
45
46
  },
46
47
  "devDependencies": {
47
48
  "@eslint/js": "^10.0.1",