veryfront 0.1.217 → 0.1.218
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/esm/deno.d.ts +1 -2
- package/esm/deno.js +6 -4
- package/esm/src/extensions/interfaces/auth-provider.d.ts +30 -3
- package/esm/src/extensions/interfaces/auth-provider.d.ts.map +1 -1
- package/esm/src/extensions/interfaces/index.d.ts +2 -1
- package/esm/src/extensions/interfaces/index.d.ts.map +1 -1
- package/esm/src/extensions/interfaces/token-cache-store.d.ts +56 -0
- package/esm/src/extensions/interfaces/token-cache-store.d.ts.map +1 -0
- package/esm/src/extensions/interfaces/token-cache-store.js +12 -0
- package/esm/src/extensions/recommendations.d.ts.map +1 -1
- package/esm/src/extensions/recommendations.js +1 -0
- package/esm/src/proxy/cache/index.d.ts +1 -1
- package/esm/src/proxy/cache/index.d.ts.map +1 -1
- package/esm/src/proxy/cache/index.js +25 -15
- package/esm/src/proxy/cache/tracing-cache.d.ts +31 -0
- package/esm/src/proxy/cache/tracing-cache.d.ts.map +1 -0
- package/esm/src/proxy/cache/tracing-cache.js +44 -0
- package/esm/src/proxy/cache/types.d.ts +1 -1
- package/esm/src/proxy/cache/types.js +1 -1
- package/esm/src/proxy/handler.d.ts +7 -0
- package/esm/src/proxy/handler.d.ts.map +1 -1
- package/esm/src/proxy/handler.js +50 -29
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +66 -35
- package/src/deno.js +6 -4
- package/src/src/extensions/interfaces/auth-provider.ts +35 -3
- package/src/src/extensions/interfaces/index.ts +10 -1
- package/src/src/extensions/interfaces/token-cache-store.ts +58 -0
- package/src/src/extensions/recommendations.ts +1 -0
- package/src/src/proxy/cache/index.ts +27 -15
- package/src/src/proxy/cache/tracing-cache.ts +77 -0
- package/src/src/proxy/cache/types.ts +1 -1
- package/src/src/proxy/handler.ts +57 -31
- package/src/src/utils/version-constant.ts +1 -1
- package/esm/src/proxy/cache/redis-cache.d.ts +0 -25
- package/esm/src/proxy/cache/redis-cache.d.ts.map +0 -1
- package/esm/src/proxy/cache/redis-cache.js +0 -219
- package/src/src/proxy/cache/redis-cache.ts +0 -255
package/esm/deno.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ declare namespace _default {
|
|
|
3
3
|
let version: string;
|
|
4
4
|
let license: string;
|
|
5
5
|
let nodeModulesDir: string;
|
|
6
|
+
let workspace: string[];
|
|
6
7
|
let exclude: string[];
|
|
7
8
|
let exports: {
|
|
8
9
|
".": string;
|
|
@@ -250,9 +251,7 @@ declare namespace _default {
|
|
|
250
251
|
"tailwindcss/plugin": string;
|
|
251
252
|
"tailwindcss/defaultTheme": string;
|
|
252
253
|
"tailwindcss/colors": string;
|
|
253
|
-
redis: string;
|
|
254
254
|
pg: string;
|
|
255
|
-
jose: string;
|
|
256
255
|
"@opentelemetry/api": string;
|
|
257
256
|
"@opentelemetry/core": string;
|
|
258
257
|
"@opentelemetry/context-async-hooks": string;
|
package/esm/deno.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.218",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"nodeModulesDir": "auto",
|
|
6
|
+
"workspace": [
|
|
7
|
+
"./extensions/ext-redis"
|
|
8
|
+
],
|
|
6
9
|
"exclude": [
|
|
7
10
|
"npm/",
|
|
8
11
|
"dist/",
|
|
@@ -12,7 +15,8 @@ export default {
|
|
|
12
15
|
"data/",
|
|
13
16
|
".deno_cache/",
|
|
14
17
|
"cli/templates/files/",
|
|
15
|
-
"cli/templates/integrations/"
|
|
18
|
+
"cli/templates/integrations/",
|
|
19
|
+
"extensions/"
|
|
16
20
|
],
|
|
17
21
|
"exports": {
|
|
18
22
|
".": "./src/index.ts",
|
|
@@ -260,9 +264,7 @@ export default {
|
|
|
260
264
|
"tailwindcss/plugin": "https://esm.sh/tailwindcss@4.2.2/plugin",
|
|
261
265
|
"tailwindcss/defaultTheme": "https://esm.sh/tailwindcss@4.2.2/defaultTheme",
|
|
262
266
|
"tailwindcss/colors": "https://esm.sh/tailwindcss@4.2.2/colors",
|
|
263
|
-
"redis": "npm:redis@5.11.0",
|
|
264
267
|
"pg": "npm:pg@8.13.1",
|
|
265
|
-
"jose": "npm:jose@5.9.6",
|
|
266
268
|
"@opentelemetry/api": "npm:@opentelemetry/api@1.9.0",
|
|
267
269
|
"@opentelemetry/core": "npm:@opentelemetry/core@2.6.0",
|
|
268
270
|
"@opentelemetry/context-async-hooks": "npm:@opentelemetry/context-async-hooks@2.6.0",
|
|
@@ -32,18 +32,45 @@ export interface VerifyOptions {
|
|
|
32
32
|
/** Additional implementation-specific options. */
|
|
33
33
|
[key: string]: unknown;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* The parsed, unverified header of a JWT.
|
|
37
|
+
*
|
|
38
|
+
* Returned by {@link AuthProvider.decode}. `alg` is the signing algorithm
|
|
39
|
+
* advertised by the token (e.g. `"HS256"`, `"RS256"`); additional fields
|
|
40
|
+
* such as `kid` or `typ` may be present.
|
|
41
|
+
*/
|
|
42
|
+
export interface TokenHeader {
|
|
43
|
+
/** Signing algorithm advertised by the token header. */
|
|
44
|
+
alg?: string;
|
|
45
|
+
/** Additional header fields. */
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
35
48
|
/**
|
|
36
49
|
* AuthProvider contract interface.
|
|
37
50
|
*
|
|
38
51
|
* Implementations sign, verify, and decode authentication tokens
|
|
39
|
-
* (e.g. JWTs) for request authentication
|
|
52
|
+
* (e.g. JWTs) for request authentication, and verify third-party tokens
|
|
53
|
+
* against a remote JWKS.
|
|
40
54
|
*/
|
|
41
55
|
export interface AuthProvider {
|
|
42
56
|
/** Sign a payload into a token string. */
|
|
43
57
|
sign(payload: TokenPayload, options?: SignOptions): Promise<string>;
|
|
44
58
|
/** Verify a token and return its decoded payload. Throws on invalid tokens. */
|
|
45
59
|
verify(token: string, options?: VerifyOptions): Promise<TokenPayload>;
|
|
46
|
-
/**
|
|
47
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Verify a token against a remote JSON Web Key Set.
|
|
62
|
+
*
|
|
63
|
+
* Fetches (and caches) the JWKS at `jwksUrl`, then verifies the token's
|
|
64
|
+
* signature and claims. Throws on invalid tokens, unreachable JWKS, or
|
|
65
|
+
* `kid`/algorithm mismatch.
|
|
66
|
+
*/
|
|
67
|
+
verifyWithJwks(token: string, jwksUrl: string, options?: VerifyOptions): Promise<TokenPayload>;
|
|
68
|
+
/**
|
|
69
|
+
* Decode a token's protected header without verifying its signature.
|
|
70
|
+
*
|
|
71
|
+
* Returns `undefined` on malformed input. Useful for inspecting `alg`
|
|
72
|
+
* before choosing a verification strategy.
|
|
73
|
+
*/
|
|
74
|
+
decode(token: string): TokenHeader | undefined;
|
|
48
75
|
}
|
|
49
76
|
//# sourceMappingURL=auth-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../../../../src/src/extensions/interfaces/auth-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,kDAAkD;IAClD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED
|
|
1
|
+
{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../../../../src/src/extensions/interfaces/auth-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,mCAAmC;AACnC,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,kDAAkD;IAClD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,+EAA+E;IAC/E,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACtE;;;;;;OAMG;IACH,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;CAChD"}
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
import "../../../_dnt.polyfills.js";
|
|
9
9
|
export type { BundleOptions, BundleOutput, Bundler, BundleResult, BundlerPlugin, BundlerPluginBuild, TransformOptions, TransformResult, } from "./bundler.js";
|
|
10
10
|
export type { CacheStore } from "./cache-store.js";
|
|
11
|
+
export type { TokenCacheEntry, TokenCacheStats, TokenCacheStore } from "./token-cache-store.js";
|
|
11
12
|
export type { CSSProcessOptions, CSSProcessor, CSSProcessResult } from "./css-processor.js";
|
|
12
13
|
export type { ContentTransformer, ContentTransformOptions, ContentTransformResult, } from "./content-transformer.js";
|
|
13
14
|
export type { DatabaseClient, QueryResult } from "./database-client.js";
|
|
14
|
-
export type { AuthProvider, SignOptions, TokenPayload, VerifyOptions } from "./auth-provider.js";
|
|
15
|
+
export type { AuthProvider, SignOptions, TokenHeader, TokenPayload, VerifyOptions, } from "./auth-provider.js";
|
|
15
16
|
export type { SpanData, TracingExporter } from "./tracing-exporter.js";
|
|
16
17
|
export type { AIModelProvider, ChatMessage, CompletionOptions, CompletionResult, ContentPart, StreamChunk, ToolDefinition, } from "./ai-model-provider.js";
|
|
17
18
|
export type { EmbeddingOptions, EmbeddingProvider, EmbeddingResult } from "./embedding-provider.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/extensions/interfaces/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,4BAA4B,CAAC;AAEpC,YAAY,EACV,aAAa,EACb,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG5F,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxE,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/extensions/interfaces/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,4BAA4B,CAAC;AAEpC,YAAY,EACV,aAAa,EACb,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,GAChB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGhG,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG5F,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxE,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,GACd,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGvE,YAAY,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,cAAc,GACf,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAGpG,YAAY,EACV,OAAO,EACP,UAAU,EACV,eAAe,EACf,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,MAAM,EACN,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract interface for OAuth-token-style cache stores used by the proxy.
|
|
3
|
+
*
|
|
4
|
+
* This contract is richer than the generic `CacheStore` — it adds scan-by-prefix,
|
|
5
|
+
* bulk read, and usage statistics primitives that the proxy's token cache needs.
|
|
6
|
+
* Simpler key-value consumers should use `CacheStore` instead.
|
|
7
|
+
*
|
|
8
|
+
* Default implementation: `@veryfront/ext-redis`.
|
|
9
|
+
*
|
|
10
|
+
* @module extensions/interfaces/token-cache-store
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A cache entry stored by `TokenCacheStore`.
|
|
14
|
+
*
|
|
15
|
+
* The proxy persists OAuth tokens keyed by request metadata; this entry shape
|
|
16
|
+
* mirrors what the proxy has historically stored.
|
|
17
|
+
*/
|
|
18
|
+
export interface TokenCacheEntry {
|
|
19
|
+
token: string;
|
|
20
|
+
/** Unix timestamp in milliseconds. */
|
|
21
|
+
expiresAt: number;
|
|
22
|
+
scope: "preview" | "production";
|
|
23
|
+
projectSlug?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Aggregate usage statistics for a `TokenCacheStore`.
|
|
27
|
+
*/
|
|
28
|
+
export interface TokenCacheStats {
|
|
29
|
+
hits: number;
|
|
30
|
+
misses: number;
|
|
31
|
+
size: number;
|
|
32
|
+
type: "memory" | "redis";
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* TokenCacheStore contract interface.
|
|
36
|
+
*
|
|
37
|
+
* Implementations provide TTL-aware token caching, plus scan and stats
|
|
38
|
+
* primitives that generic key-value caches do not require.
|
|
39
|
+
*/
|
|
40
|
+
export interface TokenCacheStore {
|
|
41
|
+
/** Retrieve a cached entry by key. Returns `null` on miss or expiry. */
|
|
42
|
+
get(key: string): Promise<TokenCacheEntry | null>;
|
|
43
|
+
/** Store an entry. TTL is derived from `entry.expiresAt`. */
|
|
44
|
+
set(key: string, entry: TokenCacheEntry): Promise<void>;
|
|
45
|
+
/** Delete a cached entry. No-op if the key does not exist. */
|
|
46
|
+
delete(key: string): Promise<void>;
|
|
47
|
+
/** Remove every entry owned by this store. */
|
|
48
|
+
clear(): Promise<void>;
|
|
49
|
+
/** Check whether a non-expired entry exists for the given key. */
|
|
50
|
+
has(key: string): Promise<boolean>;
|
|
51
|
+
/** Return current hit/miss/size statistics. */
|
|
52
|
+
stats(): Promise<TokenCacheStats>;
|
|
53
|
+
/** Close connections and release resources. */
|
|
54
|
+
close(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=token-cache-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-cache-store.d.ts","sourceRoot":"","sources":["../../../../src/src/extensions/interfaces/token-cache-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,GAAG,YAAY,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAClD,6DAA6D;IAC7D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,8DAA8D;IAC9D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,8CAA8C;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kEAAkE;IAClE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,+CAA+C;IAC/C,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IAClC,+CAA+C;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract interface for OAuth-token-style cache stores used by the proxy.
|
|
3
|
+
*
|
|
4
|
+
* This contract is richer than the generic `CacheStore` — it adds scan-by-prefix,
|
|
5
|
+
* bulk read, and usage statistics primitives that the proxy's token cache needs.
|
|
6
|
+
* Simpler key-value consumers should use `CacheStore` instead.
|
|
7
|
+
*
|
|
8
|
+
* Default implementation: `@veryfront/ext-redis`.
|
|
9
|
+
*
|
|
10
|
+
* @module extensions/interfaces/token-cache-store
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommendations.d.ts","sourceRoot":"","sources":["../../../src/src/extensions/recommendations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"recommendations.d.ts","sourceRoot":"","sources":["../../../src/src/extensions/recommendations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1E"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const recommendations = new Map([
|
|
7
7
|
["Bundler", "@veryfront/ext-esbuild"],
|
|
8
8
|
["CacheStore", "@veryfront/ext-redis"],
|
|
9
|
+
["TokenCacheStore", "@veryfront/ext-redis"],
|
|
9
10
|
["CSSProcessor", "@veryfront/ext-tailwind"],
|
|
10
11
|
["ContentTransformer", "@veryfront/ext-mdx"],
|
|
11
12
|
["DatabaseClient", "@veryfront/ext-postgres"],
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export type { CacheOptions, CacheStats, MemoryCacheOptions, RedisCacheOptions, TokenCache, TokenCacheEntry, } from "./types.js";
|
|
7
7
|
export { MemoryCache } from "./memory-cache.js";
|
|
8
|
-
export { RedisCache } from "./redis-cache.js";
|
|
9
8
|
export { ResilientCache } from "./resilient-cache.js";
|
|
9
|
+
export { TracingTokenCache } from "./tracing-cache.js";
|
|
10
10
|
import type { CacheOptions, TokenCache } from "./types.js";
|
|
11
11
|
export declare function createCache(options: CacheOptions): Promise<TokenCache>;
|
|
12
12
|
export declare function createCacheFromEnv(): Promise<TokenCache>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/proxy/cache/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/proxy/cache/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAe3D,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAc5E;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,UAAU,CAAC,CA4B9D"}
|
|
@@ -4,19 +4,26 @@
|
|
|
4
4
|
* @module proxy/cache
|
|
5
5
|
*/
|
|
6
6
|
export { MemoryCache } from "./memory-cache.js";
|
|
7
|
-
export { RedisCache } from "./redis-cache.js";
|
|
8
7
|
export { ResilientCache } from "./resilient-cache.js";
|
|
8
|
+
export { TracingTokenCache } from "./tracing-cache.js";
|
|
9
9
|
import { MemoryCache } from "./memory-cache.js";
|
|
10
|
-
import { RedisCache } from "./redis-cache.js";
|
|
11
10
|
import { ResilientCache } from "./resilient-cache.js";
|
|
11
|
+
import { TracingTokenCache } from "./tracing-cache.js";
|
|
12
|
+
import { tryResolve } from "../../extensions/contracts.js";
|
|
12
13
|
import { getEnv } from "../../platform/compat/process.js";
|
|
13
14
|
import { proxyLogger } from "../logger.js";
|
|
14
15
|
import { withSpan } from "../tracing.js";
|
|
15
16
|
const logger = proxyLogger.child({ module: "cache" });
|
|
17
|
+
const MISSING_EXTENSION_INFO = "TokenCacheStore contract not provided — install @veryfront/ext-redis or scaffold extensions/ext-redis/";
|
|
16
18
|
export async function createCache(options) {
|
|
17
19
|
return withSpan("cache.create", async () => {
|
|
18
|
-
if (options.type === "redis")
|
|
19
|
-
|
|
20
|
+
if (options.type === "redis") {
|
|
21
|
+
const tokenCache = tryResolve("TokenCacheStore");
|
|
22
|
+
if (tokenCache)
|
|
23
|
+
return new TracingTokenCache(tokenCache);
|
|
24
|
+
logger.info(MISSING_EXTENSION_INFO);
|
|
25
|
+
return new MemoryCache(undefined);
|
|
26
|
+
}
|
|
20
27
|
return new MemoryCache(options.options);
|
|
21
28
|
}, { "cache.type": options.type });
|
|
22
29
|
}
|
|
@@ -25,18 +32,21 @@ export async function createCacheFromEnv() {
|
|
|
25
32
|
return withSpan("cache.createFromEnv", async () => {
|
|
26
33
|
if (cacheType !== "redis")
|
|
27
34
|
return new MemoryCache();
|
|
28
|
-
const
|
|
29
|
-
if (!
|
|
30
|
-
|
|
35
|
+
const tokenCache = tryResolve("TokenCacheStore");
|
|
36
|
+
if (!tokenCache) {
|
|
37
|
+
// Redis was requested via config/env but no extension registered the
|
|
38
|
+
// TokenCacheStore contract. Log an info (misconfiguration, not error),
|
|
39
|
+
// then fall back to an in-memory cache so the proxy still boots.
|
|
40
|
+
logger.info(MISSING_EXTENSION_INFO);
|
|
31
41
|
return new MemoryCache();
|
|
32
42
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return new ResilientCache(
|
|
43
|
+
// Wrap the extension-provided cache with a memory fallback so a Redis
|
|
44
|
+
// outage does not take the proxy down. TracingTokenCache sits between
|
|
45
|
+
// ResilientCache and the extension impl so spans wrap the actual
|
|
46
|
+
// primary-cache attempt (mirrors the pre-extraction RedisCache which
|
|
47
|
+
// had inner withSpan calls).
|
|
48
|
+
logger.debug("[Cache] Using TokenCacheStore extension with memory fallback (ResilientCache)");
|
|
49
|
+
const traced = new TracingTokenCache(tokenCache);
|
|
50
|
+
return new ResilientCache(traced, new MemoryCache());
|
|
41
51
|
}, { "cache.type": cacheType });
|
|
42
52
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TracingTokenCache
|
|
3
|
+
*
|
|
4
|
+
* Wraps a {@link TokenCache} implementation and emits an OpenTelemetry span
|
|
5
|
+
* around each public method. This keeps extension-provided caches (such as
|
|
6
|
+
* `@veryfront/ext-redis`) tracer-agnostic: the extension implements the
|
|
7
|
+
* contract only, and the proxy applies observability at the factory boundary.
|
|
8
|
+
*
|
|
9
|
+
* Span names default to `cache.redis.<op>` to preserve the pre-extraction
|
|
10
|
+
* behavior of the in-tree RedisCache. Callers may override via
|
|
11
|
+
* {@link TracingTokenCacheOptions.spanPrefix} when wrapping a different
|
|
12
|
+
* backend.
|
|
13
|
+
*/
|
|
14
|
+
import type { CacheStats, TokenCache, TokenCacheEntry } from "./types.js";
|
|
15
|
+
export interface TracingTokenCacheOptions {
|
|
16
|
+
/** Span name prefix, e.g. "cache.redis" produces "cache.redis.get". */
|
|
17
|
+
spanPrefix?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class TracingTokenCache implements TokenCache {
|
|
20
|
+
private readonly inner;
|
|
21
|
+
private readonly prefix;
|
|
22
|
+
constructor(inner: TokenCache, options?: TracingTokenCacheOptions);
|
|
23
|
+
get(key: string): Promise<TokenCacheEntry | null>;
|
|
24
|
+
set(key: string, entry: TokenCacheEntry): Promise<void>;
|
|
25
|
+
delete(key: string): Promise<void>;
|
|
26
|
+
clear(): Promise<void>;
|
|
27
|
+
has(key: string): Promise<boolean>;
|
|
28
|
+
stats(): Promise<CacheStats>;
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=tracing-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing-cache.d.ts","sourceRoot":"","sources":["../../../../src/src/proxy/cache/tracing-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG1E,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID,qBAAa,iBAAkB,YAAW,UAAU;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,wBAA6B;IAKrE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAQjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAQvD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQlC,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;IAI5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TracingTokenCache
|
|
3
|
+
*
|
|
4
|
+
* Wraps a {@link TokenCache} implementation and emits an OpenTelemetry span
|
|
5
|
+
* around each public method. This keeps extension-provided caches (such as
|
|
6
|
+
* `@veryfront/ext-redis`) tracer-agnostic: the extension implements the
|
|
7
|
+
* contract only, and the proxy applies observability at the factory boundary.
|
|
8
|
+
*
|
|
9
|
+
* Span names default to `cache.redis.<op>` to preserve the pre-extraction
|
|
10
|
+
* behavior of the in-tree RedisCache. Callers may override via
|
|
11
|
+
* {@link TracingTokenCacheOptions.spanPrefix} when wrapping a different
|
|
12
|
+
* backend.
|
|
13
|
+
*/
|
|
14
|
+
import { withSpan } from "../tracing.js";
|
|
15
|
+
const DEFAULT_SPAN_PREFIX = "cache.redis";
|
|
16
|
+
export class TracingTokenCache {
|
|
17
|
+
inner;
|
|
18
|
+
prefix;
|
|
19
|
+
constructor(inner, options = {}) {
|
|
20
|
+
this.inner = inner;
|
|
21
|
+
this.prefix = options.spanPrefix ?? DEFAULT_SPAN_PREFIX;
|
|
22
|
+
}
|
|
23
|
+
get(key) {
|
|
24
|
+
return withSpan(`${this.prefix}.get`, () => this.inner.get(key), { "cache.key": key });
|
|
25
|
+
}
|
|
26
|
+
set(key, entry) {
|
|
27
|
+
return withSpan(`${this.prefix}.set`, () => this.inner.set(key, entry), { "cache.key": key });
|
|
28
|
+
}
|
|
29
|
+
delete(key) {
|
|
30
|
+
return withSpan(`${this.prefix}.delete`, () => this.inner.delete(key), { "cache.key": key });
|
|
31
|
+
}
|
|
32
|
+
clear() {
|
|
33
|
+
return withSpan(`${this.prefix}.clear`, () => this.inner.clear());
|
|
34
|
+
}
|
|
35
|
+
has(key) {
|
|
36
|
+
return withSpan(`${this.prefix}.has`, () => this.inner.has(key), { "cache.key": key });
|
|
37
|
+
}
|
|
38
|
+
stats() {
|
|
39
|
+
return withSpan(`${this.prefix}.stats`, () => this.inner.stats());
|
|
40
|
+
}
|
|
41
|
+
close() {
|
|
42
|
+
return withSpan(`${this.prefix}.close`, () => this.inner.close());
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Token Cache Interface
|
|
3
3
|
*
|
|
4
4
|
* Abstraction for storing OAuth tokens with TTL support.
|
|
5
|
-
* Implementations: MemoryCache, RedisCache
|
|
5
|
+
* Implementations: MemoryCache (built-in), RedisCache (via @veryfront/ext-redis)
|
|
6
6
|
*/
|
|
7
7
|
export interface TokenCacheEntry {
|
|
8
8
|
token: string;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { type ParsedDomain } from "../server/utils/domain-parser.js";
|
|
2
2
|
import type { TokenCache } from "./cache/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Reset the cached AuthProvider. Intended for tests that `register()` a mock
|
|
5
|
+
* after the handler module has been imported.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function __resetCachedAuthProviderForTests(): void;
|
|
3
10
|
export declare const INTERNAL_PROXY_HEADERS: readonly ["x-token", "x-project-slug", "x-environment", "x-environment-id", "x-content-source-id", "x-forwarded-host", "x-project-path", "x-project-id", "x-release-id", "x-branch-id", "x-branch-name"];
|
|
4
11
|
export interface ProxyConfig {
|
|
5
12
|
apiBaseUrl: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,kCAAkC,CAAC;AACzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/src/proxy/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,kCAAkC,CAAC;AACzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAuCnD;;;;;GAKG;AACH,wBAAgB,iCAAiC,IAAI,IAAI,CAExD;AAED,eAAO,MAAM,sBAAsB,0MAYzB,CAAC;AAqHX,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,SAAS,GAAG,YAAY,CAAC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC9D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC7D,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC7D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAgGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB;0BA4Q1B,OAAO,KAAG,OAAO,CAAC,YAAY,CAAC;0BAmQ/B,OAAO,KAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;;;;;;;;0BApd7C,MAAM,EAAE;;EAgfpC;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEjE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAwB7E"}
|
package/esm/src/proxy/handler.js
CHANGED
|
@@ -5,7 +5,42 @@ import { cwd, getEnv } from "../platform/compat/process.js";
|
|
|
5
5
|
import { join } from "../platform/compat/path/index.js";
|
|
6
6
|
import { injectContext, ProxySpanNames, withSpan } from "./tracing.js";
|
|
7
7
|
import { computeContentSourceId } from "../cache/keys.js";
|
|
8
|
-
import {
|
|
8
|
+
import { resolve as resolveContract } from "../extensions/contracts.js";
|
|
9
|
+
/**
|
|
10
|
+
* Cache the resolved AuthProvider at module scope so the proxy does not pay
|
|
11
|
+
* the registry lookup on every request. The cache is cleared implicitly when
|
|
12
|
+
* `ExtensionLoader.teardownAll()` clears the registry — the next call
|
|
13
|
+
* re-resolves (or surfaces the "install ext-jwt" hint if the extension was
|
|
14
|
+
* removed).
|
|
15
|
+
*/
|
|
16
|
+
let cachedAuthProvider;
|
|
17
|
+
function getAuthProvider() {
|
|
18
|
+
if (cachedAuthProvider)
|
|
19
|
+
return cachedAuthProvider;
|
|
20
|
+
try {
|
|
21
|
+
cachedAuthProvider = resolveContract("AuthProvider");
|
|
22
|
+
return cachedAuthProvider;
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
// resolve() already throws with a helpful "Recommended: @veryfront/ext-jwt"
|
|
26
|
+
// message, but the proxy is a load-bearing code path — append a concrete
|
|
27
|
+
// remediation hint that names the project-root extension directory so
|
|
28
|
+
// the user knows exactly what's missing.
|
|
29
|
+
const base = err instanceof Error ? err.message : String(err);
|
|
30
|
+
throw new Error(`${base}\nTo enable JWT verification in the proxy, install ext-jwt ` +
|
|
31
|
+
`(scaffold with \`deno task cli extension init ext-jwt\` or add the ` +
|
|
32
|
+
`npm package @veryfront/ext-jwt).`, { cause: err });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Reset the cached AuthProvider. Intended for tests that `register()` a mock
|
|
37
|
+
* after the handler module has been imported.
|
|
38
|
+
*
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
export function __resetCachedAuthProviderForTests() {
|
|
42
|
+
cachedAuthProvider = undefined;
|
|
43
|
+
}
|
|
9
44
|
export const INTERNAL_PROXY_HEADERS = [
|
|
10
45
|
"x-token",
|
|
11
46
|
"x-project-slug",
|
|
@@ -40,21 +75,10 @@ function isSignedInternalControlPlaneRequest(req) {
|
|
|
40
75
|
}
|
|
41
76
|
return !!req.headers.get("x-token");
|
|
42
77
|
}
|
|
43
|
-
|
|
44
|
-
function getApiJwks(apiBaseUrl, logger) {
|
|
78
|
+
function resolveApiJwksUrl(apiBaseUrl, logger) {
|
|
45
79
|
try {
|
|
46
80
|
const normalizedBaseUrl = apiBaseUrl.endsWith("/") ? apiBaseUrl : `${apiBaseUrl}/`;
|
|
47
|
-
|
|
48
|
-
const cacheKey = jwksUrl.toString();
|
|
49
|
-
// Lazily initialize and cache JWKS in a single, idempotent step to avoid
|
|
50
|
-
// unsynchronized read/then-write on the shared Map across concurrent calls.
|
|
51
|
-
let jwks = remoteJwksByUrl.get(cacheKey);
|
|
52
|
-
if (!jwks) {
|
|
53
|
-
const created = createRemoteJWKSet(jwksUrl);
|
|
54
|
-
remoteJwksByUrl.set(cacheKey, created);
|
|
55
|
-
jwks = created;
|
|
56
|
-
}
|
|
57
|
-
return jwks;
|
|
81
|
+
return new URL(".well-known/jwks.json", normalizedBaseUrl).toString();
|
|
58
82
|
}
|
|
59
83
|
catch (error) {
|
|
60
84
|
logger?.error("Invalid API base URL for JWKS lookup", error, {
|
|
@@ -130,22 +154,19 @@ function isMissingCustomDomainProjectError(error) {
|
|
|
130
154
|
return /project not found for domain/i.test(message);
|
|
131
155
|
}
|
|
132
156
|
async function extractUserIdFromToken(token, apiBaseUrl, log) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
catch (error) {
|
|
138
|
-
log?.debug("Failed to decode JWT header", {
|
|
139
|
-
error: error instanceof Error ? error.message : String(error),
|
|
140
|
-
});
|
|
157
|
+
const auth = getAuthProvider();
|
|
158
|
+
const header = auth.decode(token);
|
|
159
|
+
if (!header) {
|
|
160
|
+
log?.debug("Failed to decode JWT header");
|
|
141
161
|
return undefined;
|
|
142
162
|
}
|
|
163
|
+
const algorithm = header.alg;
|
|
143
164
|
if (algorithm === "RS256") {
|
|
144
|
-
const
|
|
145
|
-
if (!
|
|
165
|
+
const jwksUrl = resolveApiJwksUrl(apiBaseUrl, log);
|
|
166
|
+
if (!jwksUrl)
|
|
146
167
|
return undefined;
|
|
147
168
|
try {
|
|
148
|
-
const
|
|
169
|
+
const payload = await auth.verifyWithJwks(token, jwksUrl, {
|
|
149
170
|
algorithms: ["RS256"],
|
|
150
171
|
});
|
|
151
172
|
return payload.userId;
|
|
@@ -167,10 +188,10 @@ async function extractUserIdFromToken(token, apiBaseUrl, log) {
|
|
|
167
188
|
return undefined;
|
|
168
189
|
}
|
|
169
190
|
try {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
});
|
|
191
|
+
// ext-jwt reads JWT_SECRET from the environment when no `secret` was
|
|
192
|
+
// passed to the extension factory; the explicit env check above is kept
|
|
193
|
+
// so callers can warn once before we attempt verification.
|
|
194
|
+
const payload = await auth.verify(token, { algorithms: ["HS256"] });
|
|
174
195
|
return payload.userId;
|
|
175
196
|
}
|
|
176
197
|
catch (error) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.218";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|