@seaverse/dataservice 1.0.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.
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Core type definitions for SeaVerse Data Service SDK
3
+ *
4
+ * These types are designed to be AI-friendly:
5
+ * - Clear, descriptive names
6
+ * - Self-documenting structure
7
+ * - Rich JSDoc comments
8
+ */
9
+ /**
10
+ * Configuration options for creating a Data Service client
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const config: ClientConfig = {
15
+ * url: 'https://your-postgrest-api.example.com',
16
+ * token: 'Bearer your-jwt-token-here',
17
+ * };
18
+ * ```
19
+ */
20
+ interface ClientConfig {
21
+ /** PostgREST API base URL */
22
+ url: string;
23
+ /** JWT token containing user_id in payload.user_id */
24
+ token: string;
25
+ /** Optional configuration */
26
+ options?: {
27
+ /** Custom fetch implementation (useful for Node.js < 18) */
28
+ fetch?: typeof fetch;
29
+ /** Additional HTTP headers to include in all requests */
30
+ headers?: Record<string, string>;
31
+ /** Request timeout in milliseconds (default: 30000) */
32
+ timeout?: number;
33
+ };
34
+ }
35
+ /**
36
+ * Data record structure returned from the database
37
+ *
38
+ * @template T - Type of the data field (flexible JSONB)
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * type Order = DataRecord<{
43
+ * order_number: string;
44
+ * status: string;
45
+ * total: number;
46
+ * }>;
47
+ * ```
48
+ */
49
+ interface DataRecord<T = any> {
50
+ /** UUID primary key (database-generated or client-provided) */
51
+ id: string;
52
+ /** User ID (auto-filled from JWT token) */
53
+ user_id: string;
54
+ /** Application identifier */
55
+ app_id: string;
56
+ /** Collection name (like MongoDB collection) */
57
+ collection_name: string;
58
+ /** Flexible JSONB data field */
59
+ data: T;
60
+ /** Creation timestamp (auto-filled) */
61
+ created_at: string;
62
+ /** Last update timestamp (auto-updated) */
63
+ updated_at: string;
64
+ /** Soft delete timestamp (null if not deleted) */
65
+ deleted_at: string | null;
66
+ }
67
+ /**
68
+ * Query filter operators for building complex queries
69
+ *
70
+ * AI-friendly: Each operator has a clear, predictable name
71
+ */
72
+ interface QueryFilter {
73
+ /** Field path (supports JSONB paths like 'data->status') */
74
+ field: string;
75
+ /** Operator type */
76
+ operator: 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'ilike' | 'in' | 'contains' | 'overlaps';
77
+ /** Value to compare against */
78
+ value: any;
79
+ }
80
+ /**
81
+ * Query builder options for ordering results
82
+ */
83
+ interface OrderOptions {
84
+ /** Sort in descending order (default: false) */
85
+ descending?: boolean;
86
+ /** Handle null values (first or last) */
87
+ nullsFirst?: boolean;
88
+ }
89
+ /**
90
+ * Statistics about user's data
91
+ *
92
+ * Returned by getStats() RPC function
93
+ */
94
+ interface UserDataStats {
95
+ /** Total number of records (including deleted) */
96
+ total_records: number;
97
+ /** Number of active (non-deleted) records */
98
+ active_records: number;
99
+ /** Number of soft-deleted records */
100
+ deleted_records: number;
101
+ /** Number of unique app_ids */
102
+ total_apps: number;
103
+ /** Number of unique collection_names */
104
+ total_collections: number;
105
+ }
106
+ /**
107
+ * Error response from PostgREST API
108
+ */
109
+ interface APIError {
110
+ /** Error code (e.g., '23505' for unique constraint violation) */
111
+ code?: string;
112
+ /** Human-readable error message */
113
+ message: string;
114
+ /** Additional error details */
115
+ details?: string;
116
+ /** Hint for resolving the error */
117
+ hint?: string;
118
+ }
119
+ /**
120
+ * Custom error class for SDK errors
121
+ *
122
+ * AI-friendly: Clear error types and messages
123
+ */
124
+ declare class DataServiceError extends Error {
125
+ code?: string | undefined;
126
+ details?: string | undefined;
127
+ hint?: string | undefined;
128
+ statusCode?: number | undefined;
129
+ constructor(message: string, code?: string | undefined, details?: string | undefined, hint?: string | undefined, statusCode?: number | undefined);
130
+ }
131
+ /**
132
+ * Query builder interface for fluent API
133
+ *
134
+ * AI-friendly: Method chaining with clear intent
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const results = await query
139
+ * .eq('status', 'active')
140
+ * .gt('total', 100)
141
+ * .order('created_at', { descending: true })
142
+ * .limit(20);
143
+ * ```
144
+ */
145
+ interface QueryBuilder<T = any> {
146
+ /** Filter: field equals value */
147
+ eq(field: string, value: any): QueryBuilder<T>;
148
+ /** Filter: field not equals value */
149
+ neq(field: string, value: any): QueryBuilder<T>;
150
+ /** Filter: field greater than value */
151
+ gt(field: string, value: any): QueryBuilder<T>;
152
+ /** Filter: field greater than or equal to value */
153
+ gte(field: string, value: any): QueryBuilder<T>;
154
+ /** Filter: field less than value */
155
+ lt(field: string, value: any): QueryBuilder<T>;
156
+ /** Filter: field less than or equal to value */
157
+ lte(field: string, value: any): QueryBuilder<T>;
158
+ /** Filter: field matches pattern (case-sensitive) */
159
+ like(field: string, pattern: string): QueryBuilder<T>;
160
+ /** Filter: field matches pattern (case-insensitive) */
161
+ ilike(field: string, pattern: string): QueryBuilder<T>;
162
+ /** Filter: field value in array */
163
+ in(field: string, values: any[]): QueryBuilder<T>;
164
+ /** Filter: JSONB contains value */
165
+ contains(value: Record<string, any>): QueryBuilder<T>;
166
+ /** Filter: JSONB overlaps with value */
167
+ overlaps(value: Record<string, any>): QueryBuilder<T>;
168
+ /** Order results by field */
169
+ order(field: string, options?: OrderOptions): QueryBuilder<T>;
170
+ /** Limit number of results */
171
+ limit(count: number): QueryBuilder<T>;
172
+ /** Skip number of results (pagination) */
173
+ offset(count: number): QueryBuilder<T>;
174
+ /** Execute query and return results */
175
+ execute(): Promise<DataRecord<T>[]>;
176
+ /** Execute query and return count */
177
+ count(): Promise<number>;
178
+ }
179
+ /**
180
+ * Collection interface for CRUD operations
181
+ *
182
+ * AI-friendly: Clear method names indicating intent
183
+ */
184
+ interface Collection<T = any> {
185
+ /** Insert a new record (optionally provide UUID) */
186
+ insert(data: T, id?: string): Promise<DataRecord<T>>;
187
+ /** Get a single record by ID (alias for selectById) */
188
+ get(id: string): Promise<DataRecord<T> | null>;
189
+ /** Select records with optional filters */
190
+ select(): QueryBuilder<T>;
191
+ /** Select a single record by ID */
192
+ selectById(id: string): Promise<DataRecord<T> | null>;
193
+ /** Update a record by ID (replaces entire data field) */
194
+ update(id: string, data: T): Promise<DataRecord<T>>;
195
+ /** Patch a record by ID (merges with existing data) */
196
+ patch(id: string, partial: Partial<T>): Promise<DataRecord<T>>;
197
+ /** Hard delete a record by ID */
198
+ delete(id: string): Promise<void>;
199
+ /** Soft delete a record by ID (sets deleted_at) */
200
+ softDelete(id: string): Promise<boolean>;
201
+ /** Restore a soft-deleted record */
202
+ restore(id: string): Promise<boolean>;
203
+ /** Search records by JSONB contains */
204
+ search(criteria: Partial<T>): Promise<DataRecord<T>[]>;
205
+ /** Count records in collection */
206
+ count(): Promise<number>;
207
+ }
208
+ /**
209
+ * Data table interface for accessing collections within a specific table
210
+ *
211
+ * Represents a physical database table (e.g., user_data, public_data)
212
+ */
213
+ interface DataTable {
214
+ /** Get a collection from this table */
215
+ collection<T = any>(name: string): Collection<T>;
216
+ /** Batch insert multiple records into different collections */
217
+ batchInsert<T = any>(baseCollectionName: string, records: T[]): Promise<DataRecord<T>[]>;
218
+ }
219
+ /**
220
+ * Main client interface
221
+ *
222
+ * AI-friendly: Entry point with clear hierarchy
223
+ */
224
+ interface DataServiceClient {
225
+ /** Automatically extracted application ID from current URL */
226
+ readonly appId: string;
227
+ /** Access user private data table (user_data) */
228
+ readonly userData: DataTable;
229
+ /** Get user data statistics (RPC call) */
230
+ getStats(): Promise<UserDataStats>;
231
+ /** Health check (RPC call) */
232
+ health(): Promise<{
233
+ status: string;
234
+ user_id: string;
235
+ }>;
236
+ }
237
+
238
+ /**
239
+ * Core client implementation for SeaVerse Data Service SDK
240
+ *
241
+ * Design principles:
242
+ * 1. AI-friendly: Clear method names, predictable behavior
243
+ * 2. Type-safe: Full TypeScript support
244
+ * 3. Chainable: Fluent API for query building
245
+ * 4. Secure: RLS enforced, token-based auth
246
+ */
247
+
248
+ /**
249
+ * Create a new Data Service client
250
+ *
251
+ * AI-friendly: Single entry point with clear configuration
252
+ *
253
+ * @param config - Client configuration with URL and JWT token
254
+ * @returns DataServiceClient instance
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * const client = createClient({
259
+ * url: 'https://your-postgrest-api.example.com',
260
+ * token: 'Bearer your-jwt-token-here',
261
+ * });
262
+ *
263
+ * // appId is automatically extracted from current URL
264
+ * // Direct access to collections - clean and simple
265
+ * const order = await client.userData.collection('orders').insert({ ... });
266
+ * const orders = await client.userData.collection('orders').select().execute();
267
+ * ```
268
+ */
269
+ declare function createClient(config: ClientConfig): DataServiceClient;
270
+
271
+ /**
272
+ * SeaVerse Data Service SDK
273
+ *
274
+ * AI-Friendly Universal Data Storage for TypeScript/JavaScript
275
+ *
276
+ * @packageDocumentation
277
+ *
278
+ * @example Basic Usage
279
+ * ```typescript
280
+ * import { createClient } from '@seaverse/data-service-sdk';
281
+ *
282
+ * // appId is automatically extracted from current URL
283
+ * const client = createClient({
284
+ * url: 'https://postgrest.example.com',
285
+ * token: 'your-jwt-token',
286
+ * });
287
+ *
288
+ * // Insert data - appId is automatically included
289
+ * const order = await client.userData.collection('orders').insert({
290
+ * order_number: 'ORD-123',
291
+ * status: 'pending',
292
+ * total: 99.99,
293
+ * });
294
+ *
295
+ * // Query data
296
+ * const orders = await client.userData
297
+ * .collection('orders')
298
+ * .select()
299
+ * .eq('status', 'pending')
300
+ * .order('created_at', { descending: true })
301
+ * .limit(10)
302
+ * .execute();
303
+ * ```
304
+ */
305
+
306
+ declare const VERSION = "1.0.0";
307
+
308
+ export { type APIError, type ClientConfig, type Collection, type DataRecord, type DataServiceClient, DataServiceError, type DataTable, type OrderOptions, type QueryBuilder, type QueryFilter, type UserDataStats, VERSION, createClient };
package/dist/index.js ADDED
@@ -0,0 +1,371 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ DataServiceError: () => DataServiceError,
24
+ VERSION: () => VERSION,
25
+ createClient: () => createClient
26
+ });
27
+ module.exports = __toCommonJS(src_exports);
28
+
29
+ // src/types.ts
30
+ var DataServiceError = class extends Error {
31
+ constructor(message, code, details, hint, statusCode) {
32
+ super(message);
33
+ this.code = code;
34
+ this.details = details;
35
+ this.hint = hint;
36
+ this.statusCode = statusCode;
37
+ this.name = "DataServiceError";
38
+ }
39
+ };
40
+
41
+ // src/client.ts
42
+ function extractAppId() {
43
+ if (typeof globalThis !== "undefined" && "location" in globalThis) {
44
+ const location = globalThis.location;
45
+ const hostname = location.hostname;
46
+ const withoutSeaverse = hostname.replace(/\.app\.seaverse\.ai$/, "").replace(/\.seaverse\.ai$/, "");
47
+ return withoutSeaverse !== hostname ? withoutSeaverse : hostname;
48
+ }
49
+ if (typeof process !== "undefined" && process.env) {
50
+ return process.env.SEAVERSE_APP_ID || "default";
51
+ }
52
+ return "default";
53
+ }
54
+ var HTTPClient = class {
55
+ baseUrl;
56
+ headers;
57
+ fetchFn;
58
+ timeout;
59
+ constructor(config) {
60
+ this.baseUrl = config.url.replace(/\/$/, "");
61
+ this.fetchFn = config.options?.fetch || globalThis.fetch;
62
+ this.timeout = config.options?.timeout || 3e4;
63
+ this.headers = {
64
+ "Authorization": config.token,
65
+ "Content-Type": "application/json",
66
+ "Prefer": "return=representation",
67
+ ...config.options?.headers
68
+ };
69
+ }
70
+ /**
71
+ * Make HTTP request with timeout and error handling
72
+ */
73
+ async request(method, path, body, additionalHeaders) {
74
+ const controller = new AbortController();
75
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
76
+ try {
77
+ const response = await this.fetchFn(`${this.baseUrl}${path}`, {
78
+ method,
79
+ headers: { ...this.headers, ...additionalHeaders },
80
+ body: body ? JSON.stringify(body) : void 0,
81
+ signal: controller.signal
82
+ });
83
+ clearTimeout(timeoutId);
84
+ if (!response.ok) {
85
+ let error;
86
+ try {
87
+ error = await response.json();
88
+ } catch {
89
+ error = { message: response.statusText };
90
+ }
91
+ throw new DataServiceError(
92
+ error.message || "Request failed",
93
+ error.code,
94
+ error.details,
95
+ error.hint,
96
+ response.status
97
+ );
98
+ }
99
+ const text = await response.text();
100
+ return text ? JSON.parse(text) : null;
101
+ } catch (error) {
102
+ clearTimeout(timeoutId);
103
+ if (error instanceof DataServiceError) {
104
+ throw error;
105
+ }
106
+ if (error.name === "AbortError") {
107
+ throw new DataServiceError("Request timeout", "TIMEOUT");
108
+ }
109
+ throw new DataServiceError(
110
+ error.message || "Unknown error",
111
+ "NETWORK_ERROR"
112
+ );
113
+ }
114
+ }
115
+ async get(path, params) {
116
+ const query = params ? "?" + new URLSearchParams(params).toString() : "";
117
+ return this.request("GET", `${path}${query}`);
118
+ }
119
+ async post(path, body, headers) {
120
+ return this.request("POST", path, body, headers);
121
+ }
122
+ async patch(path, body) {
123
+ return this.request("PATCH", path, body);
124
+ }
125
+ async delete(path) {
126
+ await this.request("DELETE", path);
127
+ }
128
+ };
129
+ var QueryBuilderImpl = class {
130
+ constructor(client, tablePath, appId, collectionName) {
131
+ this.client = client;
132
+ this.tablePath = tablePath;
133
+ this.appId = appId;
134
+ this.collectionName = collectionName;
135
+ }
136
+ filters = [];
137
+ ordering = null;
138
+ limitValue = null;
139
+ offsetValue = null;
140
+ eq(field, value) {
141
+ this.filters.push(`${field}=eq.${encodeURIComponent(String(value))}`);
142
+ return this;
143
+ }
144
+ neq(field, value) {
145
+ this.filters.push(`${field}=neq.${encodeURIComponent(String(value))}`);
146
+ return this;
147
+ }
148
+ gt(field, value) {
149
+ this.filters.push(`${field}=gt.${encodeURIComponent(String(value))}`);
150
+ return this;
151
+ }
152
+ gte(field, value) {
153
+ this.filters.push(`${field}=gte.${encodeURIComponent(String(value))}`);
154
+ return this;
155
+ }
156
+ lt(field, value) {
157
+ this.filters.push(`${field}=lt.${encodeURIComponent(String(value))}`);
158
+ return this;
159
+ }
160
+ lte(field, value) {
161
+ this.filters.push(`${field}=lte.${encodeURIComponent(String(value))}`);
162
+ return this;
163
+ }
164
+ like(field, pattern) {
165
+ this.filters.push(`${field}=like.${encodeURIComponent(pattern)}`);
166
+ return this;
167
+ }
168
+ ilike(field, pattern) {
169
+ this.filters.push(`${field}=ilike.${encodeURIComponent(pattern)}`);
170
+ return this;
171
+ }
172
+ in(field, values) {
173
+ const encoded = values.map((v) => encodeURIComponent(String(v))).join(",");
174
+ this.filters.push(`${field}=in.(${encoded})`);
175
+ return this;
176
+ }
177
+ contains(value) {
178
+ this.filters.push(`data=@>.${encodeURIComponent(JSON.stringify(value))}`);
179
+ return this;
180
+ }
181
+ overlaps(value) {
182
+ this.filters.push(`data=&&.${encodeURIComponent(JSON.stringify(value))}`);
183
+ return this;
184
+ }
185
+ order(field, options = {}) {
186
+ let orderStr = field;
187
+ if (options.descending)
188
+ orderStr += ".desc";
189
+ if (options.nullsFirst !== void 0) {
190
+ orderStr += options.nullsFirst ? ".nullsfirst" : ".nullslast";
191
+ }
192
+ this.ordering = orderStr;
193
+ return this;
194
+ }
195
+ limit(count) {
196
+ this.limitValue = count;
197
+ return this;
198
+ }
199
+ offset(count) {
200
+ this.offsetValue = count;
201
+ return this;
202
+ }
203
+ async execute() {
204
+ const params = {
205
+ app_id: `eq.${this.appId}`,
206
+ collection_name: `eq.${this.collectionName}`,
207
+ ...Object.fromEntries(this.filters.map((f, i) => [`filter${i}`, f]))
208
+ };
209
+ if (this.ordering)
210
+ params.order = this.ordering;
211
+ if (this.limitValue !== null)
212
+ params.limit = String(this.limitValue);
213
+ if (this.offsetValue !== null)
214
+ params.offset = String(this.offsetValue);
215
+ return this.client.get(this.tablePath, params);
216
+ }
217
+ async count() {
218
+ const params = {
219
+ app_id: `eq.${this.appId}`,
220
+ collection_name: `eq.${this.collectionName}`,
221
+ ...Object.fromEntries(this.filters.map((f, i) => [`filter${i}`, f]))
222
+ };
223
+ const response = await this.client.get(this.tablePath, {
224
+ ...params,
225
+ select: "count"
226
+ });
227
+ return response.length;
228
+ }
229
+ };
230
+ var CollectionImpl = class {
231
+ constructor(client, tablePath, appId, collectionName) {
232
+ this.client = client;
233
+ this.tablePath = tablePath;
234
+ this.appId = appId;
235
+ this.collectionName = collectionName;
236
+ }
237
+ async insert(data, id) {
238
+ const payload = {
239
+ app_id: this.appId,
240
+ collection_name: this.collectionName,
241
+ data
242
+ };
243
+ if (id) {
244
+ payload.id = id;
245
+ }
246
+ const response = await this.client.post(this.tablePath, payload);
247
+ return Array.isArray(response) ? response[0] : response;
248
+ }
249
+ async get(id) {
250
+ return this.selectById(id);
251
+ }
252
+ select() {
253
+ return new QueryBuilderImpl(this.client, this.tablePath, this.appId, this.collectionName);
254
+ }
255
+ async selectById(id) {
256
+ try {
257
+ const results = await this.client.get(
258
+ `/user_data?id=eq.${id}&app_id=eq.${this.appId}&collection_name=eq.${this.collectionName}`
259
+ );
260
+ return results[0] || null;
261
+ } catch (error) {
262
+ if (error.statusCode === 404) {
263
+ return null;
264
+ }
265
+ throw error;
266
+ }
267
+ }
268
+ async update(id, data) {
269
+ const response = await this.client.patch(
270
+ `/user_data?id=eq.${id}&app_id=eq.${this.appId}&collection_name=eq.${this.collectionName}`,
271
+ { data }
272
+ );
273
+ return Array.isArray(response) ? response[0] : response;
274
+ }
275
+ async patch(id, partial) {
276
+ const existing = await this.selectById(id);
277
+ if (!existing) {
278
+ throw new DataServiceError(`Record with id ${id} not found`, "NOT_FOUND");
279
+ }
280
+ const merged = { ...existing.data, ...partial };
281
+ return this.update(id, merged);
282
+ }
283
+ async delete(id) {
284
+ await this.client.delete(
285
+ `/user_data?id=eq.${id}&app_id=eq.${this.appId}&collection_name=eq.${this.collectionName}`
286
+ );
287
+ }
288
+ async softDelete(id) {
289
+ const response = await this.client.post("/rpc/soft_delete_user_data", {
290
+ p_id: id
291
+ });
292
+ return response;
293
+ }
294
+ async restore(id) {
295
+ const response = await this.client.post("/rpc/restore_user_data", {
296
+ p_id: id
297
+ });
298
+ return response;
299
+ }
300
+ async search(criteria) {
301
+ return this.client.get(this.tablePath, {
302
+ app_id: `eq.${this.appId}`,
303
+ collection_name: `eq.${this.collectionName}`,
304
+ data: `@>.${JSON.stringify(criteria)}`
305
+ });
306
+ }
307
+ async count() {
308
+ const results = await this.client.get(this.tablePath, {
309
+ app_id: `eq.${this.appId}`,
310
+ collection_name: `eq.${this.collectionName}`
311
+ });
312
+ return results.length;
313
+ }
314
+ };
315
+ var DataTableImpl = class {
316
+ constructor(client, tablePath, appId) {
317
+ this.client = client;
318
+ this.tablePath = tablePath;
319
+ this.appId = appId;
320
+ }
321
+ collection(name) {
322
+ return new CollectionImpl(this.client, this.tablePath, this.appId, name);
323
+ }
324
+ async batchInsert(baseCollectionName, records) {
325
+ const results = [];
326
+ for (let i = 0; i < records.length; i++) {
327
+ const uniqueCollectionName = `${baseCollectionName}_${Date.now()}_${i}`;
328
+ const collection = new CollectionImpl(
329
+ this.client,
330
+ this.tablePath,
331
+ this.appId,
332
+ uniqueCollectionName
333
+ );
334
+ const result = await collection.insert(records[i]);
335
+ results.push(result);
336
+ if (i < records.length - 1) {
337
+ await new Promise((resolve) => setTimeout(resolve, 1));
338
+ }
339
+ }
340
+ return results;
341
+ }
342
+ };
343
+ var DataServiceClientImpl = class {
344
+ client;
345
+ userData;
346
+ appId;
347
+ constructor(config) {
348
+ this.client = new HTTPClient(config);
349
+ this.appId = extractAppId();
350
+ this.userData = new DataTableImpl(this.client, "/user_data", this.appId);
351
+ }
352
+ async getStats() {
353
+ const response = await this.client.post("/rpc/get_user_data_stats");
354
+ return Array.isArray(response) ? response[0] : response;
355
+ }
356
+ async health() {
357
+ return this.client.post("/rpc/health");
358
+ }
359
+ };
360
+ function createClient(config) {
361
+ return new DataServiceClientImpl(config);
362
+ }
363
+
364
+ // src/index.ts
365
+ var VERSION = "1.0.0";
366
+ // Annotate the CommonJS export names for ESM import in node:
367
+ 0 && (module.exports = {
368
+ DataServiceError,
369
+ VERSION,
370
+ createClient
371
+ });