@uploadista/server 0.0.3

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.
Files changed (91) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-check.log +34 -0
  3. package/LICENSE +21 -0
  4. package/README.md +503 -0
  5. package/dist/auth/cache.d.ts +87 -0
  6. package/dist/auth/cache.d.ts.map +1 -0
  7. package/dist/auth/cache.js +121 -0
  8. package/dist/auth/cache.test.d.ts +2 -0
  9. package/dist/auth/cache.test.d.ts.map +1 -0
  10. package/dist/auth/cache.test.js +209 -0
  11. package/dist/auth/get-auth-credentials.d.ts +73 -0
  12. package/dist/auth/get-auth-credentials.d.ts.map +1 -0
  13. package/dist/auth/get-auth-credentials.js +55 -0
  14. package/dist/auth/index.d.ts +2 -0
  15. package/dist/auth/index.d.ts.map +1 -0
  16. package/dist/auth/index.js +1 -0
  17. package/dist/auth/jwt/index.d.ts +38 -0
  18. package/dist/auth/jwt/index.d.ts.map +1 -0
  19. package/dist/auth/jwt/index.js +36 -0
  20. package/dist/auth/jwt/types.d.ts +77 -0
  21. package/dist/auth/jwt/types.d.ts.map +1 -0
  22. package/dist/auth/jwt/types.js +1 -0
  23. package/dist/auth/jwt/validate.d.ts +58 -0
  24. package/dist/auth/jwt/validate.d.ts.map +1 -0
  25. package/dist/auth/jwt/validate.js +226 -0
  26. package/dist/auth/jwt/validate.test.d.ts +2 -0
  27. package/dist/auth/jwt/validate.test.d.ts.map +1 -0
  28. package/dist/auth/jwt/validate.test.js +492 -0
  29. package/dist/auth/service.d.ts +63 -0
  30. package/dist/auth/service.d.ts.map +1 -0
  31. package/dist/auth/service.js +43 -0
  32. package/dist/auth/service.test.d.ts +2 -0
  33. package/dist/auth/service.test.d.ts.map +1 -0
  34. package/dist/auth/service.test.js +195 -0
  35. package/dist/auth/types.d.ts +38 -0
  36. package/dist/auth/types.d.ts.map +1 -0
  37. package/dist/auth/types.js +1 -0
  38. package/dist/cache.d.ts +87 -0
  39. package/dist/cache.d.ts.map +1 -0
  40. package/dist/cache.js +121 -0
  41. package/dist/cache.test.d.ts +2 -0
  42. package/dist/cache.test.d.ts.map +1 -0
  43. package/dist/cache.test.js +209 -0
  44. package/dist/cloudflare-config.d.ts +72 -0
  45. package/dist/cloudflare-config.d.ts.map +1 -0
  46. package/dist/cloudflare-config.js +67 -0
  47. package/dist/error-types.d.ts +138 -0
  48. package/dist/error-types.d.ts.map +1 -0
  49. package/dist/error-types.js +155 -0
  50. package/dist/hono-adapter.d.ts +48 -0
  51. package/dist/hono-adapter.d.ts.map +1 -0
  52. package/dist/hono-adapter.js +58 -0
  53. package/dist/http-utils.d.ts +148 -0
  54. package/dist/http-utils.d.ts.map +1 -0
  55. package/dist/http-utils.js +233 -0
  56. package/dist/index.d.ts +9 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +8 -0
  59. package/dist/layer-utils.d.ts +121 -0
  60. package/dist/layer-utils.d.ts.map +1 -0
  61. package/dist/layer-utils.js +80 -0
  62. package/dist/metrics/service.d.ts +26 -0
  63. package/dist/metrics/service.d.ts.map +1 -0
  64. package/dist/metrics/service.js +20 -0
  65. package/dist/plugins-typing.d.ts +11 -0
  66. package/dist/plugins-typing.d.ts.map +1 -0
  67. package/dist/plugins-typing.js +1 -0
  68. package/dist/service.d.ts +63 -0
  69. package/dist/service.d.ts.map +1 -0
  70. package/dist/service.js +43 -0
  71. package/dist/service.test.d.ts +2 -0
  72. package/dist/service.test.d.ts.map +1 -0
  73. package/dist/service.test.js +195 -0
  74. package/dist/types.d.ts +38 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +1 -0
  77. package/package.json +47 -0
  78. package/src/auth/get-auth-credentials.ts +97 -0
  79. package/src/auth/index.ts +1 -0
  80. package/src/cache.test.ts +306 -0
  81. package/src/cache.ts +204 -0
  82. package/src/error-types.ts +172 -0
  83. package/src/http-utils.ts +264 -0
  84. package/src/index.ts +8 -0
  85. package/src/layer-utils.ts +184 -0
  86. package/src/plugins-typing.ts +57 -0
  87. package/src/service.test.ts +275 -0
  88. package/src/service.ts +78 -0
  89. package/src/types.ts +40 -0
  90. package/tsconfig.json +13 -0
  91. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,58 @@
