@edge-base/ssr 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ <h1 align="center">@edge-base/ssr</h1>
2
+
3
+ <p align="center">
4
+ <b>Server-side auth and data helpers for EdgeBase</b><br>
5
+ Cookie-based session handling for SSR frameworks like Next.js, Remix, Nuxt, and SvelteKit
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="https://www.npmjs.com/package/@edge-base/ssr"><img src="https://img.shields.io/npm/v/%40edge-base%2Fssr?color=brightgreen" alt="npm"></a>&nbsp;
10
+ <a href="https://edgebase.fun/docs/sdks/nextjs"><img src="https://img.shields.io/badge/docs-ssr-blue" alt="Docs"></a>&nbsp;
11
+ <a href="https://github.com/edge-base/edgebase/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ Next.js · Remix · Nuxt · SvelteKit · Hono SSR
16
+ </p>
17
+
18
+ <p align="center">
19
+ <a href="https://edgebase.fun/docs/sdks/nextjs"><b>Next.js Guide</b></a> ·
20
+ <a href="https://edgebase.fun/docs/sdks/client-vs-server"><b>Client vs Server</b></a> ·
21
+ <a href="https://edgebase.fun/docs/authentication"><b>Authentication</b></a>
22
+ </p>
23
+
24
+ ---
25
+
26
+ `@edge-base/ssr` is the package you use when server-side code should run as the current signed-in user via cookies.
27
+
28
+ It is built for:
29
+
30
+ - Server Components
31
+ - Route Handlers
32
+ - loaders and actions
33
+ - SSR middleware and request handlers
34
+ - cookie-based session transfer between server and browser code
35
+
36
+ If you are writing browser code, use [`@edge-base/web`](https://www.npmjs.com/package/@edge-base/web). If you need privileged admin access from the server, use [`@edge-base/admin`](https://www.npmjs.com/package/@edge-base/admin).
37
+
38
+ > Beta: the package is already usable, but some APIs may still evolve before general availability.
39
+
40
+ ## Documentation Map
41
+
42
+ - [Next.js Integration](https://edgebase.fun/docs/sdks/nextjs)
43
+ End-to-end SSR and client setup
44
+ - [Client vs Server SDKs](https://edgebase.fun/docs/sdks/client-vs-server)
45
+ Pick the right package for each runtime
46
+ - [Authentication](https://edgebase.fun/docs/authentication)
47
+ Session, OAuth, MFA, and cookie-backed auth concepts
48
+ - [Database Client SDK](https://edgebase.fun/docs/database/client-sdk)
49
+ Query patterns that also apply to SSR DB access
50
+
51
+ ## For AI Coding Assistants
52
+
53
+ This package ships with an `llms.txt` file for AI-assisted SSR integration.
54
+
55
+ You can find it:
56
+
57
+ - after install: `node_modules/@edge-base/ssr/llms.txt`
58
+ - in the repository: [llms.txt](https://github.com/edge-base/edgebase/blob/main/packages/sdk/js/packages/ssr/llms.txt)
59
+
60
+ Use it when you want an agent to:
61
+
62
+ - set up a cookie adapter correctly
63
+ - keep browser auth code out of server components
64
+ - avoid mixing `ssr`, `web`, and `admin`
65
+ - use `getUser()`, `getSession()`, `setSession()`, and `clearSession()` correctly
66
+
67
+ ## Installation
68
+
69
+ ```bash
70
+ npm install @edge-base/ssr
71
+ ```
72
+
73
+ Most SSR apps also use the browser SDK alongside it:
74
+
75
+ ```bash
76
+ npm install @edge-base/web @edge-base/ssr
77
+ ```
78
+
79
+ ## Quick Start
80
+
81
+ ```ts
82
+ import { createServerClient } from '@edge-base/ssr';
83
+ import { cookies } from 'next/headers';
84
+
85
+ export async function createEdgeBaseServer() {
86
+ const cookieStore = await cookies();
87
+
88
+ return createServerClient(process.env.EDGEBASE_URL!, {
89
+ cookies: {
90
+ get: (name) => cookieStore.get(name)?.value,
91
+ set: (name, value, options) => {
92
+ try {
93
+ cookieStore.set(name, value, options);
94
+ } catch {
95
+ // read-only contexts such as some Server Components
96
+ }
97
+ },
98
+ delete: (name) => {
99
+ try {
100
+ cookieStore.delete(name);
101
+ } catch {
102
+ // read-only contexts such as some Server Components
103
+ }
104
+ },
105
+ },
106
+ });
107
+ }
108
+ ```
109
+
110
+ Then use it inside a server-side request flow:
111
+
112
+ ```ts
113
+ const client = await createEdgeBaseServer();
114
+ const user = client.getUser();
115
+
116
+ if (user) {
117
+ const posts = await client.db('app').table('posts').getList();
118
+ console.log(posts.items);
119
+ }
120
+ ```
121
+
122
+ ## What This Package Includes
123
+
124
+ | Surface | Included |
125
+ | --- | --- |
126
+ | Cookie-backed session tokens | Yes |
127
+ | Request-bound user context | Yes |
128
+ | `db(namespace, id?)` | Yes |
129
+ | `storage` and `functions` | Yes |
130
+ | Client-side sign-in UI | No |
131
+ | Database live subscriptions | No |
132
+ | Rooms / push / browser auth flows | No |
133
+ | Service Key admin user management | No |
134
+
135
+ ## Cookie Store Contract
136
+
137
+ `createServerClient()` expects a cookie adapter with:
138
+
139
+ - `get(name)`
140
+ - `set(name, value, options?)`
141
+ - `delete(name)`
142
+
143
+ That makes it easy to adapt to framework-specific cookie stores while keeping one EdgeBase interface.
144
+
145
+ ## OAuth And Session Transfer
146
+
147
+ On the server, `@edge-base/ssr` is especially useful for:
148
+
149
+ - reading the current session from cookies
150
+ - writing tokens after a server-side OAuth callback
151
+ - clearing session cookies during server-side sign out
152
+
153
+ Example:
154
+
155
+ ```ts
156
+ client.setSession({
157
+ accessToken,
158
+ refreshToken,
159
+ });
160
+
161
+ const session = client.getSession();
162
+ console.log(session.accessToken);
163
+ ```
164
+
165
+ ## Choose The Right Package
166
+
167
+ | Package | Use it for |
168
+ | --- | --- |
169
+ | `@edge-base/web` | Browser components and client-side auth flows |
170
+ | `@edge-base/ssr` | Server-side code acting as the current signed-in user via cookies |
171
+ | `@edge-base/admin` | Trusted server-side code with Service Key access |
172
+
173
+ ## License
174
+
175
+ MIT
@@ -0,0 +1,20 @@
1
+ /**
2
+ * CookieTokenManager — ITokenManager implementation for SSR environments.
3
+ *
4
+ * Stores access/refresh tokens in httpOnly cookies instead of localStorage.
5
+ * Works with any framework that provides a CookieStore interface
6
+ * (Next.js cookies(), Nuxt useCookie, etc.).
7
+ */
8
+ import type { ITokenManager, ITokenPair } from '@edge-base/core';
9
+ import type { CookieStore, CookieOptions } from './types.js';
10
+ export declare class CookieTokenManager implements ITokenManager {
11
+ private cookies;
12
+ private cookieOptions;
13
+ constructor(cookies: CookieStore, cookieOptions?: Partial<CookieOptions>);
14
+ getAccessToken(refreshFn?: (refreshToken: string) => Promise<ITokenPair>): Promise<string | null> | string | null;
15
+ getRefreshToken(): string | null;
16
+ invalidateAccessToken(): void;
17
+ setTokens(tokens: ITokenPair): void;
18
+ clearTokens(): void;
19
+ }
20
+ //# sourceMappingURL=cookie-token-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie-token-manager.d.ts","sourceRoot":"","sources":["../src/cookie-token-manager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAwC7D,qBAAa,kBAAmB,YAAW,aAAa;IAIpD,OAAO,CAAC,OAAO;IAHjB,OAAO,CAAC,aAAa,CAAgB;gBAG3B,OAAO,EAAE,WAAW,EAC5B,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAKxC,cAAc,CACZ,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GACxD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI;IAsBzC,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,qBAAqB,IAAI,IAAI;IAI7B,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAcnC,WAAW,IAAI,IAAI;CAIpB"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * CookieTokenManager — ITokenManager implementation for SSR environments.
3
+ *
4
+ * Stores access/refresh tokens in httpOnly cookies instead of localStorage.
5
+ * Works with any framework that provides a CookieStore interface
6
+ * (Next.js cookies(), Nuxt useCookie, etc.).
7
+ */
8
+ const ACCESS_TOKEN_COOKIE = 'eb_access_token';
9
+ const REFRESH_TOKEN_COOKIE = 'eb_refresh_token';
10
+ /** Default cookie options — secure, httpOnly, SameSite=Lax */
11
+ const DEFAULT_COOKIE_OPTIONS = {
12
+ httpOnly: true,
13
+ secure: true,
14
+ sameSite: 'lax',
15
+ path: '/',
16
+ };
17
+ function decodeJwtPayload(token) {
18
+ try {
19
+ const parts = token.split('.');
20
+ if (parts.length !== 3)
21
+ return null;
22
+ const payload = parts[1];
23
+ const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
24
+ const padded = base64 + '=='.slice(0, (4 - (base64.length % 4)) % 4);
25
+ const binary = atob(padded);
26
+ const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
27
+ return JSON.parse(new TextDecoder().decode(bytes));
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ function getTokenMaxAge(token) {
34
+ const exp = decodeJwtPayload(token)?.exp;
35
+ if (typeof exp !== 'number')
36
+ return null;
37
+ return Math.max(0, exp - Math.floor(Date.now() / 1000));
38
+ }
39
+ function isTokenExpired(token) {
40
+ const maxAge = getTokenMaxAge(token);
41
+ if (maxAge === null)
42
+ return true;
43
+ return maxAge <= 0;
44
+ }
45
+ export class CookieTokenManager {
46
+ cookies;
47
+ cookieOptions;
48
+ constructor(cookies, cookieOptions) {
49
+ this.cookies = cookies;
50
+ this.cookieOptions = { ...DEFAULT_COOKIE_OPTIONS, ...cookieOptions };
51
+ }
52
+ getAccessToken(refreshFn) {
53
+ const accessToken = this.cookies.get(ACCESS_TOKEN_COOKIE) ?? null;
54
+ // If we have an access token, return it directly
55
+ if (accessToken && !isTokenExpired(accessToken))
56
+ return accessToken;
57
+ if (accessToken) {
58
+ this.cookies.delete(ACCESS_TOKEN_COOKIE);
59
+ }
60
+ // If no access token but we have a refresh token and a refresh function,
61
+ // try to refresh
62
+ const refreshToken = this.getRefreshToken();
63
+ if (refreshToken && refreshFn) {
64
+ return refreshFn(refreshToken).then((tokens) => {
65
+ this.setTokens(tokens);
66
+ return tokens.accessToken;
67
+ });
68
+ }
69
+ return null;
70
+ }
71
+ getRefreshToken() {
72
+ return this.cookies.get(REFRESH_TOKEN_COOKIE) ?? null;
73
+ }
74
+ invalidateAccessToken() {
75
+ this.cookies.delete(ACCESS_TOKEN_COOKIE);
76
+ }
77
+ setTokens(tokens) {
78
+ const accessMaxAge = getTokenMaxAge(tokens.accessToken) ?? 900;
79
+ const refreshMaxAge = getTokenMaxAge(tokens.refreshToken) ?? 60 * 60 * 24 * 28;
80
+ this.cookies.set(ACCESS_TOKEN_COOKIE, tokens.accessToken, {
81
+ ...this.cookieOptions,
82
+ maxAge: accessMaxAge,
83
+ });
84
+ this.cookies.set(REFRESH_TOKEN_COOKIE, tokens.refreshToken, {
85
+ ...this.cookieOptions,
86
+ maxAge: refreshMaxAge,
87
+ });
88
+ }
89
+ clearTokens() {
90
+ this.cookies.delete(ACCESS_TOKEN_COOKIE);
91
+ this.cookies.delete(REFRESH_TOKEN_COOKIE);
92
+ }
93
+ }
94
+ //# sourceMappingURL=cookie-token-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie-token-manager.js","sourceRoot":"","sources":["../src/cookie-token-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @edge-base/ssr — Server-side rendering helpers for EdgeBase.
3
+ *
4
+ * Provides cookie-based token management for SSR frameworks
5
+ * (Next.js, Nuxt, SvelteKit, Remix, etc.).
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * import { createServerClient } from '@edge-base/ssr';
10
+ *
11
+ * const client = createServerClient('https://my-app.edgebase.fun', {
12
+ * cookies: {
13
+ * get: (name) => cookieStore.get(name)?.value,
14
+ * set: (name, value, options) => cookieStore.set(name, value, options),
15
+ * delete: (name) => cookieStore.delete(name),
16
+ * },
17
+ * });
18
+ *
19
+ * const user = client.getUser();
20
+ * const posts = await client.db('shared').table('posts').get();
21
+ * ```
22
+ */
23
+ export { ServerEdgeBase, type ServerUser } from './server-client.js';
24
+ export { CookieTokenManager } from './cookie-token-manager.js';
25
+ export type { CookieStore, CookieOptions, ServerClientOptions } from './types.js';
26
+ export type { ITokenPair } from '@edge-base/core';
27
+ export { EdgeBaseError } from '@edge-base/core';
28
+ import { ServerEdgeBase } from './server-client.js';
29
+ import type { ServerClientOptions } from './types.js';
30
+ /**
31
+ * Create a server-side EdgeBase client with cookie-based token management.
32
+ *
33
+ * @param url - EdgeBase project URL
34
+ * @param options - Cookie store and optional settings
35
+ *
36
+ * @example
37
+ * // Next.js App Router (Server Component)
38
+ * import { cookies } from 'next/headers';
39
+ * const cookieStore = await cookies();
40
+ * const client = createServerClient(process.env.EDGEBASE_URL!, {
41
+ * cookies: {
42
+ * get: (name) => cookieStore.get(name)?.value,
43
+ * set: (name, value, options) => cookieStore.set(name, value, options),
44
+ * delete: (name) => cookieStore.delete(name),
45
+ * },
46
+ * });
47
+ */
48
+ export declare function createServerClient(url: string, options: ServerClientOptions): ServerEdgeBase;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGlF,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIhD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,cAAc,CAE5F"}
package/dist/index.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @edge-base/ssr — Server-side rendering helpers for EdgeBase.
3
+ *
4
+ * Provides cookie-based token management for SSR frameworks
5
+ * (Next.js, Nuxt, SvelteKit, Remix, etc.).
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * import { createServerClient } from '@edge-base/ssr';
10
+ *
11
+ * const client = createServerClient('https://my-app.edgebase.fun', {
12
+ * cookies: {
13
+ * get: (name) => cookieStore.get(name)?.value,
14
+ * set: (name, value, options) => cookieStore.set(name, value, options),
15
+ * delete: (name) => cookieStore.delete(name),
16
+ * },
17
+ * });
18
+ *
19
+ * const user = client.getUser();
20
+ * const posts = await client.db('shared').table('posts').get();
21
+ * ```
22
+ */
23
+ // Server client
24
+ export { ServerEdgeBase } from './server-client.js';
25
+ // Cookie token manager (for advanced usage)
26
+ export { CookieTokenManager } from './cookie-token-manager.js';
27
+ export { EdgeBaseError } from '@edge-base/core';
28
+ // ─── Factory ───
29
+ import { ServerEdgeBase } from './server-client.js';
30
+ /**
31
+ * Create a server-side EdgeBase client with cookie-based token management.
32
+ *
33
+ * @param url - EdgeBase project URL
34
+ * @param options - Cookie store and optional settings
35
+ *
36
+ * @example
37
+ * // Next.js App Router (Server Component)
38
+ * import { cookies } from 'next/headers';
39
+ * const cookieStore = await cookies();
40
+ * const client = createServerClient(process.env.EDGEBASE_URL!, {
41
+ * cookies: {
42
+ * get: (name) => cookieStore.get(name)?.value,
43
+ * set: (name, value, options) => cookieStore.set(name, value, options),
44
+ * delete: (name) => cookieStore.delete(name),
45
+ * },
46
+ * });
47
+ */
48
+ export function createServerClient(url, options) {
49
+ return new ServerEdgeBase(url, options);
50
+ }
51
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,gBAAgB;AAChB,OAAO,EAAE,cAAc,EAAmB,MAAM,oBAAoB,CAAC;AAErE,4CAA4C;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAO/D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,kBAAkB;AAElB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW,EAAE,OAA4B;IAC1E,OAAO,IAAI,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * ServerEdgeBase — SSR-optimized EdgeBase client.
3
+ *
4
+ * Uses cookie-based token management instead of localStorage.
5
+ * Provides db(), storage, and functions access on behalf of the authenticated user.
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * import { createServerClient } from '@edge-base/ssr';
10
+ * const client = createServerClient('https://my-app.edgebase.fun', {
11
+ * cookies: cookieStore,
12
+ * });
13
+ * const posts = await client.db('shared').table('posts').get();
14
+ * const health = await client.functions.get('public/health');
15
+ * ```
16
+ */
17
+ import { DbRef, StorageClient, FunctionsClient } from '@edge-base/core';
18
+ import type { ITokenPair } from '@edge-base/core';
19
+ import type { ServerClientOptions } from './types.js';
20
+ /** Decoded user from JWT access token (payload only, no verification). */
21
+ export interface ServerUser {
22
+ id: string;
23
+ email?: string;
24
+ displayName?: string;
25
+ avatarUrl?: string;
26
+ role?: string;
27
+ isAnonymous?: boolean;
28
+ emailVisibility?: string;
29
+ custom?: Record<string, unknown>;
30
+ }
31
+ /**
32
+ * Server-side EdgeBase client for SSR environments.
33
+ *
34
+ * Exposes: db(), storage, functions, getUser(), getSession().
35
+ * Does NOT expose: auth signIn/signUp (client-side only), database-live, room, push.
36
+ */
37
+ export declare class ServerEdgeBase {
38
+ readonly storage: StorageClient;
39
+ readonly functions: FunctionsClient;
40
+ private httpClient;
41
+ private tokenManager;
42
+ private baseUrl;
43
+ private core;
44
+ constructor(url: string, options: ServerClientOptions);
45
+ /**
46
+ * Access a database by namespace + optional instance ID.
47
+ *
48
+ * @example
49
+ * const posts = await client.db('shared').table('posts').get();
50
+ * const docs = await client.db('workspace', 'ws-456').table('documents').get();
51
+ */
52
+ db(namespace: string, id?: string): DbRef;
53
+ /**
54
+ * Get the current authenticated user from the cookie token.
55
+ * Decodes the JWT payload without server verification.
56
+ * Returns null if no valid access token is present.
57
+ */
58
+ getUser(): ServerUser | null;
59
+ /**
60
+ * Get the current session tokens.
61
+ * Useful for passing tokens to client-side hydration.
62
+ */
63
+ getSession(): {
64
+ accessToken: string | null;
65
+ refreshToken: string | null;
66
+ };
67
+ /**
68
+ * Set session tokens (e.g., after OAuth callback on the server).
69
+ * Writes tokens to cookies for subsequent requests.
70
+ */
71
+ setSession(tokens: ITokenPair): void;
72
+ /**
73
+ * Clear session tokens (server-side sign out).
74
+ * Removes token cookies.
75
+ */
76
+ clearSession(): void;
77
+ }
78
+ //# sourceMappingURL=server-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-client.d.ts","sourceRoot":"","sources":["../src/server-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAEL,KAAK,EACL,aAAa,EACb,eAAe,EAIhB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAe;gBACf,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB;IAgBrD;;;;;;OAMG;IACH,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK;IAIzC;;;;OAIG;IACH,OAAO,IAAI,UAAU,GAAG,IAAI;IAM5B;;;OAGG;IACH,UAAU,IAAI;QAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IAOzE;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAIpC;;;OAGG;IACH,YAAY,IAAI,IAAI;CAIrB"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * ServerEdgeBase — SSR-optimized EdgeBase client.
3
+ *
4
+ * Uses cookie-based token management instead of localStorage.
5
+ * Provides db(), storage, and functions access on behalf of the authenticated user.
6
+ *
7
+ * Usage:
8
+ * ```ts
9
+ * import { createServerClient } from '@edge-base/ssr';
10
+ * const client = createServerClient('https://my-app.edgebase.fun', {
11
+ * cookies: cookieStore,
12
+ * });
13
+ * const posts = await client.db('shared').table('posts').get();
14
+ * const health = await client.functions.get('public/health');
15
+ * ```
16
+ */
17
+ import { HttpClient, DbRef, StorageClient, FunctionsClient, ContextManager, DefaultDbApi, HttpClientAdapter, } from '@edge-base/core';
18
+ import { CookieTokenManager } from './cookie-token-manager.js';
19
+ /**
20
+ * Server-side EdgeBase client for SSR environments.
21
+ *
22
+ * Exposes: db(), storage, functions, getUser(), getSession().
23
+ * Does NOT expose: auth signIn/signUp (client-side only), database-live, room, push.
24
+ */
25
+ export class ServerEdgeBase {
26
+ storage;
27
+ functions;
28
+ httpClient;
29
+ tokenManager;
30
+ baseUrl;
31
+ core;
32
+ constructor(url, options) {
33
+ this.baseUrl = url.replace(/\/$/, '');
34
+ this.tokenManager = new CookieTokenManager(options.cookies, options.cookieOptions);
35
+ this.httpClient = new HttpClient({
36
+ baseUrl: this.baseUrl,
37
+ tokenManager: options.serviceKey ? undefined : this.tokenManager,
38
+ serviceKey: options.serviceKey,
39
+ contextManager: new ContextManager(),
40
+ });
41
+ this.core = new DefaultDbApi(new HttpClientAdapter(this.httpClient));
42
+ this.storage = new StorageClient(this.httpClient, this.core);
43
+ this.functions = new FunctionsClient(this.httpClient);
44
+ }
45
+ /**
46
+ * Access a database by namespace + optional instance ID.
47
+ *
48
+ * @example
49
+ * const posts = await client.db('shared').table('posts').get();
50
+ * const docs = await client.db('workspace', 'ws-456').table('documents').get();
51
+ */
52
+ db(namespace, id) {
53
+ return new DbRef(this.core, namespace, id, undefined, undefined);
54
+ }
55
+ /**
56
+ * Get the current authenticated user from the cookie token.
57
+ * Decodes the JWT payload without server verification.
58
+ * Returns null if no valid access token is present.
59
+ */
60
+ getUser() {
61
+ const token = this.tokenManager.getAccessToken();
62
+ if (!token)
63
+ return null;
64
+ return decodeJwtPayload(token);
65
+ }
66
+ /**
67
+ * Get the current session tokens.
68
+ * Useful for passing tokens to client-side hydration.
69
+ */
70
+ getSession() {
71
+ return {
72
+ accessToken: this.tokenManager.getAccessToken(),
73
+ refreshToken: this.tokenManager.getRefreshToken(),
74
+ };
75
+ }
76
+ /**
77
+ * Set session tokens (e.g., after OAuth callback on the server).
78
+ * Writes tokens to cookies for subsequent requests.
79
+ */
80
+ setSession(tokens) {
81
+ this.tokenManager.setTokens(tokens);
82
+ }
83
+ /**
84
+ * Clear session tokens (server-side sign out).
85
+ * Removes token cookies.
86
+ */
87
+ clearSession() {
88
+ this.tokenManager.clearTokens();
89
+ }
90
+ }
91
+ // ─── JWT Decode (payload only, no verification) ───
92
+ function decodeJwtPayload(token) {
93
+ try {
94
+ const parts = token.split('.');
95
+ if (parts.length !== 3)
96
+ return null;
97
+ // Base64url decode the payload
98
+ const payload = parts[1]
99
+ .replace(/-/g, '+')
100
+ .replace(/_/g, '/');
101
+ const padded = payload + '='.repeat((4 - (payload.length % 4)) % 4);
102
+ // Use TextDecoder for portable base64 decoding (Node 16+, Deno, Bun, Edge)
103
+ const bytes = Uint8Array.from(
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ globalThis.atob(padded), (c) => c.charCodeAt(0));
106
+ const json = new TextDecoder().decode(bytes);
107
+ const data = JSON.parse(json);
108
+ return {
109
+ id: data.sub ?? data.id,
110
+ email: data.email,
111
+ displayName: data.displayName,
112
+ avatarUrl: data.avatarUrl,
113
+ role: data.role,
114
+ isAnonymous: data.isAnonymous,
115
+ emailVisibility: data.emailVisibility,
116
+ custom: data.custom,
117
+ };
118
+ }
119
+ catch {
120
+ return null;
121
+ }
122
+ }
123
+ //# sourceMappingURL=server-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-client.js","sourceRoot":"","sources":["../src/server-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,UAAU,EACV,KAAK,EACL,aAAa,EACb,eAAe,EACf,cAAc,EACd,YAAY,EACZ,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAe/D;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IAChB,OAAO,CAAgB;IACvB,SAAS,CAAkB;IAC5B,UAAU,CAAa;IACvB,YAAY,CAAqB;IACjC,OAAO,CAAS;IAChB,IAAI,CAAe;IAC3B,YAAY,GAAW,EAAE,OAA4B;QACnD,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;QAEnF,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAAC;YAC/B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY;YAChE,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,cAAc,EAAE,IAAI,cAAc,EAAE;SACrC,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;OAMG;IACH,EAAE,CAAC,SAAiB,EAAE,EAAW;QAC/B,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACnE,CAAC;IAED;;;;OAIG;IACH,OAAO;QACL,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,EAAmB,CAAC;QAClE,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc,EAAmB;YAChE,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE;SAClD,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,MAAkB;QAC3B,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,YAAY;QACV,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;CAEF;AAED,qDAAqD;AAErD,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,+BAA+B;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;aACrB,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;aAClB,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACtB,MAAM,MAAM,GAAG,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,2EAA2E;QAC3E,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI;QAC3B,8DAA8D;QAC7D,UAAkB,CAAC,IAAI,CAAC,MAAM,CAAW,EAC1C,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAC/B,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE9B,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE;YACvB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @edge-base/ssr — Type definitions for cookie-based SSR authentication.
3
+ */
4
+ /** Options for cookie serialization. */
5
+ export interface CookieOptions {
6
+ httpOnly?: boolean;
7
+ secure?: boolean;
8
+ sameSite?: 'strict' | 'lax' | 'none';
9
+ maxAge?: number;
10
+ path?: string;
11
+ domain?: string;
12
+ }
13
+ /**
14
+ * Abstract cookie store interface.
15
+ *
16
+ * Implementations:
17
+ * - Next.js App Router: `cookies()` from `next/headers`
18
+ * - Next.js Pages Router: wrapper around `nookies` or `req.cookies` + `res.setHeader`
19
+ * - Nuxt 3: wrapper around `useCookie` or `getCookie`/`setCookie` from `h3`
20
+ * - SvelteKit: wrapper around `cookies` from `event`
21
+ */
22
+ export interface CookieStore {
23
+ /** Get a cookie value by name. Returns null/undefined if not set. */
24
+ get(name: string): string | null | undefined;
25
+ /** Set a cookie with the given name, value, and options. */
26
+ set(name: string, value: string, options?: CookieOptions): void;
27
+ /** Delete a cookie by name. */
28
+ delete(name: string): void;
29
+ }
30
+ /** Options for creating a server-side EdgeBase client. */
31
+ export interface ServerClientOptions {
32
+ /** Cookie store for token persistence across requests. */
33
+ cookies: CookieStore;
34
+ /** Override default cookie options (httpOnly, secure, sameSite, path). */
35
+ cookieOptions?: Partial<CookieOptions>;
36
+ /**
37
+ * Service key for admin-level access.
38
+ * When provided, requests use the service key instead of user tokens.
39
+ */
40
+ serviceKey?: string;
41
+ }
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,4DAA4D;IAC5D,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAChE,+BAA+B;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,OAAO,EAAE,WAAW,CAAC;IACrB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @edge-base/ssr — Type definitions for cookie-based SSR authentication.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/llms.txt ADDED
@@ -0,0 +1,96 @@
1
+ # EdgeBase JS SSR SDK
2
+
3
+ Use this file as a quick-reference contract for AI coding assistants working with `@edge-base/ssr`.
4
+
5
+ ## Package Boundary
6
+
7
+ Use `@edge-base/ssr` for server-side code that should act as the current cookie-authenticated user.
8
+
9
+ Do not use it for browser bundles or client-side sign-in UI. Use `@edge-base/web` there. Do not use it for Service Key admin work; use `@edge-base/admin`.
10
+
11
+ ## Source Of Truth
12
+
13
+ - Package README: https://github.com/edge-base/edgebase/blob/main/packages/sdk/js/packages/ssr/README.md
14
+ - Next.js guide: https://edgebase.fun/docs/sdks/nextjs
15
+ - Client vs server SDKs: https://edgebase.fun/docs/sdks/client-vs-server
16
+ - Authentication: https://edgebase.fun/docs/authentication
17
+ - Database client SDK: https://edgebase.fun/docs/database/client-sdk
18
+
19
+ ## Canonical Examples
20
+
21
+ ### Create a server client
22
+
23
+ ```ts
24
+ import { createServerClient } from '@edge-base/ssr';
25
+
26
+ const client = createServerClient(process.env.EDGEBASE_URL!, {
27
+ cookies: {
28
+ get: (name) => cookieStore.get(name)?.value,
29
+ set: (name, value, options) => cookieStore.set(name, value, options),
30
+ delete: (name) => cookieStore.delete(name),
31
+ },
32
+ });
33
+ ```
34
+
35
+ ### Read the current user
36
+
37
+ ```ts
38
+ const user = client.getUser();
39
+ ```
40
+
41
+ ### Query data on the server
42
+
43
+ ```ts
44
+ const posts = await client
45
+ .db('app')
46
+ .table('posts')
47
+ .where('published', '==', true)
48
+ .getList();
49
+ ```
50
+
51
+ ### Write cookies after an OAuth callback
52
+
53
+ ```ts
54
+ client.setSession({
55
+ accessToken,
56
+ refreshToken,
57
+ });
58
+ ```
59
+
60
+ ### Clear the session
61
+
62
+ ```ts
63
+ client.clearSession();
64
+ ```
65
+
66
+ ## Hard Rules
67
+
68
+ - `createServerClient(url, options)` requires a cookie adapter
69
+ - the cookie adapter must implement `get(name)`, `set(name, value, options?)`, and `delete(name)`
70
+ - `getUser()` is synchronous and returns decoded JWT payload data or `null`
71
+ - `getSession()` is synchronous
72
+ - `setSession()` and `clearSession()` are synchronous cookie operations
73
+ - `client.db(namespace, id?)` takes the instance id positionally
74
+ - this package exposes `db`, `storage`, and `functions`
75
+ - this package does not expose browser auth flows, database live, rooms, or push
76
+
77
+ ## Common Mistakes
78
+
79
+ - do not call browser-only auth methods like `client.auth.signIn()` here; this package does not expose them
80
+ - do not use `@edge-base/ssr` in client components
81
+ - do not confuse `getUser()` with a server-side verification call; it decodes the cookie token payload
82
+ - if you need privileged admin access or Service Key behavior, use `@edge-base/admin`
83
+ - if you need browser auth state listeners or realtime UI, use `@edge-base/web`
84
+
85
+ ## Quick Reference
86
+
87
+ ```text
88
+ createServerClient(url, { cookies, cookieOptions?, serviceKey? }) -> ServerEdgeBase
89
+ client.getUser() -> ServerUser | null
90
+ client.getSession() -> { accessToken, refreshToken }
91
+ client.setSession(tokens) -> void
92
+ client.clearSession() -> void
93
+ client.db(namespace, id?) -> DbRef
94
+ client.storage -> StorageClient
95
+ client.functions -> FunctionsClient
96
+ ```
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@edge-base/ssr",
3
+ "version": "0.1.1",
4
+ "description": "EdgeBase SSR helpers — cookie-based token management for server-side rendering",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/edge-base/edgebase.git",
9
+ "directory": "packages/sdk/js/packages/ssr"
10
+ },
11
+ "homepage": "https://edgebase.fun",
12
+ "bugs": "https://github.com/edge-base/edgebase/issues",
13
+ "keywords": [
14
+ "edgebase",
15
+ "ssr",
16
+ "server-side-rendering",
17
+ "cookies",
18
+ "auth"
19
+ ],
20
+ "type": "module",
21
+ "main": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
+ }
28
+ },
29
+ "sideEffects": false,
30
+ "files": [
31
+ "dist",
32
+ "llms.txt"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc",
39
+ "dev": "tsc --watch",
40
+ "prepack": "pnpm run build"
41
+ },
42
+ "dependencies": {
43
+ "@edge-base/core": "workspace:*"
44
+ },
45
+ "devDependencies": {
46
+ "typescript": "^5.7.0"
47
+ }
48
+ }