@bounded-sh/client 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/useQuery.d.ts +58 -0
- package/dist/{index-DyfiK3_X.esm.js → index-30RA_Bdf.esm.js} +268 -18
- package/dist/index-30RA_Bdf.esm.js.map +1 -0
- package/dist/{index-DJg-Dduo.esm.js → index-B9DtkVXb.esm.js} +2 -2
- package/dist/{index-DJg-Dduo.esm.js.map → index-B9DtkVXb.esm.js.map} +1 -1
- package/dist/{index-CYVVTWs4.js → index-CdqFc68L.js} +2 -2
- package/dist/{index-CYVVTWs4.js.map → index-CdqFc68L.js.map} +1 -1
- package/dist/{index-C2JpxGAC.js → index-CplhW55m.js} +2 -2
- package/dist/{index-C2JpxGAC.js.map → index-CplhW55m.js.map} +1 -1
- package/dist/{index-C2yvle9S.esm.js → index-DXdFMfDw.esm.js} +2 -2
- package/dist/{index-C2yvle9S.esm.js.map → index-DXdFMfDw.esm.js.map} +1 -1
- package/dist/{index-2UpSvA7V.js → index-ZYhdEVCA.js} +272 -17
- package/dist/index-ZYhdEVCA.js.map +1 -0
- package/dist/{index.browser-pymH6o1X.esm.js → index.browser-Cictefil.esm.js} +2 -2
- package/dist/{index.browser-pymH6o1X.esm.js.map → index.browser-Cictefil.esm.js.map} +1 -1
- package/dist/{index.browser-BTJZmhY1.js → index.browser-sADlt75X.js} +2 -2
- package/dist/{index.browser-BTJZmhY1.js.map → index.browser-sADlt75X.js.map} +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/{index.native-BTjBgNiE.esm.js → index.native-C8GJTcIy.esm.js} +204 -14
- package/dist/index.native-C8GJTcIy.esm.js.map +1 -0
- package/dist/{index.native-BvsmNFXn.js → index.native-DpYQ8GUh.js} +207 -13
- package/dist/index.native-DpYQ8GUh.js.map +1 -0
- package/dist/index.native.d.ts +1 -1
- package/dist/index.native.esm.js +1 -1
- package/dist/index.native.js +5 -1
- package/dist/index.native.js.map +1 -1
- package/dist/{phantom-wallet-provider-BXMvoOrI.js → phantom-wallet-provider-B8gezRxB.js} +3 -3
- package/dist/{phantom-wallet-provider-BXMvoOrI.js.map → phantom-wallet-provider-B8gezRxB.js.map} +1 -1
- package/dist/{phantom-wallet-provider-CTossIFB.esm.js → phantom-wallet-provider-FOSnYV4t.esm.js} +3 -3
- package/dist/{phantom-wallet-provider-CTossIFB.esm.js.map → phantom-wallet-provider-FOSnYV4t.esm.js.map} +1 -1
- package/dist/{privy-wallet-provider-1qE_f-DF.esm.js → privy-wallet-provider-BPOjNW9O.esm.js} +3 -3
- package/dist/{privy-wallet-provider-1qE_f-DF.esm.js.map → privy-wallet-provider-BPOjNW9O.esm.js.map} +1 -1
- package/dist/{privy-wallet-provider-D64DJ3u4.js → privy-wallet-provider-DfR-7xpE.js} +3 -3
- package/dist/{privy-wallet-provider-D64DJ3u4.js.map → privy-wallet-provider-DfR-7xpE.js.map} +1 -1
- package/dist/{solana-mobile-wallet-provider-C1wQ1DRK.js → solana-mobile-wallet-provider-CBAeRxGQ.js} +2 -2
- package/dist/{solana-mobile-wallet-provider-C1wQ1DRK.js.map → solana-mobile-wallet-provider-CBAeRxGQ.js.map} +1 -1
- package/dist/{solana-mobile-wallet-provider-9M8U6AA7.esm.js → solana-mobile-wallet-provider-CoS-38SL.esm.js} +2 -2
- package/dist/{solana-mobile-wallet-provider-9M8U6AA7.esm.js.map → solana-mobile-wallet-provider-CoS-38SL.esm.js.map} +1 -1
- package/package.json +2 -2
- package/dist/index-2UpSvA7V.js.map +0 -1
- package/dist/index-DyfiK3_X.esm.js.map +0 -1
- package/dist/index.native-BTjBgNiE.esm.js.map +0 -1
- package/dist/index.native-BvsmNFXn.js.map +0 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive realtime query hook — the ergonomic counterpart to the imperative
|
|
3
|
+
* `subscribe(path, { onData })`.
|
|
4
|
+
*
|
|
5
|
+
* `useQuery` subscribes for you and returns an **auto-updating value**, so you
|
|
6
|
+
* never write an `onData` callback (and never trip the classic trap of treating
|
|
7
|
+
* the *first* callback as the final state). `data` always holds the **full,
|
|
8
|
+
* current, read-rule-filtered** result the server last delivered — an array for
|
|
9
|
+
* a collection path, the document (or `null`) for a single-document path — and
|
|
10
|
+
* re-renders whenever ANY writer changes the matching set.
|
|
11
|
+
*
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const { data: rows, loading, error } = useQuery<Presence[]>(
|
|
14
|
+
* `rooms/${roomId}/presence`,
|
|
15
|
+
* { filter: { online: true } },
|
|
16
|
+
* );
|
|
17
|
+
* if (loading) return <Spinner/>;
|
|
18
|
+
* return <>{rows!.map(p => <Peer key={p.id} p={p}/>)}</>; // p.id = leaf doc key; shows EVERYONE, always
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Mirrors Convex's `useQuery`: there is no callback to get wrong, so a doc
|
|
22
|
+
* another client writes a moment later simply appears in `data` on the next
|
|
23
|
+
* render — there is no "missed cross-writer update".
|
|
24
|
+
*
|
|
25
|
+
* Pass `path = null`/`undefined` to skip subscribing (e.g. until an id is ready);
|
|
26
|
+
* `data` stays `undefined` and `loading` flips to `false`.
|
|
27
|
+
*/
|
|
28
|
+
export interface UseQueryOptions {
|
|
29
|
+
/** MongoDB-style filter, same shape as `get()`/`subscribe()`. */
|
|
30
|
+
filter?: Record<string, any>;
|
|
31
|
+
/** Server-side sort, e.g. `{ createdAt: -1 }`. */
|
|
32
|
+
sort?: Record<string, number>;
|
|
33
|
+
/** Natural-language filter (AI), evaluated server-side. */
|
|
34
|
+
prompt?: string;
|
|
35
|
+
/** Also walk nested sub-collections at the path. */
|
|
36
|
+
includeSubPaths?: boolean;
|
|
37
|
+
/** Expand relationship links on each delivered doc. */
|
|
38
|
+
shape?: Record<string, any>;
|
|
39
|
+
/** Cap how many docs the live feed tracks. */
|
|
40
|
+
limit?: number;
|
|
41
|
+
/** Pagination cursor. */
|
|
42
|
+
cursor?: string;
|
|
43
|
+
/** Explicit app id override (else the configured one). */
|
|
44
|
+
appId?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface UseQueryResult<T> {
|
|
47
|
+
/**
|
|
48
|
+
* The full current value the server delivered: an array of documents for a
|
|
49
|
+
* collection path, the document (or `null`) for a single-document path, and
|
|
50
|
+
* `undefined` before the first delivery (or when `path` is nullish).
|
|
51
|
+
*/
|
|
52
|
+
data: T | undefined;
|
|
53
|
+
/** `true` until the first delivery arrives. */
|
|
54
|
+
loading: boolean;
|
|
55
|
+
/** The last subscription error, or `null`. */
|
|
56
|
+
error: Error | null;
|
|
57
|
+
}
|
|
58
|
+
export declare function useQuery<T = any>(path: string | null | undefined, options?: UseQueryOptions): UseQueryResult<T>;
|
|
@@ -10632,6 +10632,87 @@ const pendingRequests = {};
|
|
|
10632
10632
|
const GET_CACHE_TTL = 500; // Adjust this value as needed (in milliseconds)
|
|
10633
10633
|
// Last time we cleaned up the cache
|
|
10634
10634
|
let lastCacheCleanup = Date.now();
|
|
10635
|
+
/**
|
|
10636
|
+
* Return the leaf document key (last path segment) for a document path.
|
|
10637
|
+
*
|
|
10638
|
+
* Bounded rows carry `_id` (and `pathId`) set to the FULL document path
|
|
10639
|
+
* (e.g. `"rooms/r1/prompts/8rd49se3sg"`). Apps that build a child path from a
|
|
10640
|
+
* row naturally want the bare doc key, not the whole path — using the full path
|
|
10641
|
+
* doubles it (`rooms/r1/prompts/rooms/r1/prompts/8rd.../votes/...`) → 403/404.
|
|
10642
|
+
* `docId` extracts that leaf key. Tolerates leading slashes and a trailing `*`.
|
|
10643
|
+
*
|
|
10644
|
+
* @example docId("rooms/r1/prompts/8rd49se3sg") // "8rd49se3sg"
|
|
10645
|
+
*/
|
|
10646
|
+
function docId(path) {
|
|
10647
|
+
if (typeof path !== 'string')
|
|
10648
|
+
return '';
|
|
10649
|
+
let p = path.startsWith('/') ? path.slice(1) : path;
|
|
10650
|
+
if (p.endsWith('*') && p.length > 1)
|
|
10651
|
+
p = p.slice(0, -1);
|
|
10652
|
+
if (p.endsWith('/'))
|
|
10653
|
+
p = p.slice(0, -1);
|
|
10654
|
+
const segments = p.split('/').filter(Boolean);
|
|
10655
|
+
return segments.length ? segments[segments.length - 1] : '';
|
|
10656
|
+
}
|
|
10657
|
+
/**
|
|
10658
|
+
* Additively attach a convenience bare `id` (the leaf doc key) to a returned row.
|
|
10659
|
+
*
|
|
10660
|
+
* Rows already carry `_id`/`pathId` = the full document path; this leaves those
|
|
10661
|
+
* untouched and adds `id` = the last path segment so `row.id` is the doc key apps
|
|
10662
|
+
* expect. No-ops for non-objects, arrays, and rows that already define `id`
|
|
10663
|
+
* (never clobber a user field named `id`). Source for the leaf is `_id` (falling
|
|
10664
|
+
* back to `pathId`/`relativePath`/`absolutePath`).
|
|
10665
|
+
*/
|
|
10666
|
+
function withBareId(row) {
|
|
10667
|
+
var _a, _b, _c;
|
|
10668
|
+
if (!row || typeof row !== 'object' || Array.isArray(row))
|
|
10669
|
+
return row;
|
|
10670
|
+
const r = row;
|
|
10671
|
+
if ('id' in r)
|
|
10672
|
+
return row; // don't clobber an explicit user field
|
|
10673
|
+
const source = (_c = (_b = (_a = r._id) !== null && _a !== void 0 ? _a : r.pathId) !== null && _b !== void 0 ? _b : r.relativePath) !== null && _c !== void 0 ? _c : r.absolutePath;
|
|
10674
|
+
if (typeof source !== 'string' || source.length === 0)
|
|
10675
|
+
return row;
|
|
10676
|
+
const leaf = docId(source);
|
|
10677
|
+
if (!leaf)
|
|
10678
|
+
return row;
|
|
10679
|
+
return Object.assign(Object.assign({}, r), { id: leaf });
|
|
10680
|
+
}
|
|
10681
|
+
/**
|
|
10682
|
+
* Normalize a raw read response from the worker into the SDK's stable shape and
|
|
10683
|
+
* attach the bare `id` to every returned row (Bug 1 + Bug 2).
|
|
10684
|
+
*
|
|
10685
|
+
* - Single-document path: returns EXACTLY ONE shape — the resolved document, or
|
|
10686
|
+
* `null` if missing (Firebase/Mongo convention). Unwraps the ambiguous
|
|
10687
|
+
* `{ data, status }` envelope the worker sometimes emits for a single doc so a
|
|
10688
|
+
* single-doc `get` never sometimes-returns the doc and sometimes the envelope.
|
|
10689
|
+
* - Collection path: preserves the `{ data, nextCursor, ... }` envelope and maps
|
|
10690
|
+
* the bare `id` onto each row in `data`.
|
|
10691
|
+
*/
|
|
10692
|
+
function normalizeReadResult(responseData, pathIsDocument) {
|
|
10693
|
+
if (pathIsDocument) {
|
|
10694
|
+
let doc = responseData;
|
|
10695
|
+
// Unwrap the single-doc envelope `{ data, status }` (Bug 2). A real document
|
|
10696
|
+
// never has the exact shape `{ data, status }` with nothing else meaningful,
|
|
10697
|
+
// so detect the envelope by `data` being present alongside a numeric `status`.
|
|
10698
|
+
if (doc && typeof doc === 'object' && !Array.isArray(doc) &&
|
|
10699
|
+
'data' in doc && 'status' in doc && typeof doc.status === 'number') {
|
|
10700
|
+
doc = doc.data;
|
|
10701
|
+
}
|
|
10702
|
+
if (doc === undefined || doc === null)
|
|
10703
|
+
return null;
|
|
10704
|
+
return withBareId(doc);
|
|
10705
|
+
}
|
|
10706
|
+
// Collection read. The worker body is `{ data: rows[], nextCursor?, status? }`.
|
|
10707
|
+
if (responseData && typeof responseData === 'object' && !Array.isArray(responseData) && Array.isArray(responseData.data)) {
|
|
10708
|
+
return Object.assign(Object.assign({}, responseData), { data: responseData.data.map((row) => withBareId(row)) });
|
|
10709
|
+
}
|
|
10710
|
+
// Some paths return a bare array of rows — map id onto each.
|
|
10711
|
+
if (Array.isArray(responseData)) {
|
|
10712
|
+
return responseData.map((row) => withBareId(row));
|
|
10713
|
+
}
|
|
10714
|
+
return responseData;
|
|
10715
|
+
}
|
|
10635
10716
|
function hashForKey$1(value) {
|
|
10636
10717
|
let h = 5381;
|
|
10637
10718
|
for (let i = 0; i < value.length; i++) {
|
|
@@ -11056,7 +11137,7 @@ async function get(path, opts = {}) {
|
|
|
11056
11137
|
if (hasActiveConnection()) {
|
|
11057
11138
|
if (pathIsDocument) {
|
|
11058
11139
|
const wsResult = await wsGet(normalizedPath);
|
|
11059
|
-
const responseData = wsResult;
|
|
11140
|
+
const responseData = normalizeReadResult(wsResult, true);
|
|
11060
11141
|
if (!opts.bypassCache) {
|
|
11061
11142
|
getCache[cacheKey] = { data: responseData, expiresAt: now + GET_CACHE_TTL };
|
|
11062
11143
|
}
|
|
@@ -11068,7 +11149,7 @@ async function get(path, opts = {}) {
|
|
|
11068
11149
|
sort: undefined,
|
|
11069
11150
|
includeSubPaths: opts.includeSubPaths,
|
|
11070
11151
|
});
|
|
11071
|
-
const responseData = wsResult;
|
|
11152
|
+
const responseData = normalizeReadResult(wsResult, false);
|
|
11072
11153
|
if (!opts.bypassCache) {
|
|
11073
11154
|
getCache[cacheKey] = { data: responseData, expiresAt: now + GET_CACHE_TTL };
|
|
11074
11155
|
}
|
|
@@ -11099,7 +11180,11 @@ async function get(path, opts = {}) {
|
|
|
11099
11180
|
const apiPath = `items?path=${path}${promptQueryParam}${filterParam}${sortParam}${includeSubPathsParam}${shapeParam}${limitParam}${cursorParam}`;
|
|
11100
11181
|
response = await makeApiRequest('GET', apiPath, null, opts._overrides);
|
|
11101
11182
|
}
|
|
11102
|
-
|
|
11183
|
+
// Normalize the worker's raw body into the SDK's stable shape:
|
|
11184
|
+
// - single-doc path → the resolved document or null (Bug 2), and
|
|
11185
|
+
// - collection path → `{ data, nextCursor }` preserved,
|
|
11186
|
+
// with the bare `id` (leaf doc key) attached to every returned row (Bug 1).
|
|
11187
|
+
const responseData = normalizeReadResult(response.data, pathIsDocument);
|
|
11103
11188
|
// Cache the response (unless bypassing cache)
|
|
11104
11189
|
if (!opts.bypassCache) {
|
|
11105
11190
|
getCache[cacheKey] = {
|
|
@@ -11197,11 +11282,16 @@ async function getMany(paths, opts = {}) {
|
|
|
11197
11282
|
const normalizedPath = uncachedPaths[i];
|
|
11198
11283
|
const serverResult = serverResultsMap.get(normalizedPath);
|
|
11199
11284
|
if (serverResult) {
|
|
11200
|
-
|
|
11201
|
-
|
|
11285
|
+
// getMany batches single-doc paths — attach the bare `id` (leaf doc
|
|
11286
|
+
// key) to each returned doc, additive (Bug 1), matching get().
|
|
11287
|
+
const normalizedResult = serverResult.error
|
|
11288
|
+
? serverResult
|
|
11289
|
+
: Object.assign(Object.assign({}, serverResult), { data: withBareId(serverResult.data) });
|
|
11290
|
+
results[originalIndex] = normalizedResult;
|
|
11291
|
+
if (!normalizedResult.error && !opts.bypassCache) {
|
|
11202
11292
|
const cacheKey = `${principalKey}|${normalizedPath}:`;
|
|
11203
11293
|
getCache[cacheKey] = {
|
|
11204
|
-
data:
|
|
11294
|
+
data: normalizedResult.data,
|
|
11205
11295
|
expiresAt: now + GET_CACHE_TTL
|
|
11206
11296
|
};
|
|
11207
11297
|
}
|
|
@@ -11746,6 +11836,7 @@ var operations = /*#__PURE__*/Object.freeze({
|
|
|
11746
11836
|
aggregate: aggregate,
|
|
11747
11837
|
clearReadCacheForAuthChange: clearReadCacheForAuthChange,
|
|
11748
11838
|
count: count,
|
|
11839
|
+
docId: docId,
|
|
11749
11840
|
get: get,
|
|
11750
11841
|
getFiles: getFiles,
|
|
11751
11842
|
getMany: getMany,
|
|
@@ -12333,14 +12424,46 @@ function handleServerMessage(connection, message) {
|
|
|
12333
12424
|
}
|
|
12334
12425
|
}
|
|
12335
12426
|
}
|
|
12427
|
+
/**
|
|
12428
|
+
* Additively attach the bare `id` (leaf doc key) to a subscription row (Bug 1).
|
|
12429
|
+
* Rows carry `_id`/`pathId` = the full document path; this leaves those as-is and
|
|
12430
|
+
* adds `id` = the last path segment so `row.id` is the doc key apps expect. No-ops
|
|
12431
|
+
* for non-objects and rows that already define `id`.
|
|
12432
|
+
*/
|
|
12433
|
+
function withSubscriptionId(row) {
|
|
12434
|
+
var _a, _b, _c;
|
|
12435
|
+
if (!row || typeof row !== 'object' || Array.isArray(row))
|
|
12436
|
+
return row;
|
|
12437
|
+
if ('id' in row)
|
|
12438
|
+
return row;
|
|
12439
|
+
const source = (_c = (_b = (_a = row._id) !== null && _a !== void 0 ? _a : row.pathId) !== null && _b !== void 0 ? _b : row.relativePath) !== null && _c !== void 0 ? _c : row.absolutePath;
|
|
12440
|
+
if (typeof source !== 'string' || source.length === 0)
|
|
12441
|
+
return row;
|
|
12442
|
+
const leaf = docId(source);
|
|
12443
|
+
if (!leaf)
|
|
12444
|
+
return row;
|
|
12445
|
+
return Object.assign(Object.assign({}, row), { id: leaf });
|
|
12446
|
+
}
|
|
12447
|
+
/**
|
|
12448
|
+
* The `onData` payload follows the path: a collection delivers a bare array of
|
|
12449
|
+
* rows, a single-doc path delivers the document (or null). Attach the bare `id`
|
|
12450
|
+
* to each returned row in either case, additive (Bug 1).
|
|
12451
|
+
*/
|
|
12452
|
+
function addIdsToSubscriptionData(data) {
|
|
12453
|
+
if (Array.isArray(data))
|
|
12454
|
+
return data.map(withSubscriptionId);
|
|
12455
|
+
return withSubscriptionId(data);
|
|
12456
|
+
}
|
|
12336
12457
|
function notifyCallbacks(subscription, data) {
|
|
12337
12458
|
var _a;
|
|
12459
|
+
// Attach the bare `id` (leaf doc key) to every delivered row (Bug 1).
|
|
12460
|
+
const decorated = addIdsToSubscriptionData(data);
|
|
12338
12461
|
// Snapshot the callbacks array so that unsubscriptions during
|
|
12339
12462
|
// notification don't cause callbacks to be skipped.
|
|
12340
12463
|
const callbacks = subscription.callbacks.slice();
|
|
12341
12464
|
for (const callback of callbacks) {
|
|
12342
12465
|
try {
|
|
12343
|
-
(_a = callback.onData) === null || _a === void 0 ? void 0 : _a.call(callback,
|
|
12466
|
+
(_a = callback.onData) === null || _a === void 0 ? void 0 : _a.call(callback, decorated);
|
|
12344
12467
|
}
|
|
12345
12468
|
catch (error) {
|
|
12346
12469
|
console.error('[WS v2] Error in subscription callback:', error);
|
|
@@ -12431,7 +12554,7 @@ async function subscribeV2(path, subscriptionOptions, roomRoutePath) {
|
|
|
12431
12554
|
if (cachedEntry && Date.now() - cachedEntry.timestamp < CACHE_TTL && subscriptionOptions.onData) {
|
|
12432
12555
|
setTimeout(() => {
|
|
12433
12556
|
var _a;
|
|
12434
|
-
(_a = subscriptionOptions.onData) === null || _a === void 0 ? void 0 : _a.call(subscriptionOptions, cachedEntry.data);
|
|
12557
|
+
(_a = subscriptionOptions.onData) === null || _a === void 0 ? void 0 : _a.call(subscriptionOptions, addIdsToSubscriptionData(cachedEntry.data));
|
|
12435
12558
|
}, 0);
|
|
12436
12559
|
}
|
|
12437
12560
|
// Get or create connection for this routing target (room-scoped when a
|
|
@@ -12461,7 +12584,7 @@ async function subscribeV2(path, subscriptionOptions, roomRoutePath) {
|
|
|
12461
12584
|
if (existingSubscription.lastData !== undefined && subscriptionOptions.onData) {
|
|
12462
12585
|
setTimeout(() => {
|
|
12463
12586
|
var _a;
|
|
12464
|
-
(_a = subscriptionOptions.onData) === null || _a === void 0 ? void 0 : _a.call(subscriptionOptions, existingSubscription.lastData);
|
|
12587
|
+
(_a = subscriptionOptions.onData) === null || _a === void 0 ? void 0 : _a.call(subscriptionOptions, addIdsToSubscriptionData(existingSubscription.lastData));
|
|
12465
12588
|
}, 0);
|
|
12466
12589
|
}
|
|
12467
12590
|
return async () => {
|
|
@@ -12969,6 +13092,73 @@ function serverTimestamp() {
|
|
|
12969
13092
|
return { operation: 'time', value: 'now' };
|
|
12970
13093
|
}
|
|
12971
13094
|
|
|
13095
|
+
/**
|
|
13096
|
+
* Time units in Bounded — read this once and never get a 1000× timestamp bug.
|
|
13097
|
+
*
|
|
13098
|
+
* **Bounded's policy/proof layer is Unix SECONDS.** `@time.now` in a rule,
|
|
13099
|
+
* `rollingSum` `windowSeconds`, `scheduledAt`, and any timestamp *field your
|
|
13100
|
+
* policy compares against `@time.now`* are all **seconds**. (This is also what
|
|
13101
|
+
* the chain uses — Solana's on-chain clock is `unix_timestamp` in seconds — so a
|
|
13102
|
+
* single seconds unit works for both onchain and offchain rules.)
|
|
13103
|
+
*
|
|
13104
|
+
* **JavaScript is MILLISECONDS.** `Date.now()`, `new Date().getTime()`, and the
|
|
13105
|
+
* auto-stamped system fields `_createdAt` / `_updatedAt` are all **ms**.
|
|
13106
|
+
*
|
|
13107
|
+
* Comparing across the two (e.g. `@time.now - myField` where `myField` was set
|
|
13108
|
+
* from `Date.now()`) is 1000× off, so a freshness / TTL check silently treats
|
|
13109
|
+
* every row as ancient (or far-future) and drops it — which reads as "realtime
|
|
13110
|
+
* isn't delivering" when the data is actually fine.
|
|
13111
|
+
*
|
|
13112
|
+
* **The rules:**
|
|
13113
|
+
* - To **write** a timestamp a policy will read, prefer **`serverTimestamp()`**
|
|
13114
|
+
* (from this package) — the *server* stamps it in seconds, so it matches
|
|
13115
|
+
* `@time.now` AND can't be forged by the client (use it for TTLs, rate windows,
|
|
13116
|
+
* anti-cheat). Use `now()` only when you need the value in client code before
|
|
13117
|
+
* the write.
|
|
13118
|
+
* - To **compare** timestamps in client/render code, use `now()` (seconds), not
|
|
13119
|
+
* `Date.now()` (ms), and `toSeconds()` to convert the ms system fields
|
|
13120
|
+
* (`_createdAt`/`_updatedAt`) or any `Date.now()` value first.
|
|
13121
|
+
*/
|
|
13122
|
+
/**
|
|
13123
|
+
* Current time as a **Unix timestamp in seconds** — the unit Bounded policy rules
|
|
13124
|
+
* use (`@time.now`). Use this (not `Date.now()`) when you need a timestamp in
|
|
13125
|
+
* client code (e.g. a freshness check). For a value you *store* and a policy
|
|
13126
|
+
* reads, prefer the server-authoritative {@link serverTimestamp} instead.
|
|
13127
|
+
*
|
|
13128
|
+
* ```ts
|
|
13129
|
+
* // stale if >15s old — seconds vs seconds ✓
|
|
13130
|
+
* if (now() - doc.lastSeenSeconds > 15) renderStale();
|
|
13131
|
+
* ```
|
|
13132
|
+
*/
|
|
13133
|
+
function now() {
|
|
13134
|
+
return Math.floor(Date.now() / 1000);
|
|
13135
|
+
}
|
|
13136
|
+
/**
|
|
13137
|
+
* Convert a JavaScript millisecond timestamp to Bounded's **seconds**. Accepts a
|
|
13138
|
+
* `Date`, or an ms number such as `Date.now()` or a doc's `_createdAt` /
|
|
13139
|
+
* `_updatedAt` system field.
|
|
13140
|
+
*
|
|
13141
|
+
* ```ts
|
|
13142
|
+
* // doc is >15s old (compare the ms system field in seconds):
|
|
13143
|
+
* if (now() - toSeconds(doc._updatedAt) > 15) renderStale();
|
|
13144
|
+
* ```
|
|
13145
|
+
*/
|
|
13146
|
+
function toSeconds(msOrDate) {
|
|
13147
|
+
const ms = msOrDate instanceof Date ? msOrDate.getTime() : msOrDate;
|
|
13148
|
+
return Math.floor(ms / 1000);
|
|
13149
|
+
}
|
|
13150
|
+
/**
|
|
13151
|
+
* Convert a Bounded **seconds** timestamp back to JavaScript **milliseconds** —
|
|
13152
|
+
* e.g. to build a `Date` or do client-side date math/formatting.
|
|
13153
|
+
*
|
|
13154
|
+
* ```ts
|
|
13155
|
+
* new Date(toMillis(doc.createdAtSeconds)).toLocaleString();
|
|
13156
|
+
* ```
|
|
13157
|
+
*/
|
|
13158
|
+
function toMillis(seconds) {
|
|
13159
|
+
return seconds * 1000;
|
|
13160
|
+
}
|
|
13161
|
+
|
|
12972
13162
|
// ---------------------------------------------------------------------------
|
|
12973
13163
|
// realtime-store.ts — Client-side state manager for realtime apps.
|
|
12974
13164
|
//
|
|
@@ -21537,17 +21727,17 @@ function setAuthProviderInstance(provider) {
|
|
|
21537
21727
|
authProviderInstance = provider;
|
|
21538
21728
|
}
|
|
21539
21729
|
|
|
21540
|
-
var _a;
|
|
21730
|
+
var _a$1;
|
|
21541
21731
|
// Whether we're in a server-side rendering context (no hooks allowed).
|
|
21542
21732
|
// React Native has no `window` but DOES support hooks.
|
|
21543
21733
|
// We detect Node SSR specifically via process.versions.node to avoid
|
|
21544
21734
|
// false positives from Node 21+ which defines `navigator` globally.
|
|
21545
|
-
const isSSR = typeof window === 'undefined'
|
|
21735
|
+
const isSSR$1 = typeof window === 'undefined'
|
|
21546
21736
|
&& typeof process !== 'undefined'
|
|
21547
|
-
&& !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
|
|
21737
|
+
&& !!((_a$1 = process.versions) === null || _a$1 === void 0 ? void 0 : _a$1.node);
|
|
21548
21738
|
function useAuth() {
|
|
21549
21739
|
// Provide a fallback so server render doesn't break
|
|
21550
|
-
if (isSSR) {
|
|
21740
|
+
if (isSSR$1) {
|
|
21551
21741
|
return {
|
|
21552
21742
|
login: async () => undefined,
|
|
21553
21743
|
logout: async () => undefined,
|
|
@@ -21607,6 +21797,66 @@ function useAuth() {
|
|
|
21607
21797
|
};
|
|
21608
21798
|
}
|
|
21609
21799
|
|
|
21800
|
+
var _a;
|
|
21801
|
+
// SSR guard (mirrors useAuth): no hooks/subscriptions during Node server render.
|
|
21802
|
+
// React Native has no `window` but DOES support hooks, so detect Node SSR
|
|
21803
|
+
// specifically via process.versions.node.
|
|
21804
|
+
const isSSR = typeof window === 'undefined'
|
|
21805
|
+
&& typeof process !== 'undefined'
|
|
21806
|
+
&& !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
|
|
21807
|
+
function useQuery(path, options) {
|
|
21808
|
+
if (isSSR) {
|
|
21809
|
+
return { data: undefined, loading: true, error: null };
|
|
21810
|
+
}
|
|
21811
|
+
const [data, setData] = React$1.useState(undefined);
|
|
21812
|
+
const [loading, setLoading] = React$1.useState(true);
|
|
21813
|
+
const [error, setError] = React$1.useState(null);
|
|
21814
|
+
// Re-subscribe only when the query actually changes (not on every render).
|
|
21815
|
+
const optionsKey = options ? JSON.stringify(options) : '';
|
|
21816
|
+
React$1.useEffect(() => {
|
|
21817
|
+
if (!path) {
|
|
21818
|
+
setData(undefined);
|
|
21819
|
+
setLoading(false);
|
|
21820
|
+
setError(null);
|
|
21821
|
+
return;
|
|
21822
|
+
}
|
|
21823
|
+
let active = true;
|
|
21824
|
+
let unsubscribe;
|
|
21825
|
+
setLoading(true);
|
|
21826
|
+
setError(null);
|
|
21827
|
+
subscribe(path, Object.assign(Object.assign({}, options), { onData: (d) => {
|
|
21828
|
+
if (!active)
|
|
21829
|
+
return;
|
|
21830
|
+
setData(d);
|
|
21831
|
+
setLoading(false);
|
|
21832
|
+
}, onError: (e) => {
|
|
21833
|
+
if (!active)
|
|
21834
|
+
return;
|
|
21835
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
21836
|
+
setLoading(false);
|
|
21837
|
+
} }))
|
|
21838
|
+
.then((unsub) => {
|
|
21839
|
+
if (active)
|
|
21840
|
+
unsubscribe = unsub;
|
|
21841
|
+
else
|
|
21842
|
+
void unsub(); // unmounted before subscribe resolved
|
|
21843
|
+
})
|
|
21844
|
+
.catch((e) => {
|
|
21845
|
+
if (!active)
|
|
21846
|
+
return;
|
|
21847
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
21848
|
+
setLoading(false);
|
|
21849
|
+
});
|
|
21850
|
+
return () => {
|
|
21851
|
+
active = false;
|
|
21852
|
+
void (unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe());
|
|
21853
|
+
};
|
|
21854
|
+
// optionsKey captures the option object's contents; path is the other input.
|
|
21855
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
21856
|
+
}, [path, optionsKey]);
|
|
21857
|
+
return { data, loading, error };
|
|
21858
|
+
}
|
|
21859
|
+
|
|
21610
21860
|
async function deserializeTransaction(tx) {
|
|
21611
21861
|
const buf = Buffer.isBuffer(tx) ? tx : Buffer.from(tx, 'base64');
|
|
21612
21862
|
if ((buf[0] & 0x80) !== 0) {
|
|
@@ -21740,7 +21990,7 @@ async function loadDependencies() {
|
|
|
21740
21990
|
const [reactModule, reactDomModule, phantomModule] = await Promise.all([
|
|
21741
21991
|
import('react'),
|
|
21742
21992
|
import('react-dom/client'),
|
|
21743
|
-
import('./index-
|
|
21993
|
+
import('./index-B9DtkVXb.esm.js')
|
|
21744
21994
|
]);
|
|
21745
21995
|
// Extract default export from ESM module namespace
|
|
21746
21996
|
// Dynamic import() returns { default: Module, ...exports }, not the module directly
|
|
@@ -23641,7 +23891,7 @@ async function registerMobileWalletAdapter(config) {
|
|
|
23641
23891
|
if (typeof window === 'undefined')
|
|
23642
23892
|
return;
|
|
23643
23893
|
try {
|
|
23644
|
-
const walletStandardMobile = await import('./index.browser-
|
|
23894
|
+
const walletStandardMobile = await import('./index.browser-Cictefil.esm.js');
|
|
23645
23895
|
const registerMwa = walletStandardMobile.registerMwa || ((_a = walletStandardMobile.default) === null || _a === void 0 ? void 0 : _a.registerMwa);
|
|
23646
23896
|
if (!registerMwa) {
|
|
23647
23897
|
console.warn('[SolanaMobileWallet] registerMwa not found in @solana-mobile/wallet-standard-mobile');
|
|
@@ -23780,7 +24030,7 @@ class SolanaMobileWalletProvider {
|
|
|
23780
24030
|
async ensureWallet() {
|
|
23781
24031
|
if (this.wallet)
|
|
23782
24032
|
return this.wallet;
|
|
23783
|
-
const mod = await import('./index.browser-
|
|
24033
|
+
const mod = await import('./index.browser-Cictefil.esm.js');
|
|
23784
24034
|
const chain = mapChainToWalletStandard(this.cluster);
|
|
23785
24035
|
this.wallet = new mod.LocalSolanaMobileWalletAdapterWallet({
|
|
23786
24036
|
appIdentity: this.appIdentity,
|
|
@@ -25913,5 +26163,5 @@ class PrivyExpoProvider {
|
|
|
25913
26163
|
}
|
|
25914
26164
|
}
|
|
25915
26165
|
|
|
25916
|
-
export {
|
|
25917
|
-
//# sourceMappingURL=index-
|
|
26166
|
+
export { registerMobileWalletAdapter as $, setMany as A, setFile as B, getFiles as C, search as D, queryAggregate as E, runQuery as F, runQueryMany as G, runExpression as H, runExpressionMany as I, signMessage as J, signTransaction as K, signAndSubmitTransaction as L, count as M, aggregate as N, subscribe as O, useAuth as P, useQuery as Q, deserializeTransaction as R, getIdToken as S, setPlatform as T, getPlatform as U, PhantomWalletProvider as V, MockAuthProvider as W, DEFAULT_TEST_ADDRESS as X, OffchainAuthProvider as Y, SolanaMobileWalletProvider as Z, isMobileWalletAvailable as _, bs582 as a, PrivyWalletProvider as a0, PrivyExpoProvider as a1, EFFECT_INTENT_ADDRESS as a2, FunctionInvokeError as a3, InsufficientBalanceError as a4, LiveIntentError as a5, ReactNativeSessionManager as a6, RealtimeStore as a7, ServerSessionManager as a8, WebSessionManager as a9, serverTimestamp as aA, signSessionCreateMessage as aB, subscribeView as aC, toMillis as aD, toSeconds as aE, withEffects as aF, wsDelete as aG, wsGet as aH, wsGetMany as aI, wsQuery as aJ, wsSet as aK, buildSetDocumentsTransaction as aa, clearCache as ab, closeAllSubscriptions as ac, convertRemainingAccounts as ad, createSessionWithSignature as ae, defineLiveModule as af, deriveUserIdentityFromIdToken as ag, functions as ah, genAuthNonce as ai, genSolanaMessage as aj, getActiveSessionManager as ak, getCachedData as al, getRealtimeStore as am, getWebhookKeysUrl as an, hasActiveConnection as ao, increment as ap, invoke as aq, isEffectResult as ar, live as as, intent as at, status as au, now as av, reconnectWithNewAuth as aw, refreshSession as ax, resetRealtimeStore as ay, revokeSession as az, bufferExports as b, getCurrentUser as c, onAuthLoadingChanged as d, getAuthLoading as e, logout as f, getDefaultExportFromCjs$1 as g, getConfig as h, init as i, getAuthProvider as j, sendEmailOtp as k, login as l, linkEmail as m, loginWithPrivy as n, onAuthStateChanged as o, loginWithRedirect as p, linkWithRedirect as q, completeLoginFromRedirect as r, signInAnonymously as s, loginWithPopup as t, completeLoginInPopup as u, verifyEmailOtp as v, get as w, getMany as x, docId as y, set as z };
|
|
26167
|
+
//# sourceMappingURL=index-30RA_Bdf.esm.js.map
|