@ponxa/potatobase-client 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 PotatoBase Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # PotatoBase Client SDK
2
+
3
+ Official JavaScript/TypeScript client for PotatoBase - The DynamoDB platform built on SST v3.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @potatobase/client
9
+ # or
10
+ yarn add @potatobase/client
11
+ # or
12
+ pnpm add @potatobase/client
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { PotatoBaseClient } from '@potatobase/client';
19
+
20
+ // Initialize the client
21
+ const client = new PotatoBaseClient({
22
+ apiUrl: process.env.NEXT_PUBLIC_API_URL || 'https://api.potatobase.com',
23
+ projectId: process.env.NEXT_PUBLIC_PROJECT_ID,
24
+ apiKey: process.env.NEXT_PUBLIC_API_KEY, // Optional, for frontend usage
25
+ });
26
+
27
+ // Access your tables
28
+ const products = client.table('products');
29
+ const orders = client.table('orders');
30
+
31
+ // Create a record
32
+ const product = await products.create({
33
+ name: 'Awesome Product',
34
+ price: 29.99,
35
+ category: 'electronics'
36
+ });
37
+
38
+ // Query records
39
+ const electronics = await products.query({
40
+ category: 'electronics'
41
+ });
42
+
43
+ // Get a single record
44
+ const product = await products.get('product-id');
45
+
46
+ // Update a record
47
+ await products.update('product-id', {
48
+ price: 24.99
49
+ });
50
+
51
+ // Delete a record
52
+ await products.delete('product-id');
53
+ ```
54
+
55
+ ## Advanced Usage
56
+
57
+ ### Batch Operations
58
+
59
+ ```typescript
60
+ // Batch get multiple records
61
+ const products = await client.table('products').batchGet([
62
+ 'product-1',
63
+ 'product-2',
64
+ 'product-3'
65
+ ]);
66
+
67
+ // Query with filters
68
+ const expensiveProducts = await client.table('products').query({
69
+ category: 'electronics',
70
+ minPrice: 100
71
+ });
72
+ ```
73
+
74
+ ### Real-time Updates (Coming Soon)
75
+
76
+ ```typescript
77
+ // Subscribe to real-time changes
78
+ const unsubscribe = client.table('orders').subscribe(
79
+ { status: 'pending' },
80
+ (order) => {
81
+ console.log('Order updated:', order);
82
+ }
83
+ );
84
+
85
+ // Cleanup
86
+ unsubscribe();
87
+ ```
88
+
89
+ ## TypeScript Support
90
+
91
+ The SDK is written in TypeScript and provides full type safety:
92
+
93
+ ```typescript
94
+ interface Product {
95
+ productId: string;
96
+ name: string;
97
+ price: number;
98
+ category: string;
99
+ }
100
+
101
+ const products = client.table<Product>('products');
102
+
103
+ // TypeScript will enforce the Product interface
104
+ const product = await products.create({
105
+ name: 'Type-safe Product',
106
+ price: 49.99,
107
+ category: 'electronics'
108
+ });
109
+ ```
110
+
111
+ ## Environment Variables
112
+
113
+ Create a `.env.local` file in your project:
114
+
115
+ ```env
116
+ NEXT_PUBLIC_API_URL=https://api.potatobase.com
117
+ NEXT_PUBLIC_PROJECT_ID=your-project-id
118
+ NEXT_PUBLIC_API_KEY=your-api-key
119
+ ```
120
+
121
+ ## API Reference
122
+
123
+ ### PotatoBaseClient
124
+
125
+ The main client class for interacting with PotatoBase.
126
+
127
+ #### Constructor Options
128
+
129
+ - `apiUrl` (string): The PotatoBase API endpoint
130
+ - `projectId` (string): Your project ID
131
+ - `apiKey` (string, optional): API key for frontend authentication
132
+
133
+ ### Table Methods
134
+
135
+ All table operations return promises and support async/await:
136
+
137
+ - `create(data)`: Create a new record
138
+ - `get(id)`: Get a record by ID
139
+ - `update(id, data)`: Update a record
140
+ - `delete(id)`: Delete a record
141
+ - `query(params)`: Query records with filters
142
+ - `batchGet(ids)`: Get multiple records by IDs
143
+ - `list(options)`: List all records with pagination
144
+
145
+ ## Error Handling
146
+
147
+ ```typescript
148
+ try {
149
+ const product = await products.get('non-existent-id');
150
+ } catch (error) {
151
+ if (error.code === 'NOT_FOUND') {
152
+ console.log('Product not found');
153
+ } else {
154
+ console.error('Unexpected error:', error);
155
+ }
156
+ }
157
+ ```
158
+
159
+ ## Contributing
160
+
161
+ We welcome contributions! Please see our [Contributing Guide](https://github.com/potatobase/client/blob/main/CONTRIBUTING.md) for details.
162
+
163
+ ## License
164
+
165
+ MIT © PotatoBase Team
166
+
167
+ ## Support
168
+
169
+ - Documentation: [https://docs.potatobase.com](https://docs.potatobase.com)
170
+ - GitHub Issues: [https://github.com/potatobase/client/issues](https://github.com/potatobase/client/issues)
171
+ - Discord: [Join our community](https://discord.gg/potatobase)
@@ -0,0 +1,460 @@
1
+ /**
2
+ * PotatoBase Client Types
3
+ *
4
+ * Public type definitions for the SDK
5
+ */
6
+ /**
7
+ * Client configuration
8
+ */
9
+ interface ClientConfig {
10
+ /** Project ID (from PotatoBase dashboard) */
11
+ projectId: string;
12
+ /** API key for authentication */
13
+ apiKey: string;
14
+ /** Optional: Custom API URL (defaults to production) */
15
+ apiUrl?: string;
16
+ /** Optional: Enable debug logging */
17
+ debug?: boolean;
18
+ }
19
+ /**
20
+ * Range condition for filtering by date or number fields
21
+ */
22
+ interface RangeCondition {
23
+ /** Field name to filter on (e.g., 'createdAt', 'price') */
24
+ field: string;
25
+ /** Greater than or equal */
26
+ gte?: string | number;
27
+ /** Less than or equal */
28
+ lte?: string | number;
29
+ /** Greater than */
30
+ gt?: string | number;
31
+ /** Less than */
32
+ lt?: string | number;
33
+ /** Between two values (inclusive) */
34
+ between?: [string | number, string | number];
35
+ }
36
+ /**
37
+ * Query parameters for table queries
38
+ */
39
+ interface QueryParams<TRecord = any> {
40
+ /** GSI index name (e.g., 'byCategory') */
41
+ index?: string;
42
+ /** Filter conditions */
43
+ where?: Partial<TRecord>;
44
+ /** Range condition for date/number filtering */
45
+ range?: RangeCondition;
46
+ /** Max number of results */
47
+ limit?: number;
48
+ /** Pagination cursor */
49
+ cursor?: string;
50
+ }
51
+ /**
52
+ * Query result with pagination
53
+ */
54
+ interface QueryResult<TRecord> {
55
+ /** Array of records */
56
+ data: TRecord[];
57
+ /** Pagination cursor (if more results available) */
58
+ cursor?: string;
59
+ }
60
+ /**
61
+ * Type generator result
62
+ */
63
+ interface TypeGenerationResult {
64
+ /** Generated TypeScript types as string */
65
+ types: string;
66
+ }
67
+ /**
68
+ * Error response from API
69
+ */
70
+ interface ApiError {
71
+ message: string;
72
+ code?: string;
73
+ details?: any;
74
+ }
75
+
76
+ /**
77
+ * TableClient
78
+ *
79
+ * Provides type-safe CRUD operations for a specific table.
80
+ * Each table in your database gets its own TableClient instance.
81
+ *
82
+ * Example:
83
+ * ```typescript
84
+ * const products = pb.table('products');
85
+ * const items = await products.query({ where: { category: 'clothing' } });
86
+ * ```
87
+ */
88
+ declare class TableClient<TRecord extends {
89
+ id: string;
90
+ } = any> {
91
+ private apiUrl;
92
+ private apiKey;
93
+ private projectId;
94
+ private tableName;
95
+ private debug;
96
+ constructor(apiUrl: string, apiKey: string, projectId: string, tableName: string, debug?: boolean);
97
+ private callAPI;
98
+ /**
99
+ * Query records from the table
100
+ *
101
+ * @param params - Query parameters (index, where, range, limit, cursor)
102
+ * @returns Query result with data and optional cursor
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * // Query by primary key
107
+ * const result = await products.query({ where: { id: 'prod-1' } });
108
+ *
109
+ * // Query by GSI
110
+ * const result = await products.query({
111
+ * index: 'byCategory',
112
+ * where: { category: 'clothing' },
113
+ * limit: 10
114
+ * });
115
+ *
116
+ * // Query with date range
117
+ * const result = await products.query({
118
+ * index: 'byCategory',
119
+ * where: { category: 'clothing' },
120
+ * range: {
121
+ * field: 'createdAt',
122
+ * gte: '2025-01-01',
123
+ * lte: '2025-01-31'
124
+ * }
125
+ * });
126
+ * ```
127
+ */
128
+ query(params?: QueryParams<TRecord>): Promise<TRecord[]>;
129
+ /**
130
+ * Get a single record by ID
131
+ *
132
+ * @param id - Record ID
133
+ * @returns Record or null if not found
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const product = await products.get('prod-1');
138
+ * ```
139
+ */
140
+ get(id: string): Promise<TRecord | null>;
141
+ /**
142
+ * Insert a new record
143
+ *
144
+ * @param data - Record data (must include 'id' field)
145
+ * @returns Created record
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const newProduct = await products.insert({
150
+ * id: 'prod-1',
151
+ * title: 'T-Shirt',
152
+ * price: 29.99,
153
+ * category: 'clothing'
154
+ * });
155
+ * ```
156
+ */
157
+ insert(data: TRecord): Promise<TRecord>;
158
+ /**
159
+ * Update an existing record
160
+ *
161
+ * @param id - Record ID
162
+ * @param data - Fields to update
163
+ * @returns Updated record
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * const updated = await products.update('prod-1', {
168
+ * price: 24.99,
169
+ * stock: 100
170
+ * });
171
+ * ```
172
+ */
173
+ update(id: string, data: Partial<Omit<TRecord, 'id'>>): Promise<TRecord>;
174
+ /**
175
+ * Delete a record
176
+ *
177
+ * @param id - Record ID
178
+ * @returns Success status
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * await products.delete('prod-1');
183
+ * ```
184
+ */
185
+ delete(id: string): Promise<{
186
+ success: boolean;
187
+ }>;
188
+ /**
189
+ * Create a new record (alias for insert)
190
+ *
191
+ * @param data - Record data (must include 'id' field)
192
+ * @returns Created record
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * const newProduct = await products.create({
197
+ * id: 'prod-1',
198
+ * title: 'T-Shirt',
199
+ * price: 29.99,
200
+ * category: 'clothing'
201
+ * });
202
+ * ```
203
+ */
204
+ create(data: TRecord): Promise<TRecord>;
205
+ /**
206
+ * Alias for query() - chainable method
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * const items = await products.from().query({ limit: 10 });
211
+ * ```
212
+ */
213
+ from(): this;
214
+ }
215
+
216
+ /**
217
+ * Helper functions for date range queries
218
+ *
219
+ * These functions make it easier to construct range conditions
220
+ * for common date/time filtering scenarios.
221
+ */
222
+
223
+ /**
224
+ * Get ISO date string for N days ago from now
225
+ *
226
+ * @param days - Number of days ago
227
+ * @returns ISO date string
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * daysAgo(7) // "2025-01-21T10:30:00.000Z" (if today is Jan 28)
232
+ * daysAgo(30) // "2024-12-29T10:30:00.000Z"
233
+ * ```
234
+ */
235
+ declare function daysAgo(days: number): string;
236
+ /**
237
+ * Get ISO date string for N hours ago from now
238
+ *
239
+ * @param hours - Number of hours ago
240
+ * @returns ISO date string
241
+ */
242
+ declare function hoursAgo(hours: number): string;
243
+ /**
244
+ * Get ISO date string for N minutes ago from now
245
+ *
246
+ * @param minutes - Number of minutes ago
247
+ * @returns ISO date string
248
+ */
249
+ declare function minutesAgo(minutes: number): string;
250
+ /**
251
+ * Get range condition for last N days
252
+ *
253
+ * @param field - Field name (e.g., 'createdAt')
254
+ * @param days - Number of days to go back
255
+ * @returns RangeCondition object
256
+ *
257
+ * @example
258
+ * ```typescript
259
+ * // Get orders from last 7 days
260
+ * await pb.table('orders').query({
261
+ * index: 'byCustomer',
262
+ * where: { customerId: 'customer-1' },
263
+ * range: lastDays('createdAt', 7)
264
+ * });
265
+ * ```
266
+ */
267
+ declare function lastDays(field: string, days: number): RangeCondition;
268
+ /**
269
+ * Get range condition for date between two dates
270
+ *
271
+ * @param field - Field name (e.g., 'createdAt')
272
+ * @param startDate - Start date (inclusive)
273
+ * @param endDate - End date (inclusive)
274
+ * @returns RangeCondition object
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * // Get orders from January 2025
279
+ * await pb.table('orders').query({
280
+ * index: 'byCustomer',
281
+ * where: { customerId: 'customer-1' },
282
+ * range: between('createdAt', '2025-01-01', '2025-01-31')
283
+ * });
284
+ * ```
285
+ */
286
+ declare function between(field: string, startDate: string, endDate: string): RangeCondition;
287
+ /**
288
+ * Get range condition for dates since a specific date
289
+ *
290
+ * @param field - Field name (e.g., 'createdAt')
291
+ * @param date - Start date (inclusive)
292
+ * @returns RangeCondition object
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * // Get all orders since Jan 1, 2025
297
+ * await pb.table('orders').query({
298
+ * index: 'byStatus',
299
+ * where: { status: 'delivered' },
300
+ * range: since('createdAt', '2025-01-01')
301
+ * });
302
+ * ```
303
+ */
304
+ declare function since(field: string, date: string): RangeCondition;
305
+ /**
306
+ * Get range condition for dates until a specific date
307
+ *
308
+ * @param field - Field name (e.g., 'createdAt')
309
+ * @param date - End date (inclusive)
310
+ * @returns RangeCondition object
311
+ *
312
+ * @example
313
+ * ```typescript
314
+ * // Get all orders until Dec 31, 2024
315
+ * await pb.table('orders').query({
316
+ * index: 'byCustomer',
317
+ * where: { customerId: 'customer-1' },
318
+ * range: until('createdAt', '2024-12-31')
319
+ * });
320
+ * ```
321
+ */
322
+ declare function until(field: string, date: string): RangeCondition;
323
+ /**
324
+ * Get range condition for this month
325
+ *
326
+ * @param field - Field name (e.g., 'createdAt')
327
+ * @returns RangeCondition object
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * // Get orders from this month
332
+ * await pb.table('orders').query({
333
+ * index: 'byStatus',
334
+ * where: { status: 'processing' },
335
+ * range: thisMonth('createdAt')
336
+ * });
337
+ * ```
338
+ */
339
+ declare function thisMonth(field: string): RangeCondition;
340
+ /**
341
+ * Get range condition for this year
342
+ *
343
+ * @param field - Field name (e.g., 'publishedAt')
344
+ * @returns RangeCondition object
345
+ */
346
+ declare function thisYear(field: string): RangeCondition;
347
+ /**
348
+ * Get range condition for today
349
+ *
350
+ * @param field - Field name (e.g., 'createdAt')
351
+ * @returns RangeCondition object
352
+ */
353
+ declare function today(field: string): RangeCondition;
354
+
355
+ /**
356
+ * @potatobase/client
357
+ *
358
+ * Official JavaScript/TypeScript client for PotatoBase.
359
+ * Type-safe, easy-to-use SDK for querying your DynamoDB data.
360
+ *
361
+ * @example
362
+ * ```typescript
363
+ * import { createClient } from '@potatobase/client';
364
+ * import type { Database } from './types/database';
365
+ *
366
+ * const pb = createClient<Database>({
367
+ * projectId: 'proj_abc123',
368
+ * apiKey: 'pk_live_xyz...',
369
+ * });
370
+ *
371
+ * // Type-safe queries!
372
+ * const products = await pb.table('products').query({
373
+ * index: 'byCategory',
374
+ * where: { category: 'clothing' }
375
+ * });
376
+ * ```
377
+ */
378
+
379
+ /**
380
+ * PotatoBaseClient
381
+ *
382
+ * Main client class for interacting with PotatoBase.
383
+ * Provides access to tables and utility methods.
384
+ */
385
+ declare class PotatoBaseClient<TDatabase = any> {
386
+ private config;
387
+ private tableClients;
388
+ constructor(config: ClientConfig);
389
+ /**
390
+ * Access a table by name
391
+ *
392
+ * Returns a TableClient instance for performing CRUD operations.
393
+ * TableClient instances are cached for performance.
394
+ *
395
+ * @param tableName - Name of the table
396
+ * @returns TableClient for the specified table
397
+ *
398
+ * @example
399
+ * ```typescript
400
+ * const products = pb.table('products');
401
+ * const items = await products.query({ limit: 10 });
402
+ * ```
403
+ */
404
+ table<TTable extends keyof TDatabase>(tableName: TTable): TableClient<TDatabase[TTable] extends infer R ? R & {
405
+ id: string;
406
+ } : any>;
407
+ /**
408
+ * Generate TypeScript types for your project
409
+ *
410
+ * Fetches the current schema and generates TypeScript interface definitions.
411
+ * Save the result to a .d.ts file in your project.
412
+ *
413
+ * @returns Generated TypeScript types as string
414
+ *
415
+ * @example
416
+ * ```typescript
417
+ * const types = await pb.generateTypes();
418
+ * fs.writeFileSync('./types/database.d.ts', types);
419
+ * ```
420
+ */
421
+ generateTypes(): Promise<string>;
422
+ /**
423
+ * Get the project ID
424
+ */
425
+ getProjectId(): string;
426
+ /**
427
+ * Get the API URL
428
+ */
429
+ getApiUrl(): string;
430
+ /**
431
+ * Clear all cached table clients
432
+ *
433
+ * Useful for testing or when you want to force fresh clients.
434
+ */
435
+ clearCache(): void;
436
+ /**
437
+ * Enable/disable debug logging
438
+ */
439
+ setDebug(enabled: boolean): void;
440
+ }
441
+ /**
442
+ * Create a new PotatoBase client
443
+ *
444
+ * @param config - Client configuration
445
+ * @returns PotatoBaseClient instance
446
+ *
447
+ * @example
448
+ * ```typescript
449
+ * import { createClient } from '@potatobase/client';
450
+ * import type { Database } from './types/database';
451
+ *
452
+ * const pb = createClient<Database>({
453
+ * projectId: 'proj_abc123',
454
+ * apiKey: 'pk_live_xyz...',
455
+ * });
456
+ * ```
457
+ */
458
+ declare function createClient<TDatabase = any>(config: ClientConfig): PotatoBaseClient<TDatabase>;
459
+
460
+ export { type ApiError, type ClientConfig, PotatoBaseClient, type QueryParams, type QueryResult, type RangeCondition, TableClient, type TypeGenerationResult, between, createClient, daysAgo, hoursAgo, lastDays, minutesAgo, since, thisMonth, thisYear, today, until };