@picobase_app/client 0.1.0 → 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.
package/README.md CHANGED
@@ -8,6 +8,8 @@ TypeScript SDK for PicoBase — add auth, database, realtime, and file storage t
8
8
  npm install @picobase_app/client
9
9
  ```
10
10
 
11
+ > ⚠️ **Important:** Install `@picobase_app/client`, **NOT** `pocketbase` directly. PicoBase wraps PocketBase with managed hosting features. If you accidentally installed `pocketbase`, remove it from your dependencies.
12
+
11
13
  ## Quickstart
12
14
 
13
15
  ```typescript
@@ -145,6 +147,39 @@ const unsub = await pb.realtime.subscribe('posts', (event) => {
145
147
  await pb.realtime.disconnectAll()
146
148
  ```
147
149
 
150
+ ## RPC (Remote Procedure Calls)
151
+
152
+ Call custom server-side functions using the `.rpc()` method. This is especially useful for Supabase migrations.
153
+
154
+ ```typescript
155
+ // Simple RPC call
156
+ const result = await pb.rpc('calculate_cart_total', {
157
+ cart_id: '123'
158
+ })
159
+
160
+ // Complex RPC with typed response
161
+ interface DashboardStats {
162
+ posts: number
163
+ comments: number
164
+ followers: number
165
+ }
166
+
167
+ const stats = await pb.rpc<DashboardStats>('get_dashboard_stats', {
168
+ user_id: currentUser.id
169
+ })
170
+ // stats.posts, stats.comments, stats.followers are typed!
171
+
172
+ // Common patterns
173
+ await pb.rpc('increment_views', { post_id: '123' })
174
+ const results = await pb.rpc('search_products', {
175
+ query: 'laptop',
176
+ min_price: 500,
177
+ category: 'electronics'
178
+ })
179
+ ```
180
+
181
+ RPC calls are mapped to custom PocketBase endpoints at `/api/rpc/{functionName}`. You'll need to implement these routes in your PocketBase instance. See the [PocketBase routing docs](https://pocketbase.io/docs/js-routing/) for details.
182
+
148
183
  ## File Storage
149
184
 
150
185
  PocketBase stores files as fields on records. Use the storage module to get URLs.
@@ -197,20 +232,54 @@ const pb = createClient('https://myapp.picobase.com', 'pbk_...', {
197
232
 
198
233
  ### Error handling
199
234
 
235
+ Every SDK error includes a `code` and `fix` property with actionable suggestions:
236
+
200
237
  ```typescript
201
- import { PicoBaseError, InstanceUnavailableError, AuthorizationError } from '@picobase_app/client'
238
+ import {
239
+ PicoBaseError,
240
+ AuthorizationError,
241
+ InstanceUnavailableError,
242
+ CollectionNotFoundError,
243
+ RecordNotFoundError,
244
+ ConfigurationError,
245
+ RpcError,
246
+ } from '@picobase_app/client'
202
247
 
203
248
  try {
204
249
  await pb.collection('posts').getList()
205
250
  } catch (err) {
206
- if (err instanceof AuthorizationError) {
207
- // Invalid API key
208
- } else if (err instanceof InstanceUnavailableError) {
209
- // Instance not available after retries
251
+ if (err instanceof PicoBaseError) {
252
+ console.log(err.message) // "Collection 'posts' not found."
253
+ console.log(err.code) // "COLLECTION_NOT_FOUND"
254
+ console.log(err.fix) // "Make sure the collection 'posts' exists..."
210
255
  }
211
256
  }
212
257
  ```
213
258
 
259
+ **Error types:**
260
+
261
+ | Error | Code | When |
262
+ |---|---|---|
263
+ | `ConfigurationError` | `CONFIGURATION_ERROR` | Missing URL, API key, or bad config |
264
+ | `AuthorizationError` | `UNAUTHORIZED` | Invalid or missing API key |
265
+ | `CollectionNotFoundError` | `COLLECTION_NOT_FOUND` | Collection doesn't exist |
266
+ | `RecordNotFoundError` | `RECORD_NOT_FOUND` | Record ID not found |
267
+ | `InstanceUnavailableError` | `INSTANCE_UNAVAILABLE` | Instance down after retries |
268
+ | `RpcError` | `RPC_ERROR` | RPC function call failed (includes endpoint-specific fix hints) |
269
+ | `RequestError` | `REQUEST_FAILED` | Generic HTTP error (includes status-specific fix hints) |
270
+
271
+ ### Typed collections with `picobase typegen`
272
+
273
+ Run `picobase typegen` to generate types from your schema. The generated file includes a typed client:
274
+
275
+ ```typescript
276
+ import { pb } from './src/types/picobase'
277
+
278
+ // Collection names autocomplete, record fields are typed
279
+ const result = await pb.collection('posts').getList(1, 20)
280
+ result.items[0].title // string — fully typed!
281
+ ```
282
+
214
283
  ## API Reference
215
284
 
216
285
  ### `createClient(url, apiKey, options?)`
package/dist/index.d.mts CHANGED
@@ -410,6 +410,33 @@ declare class PicoBaseClient {
410
410
  * Proxies to PocketBase's send() method.
411
411
  */
412
412
  send<T = unknown>(path: string, options?: SendOptions): Promise<T>;
413
+ /**
414
+ * Call a remote procedure (RPC) - a convenience method for calling custom API endpoints.
415
+ *
416
+ * Maps Supabase-style RPC calls to PicoBase custom endpoints:
417
+ * - `pb.rpc('my_function', params)` → `POST /api/rpc/my_function` with params as body
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * // Simple RPC call
422
+ * const result = await pb.rpc('calculate_total', { cart_id: '123' })
423
+ *
424
+ * // Complex RPC with typed response
425
+ * interface DashboardStats {
426
+ * posts: number
427
+ * comments: number
428
+ * followers: number
429
+ * }
430
+ * const stats = await pb.rpc<DashboardStats>('get_dashboard_stats', {
431
+ * user_id: currentUser.id
432
+ * })
433
+ * ```
434
+ *
435
+ * @param functionName The name of the RPC function to call
436
+ * @param params Optional parameters to pass to the function
437
+ * @returns The function result
438
+ */
439
+ rpc<T = unknown>(functionName: string, params?: Record<string, unknown>): Promise<T>;
413
440
  /**
414
441
  * Get the current auth token (if signed in), or empty string.
415
442
  */
@@ -462,12 +489,21 @@ declare function createClient(url: string, apiKey: string, options?: PicoBaseCli
462
489
 
463
490
  /**
464
491
  * Base error class for all PicoBase SDK errors.
492
+ *
493
+ * Every error includes a `code` for programmatic handling and a `fix`
494
+ * suggestion so developers can resolve issues without digging through docs.
465
495
  */
466
496
  declare class PicoBaseError extends Error {
467
497
  readonly code: string;
468
498
  readonly status?: number | undefined;
469
499
  readonly details?: unknown | undefined;
470
- constructor(message: string, code: string, status?: number | undefined, details?: unknown | undefined);
500
+ /** Actionable suggestion for how to fix this error. */
501
+ readonly fix?: string | undefined;
502
+ constructor(message: string, code: string, status?: number | undefined, details?: unknown | undefined,
503
+ /** Actionable suggestion for how to fix this error. */
504
+ fix?: string | undefined);
505
+ /** Formatted error string including fix suggestion. */
506
+ toString(): string;
471
507
  }
472
508
  /**
473
509
  * Thrown when the instance is not running and cold-start retries are exhausted.
@@ -481,11 +517,35 @@ declare class InstanceUnavailableError extends PicoBaseError {
481
517
  declare class AuthorizationError extends PicoBaseError {
482
518
  constructor(message?: string);
483
519
  }
520
+ /**
521
+ * Thrown when a collection is not found.
522
+ */
523
+ declare class CollectionNotFoundError extends PicoBaseError {
524
+ constructor(collectionName: string);
525
+ }
526
+ /**
527
+ * Thrown when a record is not found.
528
+ */
529
+ declare class RecordNotFoundError extends PicoBaseError {
530
+ constructor(collectionName: string, recordId: string);
531
+ }
484
532
  /**
485
533
  * Thrown when a PocketBase API request fails.
486
534
  */
487
535
  declare class RequestError extends PicoBaseError {
488
536
  constructor(message: string, status: number, details?: unknown);
489
537
  }
538
+ /**
539
+ * Thrown when the SDK is misconfigured (bad URL, missing params, etc.).
540
+ */
541
+ declare class ConfigurationError extends PicoBaseError {
542
+ constructor(message: string, fix: string);
543
+ }
544
+ /**
545
+ * Thrown when an RPC (remote procedure call) fails.
546
+ */
547
+ declare class RpcError extends PicoBaseError {
548
+ constructor(functionName: string, status: number, details?: unknown);
549
+ }
490
550
 
491
- export { type AuthEvent, type AuthResponse, type AuthStateChange, type AuthStateChangeCallback, AuthorizationError, type FileOptions, InstanceUnavailableError, type ListOptions, type OAuthSignInOptions, PicoBaseAuth, PicoBaseClient, type PicoBaseClientOptions, PicoBaseCollection, PicoBaseError, PicoBaseRealtime, PicoBaseStorage, type RealtimeAction, type RealtimeCallback, type RecordQueryOptions, RequestError, type SignInOptions, type SignUpOptions, type UnsubscribeFunc, createClient };
551
+ export { type AuthEvent, type AuthResponse, type AuthStateChange, type AuthStateChangeCallback, AuthorizationError, CollectionNotFoundError, ConfigurationError, type FileOptions, InstanceUnavailableError, type ListOptions, type OAuthSignInOptions, PicoBaseAuth, PicoBaseClient, type PicoBaseClientOptions, PicoBaseCollection, PicoBaseError, PicoBaseRealtime, PicoBaseStorage, type RealtimeAction, type RealtimeCallback, RecordNotFoundError, type RecordQueryOptions, RequestError, RpcError, type SignInOptions, type SignUpOptions, type UnsubscribeFunc, createClient };
package/dist/index.d.ts CHANGED
@@ -410,6 +410,33 @@ declare class PicoBaseClient {
410
410
  * Proxies to PocketBase's send() method.
411
411
  */
412
412
  send<T = unknown>(path: string, options?: SendOptions): Promise<T>;
413
+ /**
414
+ * Call a remote procedure (RPC) - a convenience method for calling custom API endpoints.
415
+ *
416
+ * Maps Supabase-style RPC calls to PicoBase custom endpoints:
417
+ * - `pb.rpc('my_function', params)` → `POST /api/rpc/my_function` with params as body
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * // Simple RPC call
422
+ * const result = await pb.rpc('calculate_total', { cart_id: '123' })
423
+ *
424
+ * // Complex RPC with typed response
425
+ * interface DashboardStats {
426
+ * posts: number
427
+ * comments: number
428
+ * followers: number
429
+ * }
430
+ * const stats = await pb.rpc<DashboardStats>('get_dashboard_stats', {
431
+ * user_id: currentUser.id
432
+ * })
433
+ * ```
434
+ *
435
+ * @param functionName The name of the RPC function to call
436
+ * @param params Optional parameters to pass to the function
437
+ * @returns The function result
438
+ */
439
+ rpc<T = unknown>(functionName: string, params?: Record<string, unknown>): Promise<T>;
413
440
  /**
414
441
  * Get the current auth token (if signed in), or empty string.
415
442
  */
@@ -462,12 +489,21 @@ declare function createClient(url: string, apiKey: string, options?: PicoBaseCli
462
489
 
463
490
  /**
464
491
  * Base error class for all PicoBase SDK errors.
492
+ *
493
+ * Every error includes a `code` for programmatic handling and a `fix`
494
+ * suggestion so developers can resolve issues without digging through docs.
465
495
  */
466
496
  declare class PicoBaseError extends Error {
467
497
  readonly code: string;
468
498
  readonly status?: number | undefined;
469
499
  readonly details?: unknown | undefined;
470
- constructor(message: string, code: string, status?: number | undefined, details?: unknown | undefined);
500
+ /** Actionable suggestion for how to fix this error. */
501
+ readonly fix?: string | undefined;
502
+ constructor(message: string, code: string, status?: number | undefined, details?: unknown | undefined,
503
+ /** Actionable suggestion for how to fix this error. */
504
+ fix?: string | undefined);
505
+ /** Formatted error string including fix suggestion. */
506
+ toString(): string;
471
507
  }
472
508
  /**
473
509
  * Thrown when the instance is not running and cold-start retries are exhausted.
@@ -481,11 +517,35 @@ declare class InstanceUnavailableError extends PicoBaseError {
481
517
  declare class AuthorizationError extends PicoBaseError {
482
518
  constructor(message?: string);
483
519
  }
520
+ /**
521
+ * Thrown when a collection is not found.
522
+ */
523
+ declare class CollectionNotFoundError extends PicoBaseError {
524
+ constructor(collectionName: string);
525
+ }
526
+ /**
527
+ * Thrown when a record is not found.
528
+ */
529
+ declare class RecordNotFoundError extends PicoBaseError {
530
+ constructor(collectionName: string, recordId: string);
531
+ }
484
532
  /**
485
533
  * Thrown when a PocketBase API request fails.
486
534
  */
487
535
  declare class RequestError extends PicoBaseError {
488
536
  constructor(message: string, status: number, details?: unknown);
489
537
  }
538
+ /**
539
+ * Thrown when the SDK is misconfigured (bad URL, missing params, etc.).
540
+ */
541
+ declare class ConfigurationError extends PicoBaseError {
542
+ constructor(message: string, fix: string);
543
+ }
544
+ /**
545
+ * Thrown when an RPC (remote procedure call) fails.
546
+ */
547
+ declare class RpcError extends PicoBaseError {
548
+ constructor(functionName: string, status: number, details?: unknown);
549
+ }
490
550
 
491
- export { type AuthEvent, type AuthResponse, type AuthStateChange, type AuthStateChangeCallback, AuthorizationError, type FileOptions, InstanceUnavailableError, type ListOptions, type OAuthSignInOptions, PicoBaseAuth, PicoBaseClient, type PicoBaseClientOptions, PicoBaseCollection, PicoBaseError, PicoBaseRealtime, PicoBaseStorage, type RealtimeAction, type RealtimeCallback, type RecordQueryOptions, RequestError, type SignInOptions, type SignUpOptions, type UnsubscribeFunc, createClient };
551
+ export { type AuthEvent, type AuthResponse, type AuthStateChange, type AuthStateChangeCallback, AuthorizationError, CollectionNotFoundError, ConfigurationError, type FileOptions, InstanceUnavailableError, type ListOptions, type OAuthSignInOptions, PicoBaseAuth, PicoBaseClient, type PicoBaseClientOptions, PicoBaseCollection, PicoBaseError, PicoBaseRealtime, PicoBaseStorage, type RealtimeAction, type RealtimeCallback, RecordNotFoundError, type RecordQueryOptions, RequestError, RpcError, type SignInOptions, type SignUpOptions, type UnsubscribeFunc, createClient };