postgresdk 0.14.5 → 0.15.2

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
@@ -165,7 +165,7 @@ export default {
165
165
  // OR
166
166
  jwt: { // JWT with multi-service support
167
167
  services: [
168
- { issuer: "my-app", secret: process.env.JWT_SECRET }
168
+ { issuer: "my-app", secret: "env:JWT_SECRET" } // Use "env:" prefix!
169
169
  ]
170
170
  }
171
171
  },
@@ -296,7 +296,7 @@ export default {
296
296
  strategy: "jwt-hs256",
297
297
  jwt: {
298
298
  services: [
299
- { issuer: "my-app", secret: process.env.JWT_SECRET }
299
+ { issuer: "my-app", secret: "env:JWT_SECRET" } // Use "env:" prefix!
300
300
  ],
301
301
  audience: "my-api" // Optional
302
302
  }
@@ -310,8 +310,8 @@ export default {
310
310
  strategy: "jwt-hs256",
311
311
  jwt: {
312
312
  services: [
313
- { issuer: "web-app", secret: process.env.WEB_APP_SECRET },
314
- { issuer: "mobile-app", secret: process.env.MOBILE_SECRET },
313
+ { issuer: "web-app", secret: "env:WEB_APP_SECRET" },
314
+ { issuer: "mobile-app", secret: "env:MOBILE_SECRET" },
315
315
  ],
316
316
  audience: "my-api"
317
317
  }
@@ -352,8 +352,8 @@ export default {
352
352
  strategy: "jwt-hs256",
353
353
  jwt: {
354
354
  services: [
355
- { issuer: "web-app", secret: process.env.WEB_SECRET },
356
- { issuer: "analytics-service", secret: process.env.ANALYTICS_SECRET }
355
+ { issuer: "web-app", secret: "env:WEB_SECRET" },
356
+ { issuer: "analytics-service", secret: "env:ANALYTICS_SECRET" }
357
357
  ],
358
358
  audience: "my-api"
359
359
  }
package/dist/cli.js CHANGED
@@ -3220,7 +3220,7 @@ function emitClientIndex(tables, useJsExtensions) {
3220
3220
  * To make changes, modify your schema or configuration and regenerate.
3221
3221
  */
3222
3222
  `;
3223
- out += `import { BaseClient, type AuthConfig } from "./base-client${ext}";
3223
+ out += `import type { AuthConfig } from "./base-client${ext}";
3224
3224
  `;
3225
3225
  for (const t of tables) {
3226
3226
  out += `import { ${pascal(t.name)}Client } from "./${t.name}${ext}";
@@ -3941,10 +3941,37 @@ function emitAuth(cfgAuth) {
3941
3941
  const apiKeys = cfgAuth?.apiKeys ?? [];
3942
3942
  const jwtServices = cfgAuth?.jwt?.services ?? [];
3943
3943
  const jwtAudience = cfgAuth?.jwt?.audience ?? undefined;
3944
+ if (strategy === "jwt-hs256" && jwtServices.length > 0) {
3945
+ for (const svc of jwtServices) {
3946
+ if (!svc.secret) {
3947
+ throw new Error(`JWT service "${svc.issuer}" is missing required secret.
3948
+
3949
+ ` + `Use the "env:VAR_NAME" pattern in your config:
3950
+ ` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }`);
3951
+ }
3952
+ if (!svc.secret.startsWith("env:")) {
3953
+ throw new Error(`SECURITY ERROR: JWT secret for "${svc.issuer}" must use "env:VAR_NAME" pattern.
3954
+
3955
+ ` + `Found: secret: ${typeof svc.secret === "string" && svc.secret.length > 20 ? '"***REDACTED***"' : JSON.stringify(svc.secret)}
3956
+
3957
+ ` + `Hardcoding secrets in config files is a security risk!
3958
+ ` + `Instead, use:
3959
+ ` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }
3960
+
3961
+ ` + `Then set the environment variable at runtime.`);
3962
+ }
3963
+ }
3964
+ }
3944
3965
  const STRATEGY = JSON.stringify(strategy);
3945
3966
  const API_KEY_HEADER = JSON.stringify(apiKeyHeader);
3946
3967
  const RAW_API_KEYS = JSON.stringify(apiKeys);
3947
- const JWT_SERVICES = JSON.stringify(jwtServices);
3968
+ const jwtServicesCode = jwtServices.length === 0 ? "[]" : `[
3969
+ ${jwtServices.map((svc) => {
3970
+ const varName = svc.secret.slice(4);
3971
+ return ` { issuer: ${JSON.stringify(svc.issuer)}, secret: process.env.${varName} ?? "" }`;
3972
+ }).join(`,
3973
+ `)}
3974
+ ]`;
3948
3975
  const JWT_AUDIENCE = jwtAudience === undefined ? "undefined" : JSON.stringify(jwtAudience);
3949
3976
  return `/**
3950
3977
  * AUTO-GENERATED FILE - DO NOT EDIT
@@ -3962,7 +3989,7 @@ const STRATEGY = ${STRATEGY} as "none" | "api-key" | "jwt-hs256";
3962
3989
  const API_KEY_HEADER = ${API_KEY_HEADER} as string;
3963
3990
  const RAW_API_KEYS = ${RAW_API_KEYS} as readonly string[];
3964
3991
 
3965
- const JWT_SERVICES = ${JWT_SERVICES} as ReadonlyArray<{ issuer: string; secret?: string }>;
3992
+ const JWT_SERVICES = ${jwtServicesCode} as ReadonlyArray<{ issuer: string; secret: string }>;
3966
3993
  const JWT_AUDIENCE = ${JWT_AUDIENCE} as string | undefined;
3967
3994
  // -------------------------------------
3968
3995
 
@@ -3978,15 +4005,6 @@ function expandEnvList(v: string): string[] {
3978
4005
  return v.split(",").map(s => s.trim()).filter(Boolean);
3979
4006
  }
3980
4007
 
3981
- function resolveValue(v: string | undefined): string {
3982
- if (!v) return "";
3983
- if (v.startsWith("env:")) {
3984
- const name = v.slice(4);
3985
- return process.env[name] ?? "";
3986
- }
3987
- return v;
3988
- }
3989
-
3990
4008
  function resolveKeys(keys: readonly string[]): string[] {
3991
4009
  const out: string[] = [];
3992
4010
  for (const k of keys) {
@@ -4004,12 +4022,6 @@ function resolveKeys(keys: readonly string[]): string[] {
4004
4022
 
4005
4023
  const API_KEYS = resolveKeys(RAW_API_KEYS);
4006
4024
 
4007
- // Resolve JWT service secrets from env vars if needed
4008
- const RESOLVED_JWT_SERVICES = JWT_SERVICES.map(svc => ({
4009
- issuer: svc.issuer,
4010
- secret: resolveValue(svc.secret)
4011
- }));
4012
-
4013
4025
  // Augment Hono context for DX
4014
4026
  declare module "hono" {
4015
4027
  interface ContextVariableMap {
@@ -4052,7 +4064,7 @@ export async function authMiddleware(c: Context, next: Next) {
4052
4064
  }
4053
4065
  const token = m[1];
4054
4066
 
4055
- if (!RESOLVED_JWT_SERVICES.length) {
4067
+ if (!JWT_SERVICES.length) {
4056
4068
  log.error("JWT strategy configured but no services defined");
4057
4069
  return c.json({ error: "Unauthorized" }, 401);
4058
4070
  }
@@ -4071,7 +4083,7 @@ export async function authMiddleware(c: Context, next: Next) {
4071
4083
  }
4072
4084
 
4073
4085
  // Find matching service by issuer
4074
- const service = RESOLVED_JWT_SERVICES.find(s => s.issuer === issuer);
4086
+ const service = JWT_SERVICES.find(s => s.issuer === issuer);
4075
4087
  if (!service) {
4076
4088
  log.error("Unknown JWT issuer:", issuer);
4077
4089
  return c.json({ error: "Unauthorized" }, 401);
package/dist/index.js CHANGED
@@ -2394,7 +2394,7 @@ function emitClientIndex(tables, useJsExtensions) {
2394
2394
  * To make changes, modify your schema or configuration and regenerate.
2395
2395
  */
2396
2396
  `;
2397
- out += `import { BaseClient, type AuthConfig } from "./base-client${ext}";
2397
+ out += `import type { AuthConfig } from "./base-client${ext}";
2398
2398
  `;
2399
2399
  for (const t of tables) {
2400
2400
  out += `import { ${pascal(t.name)}Client } from "./${t.name}${ext}";
@@ -3115,10 +3115,37 @@ function emitAuth(cfgAuth) {
3115
3115
  const apiKeys = cfgAuth?.apiKeys ?? [];
3116
3116
  const jwtServices = cfgAuth?.jwt?.services ?? [];
3117
3117
  const jwtAudience = cfgAuth?.jwt?.audience ?? undefined;
3118
+ if (strategy === "jwt-hs256" && jwtServices.length > 0) {
3119
+ for (const svc of jwtServices) {
3120
+ if (!svc.secret) {
3121
+ throw new Error(`JWT service "${svc.issuer}" is missing required secret.
3122
+
3123
+ ` + `Use the "env:VAR_NAME" pattern in your config:
3124
+ ` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }`);
3125
+ }
3126
+ if (!svc.secret.startsWith("env:")) {
3127
+ throw new Error(`SECURITY ERROR: JWT secret for "${svc.issuer}" must use "env:VAR_NAME" pattern.
3128
+
3129
+ ` + `Found: secret: ${typeof svc.secret === "string" && svc.secret.length > 20 ? '"***REDACTED***"' : JSON.stringify(svc.secret)}
3130
+
3131
+ ` + `Hardcoding secrets in config files is a security risk!
3132
+ ` + `Instead, use:
3133
+ ` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }
3134
+
3135
+ ` + `Then set the environment variable at runtime.`);
3136
+ }
3137
+ }
3138
+ }
3118
3139
  const STRATEGY = JSON.stringify(strategy);
3119
3140
  const API_KEY_HEADER = JSON.stringify(apiKeyHeader);
3120
3141
  const RAW_API_KEYS = JSON.stringify(apiKeys);
3121
- const JWT_SERVICES = JSON.stringify(jwtServices);
3142
+ const jwtServicesCode = jwtServices.length === 0 ? "[]" : `[
3143
+ ${jwtServices.map((svc) => {
3144
+ const varName = svc.secret.slice(4);
3145
+ return ` { issuer: ${JSON.stringify(svc.issuer)}, secret: process.env.${varName} ?? "" }`;
3146
+ }).join(`,
3147
+ `)}
3148
+ ]`;
3122
3149
  const JWT_AUDIENCE = jwtAudience === undefined ? "undefined" : JSON.stringify(jwtAudience);
3123
3150
  return `/**
3124
3151
  * AUTO-GENERATED FILE - DO NOT EDIT
@@ -3136,7 +3163,7 @@ const STRATEGY = ${STRATEGY} as "none" | "api-key" | "jwt-hs256";
3136
3163
  const API_KEY_HEADER = ${API_KEY_HEADER} as string;
3137
3164
  const RAW_API_KEYS = ${RAW_API_KEYS} as readonly string[];
3138
3165
 
3139
- const JWT_SERVICES = ${JWT_SERVICES} as ReadonlyArray<{ issuer: string; secret?: string }>;
3166
+ const JWT_SERVICES = ${jwtServicesCode} as ReadonlyArray<{ issuer: string; secret: string }>;
3140
3167
  const JWT_AUDIENCE = ${JWT_AUDIENCE} as string | undefined;
3141
3168
  // -------------------------------------
3142
3169
 
@@ -3152,15 +3179,6 @@ function expandEnvList(v: string): string[] {
3152
3179
  return v.split(",").map(s => s.trim()).filter(Boolean);
3153
3180
  }
3154
3181
 
3155
- function resolveValue(v: string | undefined): string {
3156
- if (!v) return "";
3157
- if (v.startsWith("env:")) {
3158
- const name = v.slice(4);
3159
- return process.env[name] ?? "";
3160
- }
3161
- return v;
3162
- }
3163
-
3164
3182
  function resolveKeys(keys: readonly string[]): string[] {
3165
3183
  const out: string[] = [];
3166
3184
  for (const k of keys) {
@@ -3178,12 +3196,6 @@ function resolveKeys(keys: readonly string[]): string[] {
3178
3196
 
3179
3197
  const API_KEYS = resolveKeys(RAW_API_KEYS);
3180
3198
 
3181
- // Resolve JWT service secrets from env vars if needed
3182
- const RESOLVED_JWT_SERVICES = JWT_SERVICES.map(svc => ({
3183
- issuer: svc.issuer,
3184
- secret: resolveValue(svc.secret)
3185
- }));
3186
-
3187
3199
  // Augment Hono context for DX
3188
3200
  declare module "hono" {
3189
3201
  interface ContextVariableMap {
@@ -3226,7 +3238,7 @@ export async function authMiddleware(c: Context, next: Next) {
3226
3238
  }
3227
3239
  const token = m[1];
3228
3240
 
3229
- if (!RESOLVED_JWT_SERVICES.length) {
3241
+ if (!JWT_SERVICES.length) {
3230
3242
  log.error("JWT strategy configured but no services defined");
3231
3243
  return c.json({ error: "Unauthorized" }, 401);
3232
3244
  }
@@ -3245,7 +3257,7 @@ export async function authMiddleware(c: Context, next: Next) {
3245
3257
  }
3246
3258
 
3247
3259
  // Find matching service by issuer
3248
- const service = RESOLVED_JWT_SERVICES.find(s => s.issuer === issuer);
3260
+ const service = JWT_SERVICES.find(s => s.issuer === issuer);
3249
3261
  if (!service) {
3250
3262
  log.error("Unknown JWT issuer:", issuer);
3251
3263
  return c.json({ error: "Unauthorized" }, 401);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "postgresdk",
3
- "version": "0.14.5",
3
+ "version": "0.15.2",
4
4
  "description": "Generate a typed server/client SDK from a Postgres schema (includes, Zod, Hono).",
5
5
  "type": "module",
6
6
  "bin": {