palbase 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +2 -2
  3. package/dist/ai/index.js +17 -0
  4. package/dist/backend/engine.js +2 -0
  5. package/dist/backend/env.js +1 -0
  6. package/dist/backend/index.js +12 -0
  7. package/dist/backend/stack.js +1 -0
  8. package/dist/backend/test.js +2 -0
  9. package/dist/chunks/5W6XJM46.js +13 -0
  10. package/dist/chunks/6OPBXB7Z.js +2 -0
  11. package/dist/chunks/7LOMYBLN.js +20 -0
  12. package/dist/chunks/AN5LCF5K.js +55 -0
  13. package/dist/chunks/ECUYQ73P.js +2 -0
  14. package/dist/chunks/HDX6YUAB.js +2 -0
  15. package/dist/chunks/HVC2C35F.js +2 -0
  16. package/dist/chunks/I3JNX6MZ.js +4 -0
  17. package/dist/chunks/JEJ5CFTK.js +2 -0
  18. package/dist/chunks/K3C2IEDS.js +2 -0
  19. package/dist/chunks/KRBVYYME.js +2 -0
  20. package/dist/chunks/NIJHTHNF.js +2 -0
  21. package/dist/chunks/TL4H6V3P.js +2 -0
  22. package/dist/chunks/UTRQWCMD.js +6 -0
  23. package/dist/chunks/ZFPDYRRY.js +2 -0
  24. package/dist/cli.js +815 -0
  25. package/dist/refuse/ai.js +2 -0
  26. package/dist/refuse/backend.js +2 -0
  27. package/dist/refuse/server.js +2 -0
  28. package/dist/server/index.js +2 -0
  29. package/dist/server/testing.js +2 -0
  30. package/dist/web/index.js +2 -0
  31. package/dist/web/palbe.js +2 -0
  32. package/dist/web/paywall.js +2 -0
  33. package/dist/web/vite.js +3 -0
  34. package/package.json +111 -4
  35. package/types/ai/src/ai.d.ts +178 -0
  36. package/types/ai/src/index.d.ts +5 -0
  37. package/types/ai/src/partial.d.ts +1 -0
  38. package/types/ai/src/schema.d.ts +47 -0
  39. package/types/backend/src/bootstrap.d.ts +72 -0
  40. package/types/backend/src/cache.d.ts +32 -0
  41. package/types/backend/src/container.d.ts +49 -0
  42. package/types/backend/src/database.d.ts +148 -0
  43. package/types/backend/src/db-env.d.ts +4 -0
  44. package/types/backend/src/decorators.d.ts +293 -0
  45. package/types/backend/src/engine-db.d.ts +24 -0
  46. package/types/backend/src/engine-exports.d.ts +3 -0
  47. package/types/backend/src/engine.d.ts +124 -0
  48. package/types/backend/src/env.d.ts +27 -0
  49. package/types/backend/src/errors.d.ts +70 -0
  50. package/types/backend/src/i18n.d.ts +21 -0
  51. package/types/backend/src/index.d.ts +23 -0
  52. package/types/backend/src/openapi.d.ts +73 -0
  53. package/types/backend/src/platform-calls.d.ts +41 -0
  54. package/types/backend/src/requests.d.ts +81 -0
  55. package/types/backend/src/rooms.d.ts +168 -0
  56. package/types/backend/src/router.d.ts +22 -0
  57. package/types/backend/src/runtime.d.ts +56 -0
  58. package/types/backend/src/services.d.ts +262 -0
  59. package/types/backend/src/stack.d.ts +20 -0
  60. package/types/backend/src/strings-files.d.ts +3 -0
  61. package/types/backend/src/testing/index.d.ts +3 -0
  62. package/types/backend/src/testing/unit.d.ts +66 -0
  63. package/types/backend/src/upload.d.ts +125 -0
  64. package/types/backend/src/webhooks.d.ts +113 -0
  65. package/types/internal/src/event.d.ts +9 -0
  66. package/types/internal/src/modules/ai.d.ts +678 -0
  67. package/types/internal/src/modules/analytics.d.ts +1414 -0
  68. package/types/internal/src/modules/auth.d.ts +5660 -0
  69. package/types/internal/src/modules/cache.d.ts +158 -0
  70. package/types/internal/src/modules/events.d.ts +19 -0
  71. package/types/internal/src/modules/flags.d.ts +957 -0
  72. package/types/internal/src/modules/index.d.ts +13 -0
  73. package/types/internal/src/modules/machines.d.ts +1584 -0
  74. package/types/internal/src/modules/notify.d.ts +1450 -0
  75. package/types/internal/src/modules/purchases.d.ts +4113 -0
  76. package/types/internal/src/modules/realtime.d.ts +326 -0
  77. package/types/internal/src/modules/secrets.d.ts +275 -0
  78. package/types/internal/src/modules/storage.d.ts +691 -0
  79. package/types/internal/src/modules/stores.d.ts +1516 -0
  80. package/types/internal/src/retry.d.ts +14 -0
  81. package/types/internal/src/transport.d.ts +106 -0
  82. package/types/server/src/auth/dpop.d.ts +47 -0
  83. package/types/server/src/auth/jwt.d.ts +115 -0
  84. package/types/server/src/index.d.ts +9 -0
  85. package/types/server/src/pages.d.ts +4 -0
  86. package/types/server/src/purchases.d.ts +51 -0
  87. package/types/server/src/secrets-env.d.ts +22 -0
  88. package/types/server/src/server.d.ts +40 -0
  89. package/types/server/src/testing.d.ts +91 -0
  90. package/types/server/src/webhooks.d.ts +72 -0
  91. package/types/web/src/analytics.d.ts +87 -0
  92. package/types/web/src/auth.d.ts +155 -0
  93. package/types/web/src/backend-error.d.ts +38 -0
  94. package/types/web/src/backend-names.d.ts +25 -0
  95. package/types/web/src/backends.d.ts +84 -0
  96. package/types/web/src/client.d.ts +51 -0
  97. package/types/web/src/index.d.ts +13 -0
  98. package/types/web/src/palbe.d.ts +2 -0
  99. package/types/web/src/paywall/icons.d.ts +5 -0
  100. package/types/web/src/paywall/index.d.ts +5 -0
  101. package/types/web/src/paywall/placement.d.ts +85 -0
  102. package/types/web/src/paywall/prices.d.ts +40 -0
  103. package/types/web/src/paywall/render.d.ts +54 -0
  104. package/types/web/src/paywall/resolve.d.ts +149 -0
  105. package/types/web/src/purchases.d.ts +86 -0
  106. package/types/web/src/rooms.d.ts +61 -0
  107. package/types/web/src/session.d.ts +91 -0
  108. package/types/web/src/socket.d.ts +87 -0
  109. package/types/web/src/vite.d.ts +49 -0
