sprint-es 0.0.44 → 0.0.46

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/dist/cjs/cli.cjs CHANGED
@@ -87,14 +87,16 @@ switch (command) {
87
87
  runCommand("node dist/index.js", { NODE_ENV: "production" });
88
88
  break;
89
89
  case "generate-keys":
90
- const { publicKey, privateKey } = crypto__namespace.generateKeyPairSync("ec", {
91
- namedCurve: "prime256v1",
90
+ const { publicKey, privateKey } = crypto__namespace.generateKeyPairSync("rsa", {
91
+ modulusLength: 4096,
92
92
  publicKeyEncoding: { type: "spki", format: "pem" },
93
93
  privateKeyEncoding: { type: "pkcs8", format: "pem" }
94
94
  });
95
+ const jwtSecret = crypto__namespace.randomBytes(32).toString("hex");
95
96
  console.log("\nšŸ”‘ Generating JWT keys...\n");
96
97
  console.log("JWT_PUBLIC_KEY='" + publicKey + "'");
97
98
  console.log("\nJWT_PRIVATE_KEY='" + privateKey + "'");
99
+ console.log("\nJWT_ENCRYPTION_SECRET=" + jwtSecret);
98
100
  console.log("\nšŸ“ Add these to your .env file (use single quotes for multiline values):\n");
99
101
  process.exit(0);
100
102
  break;
@@ -184,7 +184,7 @@ class Sprint {
184
184
  name,
185
185
  filePath
186
186
  });
187
- console.log(`[Sprint] Loaded middleware: ${name} (priority: ${config.priority ?? 100})`);
187
+ if (isVerbose) console.log(`[Sprint] Loaded middleware: ${name} (priority: ${config.priority ?? 100})`);
188
188
  }
189
189
  } catch (err) {
190
190
  console.warn(`[Sprint] Failed to load middleware ${filePath}:`, err);
@@ -226,10 +226,10 @@ class Sprint {
226
226
  const routeMiddlewares = this.getMiddlewaresForRoute(routePath);
227
227
  if (routeMiddlewares.length > 0) {
228
228
  this.app.use(finalRoute, ...routeMiddlewares, router);
229
- console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
229
+ if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
230
230
  } else {
231
231
  this.app.use(finalRoute, router);
232
- console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
232
+ if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
233
233
  }
234
234
  }
235
235
  } catch (err) {
@@ -249,7 +249,7 @@ class Sprint {
249
249
  try {
250
250
  const moduleUrl = url.pathToFileURL(filePath).href;
251
251
  await import(moduleUrl);
252
- console.log(`[Sprint] Loaded cronjob: ${file.replace(/\.(ts|js)$/, "")}`);
252
+ if (isVerbose) console.log(`[Sprint] Loaded cronjob: ${file.replace(/\.(ts|js)$/, "")}`);
253
253
  } catch (err) {
254
254
  console.warn(`[Sprint] Failed to load cronjob ${filePath}:`, err);
255
255
  }
@@ -1,80 +1,112 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const crypto = require("crypto");
4
+ const base64UrlEncode = (buffer) => buffer.toString("base64url");
5
+ const base64UrlDecode = (str) => Buffer.from(str, "base64url");
6
+ const decodeBase64Url = (str) => Buffer.from(str, "base64url").toString("utf8");
4
7
  const ALGORITHM = "ES256";
5
- function base64UrlEncode(buffer) {
6
- return buffer.toString("base64url");
7
- }
8
- function base64UrlDecode(str) {
9
- const pad = str.length % 4;
10
- const padded = pad ? str + "=".repeat(4 - pad) : str;
11
- return Buffer.from(padded.replace(/-/g, "+").replace(/_/g, "/"), "base64");
12
- }
13
- function decodeBase64Url(str) {
14
- return Buffer.from(str, "base64url").toString();
15
- }
16
- function generateKeyPair(algorithm = ALGORITHM) {
8
+ const ENCRYPTION_ALGORITHM = "aes-256-gcm";
9
+ function generateKeyPair() {
17
10
  const { publicKey, privateKey } = crypto.generateKeyPairSync("ec", {
18
11
  namedCurve: "prime256v1",
19
- publicKeyEncoding: {
20
- type: "spki",
21
- format: "pem"
22
- },
23
- privateKeyEncoding: {
24
- type: "pkcs8",
25
- format: "pem"
26
- }
12
+ publicKeyEncoding: { type: "spki", format: "pem" },
13
+ privateKeyEncoding: { type: "pkcs8", format: "pem" }
27
14
  });
28
15
  return { publicKey, privateKey };
29
16
  }
30
- function sign(payload, privateKey, options = {}) {
31
- const header = { alg: ALGORITHM, typ: "JWT" };
17
+ function parseExpiry(expiresIn) {
18
+ if (typeof expiresIn === "number") return expiresIn;
19
+ const units = {
20
+ s: 1,
21
+ m: 60,
22
+ h: 3600,
23
+ d: 86400,
24
+ w: 604800
25
+ };
26
+ const match = expiresIn.match(/^(\d+)([smhdw])$/);
27
+ if (!match) throw new Error(`Invalid expiresIn format: "${expiresIn}". Use e.g. "15m", "2h", "7d".`);
28
+ return parseInt(match[1]) * units[match[2]];
29
+ }
30
+ function buildClaims(payload, options) {
32
31
  const now = Math.floor(Date.now() / 1e3);
33
- const claims = { ...payload };
34
- if (options.expiresIn) {
35
- claims.exp = typeof options.expiresIn === "number" ? now + options.expiresIn : now + parseInt(options.expiresIn);
36
- }
32
+ const claims = { ...payload, iat: now };
33
+ if (options.expiresIn !== void 0) claims.exp = now + parseExpiry(options.expiresIn);
37
34
  if (options.issuer) claims.iss = options.issuer;
38
35
  if (options.subject) claims.sub = options.subject;
39
36
  if (options.audience) claims.aud = options.audience;
40
- claims.iat = now;
37
+ return claims;
38
+ }
39
+ function encryptPayload(plaintext, secret) {
40
+ const key = crypto.scryptSync(secret, "sprint-jwt-salt", 32);
41
+ const iv = crypto.randomBytes(12);
42
+ const cipher = crypto.createCipheriv(ENCRYPTION_ALGORITHM, key, iv);
43
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
44
+ const tag = cipher.getAuthTag();
45
+ return base64UrlEncode(Buffer.concat([iv, tag, encrypted]));
46
+ }
47
+ function decryptPayload(data, secret) {
48
+ const key = crypto.scryptSync(secret, "sprint-jwt-salt", 32);
49
+ const buf = base64UrlDecode(data);
50
+ if (buf.length < 28) throw new Error("Invalid encrypted payload.");
51
+ const iv = buf.subarray(0, 12);
52
+ const tag = buf.subarray(12, 28);
53
+ const ciphertext = buf.subarray(28);
54
+ const decipher = crypto.createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);
55
+ decipher.setAuthTag(tag);
56
+ return decipher.update(ciphertext).toString("utf8") + decipher.final("utf8");
57
+ }
58
+ function sign(payload, privateKey, options = {}) {
59
+ const header = { alg: ALGORITHM, typ: "JWT" };
60
+ const claims = buildClaims(payload, options);
41
61
  const encodedHeader = base64UrlEncode(Buffer.from(JSON.stringify(header)));
42
62
  const encodedPayload = base64UrlEncode(Buffer.from(JSON.stringify(claims)));
43
- const sign2 = crypto.createSign("SHA256");
44
- sign2.update(`${encodedHeader}.${encodedPayload}`);
45
- const signature = sign2.sign(privateKey);
46
- return `${encodedHeader}.${encodedPayload}.${base64UrlEncode(signature)}`;
63
+ const signingInput = `${encodedHeader}.${encodedPayload}`;
64
+ const signer = crypto.createSign("SHA256");
65
+ signer.update(signingInput);
66
+ const signature = signer.sign(privateKey);
67
+ return `${signingInput}.${base64UrlEncode(signature)}`;
47
68
  }
48
69
  function verify(token, publicKey) {
49
70
  try {
50
71
  const parts = token.split(".");
51
72
  if (parts.length !== 3) return null;
52
- const [encodedHeader, encodedPayload, signature] = parts;
53
- const verify2 = crypto.createVerify("SHA256");
54
- verify2.update(`${encodedHeader}.${encodedPayload}`);
55
- const isValid = verify2.verify(publicKey, base64UrlDecode(signature));
73
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
74
+ const verifier = crypto.createVerify("SHA256");
75
+ verifier.update(`${encodedHeader}.${encodedPayload}`);
76
+ const isValid = verifier.verify(publicKey, base64UrlDecode(encodedSignature));
56
77
  if (!isValid) return null;
57
78
  const payload = JSON.parse(decodeBase64Url(encodedPayload));
58
- if (payload.exp && payload.exp < Math.floor(Date.now() / 1e3)) return null;
79
+ const now = Math.floor(Date.now() / 1e3);
80
+ if (payload.exp !== void 0 && payload.exp < now) return null;
59
81
  return payload;
60
82
  } catch {
61
83
  return null;
62
84
  }
63
85
  }
64
- function signEncrypted(payload, privateKey, options = {}) {
65
- return sign(payload, privateKey, options);
86
+ function signEncrypted(payload, privateKey, encryptionSecret, options = {}) {
87
+ const encrypted = encryptPayload(JSON.stringify(payload), encryptionSecret);
88
+ return `sprx_${sign({ enc: encrypted }, privateKey, options).slice(2)}`;
66
89
  }
67
- function verifyEncrypted(token, publicKey) {
68
- return verify(token, publicKey);
90
+ function verifyEncrypted(token, publicKey, encryptionSecret) {
91
+ if (!token.startsWith("sprx_")) return null;
92
+ const verified = verify(`ey${token.slice(5)}`, publicKey);
93
+ if (!verified?.enc || typeof verified.enc !== "string") return null;
94
+ try {
95
+ return JSON.parse(decryptPayload(verified.enc, encryptionSecret));
96
+ } catch {
97
+ return null;
98
+ }
69
99
  }
70
100
  function createTokenPair(payload, privateKey, options = {}) {
71
101
  const accessToken = sign(payload, privateKey, options);
72
- const refreshPayload = { ...payload, type: "refresh" };
73
- const refreshToken = sign(refreshPayload, privateKey, { ...options, expiresIn: "7d" });
102
+ const refreshToken = sign(
103
+ { sub: payload.sub ?? payload.id, type: "refresh" },
104
+ privateKey,
105
+ { expiresIn: "7d", issuer: options.issuer }
106
+ );
74
107
  return { accessToken, refreshToken };
75
108
  }
76
- function verifyTokenPair(token, publicKey) {
77
- const [accessToken, refreshToken] = token.split(".");
109
+ function verifyTokenPair(accessToken, refreshToken, publicKey) {
78
110
  return {
79
111
  accessToken: verify(accessToken, publicKey),
80
112
  refreshToken: verify(refreshToken, publicKey)
@@ -83,12 +115,10 @@ function verifyTokenPair(token, publicKey) {
83
115
  function getJwtFromEnv() {
84
116
  let publicKey = process.env.JWT_PUBLIC_KEY;
85
117
  let privateKey = process.env.JWT_PRIVATE_KEY;
86
- if (!publicKey || !privateKey) {
87
- throw new Error("JWT keys not configured. Run 'npm run generate:keys' and add the keys to your .env file.");
88
- }
89
- publicKey = publicKey.replace(/^['"]|['"]$/g, "").replace(/\\n/g, "\n");
90
- privateKey = privateKey.replace(/^['"]|['"]$/g, "").replace(/\\n/g, "\n");
91
- return { publicKey, privateKey };
118
+ let encryptionSecret = process.env.JWT_ENCRYPTION_SECRET;
119
+ if (!publicKey || !privateKey || !encryptionSecret) throw new Error("JWT keys not configured. Run 'npm run generate:keys' and add the keys to your .env file.");
120
+ const normalize = (k) => k.replace(/^['"]|['"]$/g, "").replace(/\\n/g, "\n");
121
+ return { publicKey: normalize(publicKey), privateKey: normalize(privateKey), encryptionSecret };
92
122
  }
93
123
  exports.createTokenPair = createTokenPair;
94
124
  exports.generateKeyPair = generateKeyPair;
package/dist/esm/cli.js CHANGED
@@ -69,14 +69,16 @@ switch (command) {
69
69
  runCommand("node dist/index.js", { NODE_ENV: "production" });
70
70
  break;
71
71
  case "generate-keys":
72
- const { publicKey, privateKey } = crypto.generateKeyPairSync("ec", {
73
- namedCurve: "prime256v1",
72
+ const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
73
+ modulusLength: 4096,
74
74
  publicKeyEncoding: { type: "spki", format: "pem" },
75
75
  privateKeyEncoding: { type: "pkcs8", format: "pem" }
76
76
  });
77
+ const jwtSecret = crypto.randomBytes(32).toString("hex");
77
78
  console.log("\nšŸ”‘ Generating JWT keys...\n");
78
79
  console.log("JWT_PUBLIC_KEY='" + publicKey + "'");
79
80
  console.log("\nJWT_PRIVATE_KEY='" + privateKey + "'");
81
+ console.log("\nJWT_ENCRYPTION_SECRET=" + jwtSecret);
80
82
  console.log("\nšŸ“ Add these to your .env file (use single quotes for multiline values):\n");
81
83
  process.exit(0);
82
84
  break;
package/dist/esm/index.js CHANGED
@@ -181,7 +181,7 @@ class Sprint {
181
181
  name,
182
182
  filePath
183
183
  });
184
- console.log(`[Sprint] Loaded middleware: ${name} (priority: ${config.priority ?? 100})`);
184
+ if (isVerbose) console.log(`[Sprint] Loaded middleware: ${name} (priority: ${config.priority ?? 100})`);
185
185
  }
186
186
  } catch (err) {
187
187
  console.warn(`[Sprint] Failed to load middleware ${filePath}:`, err);
@@ -223,10 +223,10 @@ class Sprint {
223
223
  const routeMiddlewares = this.getMiddlewaresForRoute(routePath);
224
224
  if (routeMiddlewares.length > 0) {
225
225
  this.app.use(finalRoute, ...routeMiddlewares, router);
226
- console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
226
+ if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath} (with ${routeMiddlewares.length} middleware(s))`);
227
227
  } else {
228
228
  this.app.use(finalRoute, router);
229
- console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
229
+ if (isVerbose) console.log(`[Sprint] Loaded route: ${finalRoute} -> ${filePath}`);
230
230
  }
231
231
  }
232
232
  } catch (err) {
@@ -246,7 +246,7 @@ class Sprint {
246
246
  try {
247
247
  const moduleUrl = pathToFileURL(filePath).href;
248
248
  await import(moduleUrl);
249
- console.log(`[Sprint] Loaded cronjob: ${file.replace(/\.(ts|js)$/, "")}`);
249
+ if (isVerbose) console.log(`[Sprint] Loaded cronjob: ${file.replace(/\.(ts|js)$/, "")}`);
250
250
  } catch (err) {
251
251
  console.warn(`[Sprint] Failed to load cronjob ${filePath}:`, err);
252
252
  }
@@ -1,78 +1,110 @@
1
1
  import crypto__default from "crypto";
2
+ const base64UrlEncode = (buffer) => buffer.toString("base64url");
3
+ const base64UrlDecode = (str) => Buffer.from(str, "base64url");
4
+ const decodeBase64Url = (str) => Buffer.from(str, "base64url").toString("utf8");
2
5
  const ALGORITHM = "ES256";
3
- function base64UrlEncode(buffer) {
4
- return buffer.toString("base64url");
5
- }
6
- function base64UrlDecode(str) {
7
- const pad = str.length % 4;
8
- const padded = pad ? str + "=".repeat(4 - pad) : str;
9
- return Buffer.from(padded.replace(/-/g, "+").replace(/_/g, "/"), "base64");
10
- }
11
- function decodeBase64Url(str) {
12
- return Buffer.from(str, "base64url").toString();
13
- }
14
- function generateKeyPair(algorithm = ALGORITHM) {
6
+ const ENCRYPTION_ALGORITHM = "aes-256-gcm";
7
+ function generateKeyPair() {
15
8
  const { publicKey, privateKey } = crypto__default.generateKeyPairSync("ec", {
16
9
  namedCurve: "prime256v1",
17
- publicKeyEncoding: {
18
- type: "spki",
19
- format: "pem"
20
- },
21
- privateKeyEncoding: {
22
- type: "pkcs8",
23
- format: "pem"
24
- }
10
+ publicKeyEncoding: { type: "spki", format: "pem" },
11
+ privateKeyEncoding: { type: "pkcs8", format: "pem" }
25
12
  });
26
13
  return { publicKey, privateKey };
27
14
  }
28
- function sign(payload, privateKey, options = {}) {
29
- const header = { alg: ALGORITHM, typ: "JWT" };
15
+ function parseExpiry(expiresIn) {
16
+ if (typeof expiresIn === "number") return expiresIn;
17
+ const units = {
18
+ s: 1,
19
+ m: 60,
20
+ h: 3600,
21
+ d: 86400,
22
+ w: 604800
23
+ };
24
+ const match = expiresIn.match(/^(\d+)([smhdw])$/);
25
+ if (!match) throw new Error(`Invalid expiresIn format: "${expiresIn}". Use e.g. "15m", "2h", "7d".`);
26
+ return parseInt(match[1]) * units[match[2]];
27
+ }
28
+ function buildClaims(payload, options) {
30
29
  const now = Math.floor(Date.now() / 1e3);
31
- const claims = { ...payload };
32
- if (options.expiresIn) {
33
- claims.exp = typeof options.expiresIn === "number" ? now + options.expiresIn : now + parseInt(options.expiresIn);
34
- }
30
+ const claims = { ...payload, iat: now };
31
+ if (options.expiresIn !== void 0) claims.exp = now + parseExpiry(options.expiresIn);
35
32
  if (options.issuer) claims.iss = options.issuer;
36
33
  if (options.subject) claims.sub = options.subject;
37
34
  if (options.audience) claims.aud = options.audience;
38
- claims.iat = now;
35
+ return claims;
36
+ }
37
+ function encryptPayload(plaintext, secret) {
38
+ const key = crypto__default.scryptSync(secret, "sprint-jwt-salt", 32);
39
+ const iv = crypto__default.randomBytes(12);
40
+ const cipher = crypto__default.createCipheriv(ENCRYPTION_ALGORITHM, key, iv);
41
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
42
+ const tag = cipher.getAuthTag();
43
+ return base64UrlEncode(Buffer.concat([iv, tag, encrypted]));
44
+ }
45
+ function decryptPayload(data, secret) {
46
+ const key = crypto__default.scryptSync(secret, "sprint-jwt-salt", 32);
47
+ const buf = base64UrlDecode(data);
48
+ if (buf.length < 28) throw new Error("Invalid encrypted payload.");
49
+ const iv = buf.subarray(0, 12);
50
+ const tag = buf.subarray(12, 28);
51
+ const ciphertext = buf.subarray(28);
52
+ const decipher = crypto__default.createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);
53
+ decipher.setAuthTag(tag);
54
+ return decipher.update(ciphertext).toString("utf8") + decipher.final("utf8");
55
+ }
56
+ function sign(payload, privateKey, options = {}) {
57
+ const header = { alg: ALGORITHM, typ: "JWT" };
58
+ const claims = buildClaims(payload, options);
39
59
  const encodedHeader = base64UrlEncode(Buffer.from(JSON.stringify(header)));
40
60
  const encodedPayload = base64UrlEncode(Buffer.from(JSON.stringify(claims)));
41
- const sign2 = crypto__default.createSign("SHA256");
42
- sign2.update(`${encodedHeader}.${encodedPayload}`);
43
- const signature = sign2.sign(privateKey);
44
- return `${encodedHeader}.${encodedPayload}.${base64UrlEncode(signature)}`;
61
+ const signingInput = `${encodedHeader}.${encodedPayload}`;
62
+ const signer = crypto__default.createSign("SHA256");
63
+ signer.update(signingInput);
64
+ const signature = signer.sign(privateKey);
65
+ return `${signingInput}.${base64UrlEncode(signature)}`;
45
66
  }
46
67
  function verify(token, publicKey) {
47
68
  try {
48
69
  const parts = token.split(".");
49
70
  if (parts.length !== 3) return null;
50
- const [encodedHeader, encodedPayload, signature] = parts;
51
- const verify2 = crypto__default.createVerify("SHA256");
52
- verify2.update(`${encodedHeader}.${encodedPayload}`);
53
- const isValid = verify2.verify(publicKey, base64UrlDecode(signature));
71
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
72
+ const verifier = crypto__default.createVerify("SHA256");
73
+ verifier.update(`${encodedHeader}.${encodedPayload}`);
74
+ const isValid = verifier.verify(publicKey, base64UrlDecode(encodedSignature));
54
75
  if (!isValid) return null;
55
76
  const payload = JSON.parse(decodeBase64Url(encodedPayload));
56
- if (payload.exp && payload.exp < Math.floor(Date.now() / 1e3)) return null;
77
+ const now = Math.floor(Date.now() / 1e3);
78
+ if (payload.exp !== void 0 && payload.exp < now) return null;
57
79
  return payload;
58
80
  } catch {
59
81
  return null;
60
82
  }
61
83
  }
62
- function signEncrypted(payload, privateKey, options = {}) {
63
- return sign(payload, privateKey, options);
84
+ function signEncrypted(payload, privateKey, encryptionSecret, options = {}) {
85
+ const encrypted = encryptPayload(JSON.stringify(payload), encryptionSecret);
86
+ return `sprx_${sign({ enc: encrypted }, privateKey, options).slice(2)}`;
64
87
  }
65
- function verifyEncrypted(token, publicKey) {
66
- return verify(token, publicKey);
88
+ function verifyEncrypted(token, publicKey, encryptionSecret) {
89
+ if (!token.startsWith("sprx_")) return null;
90
+ const verified = verify(`ey${token.slice(5)}`, publicKey);
91
+ if (!verified?.enc || typeof verified.enc !== "string") return null;
92
+ try {
93
+ return JSON.parse(decryptPayload(verified.enc, encryptionSecret));
94
+ } catch {
95
+ return null;
96
+ }
67
97
  }
68
98
  function createTokenPair(payload, privateKey, options = {}) {
69
99
  const accessToken = sign(payload, privateKey, options);
70
- const refreshPayload = { ...payload, type: "refresh" };
71
- const refreshToken = sign(refreshPayload, privateKey, { ...options, expiresIn: "7d" });
100
+ const refreshToken = sign(
101
+ { sub: payload.sub ?? payload.id, type: "refresh" },
102
+ privateKey,
103
+ { expiresIn: "7d", issuer: options.issuer }
104
+ );
72
105
  return { accessToken, refreshToken };
73
106
  }
74
- function verifyTokenPair(token, publicKey) {
75
- const [accessToken, refreshToken] = token.split(".");
107
+ function verifyTokenPair(accessToken, refreshToken, publicKey) {
76
108
  return {
77
109
  accessToken: verify(accessToken, publicKey),
78
110
  refreshToken: verify(refreshToken, publicKey)
@@ -81,12 +113,10 @@ function verifyTokenPair(token, publicKey) {
81
113
  function getJwtFromEnv() {
82
114
  let publicKey = process.env.JWT_PUBLIC_KEY;
83
115
  let privateKey = process.env.JWT_PRIVATE_KEY;
84
- if (!publicKey || !privateKey) {
85
- throw new Error("JWT keys not configured. Run 'npm run generate:keys' and add the keys to your .env file.");
86
- }
87
- publicKey = publicKey.replace(/^['"]|['"]$/g, "").replace(/\\n/g, "\n");
88
- privateKey = privateKey.replace(/^['"]|['"]$/g, "").replace(/\\n/g, "\n");
89
- return { publicKey, privateKey };
116
+ let encryptionSecret = process.env.JWT_ENCRYPTION_SECRET;
117
+ if (!publicKey || !privateKey || !encryptionSecret) throw new Error("JWT keys not configured. Run 'npm run generate:keys' and add the keys to your .env file.");
118
+ const normalize = (k) => k.replace(/^['"]|['"]$/g, "").replace(/\\n/g, "\n");
119
+ return { publicKey: normalize(publicKey), privateKey: normalize(privateKey), encryptionSecret };
90
120
  }
91
121
  export {
92
122
  createTokenPair,
@@ -2,7 +2,7 @@ import { Sprint } from './sprint';
2
2
  export { Sprint, isDevelopment, isProduction } from './sprint';
3
3
  export { defineMiddleware } from './middleware';
4
4
  export { __filename, __dirname } from './utils';
5
- export type { Handler, AsyncRequestHandler, MiddlewareConfig, SprintOptions, LoadedMiddleware, AuthorizationSource, SprintRequest } from './types';
5
+ export type { Handler, AsyncRequestHandler, MiddlewareConfig, SprintOptions, LoadedMiddleware, AuthorizationSource, SprintRequest, SprintResponse } from './types';
6
6
  export declare const Router: () => import('express-serve-static-core').Router;
7
7
  export default Sprint;
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGhD,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGnJ,eAAO,MAAM,MAAM,kDAAwB,CAAC;AAG5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGhD,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGnK,eAAO,MAAM,MAAM,kDAAwB,CAAC;AAG5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,eAAe,MAAM,CAAC"}
@@ -11,21 +11,22 @@ export interface KeyPair {
11
11
  publicKey: string;
12
12
  privateKey: string;
13
13
  }
14
- export declare function generateKeyPair(algorithm?: string): KeyPair;
14
+ export declare function generateKeyPair(): KeyPair;
15
15
  export declare function sign(payload: JWTPayload, privateKey: string, options?: JWTOptions): string;
16
16
  export declare function verify(token: string, publicKey: string): JWTPayload | null;
17
- export declare function signEncrypted(payload: JWTPayload, privateKey: string, options?: JWTOptions): string;
18
- export declare function verifyEncrypted(token: string, publicKey: string): JWTPayload | null;
17
+ export declare function signEncrypted(payload: JWTPayload, privateKey: string, encryptionSecret: string, options?: JWTOptions): string;
18
+ export declare function verifyEncrypted(token: string, publicKey: string, encryptionSecret: string): JWTPayload | null;
19
19
  export declare function createTokenPair(payload: JWTPayload, privateKey: string, options?: JWTOptions): {
20
20
  accessToken: string;
21
21
  refreshToken: string;
22
22
  };
23
- export declare function verifyTokenPair(token: string, publicKey: string): {
23
+ export declare function verifyTokenPair(accessToken: string, refreshToken: string, publicKey: string): {
24
24
  accessToken: JWTPayload | null;
25
25
  refreshToken: JWTPayload | null;
26
26
  };
27
27
  export declare function getJwtFromEnv(): {
28
28
  publicKey: string;
29
29
  privateKey: string;
30
+ encryptionSecret: string;
30
31
  };
31
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/jwt/index.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,UAAU;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,OAAO;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,SAAS,GAAE,MAAkB,GAAG,OAAO,CActE;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAqB9F;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAqB1E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAEvG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEnF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAMhJ;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,UAAU,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,UAAU,GAAG,IAAI,CAAA;CAAE,CAMrI;AAED,wBAAgB,aAAa,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAYzE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/jwt/index.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,UAAU;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,OAAO;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,eAAe,IAAI,OAAO,CAOzC;AAwDD,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAa9F;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAoB1E;AAMD,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,MAAM,CAGjI;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAU7G;AAID,wBAAgB,eAAe,CAC3B,OAAO,EAAE,UAAU,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,UAAe,GACzB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAQ/C;AAED,wBAAgB,eAAe,CAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAClB;IAAE,WAAW,EAAE,UAAU,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,UAAU,GAAG,IAAI,CAAA;CAAE,CAKrE;AAID,wBAAgB,aAAa,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CASnG"}
@@ -0,0 +1,4 @@
1
+ export declare const base64UrlEncode: (buffer: Buffer) => string;
2
+ export declare const base64UrlDecode: (str: string) => Buffer;
3
+ export declare const decodeBase64Url: (str: string) => string;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/utils/index.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,KAAG,MAAsC,CAAC;AACxF,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,MAAuC,CAAC;AACtF,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,MAAwD,CAAC"}
@@ -5,6 +5,7 @@ export type AuthorizationSource = `query:${string}` | `headers:${string}`;
5
5
  export interface SprintRequest {
6
6
  getAuthorization: (sources?: AuthorizationSource | AuthorizationSource[]) => string | undefined;
7
7
  }
8
+ export type SprintResponse = Response;
8
9
  declare global {
9
10
  namespace Express {
10
11
  interface Request {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE1E,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAEpG,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,GAAG,CAAC;AAE/E,MAAM,MAAM,mBAAmB,GACzB,SAAS,MAAM,EAAE,GACjB,WAAW,MAAM,EAAE,CAAC;AAE1B,MAAM,WAAW,aAAa;IAC1B,gBAAgB,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC;CACnG;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,OAAO,CAAC;QACd,UAAU,OAAO;YACb,MAAM,EAAE,aAAa,CAAC;SACzB;KACJ;CACJ;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,oFAAoF;IACpF,OAAO,EAAE,cAAc,GAAG,mBAAmB,GAAG,CAAC,cAAc,GAAG,mBAAmB,CAAC,EAAE,CAAC;IACzF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE1E,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAEpG,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,GAAG,CAAC;AAE/E,MAAM,MAAM,mBAAmB,GACzB,SAAS,MAAM,EAAE,GACjB,WAAW,MAAM,EAAE,CAAC;AAE1B,MAAM,WAAW,aAAa;IAC1B,gBAAgB,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC;CACnG;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;AAEtC,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,OAAO,CAAC;QACd,UAAU,OAAO;YACb,MAAM,EAAE,aAAa,CAAC;SACzB;KACJ;CACJ;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,oFAAoF;IACpF,OAAO,EAAE,cAAc,GAAG,mBAAmB,GAAG,CAAC,cAAc,GAAG,mBAAmB,CAAC,EAAE,CAAC;IACzF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprint-es",
3
- "version": "0.0.44",
3
+ "version": "0.0.46",
4
4
  "description": "Sprint - Quickly API",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -42,6 +42,11 @@
42
42
  "types": "./dist/types/modules/jwt/index.d.ts",
43
43
  "require": "./dist/cjs/modules/jwt/index.cjs",
44
44
  "import": "./dist/esm/modules/jwt/index.js"
45
+ },
46
+ "./utils": {
47
+ "types": "./dist/types/modules/utils/index.d.ts",
48
+ "require": "./dist/cjs/modules/utils/index.cjs",
49
+ "import": "./dist/esm/modules/utils/index.js"
45
50
  }
46
51
  },
47
52
  "files": [