@fenaura/sdk 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.
@@ -0,0 +1,376 @@
1
+ /**
2
+ * Fenaura Client SDK - TypeScript Types
3
+ */
4
+
5
+ // ─── Query Operations ────────────────────────────────────────────────────────
6
+
7
+ type QueryOperation =
8
+ | 'select'
9
+ | 'insert'
10
+ | 'update'
11
+ | 'upsert'
12
+ | 'delete'
13
+ | 'rpc';
14
+
15
+ // ─── Filter Operations ───────────────────────────────────────────────────────
16
+
17
+ type FilterOperator =
18
+ | 'eq'
19
+ | 'neq'
20
+ | 'gt'
21
+ | 'gte'
22
+ | 'lt'
23
+ | 'lte'
24
+ | 'like'
25
+ | 'ilike'
26
+ | 'in'
27
+ | 'is'
28
+ | 'contains'
29
+ | 'containedBy'
30
+ | 'overlaps'
31
+ | 'textSearch'
32
+ | 'not'
33
+ | 'or';
34
+
35
+ // ─── Filter Types ────────────────────────────────────────────────────────────
36
+
37
+ interface Filter {
38
+ column?: string;
39
+ op: FilterOperator;
40
+ value?: any;
41
+ filter?: Filter;
42
+ filters?: Filter[];
43
+ }
44
+
45
+ // ─── Order Types ─────────────────────────────────────────────────────────────
46
+
47
+ interface Order {
48
+ column: string;
49
+ ascending?: boolean;
50
+ }
51
+
52
+ // ─── Request Types ───────────────────────────────────────────────────────────
53
+
54
+ interface DataRequest {
55
+ op: QueryOperation;
56
+ table: string;
57
+ columns?: string;
58
+ filters?: Filter[];
59
+ order?: Order;
60
+ limit?: number;
61
+ offset?: number;
62
+ count?: 'exact' | 'planned' | 'estimated';
63
+ single?: boolean;
64
+ returning?: string;
65
+ data?: Record<string, any> | Record<string, any>[];
66
+ function?: string;
67
+ args?: Record<string, any>;
68
+ }
69
+
70
+ // ─── Response Types ──────────────────────────────────────────────────────────
71
+
72
+ interface QuerySuccess {
73
+ status: 'success';
74
+ data: any;
75
+ count?: number;
76
+ request_id: string;
77
+ }
78
+
79
+ interface QueryError {
80
+ status: 'error';
81
+ data: null;
82
+ error: {
83
+ code: string;
84
+ message: string;
85
+ details?: any;
86
+ };
87
+ request_id: string;
88
+ }
89
+
90
+ type QueryResult = QuerySuccess | QueryError;
91
+
92
+ // ─── Auth Types ──────────────────────────────────────────────────────────────
93
+
94
+ interface SignUpParams {
95
+ email: string;
96
+ password: string;
97
+ }
98
+
99
+ interface SignInParams {
100
+ email: string;
101
+ password: string;
102
+ }
103
+
104
+ interface AuthResult {
105
+ status: 'success' | 'error';
106
+ data: {
107
+ session?: {
108
+ access_token: string;
109
+ refresh_token: string;
110
+ expires_in: number;
111
+ token_type: string;
112
+ };
113
+ user?: {
114
+ id: string;
115
+ email: string;
116
+ role: string;
117
+ created_at: string;
118
+ };
119
+ } | null;
120
+ error?: {
121
+ code: string;
122
+ message: string;
123
+ };
124
+ request_id: string;
125
+ }
126
+
127
+ // ─── Compression Types ───────────────────────────────────────────────────────
128
+
129
+ type CompressMode = 'auto' | 'image' | 'gzip' | 'deflate' | 'deflate-raw' | 'none';
130
+ type CompressImageFormat = 'original' | 'webp' | 'jpeg' | 'png';
131
+
132
+ interface CompressOptions {
133
+ /** 'auto' (images→canvas, rest→gzip) | 'image' | 'gzip' | 'deflate' | 'deflate-raw' | 'none' (default: 'auto') */
134
+ mode?: CompressMode;
135
+ /** Max width px, aspect preserved, never upscales (default: 1920, integer 1-8192) */
136
+ maxWidth?: number;
137
+ /** Max height px (default: 1920, integer 1-8192) */
138
+ maxHeight?: number;
139
+ /** Quality (0,1] for jpeg/webp (default: 0.8; ignored for png/lossless) */
140
+ quality?: number;
141
+ /** Output image format (default: 'original'). Actual bytes rule: reported type is always the real output type. */
142
+ format?: CompressImageFormat;
143
+ /** Force lossless PNG for images (default: false) */
144
+ lossless?: boolean;
145
+ /** Keep output even when >= input (default: false → returns original) */
146
+ force?: boolean;
147
+ /** Abort compression */
148
+ signal?: AbortSignal;
149
+ }
150
+
151
+ interface CompressResult {
152
+ /** Bytes to upload (original Blob when nothing gained and force:false) */
153
+ file: Blob;
154
+ /** False when the original was kept */
155
+ compressed: boolean;
156
+ /** Applied backend: 'image'|'gzip'|'deflate'|'deflate-raw'|'none' */
157
+ mode: string;
158
+ originalSize: number;
159
+ compressedSize: number;
160
+ /** Real MIME of `file` — never assumed, always the produced bytes' type */
161
+ contentType: string;
162
+ }
163
+
164
+ // ─── Storage Types ───────────────────────────────────────────────────────────
165
+
166
+ interface UploadOptions {
167
+ contentType?: string;
168
+ upsert?: boolean;
169
+ /** Client-side cap applied AFTER compression (default: 50 MiB) */
170
+ maxSize?: number;
171
+ /** true = defaults, or full CompressOptions. Compressed bytes are uploaded; success data carries compression:{mode,original_size,compressed_size}. */
172
+ compress?: boolean | CompressOptions;
173
+ onProgress?: (p: { sentBytes: number; totalBytes: number; chunksDone: number; chunksTotal: number; index: number }) => void;
174
+ signal?: AbortSignal;
175
+ }
176
+
177
+ interface ListOptions {
178
+ limit?: number;
179
+ offset?: number;
180
+ }
181
+
182
+ interface FileObject {
183
+ name: string;
184
+ id: string;
185
+ updated_at: string;
186
+ created_at: string;
187
+ last_accessed_at: string;
188
+ metadata: Record<string, any>;
189
+ }
190
+
191
+ interface StorageFileResponse {
192
+ path: string;
193
+ id: string;
194
+ }
195
+
196
+ // ─── Client Types ────────────────────────────────────────────────────────────
197
+
198
+ interface ClientOptions {
199
+ /** Postgres schema to query (default: public) */
200
+ schema?: string;
201
+ /** Request timeout in ms (default: 30000) */
202
+ timeout?: number;
203
+ /** Use same-domain proxy (default: auto). Set to '/fenaura' or true to force cookie mode via proxy, false to force direct Bearer. */
204
+ proxy?: boolean | string;
205
+ /** Alias for proxy path (e.g. '/fenaura') */
206
+ proxyPath?: string;
207
+ }
208
+
209
+ interface FenauraClient {
210
+ from<T = Record<string, any>>(table: string): QueryBuilder<T>;
211
+ schema(schema: string): FenauraClient;
212
+ rpc<T = any>(fn: string, args?: Record<string, any>, options?: { count?: boolean; get?: boolean; head?: boolean }): Promise<QueryResult & { data: T }>;
213
+ auth: AuthClient;
214
+ storage: StorageClient;
215
+ channel(name: string): Channel;
216
+ setSession(token: string): void;
217
+ getSession(): string | null;
218
+ }
219
+
220
+ // ─── Query Builder Types ─────────────────────────────────────────────────────
221
+
222
+ interface QueryBuilder<T = Record<string, any>> {
223
+ select(columns?: string): QueryBuilder<T>;
224
+ insert(data: T | T[]): Promise<QueryResult & { data: T[] }>;
225
+ update(data: Partial<T>): QueryBuilder<T>;
226
+ /** Single object only — arrays are rejected 400 server-side. */
227
+ upsert(data: T): Promise<QueryResult & { data: T[] }>;
228
+ delete(): QueryBuilder<T>;
229
+
230
+ eq(column: keyof T, value: any): QueryBuilder<T>;
231
+ neq(column: keyof T, value: any): QueryBuilder<T>;
232
+ gt(column: keyof T, value: any): QueryBuilder<T>;
233
+ gte(column: keyof T, value: any): QueryBuilder<T>;
234
+ lt(column: keyof T, value: any): QueryBuilder<T>;
235
+ lte(column: keyof T, value: any): QueryBuilder<T>;
236
+ like(column: keyof T, pattern: string): QueryBuilder<T>;
237
+ ilike(column: keyof T, pattern: string): QueryBuilder<T>;
238
+ in(column: keyof T, values: any[]): QueryBuilder<T>;
239
+ is(column: keyof T, value: null): QueryBuilder<T>;
240
+ contains(column: keyof T, value: any): QueryBuilder<T>;
241
+ containedBy(column: keyof T, value: any): QueryBuilder<T>;
242
+ overlaps(column: keyof T, value: any): QueryBuilder<T>;
243
+ textSearch(column: keyof T, query: string): QueryBuilder<T>;
244
+ not(filter: Filter): QueryBuilder<T>;
245
+ or(filters: Filter[]): QueryBuilder<T>;
246
+
247
+ order(column: keyof T, options?: { ascending?: boolean }): QueryBuilder<T>;
248
+ limit(count: number): QueryBuilder<T>;
249
+ offset(count: number): QueryBuilder<T>;
250
+ single(): Promise<T | null>;
251
+ maybeSingle(): Promise<T | null>;
252
+ count(mode?: 'exact' | 'planned' | 'estimated'): QueryBuilder<T>;
253
+ returning(columns: string): QueryBuilder<T>;
254
+ }
255
+
256
+ // ─── Auth Client Types ───────────────────────────────────────────────────────
257
+
258
+ type OAuthProvider = 'google' | 'github' | 'microsoft' | 'apple' | 'facebook' | 'twitter' | 'discord' | 'linkedin' | 'spotify' | 'slack' | 'gitlab' | 'twitch';
259
+
260
+ interface OAuthSignInOptions {
261
+ redirectTo?: string;
262
+ scopes?: string;
263
+ queryParams?: Record<string, string>;
264
+ skipBrowserRedirect?: boolean;
265
+ browser?: boolean;
266
+ }
267
+
268
+ interface OAuthUrlResult {
269
+ status: string;
270
+ data: { url: string; provider: OAuthProvider } | null;
271
+ error: { message: string; hint?: string } | null;
272
+ request_id?: string;
273
+ }
274
+
275
+ interface AuthOptions {
276
+ browser?: boolean;
277
+ }
278
+
279
+ interface AuthClient {
280
+ signUp(params: SignUpParams, options?: AuthOptions): Promise<AuthResult>;
281
+ signIn(params: SignInParams, options?: AuthOptions): Promise<AuthResult>;
282
+ signOut(): Promise<QueryResult>;
283
+ getSession(): Promise<AuthResult>;
284
+ getUser(): Promise<AuthResult>;
285
+ signInWithOAuth(provider: OAuthProvider, options?: OAuthSignInOptions): Promise<OAuthUrlResult>;
286
+ sendVerificationCode(params: { email: string }): Promise<QueryResult>;
287
+ submitVerificationCode(params: { email: string; code: string }, options?: AuthOptions): Promise<AuthResult>;
288
+ sendPasswordReset(params: { email: string }): Promise<QueryResult>;
289
+ confirmPasswordReset(params: { email: string; code: string; newPassword: string }, options?: AuthOptions): Promise<AuthResult>;
290
+ sendMagicLink(params: { email: string }): Promise<QueryResult>;
291
+ verifyMagicCode(params: { email: string; code: string }, options?: AuthOptions): Promise<AuthResult>;
292
+ exchangeCodeForSession(code: string): Promise<QueryResult & { data: { token: string; project_id: string } | null }>;
293
+ handleOAuthCallback(): Promise<AuthResult>;
294
+ onAuthStateChange(callback: (event: string, session: any) => void): {
295
+ data: {
296
+ subscription: {
297
+ unsubscribe(): void;
298
+ };
299
+ };
300
+ };
301
+ }
302
+
303
+ // ─── Storage Client Types ────────────────────────────────────────────────────
304
+
305
+ interface StorageClient {
306
+ from(bucket: string): StorageBucket;
307
+ }
308
+
309
+ interface StorageBucket {
310
+ upload(path: string, file: File | Blob, options?: UploadOptions): Promise<QueryResult & { data: StorageFileResponse }>;
311
+ download(path: string): Promise<QueryResult & { data: Blob }>;
312
+ list(path?: string, options?: ListOptions): Promise<QueryResult & { data: FileObject[] }>;
313
+ remove(paths: string[]): Promise<QueryResult>;
314
+ /** Same-origin SESSION url (not public — GET needs the caller's cookie). Segments encoded. Outsiders: createSignedUrl. */
315
+ getPublicUrl(path: string): string;
316
+ /** Real HMAC-signed expiring link (server-enforced, ≤7d). Anonymous fetches OK until exp. */
317
+ createSignedUrl(path: string, expiresIn?: number): Promise<QueryResult & { data: { signedUrl: string } }>;
318
+ }
319
+
320
+ // ─── Channel Types (Placeholder) ─────────────────────────────────────────────
321
+
322
+ interface Channel {
323
+ on(event: string, filter: any, callback: (payload: any) => void): Channel;
324
+ subscribe(callback?: (status: string) => void): Channel;
325
+ unsubscribe(): Channel;
326
+ }
327
+
328
+ // ─── Export ──────────────────────────────────────────────────────────────────
329
+
330
+ /**
331
+ * Create a Fenaura client. After `npx @fenaura/sdk init`, use the proxy for cookies:
332
+ * `createClient('/fenaura', apiKey)` or `createClient(url, apiKey, { proxy: '/fenaura' })`.
333
+ * Direct mode: `createClient('https://api.fenaura.com', apiKey)` uses Bearer token.
334
+ */
335
+ export declare function createClient(
336
+ url: string,
337
+ apiKey: string,
338
+ options?: ClientOptions
339
+ ): FenauraClient;
340
+
341
+ /**
342
+ * Compress a file on-device before upload. See CompressOptions.
343
+ * `compressFile.supports()` reports `{ image, gzip }` backend availability.
344
+ */
345
+ export declare function compressFile(
346
+ file: Blob,
347
+ options?: CompressOptions | boolean
348
+ ): Promise<CompressResult>;
349
+
350
+ export declare namespace compressFile {
351
+ function supports(): { image: boolean; gzip: boolean };
352
+ }
353
+
354
+ export type {
355
+ ClientOptions,
356
+ FenauraClient,
357
+ QueryBuilder,
358
+ AuthClient,
359
+ StorageClient,
360
+ StorageBucket,
361
+ Channel,
362
+ QueryResult,
363
+ QuerySuccess,
364
+ QueryError,
365
+ AuthResult,
366
+ Filter,
367
+ FilterOperator,
368
+ Order,
369
+ FileObject,
370
+ UploadOptions,
371
+ ListOptions,
372
+ CompressOptions,
373
+ CompressResult,
374
+ CompressMode,
375
+ CompressImageFormat,
376
+ };