1
+ import type { AuthContext } from "../types";
2
+ import type { JwtValidationConfig, JwtValidationResult } from "./types";
3
+ /**
4
+ * Validates a JWT token and returns the validation result with claims.
5
+ *
6
+ * This function verifies:
7
+ * - Token signature using the provided secret/public key
8
+ * - Token expiry (with clock tolerance)
9
+ * - Issuer claim (if configured)
10
+ * - Audience claim (if configured)
11
+ * - Required subject (sub) claim presence
12
+ *
13
+ * @param token - The JWT token string to validate
14
+ * @param config - Validation configuration (secret, issuer, audience, etc.)
15
+ * @returns JwtValidationResult with success status and claims or error
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const result = await validateJwtToken(token, {
20
+ * secret: 'my-secret-key',
21
+ * issuer: 'https://auth.example.com',
22
+ * audience: 'uploadista-api',
23
+ * clockTolerance: 60,
24
+ * });
25
+ *
26
+ * if (result.success) {
27
+ * console.log('User ID:', result.userId);
28
+ * console.log('Claims:', result.claims);
29
+ * } else {
30
+ * console.error('Validation failed:', result.error);
31
+ * }
32
+ * ```
33
+ */
34
+ export declare function validateJwtToken(token: string, config: JwtValidationConfig): Promise<JwtValidationResult>;
35
+ /**
36
+ * Extracts AuthContext from a validated JWT token.
37
+ * This is a convenience function that combines validation and extraction.
38
+ *
39
+ * @param token - The JWT token string to validate and extract from
40
+ * @param config - Validation configuration
41
+ * @returns AuthContext if validation succeeds, null otherwise
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const authContext = await extractAuthContextFromJwt(token, {
46
+ * secret: process.env.JWT_SECRET,
47
+ * issuer: 'https://auth.example.com',
48
+ * });
49
+ *
50
+ * if (authContext) {
51
+ * console.log('Authenticated user:', authContext.userId);
52
+ * } else {
53
+ * console.log('Invalid token');
54
+ * }
55
+ * ```
56
+ */
57
+ export declare function extractAuthContextFromJwt(token: string, config: JwtValidationConfig): Promise<AuthContext | null>;
58
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/auth/jwt/validate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAmF9B;AA6ED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmC7B"}
@@ -0,0 +1,226 @@
1
+ import { jwtVerify } from "jose";
2
+ /**
3
+ * Validates a JWT token and returns the validation result with claims.
4
+ *
5
+ * This function verifies:
6
+ * - Token signature using the provided secret/public key
7
+ * - Token expiry (with clock tolerance)
8
+ * - Issuer claim (if configured)
9
+ * - Audience claim (if configured)
10
+ * - Required subject (sub) claim presence
11
+ *
12
+ * @param token - The JWT token string to validate
13
+ * @param config - Validation configuration (secret, issuer, audience, etc.)
14
+ * @returns JwtValidationResult with success status and claims or error
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const result = await validateJwtToken(token, {
19
+ * secret: 'my-secret-key',
20
+ * issuer: 'https://auth.example.com',
21
+ * audience: 'uploadista-api',
22
+ * clockTolerance: 60,
23
+ * });
24
+ *
25
+ * if (result.success) {
26
+ * console.log('User ID:', result.userId);
27
+ * console.log('Claims:', result.claims);
28
+ * } else {
29
+ * console.error('Validation failed:', result.error);
30
+ * }
31
+ * ```
32
+ */
33
+ export async function validateJwtToken(token, config) {
34
+ try {
35
+ // Prepare secret/key for validation
36
+ let secret;
37
+ if (typeof config.secret === "string") {
38
+ secret = new TextEncoder().encode(config.secret);
39
+ }
40
+ else {
41
+ secret = config.secret;
42
+ }
43
+ // Prepare verification options
44
+ const options = {
45
+ clockTolerance: config.clockTolerance ?? 60, // Default 1 minute tolerance
46
+ };
47
+ if (config.issuer) {
48
+ options.issuer = config.issuer;
49
+ }
50
+ if (config.audience) {
51
+ options.audience = config.audience;
52
+ }
53
+ if (config.algorithms && config.algorithms.length > 0) {
54
+ options.algorithms = config.algorithms;
55
+ }
56
+ // Verify the JWT
57
+ let verifyResult;
58
+ try {
59
+ verifyResult = await jwtVerify(token, secret, options);
60
+ }
61
+ catch (error) {
62
+ return handleJwtVerifyError(error, config);
63
+ }
64
+ const { payload, protectedHeader } = verifyResult;
65
+ // Validate algorithm if specified
66
+ if (config.algorithms &&
67
+ config.algorithms.length > 0 &&
68
+ !config.algorithms.includes(protectedHeader.alg)) {
69
+ return {
70
+ success: false,
71
+ error: {
72
+ type: "INVALID_ALGORITHM",
73
+ message: `Invalid algorithm: expected one of [${config.algorithms.join(", ")}], got ${protectedHeader.alg}`,
74
+ expected: config.algorithms,
75
+ actual: protectedHeader.alg,
76
+ },
77
+ };
78
+ }
79
+ // Extract userId from sub claim
80
+ const userId = payload.sub;
81
+ if (!userId) {
82
+ return {
83
+ success: false,
84
+ error: {
85
+ type: "MISSING_SUBJECT",
86
+ message: "Token is missing required 'sub' claim. Cannot extract user ID.",
87
+ },
88
+ };
89
+ }
90
+ // Return success with claims
91
+ return {
92
+ success: true,
93
+ claims: payload,
94
+ userId,
95
+ };
96
+ }
97
+ catch (error) {
98
+ // Catch-all for unexpected errors
99
+ return {
100
+ success: false,
101
+ error: {
102
+ type: "INVALID_TOKEN",
103
+ message: error instanceof Error ? error.message : "Unknown error occurred",
104
+ },
105
+ };
106
+ }
107
+ }
108
+ /**
109
+ * Handles errors from jose's jwtVerify and converts them to our error format
110
+ */
111
+ function handleJwtVerifyError(error, config) {
112
+ if (!(error instanceof Error)) {
113
+ return {
114
+ success: false,
115
+ error: {
116
+ type: "INVALID_TOKEN",
117
+ message: "Unknown validation error occurred",
118
+ },
119
+ };
120
+ }
121
+ const message = error.message.toLowerCase();
122
+ // Check for specific error types - order matters!
123
+ // Check issuer/audience before expired since "exp" might match "expected"
124
+ if (message.includes("issuer") || message.includes('"iss"') || message.includes("'iss'")) {
125
+ return {
126
+ success: false,
127
+ error: {
128
+ type: "INVALID_ISSUER",
129
+ message: "Token issuer does not match expected value",
130
+ expected: config.issuer ?? "",
131
+ actual: "unknown",
132
+ },
133
+ };
134
+ }
135
+ if (message.includes("audience") || message.includes('"aud"') || message.includes("'aud'")) {
136
+ return {
137
+ success: false,
138
+ error: {
139
+ type: "INVALID_AUDIENCE",
140
+ message: "Token audience does not match expected value",
141
+ expected: config.audience ?? "",
142
+ actual: "unknown",
143
+ },
144
+ };
145
+ }
146
+ if (message.includes("expired") || (message.includes("exp") && !message.includes("unexpected"))) {
147
+ return {
148
+ success: false,
149
+ error: {
150
+ type: "EXPIRED",
151
+ message: "Token has expired",
152
+ },
153
+ };
154
+ }
155
+ if (message.includes("signature")) {
156
+ return {
157
+ success: false,
158
+ error: {
159
+ type: "INVALID_SIGNATURE",
160
+ message: "Invalid token signature",
161
+ },
162
+ };
163
+ }
164
+ // Default to invalid token error
165
+ return {
166
+ success: false,
167
+ error: {
168
+ type: "INVALID_TOKEN",
169
+ message: error.message,
170
+ },
171
+ };
172
+ }
173
+ /**
174
+ * Extracts AuthContext from a validated JWT token.
175
+ * This is a convenience function that combines validation and extraction.
176
+ *
177
+ * @param token - The JWT token string to validate and extract from
178
+ * @param config - Validation configuration
179
+ * @returns AuthContext if validation succeeds, null otherwise
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * const authContext = await extractAuthContextFromJwt(token, {
184
+ * secret: process.env.JWT_SECRET,
185
+ * issuer: 'https://auth.example.com',
186
+ * });
187
+ *
188
+ * if (authContext) {
189
+ * console.log('Authenticated user:', authContext.userId);
190
+ * } else {
191
+ * console.log('Invalid token');
192
+ * }
193
+ * ```
194
+ */
195
+ export async function extractAuthContextFromJwt(token, config) {
196
+ const result = await validateJwtToken(token, config);
197
+ if (!result.success) {
198
+ return null;
199
+ }
200
+ // Extract permissions from claims (if present)
201
+ const permissions = Array.isArray(result.claims.permissions)
202
+ ? result.claims.permissions
203
+ : undefined;
204
+ // Extract metadata (all claims except standard JWT claims)
205
+ const standardClaims = new Set([
206
+ "iss",
207
+ "sub",
208
+ "aud",
209
+ "exp",
210
+ "nbf",
211
+ "iat",
212
+ "jti",
213
+ "permissions",
214
+ ]);
215
+ const metadata = {};
216
+ for (const [key, value] of Object.entries(result.claims)) {
217
+ if (!standardClaims.has(key)) {
218
+ metadata[key] = value;
219
+ }
220
+ }
221
+ return {
222
+ userId: result.userId,
223
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
224
+ permissions,
225
+ };
226
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../../../src/auth/jwt/validate.test.ts"],"names":[],"mappings":""}