@pooflabs/core 0.0.31 → 0.0.32

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.
@@ -17,6 +17,10 @@ export type GetOptions = {
17
17
  includeSubPaths?: boolean;
18
18
  /** Shape object for relationship resolution - specifies which related documents to include */
19
19
  shape?: Record<string, any>;
20
+ /** Maximum number of items to return (opt-in pagination) */
21
+ limit?: number;
22
+ /** Opaque cursor for cursor-based pagination (used with limit) */
23
+ cursor?: string;
20
24
  /** Internal overrides for headers */
21
25
  _overrides?: {
22
26
  headers?: Record<string, string>;
@@ -66,8 +70,16 @@ export declare function setMany(many: {
66
70
  export declare function clearCache(path?: string, opts?: {
67
71
  prompt?: string;
68
72
  }): void;
69
- export declare function getFiles(path: string): Promise<any>;
70
- export declare function setFile(path: string, file: File | null): Promise<boolean>;
73
+ export declare function getFiles(path: string, options?: {
74
+ _overrides?: {
75
+ headers?: Record<string, string>;
76
+ };
77
+ }): Promise<any>;
78
+ export declare function setFile(path: string, file: File | null, options?: {
79
+ _overrides?: {
80
+ headers?: Record<string, string>;
81
+ };
82
+ }): Promise<boolean>;
71
83
  export declare function signMessage(message: string): Promise<string>;
72
84
  export declare function signTransaction(transaction: Transaction | VersionedTransaction): Promise<Transaction | VersionedTransaction>;
73
85
  export declare function signAndSubmitTransaction(transaction: Transaction | VersionedTransaction, feePayer?: PublicKey): Promise<string>;
package/dist/index.js CHANGED
@@ -3240,7 +3240,7 @@ async function makeApiRequest(method, urlPath, data, _overrides) {
3240
3240
  requestConfig.data = data ? JSON.stringify(data) : {};
3241
3241
  }
3242
3242
  const response = await axios(requestConfig);
3243
- return { data: response.data, status: response.status };
3243
+ return { data: response.data, status: response.status, headers: response.headers };
3244
3244
  }
3245
3245
  try {
3246
3246
  return await executeRequest();
@@ -3382,6 +3382,13 @@ const pendingRequests = {};
3382
3382
  const GET_CACHE_TTL = 500; // Adjust this value as needed (in milliseconds)
3383
3383
  // Last time we cleaned up the cache
3384
3384
  let lastCacheCleanup = Date.now();
3385
+ function hashForKey$1(value) {
3386
+ let h = 5381;
3387
+ for (let i = 0; i < value.length; i++) {
3388
+ h = ((h << 5) + h + value.charCodeAt(i)) & 0x7fffffff;
3389
+ }
3390
+ return h.toString(36);
3391
+ }
3385
3392
  async function get(path, opts = {}) {
3386
3393
  try {
3387
3394
  let normalizedPath = path.startsWith("/") ? path.slice(1) : path;
@@ -3392,10 +3399,12 @@ async function get(path, opts = {}) {
3392
3399
  if (!normalizedPath || normalizedPath.length === 0) {
3393
3400
  return new Error("Invalid path provided.");
3394
3401
  }
3395
- // Create cache key combining path, prompt, includeSubPaths, and shape
3402
+ // Create cache key combining path, prompt, includeSubPaths, shape, limit, and cursor
3396
3403
  const shapeKey = opts.shape ? JSON.stringify(opts.shape) : '';
3397
3404
  const includeSubPathsKey = opts.includeSubPaths ? ':subpaths' : '';
3398
- const cacheKey = `${normalizedPath}:${opts.prompt || ''}${includeSubPathsKey}:${shapeKey}`;
3405
+ const limitKey = opts.limit !== undefined ? `:l${opts.limit}` : '';
3406
+ const cursorKey = opts.cursor ? `:c${hashForKey$1(opts.cursor)}` : '';
3407
+ const cacheKey = `${normalizedPath}:${opts.prompt || ''}${includeSubPathsKey}:${shapeKey}${limitKey}${cursorKey}`;
3399
3408
  const now = Date.now();
3400
3409
  // Check for valid cache entry if not bypassing cache
3401
3410
  if (!opts.bypassCache && getCache[cacheKey] && now < getCache[cacheKey].expiresAt) {
@@ -3419,6 +3428,8 @@ async function get(path, opts = {}) {
3419
3428
  // Build common query params
3420
3429
  const includeSubPathsParam = opts.includeSubPaths ? '&includeSubPaths=true' : '';
3421
3430
  const shapeParam = opts.shape ? `&shape=${encodeURIComponent(JSON.stringify(opts.shape))}` : '';
3431
+ const limitParam = opts.limit !== undefined ? `&limit=${opts.limit}` : '';
3432
+ const cursorParam = opts.cursor ? `&cursor=${encodeURIComponent(opts.cursor)}` : '';
3422
3433
  if (pathIsDocument) {
3423
3434
  const itemId = encodeURIComponent(normalizedPath);
3424
3435
  // For documents, query params go after the path
@@ -3429,13 +3440,14 @@ async function get(path, opts = {}) {
3429
3440
  else {
3430
3441
  const path = encodeURIComponent(normalizedPath);
3431
3442
  const promptQueryParam = (opts === null || opts === void 0 ? void 0 : opts.prompt) ? `&prompt=${btoa(opts.prompt)}` : "";
3432
- const apiPath = `items?path=${path}${promptQueryParam}${includeSubPathsParam}${shapeParam}`;
3443
+ const apiPath = `items?path=${path}${promptQueryParam}${includeSubPathsParam}${shapeParam}${limitParam}${cursorParam}`;
3433
3444
  response = await makeApiRequest('GET', apiPath, null, opts._overrides);
3434
3445
  }
3446
+ const responseData = response.data;
3435
3447
  // Cache the response (unless bypassing cache)
3436
3448
  if (!opts.bypassCache) {
3437
3449
  getCache[cacheKey] = {
3438
- data: response.data,
3450
+ data: responseData,
3439
3451
  expiresAt: now + GET_CACHE_TTL
3440
3452
  };
3441
3453
  // Periodically clean up expired cache entries (every 5 seconds)
@@ -3445,7 +3457,7 @@ async function get(path, opts = {}) {
3445
3457
  }
3446
3458
  }
3447
3459
  // Return the data from the response
3448
- return response.data;
3460
+ return responseData;
3449
3461
  }
3450
3462
  finally {
3451
3463
  // Remove this request from pendingRequests regardless of success/failure
@@ -3742,21 +3754,21 @@ function clearCacheByPrefix(prefix) {
3742
3754
  }
3743
3755
  });
3744
3756
  }
3745
- async function getFiles(path) {
3757
+ async function getFiles(path, options) {
3746
3758
  try {
3747
3759
  const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
3748
3760
  if (!normalizedPath || normalizedPath.length === 0) {
3749
3761
  return new Error("Invalid path provided.");
3750
3762
  }
3751
3763
  const apiPath = `storage?path=${normalizedPath}`;
3752
- const response = await makeApiRequest('GET', apiPath, null, undefined);
3764
+ const response = await makeApiRequest('GET', apiPath, null, options === null || options === void 0 ? void 0 : options._overrides);
3753
3765
  return response.data;
3754
3766
  }
3755
3767
  catch (error) {
3756
3768
  throw error;
3757
3769
  }
3758
3770
  }
3759
- async function setFile(path, file) {
3771
+ async function setFile(path, file, options) {
3760
3772
  var _a;
3761
3773
  // 1) Get the presigned URL from your backend
3762
3774
  const requestBody = {
@@ -3767,7 +3779,7 @@ async function setFile(path, file) {
3767
3779
  if (file) {
3768
3780
  requestBody.contentLength = file.size;
3769
3781
  }
3770
- const response = await makeApiRequest('POST', 'storage/url', requestBody, undefined);
3782
+ const response = await makeApiRequest('POST', 'storage/url', requestBody, options === null || options === void 0 ? void 0 : options._overrides);
3771
3783
  if (file == null) {
3772
3784
  return true;
3773
3785
  }
@@ -3863,10 +3875,19 @@ let lastBrowserTriggeredReconnectAt = 0;
3863
3875
  function generateSubscriptionId() {
3864
3876
  return `sub_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
3865
3877
  }
3866
- function getCacheKey(path, prompt, shape) {
3878
+ function hashForKey(value) {
3879
+ let h = 5381;
3880
+ for (let i = 0; i < value.length; i++) {
3881
+ h = ((h << 5) + h + value.charCodeAt(i)) & 0x7fffffff;
3882
+ }
3883
+ return h.toString(36);
3884
+ }
3885
+ function getCacheKey(path, prompt, shape, limit, cursor) {
3867
3886
  const normalizedPath = path.startsWith('/') ? path.slice(1) : path;
3868
3887
  const shapeKey = shape && Object.keys(shape).length > 0 ? JSON.stringify(shape) : '';
3869
- return `${normalizedPath}:${prompt || 'default'}:${shapeKey}`;
3888
+ const limitKey = limit !== undefined ? `:l${limit}` : '';
3889
+ const cursorKey = cursor ? `:c${hashForKey(cursor)}` : '';
3890
+ return `${normalizedPath}:${prompt || 'default'}:${shapeKey}${limitKey}${cursorKey}`;
3870
3891
  }
3871
3892
  function isTokenExpired(token) {
3872
3893
  try {
@@ -4007,8 +4028,12 @@ async function getOrCreateConnection(appId, isServer) {
4007
4028
  const wsUrl = new URL(config.wsApiUrl);
4008
4029
  // Always use v2 path
4009
4030
  wsUrl.pathname = WS_V2_PATH;
4010
- // Set appId
4011
- if (typeof window !== 'undefined' && window.CUSTOM_TAROBASE_APP_ID_HEADER) {
4031
+ // Set appId — prefer the explicit appId passed to getOrCreateConnection,
4032
+ // fall back to window global for legacy callers, then config default
4033
+ if (appId && appId !== config.appId) {
4034
+ wsUrl.searchParams.append('appId', appId);
4035
+ }
4036
+ else if (typeof window !== 'undefined' && window.CUSTOM_TAROBASE_APP_ID_HEADER) {
4012
4037
  wsUrl.searchParams.append('appId', window.CUSTOM_TAROBASE_APP_ID_HEADER);
4013
4038
  }
4014
4039
  else {
@@ -4081,7 +4106,7 @@ function handleServerMessage(connection, message) {
4081
4106
  // If we already received data for this subscription, treat subscribed
4082
4107
  // as an ack only and avoid regressing to an older snapshot.
4083
4108
  if (subscription.lastData === undefined) {
4084
- const cacheKey = getCacheKey(subscription.path, subscription.prompt, subscription.shape);
4109
+ const cacheKey = getCacheKey(subscription.path, subscription.prompt, subscription.shape, subscription.limit, subscription.cursor);
4085
4110
  responseCache.set(cacheKey, { data: message.data, timestamp: Date.now() });
4086
4111
  subscription.lastData = message.data;
4087
4112
  notifyCallbacks(subscription, message.data);
@@ -4108,7 +4133,7 @@ function handleServerMessage(connection, message) {
4108
4133
  const subscription = connection.subscriptions.get(message.subscriptionId);
4109
4134
  if (subscription) {
4110
4135
  // Update cache
4111
- const cacheKey = getCacheKey(subscription.path, subscription.prompt, subscription.shape);
4136
+ const cacheKey = getCacheKey(subscription.path, subscription.prompt, subscription.shape, subscription.limit, subscription.cursor);
4112
4137
  responseCache.set(cacheKey, { data: message.data, timestamp: Date.now() });
4113
4138
  // Store last data
4114
4139
  subscription.lastData = message.data;
@@ -4165,6 +4190,8 @@ function sendSubscribe(connection, subscription) {
4165
4190
  shape: subscription.shape && Object.keys(subscription.shape).length > 0
4166
4191
  ? subscription.shape
4167
4192
  : undefined,
4193
+ limit: subscription.limit,
4194
+ cursor: subscription.cursor,
4168
4195
  };
4169
4196
  try {
4170
4197
  connection.ws.send(JSON.stringify(message));
@@ -4196,7 +4223,7 @@ function sendUnsubscribe(connection, subscriptionId) {
4196
4223
  async function subscribeV2(path, subscriptionOptions) {
4197
4224
  const config = await getConfig();
4198
4225
  const normalizedPath = path.startsWith('/') ? path.slice(1) : path;
4199
- const cacheKey = getCacheKey(normalizedPath, subscriptionOptions.prompt, subscriptionOptions.shape);
4226
+ const cacheKey = getCacheKey(normalizedPath, subscriptionOptions.prompt, subscriptionOptions.shape, subscriptionOptions.limit, subscriptionOptions.cursor);
4200
4227
  // Deliver cached data immediately if available
4201
4228
  const cachedEntry = responseCache.get(cacheKey);
4202
4229
  if (cachedEntry && Date.now() - cachedEntry.timestamp < CACHE_TTL && subscriptionOptions.onData) {
@@ -4205,14 +4232,16 @@ async function subscribeV2(path, subscriptionOptions) {
4205
4232
  (_a = subscriptionOptions.onData) === null || _a === void 0 ? void 0 : _a.call(subscriptionOptions, cachedEntry.data);
4206
4233
  }, 0);
4207
4234
  }
4235
+ // Use explicit appId override if provided, otherwise fall back to config
4236
+ const effectiveAppId = subscriptionOptions.appId || config.appId;
4208
4237
  // Get or create connection for this appId
4209
- const connection = await getOrCreateConnection(config.appId, config.isServer);
4210
- // Check if we already have a subscription for this path+prompt+shape
4238
+ const connection = await getOrCreateConnection(effectiveAppId, config.isServer);
4239
+ // Check if we already have a subscription for this path+prompt+shape+limit+cursor
4211
4240
  const shapeKey = subscriptionOptions.shape ? JSON.stringify(subscriptionOptions.shape) : '';
4212
4241
  let existingSubscription;
4213
4242
  for (const sub of connection.subscriptions.values()) {
4214
4243
  const subShapeKey = sub.shape ? JSON.stringify(sub.shape) : '';
4215
- if (sub.path === normalizedPath && sub.prompt === subscriptionOptions.prompt && subShapeKey === shapeKey) {
4244
+ if (sub.path === normalizedPath && sub.prompt === subscriptionOptions.prompt && subShapeKey === shapeKey && sub.limit === subscriptionOptions.limit && sub.cursor === subscriptionOptions.cursor) {
4216
4245
  existingSubscription = sub;
4217
4246
  break;
4218
4247
  }
@@ -4238,6 +4267,8 @@ async function subscribeV2(path, subscriptionOptions) {
4238
4267
  path: normalizedPath,
4239
4268
  prompt: subscriptionOptions.prompt,
4240
4269
  shape: subscriptionOptions.shape,
4270
+ limit: subscriptionOptions.limit,
4271
+ cursor: subscriptionOptions.cursor,
4241
4272
  includeSubPaths: false,
4242
4273
  callbacks: [subscriptionOptions],
4243
4274
  lastData: undefined,