@capxul/sdk 1.0.0-alpha.11 → 1.0.0-alpha.12
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/InMemoryAuthCacheAdapter-EBzKEJmQ.mjs +113 -0
- package/dist/InMemoryAuthCacheAdapter-EBzKEJmQ.mjs.map +1 -0
- package/dist/index.d.mts +335 -459
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +583 -1467
- package/dist/index.mjs.map +1 -1
- package/dist/node/index.d.mts +3 -3
- package/dist/node/index.mjs +2 -1
- package/dist/node/index.mjs.map +1 -1
- package/dist/ports/safe-deployment.d.mts +1 -1
- package/dist/{safe-deployment-D3k9yndM.d.mts → safe-deployment-DMGB1kEL.d.mts} +5 -4
- package/dist/safe-deployment-DMGB1kEL.d.mts.map +1 -0
- package/dist/{signer-D9fUJp8o.d.mts → signer-DEMJbpJ2.d.mts} +8 -7
- package/dist/signer-DEMJbpJ2.d.mts.map +1 -0
- package/package.json +8 -8
- package/dist/InMemoryAuthCacheAdapter-v5W-XB5M.mjs +0 -457
- package/dist/InMemoryAuthCacheAdapter-v5W-XB5M.mjs.map +0 -1
- package/dist/index-CTXgQ_xR.d.mts +0 -158
- package/dist/index-CTXgQ_xR.d.mts.map +0 -1
- package/dist/safe-deployment-D3k9yndM.d.mts.map +0 -1
- package/dist/signer-D9fUJp8o.d.mts.map +0 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { toAuthUserId, toEmail, toEpochMs, toEpochSeconds, toJwtToken, toSessionToken } from "@capxul/types";
|
|
2
|
+
import { Context, Data, Effect, Layer } from "effect";
|
|
3
|
+
//#region src/ports/auth-cache.ts
|
|
4
|
+
var AuthCacheError = class extends Data.TaggedError("AuthCacheError") {};
|
|
5
|
+
var AuthCachePortTag = class extends Context.Tag("@capxul/sdk/ports/AuthCachePort")() {};
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/adapters/auth-cache/serialization.ts
|
|
8
|
+
function parseAuthSession(raw) {
|
|
9
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
10
|
+
const candidate = raw;
|
|
11
|
+
try {
|
|
12
|
+
return {
|
|
13
|
+
authUserId: toAuthUserId(candidate.authUserId),
|
|
14
|
+
email: toEmail(candidate.email),
|
|
15
|
+
token: toSessionToken(candidate.token),
|
|
16
|
+
expiresAt: toEpochMs(candidate.expiresAt)
|
|
17
|
+
};
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function parseCachedJwt(raw) {
|
|
23
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
24
|
+
const candidate = raw;
|
|
25
|
+
try {
|
|
26
|
+
return {
|
|
27
|
+
token: toJwtToken(candidate.token),
|
|
28
|
+
expEpochSeconds: toEpochSeconds(candidate.expEpochSeconds)
|
|
29
|
+
};
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/adapters/auth-cache/BrowserAuthCacheAdapter.ts
|
|
36
|
+
const SESSION_KEY = "capxul.session";
|
|
37
|
+
const JWT_KEY = "capxul.jwt";
|
|
38
|
+
var BrowserAuthCacheAdapter = class {
|
|
39
|
+
storage;
|
|
40
|
+
constructor(storage) {
|
|
41
|
+
this.storage = storage;
|
|
42
|
+
}
|
|
43
|
+
getSession = authCacheTry("getSession", () => {
|
|
44
|
+
const raw = this.storage.getItem(SESSION_KEY);
|
|
45
|
+
if (raw === null) return null;
|
|
46
|
+
try {
|
|
47
|
+
return parseAuthSession(JSON.parse(raw));
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
setSession = (session) => authCacheTry("setSession", () => {
|
|
53
|
+
this.storage.setItem(SESSION_KEY, JSON.stringify(session));
|
|
54
|
+
});
|
|
55
|
+
clearSession = authCacheTry("clearSession", () => {
|
|
56
|
+
this.storage.removeItem(SESSION_KEY);
|
|
57
|
+
});
|
|
58
|
+
getJwt = authCacheTry("getJwt", () => {
|
|
59
|
+
const raw = this.storage.getItem(JWT_KEY);
|
|
60
|
+
if (raw === null) return null;
|
|
61
|
+
try {
|
|
62
|
+
return parseCachedJwt(JSON.parse(raw));
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
setJwt = (jwt) => authCacheTry("setJwt", () => {
|
|
68
|
+
this.storage.setItem(JWT_KEY, JSON.stringify(jwt));
|
|
69
|
+
});
|
|
70
|
+
clearJwt = authCacheTry("clearJwt", () => {
|
|
71
|
+
this.storage.removeItem(JWT_KEY);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
function toAuthCacheError(operation, cause) {
|
|
75
|
+
return new AuthCacheError({
|
|
76
|
+
operation,
|
|
77
|
+
cause
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function authCacheTry(operation, run) {
|
|
81
|
+
return Effect.try({
|
|
82
|
+
try: run,
|
|
83
|
+
catch: (cause) => toAuthCacheError(operation, cause)
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/adapters/auth-cache/InMemoryAuthCacheAdapter.ts
|
|
88
|
+
var InMemoryAuthCacheAdapter = class {
|
|
89
|
+
session = null;
|
|
90
|
+
jwt = null;
|
|
91
|
+
getSession = Effect.sync(() => this.session);
|
|
92
|
+
setSession = (session) => Effect.sync(() => {
|
|
93
|
+
this.session = session;
|
|
94
|
+
});
|
|
95
|
+
clearSession = Effect.sync(() => {
|
|
96
|
+
this.session = null;
|
|
97
|
+
});
|
|
98
|
+
getJwt = Effect.sync(() => this.jwt);
|
|
99
|
+
setJwt = (jwt) => Effect.sync(() => {
|
|
100
|
+
this.jwt = jwt;
|
|
101
|
+
});
|
|
102
|
+
clearJwt = Effect.sync(() => {
|
|
103
|
+
this.jwt = null;
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
Layer.effect(AuthCachePortTag, Effect.sync(() => new InMemoryAuthCacheAdapter()).pipe(Effect.mapError((cause) => new AuthCacheError({
|
|
107
|
+
operation: "initialize",
|
|
108
|
+
cause
|
|
109
|
+
}))));
|
|
110
|
+
//#endregion
|
|
111
|
+
export { AuthCacheError as a, parseCachedJwt as i, BrowserAuthCacheAdapter as n, AuthCachePortTag as o, parseAuthSession as r, InMemoryAuthCacheAdapter as t };
|
|
112
|
+
|
|
113
|
+
//# sourceMappingURL=InMemoryAuthCacheAdapter-EBzKEJmQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InMemoryAuthCacheAdapter-EBzKEJmQ.mjs","names":[],"sources":["../src/ports/auth-cache.ts","../src/adapters/auth-cache/serialization.ts","../src/adapters/auth-cache/BrowserAuthCacheAdapter.ts","../src/adapters/auth-cache/InMemoryAuthCacheAdapter.ts"],"sourcesContent":["import { Context, Data, Effect } from \"effect\";\nimport type { AuthSession, EpochSeconds, JwtToken } from \"@capxul/types\";\n\n/**\n * AuthCachePort (TA4) — replaces `SessionStoragePort` in the rebuild slice's\n * consumer-facing wiring. Stores the user-snapshot Session AND the cached\n * Convex JWT (W7 bridge endpoint). The two slots are independent so a session\n * refresh doesn't invalidate the JWT and vice versa.\n *\n * Three adapters (TA7):\n * - `BrowserAuthCacheAdapter` — backed by `localStorage`\n * - `FileSystemAuthCacheAdapter` — mode-0600 JSON file in `~/.config/capxul/`\n * - `InMemoryAuthCacheAdapter` — for tests\n *\n * `SessionStoragePort` was retired by the Stage 4 rebuild; session and JWT\n * persistence now share this cache boundary.\n */\nexport interface AuthCachePort {\n readonly getSession: Effect.Effect<AuthSession | null, AuthCacheError>;\n readonly setSession: (session: AuthSession) => Effect.Effect<void, AuthCacheError>;\n readonly clearSession: Effect.Effect<void, AuthCacheError>;\n\n /**\n * JWT cache for the `/api/auth/convex/token` bridge endpoint (W7).\n * Stored separately from the session so a session refresh doesn't\n * invalidate cached JWT.\n */\n readonly getJwt: Effect.Effect<CachedJwt | null, AuthCacheError>;\n readonly setJwt: (jwt: CachedJwt) => Effect.Effect<void, AuthCacheError>;\n readonly clearJwt: Effect.Effect<void, AuthCacheError>;\n}\n\n/**\n * Cached Convex JWT shape (TA4). `expEpochSeconds` is decoded from the JWT's\n * `exp` claim at fetch time so the `tokenProvider` cache eviction logic can\n * proactively refresh at `exp - 30s` per TA3.\n */\nexport interface CachedJwt {\n readonly token: JwtToken;\n readonly expEpochSeconds: EpochSeconds;\n}\n\nexport class AuthCacheError extends Data.TaggedError(\"AuthCacheError\")<{\n readonly operation: string;\n readonly cause: unknown;\n}> {}\n\nexport class AuthCachePortTag extends Context.Tag(\"@capxul/sdk/ports/AuthCachePort\")<\n AuthCachePortTag,\n AuthCachePort\n>() {}\n","import {\n toAuthUserId,\n toEmail,\n toEpochMs,\n toEpochSeconds,\n toJwtToken,\n toSessionToken,\n type AuthSession,\n} from \"@capxul/types\";\n\nimport type { CachedJwt } from \"../../ports/auth-cache\";\n\nexport function parseAuthSession(raw: unknown): AuthSession | null {\n if (typeof raw !== \"object\" || raw === null) return null;\n const candidate = raw as {\n readonly authUserId?: unknown;\n readonly email?: unknown;\n readonly token?: unknown;\n readonly expiresAt?: unknown;\n };\n\n try {\n return {\n authUserId: toAuthUserId(candidate.authUserId),\n email: toEmail(candidate.email),\n token: toSessionToken(candidate.token),\n expiresAt: toEpochMs(candidate.expiresAt),\n };\n } catch {\n return null;\n }\n}\n\nexport function parseCachedJwt(raw: unknown): CachedJwt | null {\n if (typeof raw !== \"object\" || raw === null) return null;\n const candidate = raw as {\n readonly token?: unknown;\n readonly expEpochSeconds?: unknown;\n };\n\n try {\n return {\n token: toJwtToken(candidate.token),\n expEpochSeconds: toEpochSeconds(candidate.expEpochSeconds),\n };\n } catch {\n return null;\n }\n}\n","import { Effect, Layer } from \"effect\";\nimport type { AuthSession } from \"@capxul/types\";\n\nimport {\n AuthCacheError,\n AuthCachePortTag,\n type AuthCachePort,\n type CachedJwt,\n} from \"../../ports/auth-cache\";\nimport { parseAuthSession, parseCachedJwt } from \"./serialization\";\n\nexport interface BrowserStorageShape {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nconst SESSION_KEY = \"capxul.session\";\nconst JWT_KEY = \"capxul.jwt\";\n\nexport class BrowserAuthCacheAdapter implements AuthCachePort {\n private readonly storage: BrowserStorageShape;\n\n constructor(storage: BrowserStorageShape) {\n this.storage = storage;\n }\n\n readonly getSession = authCacheTry(\"getSession\", () => {\n const raw = this.storage.getItem(SESSION_KEY);\n if (raw === null) return null;\n try {\n return parseAuthSession(JSON.parse(raw));\n } catch {\n return null;\n }\n });\n\n readonly setSession = (session: AuthSession) =>\n authCacheTry(\"setSession\", () => {\n this.storage.setItem(SESSION_KEY, JSON.stringify(session));\n });\n\n readonly clearSession = authCacheTry(\"clearSession\", () => {\n this.storage.removeItem(SESSION_KEY);\n });\n\n readonly getJwt = authCacheTry(\"getJwt\", () => {\n const raw = this.storage.getItem(JWT_KEY);\n if (raw === null) return null;\n try {\n return parseCachedJwt(JSON.parse(raw));\n } catch {\n return null;\n }\n });\n\n readonly setJwt = (jwt: CachedJwt) =>\n authCacheTry(\"setJwt\", () => {\n this.storage.setItem(JWT_KEY, JSON.stringify(jwt));\n });\n\n readonly clearJwt = authCacheTry(\"clearJwt\", () => {\n this.storage.removeItem(JWT_KEY);\n });\n}\n\nexport function BrowserAuthCacheLayer(input: {\n readonly storage: BrowserStorageShape;\n}): Layer.Layer<AuthCachePortTag, AuthCacheError> {\n return Layer.effect(\n AuthCachePortTag,\n Effect.sync(() => new BrowserAuthCacheAdapter(input.storage)).pipe(\n Effect.mapError((cause) => toAuthCacheError(\"initialize\", cause)),\n ),\n );\n}\n\nfunction toAuthCacheError(operation: string, cause: unknown): AuthCacheError {\n return new AuthCacheError({ operation, cause });\n}\n\nfunction authCacheTry<T>(operation: string, run: () => T): Effect.Effect<T, AuthCacheError> {\n return Effect.try({\n try: run,\n catch: (cause) => toAuthCacheError(operation, cause),\n });\n}\n","import { Effect, Layer } from \"effect\";\nimport type { AuthSession } from \"@capxul/types\";\n\nimport {\n AuthCacheError,\n AuthCachePortTag,\n type AuthCachePort,\n type CachedJwt,\n} from \"../../ports/auth-cache\";\n\nexport class InMemoryAuthCacheAdapter implements AuthCachePort {\n private session: AuthSession | null = null;\n private jwt: CachedJwt | null = null;\n\n readonly getSession = Effect.sync(() => this.session);\n\n readonly setSession = (session: AuthSession) =>\n Effect.sync(() => {\n this.session = session;\n });\n\n readonly clearSession = Effect.sync(() => {\n this.session = null;\n });\n\n readonly getJwt = Effect.sync(() => this.jwt);\n\n readonly setJwt = (jwt: CachedJwt) =>\n Effect.sync(() => {\n this.jwt = jwt;\n });\n\n readonly clearJwt = Effect.sync(() => {\n this.jwt = null;\n });\n}\n\nexport const InMemoryAuthCacheLayer = Layer.effect(\n AuthCachePortTag,\n Effect.sync(() => new InMemoryAuthCacheAdapter()).pipe(\n Effect.mapError((cause) => new AuthCacheError({ operation: \"initialize\", cause })),\n ),\n);\n"],"mappings":";;;AA0CA,IAAa,iBAAb,cAAoC,KAAK,YAAY,gBAAgB,EAGlE,CAAC;AAEJ,IAAa,mBAAb,cAAsC,QAAQ,IAAI,iCAAiC,EAGjF,EAAE,CAAC;;;ACtCL,SAAgB,iBAAiB,KAAkC;CACjE,IAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM,OAAO;CACpD,MAAM,YAAY;CAOlB,IAAI;EACF,OAAO;GACL,YAAY,aAAa,UAAU,UAAU;GAC7C,OAAO,QAAQ,UAAU,KAAK;GAC9B,OAAO,eAAe,UAAU,KAAK;GACrC,WAAW,UAAU,UAAU,SAAS;EAC1C;CACF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,eAAe,KAAgC;CAC7D,IAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM,OAAO;CACpD,MAAM,YAAY;CAKlB,IAAI;EACF,OAAO;GACL,OAAO,WAAW,UAAU,KAAK;GACjC,iBAAiB,eAAe,UAAU,eAAe;EAC3D;CACF,QAAQ;EACN,OAAO;CACT;AACF;;;AC/BA,MAAM,cAAc;AACpB,MAAM,UAAU;AAEhB,IAAa,0BAAb,MAA8D;CAC5D;CAEA,YAAY,SAA8B;EACxC,KAAK,UAAU;CACjB;CAEA,aAAsB,aAAa,oBAAoB;EACrD,MAAM,MAAM,KAAK,QAAQ,QAAQ,WAAW;EAC5C,IAAI,QAAQ,MAAM,OAAO;EACzB,IAAI;GACF,OAAO,iBAAiB,KAAK,MAAM,GAAG,CAAC;EACzC,QAAQ;GACN,OAAO;EACT;CACF,CAAC;CAED,cAAuB,YACrB,aAAa,oBAAoB;EAC/B,KAAK,QAAQ,QAAQ,aAAa,KAAK,UAAU,OAAO,CAAC;CAC3D,CAAC;CAEH,eAAwB,aAAa,sBAAsB;EACzD,KAAK,QAAQ,WAAW,WAAW;CACrC,CAAC;CAED,SAAkB,aAAa,gBAAgB;EAC7C,MAAM,MAAM,KAAK,QAAQ,QAAQ,OAAO;EACxC,IAAI,QAAQ,MAAM,OAAO;EACzB,IAAI;GACF,OAAO,eAAe,KAAK,MAAM,GAAG,CAAC;EACvC,QAAQ;GACN,OAAO;EACT;CACF,CAAC;CAED,UAAmB,QACjB,aAAa,gBAAgB;EAC3B,KAAK,QAAQ,QAAQ,SAAS,KAAK,UAAU,GAAG,CAAC;CACnD,CAAC;CAEH,WAAoB,aAAa,kBAAkB;EACjD,KAAK,QAAQ,WAAW,OAAO;CACjC,CAAC;AACH;AAaA,SAAS,iBAAiB,WAAmB,OAAgC;CAC3E,OAAO,IAAI,eAAe;EAAE;EAAW;CAAM,CAAC;AAChD;AAEA,SAAS,aAAgB,WAAmB,KAAgD;CAC1F,OAAO,OAAO,IAAI;EAChB,KAAK;EACL,QAAQ,UAAU,iBAAiB,WAAW,KAAK;CACrD,CAAC;AACH;;;AC5EA,IAAa,2BAAb,MAA+D;CAC7D,UAAsC;CACtC,MAAgC;CAEhC,aAAsB,OAAO,WAAW,KAAK,OAAO;CAEpD,cAAuB,YACrB,OAAO,WAAW;EAChB,KAAK,UAAU;CACjB,CAAC;CAEH,eAAwB,OAAO,WAAW;EACxC,KAAK,UAAU;CACjB,CAAC;CAED,SAAkB,OAAO,WAAW,KAAK,GAAG;CAE5C,UAAmB,QACjB,OAAO,WAAW;EAChB,KAAK,MAAM;CACb,CAAC;CAEH,WAAoB,OAAO,WAAW;EACpC,KAAK,MAAM;CACb,CAAC;AACH;AAEsC,MAAM,OAC1C,kBACA,OAAO,WAAW,IAAI,yBAAyB,CAAC,EAAE,KAChD,OAAO,UAAU,UAAU,IAAI,eAAe;CAAE,WAAW;CAAc;AAAM,CAAC,CAAC,CACnF,CACF"}
|