@bounded-sh/core 0.0.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 +78 -0
- package/dist/client/config.d.ts +105 -0
- package/dist/client/field-values.d.ts +24 -0
- package/dist/client/functions.d.ts +34 -0
- package/dist/client/live-effects.d.ts +120 -0
- package/dist/client/live.d.ts +61 -0
- package/dist/client/operations.d.ts +264 -0
- package/dist/client/realtime-store.d.ts +89 -0
- package/dist/client/subscription-v2.d.ts +92 -0
- package/dist/client/subscription.d.ts +64 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +7807 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7726 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types.d.ts +157 -0
- package/dist/utils/api.d.ts +11 -0
- package/dist/utils/auth-api.d.ts +10 -0
- package/dist/utils/core-platform.d.ts +16 -0
- package/dist/utils/rn-session-manager.d.ts +84 -0
- package/dist/utils/server-session-manager.d.ts +35 -0
- package/dist/utils/session-manager.d.ts +31 -0
- package/dist/utils/sol/poof4b5pk1L9tmThvBmaABjcyjfhFGbMbQP5BXk2QZpDevnet-program.d.ts +2027 -0
- package/dist/utils/sol/poof4b5pk1L9tmThvBmaABjcyjfhFGbMbQP5BXk2QZpMainnet-program.d.ts +2027 -0
- package/dist/utils/sol/sol-utils.d.ts +40 -0
- package/dist/utils/sol/taro6CvKqwrYrDc16ufYgzQ2NZcyyVKStffbtudrhRuDevnet-program.d.ts +1161 -0
- package/dist/utils/utils.d.ts +41 -0
- package/dist/utils/web-session-manager.d.ts +20 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# @tarobase/core
|
|
2
|
+
|
|
3
|
+
Core functionality for Tarobase SDKs. This package provides the shared functionality used by both the web and server SDKs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @tarobase/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
This package is typically not used directly, but is instead used as a dependency by `@tarobase/web` and `@tarobase/server`. If you're building a browser application, use `@tarobase/web`. If you're building a server application, use `@tarobase/server`.
|
|
14
|
+
|
|
15
|
+
## API Reference
|
|
16
|
+
|
|
17
|
+
### Core Types
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
export interface ClientConfig {
|
|
21
|
+
appId: string;
|
|
22
|
+
apiUrl: string;
|
|
23
|
+
authMethod: string;
|
|
24
|
+
privyConfig?: any;
|
|
25
|
+
chain?: string;
|
|
26
|
+
useSessionStorage?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface AuthProvider {
|
|
30
|
+
login(): Promise<User | null>;
|
|
31
|
+
runTransaction(evmTransactionData?: EVMTransaction, solTransactionData?: SolTransaction, options?: SetOptions): Promise<TransactionResult>;
|
|
32
|
+
signMessage(message: string): Promise<string>;
|
|
33
|
+
restoreSession(): Promise<User | null>;
|
|
34
|
+
logout(): Promise<void>;
|
|
35
|
+
getNativeMethods(): Promise<any>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface User {
|
|
39
|
+
address: string;
|
|
40
|
+
provider: AuthProvider;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface GetManyResult {
|
|
44
|
+
path: string;
|
|
45
|
+
data: any | null;
|
|
46
|
+
error?: {
|
|
47
|
+
code: 'NOT_FOUND' | 'UNAUTHORIZED' | 'INVALID_PATH';
|
|
48
|
+
message: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Core Operations
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// Initialize the SDK
|
|
57
|
+
function configInit(newConfig: Partial<ClientConfig>, options?: SessionOptions): Promise<void>;
|
|
58
|
+
|
|
59
|
+
// Get the current configuration
|
|
60
|
+
function getConfig(): Promise<ClientConfig>;
|
|
61
|
+
|
|
62
|
+
// Data operations
|
|
63
|
+
function get(path: string): Promise<any>;
|
|
64
|
+
function getMany(paths: string[], options?: { bypassCache?: boolean }): Promise<GetManyResult[]>;
|
|
65
|
+
function set(path: string, data: any, options?: SetOptions): Promise<any>;
|
|
66
|
+
function setMany(paths: { [key: string]: any }, options?: SetOptions): Promise<any>;
|
|
67
|
+
function setFile(path: string, file: File, metadata?: any): Promise<any>;
|
|
68
|
+
function getFiles(path: string): Promise<any>;
|
|
69
|
+
function runQuery(queryString: string, variables?: any): Promise<any>;
|
|
70
|
+
function runQueryMany(queryString: string, variables?: any): Promise<any>;
|
|
71
|
+
|
|
72
|
+
// Subscription
|
|
73
|
+
function subscribe(path: string, options?: SubscriptionOptions): Promise<() => void>;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Contributing
|
|
77
|
+
|
|
78
|
+
Please see the main repository for contribution guidelines.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { AuthProvider } from '../types';
|
|
2
|
+
export interface ClientConfig {
|
|
3
|
+
name: string;
|
|
4
|
+
logoUrl: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
/** Auth method. 'email' = Bounded Better Auth human login (email OTP, inline) —
|
|
7
|
+
* the default for most apps. 'phantom' = connect a Solana wallet (Phantom), the
|
|
8
|
+
* recommended wallet option (yields a real @user.address). 'guest' = zero-config
|
|
9
|
+
* anonymous (device keypair). All coexist; an app can offer email login AND Phantom
|
|
10
|
+
* AND `signInAnonymously()` side by side. */
|
|
11
|
+
authMethod: 'none' | 'email' | 'guest' | 'wallet' | 'rainbowkit' | 'coinbase-smart-wallet' | 'onboard' | 'phantom' | 'mobile-wallet-adapter' | 'privy' | 'privy-expo';
|
|
12
|
+
wsApiUrl: string;
|
|
13
|
+
apiUrl: string;
|
|
14
|
+
/**
|
|
15
|
+
* Base URL of the Bounded Functions dispatcher (the imperative escape hatch).
|
|
16
|
+
* Optional and ADDITIVE — when unset, bounded.functions.invoke() throws a
|
|
17
|
+
* clear "functions not configured" error. Defaults to the staging dispatcher.
|
|
18
|
+
*/
|
|
19
|
+
functionsUrl?: string;
|
|
20
|
+
appId: string;
|
|
21
|
+
/** Wallet/SIWS issuer (wallet + guest providers sign challenges against this). */
|
|
22
|
+
authApiUrl: string;
|
|
23
|
+
/** Human-login issuer (Bounded Better Auth — email OTP). The 'email' provider
|
|
24
|
+
* calls {humanAuthApiUrl}/email + /verify. Defaults per network. */
|
|
25
|
+
humanAuthApiUrl?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Selects a Bounded backend preset. When set, the endpoint defaults
|
|
28
|
+
* (apiUrl/wsApiUrl/authApiUrl/functionsUrl) resolve to that network's Bounded
|
|
29
|
+
* services instead of the legacy defaults — so a Bounded app needs only
|
|
30
|
+
* `{ appId, network }`. Anything you pass explicitly still wins. Unset =
|
|
31
|
+
* legacy behavior (unchanged for existing apps).
|
|
32
|
+
*/
|
|
33
|
+
network?: 'bounded' | 'bounded-staging' | 'bounded-production';
|
|
34
|
+
chain: string;
|
|
35
|
+
rpcUrl: string;
|
|
36
|
+
skipBackendInit: boolean;
|
|
37
|
+
authProvider: AuthProvider | null;
|
|
38
|
+
isServer: boolean;
|
|
39
|
+
phantomConfig?: {
|
|
40
|
+
appId?: string;
|
|
41
|
+
providers?: Array<'injected' | 'google' | 'apple' | 'phantom' | 'deeplink'>;
|
|
42
|
+
redirectUrl?: string;
|
|
43
|
+
autoConnect?: boolean;
|
|
44
|
+
/** Theme for the login modal: 'light' or 'dark'. Defaults to 'dark'. */
|
|
45
|
+
theme?: 'light' | 'dark';
|
|
46
|
+
appName?: string;
|
|
47
|
+
appIcon?: string;
|
|
48
|
+
/** Custom title shown at the top of the login modal. */
|
|
49
|
+
modalTitle?: string;
|
|
50
|
+
/** Custom subtitle shown below the title in the login modal. */
|
|
51
|
+
modalSubtitle?: string;
|
|
52
|
+
/** When true, the Phantom login modal offers a Privy (email/social) fallback
|
|
53
|
+
* route, hot-swapping to the Privy provider on demand. Web only. */
|
|
54
|
+
enablePrivyFallback?: boolean;
|
|
55
|
+
};
|
|
56
|
+
/** Privy (web) configuration — the @privy-io/react-auth app id + its config
|
|
57
|
+
* object. Used when authMethod is 'privy' (a co-equal login route alongside
|
|
58
|
+
* email/phantom/guest). The Privy embedded/external Solana wallet signs the
|
|
59
|
+
* standard SIWS challenge, so the session is minted via the same wallet path
|
|
60
|
+
* as Phantom — no Privy-specific backend verification required. */
|
|
61
|
+
privyConfig?: {
|
|
62
|
+
appId: string;
|
|
63
|
+
config: any;
|
|
64
|
+
};
|
|
65
|
+
/** React Native (Expo) Privy provider instance, bridged from the host app's
|
|
66
|
+
* <PrivyProvider> tree via setPrivyMethods(). Required when authMethod is
|
|
67
|
+
* 'privy-expo' because @privy-io/expo is hook-based and must be rendered by
|
|
68
|
+
* the RN component tree (see PrivyExpoProvider). */
|
|
69
|
+
privyExpoProvider?: AuthProvider;
|
|
70
|
+
mobileWalletConfig?: {
|
|
71
|
+
appIdentity?: {
|
|
72
|
+
name?: string;
|
|
73
|
+
uri?: string;
|
|
74
|
+
icon?: string;
|
|
75
|
+
};
|
|
76
|
+
cluster?: string;
|
|
77
|
+
theme?: 'light' | 'dark';
|
|
78
|
+
};
|
|
79
|
+
mockAuth?: boolean;
|
|
80
|
+
}
|
|
81
|
+
export declare let clientConfig: ClientConfig;
|
|
82
|
+
type BoundedEndpoints = Pick<ClientConfig, 'wsApiUrl' | 'apiUrl' | 'authApiUrl' | 'humanAuthApiUrl' | 'functionsUrl'>;
|
|
83
|
+
export declare const BOUNDED_NETWORKS: Record<string, BoundedEndpoints>;
|
|
84
|
+
/**
|
|
85
|
+
* The hosted `/.well-known/bounded-webhook-keys.json` URL for the configured
|
|
86
|
+
* Bounded network, or `undefined` when no Bounded network is set. Used by
|
|
87
|
+
* `verifyWebhook` so a staging receiver that did `init({ network:
|
|
88
|
+
* 'bounded-staging' })` verifies against the STAGING signing keys instead of
|
|
89
|
+
* the production default. Synchronous and non-blocking on purpose: a pure
|
|
90
|
+
* webhook receiver may never call `init()`, so we read the already-applied
|
|
91
|
+
* config rather than awaiting `getConfig()` (which blocks on initialization).
|
|
92
|
+
* Returns `undefined` when the network is unknown so the caller keeps its
|
|
93
|
+
* fail-closed production default (audit SDK LOW-7).
|
|
94
|
+
*/
|
|
95
|
+
export declare function getWebhookKeysUrl(): string | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* True when init() configured a Bounded network (the Cloudflare-native stack).
|
|
98
|
+
* Synchronous + non-blocking. Used to route reads/writes that behave differently
|
|
99
|
+
* on Bounded vs the legacy Tarobase backend (e.g. `count`/`aggregate`, which on
|
|
100
|
+
* Bounded must use the deterministic server aggregation, not the legacy AI query).
|
|
101
|
+
*/
|
|
102
|
+
export declare function isBoundedNetwork(): boolean;
|
|
103
|
+
export declare function init(newConfig: Partial<ClientConfig>): Promise<void>;
|
|
104
|
+
export declare function getConfig(): Promise<ClientConfig>;
|
|
105
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** A server-resolved field operation. Pass as a field value in `set`/`setMany`. */
|
|
2
|
+
export type FieldOperation = {
|
|
3
|
+
operation: 'increment';
|
|
4
|
+
value: number;
|
|
5
|
+
} | {
|
|
6
|
+
operation: 'time';
|
|
7
|
+
value: 'now';
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Atomically add `value` to a numeric field when the write commits, server-side.
|
|
11
|
+
* Use a negative `value` to decrement. The field starts from 0 if the document
|
|
12
|
+
* (or field) does not exist yet. Concurrent increments are race-free.
|
|
13
|
+
*
|
|
14
|
+
* await set("counters/likes", { n: increment(1) });
|
|
15
|
+
* await set("scores/p1", { points: increment(-5) });
|
|
16
|
+
*/
|
|
17
|
+
export declare function increment(value: number): FieldOperation;
|
|
18
|
+
/**
|
|
19
|
+
* Stamp a field with the server's clock (Unix seconds) when the write commits —
|
|
20
|
+
* the trustworthy "when did this happen" you can't get from a client clock.
|
|
21
|
+
*
|
|
22
|
+
* await set("posts/p1", { createdAt: serverTimestamp() });
|
|
23
|
+
*/
|
|
24
|
+
export declare function serverTimestamp(): FieldOperation;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type InvokeOptions = {
|
|
2
|
+
/** Per-call timeout (ms) for the HTTP request to the dispatcher. */
|
|
3
|
+
timeoutMs?: number;
|
|
4
|
+
/** Extra headers (advanced/testing). */
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* @internal Auth override. The server `WalletClient.invoke` sets this so the
|
|
8
|
+
* call authenticates as that wallet's session instead of the ambient
|
|
9
|
+
* `BOUNDED_PRIVATE_KEY` keypair (which would otherwise throw when unset). App
|
|
10
|
+
* code never sets this.
|
|
11
|
+
*/
|
|
12
|
+
_overrides?: {
|
|
13
|
+
_getAuthHeaders?: () => Promise<Record<string, string>>;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare class FunctionInvokeError extends Error {
|
|
17
|
+
statusCode?: number | undefined;
|
|
18
|
+
details?: any | undefined;
|
|
19
|
+
constructor(message: string, statusCode?: number | undefined, details?: any | undefined);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Invoke a deployed Bounded Function by name. Returns the function's JSON.
|
|
23
|
+
*
|
|
24
|
+
* const res = await bounded.functions.invoke('syncStripe', { customerId });
|
|
25
|
+
*
|
|
26
|
+
* Throws FunctionInvokeError on 401 (not logged in / bad token), 403 (the
|
|
27
|
+
* function's auth policy rule denied this caller), 404 (unknown function),
|
|
28
|
+
* 503 (Workers for Platforms not configured), or any non-2xx / transport error.
|
|
29
|
+
*/
|
|
30
|
+
export declare function invoke<T = any>(name: string, args?: Record<string, any>, opts?: InvokeOptions): Promise<T>;
|
|
31
|
+
/** The `bounded.functions` namespace surface. */
|
|
32
|
+
export declare const functions: {
|
|
33
|
+
invoke: typeof invoke;
|
|
34
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An effect a tick may emit. Structured-clonable JSON ONLY — no functions/closures.
|
|
3
|
+
*
|
|
4
|
+
* `id` is your stable correlation/idempotency key (e.g. `"npc:7:turn-42"`). It is
|
|
5
|
+
* MANDATORY for charged kinds (ai/function/agent/onchain) so an in-sim retry of the
|
|
6
|
+
* SAME logical action reuses the SAME id and never double-charges. For the other
|
|
7
|
+
* kinds the platform assigns a deterministic `${tick}:${seq}` fallback.
|
|
8
|
+
*
|
|
9
|
+
* `onBehalfOf` runs the effect AS that player (their auth/rules downstream). It must
|
|
10
|
+
* be a player whose intent you processed in the SAME tick (no privilege escalation);
|
|
11
|
+
* omit it to run as the game's own service principal.
|
|
12
|
+
*/
|
|
13
|
+
export type Effect = {
|
|
14
|
+
kind: "ai";
|
|
15
|
+
id: string;
|
|
16
|
+
model: string;
|
|
17
|
+
input: unknown;
|
|
18
|
+
onBehalfOf?: string;
|
|
19
|
+
} | {
|
|
20
|
+
kind: "function";
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
args?: Record<string, unknown>;
|
|
24
|
+
onBehalfOf?: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "agent";
|
|
27
|
+
id: string;
|
|
28
|
+
agent: string;
|
|
29
|
+
message: unknown;
|
|
30
|
+
onBehalfOf?: string;
|
|
31
|
+
} | {
|
|
32
|
+
kind: "http";
|
|
33
|
+
id?: string;
|
|
34
|
+
url: string;
|
|
35
|
+
method?: string;
|
|
36
|
+
headers?: Record<string, string>;
|
|
37
|
+
body?: unknown;
|
|
38
|
+
/** Secret NAME(s) only — the value is injected host-side on egress, never in your code. */
|
|
39
|
+
secret?: string | string[];
|
|
40
|
+
onBehalfOf?: string;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "onchain";
|
|
43
|
+
id: string;
|
|
44
|
+
collection: string;
|
|
45
|
+
op: "set" | "delete";
|
|
46
|
+
data?: Record<string, unknown>;
|
|
47
|
+
onBehalfOf?: string;
|
|
48
|
+
/** Require the player to co-sign the transaction. */
|
|
49
|
+
cosign?: boolean;
|
|
50
|
+
} | {
|
|
51
|
+
kind: "data";
|
|
52
|
+
id?: string;
|
|
53
|
+
op: "set" | "delete";
|
|
54
|
+
path: string;
|
|
55
|
+
document?: Record<string, unknown>;
|
|
56
|
+
onBehalfOf?: string;
|
|
57
|
+
} | {
|
|
58
|
+
kind: "schedule";
|
|
59
|
+
id?: string;
|
|
60
|
+
name: string;
|
|
61
|
+
atMs?: number;
|
|
62
|
+
everyMs?: number;
|
|
63
|
+
};
|
|
64
|
+
export type EffectKind = Effect["kind"];
|
|
65
|
+
/** Reserved intent address an effect result arrives on. */
|
|
66
|
+
export declare const EFFECT_INTENT_ADDRESS: "@effect";
|
|
67
|
+
/**
|
|
68
|
+
* The result of an effect, re-entered into your tick as an intent on the reserved
|
|
69
|
+
* `@effect` address. Match `effectId` to the `id` you emitted; read `result` iff
|
|
70
|
+
* `ok`, else `error` (an enumerated code).
|
|
71
|
+
*/
|
|
72
|
+
export interface EffectResult<T = unknown> {
|
|
73
|
+
__effect: true;
|
|
74
|
+
effectId: string;
|
|
75
|
+
ok: boolean;
|
|
76
|
+
result?: T;
|
|
77
|
+
error?: string;
|
|
78
|
+
}
|
|
79
|
+
/** A per-tick input: a player intent, or an `@effect` result the platform re-injected. */
|
|
80
|
+
export interface LiveIntent {
|
|
81
|
+
address: string;
|
|
82
|
+
intent: unknown;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The tick may return the bare next state, OR `{ state, effects }` to also emit
|
|
86
|
+
* effects this tick. Use {@link withEffects} to build the wrapper unambiguously.
|
|
87
|
+
*/
|
|
88
|
+
export type LiveTickResult<S> = S | {
|
|
89
|
+
state: S;
|
|
90
|
+
effects?: Effect[];
|
|
91
|
+
};
|
|
92
|
+
/** A Bounded live module (game/realtime-room logic) that can emit effects. */
|
|
93
|
+
export interface LiveModule<S = unknown> {
|
|
94
|
+
init(seed: unknown): S;
|
|
95
|
+
tick(state: S, intents: LiveIntent[], dt: number): LiveTickResult<S>;
|
|
96
|
+
views?(state: S): Record<string, unknown>;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Build the `{ state, effects }` tick return. Always include this (even with an
|
|
100
|
+
* empty list) when you intend the wrapper, so the runtime never has to guess
|
|
101
|
+
* whether your state object happens to look like the wrapper.
|
|
102
|
+
*
|
|
103
|
+
* return withEffects(next, [{ kind: "ai", id: `npc:${id}:${next.turn}`, model, input }]);
|
|
104
|
+
*/
|
|
105
|
+
export declare function withEffects<S>(state: S, effects?: Effect[]): {
|
|
106
|
+
state: S;
|
|
107
|
+
effects: Effect[];
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Narrow an incoming intent to an effect result inside your tick:
|
|
111
|
+
*
|
|
112
|
+
* for (const i of intents) {
|
|
113
|
+
* if (i.address === EFFECT_INTENT_ADDRESS && isEffectResult(i.intent)) {
|
|
114
|
+
* applyResult(state, i.intent); // i.intent.effectId / .ok / .result / .error
|
|
115
|
+
* } else { applyPlayerIntent(state, i); }
|
|
116
|
+
* }
|
|
117
|
+
*/
|
|
118
|
+
export declare function isEffectResult<T = unknown>(intent: unknown): intent is EffectResult<T>;
|
|
119
|
+
/** Identity helper purely for type inference when authoring a module. */
|
|
120
|
+
export declare function defineLiveModule<S>(mod: LiveModule<S>): LiveModule<S>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type LiveIntentOptions = {
|
|
2
|
+
/** Per-call timeout (ms) for the HTTP request to the realtime worker. */
|
|
3
|
+
timeoutMs?: number;
|
|
4
|
+
/** Extra headers (advanced/testing). */
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* Fire-and-forget over the room socket without awaiting a server ack — lowest
|
|
8
|
+
* latency, but a rejection (auth/policy deny, room gone) is NOT surfaced. Use
|
|
9
|
+
* for high-frequency, idempotent input (movement/aim). Default (false): the
|
|
10
|
+
* intent rides the socket but AWAITS the ack, so a denial throws — important
|
|
11
|
+
* for join/ready/leave and any intent whose failure the player must know about.
|
|
12
|
+
*/
|
|
13
|
+
fireAndForget?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export declare class LiveIntentError extends Error {
|
|
16
|
+
statusCode?: number | undefined;
|
|
17
|
+
details?: any | undefined;
|
|
18
|
+
constructor(message: string, statusCode?: number | undefined, details?: any | undefined);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Send a player intent to a running live room. Returns `{ ok: true }`.
|
|
22
|
+
*
|
|
23
|
+
* await bounded.live.intent('rooms/abc', { type: 'move', dir: 'up' });
|
|
24
|
+
*
|
|
25
|
+
* `roomPath` is the document path of the room (e.g. `rooms/abc`). The worker
|
|
26
|
+
* derives the room from this path and reads `intent` as the opaque per-tick
|
|
27
|
+
* input. The caller's address is taken from the attached session token.
|
|
28
|
+
*
|
|
29
|
+
* Throws LiveIntentError on 401 (not logged in / bad token), 404 (room has no
|
|
30
|
+
* live module), 503 (live runtime/module unavailable), or any non-2xx /
|
|
31
|
+
* transport error / timeout.
|
|
32
|
+
*/
|
|
33
|
+
export declare function intent(roomPath: string, intent: unknown, opts?: LiveIntentOptions): Promise<{
|
|
34
|
+
ok: true;
|
|
35
|
+
}>;
|
|
36
|
+
export type SubscribeViewOptions = {
|
|
37
|
+
/** Address whose view to read. Defaults to the logged-in user's address. */
|
|
38
|
+
address?: string;
|
|
39
|
+
/** Called with the latest per-player view document. */
|
|
40
|
+
onData: (view: any) => void;
|
|
41
|
+
/** Called on subscription error. */
|
|
42
|
+
onError?: (error: any) => void;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Subscribe to YOUR per-player view of a room. Thin sugar over:
|
|
46
|
+
*
|
|
47
|
+
* subscribe('<roomPath>/view/<myAddress>', { onData, onError })
|
|
48
|
+
*
|
|
49
|
+
* The address defaults to the logged-in user's address (from the session
|
|
50
|
+
* token's claims); pass `opts.address` to override. Returns the unsubscribe
|
|
51
|
+
* function (a Promise<() => Promise<void>>, same as `subscribe`).
|
|
52
|
+
*
|
|
53
|
+
* Note: this is a browser-first helper (the WS subscription manager is
|
|
54
|
+
* browser-oriented). Server consumers should use `live.intent`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function subscribeView(roomPath: string, opts: SubscribeViewOptions): Promise<() => Promise<void>>;
|
|
57
|
+
/** The `bounded.live` namespace surface. */
|
|
58
|
+
export declare const live: {
|
|
59
|
+
intent: typeof intent;
|
|
60
|
+
subscribeView: typeof subscribeView;
|
|
61
|
+
};
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { AuthProvider } from '../types';
|
|
2
|
+
import { PublicKey, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
3
|
+
/** Internal overrides for per-request auth and headers. */
|
|
4
|
+
export type RequestOverrides = {
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
authProvider?: AuthProvider;
|
|
7
|
+
_getAuthHeaders?: () => Promise<Record<string, string>>;
|
|
8
|
+
_clearAuth?: () => Promise<void>;
|
|
9
|
+
_walletAddress?: string;
|
|
10
|
+
timeout?: number;
|
|
11
|
+
};
|
|
12
|
+
export type SetOptions = {
|
|
13
|
+
shouldSubmitTx?: boolean;
|
|
14
|
+
_overrides?: RequestOverrides;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Thrown when a user's wallet doesn't have enough SOL to cover the transaction.
|
|
18
|
+
* Apps can catch this to trigger an onramp/funding flow.
|
|
19
|
+
*/
|
|
20
|
+
export declare class InsufficientBalanceError extends Error {
|
|
21
|
+
address: string;
|
|
22
|
+
balanceLamports: number;
|
|
23
|
+
estimatedCostLamports: number;
|
|
24
|
+
deficitLamports: number;
|
|
25
|
+
deficitSol: number;
|
|
26
|
+
constructor(address: string, balanceLamports: number, estimatedCostLamports: number, deficitLamports: number, deficitSol: number);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Options for the get function.
|
|
30
|
+
*/
|
|
31
|
+
export type GetOptions = {
|
|
32
|
+
/**
|
|
33
|
+
* Structured MongoDB-style filter for collection reads, e.g.
|
|
34
|
+
* `{ status: "open", amount: { $gt: 10 } }`. Deterministic (no AI). Supported
|
|
35
|
+
* operators: $gt $gte $lt $lte $ne $in $nin $exists $regex ($options) $and $or
|
|
36
|
+
* $nor; a bare value means equality. Read rules still apply on top.
|
|
37
|
+
*/
|
|
38
|
+
filter?: Record<string, any>;
|
|
39
|
+
/** Sort spec for collection reads, e.g. `{ createdAt: -1 }` (1 = asc, -1 = desc). */
|
|
40
|
+
sort?: Record<string, number>;
|
|
41
|
+
/** Natural language prompt for AI-powered queries (collections only) */
|
|
42
|
+
prompt?: string | undefined;
|
|
43
|
+
/** Bypass the local cache and fetch fresh data */
|
|
44
|
+
bypassCache?: boolean;
|
|
45
|
+
/** Include documents from sub-paths (nested collections) */
|
|
46
|
+
includeSubPaths?: boolean;
|
|
47
|
+
/** Shape object for relationship resolution - specifies which related documents to include */
|
|
48
|
+
shape?: Record<string, any>;
|
|
49
|
+
/** Maximum number of items to return (opt-in pagination) */
|
|
50
|
+
limit?: number;
|
|
51
|
+
/** Opaque cursor for cursor-based pagination (used with limit) */
|
|
52
|
+
cursor?: string;
|
|
53
|
+
_overrides?: RequestOverrides;
|
|
54
|
+
};
|
|
55
|
+
export type RunQueryOptions = {
|
|
56
|
+
_overrides?: RequestOverrides;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Supported aggregate operations for count/aggregate queries.
|
|
60
|
+
*/
|
|
61
|
+
export type AggregateOperation = 'count' | 'uniqueCount' | 'sum' | 'avg' | 'min' | 'max';
|
|
62
|
+
/**
|
|
63
|
+
* Result of a count or aggregate query — always a single numeric value.
|
|
64
|
+
*/
|
|
65
|
+
export type AggregateResult = {
|
|
66
|
+
value: number;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Options for the count function.
|
|
70
|
+
*/
|
|
71
|
+
export type CountOptions = {
|
|
72
|
+
/** Natural language filter prompt (e.g., "posts created in the last 7 days"). Legacy backend only. */
|
|
73
|
+
prompt?: string;
|
|
74
|
+
/** Structured filter (same shape as `get`/`queryAggregate`). Preferred on Bounded. */
|
|
75
|
+
filter?: Record<string, any>;
|
|
76
|
+
_overrides?: RequestOverrides;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Options for the aggregate function.
|
|
80
|
+
*/
|
|
81
|
+
export type AggregateOptions = {
|
|
82
|
+
/** Natural language filter prompt. Legacy backend only. */
|
|
83
|
+
prompt?: string;
|
|
84
|
+
/** Structured filter (same shape as `get`/`queryAggregate`). Preferred on Bounded. */
|
|
85
|
+
filter?: Record<string, any>;
|
|
86
|
+
/** Field name to aggregate on (required for sum, avg, min, max) */
|
|
87
|
+
field?: string;
|
|
88
|
+
_overrides?: RequestOverrides;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Count items in a collection path. Returns a numeric result.
|
|
92
|
+
*
|
|
93
|
+
* This uses the AI query engine with a count-specific prompt prefix,
|
|
94
|
+
* so TaroBase will generate a $count aggregation pipeline and return
|
|
95
|
+
* just the count rather than full documents.
|
|
96
|
+
*
|
|
97
|
+
* IMPORTANT: This only works for collections where the read policy is "true".
|
|
98
|
+
* If the read policy requires per-document checks, the server will return
|
|
99
|
+
* an error because aggregate counts cannot be performed without pulling all
|
|
100
|
+
* documents for access control evaluation.
|
|
101
|
+
*
|
|
102
|
+
* @param path - Collection path (e.g., "posts", "users/abc/comments")
|
|
103
|
+
* @param opts - Optional filter prompt and overrides
|
|
104
|
+
* @returns AggregateResult with the count value
|
|
105
|
+
*/
|
|
106
|
+
export declare function count(path: string, opts?: CountOptions): Promise<AggregateResult>;
|
|
107
|
+
/**
|
|
108
|
+
* Run an aggregate operation on a collection path. Returns a numeric result.
|
|
109
|
+
*
|
|
110
|
+
* Supported operations:
|
|
111
|
+
* - count: Total number of documents
|
|
112
|
+
* - uniqueCount: Number of distinct values for a field
|
|
113
|
+
* - sum: Sum of a numeric field
|
|
114
|
+
* - avg: Average of a numeric field
|
|
115
|
+
* - min: Minimum value of a numeric field
|
|
116
|
+
* - max: Maximum value of a numeric field
|
|
117
|
+
*
|
|
118
|
+
* IMPORTANT: This only works for collections where the read policy is "true".
|
|
119
|
+
* If the read policy requires per-document checks, the server will return
|
|
120
|
+
* an error because aggregate operations cannot be performed without pulling
|
|
121
|
+
* all documents for access control evaluation.
|
|
122
|
+
*
|
|
123
|
+
* @param path - Collection path (e.g., "posts", "users/abc/comments")
|
|
124
|
+
* @param operation - The aggregate operation to perform
|
|
125
|
+
* @param opts - Options including optional filter prompt and field name
|
|
126
|
+
* @returns AggregateResult with the computed numeric value
|
|
127
|
+
*/
|
|
128
|
+
export declare function aggregate(path: string, operation: AggregateOperation, opts?: AggregateOptions): Promise<AggregateResult>;
|
|
129
|
+
/**
|
|
130
|
+
* Structured aggregation spec — group rows and compute count/sum/avg/min/max.
|
|
131
|
+
* Unlike `aggregate` (a single scalar via AI prompt), this runs deterministically
|
|
132
|
+
* server-side and can return MULTIPLE grouped rows.
|
|
133
|
+
*/
|
|
134
|
+
export type AggregateSpec = {
|
|
135
|
+
/** Group rows by these field values (omit for a single overall row). */
|
|
136
|
+
groupBy?: string[];
|
|
137
|
+
/** Include the document count per group. */
|
|
138
|
+
count?: boolean;
|
|
139
|
+
/** Sum these numeric fields per group. */
|
|
140
|
+
sum?: string[];
|
|
141
|
+
/** Average these numeric fields per group. */
|
|
142
|
+
avg?: string[];
|
|
143
|
+
/** Minimum of these fields per group. */
|
|
144
|
+
min?: string[];
|
|
145
|
+
/** Maximum of these fields per group. */
|
|
146
|
+
max?: string[];
|
|
147
|
+
};
|
|
148
|
+
/** One row of a `queryAggregate` result. */
|
|
149
|
+
export type AggregateRow = {
|
|
150
|
+
group?: Record<string, any>;
|
|
151
|
+
count?: number;
|
|
152
|
+
sum?: Record<string, number>;
|
|
153
|
+
avg?: Record<string, number | null>;
|
|
154
|
+
min?: Record<string, any>;
|
|
155
|
+
max?: Record<string, any>;
|
|
156
|
+
};
|
|
157
|
+
/** Options for `queryAggregate`. */
|
|
158
|
+
export type QueryAggregateOptions = {
|
|
159
|
+
/** Structured MongoDB-style filter applied before grouping (same shape as GetOptions.filter). */
|
|
160
|
+
filter?: Record<string, any>;
|
|
161
|
+
_overrides?: RequestOverrides;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Structured, grouped aggregation over a collection. Returns one row per group
|
|
165
|
+
* (or a single row when `spec.groupBy` is omitted). Read rules are enforced — the
|
|
166
|
+
* aggregation only sees documents the caller can read.
|
|
167
|
+
*
|
|
168
|
+
* ```ts
|
|
169
|
+
* const byCat = await queryAggregate("spend", { groupBy: ["category"], count: true, sum: ["amount"] });
|
|
170
|
+
* // [{ group: { category: "food" }, count: 2, sum: { amount: 70 } }, ...]
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export declare function queryAggregate(path: string, spec: AggregateSpec, opts?: QueryAggregateOptions): Promise<AggregateRow[]>;
|
|
174
|
+
/**
|
|
175
|
+
* Options for the full-text `search` function.
|
|
176
|
+
*/
|
|
177
|
+
export type SearchOptions = {
|
|
178
|
+
/** Restrict the match to these declared search fields (default: all indexed fields). */
|
|
179
|
+
fields?: string[];
|
|
180
|
+
/** Maximum number of matches to return. */
|
|
181
|
+
limit?: number;
|
|
182
|
+
/** Opaque pagination cursor from a prior page. */
|
|
183
|
+
cursor?: string;
|
|
184
|
+
_overrides?: RequestOverrides;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Full-text search a collection declared with `search: { fields: [...] }`.
|
|
188
|
+
*
|
|
189
|
+
* The match runs over the collection's indexed fields (or the subset passed in
|
|
190
|
+
* `opts.fields`) and respects each document's `read` rule — results the caller
|
|
191
|
+
* cannot read are omitted. Returns the matching documents (optionally paged via
|
|
192
|
+
* `opts.limit`/`opts.cursor`).
|
|
193
|
+
*
|
|
194
|
+
* @param path Collection path, e.g. "orgs/o1/docs"
|
|
195
|
+
* @param query Free-text query string (non-empty)
|
|
196
|
+
*/
|
|
197
|
+
export declare function search(path: string, query: string, opts?: SearchOptions): Promise<any>;
|
|
198
|
+
export declare function get(path: string, opts?: GetOptions): Promise<any>;
|
|
199
|
+
export type GetManyResult = {
|
|
200
|
+
path: string;
|
|
201
|
+
data: any | null;
|
|
202
|
+
error?: {
|
|
203
|
+
code: 'NOT_FOUND' | 'UNAUTHORIZED' | 'INVALID_PATH';
|
|
204
|
+
message: string;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
export declare function getMany(paths: string[], opts?: {
|
|
208
|
+
bypassCache?: boolean;
|
|
209
|
+
_overrides?: {
|
|
210
|
+
headers?: Record<string, string>;
|
|
211
|
+
};
|
|
212
|
+
}): Promise<GetManyResult[]>;
|
|
213
|
+
export type RunExpressionOptions = {
|
|
214
|
+
returnType?: 'Bool' | 'String' | 'Int' | 'UInt';
|
|
215
|
+
_overrides?: RequestOverrides;
|
|
216
|
+
};
|
|
217
|
+
export type RunExpressionResult = {
|
|
218
|
+
result: any;
|
|
219
|
+
trace?: {
|
|
220
|
+
variable: string;
|
|
221
|
+
resolvedValue: any;
|
|
222
|
+
operation?: string;
|
|
223
|
+
result?: any;
|
|
224
|
+
}[];
|
|
225
|
+
};
|
|
226
|
+
export declare function runQuery(absolutePath: string, queryName: string, queryArgs: any, opts?: RunQueryOptions): Promise<any>;
|
|
227
|
+
export declare function runQueryMany(many: {
|
|
228
|
+
absolutePath: string;
|
|
229
|
+
queryName: string;
|
|
230
|
+
queryArgs: any;
|
|
231
|
+
}[], opts?: RunQueryOptions): Promise<any>;
|
|
232
|
+
export declare function runExpression(expression: string, queryArgs: any, options?: RunExpressionOptions): Promise<RunExpressionResult>;
|
|
233
|
+
export declare function runExpressionMany(many: {
|
|
234
|
+
expression: string;
|
|
235
|
+
queryArgs: any;
|
|
236
|
+
returnType?: 'Bool' | 'String' | 'Int' | 'UInt';
|
|
237
|
+
_overrides?: RequestOverrides;
|
|
238
|
+
}[]): Promise<RunExpressionResult[]>;
|
|
239
|
+
export declare function set(path: string, document: any, options?: SetOptions): Promise<any>;
|
|
240
|
+
export declare function setMany(many: {
|
|
241
|
+
path: string;
|
|
242
|
+
document: any;
|
|
243
|
+
}[], options?: SetOptions): Promise<any>;
|
|
244
|
+
export declare function clearCache(path?: string, opts?: {
|
|
245
|
+
prompt?: string;
|
|
246
|
+
}): void;
|
|
247
|
+
/**
|
|
248
|
+
* SECURITY (H1): Wipe ALL HTTP read caches + in-flight reads. Call this whenever
|
|
249
|
+
* the logged-in identity changes (login / logout / switch identity) so a freshly
|
|
250
|
+
* authenticated principal can never observe data cached for the previous one.
|
|
251
|
+
* This is invoked from the WS auth-change path (reconnectWithNewAuthV2).
|
|
252
|
+
*/
|
|
253
|
+
export declare function clearReadCacheForAuthChange(): void;
|
|
254
|
+
export declare function getFiles(path: string, options?: {
|
|
255
|
+
_overrides?: RequestOverrides;
|
|
256
|
+
}): Promise<any>;
|
|
257
|
+
export declare function setFile(path: string, file: File | null, options?: {
|
|
258
|
+
_overrides?: RequestOverrides;
|
|
259
|
+
metadata?: Record<string, any>;
|
|
260
|
+
}): Promise<boolean>;
|
|
261
|
+
export declare function signMessage(message: string): Promise<string>;
|
|
262
|
+
export declare function signTransaction(transaction: Transaction | VersionedTransaction): Promise<Transaction | VersionedTransaction>;
|
|
263
|
+
export declare function signAndSubmitTransaction(transaction: Transaction | VersionedTransaction, feePayer?: PublicKey): Promise<string>;
|
|
264
|
+
export declare function syncItems(paths: string[], options?: SetOptions): Promise<any>;
|