@somewhere-cloud/sdk 0.0.0-stage → 0.13.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/LICENSE +21 -0
- package/README.md +191 -2
- package/dist/cjs/auth/client.js +1142 -0
- package/dist/cjs/auth/client.js.map +1 -0
- package/dist/cjs/auth/continuation.js +27 -0
- package/dist/cjs/auth/continuation.js.map +1 -0
- package/dist/cjs/auth/index.js +21 -0
- package/dist/cjs/auth/index.js.map +1 -0
- package/dist/cjs/auth/react.js +295 -0
- package/dist/cjs/auth/react.js.map +1 -0
- package/dist/cjs/auth/server.js +368 -0
- package/dist/cjs/auth/server.js.map +1 -0
- package/dist/cjs/client.js +392 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/errors.js +16 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.cjs +215 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/query-cache.js +91 -0
- package/dist/cjs/query-cache.js.map +1 -0
- package/dist/cjs/resources/auth.js +875 -0
- package/dist/cjs/resources/auth.js.map +1 -0
- package/dist/cjs/resources/calls.js +42 -0
- package/dist/cjs/resources/calls.js.map +1 -0
- package/dist/cjs/resources/chat.js +82 -0
- package/dist/cjs/resources/chat.js.map +1 -0
- package/dist/cjs/resources/db.js +124 -0
- package/dist/cjs/resources/db.js.map +1 -0
- package/dist/cjs/resources/emails.js +39 -0
- package/dist/cjs/resources/emails.js.map +1 -0
- package/dist/cjs/resources/fs.js +141 -0
- package/dist/cjs/resources/fs.js.map +1 -0
- package/dist/cjs/resources/functions.js +145 -0
- package/dist/cjs/resources/functions.js.map +1 -0
- package/dist/cjs/resources/inbox.js +76 -0
- package/dist/cjs/resources/inbox.js.map +1 -0
- package/dist/cjs/resources/payments.js +68 -0
- package/dist/cjs/resources/payments.js.map +1 -0
- package/dist/cjs/resources/postgrest.js +391 -0
- package/dist/cjs/resources/postgrest.js.map +1 -0
- package/dist/cjs/resources/projects.js +71 -0
- package/dist/cjs/resources/projects.js.map +1 -0
- package/dist/cjs/resources/storage.js +191 -0
- package/dist/cjs/resources/storage.js.map +1 -0
- package/dist/cjs/resources/tasks.js +99 -0
- package/dist/cjs/resources/tasks.js.map +1 -0
- package/dist/cjs/resources/video.js +50 -0
- package/dist/cjs/resources/video.js.map +1 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/auth/client.js +1137 -0
- package/dist/esm/auth/client.js.map +1 -0
- package/dist/esm/auth/continuation.js +22 -0
- package/dist/esm/auth/continuation.js.map +1 -0
- package/dist/esm/auth/index.js +5 -0
- package/dist/esm/auth/index.js.map +1 -0
- package/dist/esm/auth/react.js +279 -0
- package/dist/esm/auth/react.js.map +1 -0
- package/dist/esm/auth/server.js +365 -0
- package/dist/esm/auth/server.js.map +1 -0
- package/dist/esm/client.js +388 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.js +12 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.js +188 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/query-cache.js +87 -0
- package/dist/esm/query-cache.js.map +1 -0
- package/dist/esm/resources/auth.js +871 -0
- package/dist/esm/resources/auth.js.map +1 -0
- package/dist/esm/resources/calls.js +38 -0
- package/dist/esm/resources/calls.js.map +1 -0
- package/dist/esm/resources/chat.js +77 -0
- package/dist/esm/resources/chat.js.map +1 -0
- package/dist/esm/resources/db.js +120 -0
- package/dist/esm/resources/db.js.map +1 -0
- package/dist/esm/resources/emails.js +35 -0
- package/dist/esm/resources/emails.js.map +1 -0
- package/dist/esm/resources/fs.js +137 -0
- package/dist/esm/resources/fs.js.map +1 -0
- package/dist/esm/resources/functions.js +141 -0
- package/dist/esm/resources/functions.js.map +1 -0
- package/dist/esm/resources/inbox.js +70 -0
- package/dist/esm/resources/inbox.js.map +1 -0
- package/dist/esm/resources/payments.js +64 -0
- package/dist/esm/resources/payments.js.map +1 -0
- package/dist/esm/resources/postgrest.js +386 -0
- package/dist/esm/resources/postgrest.js.map +1 -0
- package/dist/esm/resources/projects.js +67 -0
- package/dist/esm/resources/projects.js.map +1 -0
- package/dist/esm/resources/storage.js +186 -0
- package/dist/esm/resources/storage.js.map +1 -0
- package/dist/esm/resources/tasks.js +95 -0
- package/dist/esm/resources/tasks.js.map +1 -0
- package/dist/esm/resources/video.js +46 -0
- package/dist/esm/resources/video.js.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/types/auth/client.d.ts +272 -0
- package/dist/types/auth/client.d.ts.map +1 -0
- package/dist/types/auth/continuation.d.ts +10 -0
- package/dist/types/auth/continuation.d.ts.map +1 -0
- package/dist/types/auth/index.d.ts +2 -0
- package/dist/types/auth/index.d.ts.map +1 -0
- package/dist/types/auth/react.d.ts +140 -0
- package/dist/types/auth/react.d.ts.map +1 -0
- package/dist/types/auth/server.d.ts +124 -0
- package/dist/types/auth/server.d.ts.map +1 -0
- package/dist/types/client.d.ts +128 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/errors.d.ts +17 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/index.d.ts +145 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/query-cache.d.ts +59 -0
- package/dist/types/query-cache.d.ts.map +1 -0
- package/dist/types/resources/auth.d.ts +188 -0
- package/dist/types/resources/auth.d.ts.map +1 -0
- package/dist/types/resources/calls.d.ts +27 -0
- package/dist/types/resources/calls.d.ts.map +1 -0
- package/dist/types/resources/chat.d.ts +24 -0
- package/dist/types/resources/chat.d.ts.map +1 -0
- package/dist/types/resources/db.d.ts +81 -0
- package/dist/types/resources/db.d.ts.map +1 -0
- package/dist/types/resources/emails.d.ts +20 -0
- package/dist/types/resources/emails.d.ts.map +1 -0
- package/dist/types/resources/fs.d.ts +68 -0
- package/dist/types/resources/fs.d.ts.map +1 -0
- package/dist/types/resources/functions.d.ts +30 -0
- package/dist/types/resources/functions.d.ts.map +1 -0
- package/dist/types/resources/inbox.d.ts +52 -0
- package/dist/types/resources/inbox.d.ts.map +1 -0
- package/dist/types/resources/payments.d.ts +31 -0
- package/dist/types/resources/payments.d.ts.map +1 -0
- package/dist/types/resources/postgrest.d.ts +121 -0
- package/dist/types/resources/postgrest.d.ts.map +1 -0
- package/dist/types/resources/projects.d.ts +79 -0
- package/dist/types/resources/projects.d.ts.map +1 -0
- package/dist/types/resources/storage.d.ts +63 -0
- package/dist/types/resources/storage.d.ts.map +1 -0
- package/dist/types/resources/tasks.d.ts +87 -0
- package/dist/types/resources/tasks.d.ts.map +1 -0
- package/dist/types/resources/video.d.ts +30 -0
- package/dist/types/resources/video.d.ts.map +1 -0
- package/dist/types/types.d.ts +379 -0
- package/dist/types/types.d.ts.map +1 -0
- package/package.json +86 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/index.ts"],"names":[],"mappings":"AAGA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @somewhere-cloud/sdk/react — the "you never touch a token" layer.
|
|
3
|
+
*
|
|
4
|
+
* <SomewhereAuthProvider>
|
|
5
|
+
* <SignedIn><Dashboard/></SignedIn>
|
|
6
|
+
* <SignedOut><SignIn/></SignedOut>
|
|
7
|
+
* </SomewhereAuthProvider>
|
|
8
|
+
*
|
|
9
|
+
* const user = useUser(); // null | User
|
|
10
|
+
* const auth = useAuth(); // actions + auth.fetch
|
|
11
|
+
*
|
|
12
|
+
* The provider hydrates the user once on mount (validating + refreshing the
|
|
13
|
+
* session) and re-renders on every login / logout / token rotation.
|
|
14
|
+
*/
|
|
15
|
+
import React from 'react';
|
|
16
|
+
import { type SomewhereAuth, type SomewhereAuthOptions, type User, type Session, type AuthState } from './client.js';
|
|
17
|
+
export declare function SomewhereAuthProvider(props: {
|
|
18
|
+
options?: SomewhereAuthOptions;
|
|
19
|
+
/** Pass a pre-created client instead of options, e.g. to share it with
|
|
20
|
+
* non-React code. */
|
|
21
|
+
client?: SomewhereAuth;
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
}): React.JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* The session as the backend last reported it: status ('checking' |
|
|
26
|
+
* 'authenticated' | 'signed-out' | 'indeterminate'), the user (last-known and
|
|
27
|
+
* unverified unless 'authenticated'), and the check error. `recheck()` asks
|
|
28
|
+
* /me again. Unlike useUser(), this never presents a cached user as verified.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useAuthState(): AuthState & {
|
|
31
|
+
recheck(): Promise<User | null>;
|
|
32
|
+
};
|
|
33
|
+
/** The current user, or null. Re-renders on login/logout/rotation. */
|
|
34
|
+
export declare function useUser(): User | null;
|
|
35
|
+
/** The raw session tokens (rarely needed — prefer auth.fetch). */
|
|
36
|
+
export declare function useSession(): Session | null;
|
|
37
|
+
/** True until the first session check resolves. */
|
|
38
|
+
export declare function useAuthLoading(): boolean;
|
|
39
|
+
/** The client: actions (signIn, signUp, signOut, …) + auth.fetch. */
|
|
40
|
+
export declare function useAuth(): SomewhereAuth;
|
|
41
|
+
export declare function SignedIn({ children }: {
|
|
42
|
+
children: React.ReactNode;
|
|
43
|
+
}): React.JSX.Element | null;
|
|
44
|
+
/**
|
|
45
|
+
* Renders `children` when signed out. While a signOut() is waiting for the
|
|
46
|
+
* server (`useAuthState().signingOut`), the server may still accept the
|
|
47
|
+
* session, so it renders `pending` instead (default nothing), e.g.
|
|
48
|
+
* `<SignedOut pending={<p>Signing out…</p>}><SignIn/></SignedOut>`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function SignedOut({ children, pending }: {
|
|
51
|
+
children: React.ReactNode;
|
|
52
|
+
pending?: React.ReactNode;
|
|
53
|
+
}): React.JSX.Element | null;
|
|
54
|
+
/** Gate a subtree behind auth; shows `fallback` (default null) when signed
|
|
55
|
+
* out, and `pending` (default null) while a signOut() awaits the server. */
|
|
56
|
+
export declare function Protect({ children, fallback, pending }: {
|
|
57
|
+
children: React.ReactNode;
|
|
58
|
+
fallback?: React.ReactNode;
|
|
59
|
+
pending?: React.ReactNode;
|
|
60
|
+
}): React.JSX.Element | null;
|
|
61
|
+
/** An explicit server billing observation, separate from sign-in identity. */
|
|
62
|
+
export type BillingObservation = {
|
|
63
|
+
status: 'ready';
|
|
64
|
+
features: readonly string[];
|
|
65
|
+
} | {
|
|
66
|
+
status: 'loading';
|
|
67
|
+
} | {
|
|
68
|
+
status: 'unavailable';
|
|
69
|
+
};
|
|
70
|
+
/** Local presentation check against an explicit observation; server authorization remains required. */
|
|
71
|
+
export declare function useEntitlements(observation?: BillingObservation): {
|
|
72
|
+
status: 'ready';
|
|
73
|
+
has: (feature: string) => boolean;
|
|
74
|
+
entitlements: readonly string[];
|
|
75
|
+
} | {
|
|
76
|
+
status: 'loading';
|
|
77
|
+
} | {
|
|
78
|
+
status: 'unavailable';
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Present a billing feature using an explicit observation from your server.
|
|
82
|
+
* Loading and unavailable observations have separate presentation from a ready denial.
|
|
83
|
+
* Server endpoints must still authorize the operation.
|
|
84
|
+
*
|
|
85
|
+
* <Gate billing={billing} feature="export" pending={<Spinner/>}
|
|
86
|
+
* unavailable={<Retry/>} fallback={<Upsell/>}><ExportButton/></Gate>
|
|
87
|
+
*/
|
|
88
|
+
export declare function Gate({ billing, feature, children, fallback, pending, unavailable, }: {
|
|
89
|
+
billing?: BillingObservation;
|
|
90
|
+
feature: string;
|
|
91
|
+
children: React.ReactNode;
|
|
92
|
+
fallback?: React.ReactNode;
|
|
93
|
+
pending?: React.ReactNode;
|
|
94
|
+
unavailable?: React.ReactNode;
|
|
95
|
+
}): React.JSX.Element;
|
|
96
|
+
/**
|
|
97
|
+
* Pricing page (sw.billing). Renders the project's code-defined plans,
|
|
98
|
+
* highlights the user's current plan, and a Subscribe button runs checkout for
|
|
99
|
+
* the signed-in user (the worker resolves the plan's price from the catalog).
|
|
100
|
+
*
|
|
101
|
+
* <PricingTable/> // that's it
|
|
102
|
+
*
|
|
103
|
+
* Logic-only / unstyled — theme it with the `sw-*` class hooks (sw-pricing-table,
|
|
104
|
+
* sw-plan[data-current], sw-plan-name/-price/-features/-feature/-cta). Pass
|
|
105
|
+
* `onSubscribe` to override the default redirect-to-Stripe behavior, `onError`
|
|
106
|
+
* to surface failures.
|
|
107
|
+
*/
|
|
108
|
+
export declare function PricingTable(props: {
|
|
109
|
+
className?: string;
|
|
110
|
+
/** Current plan from an explicit server billing observation. */
|
|
111
|
+
currentPlan?: string | null;
|
|
112
|
+
onSubscribe?: (planSlug: string) => void;
|
|
113
|
+
onError?: (message: string) => void;
|
|
114
|
+
}): React.JSX.Element;
|
|
115
|
+
/**
|
|
116
|
+
* One-click "manage subscription" (sw.billing) — opens the Stripe billing portal
|
|
117
|
+
* for the signed-in user (update card, cancel, see invoices). Renders a button;
|
|
118
|
+
* pass children to set the label (default "Manage billing"). The user can only
|
|
119
|
+
* ever reach their OWN portal (resolved server-side from their session).
|
|
120
|
+
*
|
|
121
|
+
* <BillingPortal/> // default label
|
|
122
|
+
* <BillingPortal>Manage plan</BillingPortal>
|
|
123
|
+
*/
|
|
124
|
+
export declare function BillingPortal(props: {
|
|
125
|
+
children?: React.ReactNode;
|
|
126
|
+
className?: string;
|
|
127
|
+
onError?: (message: string) => void;
|
|
128
|
+
}): React.JSX.Element;
|
|
129
|
+
/**
|
|
130
|
+
* Drop this component at an OAuth callback route (the redirect_uri). It
|
|
131
|
+
* reads `?code=` and completes sign-in, then calls onDone (or navigates to '/').
|
|
132
|
+
* The app writes no code-exchange logic.
|
|
133
|
+
*/
|
|
134
|
+
export declare function AuthCallback(props: {
|
|
135
|
+
provider?: 'google' | 'github' | 'discord';
|
|
136
|
+
onDone?: (user: User) => void;
|
|
137
|
+
onError?: (message: string) => void;
|
|
138
|
+
children?: React.ReactNode;
|
|
139
|
+
}): React.JSX.Element;
|
|
140
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/auth/react.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @somewhere-cloud/sdk/server — the backend half, so the app writes ~zero auth code.
|
|
3
|
+
*
|
|
4
|
+
* Mount it from a single deployed function that handles your /api/auth/* routes:
|
|
5
|
+
*
|
|
6
|
+
* // api/auth/[...path].ts
|
|
7
|
+
* import { somewhereAuth } from '@somewhere-cloud/sdk/server';
|
|
8
|
+
* export default (req, sw) => somewhereAuth(req, sw);
|
|
9
|
+
*
|
|
10
|
+
* It wires the standard endpoints the @somewhere-cloud/sdk/auth client talks to onto
|
|
11
|
+
* `sw.auth.*` — which already owns the Google OAuth client, JWT validation, and
|
|
12
|
+
* the bearer-token rotation contract. login/signup are developer-key-gated on the
|
|
13
|
+
* platform (can't be called from the browser), which is exactly why this thin
|
|
14
|
+
* server shim exists.
|
|
15
|
+
*
|
|
16
|
+
* SESSION TRANSPORT: a successful sign-in sets the session as httpOnly
|
|
17
|
+
* `__Host-` cookies and answers `{ user, cookie_session: true }` — tokens
|
|
18
|
+
* never reach page JS. That is the answer for every caller that does not opt
|
|
19
|
+
* out, including a plain `fetch('/api/auth/login', { credentials: 'include' })`
|
|
20
|
+
* with no header (pfb_e1254f754222). Only an explicit
|
|
21
|
+
* `X-Sw-Auth-Mode: header` (aliases `token`, `bearer`) — a server or native
|
|
22
|
+
* client that holds its own session — receives the token pair in the body, and
|
|
23
|
+
* then no cookie is set. A runtime that cannot set the cookie refuses
|
|
24
|
+
* (COOKIE_SESSION_UNAVAILABLE) instead of falling back to tokens.
|
|
25
|
+
*
|
|
26
|
+
* Covered today: email/password (signup, login, logout), magic-link/OTP,
|
|
27
|
+
* email verification for the signed-in account, Google/GitHub/Discord OAuth
|
|
28
|
+
* (url + exchange), and `me` (validate + refresh).
|
|
29
|
+
*/
|
|
30
|
+
/** The slice of the platform `sw` namespace this handler uses. */
|
|
31
|
+
export interface SwAuthNamespace {
|
|
32
|
+
auth: {
|
|
33
|
+
signup(opts: {
|
|
34
|
+
email: string;
|
|
35
|
+
password: string;
|
|
36
|
+
display_name?: string;
|
|
37
|
+
}): Promise<unknown>;
|
|
38
|
+
login(opts: {
|
|
39
|
+
email: string;
|
|
40
|
+
password: string;
|
|
41
|
+
}): Promise<unknown>;
|
|
42
|
+
loginWithCookie?(req: Request, email: string, password: string): Promise<unknown>;
|
|
43
|
+
signupWithCookie?(req: Request, email: string, password: string, opts?: {
|
|
44
|
+
display_name?: string;
|
|
45
|
+
}): Promise<unknown>;
|
|
46
|
+
mfa?: {
|
|
47
|
+
challenge?(opts: {
|
|
48
|
+
mfa_token: string;
|
|
49
|
+
code: string;
|
|
50
|
+
}): Promise<unknown>;
|
|
51
|
+
challengeWithCookie?(opts: {
|
|
52
|
+
mfa_token: string;
|
|
53
|
+
code: string;
|
|
54
|
+
}): Promise<unknown>;
|
|
55
|
+
};
|
|
56
|
+
logout(opts: Record<string, unknown>): Promise<unknown>;
|
|
57
|
+
fromRequest(req: Request, enrich?: unknown): Promise<unknown>;
|
|
58
|
+
refreshSession?(req: Request): Promise<unknown>;
|
|
59
|
+
/** Exchanges take the callback's ?code= and its public ?attempt=, which
|
|
60
|
+
* selects this browser's attempt cookie; the runtime presents only that
|
|
61
|
+
* original request cookie and the platform proves it before spending. */
|
|
62
|
+
/** Start browser-bound social sign-in: stages this attempt's HttpOnly
|
|
63
|
+
* verifier cookie on the response and resolves the provider start URL.
|
|
64
|
+
* Optional so the handler answers 501 on a runtime that predates it. The
|
|
65
|
+
* old googleUrl/githubUrl/discordUrl builders are not part of this slice:
|
|
66
|
+
* current runtimes refuse them, so a current runtime context must satisfy
|
|
67
|
+
* this type without them. */
|
|
68
|
+
oauthStart?(provider: 'google' | 'github' | 'discord', opts: {
|
|
69
|
+
redirect_uri: string;
|
|
70
|
+
}): Promise<string>;
|
|
71
|
+
googleExchange(opts: {
|
|
72
|
+
code: string;
|
|
73
|
+
attempt?: string;
|
|
74
|
+
}): Promise<unknown>;
|
|
75
|
+
githubExchange(opts: {
|
|
76
|
+
code: string;
|
|
77
|
+
attempt?: string;
|
|
78
|
+
}): Promise<unknown>;
|
|
79
|
+
discordExchange(opts: {
|
|
80
|
+
code: string;
|
|
81
|
+
attempt?: string;
|
|
82
|
+
}): Promise<unknown>;
|
|
83
|
+
signInWithOtp(opts: {
|
|
84
|
+
email: string;
|
|
85
|
+
redirect_uri?: string;
|
|
86
|
+
}): Promise<unknown>;
|
|
87
|
+
verifyOtp(opts: {
|
|
88
|
+
token: string;
|
|
89
|
+
}): Promise<unknown>;
|
|
90
|
+
/** Cookie-session primitives (tsk_1dd4e1b4) — optional so the handler
|
|
91
|
+
* degrades to token bodies on runtimes that predate them. */
|
|
92
|
+
setSessionCookies?(access: string, refresh: string): void;
|
|
93
|
+
logoutWithCookie?(req: Request): Promise<unknown>;
|
|
94
|
+
/** Email verification for the request's own session — optional so the
|
|
95
|
+
* handler answers 501 on a runtime that predates them. */
|
|
96
|
+
requestEmailVerificationWithCookie?(req: Request): Promise<unknown>;
|
|
97
|
+
verifyEmailWithCookie?(req: Request, opts: {
|
|
98
|
+
code: string;
|
|
99
|
+
}): Promise<unknown>;
|
|
100
|
+
};
|
|
101
|
+
/** Entitlements (sw.billing) — optional so the handler degrades cleanly on a
|
|
102
|
+
* runtime that predates it (the /plans route 404s instead of throwing). */
|
|
103
|
+
billing?: {
|
|
104
|
+
plans(): Promise<unknown>;
|
|
105
|
+
};
|
|
106
|
+
/** Payments (sw.payments) — drives the <PricingTable>/<BillingPortal> flows.
|
|
107
|
+
* Optional so the handler degrades cleanly on an older runtime. */
|
|
108
|
+
payments?: {
|
|
109
|
+
checkoutForUser(opts: {
|
|
110
|
+
plan: string;
|
|
111
|
+
success_url?: string;
|
|
112
|
+
cancel_url?: string;
|
|
113
|
+
}): Promise<{
|
|
114
|
+
url?: string | null;
|
|
115
|
+
}>;
|
|
116
|
+
portalForUser(opts: {
|
|
117
|
+
return_url?: string;
|
|
118
|
+
}): Promise<{
|
|
119
|
+
url?: string | null;
|
|
120
|
+
}>;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export declare function somewhereAuth(req: Request, sw: SwAuthNamespace): Promise<Response>;
|
|
124
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/auth/server.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE;QACJ,MAAM,CAAC,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3F,KAAK,CAAC,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACnE,eAAe,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAClF,gBAAgB,CAAC,CACf,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;YAAE,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,GAC/B,OAAO,CAAC,OAAO,CAAC,CAAC;QACpB,GAAG,CAAC,EAAE;YACJ,SAAS,CAAC,CAAC,IAAI,EAAE;gBAAE,SAAS,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAA;aAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YACxE,mBAAmB,CAAC,CAAC,IAAI,EAAE;gBAAE,SAAS,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAA;aAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;SACnF,CAAC;QACF,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxD,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9D,cAAc,CAAC,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChD;;kFAE0E;QAC1E;;;;;sCAK8B;QAC9B,UAAU,CAAC,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE;YAAE,YAAY,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACxG,cAAc,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3E,cAAc,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3E,eAAe,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5E,aAAa,CAAC,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChF,SAAS,CAAC,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACrD;sEAC8D;QAC9D,iBAAiB,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1D,gBAAgB,CAAC,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAClD;mEAC2D;QAC3D,kCAAkC,CAAC,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACpE,qBAAqB,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KAChF,CAAC;IACF;gFAC4E;IAC5E,OAAO,CAAC,EAAE;QACR,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;KAC3B,CAAC;IACF;wEACoE;IACpE,QAAQ,CAAC,EAAE;QAIT,eAAe,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAC,CAAC;QACrH,aAAa,CAAC,IAAI,EAAE;YAAE,UAAU,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAC,CAAC;KAChF,CAAC;CACH;AA2ED,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqSxF"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { QueryCache } from './query-cache.js';
|
|
2
|
+
import type { Result, SomewhereOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Which auth header a request should use.
|
|
5
|
+
*
|
|
6
|
+
* - `developer` — always the initial `smt_` key given at construction.
|
|
7
|
+
* Developer-only endpoints (`/ai/*`, `/email/*`, `/auth/signup`,
|
|
8
|
+
* `/auth/login`, `/auth/logout`, `/auth/forgot`, `/auth/reset`) use
|
|
9
|
+
* this mode even if a user session is active — the server rejects
|
|
10
|
+
* JWTs on those routes.
|
|
11
|
+
*
|
|
12
|
+
* - `dual` — use the user's session JWT if one is active (after
|
|
13
|
+
* `auth.signInWithPassword`), otherwise fall back to the initial
|
|
14
|
+
* key. This matches the server's dual-auth routes: `/db/query`,
|
|
15
|
+
* `/storage/*`, `/fs/*`, `/auth/me`, `/logs`.
|
|
16
|
+
*
|
|
17
|
+
* - `session` — require an active user session. Used for routes the
|
|
18
|
+
* server only accepts with an app-user JWT (`/auth/users/me`).
|
|
19
|
+
*/
|
|
20
|
+
export type AuthMode = 'developer' | 'dual' | 'session';
|
|
21
|
+
/**
|
|
22
|
+
* Internal HTTP client. Not exported from the SDK surface — the
|
|
23
|
+
* `Somewhere` facade owns a single Client instance and passes it to
|
|
24
|
+
* every resource. Handles auth mode resolution, envelope unwrapping,
|
|
25
|
+
* typed error materialization, binary round-trips, and the `safeCall`
|
|
26
|
+
* helper that converts `call` into a `Result<T>` envelope for the
|
|
27
|
+
* result-envelope surfaces.
|
|
28
|
+
*/
|
|
29
|
+
export declare class Client {
|
|
30
|
+
readonly baseUrl: string;
|
|
31
|
+
/** The project's own URL (functions host), if known. See SomewhereOptions.functionsUrl. */
|
|
32
|
+
readonly functionsUrl?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Session transport for `auth.*` (tsk_0de555b1). 'cookie' = httpOnly cookie
|
|
35
|
+
* sessions via the app's own backend routes — the browser default, because
|
|
36
|
+
* localStorage tokens are XSS-exfiltratable and httpOnly cookies aren't.
|
|
37
|
+
* 'header' = Bearer tokens in SDK memory — the default outside browsers
|
|
38
|
+
* (Node/CLI/native have no httpOnly cookie jar) and the manual/advanced mode.
|
|
39
|
+
*/
|
|
40
|
+
readonly authMode: 'cookie' | 'header';
|
|
41
|
+
/** Path the app's backend auth routes are mounted at (cookie mode). */
|
|
42
|
+
readonly authPath: string;
|
|
43
|
+
defaultProjectId?: string;
|
|
44
|
+
private readonly initialAuthHeader;
|
|
45
|
+
/** Credential supplied at construction, or none for the browser cookie path. */
|
|
46
|
+
private readonly initialAuthKind;
|
|
47
|
+
/**
|
|
48
|
+
* Set by `auth.signInWithPassword` / `auth.signUp` on success.
|
|
49
|
+
* Cleared by `auth.signOut`. Used by `dual` and `session` auth modes;
|
|
50
|
+
* NEVER overrides `developer` mode (developer-only endpoints always
|
|
51
|
+
* use the initial `smt_` key — the server rejects JWTs on them).
|
|
52
|
+
*/
|
|
53
|
+
private sessionAuthHeader;
|
|
54
|
+
private readonly fetchImpl;
|
|
55
|
+
private readonly extraHeaders;
|
|
56
|
+
/** Surfaces already warned about. Direct browser database and file API calls are disabled;
|
|
57
|
+
* each surface warns once. */
|
|
58
|
+
private readonly browserDataWarnings;
|
|
59
|
+
/**
|
|
60
|
+
* Instance-scoped query cache for `from().select()`, or `null` when the
|
|
61
|
+
* caller passed `{ cache: false }`. Consulted by the PostgrestFilterBuilder
|
|
62
|
+
* executor. Explicit session transitions clear cached and pending reads.
|
|
63
|
+
*/
|
|
64
|
+
readonly cache: QueryCache | null;
|
|
65
|
+
constructor(opts: SomewhereOptions);
|
|
66
|
+
/**
|
|
67
|
+
* Drop cached `from().select()` reads for a table. Invoked automatically
|
|
68
|
+
* after a write to the table (read-your-own-writes); also the public seam
|
|
69
|
+
* for event-driven invalidation. No-op when the cache is disabled.
|
|
70
|
+
*/
|
|
71
|
+
invalidateTable(table: string): void;
|
|
72
|
+
/** True when the client was constructed with a developer `smt_` key. */
|
|
73
|
+
get hasDeveloperKey(): boolean;
|
|
74
|
+
/** True when a user session is currently active. */
|
|
75
|
+
get hasSession(): boolean;
|
|
76
|
+
resolveProjectId(explicit?: string): string | undefined;
|
|
77
|
+
requireProjectId(explicit?: string, what?: string): string;
|
|
78
|
+
setSessionToken(accessToken: string): void;
|
|
79
|
+
clearSession(): void;
|
|
80
|
+
/**
|
|
81
|
+
* The `Authorization` value a project-function call should carry: the
|
|
82
|
+
* active user session if signed in, else the construction key/token.
|
|
83
|
+
* Same precedence as `dual` mode.
|
|
84
|
+
*/
|
|
85
|
+
get sessionOrInitialBearer(): string;
|
|
86
|
+
/** Low-level fetch passthrough for absolute URLs (project function hosts). */
|
|
87
|
+
rawFetch(url: string, init: RequestInit): Promise<Response>;
|
|
88
|
+
private authHeader;
|
|
89
|
+
/** JSON request → JSON response. Unwraps `{ok, data}` → `data`, throws on error. */
|
|
90
|
+
call<T = unknown>(method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH', path: string, opts?: {
|
|
91
|
+
body?: unknown;
|
|
92
|
+
query?: Record<string, unknown>;
|
|
93
|
+
auth?: AuthMode;
|
|
94
|
+
signal?: AbortSignal;
|
|
95
|
+
/** Session credential for this request only; never installs client state. */
|
|
96
|
+
sessionBearer?: string;
|
|
97
|
+
}): Promise<T>;
|
|
98
|
+
/**
|
|
99
|
+
* Same as `call` but never throws — always returns a `Result<T>`.
|
|
100
|
+
* Used by result-envelope surfaces where the caller branches
|
|
101
|
+
* on `.error` instead of catching.
|
|
102
|
+
*/
|
|
103
|
+
safeCall<T>(method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH', path: string, opts?: {
|
|
104
|
+
body?: unknown;
|
|
105
|
+
query?: Record<string, unknown>;
|
|
106
|
+
auth?: AuthMode;
|
|
107
|
+
}): Promise<Result<T>>;
|
|
108
|
+
/** Raw binary download. */
|
|
109
|
+
getBytes(path: string, query?: Record<string, unknown>, auth?: AuthMode): Promise<{
|
|
110
|
+
body: ArrayBuffer;
|
|
111
|
+
contentType: string;
|
|
112
|
+
}>;
|
|
113
|
+
/** Raw binary upload. */
|
|
114
|
+
putBytes<T = unknown>(path: string, body: BodyInit, contentType: string, auth?: AuthMode): Promise<T>;
|
|
115
|
+
/**
|
|
116
|
+
* Direct browser calls to the platform's database and file APIs are
|
|
117
|
+
* disabled; browser code uses declared data/file collections or a server
|
|
118
|
+
* function. This one-time warning says so. It does not block or alter the
|
|
119
|
+
* request: the server decides, and the caller gets that answer as a normal
|
|
120
|
+
* Result. Server-side use of these APIs is unaffected.
|
|
121
|
+
*/
|
|
122
|
+
private warnOnDirectBrowserDataAccess;
|
|
123
|
+
private buildUrl;
|
|
124
|
+
private parseJson;
|
|
125
|
+
private unwrap;
|
|
126
|
+
private toError;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface SomewhereErrorInit {
|
|
2
|
+
code: string;
|
|
3
|
+
message: string;
|
|
4
|
+
statusCode: number;
|
|
5
|
+
retry: boolean;
|
|
6
|
+
retryAfterMs: number | null;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
}
|
|
9
|
+
export declare class SomewhereError extends Error {
|
|
10
|
+
readonly code: string;
|
|
11
|
+
readonly statusCode: number;
|
|
12
|
+
readonly retry: boolean;
|
|
13
|
+
readonly retryAfterMs: number | null;
|
|
14
|
+
readonly body: unknown;
|
|
15
|
+
constructor(init: SomewhereErrorInit);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBAEX,IAAI,EAAE,kBAAkB;CASrC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { AuthClient } from './resources/auth.js';
|
|
2
|
+
import { CallsClient } from './resources/calls.js';
|
|
3
|
+
import { ChatClient } from './resources/chat.js';
|
|
4
|
+
import { DbClient } from './resources/db.js';
|
|
5
|
+
import { EmailsClient } from './resources/emails.js';
|
|
6
|
+
import { FsClient } from './resources/fs.js';
|
|
7
|
+
import { FunctionsClient } from './resources/functions.js';
|
|
8
|
+
import { InboxClient } from './resources/inbox.js';
|
|
9
|
+
import { PaymentsClient } from './resources/payments.js';
|
|
10
|
+
import { SomewhereQueryBuilder } from './resources/postgrest.js';
|
|
11
|
+
import type { Result } from './types.js';
|
|
12
|
+
import { StorageClient } from './resources/storage.js';
|
|
13
|
+
import { TasksClient } from './resources/tasks.js';
|
|
14
|
+
import { ProjectsClient } from './resources/projects.js';
|
|
15
|
+
import { VideoClient } from './resources/video.js';
|
|
16
|
+
import type { CreateClientOptions, SomewhereOptions } from './types.js';
|
|
17
|
+
export { SomewhereError } from './errors.js';
|
|
18
|
+
export type { SomewhereErrorInit } from './errors.js';
|
|
19
|
+
export type * from './types.js';
|
|
20
|
+
export type { UploadOptions } from './resources/storage.js';
|
|
21
|
+
export { PostgrestFilterBuilder, SomewhereQueryBuilder } from './resources/postgrest.js';
|
|
22
|
+
export type { CountMode } from './resources/postgrest.js';
|
|
23
|
+
export { QueryCache } from './query-cache.js';
|
|
24
|
+
export type { CacheOptions } from './query-cache.js';
|
|
25
|
+
export { StorageClient, StorageFileApi } from './resources/storage.js';
|
|
26
|
+
export { AuthClient } from './resources/auth.js';
|
|
27
|
+
export { DbClient } from './resources/db.js';
|
|
28
|
+
export { EmailsClient } from './resources/emails.js';
|
|
29
|
+
export { FsClient } from './resources/fs.js';
|
|
30
|
+
export { FunctionsClient } from './resources/functions.js';
|
|
31
|
+
export { ChatClient, ChatCompletionsClient } from './resources/chat.js';
|
|
32
|
+
export { PaymentsClient } from './resources/payments.js';
|
|
33
|
+
export { VideoClient } from './resources/video.js';
|
|
34
|
+
export { InboxClient, InboxAddressesClient, InboxMessagesClient } from './resources/inbox.js';
|
|
35
|
+
export { CallsClient } from './resources/calls.js';
|
|
36
|
+
export { TasksClient } from './resources/tasks.js';
|
|
37
|
+
export type { Task, CreateTaskInput, UpdateTaskInput, TaskListOptions } from './resources/tasks.js';
|
|
38
|
+
export { ProjectsClient } from './resources/projects.js';
|
|
39
|
+
export type { ProjectSeoMetadata, SeoMetadataItem, SeoStatus } from './resources/projects.js';
|
|
40
|
+
export type { AnalyticsConsentPolicy, ProjectUpdateInput, ProjectUpdateResult, ProjectAllowedOrigins } from './resources/projects.js';
|
|
41
|
+
export type { SomewhereOptions };
|
|
42
|
+
/**
|
|
43
|
+
* The somewhere.tech client for explicit server and non-browser access, plus
|
|
44
|
+
* browser auth and application-function conveniences:
|
|
45
|
+
*
|
|
46
|
+
* - `sw.db.query(sql, params)` — raw SQL
|
|
47
|
+
* - `sw.db.from(table)` / `sw.from(table)` — fluent query builder
|
|
48
|
+
* - `sw.fs.read(path)` / `sw.fs.write(path, body)` — raw filesystem
|
|
49
|
+
* - `sw.storage.from(bucket)` — prefix-oriented file API
|
|
50
|
+
* - `sw.auth` — application auth
|
|
51
|
+
* - `sw.emails.send(...)` — Resend email
|
|
52
|
+
* - `sw.inbox.messages.list(...)` — inbound email
|
|
53
|
+
* - `sw.chat.completions.create()` — OpenAI chat completions
|
|
54
|
+
* - `sw.payments.checkout(...)` — Stripe Connect (zero platform fee)
|
|
55
|
+
* - `sw.video.createUploadUrl()` — direct-upload video pipeline
|
|
56
|
+
* - `sw.calls.createSession()` — WebRTC SFU sessions
|
|
57
|
+
* - `sw.tasks.create(...)` — per-project ticketing
|
|
58
|
+
*
|
|
59
|
+
* import { Somewhere } from '@somewhere-cloud/sdk'
|
|
60
|
+
* const sw = new Somewhere({ key: process.env.SOMEWHERE_API_KEY, projectId: 'booking-app' })
|
|
61
|
+
*
|
|
62
|
+
* const { data } = await sw.from('users').select('*').eq('id', 1)
|
|
63
|
+
*/
|
|
64
|
+
export declare class Somewhere {
|
|
65
|
+
readonly auth: AuthClient;
|
|
66
|
+
readonly db: DbClient;
|
|
67
|
+
readonly fs: FsClient;
|
|
68
|
+
readonly storage: StorageClient;
|
|
69
|
+
readonly emails: EmailsClient;
|
|
70
|
+
readonly inbox: InboxClient;
|
|
71
|
+
readonly chat: ChatClient;
|
|
72
|
+
readonly payments: PaymentsClient;
|
|
73
|
+
readonly functions: FunctionsClient;
|
|
74
|
+
readonly video: VideoClient;
|
|
75
|
+
readonly calls: CallsClient;
|
|
76
|
+
readonly tasks: TasksClient;
|
|
77
|
+
readonly projects: ProjectsClient;
|
|
78
|
+
private readonly client;
|
|
79
|
+
constructor(opts: SomewhereOptions);
|
|
80
|
+
/** Fluent query builder entry point. Alias of `sw.db.from(table)`. */
|
|
81
|
+
from(table: string): SomewhereQueryBuilder;
|
|
82
|
+
/**
|
|
83
|
+
* Warm the client cache for a query ahead of need — hover-prefetch, route
|
|
84
|
+
* preload, "load the next page while they read this one". Just runs the
|
|
85
|
+
* query (populating the instance cache); a later identical `.select()`
|
|
86
|
+
* within the staleTime window is then served instantly from cache.
|
|
87
|
+
*
|
|
88
|
+
* sw.prefetch(sw.from('posts').select('*').eq('id', hoveredId))
|
|
89
|
+
* // …on click, this is a cache hit, no network round-trip:
|
|
90
|
+
* const { data } = await sw.from('posts').select('*').eq('id', hoveredId)
|
|
91
|
+
*
|
|
92
|
+
* No-op for cache effects when the client was created with `{ cache: false }`.
|
|
93
|
+
*/
|
|
94
|
+
prefetch<T = unknown>(query: PromiseLike<Result<T>>): Promise<Result<T>>;
|
|
95
|
+
/**
|
|
96
|
+
* Drop cached `from().select()` reads for a table. Read-your-own-writes is
|
|
97
|
+
* already automatic (writes self-invalidate); reach for this to invalidate
|
|
98
|
+
* by hand — e.g. from whatever tells your app a row changed:
|
|
99
|
+
*
|
|
100
|
+
* onRowChanged('posts', () => sw.invalidate('posts'))
|
|
101
|
+
*/
|
|
102
|
+
invalidate(table: string): void;
|
|
103
|
+
/**
|
|
104
|
+
* `rpc(name, args)` convenience method. On somewhere there are no SQL stored
|
|
105
|
+
* procedures — a "database function" is one of your deployed `api/<name>`
|
|
106
|
+
* functions. `rpc('foo', args)` therefore calls `POST {projectUrl}/api/foo`
|
|
107
|
+
* with `args` as the JSON body and returns `{ data, error }`. Identical to
|
|
108
|
+
* `functions.invoke(name, { body: args })`; provided so existing `rpc(...)`
|
|
109
|
+
* call sites port unchanged.
|
|
110
|
+
*/
|
|
111
|
+
rpc<T = unknown>(name: string, args?: Record<string, unknown>): Promise<Result<T>>;
|
|
112
|
+
}
|
|
113
|
+
export default Somewhere;
|
|
114
|
+
/**
|
|
115
|
+
* Derive the project id from a legacy `*.somewhere.tech` application URL's
|
|
116
|
+
* subdomain. Current `*.somewhere.site` URLs, custom domains, API hosts, and
|
|
117
|
+
* bare hosts return `undefined`; pass `projectId` explicitly for project
|
|
118
|
+
* resources. The seam is loud: an unresolved project id surfaces as a clear
|
|
119
|
+
* error on the first call that needs one.
|
|
120
|
+
*/
|
|
121
|
+
export declare function projectIdFromUrl(url: string): string | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* Create a somewhere.tech client from an application URL:
|
|
124
|
+
*
|
|
125
|
+
* import { createClient } from '@somewhere-cloud/sdk'
|
|
126
|
+
* const client = createClient('https://booking-app.somewhere.site', undefined, {
|
|
127
|
+
* projectId: 'booking-app',
|
|
128
|
+
* })
|
|
129
|
+
*
|
|
130
|
+
* await client.auth.signInWithPassword({ email, password })
|
|
131
|
+
* await client.functions.invoke('checkout', { body: { plan: 'pro' } })
|
|
132
|
+
*
|
|
133
|
+
* - `somewhereUrl` — your application's URL. Used as the `functions.invoke`
|
|
134
|
+
* host. Pass `{ projectId }` for current `*.somewhere.site` URLs and custom
|
|
135
|
+
* domains; automatic inference is retained for legacy `*.somewhere.tech`
|
|
136
|
+
* application URLs only.
|
|
137
|
+
* - `somewhereKey` — omit in a browser cookie app. For non-browser use, pass
|
|
138
|
+
* an app-user JWT or a developer `smt_` key
|
|
139
|
+
* (server-only). Detected by the `smt_` prefix.
|
|
140
|
+
*
|
|
141
|
+
* Database / auth / storage calls go to the platform REST base
|
|
142
|
+
* (`https://api.somewhere.cloud/v1`, override with `options.apiUrl`).
|
|
143
|
+
*/
|
|
144
|
+
export declare function createClient(somewhereUrl: string, somewhereKey?: string, options?: CreateClientOptions): Somewhere;
|
|
145
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Result } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Client-side query cache for the `from().select()` read path.
|
|
4
|
+
*
|
|
5
|
+
* Three jobs, all default-on (the founder's call — see
|
|
6
|
+
* `docs/platform-intelligence.md`):
|
|
7
|
+
*
|
|
8
|
+
* 1. **Request dedup / single-flight.** Two awaits of the same query while
|
|
9
|
+
* the first is still in flight share ONE network request within a generation.
|
|
10
|
+
* 2. **Short staleTime cache (~1s).** A repeat read within `staleTime` of the
|
|
11
|
+
* last fetch returns the prior result instead of refetching. 1s is the
|
|
12
|
+
* safety knob: own-writes invalidate (below), normal polling (>1s apart)
|
|
13
|
+
* stays fresh, only sub-second bursts coalesce.
|
|
14
|
+
* 3. **Invalidate-on-write.** A write to a table drops that table's cached
|
|
15
|
+
* reads so the next read is fresh (read-your-own-writes correctness).
|
|
16
|
+
*
|
|
17
|
+
* The cache is owned by a single `Client` instance. Session transitions
|
|
18
|
+
* clear its entries and detach pending reads from the next session.
|
|
19
|
+
*
|
|
20
|
+
* EVENT-INVALIDATION SEAM (future, not built here): a change event for a
|
|
21
|
+
* table should call {@link QueryCache.invalidate} for that table — the exact
|
|
22
|
+
* same path invalidate-on-write uses. That's the whole integration point.
|
|
23
|
+
*/
|
|
24
|
+
export interface CacheOptions {
|
|
25
|
+
/** Milliseconds a fetched read stays fresh before a refetch. Default 1000. */
|
|
26
|
+
staleTime?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare class QueryCache {
|
|
29
|
+
private readonly staleTime;
|
|
30
|
+
private readonly entries;
|
|
31
|
+
private readonly inFlight;
|
|
32
|
+
/**
|
|
33
|
+
* Per-table generation counter. Bumped on every invalidate so a fetch that
|
|
34
|
+
* was already in flight when its table got invalidated does NOT repopulate
|
|
35
|
+
* the cache with a pre-write value.
|
|
36
|
+
*/
|
|
37
|
+
private readonly generations;
|
|
38
|
+
private readonly now;
|
|
39
|
+
constructor(opts?: CacheOptions, now?: () => number);
|
|
40
|
+
/**
|
|
41
|
+
* Read-through with dedup + staleTime. `run` performs the actual network
|
|
42
|
+
* fetch and is invoked at most once per in-flight key and generation.
|
|
43
|
+
* `fresh` bypasses hits and dedup but still fences cache warming on invalidation.
|
|
44
|
+
*/
|
|
45
|
+
read(key: string, table: string, run: () => Promise<Result<unknown>>, fresh?: boolean): Promise<Result<unknown>>;
|
|
46
|
+
/**
|
|
47
|
+
* Store a current result directly. Reads that can overlap invalidation
|
|
48
|
+
* should use `read` so their cache warming is generation-checked.
|
|
49
|
+
*/
|
|
50
|
+
store(key: string, table: string, result: Result<unknown>): void;
|
|
51
|
+
/**
|
|
52
|
+
* Drop every cached read for a table. Called automatically after a write to
|
|
53
|
+
* that table (read-your-own-writes); also the public event/manual seam.
|
|
54
|
+
*/
|
|
55
|
+
invalidate(table: string): void;
|
|
56
|
+
/** Drop the entire cache and detach pending reads. */
|
|
57
|
+
clear(): void;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=query-cache.d.ts.map
|