@@ -0,0 +1,155 @@
1
+ import { auth as authModule } from '../../internal/src/modules/index.js';
2
+ import type { Transport } from '../../internal/src/transport.js';
3
+ import type { AuthEvent, Session, SessionManager } from './session.js';
4
+ type A = typeof authModule;
5
+ export type User = authModule.User;
6
+ export type SignupRequest = authModule.SignupRequest;
7
+ export type MfaFactor = authModule.MFARequiredResponse['factors'][number];
8
+ /** The part of navigator.credentials passkeys use. */
9
+ export interface CredentialsLike {
10
+ create(options: {
11
+ publicKey: PublicKeyCredentialCreationOptions;
12
+ }): Promise<unknown>;
13
+ get(options: {
14
+ publicKey: PublicKeyCredentialRequestOptions;
15
+ }): Promise<unknown>;
16
+ }
17
+ export type SignInResult = {
18
+ user: User;
19
+ mfaRequired?: undefined;
20
+ } | {
21
+ user?: undefined;
22
+ mfaRequired: {
23
+ mfaToken: string;
24
+ factors: MfaFactor[];
25
+ };
26
+ };
27
+ export declare class Auth {
28
+ /** Every client operation of the auth contract, through the session's transport. */
29
+ readonly api: ReturnType<A['client']>;
30
+ /**
31
+ * The same operations with the key alone. A flow that starts a session
32
+ * never carries the one already held: auth reads a bearer on a sign-in as
33
+ * "this user is here" — a social sign-in with one LINKS the new identity to
34
+ * that account — so whoever is signed in on this device must not ride along.
35
+ */
36
+ private open;
37
+ private session;
38
+ private credentials?;
39
+ readonly mfa: {
40
+ /** Completes a sign-in that asked for a second factor (TOTP, or a code sent by SMS or email). */
41
+ challenge: (mfaToken: string, type: 'totp' | 'sms' | 'email', code: string) => Promise<User>;
42
+ /** Completes it with one of the recovery codes instead. */
43
+ recovery: (mfaToken: string, code: string) => Promise<User>;
44
+ /** Sends the sign-in code by SMS; finish with challenge(mfaToken, 'sms', code). */
45
+ sendSmsCode: (mfaToken: string) => Promise<void>;
46
+ /** Sends the sign-in code by email; finish with challenge(mfaToken, 'email', code). */
47
+ sendEmailCode: (mfaToken: string) => Promise<void>;
48
+ /** Starts a TOTP factor: the secret for the authenticator app, and the recovery codes. */
49
+ enrollTotp: () => Promise<{
50
+ enrollmentId: string;
51
+ secret: string;
52
+ otpUrl: string;
53
+ qrCode: string;
54
+ recoveryCodes: string[];
55
+ }>;
56
+ /** Confirms the TOTP factor with a code the app shows. */
57
+ verifyTotp: (code: string) => Promise<void>;
58
+ enrollSms: (phone: string) => Promise<authModule.MFASMSEnrollResponse>;
59
+ verifySms: (code: string) => Promise<void>;
60
+ enrollEmail: () => Promise<void>;
61
+ factors: () => Promise<authModule.MFAFactorList>;
62
+ /** Removes a factor; the account's password confirms it. */
63
+ removeFactor: (id: string, currentPassword: string) => Promise<void>;
64
+ regenerateRecoveryCodes: () => Promise<authModule.MFARecoveryCodesResponse>;
65
+ };
66
+ readonly passkey: {
67
+ /** Adds a passkey to the signed-in user. */
68
+ register: (name?: string) => Promise<authModule.WebAuthnRegisteredCredential>;
69
+ /**
70
+ * Signs in with a passkey. With the user's id the authenticator is asked
71
+ * for that user's credentials; without it, for any passkey of the site
72
+ * (discoverable).
73
+ */
74
+ signIn: (opts?: {
75
+ userId?: string;
76
+ }) => Promise<User>;
77
+ /**
78
+ * Creates the account with a passkey and no password, then signs in with
79
+ * it (the sign-up answers no tokens). The identifier is the user's email.
80
+ */
81
+ signUp: (identifier: string, userName?: string) => Promise<User>;
82
+ list: () => Promise<authModule.WebAuthnCredentialList>;
83
+ remove: (id: string) => Promise<void>;
84
+ };
85
+ readonly magicLink: {
86
+ send: (email: string) => Promise<void>;
87
+ /** The token from the link the email carried. */
88
+ verify: (token: string) => Promise<User>;
89
+ };
90
+ readonly phone: {
91
+ sendCode: (phone: string) => Promise<authModule.PhoneOTPRequestResult>;
92
+ verifyCode: (phone: string, code: string) => Promise<SignInResult>;
93
+ };
94
+ readonly password: {
95
+ /** Sends the reset link; finish with confirmReset(token, newPassword). */
96
+ requestReset: (email: string) => Promise<void>;
97
+ confirmReset: (token: string, newPassword: string) => Promise<void>;
98
+ change: (body: authModule.PasswordChangeRequest) => Promise<authModule.SuccessResponse>;
99
+ set: (body: authModule.PasswordSetRequest) => Promise<authModule.SuccessResponse>;
100
+ };
101
+ readonly email: {
102
+ /** The token from the verification link, or the code with the address. */
103
+ verify: (body: authModule.VerifyEmailRequest) => Promise<void>;
104
+ resendVerification: (email: string) => Promise<authModule.ResendResult>;
105
+ };
106
+ readonly sessions: {
107
+ list: () => Promise<authModule.SessionList>;
108
+ revoke: (id: string) => Promise<void>;
109
+ revokeAll: () => Promise<void>;
110
+ };
111
+ constructor(transport: Transport, keyOnly: Transport, session: SessionManager, credentials?: CredentialsLike);
112
+ /** Listens to sign-in, refresh and sign-out; returns the unsubscribe. */
113
+ onAuthStateChange(listener: (event: AuthEvent, session: Session | null) => void): () => void;
114
+ /** The current session, or null when no one is signed in. */
115
+ currentSession(): Promise<Session | null>;
116
+ /** Creates the account. When the project signs new users in at once, the session starts too. */
117
+ signUp(body: SignupRequest): Promise<authModule.SignupResult>;
118
+ /** Email and password. A second factor, when the account has one, is asked for in mfaRequired. */
119
+ signIn(email: string, password: string): Promise<SignInResult>;
120
+ /** Ends the session here and on the server (a failed call still signs out locally). */
121
+ signOut(): Promise<void>;
122
+ /** The signed-in user's profile, read fresh. */
123
+ getUser(): Promise<authModule.MeProfile>;
124
+ /** Refreshes now rather than when the token is about to lapse. */
125
+ refreshSession(): Promise<Session>;
126
+ /**
127
+ * Deletes the account and ends the session. An account with a password
128
+ * gives it (`has_password` on getUser() says whether it has one): auth asks
129
+ * for it again, and answers 401 reauth_required when it is missing or
130
+ * wrong — the session is kept then. One without a password is deleted on
131
+ * the strength of its session.
132
+ */
133
+ deleteAccount(password?: string): Promise<void>;
134
+ private signInResult;
135
+ /**
136
+ * Starts the session from a token pair the app has itself — a flow it runs
137
+ * step by step (a passkey ceremony of its own, its begin and its finish), or
138
+ * a pair another of its pages was handed. The session held before is gone,
139
+ * and the user is read once.
140
+ */
141
+ setSession(pair: {
142
+ access_token: string;
143
+ refresh_token: string;
144
+ expires_in: number;
145
+ }): Promise<User>;
146
+ /** Starts the session from a token pair; the user is the answer's, or read once when it carries none. */
147
+ private signedIn;
148
+ private authenticator;
149
+ }
150
+ type Json = Record<string, unknown>;
151
+ export declare function creationOptions(pk: Json): PublicKeyCredentialCreationOptions;
152
+ export declare function requestOptions(pk: Json): PublicKeyCredentialRequestOptions;
153
+ export declare function attestationJSON(c: unknown): authModule.WebAuthnAttestationResponse;
154
+ export declare function assertionJSON(c: unknown): authModule.WebAuthnAssertionResponse;
155
+ export {};
@@ -0,0 +1,38 @@
1
+ import { PalbaseError } from '../../internal/src/transport.js';
2
+ export interface FieldError {
3
+ field: string;
4
+ message: string;
5
+ }
6
+ export type BackendErrorKind = 'validation' | 'unauthorized' | 'rateLimited' | 'server' | 'network' | 'decode';
7
+ interface BackendErrorParams {
8
+ code: string;
9
+ message: string;
10
+ status?: number;
11
+ requestId?: string;
12
+ fields?: FieldError[];
13
+ retryAfter?: number;
14
+ data?: unknown;
15
+ cause?: unknown;
16
+ }
17
+ export declare class BackendError extends Error {
18
+ readonly kind: BackendErrorKind;
19
+ readonly code: string;
20
+ readonly status: number;
21
+ readonly requestId?: string;
22
+ readonly fields?: FieldError[];
23
+ readonly retryAfter?: number;
24
+ readonly data?: unknown;
25
+ constructor(kind: BackendErrorKind, params: BackendErrorParams);
26
+ }
27
+ /**
28
+ * A BackendError, by class or by shape: two copies of the package loaded side
29
+ * by side make two classes, and `instanceof` fails for "the other" copy's.
30
+ */
31
+ export declare function isBackendError(e: unknown): e is BackendError;
32
+ /**
33
+ * The transport's refusal as a BackendError. Its body is the envelope as sent:
34
+ * `{ error, error_description, status, request_id, retry_after?, data? }`.
35
+ */
36
+ export declare function fromPalbaseError(err: PalbaseError): BackendError;
37
+ export declare function isPalbaseError(e: unknown): e is PalbaseError;
38
+ export {};
@@ -0,0 +1,25 @@
1
+ /** A name TypeScript takes bare: a property key unquoted, the client's member. */
2
+ export declare const IDENTIFIER: RegExp;
3
+ /**
4
+ * Names a backend cannot take on the client: what the client and the other
5
+ * platforms' clients already have, and what breaks an object. One list for
6
+ * every platform, so a name is refused at apps:sync and not on one of them.
7
+ */
8
+ export declare const RESERVED_CLIENT_NAMES: readonly string[];
9
+ /**
10
+ * A key no namespace tree holds, at any level: `then` (a thenable namespace
11
+ * makes `await` hang), `toJSON` (JSON.stringify calls it: logging
12
+ * `JSON.stringify(pb.api)` would make the call, with the user's token) and
13
+ * Object.prototype's members.
14
+ */
15
+ export declare function isReservedKey(key: string): boolean;
16
+ /** A key a backend's tree does not hold at its first level: `call` and `join`, the members every backend has (BackendBase), and the keys no level holds. */
17
+ export declare function isReservedTopLevelKey(key: string): boolean;
18
+ /** A backend's name on the client: an identifier, kept by neither the client, any platform's client nor Object.prototype. */
19
+ export declare function isClientName(name: unknown): name is string;
20
+ /** A machine's name on the platform, as storage takes it in an upload's address (/storage/upload/<machine>/…). */
21
+ export declare function isMachineName(name: unknown): name is string;
22
+ /** The machine's address, held to the transport's rule — https (http only on loopback), the origin alone; a TypeError says what is wrong. */
23
+ export declare function checkMachineUrl(url: string): void;
24
+ /** The origin of the project's address a client is made with (ClientOptions.url), held to the same rule. */
25
+ export declare function projectOrigin(url: string): string;
@@ -0,0 +1,84 @@
1
+ import type { Transport } from '../../internal/src/transport.js';
2
+ import { BackendError } from './backend-error.js';
3
+ import { type RoomDescriptor, type RoomEvent, type RoomHandle } from './rooms.js';
4
+ import type { RealtimeSocket } from './socket.js';
5
+ export interface CallOptions {
6
+ headers?: Record<string, string>;
7
+ signal?: AbortSignal;
8
+ }
9
+ /** How much of an upload's request has gone: `loaded` of its `total` bytes. */
10
+ export interface UploadProgress {
11
+ loaded: number;
12
+ total: number;
13
+ }
14
+ /**
15
+ * An upload's options. No headers: the call goes to storage, which hands the
16
+ * route the file and the input, never the request's headers.
17
+ */
18
+ export interface UploadOptions {
19
+ signal?: AbortSignal;
20
+ /** Told as the bytes go out — through XMLHttpRequest where the page has one — and once more when the answer is in. */
21
+ onProgress?: (progress: UploadProgress) => void;
22
+ }
23
+ export interface EndpointDescriptor {
24
+ method: string;
25
+ path: string;
26
+ /** `{name}` segments consumed as leading call args, in order. */
27
+ pathParams?: string[];
28
+ /**
29
+ * 'body' (default) | 'query' (the input serialized into the URL) | 'none'
30
+ * (no input arg — options come straight after the path params).
31
+ */
32
+ input?: 'body' | 'query' | 'none';
33
+ /** wire error code → lift fn; the call rethrows the lifted error. */
34
+ errors?: Record<string, (e: BackendError) => Error>;
35
+ /** The route answers `text/event-stream`: the call returns the frames, not one body. */
36
+ sse?: boolean;
37
+ /**
38
+ * The backend keeps the call's Idempotency-Key (its contract declares the
39
+ * header): sent again with the same key when the answer is "not now" or
40
+ * never came.
41
+ */
42
+ idempotent?: boolean;
43
+ /**
44
+ * The route is an `@Upload`: its call takes a file after its input, and
45
+ * goes to the project's storage, which has the machine authorize it, keeps
46
+ * the file and answers what the route's completion answered.
47
+ */
48
+ upload?: boolean;
49
+ }
50
+ export type NamespaceTree = {
51
+ [key: string]: NamespaceTree | EndpointDescriptor;
52
+ };
53
+ /** What every backend has besides its routes; a generated module's `Backend` extends it. */
54
+ export interface BackendBase {
55
+ /**
56
+ * POSTs `input` as the body to the route at `name` ('todos/create' or
57
+ * '/todos/create') and answers its JSON — v2's `pb.call`, for a route the
58
+ * generated types do not have.
59
+ */
60
+ call<O = unknown>(name: string, input?: unknown, options?: CallOptions): Promise<O>;
61
+ /**
62
+ * Joins a room the backend declared with `@Room` — `room` is the generated
63
+ * module's, `params` its pattern's `{param}` values: resolves once the
64
+ * backend let the user in, with the handle its events arrive on and its
65
+ * messages go through; rejects with a RoomError (its reason) when it did not.
66
+ *
67
+ * const room = await pb.api.join(AiSessionIdRoom, { sessionId });
68
+ * room.on('token', (t) => transcript.push(t.text));
69
+ * await room.send('say', { text: 'hello' });
70
+ * room.leave();
71
+ */
72
+ join<E extends RoomEvent, S, P extends readonly string[]>(room: RoomDescriptor<E, S, P>, params: Record<P[number], string>): Promise<RoomHandle<E, S>>;
73
+ }
74
+ /** What every client createClient makes inherits: one getter per registered backend name. */
75
+ export declare const clientBase: object;
76
+ /** Gives a client made by createClient its project's origin, its way to the machines, its project's transport (an upload's way, through storage) and its socket (a room's). */
77
+ export declare function bindMachines(client: object, project: string, machine: (url: string) => Transport, storage: Transport, socket: RealtimeSocket): void;
78
+ /**
79
+ * Registers a backend under `client` for the clients of `project` (the
80
+ * address createClient is given) — the machine `machine`, at `url` — called
81
+ * by its generated module, once, as it loads. The tree is checked whole here,
82
+ * so a broken one fails as the module loads, not at a call.
83
+ */
84
+ export declare function __registerBackend(project: string, client: string, machine: string, url: string, tree: NamespaceTree): void;
@@ -0,0 +1,51 @@
1
+ import { type Fetch, type Transport } from '../../internal/src/transport.js';
2
+ import { Auth, type CredentialsLike } from './auth.js';
3
+ import { type RetryPolicy } from '../../internal/src/retry.js';
4
+ import { type SessionStore } from './session.js';
5
+ import { RealtimeSocket } from './socket.js';
6
+ import { Analytics, type AnalyticsOptions } from './analytics.js';
7
+ import { Purchases } from './purchases.js';
8
+ export interface ClientOptions {
9
+ /** The project's address: https://<ref>.<domain> */
10
+ url: string;
11
+ /** The project's publishable key (pb_<ref>_c…). A secret key is refused: it never goes into an app. */
12
+ publishableKey: string;
13
+ /** Where the session is kept: localStorage in a browser, memory elsewhere, unless the app gives its own. */
14
+ storage?: SessionStore;
15
+ fetch?: Fetch;
16
+ webSocket?: typeof WebSocket;
17
+ /**
18
+ * What an upload that follows its progress is sent with (fetch tells
19
+ * nothing of a body as it goes): the page's XMLHttpRequest, unless the app
20
+ * gave its own fetch — then every request is that fetch's unless this is
21
+ * given too.
22
+ */
23
+ xmlHttpRequest?: typeof XMLHttpRequest;
24
+ /** Passkeys' authenticator: navigator.credentials in a browser. */
25
+ webauthn?: CredentialsLike;
26
+ retry?: RetryPolicy;
27
+ /**
28
+ * Starts what the browser tells of itself, as the app's analytics: page
29
+ * views, web vitals and request timings (true for all of them, or say which).
30
+ * Off unless given; events the app captures (`analytics.capture`) go either way.
31
+ */
32
+ analytics?: boolean | AnalyticsOptions;
33
+ }
34
+ /**
35
+ * The app's client. A backend's generated Palbe module (palbase apps:sync)
36
+ * gives every client of its project, made before or after the module loads,
37
+ * the backend under its name — `pb.api.rooms.create(…)`; its type is the
38
+ * module's `Backend`, and the app's file types its client `PalbaseClient & { api: Backend }`.
39
+ */
40
+ export interface PalbaseClient {
41
+ auth: Auth;
42
+ /** The project's realtime socket, opened on first use. */
43
+ socket: RealtimeSocket;
44
+ /** The transport every module call goes through (credentials, refresh, retries). */
45
+ transport: Transport;
46
+ /** The app's analytics: events it captures, page views, and — once started — the browser's own measures. */
47
+ analytics: Analytics;
48
+ /** What the signed-in customer has (live, onCustomerInfo), the paywall's catalog, and buying on the web. */
49
+ purchases: Purchases;
50
+ }
51
+ export declare function createClient(opts: ClientOptions): PalbaseClient;
@@ -0,0 +1,13 @@
1
+ export { createClient, type ClientOptions, type PalbaseClient } from './client.js';
2
+ export type { Auth, CredentialsLike, SignInResult, User } from './auth.js';
3
+ export { localStore, memoryStore, SessionChangedError, type AuthEvent, type Session, type SessionStore } from './session.js';
4
+ export { Channel, RealtimeSocket, type PushReply } from './socket.js';
5
+ export { Analytics, type AnalyticsOptions } from './analytics.js';
6
+ export { Purchases, type CustomerInfo, type CustomerInfoListener, type MergeGrant, type Offerings } from './purchases.js';
7
+ export type { Paywall, PaywallRenderOptions } from './paywall/placement.js';
8
+ export type { PaywallPackage, PaywallView } from './paywall/render.js';
9
+ export { PalbaseError } from '../../internal/src/transport.js';
10
+ export { BackendError, isBackendError, type BackendErrorKind, type FieldError } from './backend-error.js';
11
+ export type { BackendBase, CallOptions, UploadOptions, UploadProgress } from './backends.js';
12
+ export { RoomError, type RoomDescriptor, type RoomEvent, type RoomHandle, type RoomSubscription } from './rooms.js';
13
+ export type { RetryPolicy } from '../../internal/src/retry.js';
@@ -0,0 +1,2 @@
1
+ export { __registerBackend, type EndpointDescriptor, type NamespaceTree } from './backends.js';
2
+ export { isClientName, RESERVED_CLIENT_NAMES } from './backend-names.js';
@@ -0,0 +1,5 @@
1
+ export declare const ICONS: Readonly<Record<string, readonly string[]>>;
2
+ /** The close button's mark: not one of the schema's icons. */
3
+ export declare const CLOSE: string[];
4
+ /** An icon as an inline SVG, sized in CSS pixels and colored by its text color; hidden from assistive technology. */
5
+ export declare function icon(doc: Document, paths: readonly string[], size: number): SVGSVGElement;
@@ -0,0 +1,5 @@
1
+ export { PAYWALL_COMPONENTS, PAYWALL_SCHEMA, initialPackage, packagesOf, paywallLanguage, resolve as resolvePaywall, type Appearance, type PackageValues, type PaywallDefinition, type ResolveOptions, type ResolvedComponent, type ResolvedPaywall, type ResolvedTheme, } from './resolve.js';
2
+ export { renderPaywall, type PaywallHandlers, type PaywallInput, type PaywallPackage, type PaywallView } from './render.js';
3
+ export { formatPeriod, formatPrice, packageValues, parseDuration, type PricedPackage } from './prices.js';
4
+ export { ICONS as PAYWALL_ICONS } from './icons.js';
5
+ export { Paywall, defaultPaywall, type PaywallRenderOptions } from './placement.js';
@@ -0,0 +1,85 @@
1
+ import type { purchases as purchasesModule } from '../../../internal/src/modules/index.js';
2
+ import { type PricedPackage } from './prices.js';
3
+ import { type PaywallHandlers, type PaywallPackage, type PaywallView } from './render.js';
4
+ import { type Appearance, type PackageValues, type PaywallDefinition } from './resolve.js';
5
+ type Offerings = purchasesModule.Offerings;
6
+ type Api = ReturnType<typeof purchasesModule.client>;
7
+ export interface PaywallRenderOptions {
8
+ /** Stripe sends the customer back here after buying (one of the project's registered apps). */
9
+ successUrl: string;
10
+ /** … and here when they turn back. */
11
+ cancelUrl: string;
12
+ /** The system's, and kept with it as it changes, unless given. */
13
+ appearance?: Appearance;
14
+ /** The browser's language unless given. */
15
+ locale?: string;
16
+ /** The app's terms and privacy policy (https), for the definition's `terms` and `privacy` links. */
17
+ links?: {
18
+ terms?: string;
19
+ privacy?: string;
20
+ };
21
+ /** The close button; without one the paywall draws none. */
22
+ onClose?(): void;
23
+ /** A link the person opened; without one, the browser opens it in a new tab. */
24
+ onLink?(url: string): void;
25
+ /** Stripe Checkout's page for the package bought: the page goes there unless the app opens it itself. */
26
+ onCheckout?(url: string, pkg: PaywallPackage): void;
27
+ /** A purchase that could not start (no one signed in, a guest, the network). Without one it is thrown. */
28
+ onError?(error: unknown, pkg: PaywallPackage): void;
29
+ labels?: PaywallHandlers['labels'];
30
+ }
31
+ interface PaywallDeps {
32
+ checkout(opts: {
33
+ product: string;
34
+ plan: string;
35
+ successUrl: string;
36
+ cancelUrl: string;
37
+ }): Promise<string>;
38
+ expose(paywall: Paywall): Promise<void>;
39
+ }
40
+ /** What a placement shows: the paywall, where it came from, and what it sells. */
41
+ export declare class Paywall {
42
+ readonly placement: string;
43
+ /** The server's answer now, the copy kept from before when it could not be asked, or the SDK's own from the catalog (nothing published there). */
44
+ readonly source: 'server' | 'cache' | 'default';
45
+ readonly definition: PaywallDefinition;
46
+ /** What the paywall sells on the web, priced as the catalog prices it. */
47
+ readonly offerings: Offerings;
48
+ /** The paywall and the version shown, and the experiment's variant; absent for the SDK's own. */
49
+ readonly shown: {
50
+ paywallId: string;
51
+ version: number;
52
+ variant?: string;
53
+ } | undefined;
54
+ private deps;
55
+ private exposed;
56
+ constructor(placement: string, source: Paywall['source'], definition: PaywallDefinition, offerings: Offerings, shown: Paywall['shown'], deps: PaywallDeps);
57
+ /** The store's values of each package the paywall sells, in a language: what its texts' variables read. */
58
+ packages(locale: string): Record<string, PackageValues>;
59
+ /**
60
+ * Draws the paywall into a container and counts it shown — once, however
61
+ * often it is drawn. The purchase button opens Stripe Checkout for the
62
+ * package selected; the web has no restore button (a web purchase is the
63
+ * account's, wherever it signs in).
64
+ */
65
+ render(container: HTMLElement, opts: PaywallRenderOptions): PaywallView;
66
+ }
67
+ /** The packages the web sells of those named, priced as its catalog prices them. */
68
+ export declare function webPackages(offerings: Offerings, keys: readonly string[], locale: string): PricedPackage[];
69
+ /**
70
+ * The SDK's own paywall, where nothing is published: every plan the web
71
+ * sells (the first six), the purchase button with the selected one's price,
72
+ * and the legal links — plain, in the system's colors. Null when the web
73
+ * sells nothing.
74
+ */
75
+ export declare function defaultPaywall(offerings: Offerings): PaywallDefinition | null;
76
+ /** This browser's installation id: who a paywall is shown to before anyone signs in — the same experiment variant every time. */
77
+ export declare function installationId(ref: string): string;
78
+ /** The placement's paywall (see Purchases.paywall). */
79
+ export declare function loadPaywall(api: Api, ref: string, placement: string, checkout: (opts: {
80
+ product: string;
81
+ plan: string;
82
+ successUrl: string;
83
+ cancelUrl: string;
84
+ }) => Promise<string>, signal?: AbortSignal): Promise<Paywall | null>;
85
+ export {};
@@ -0,0 +1,40 @@
1
+ import type { PackageValues } from './resolve.js';
2
+ /** A package as a channel sells it: its product's name there, its price and, for a subscription, its period and trial. */
3
+ export interface PricedPackage {
4
+ /** `<product>.<plan>` */
5
+ key: string;
6
+ productName: string;
7
+ /** In the currency's minor units (999 is 9.99), as the catalog holds it. */
8
+ price: {
9
+ amount: number;
10
+ currency: string;
11
+ };
12
+ /** A subscription's billing period, ISO 8601 (P1M, P1Y …). */
13
+ period?: string;
14
+ /** An introductory offer; a free trial (mode free_trial) is the `{{trial}}` variable. */
15
+ intro?: {
16
+ mode: string;
17
+ duration: string;
18
+ };
19
+ }
20
+ interface Duration {
21
+ count: number;
22
+ unit: 'day' | 'week' | 'month' | 'year';
23
+ /** How many months it is, for a price per month. */
24
+ months: number;
25
+ }
26
+ /** P1Y, P3M, P1W, P7D — one unit, as the stores sell; null for anything else. */
27
+ export declare function parseDuration(iso: string | undefined): Duration | null;
28
+ /** An amount in minor units, in its currency as the language writes it. */
29
+ export declare function formatPrice(amount: number, currency: string, locale: string): string;
30
+ /** "month" for one, "3 months" for more — the language's own words (Intl's units). */
31
+ export declare function formatPeriod(d: Duration, locale: string): string;
32
+ /**
33
+ * The variables of each package, by key. `{{savings}}` is what a
34
+ * subscription saves a month against the dearest a month of the packages
35
+ * given in its currency (none for the dearest, nor below 1%); a package
36
+ * that is not a subscription has no `{{period}}`, `{{price_per_month}}` or
37
+ * `{{savings}}`, and one without a free trial no `{{trial}}`.
38
+ */
39
+ export declare function packageValues(packages: readonly PricedPackage[], locale: string): Record<string, PackageValues>;
40
+ export {};
@@ -0,0 +1,54 @@
1
+ import { type Appearance, type PackageValues, type PaywallDefinition } from './resolve.js';
2
+ /** What a paywall is drawn from: its definition, and the moment it is drawn in. */
3
+ export interface PaywallInput {
4
+ definition: PaywallDefinition;
5
+ /** The reader's language (`tr-TR`). */
6
+ locale: string;
7
+ appearance: Appearance;
8
+ /** The store's values of each package, by `<product>.<plan>`; a package without any is drawn, not sold. */
9
+ packages: Record<string, PackageValues>;
10
+ /** The app's own addresses of the definition's `terms` and `privacy` links (https); such a link is not drawn without one. */
11
+ links?: {
12
+ terms?: string;
13
+ privacy?: string;
14
+ };
15
+ }
16
+ /** A package of the catalog: what the purchase button buys. */
17
+ export interface PaywallPackage {
18
+ product: string;
19
+ plan: string;
20
+ }
21
+ export interface PaywallHandlers {
22
+ /** The purchase button, for the package selected; the button waits while a promise it returns runs. */
23
+ onPurchase(pkg: PaywallPackage): void | Promise<void>;
24
+ /** The restore button; without one the paywall draws none (the web restores nothing: Stripe's purchases are the account's). */
25
+ onRestore?(): void | Promise<void>;
26
+ /** The close button; without one the paywall draws none. */
27
+ onClose?(): void;
28
+ /** A link the person opened; without one, the browser opens it in a new tab. */
29
+ onLink?(url: string): void;
30
+ /** Told when the person picks another package. */
31
+ onSelect?(pkg: PaywallPackage): void;
32
+ /** The paywall's own words, which the definition does not hold: the app's, in its language. */
33
+ labels?: {
34
+ packages?: string;
35
+ close?: string;
36
+ restore?: string;
37
+ };
38
+ }
39
+ export interface PaywallView {
40
+ /** The package selected now. */
41
+ readonly selected: PaywallPackage | null;
42
+ /** Selects a package (`<product>.<plan>`) as the person would. */
43
+ select(key: string): void;
44
+ /** Draws it again from what changed: a new definition, the other appearance, another language, new prices. */
45
+ update(input: Partial<PaywallInput>): void;
46
+ /** Removes it from the page. */
47
+ destroy(): void;
48
+ }
49
+ /** An https address, with a host and no credentials: the only images and links a paywall shows. */
50
+ export declare function isHttps(s: unknown): s is string;
51
+ /** Black or white, whichever reads on a color: a badge's text. */
52
+ export declare function readableOn(hex: string): string;
53
+ /** Draws a paywall into a container (its content is replaced). */
54
+ export declare function renderPaywall(container: HTMLElement, input: PaywallInput, handlers: PaywallHandlers): PaywallView;