krisspy-sdk 0.1.0 → 0.3.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/dist/index.d.mts +218 -2
- package/dist/index.d.ts +218 -2
- package/dist/index.js +326 -0
- package/dist/index.mjs +324 -0
- package/package.json +7 -2
package/dist/index.d.mts
CHANGED
|
@@ -300,6 +300,195 @@ declare class KrisspyAuth {
|
|
|
300
300
|
}
|
|
301
301
|
type AuthChangeEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED';
|
|
302
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Krisspy Storage - File storage client
|
|
305
|
+
*
|
|
306
|
+
* Provides a simple API for uploading, downloading, and managing files
|
|
307
|
+
* in Krisspy Cloud Storage (Azure Blob Storage backend).
|
|
308
|
+
*/
|
|
309
|
+
|
|
310
|
+
interface StorageUploadResponse {
|
|
311
|
+
data: {
|
|
312
|
+
path: string;
|
|
313
|
+
url: string;
|
|
314
|
+
bucket: string;
|
|
315
|
+
contentType: string;
|
|
316
|
+
size: number;
|
|
317
|
+
} | null;
|
|
318
|
+
error: KrisspyError | null;
|
|
319
|
+
}
|
|
320
|
+
interface StorageDownloadResponse {
|
|
321
|
+
data: {
|
|
322
|
+
url: string;
|
|
323
|
+
path: string;
|
|
324
|
+
bucket: string;
|
|
325
|
+
} | null;
|
|
326
|
+
error: KrisspyError | null;
|
|
327
|
+
}
|
|
328
|
+
interface StorageListResponse {
|
|
329
|
+
data: FileObject[] | null;
|
|
330
|
+
error: KrisspyError | null;
|
|
331
|
+
}
|
|
332
|
+
interface StorageDeleteResponse {
|
|
333
|
+
data: {
|
|
334
|
+
success: boolean;
|
|
335
|
+
} | null;
|
|
336
|
+
error: KrisspyError | null;
|
|
337
|
+
}
|
|
338
|
+
interface StorageUrlResponse {
|
|
339
|
+
data: {
|
|
340
|
+
signedUrl: string;
|
|
341
|
+
path: string;
|
|
342
|
+
expiresIn: number;
|
|
343
|
+
} | null;
|
|
344
|
+
error: KrisspyError | null;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Storage bucket interface for file operations
|
|
348
|
+
*/
|
|
349
|
+
declare class StorageBucket {
|
|
350
|
+
private http;
|
|
351
|
+
private backendId;
|
|
352
|
+
private bucketName;
|
|
353
|
+
constructor(http: HttpClient, backendId: string, bucketName: string);
|
|
354
|
+
/**
|
|
355
|
+
* Upload a file to the bucket
|
|
356
|
+
*
|
|
357
|
+
* @param path - Path/filename for the file (e.g., "images/profile.jpg")
|
|
358
|
+
* @param file - File data as Blob, File, ArrayBuffer, or base64 string
|
|
359
|
+
* @param options - Upload options
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* // Upload from file input
|
|
363
|
+
* const file = event.target.files[0]
|
|
364
|
+
* const { data, error } = await krisspy.storage
|
|
365
|
+
* .from('avatars')
|
|
366
|
+
* .upload('profile.jpg', file)
|
|
367
|
+
*
|
|
368
|
+
* // Upload base64 image
|
|
369
|
+
* const { data, error } = await krisspy.storage
|
|
370
|
+
* .from('images')
|
|
371
|
+
* .upload('photo.png', base64Data, { contentType: 'image/png' })
|
|
372
|
+
*/
|
|
373
|
+
upload(path: string, file: Blob | File | ArrayBuffer | string, options?: FileUploadOptions): Promise<StorageUploadResponse>;
|
|
374
|
+
/**
|
|
375
|
+
* Get the public URL of a file
|
|
376
|
+
*
|
|
377
|
+
* @param path - Path to the file
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
381
|
+
* console.log(data.publicUrl) // https://...
|
|
382
|
+
*/
|
|
383
|
+
getPublicUrl(path: string): {
|
|
384
|
+
data: {
|
|
385
|
+
publicUrl: string;
|
|
386
|
+
};
|
|
387
|
+
};
|
|
388
|
+
/**
|
|
389
|
+
* Download a file (get download URL)
|
|
390
|
+
*
|
|
391
|
+
* @param path - Path to the file
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* const { data, error } = await krisspy.storage
|
|
395
|
+
* .from('documents')
|
|
396
|
+
* .download('report.pdf')
|
|
397
|
+
*/
|
|
398
|
+
download(path: string): Promise<StorageDownloadResponse>;
|
|
399
|
+
/**
|
|
400
|
+
* Delete a file from storage
|
|
401
|
+
*
|
|
402
|
+
* @param paths - Path(s) to delete
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* // Delete single file
|
|
406
|
+
* const { error } = await krisspy.storage.from('avatars').remove(['profile.jpg'])
|
|
407
|
+
*
|
|
408
|
+
* // Delete multiple files
|
|
409
|
+
* const { error } = await krisspy.storage.from('images').remove(['a.jpg', 'b.jpg'])
|
|
410
|
+
*/
|
|
411
|
+
remove(paths: string[]): Promise<StorageDeleteResponse>;
|
|
412
|
+
/**
|
|
413
|
+
* List files in the bucket
|
|
414
|
+
*
|
|
415
|
+
* @param prefix - Filter files by path prefix
|
|
416
|
+
* @param options - List options
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* // List all files
|
|
420
|
+
* const { data, error } = await krisspy.storage.from('uploads').list()
|
|
421
|
+
*
|
|
422
|
+
* // List files in a folder
|
|
423
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
424
|
+
*/
|
|
425
|
+
list(prefix?: string, options?: {
|
|
426
|
+
limit?: number;
|
|
427
|
+
offset?: number;
|
|
428
|
+
}): Promise<StorageListResponse>;
|
|
429
|
+
/**
|
|
430
|
+
* Create a signed URL for temporary access
|
|
431
|
+
*
|
|
432
|
+
* @param path - Path to the file
|
|
433
|
+
* @param expiresIn - Expiration time in seconds (default: 3600)
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* const { data, error } = await krisspy.storage
|
|
437
|
+
* .from('private')
|
|
438
|
+
* .createSignedUrl('document.pdf', 3600)
|
|
439
|
+
*/
|
|
440
|
+
createSignedUrl(path: string, expiresIn?: number): Promise<StorageUrlResponse>;
|
|
441
|
+
private blobToBase64;
|
|
442
|
+
private arrayBufferToBase64;
|
|
443
|
+
private detectMimeType;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Krisspy Storage client
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* // Upload a file
|
|
450
|
+
* const { data, error } = await krisspy.storage
|
|
451
|
+
* .from('avatars')
|
|
452
|
+
* .upload('profile.jpg', file)
|
|
453
|
+
*
|
|
454
|
+
* // Get public URL
|
|
455
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
456
|
+
*
|
|
457
|
+
* // Download
|
|
458
|
+
* const { data, error } = await krisspy.storage.from('docs').download('file.pdf')
|
|
459
|
+
*
|
|
460
|
+
* // List files
|
|
461
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
462
|
+
*
|
|
463
|
+
* // Delete files
|
|
464
|
+
* const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
|
|
465
|
+
*/
|
|
466
|
+
declare class KrisspyStorage {
|
|
467
|
+
private http;
|
|
468
|
+
private backendId;
|
|
469
|
+
constructor(http: HttpClient, backendId: string);
|
|
470
|
+
/**
|
|
471
|
+
* Select a storage bucket
|
|
472
|
+
*
|
|
473
|
+
* @param bucket - Bucket name (e.g., 'avatars', 'documents', 'media')
|
|
474
|
+
* @returns StorageBucket instance for file operations
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* const bucket = krisspy.storage.from('avatars')
|
|
478
|
+
* await bucket.upload('profile.jpg', file)
|
|
479
|
+
*/
|
|
480
|
+
from(bucket: string): StorageBucket;
|
|
481
|
+
/**
|
|
482
|
+
* List all buckets (currently returns predefined buckets)
|
|
483
|
+
*/
|
|
484
|
+
listBuckets(): Promise<{
|
|
485
|
+
data: {
|
|
486
|
+
name: string;
|
|
487
|
+
}[] | null;
|
|
488
|
+
error: KrisspyError | null;
|
|
489
|
+
}>;
|
|
490
|
+
}
|
|
491
|
+
|
|
303
492
|
/**
|
|
304
493
|
* Query Builder - Supabase-style fluent API for database queries
|
|
305
494
|
*/
|
|
@@ -448,6 +637,7 @@ declare class KrisspyClient {
|
|
|
448
637
|
private http;
|
|
449
638
|
private backendId;
|
|
450
639
|
private _auth;
|
|
640
|
+
private _storage;
|
|
451
641
|
private useRLS;
|
|
452
642
|
constructor(options: KrisspyClientOptions);
|
|
453
643
|
/**
|
|
@@ -473,6 +663,28 @@ declare class KrisspyClient {
|
|
|
473
663
|
* await krisspy.auth.signOut()
|
|
474
664
|
*/
|
|
475
665
|
get auth(): KrisspyAuth;
|
|
666
|
+
/**
|
|
667
|
+
* Storage module for file uploads and downloads
|
|
668
|
+
*
|
|
669
|
+
* @example
|
|
670
|
+
* // Upload a file
|
|
671
|
+
* const { data, error } = await krisspy.storage
|
|
672
|
+
* .from('avatars')
|
|
673
|
+
* .upload('profile.jpg', file)
|
|
674
|
+
*
|
|
675
|
+
* // Get public URL
|
|
676
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
677
|
+
*
|
|
678
|
+
* // Download
|
|
679
|
+
* const { data, error } = await krisspy.storage.from('docs').download('file.pdf')
|
|
680
|
+
*
|
|
681
|
+
* // List files
|
|
682
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
683
|
+
*
|
|
684
|
+
* // Delete files
|
|
685
|
+
* const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
|
|
686
|
+
*/
|
|
687
|
+
get storage(): KrisspyStorage;
|
|
476
688
|
/**
|
|
477
689
|
* Create a query builder for a table
|
|
478
690
|
*
|
|
@@ -557,7 +769,7 @@ declare class KrisspyClient {
|
|
|
557
769
|
/**
|
|
558
770
|
* @krisspy/sdk - Krisspy Cloud SDK
|
|
559
771
|
*
|
|
560
|
-
* Database, Auth, and Functions for your apps.
|
|
772
|
+
* Database, Auth, Storage, and Functions for your apps.
|
|
561
773
|
* A simpler alternative to Supabase.
|
|
562
774
|
*
|
|
563
775
|
* @example
|
|
@@ -583,6 +795,10 @@ declare class KrisspyClient {
|
|
|
583
795
|
* // Insert
|
|
584
796
|
* await krisspy.from('products').insert({ name: 'iPhone', price: 999 })
|
|
585
797
|
*
|
|
798
|
+
* // Storage
|
|
799
|
+
* await krisspy.storage.from('avatars').upload('profile.jpg', file)
|
|
800
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
801
|
+
*
|
|
586
802
|
* // Functions
|
|
587
803
|
* await krisspy.functions.invoke('hello', { body: { name: 'World' } })
|
|
588
804
|
*/
|
|
@@ -602,4 +818,4 @@ declare class KrisspyClient {
|
|
|
602
818
|
*/
|
|
603
819
|
declare function createClient(options: KrisspyClientOptions): KrisspyClient;
|
|
604
820
|
|
|
605
|
-
export { type AuthChangeEvent, type AuthResponse, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, type KrisspyError, type MutationResponse, type OAuthProvider, type OrderBy, QueryBuilder, type QueryOptions, type QueryResponse, type Session, type SignInCredentials, type SignUpCredentials, type SingleResponse, type User, createClient };
|
|
821
|
+
export { type AuthChangeEvent, type AuthResponse, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, type KrisspyError, KrisspyStorage, type MutationResponse, type OAuthProvider, type OrderBy, QueryBuilder, type QueryOptions, type QueryResponse, type Session, type SignInCredentials, type SignUpCredentials, type SingleResponse, StorageBucket, type User, createClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -300,6 +300,195 @@ declare class KrisspyAuth {
|
|
|
300
300
|
}
|
|
301
301
|
type AuthChangeEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED';
|
|
302
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Krisspy Storage - File storage client
|
|
305
|
+
*
|
|
306
|
+
* Provides a simple API for uploading, downloading, and managing files
|
|
307
|
+
* in Krisspy Cloud Storage (Azure Blob Storage backend).
|
|
308
|
+
*/
|
|
309
|
+
|
|
310
|
+
interface StorageUploadResponse {
|
|
311
|
+
data: {
|
|
312
|
+
path: string;
|
|
313
|
+
url: string;
|
|
314
|
+
bucket: string;
|
|
315
|
+
contentType: string;
|
|
316
|
+
size: number;
|
|
317
|
+
} | null;
|
|
318
|
+
error: KrisspyError | null;
|
|
319
|
+
}
|
|
320
|
+
interface StorageDownloadResponse {
|
|
321
|
+
data: {
|
|
322
|
+
url: string;
|
|
323
|
+
path: string;
|
|
324
|
+
bucket: string;
|
|
325
|
+
} | null;
|
|
326
|
+
error: KrisspyError | null;
|
|
327
|
+
}
|
|
328
|
+
interface StorageListResponse {
|
|
329
|
+
data: FileObject[] | null;
|
|
330
|
+
error: KrisspyError | null;
|
|
331
|
+
}
|
|
332
|
+
interface StorageDeleteResponse {
|
|
333
|
+
data: {
|
|
334
|
+
success: boolean;
|
|
335
|
+
} | null;
|
|
336
|
+
error: KrisspyError | null;
|
|
337
|
+
}
|
|
338
|
+
interface StorageUrlResponse {
|
|
339
|
+
data: {
|
|
340
|
+
signedUrl: string;
|
|
341
|
+
path: string;
|
|
342
|
+
expiresIn: number;
|
|
343
|
+
} | null;
|
|
344
|
+
error: KrisspyError | null;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Storage bucket interface for file operations
|
|
348
|
+
*/
|
|
349
|
+
declare class StorageBucket {
|
|
350
|
+
private http;
|
|
351
|
+
private backendId;
|
|
352
|
+
private bucketName;
|
|
353
|
+
constructor(http: HttpClient, backendId: string, bucketName: string);
|
|
354
|
+
/**
|
|
355
|
+
* Upload a file to the bucket
|
|
356
|
+
*
|
|
357
|
+
* @param path - Path/filename for the file (e.g., "images/profile.jpg")
|
|
358
|
+
* @param file - File data as Blob, File, ArrayBuffer, or base64 string
|
|
359
|
+
* @param options - Upload options
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* // Upload from file input
|
|
363
|
+
* const file = event.target.files[0]
|
|
364
|
+
* const { data, error } = await krisspy.storage
|
|
365
|
+
* .from('avatars')
|
|
366
|
+
* .upload('profile.jpg', file)
|
|
367
|
+
*
|
|
368
|
+
* // Upload base64 image
|
|
369
|
+
* const { data, error } = await krisspy.storage
|
|
370
|
+
* .from('images')
|
|
371
|
+
* .upload('photo.png', base64Data, { contentType: 'image/png' })
|
|
372
|
+
*/
|
|
373
|
+
upload(path: string, file: Blob | File | ArrayBuffer | string, options?: FileUploadOptions): Promise<StorageUploadResponse>;
|
|
374
|
+
/**
|
|
375
|
+
* Get the public URL of a file
|
|
376
|
+
*
|
|
377
|
+
* @param path - Path to the file
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
381
|
+
* console.log(data.publicUrl) // https://...
|
|
382
|
+
*/
|
|
383
|
+
getPublicUrl(path: string): {
|
|
384
|
+
data: {
|
|
385
|
+
publicUrl: string;
|
|
386
|
+
};
|
|
387
|
+
};
|
|
388
|
+
/**
|
|
389
|
+
* Download a file (get download URL)
|
|
390
|
+
*
|
|
391
|
+
* @param path - Path to the file
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* const { data, error } = await krisspy.storage
|
|
395
|
+
* .from('documents')
|
|
396
|
+
* .download('report.pdf')
|
|
397
|
+
*/
|
|
398
|
+
download(path: string): Promise<StorageDownloadResponse>;
|
|
399
|
+
/**
|
|
400
|
+
* Delete a file from storage
|
|
401
|
+
*
|
|
402
|
+
* @param paths - Path(s) to delete
|
|
403
|
+
*
|
|
404
|
+
* @example
|
|
405
|
+
* // Delete single file
|
|
406
|
+
* const { error } = await krisspy.storage.from('avatars').remove(['profile.jpg'])
|
|
407
|
+
*
|
|
408
|
+
* // Delete multiple files
|
|
409
|
+
* const { error } = await krisspy.storage.from('images').remove(['a.jpg', 'b.jpg'])
|
|
410
|
+
*/
|
|
411
|
+
remove(paths: string[]): Promise<StorageDeleteResponse>;
|
|
412
|
+
/**
|
|
413
|
+
* List files in the bucket
|
|
414
|
+
*
|
|
415
|
+
* @param prefix - Filter files by path prefix
|
|
416
|
+
* @param options - List options
|
|
417
|
+
*
|
|
418
|
+
* @example
|
|
419
|
+
* // List all files
|
|
420
|
+
* const { data, error } = await krisspy.storage.from('uploads').list()
|
|
421
|
+
*
|
|
422
|
+
* // List files in a folder
|
|
423
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
424
|
+
*/
|
|
425
|
+
list(prefix?: string, options?: {
|
|
426
|
+
limit?: number;
|
|
427
|
+
offset?: number;
|
|
428
|
+
}): Promise<StorageListResponse>;
|
|
429
|
+
/**
|
|
430
|
+
* Create a signed URL for temporary access
|
|
431
|
+
*
|
|
432
|
+
* @param path - Path to the file
|
|
433
|
+
* @param expiresIn - Expiration time in seconds (default: 3600)
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* const { data, error } = await krisspy.storage
|
|
437
|
+
* .from('private')
|
|
438
|
+
* .createSignedUrl('document.pdf', 3600)
|
|
439
|
+
*/
|
|
440
|
+
createSignedUrl(path: string, expiresIn?: number): Promise<StorageUrlResponse>;
|
|
441
|
+
private blobToBase64;
|
|
442
|
+
private arrayBufferToBase64;
|
|
443
|
+
private detectMimeType;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Krisspy Storage client
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* // Upload a file
|
|
450
|
+
* const { data, error } = await krisspy.storage
|
|
451
|
+
* .from('avatars')
|
|
452
|
+
* .upload('profile.jpg', file)
|
|
453
|
+
*
|
|
454
|
+
* // Get public URL
|
|
455
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
456
|
+
*
|
|
457
|
+
* // Download
|
|
458
|
+
* const { data, error } = await krisspy.storage.from('docs').download('file.pdf')
|
|
459
|
+
*
|
|
460
|
+
* // List files
|
|
461
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
462
|
+
*
|
|
463
|
+
* // Delete files
|
|
464
|
+
* const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
|
|
465
|
+
*/
|
|
466
|
+
declare class KrisspyStorage {
|
|
467
|
+
private http;
|
|
468
|
+
private backendId;
|
|
469
|
+
constructor(http: HttpClient, backendId: string);
|
|
470
|
+
/**
|
|
471
|
+
* Select a storage bucket
|
|
472
|
+
*
|
|
473
|
+
* @param bucket - Bucket name (e.g., 'avatars', 'documents', 'media')
|
|
474
|
+
* @returns StorageBucket instance for file operations
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* const bucket = krisspy.storage.from('avatars')
|
|
478
|
+
* await bucket.upload('profile.jpg', file)
|
|
479
|
+
*/
|
|
480
|
+
from(bucket: string): StorageBucket;
|
|
481
|
+
/**
|
|
482
|
+
* List all buckets (currently returns predefined buckets)
|
|
483
|
+
*/
|
|
484
|
+
listBuckets(): Promise<{
|
|
485
|
+
data: {
|
|
486
|
+
name: string;
|
|
487
|
+
}[] | null;
|
|
488
|
+
error: KrisspyError | null;
|
|
489
|
+
}>;
|
|
490
|
+
}
|
|
491
|
+
|
|
303
492
|
/**
|
|
304
493
|
* Query Builder - Supabase-style fluent API for database queries
|
|
305
494
|
*/
|
|
@@ -448,6 +637,7 @@ declare class KrisspyClient {
|
|
|
448
637
|
private http;
|
|
449
638
|
private backendId;
|
|
450
639
|
private _auth;
|
|
640
|
+
private _storage;
|
|
451
641
|
private useRLS;
|
|
452
642
|
constructor(options: KrisspyClientOptions);
|
|
453
643
|
/**
|
|
@@ -473,6 +663,28 @@ declare class KrisspyClient {
|
|
|
473
663
|
* await krisspy.auth.signOut()
|
|
474
664
|
*/
|
|
475
665
|
get auth(): KrisspyAuth;
|
|
666
|
+
/**
|
|
667
|
+
* Storage module for file uploads and downloads
|
|
668
|
+
*
|
|
669
|
+
* @example
|
|
670
|
+
* // Upload a file
|
|
671
|
+
* const { data, error } = await krisspy.storage
|
|
672
|
+
* .from('avatars')
|
|
673
|
+
* .upload('profile.jpg', file)
|
|
674
|
+
*
|
|
675
|
+
* // Get public URL
|
|
676
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
677
|
+
*
|
|
678
|
+
* // Download
|
|
679
|
+
* const { data, error } = await krisspy.storage.from('docs').download('file.pdf')
|
|
680
|
+
*
|
|
681
|
+
* // List files
|
|
682
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
683
|
+
*
|
|
684
|
+
* // Delete files
|
|
685
|
+
* const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
|
|
686
|
+
*/
|
|
687
|
+
get storage(): KrisspyStorage;
|
|
476
688
|
/**
|
|
477
689
|
* Create a query builder for a table
|
|
478
690
|
*
|
|
@@ -557,7 +769,7 @@ declare class KrisspyClient {
|
|
|
557
769
|
/**
|
|
558
770
|
* @krisspy/sdk - Krisspy Cloud SDK
|
|
559
771
|
*
|
|
560
|
-
* Database, Auth, and Functions for your apps.
|
|
772
|
+
* Database, Auth, Storage, and Functions for your apps.
|
|
561
773
|
* A simpler alternative to Supabase.
|
|
562
774
|
*
|
|
563
775
|
* @example
|
|
@@ -583,6 +795,10 @@ declare class KrisspyClient {
|
|
|
583
795
|
* // Insert
|
|
584
796
|
* await krisspy.from('products').insert({ name: 'iPhone', price: 999 })
|
|
585
797
|
*
|
|
798
|
+
* // Storage
|
|
799
|
+
* await krisspy.storage.from('avatars').upload('profile.jpg', file)
|
|
800
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
801
|
+
*
|
|
586
802
|
* // Functions
|
|
587
803
|
* await krisspy.functions.invoke('hello', { body: { name: 'World' } })
|
|
588
804
|
*/
|
|
@@ -602,4 +818,4 @@ declare class KrisspyClient {
|
|
|
602
818
|
*/
|
|
603
819
|
declare function createClient(options: KrisspyClientOptions): KrisspyClient;
|
|
604
820
|
|
|
605
|
-
export { type AuthChangeEvent, type AuthResponse, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, type KrisspyError, type MutationResponse, type OAuthProvider, type OrderBy, QueryBuilder, type QueryOptions, type QueryResponse, type Session, type SignInCredentials, type SignUpCredentials, type SingleResponse, type User, createClient };
|
|
821
|
+
export { type AuthChangeEvent, type AuthResponse, type FileObject, type FileUploadOptions, type Filter, type FilterOperator, type FunctionInvokeOptions, type FunctionResponse, HttpClient, KrisspyAuth, KrisspyClient, type KrisspyClientOptions, type KrisspyError, KrisspyStorage, type MutationResponse, type OAuthProvider, type OrderBy, QueryBuilder, type QueryOptions, type QueryResponse, type Session, type SignInCredentials, type SignUpCredentials, type SingleResponse, StorageBucket, type User, createClient };
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,9 @@ __export(index_exports, {
|
|
|
23
23
|
HttpClient: () => HttpClient,
|
|
24
24
|
KrisspyAuth: () => KrisspyAuth,
|
|
25
25
|
KrisspyClient: () => KrisspyClient,
|
|
26
|
+
KrisspyStorage: () => KrisspyStorage,
|
|
26
27
|
QueryBuilder: () => QueryBuilder,
|
|
28
|
+
StorageBucket: () => StorageBucket,
|
|
27
29
|
createClient: () => createClient
|
|
28
30
|
});
|
|
29
31
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -478,6 +480,303 @@ var KrisspyAuth = class {
|
|
|
478
480
|
}
|
|
479
481
|
};
|
|
480
482
|
|
|
483
|
+
// src/storage.ts
|
|
484
|
+
var StorageBucket = class {
|
|
485
|
+
constructor(http, backendId, bucketName) {
|
|
486
|
+
this.http = http;
|
|
487
|
+
this.backendId = backendId;
|
|
488
|
+
this.bucketName = bucketName;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Upload a file to the bucket
|
|
492
|
+
*
|
|
493
|
+
* @param path - Path/filename for the file (e.g., "images/profile.jpg")
|
|
494
|
+
* @param file - File data as Blob, File, ArrayBuffer, or base64 string
|
|
495
|
+
* @param options - Upload options
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* // Upload from file input
|
|
499
|
+
* const file = event.target.files[0]
|
|
500
|
+
* const { data, error } = await krisspy.storage
|
|
501
|
+
* .from('avatars')
|
|
502
|
+
* .upload('profile.jpg', file)
|
|
503
|
+
*
|
|
504
|
+
* // Upload base64 image
|
|
505
|
+
* const { data, error } = await krisspy.storage
|
|
506
|
+
* .from('images')
|
|
507
|
+
* .upload('photo.png', base64Data, { contentType: 'image/png' })
|
|
508
|
+
*/
|
|
509
|
+
async upload(path, file, options) {
|
|
510
|
+
try {
|
|
511
|
+
let base64Data;
|
|
512
|
+
let contentType = options?.contentType;
|
|
513
|
+
if (typeof file === "string") {
|
|
514
|
+
base64Data = file;
|
|
515
|
+
} else if (file instanceof Blob || file instanceof File) {
|
|
516
|
+
base64Data = await this.blobToBase64(file);
|
|
517
|
+
if (!contentType && file instanceof File) {
|
|
518
|
+
contentType = file.type;
|
|
519
|
+
}
|
|
520
|
+
} else if (file instanceof ArrayBuffer) {
|
|
521
|
+
base64Data = this.arrayBufferToBase64(file);
|
|
522
|
+
} else {
|
|
523
|
+
throw new Error("Invalid file type. Expected Blob, File, ArrayBuffer, or base64 string.");
|
|
524
|
+
}
|
|
525
|
+
if (!contentType) {
|
|
526
|
+
contentType = this.detectMimeType(path);
|
|
527
|
+
}
|
|
528
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/upload`;
|
|
529
|
+
const response = await this.http.post(apiPath, {
|
|
530
|
+
bucket: this.bucketName,
|
|
531
|
+
path,
|
|
532
|
+
data: base64Data,
|
|
533
|
+
contentType
|
|
534
|
+
});
|
|
535
|
+
if (response.error) {
|
|
536
|
+
return { data: null, error: response.error };
|
|
537
|
+
}
|
|
538
|
+
return {
|
|
539
|
+
data: {
|
|
540
|
+
path: response.data?.path || path,
|
|
541
|
+
url: response.data?.url || "",
|
|
542
|
+
bucket: response.data?.bucket || this.bucketName,
|
|
543
|
+
contentType: response.data?.contentType || contentType || "application/octet-stream",
|
|
544
|
+
size: response.data?.size || 0
|
|
545
|
+
},
|
|
546
|
+
error: null
|
|
547
|
+
};
|
|
548
|
+
} catch (error) {
|
|
549
|
+
return {
|
|
550
|
+
data: null,
|
|
551
|
+
error: {
|
|
552
|
+
message: error.message || "Upload failed",
|
|
553
|
+
code: "STORAGE_UPLOAD_ERROR"
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Get the public URL of a file
|
|
560
|
+
*
|
|
561
|
+
* @param path - Path to the file
|
|
562
|
+
*
|
|
563
|
+
* @example
|
|
564
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
565
|
+
* console.log(data.publicUrl) // https://...
|
|
566
|
+
*/
|
|
567
|
+
getPublicUrl(path) {
|
|
568
|
+
const baseUrl = "https://krisspy.blob.core.windows.net/public";
|
|
569
|
+
const storagePath = `backends/${this.backendId}/${this.bucketName}/${path}`;
|
|
570
|
+
const publicUrl = `${baseUrl}/${storagePath}`;
|
|
571
|
+
return {
|
|
572
|
+
data: { publicUrl }
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Download a file (get download URL)
|
|
577
|
+
*
|
|
578
|
+
* @param path - Path to the file
|
|
579
|
+
*
|
|
580
|
+
* @example
|
|
581
|
+
* const { data, error } = await krisspy.storage
|
|
582
|
+
* .from('documents')
|
|
583
|
+
* .download('report.pdf')
|
|
584
|
+
*/
|
|
585
|
+
async download(path) {
|
|
586
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/download`;
|
|
587
|
+
const response = await this.http.post(apiPath, {
|
|
588
|
+
bucket: this.bucketName,
|
|
589
|
+
path
|
|
590
|
+
});
|
|
591
|
+
if (response.error) {
|
|
592
|
+
return { data: null, error: response.error };
|
|
593
|
+
}
|
|
594
|
+
return {
|
|
595
|
+
data: {
|
|
596
|
+
url: response.data?.url || "",
|
|
597
|
+
path: response.data?.path || path,
|
|
598
|
+
bucket: response.data?.bucket || this.bucketName
|
|
599
|
+
},
|
|
600
|
+
error: null
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Delete a file from storage
|
|
605
|
+
*
|
|
606
|
+
* @param paths - Path(s) to delete
|
|
607
|
+
*
|
|
608
|
+
* @example
|
|
609
|
+
* // Delete single file
|
|
610
|
+
* const { error } = await krisspy.storage.from('avatars').remove(['profile.jpg'])
|
|
611
|
+
*
|
|
612
|
+
* // Delete multiple files
|
|
613
|
+
* const { error } = await krisspy.storage.from('images').remove(['a.jpg', 'b.jpg'])
|
|
614
|
+
*/
|
|
615
|
+
async remove(paths) {
|
|
616
|
+
const results = [];
|
|
617
|
+
for (const path of paths) {
|
|
618
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/delete`;
|
|
619
|
+
const response = await this.http.post(apiPath, {
|
|
620
|
+
bucket: this.bucketName,
|
|
621
|
+
path
|
|
622
|
+
});
|
|
623
|
+
if (response.error) {
|
|
624
|
+
return { data: null, error: response.error };
|
|
625
|
+
}
|
|
626
|
+
results.push({ success: response.data?.success || false });
|
|
627
|
+
}
|
|
628
|
+
return { data: { success: true }, error: null };
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* List files in the bucket
|
|
632
|
+
*
|
|
633
|
+
* @param prefix - Filter files by path prefix
|
|
634
|
+
* @param options - List options
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* // List all files
|
|
638
|
+
* const { data, error } = await krisspy.storage.from('uploads').list()
|
|
639
|
+
*
|
|
640
|
+
* // List files in a folder
|
|
641
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
642
|
+
*/
|
|
643
|
+
async list(prefix, options) {
|
|
644
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/list`;
|
|
645
|
+
const response = await this.http.post(apiPath, {
|
|
646
|
+
bucket: this.bucketName,
|
|
647
|
+
prefix,
|
|
648
|
+
limit: options?.limit || 100
|
|
649
|
+
});
|
|
650
|
+
if (response.error) {
|
|
651
|
+
return { data: null, error: response.error };
|
|
652
|
+
}
|
|
653
|
+
return { data: response.data?.files || [], error: null };
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Create a signed URL for temporary access
|
|
657
|
+
*
|
|
658
|
+
* @param path - Path to the file
|
|
659
|
+
* @param expiresIn - Expiration time in seconds (default: 3600)
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* const { data, error } = await krisspy.storage
|
|
663
|
+
* .from('private')
|
|
664
|
+
* .createSignedUrl('document.pdf', 3600)
|
|
665
|
+
*/
|
|
666
|
+
async createSignedUrl(path, expiresIn = 3600) {
|
|
667
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/signed-url`;
|
|
668
|
+
const response = await this.http.post(apiPath, {
|
|
669
|
+
bucket: this.bucketName,
|
|
670
|
+
path,
|
|
671
|
+
expiresIn
|
|
672
|
+
});
|
|
673
|
+
if (response.error) {
|
|
674
|
+
return { data: null, error: response.error };
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
data: {
|
|
678
|
+
signedUrl: response.data?.url || "",
|
|
679
|
+
path: response.data?.path || path,
|
|
680
|
+
expiresIn: response.data?.expiresIn || expiresIn
|
|
681
|
+
},
|
|
682
|
+
error: null
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
// Helper: Convert Blob to base64
|
|
686
|
+
blobToBase64(blob) {
|
|
687
|
+
return new Promise((resolve, reject) => {
|
|
688
|
+
const reader = new FileReader();
|
|
689
|
+
reader.onloadend = () => {
|
|
690
|
+
const result = reader.result;
|
|
691
|
+
const base64 = result.includes(",") ? result.split(",")[1] : result;
|
|
692
|
+
resolve(base64);
|
|
693
|
+
};
|
|
694
|
+
reader.onerror = reject;
|
|
695
|
+
reader.readAsDataURL(blob);
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
// Helper: Convert ArrayBuffer to base64
|
|
699
|
+
arrayBufferToBase64(buffer) {
|
|
700
|
+
let binary = "";
|
|
701
|
+
const bytes = new Uint8Array(buffer);
|
|
702
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
703
|
+
binary += String.fromCharCode(bytes[i]);
|
|
704
|
+
}
|
|
705
|
+
return btoa(binary);
|
|
706
|
+
}
|
|
707
|
+
// Helper: Detect MIME type from file extension
|
|
708
|
+
detectMimeType(path) {
|
|
709
|
+
const ext = path.split(".").pop()?.toLowerCase() || "";
|
|
710
|
+
const mimeTypes = {
|
|
711
|
+
// Images
|
|
712
|
+
jpg: "image/jpeg",
|
|
713
|
+
jpeg: "image/jpeg",
|
|
714
|
+
png: "image/png",
|
|
715
|
+
gif: "image/gif",
|
|
716
|
+
webp: "image/webp",
|
|
717
|
+
svg: "image/svg+xml",
|
|
718
|
+
ico: "image/x-icon",
|
|
719
|
+
// Documents
|
|
720
|
+
pdf: "application/pdf",
|
|
721
|
+
doc: "application/msword",
|
|
722
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
723
|
+
xls: "application/vnd.ms-excel",
|
|
724
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
725
|
+
// Text
|
|
726
|
+
txt: "text/plain",
|
|
727
|
+
csv: "text/csv",
|
|
728
|
+
json: "application/json",
|
|
729
|
+
xml: "application/xml",
|
|
730
|
+
html: "text/html",
|
|
731
|
+
css: "text/css",
|
|
732
|
+
js: "application/javascript",
|
|
733
|
+
// Audio/Video
|
|
734
|
+
mp3: "audio/mpeg",
|
|
735
|
+
wav: "audio/wav",
|
|
736
|
+
mp4: "video/mp4",
|
|
737
|
+
webm: "video/webm",
|
|
738
|
+
// Archives
|
|
739
|
+
zip: "application/zip",
|
|
740
|
+
tar: "application/x-tar",
|
|
741
|
+
gz: "application/gzip"
|
|
742
|
+
};
|
|
743
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
var KrisspyStorage = class {
|
|
747
|
+
constructor(http, backendId) {
|
|
748
|
+
this.http = http;
|
|
749
|
+
this.backendId = backendId;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Select a storage bucket
|
|
753
|
+
*
|
|
754
|
+
* @param bucket - Bucket name (e.g., 'avatars', 'documents', 'media')
|
|
755
|
+
* @returns StorageBucket instance for file operations
|
|
756
|
+
*
|
|
757
|
+
* @example
|
|
758
|
+
* const bucket = krisspy.storage.from('avatars')
|
|
759
|
+
* await bucket.upload('profile.jpg', file)
|
|
760
|
+
*/
|
|
761
|
+
from(bucket) {
|
|
762
|
+
return new StorageBucket(this.http, this.backendId, bucket);
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* List all buckets (currently returns predefined buckets)
|
|
766
|
+
*/
|
|
767
|
+
async listBuckets() {
|
|
768
|
+
return {
|
|
769
|
+
data: [
|
|
770
|
+
{ name: "media" },
|
|
771
|
+
{ name: "avatars" },
|
|
772
|
+
{ name: "documents" },
|
|
773
|
+
{ name: "uploads" }
|
|
774
|
+
],
|
|
775
|
+
error: null
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
|
|
481
780
|
// src/query-builder.ts
|
|
482
781
|
var QueryBuilder = class {
|
|
483
782
|
constructor(http, backendId, tableName, useRLS = true) {
|
|
@@ -769,6 +1068,7 @@ var KrisspyClient = class {
|
|
|
769
1068
|
debug: options.debug
|
|
770
1069
|
});
|
|
771
1070
|
this._auth = new KrisspyAuth(this.http, this.backendId);
|
|
1071
|
+
this._storage = new KrisspyStorage(this.http, this.backendId);
|
|
772
1072
|
}
|
|
773
1073
|
/**
|
|
774
1074
|
* Auth module for user authentication
|
|
@@ -795,6 +1095,30 @@ var KrisspyClient = class {
|
|
|
795
1095
|
get auth() {
|
|
796
1096
|
return this._auth;
|
|
797
1097
|
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Storage module for file uploads and downloads
|
|
1100
|
+
*
|
|
1101
|
+
* @example
|
|
1102
|
+
* // Upload a file
|
|
1103
|
+
* const { data, error } = await krisspy.storage
|
|
1104
|
+
* .from('avatars')
|
|
1105
|
+
* .upload('profile.jpg', file)
|
|
1106
|
+
*
|
|
1107
|
+
* // Get public URL
|
|
1108
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
1109
|
+
*
|
|
1110
|
+
* // Download
|
|
1111
|
+
* const { data, error } = await krisspy.storage.from('docs').download('file.pdf')
|
|
1112
|
+
*
|
|
1113
|
+
* // List files
|
|
1114
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
1115
|
+
*
|
|
1116
|
+
* // Delete files
|
|
1117
|
+
* const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
|
|
1118
|
+
*/
|
|
1119
|
+
get storage() {
|
|
1120
|
+
return this._storage;
|
|
1121
|
+
}
|
|
798
1122
|
/**
|
|
799
1123
|
* Create a query builder for a table
|
|
800
1124
|
*
|
|
@@ -916,6 +1240,8 @@ function createClient(options) {
|
|
|
916
1240
|
HttpClient,
|
|
917
1241
|
KrisspyAuth,
|
|
918
1242
|
KrisspyClient,
|
|
1243
|
+
KrisspyStorage,
|
|
919
1244
|
QueryBuilder,
|
|
1245
|
+
StorageBucket,
|
|
920
1246
|
createClient
|
|
921
1247
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -448,6 +448,303 @@ var KrisspyAuth = class {
|
|
|
448
448
|
}
|
|
449
449
|
};
|
|
450
450
|
|
|
451
|
+
// src/storage.ts
|
|
452
|
+
var StorageBucket = class {
|
|
453
|
+
constructor(http, backendId, bucketName) {
|
|
454
|
+
this.http = http;
|
|
455
|
+
this.backendId = backendId;
|
|
456
|
+
this.bucketName = bucketName;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Upload a file to the bucket
|
|
460
|
+
*
|
|
461
|
+
* @param path - Path/filename for the file (e.g., "images/profile.jpg")
|
|
462
|
+
* @param file - File data as Blob, File, ArrayBuffer, or base64 string
|
|
463
|
+
* @param options - Upload options
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* // Upload from file input
|
|
467
|
+
* const file = event.target.files[0]
|
|
468
|
+
* const { data, error } = await krisspy.storage
|
|
469
|
+
* .from('avatars')
|
|
470
|
+
* .upload('profile.jpg', file)
|
|
471
|
+
*
|
|
472
|
+
* // Upload base64 image
|
|
473
|
+
* const { data, error } = await krisspy.storage
|
|
474
|
+
* .from('images')
|
|
475
|
+
* .upload('photo.png', base64Data, { contentType: 'image/png' })
|
|
476
|
+
*/
|
|
477
|
+
async upload(path, file, options) {
|
|
478
|
+
try {
|
|
479
|
+
let base64Data;
|
|
480
|
+
let contentType = options?.contentType;
|
|
481
|
+
if (typeof file === "string") {
|
|
482
|
+
base64Data = file;
|
|
483
|
+
} else if (file instanceof Blob || file instanceof File) {
|
|
484
|
+
base64Data = await this.blobToBase64(file);
|
|
485
|
+
if (!contentType && file instanceof File) {
|
|
486
|
+
contentType = file.type;
|
|
487
|
+
}
|
|
488
|
+
} else if (file instanceof ArrayBuffer) {
|
|
489
|
+
base64Data = this.arrayBufferToBase64(file);
|
|
490
|
+
} else {
|
|
491
|
+
throw new Error("Invalid file type. Expected Blob, File, ArrayBuffer, or base64 string.");
|
|
492
|
+
}
|
|
493
|
+
if (!contentType) {
|
|
494
|
+
contentType = this.detectMimeType(path);
|
|
495
|
+
}
|
|
496
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/upload`;
|
|
497
|
+
const response = await this.http.post(apiPath, {
|
|
498
|
+
bucket: this.bucketName,
|
|
499
|
+
path,
|
|
500
|
+
data: base64Data,
|
|
501
|
+
contentType
|
|
502
|
+
});
|
|
503
|
+
if (response.error) {
|
|
504
|
+
return { data: null, error: response.error };
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
data: {
|
|
508
|
+
path: response.data?.path || path,
|
|
509
|
+
url: response.data?.url || "",
|
|
510
|
+
bucket: response.data?.bucket || this.bucketName,
|
|
511
|
+
contentType: response.data?.contentType || contentType || "application/octet-stream",
|
|
512
|
+
size: response.data?.size || 0
|
|
513
|
+
},
|
|
514
|
+
error: null
|
|
515
|
+
};
|
|
516
|
+
} catch (error) {
|
|
517
|
+
return {
|
|
518
|
+
data: null,
|
|
519
|
+
error: {
|
|
520
|
+
message: error.message || "Upload failed",
|
|
521
|
+
code: "STORAGE_UPLOAD_ERROR"
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Get the public URL of a file
|
|
528
|
+
*
|
|
529
|
+
* @param path - Path to the file
|
|
530
|
+
*
|
|
531
|
+
* @example
|
|
532
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
533
|
+
* console.log(data.publicUrl) // https://...
|
|
534
|
+
*/
|
|
535
|
+
getPublicUrl(path) {
|
|
536
|
+
const baseUrl = "https://krisspy.blob.core.windows.net/public";
|
|
537
|
+
const storagePath = `backends/${this.backendId}/${this.bucketName}/${path}`;
|
|
538
|
+
const publicUrl = `${baseUrl}/${storagePath}`;
|
|
539
|
+
return {
|
|
540
|
+
data: { publicUrl }
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Download a file (get download URL)
|
|
545
|
+
*
|
|
546
|
+
* @param path - Path to the file
|
|
547
|
+
*
|
|
548
|
+
* @example
|
|
549
|
+
* const { data, error } = await krisspy.storage
|
|
550
|
+
* .from('documents')
|
|
551
|
+
* .download('report.pdf')
|
|
552
|
+
*/
|
|
553
|
+
async download(path) {
|
|
554
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/download`;
|
|
555
|
+
const response = await this.http.post(apiPath, {
|
|
556
|
+
bucket: this.bucketName,
|
|
557
|
+
path
|
|
558
|
+
});
|
|
559
|
+
if (response.error) {
|
|
560
|
+
return { data: null, error: response.error };
|
|
561
|
+
}
|
|
562
|
+
return {
|
|
563
|
+
data: {
|
|
564
|
+
url: response.data?.url || "",
|
|
565
|
+
path: response.data?.path || path,
|
|
566
|
+
bucket: response.data?.bucket || this.bucketName
|
|
567
|
+
},
|
|
568
|
+
error: null
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Delete a file from storage
|
|
573
|
+
*
|
|
574
|
+
* @param paths - Path(s) to delete
|
|
575
|
+
*
|
|
576
|
+
* @example
|
|
577
|
+
* // Delete single file
|
|
578
|
+
* const { error } = await krisspy.storage.from('avatars').remove(['profile.jpg'])
|
|
579
|
+
*
|
|
580
|
+
* // Delete multiple files
|
|
581
|
+
* const { error } = await krisspy.storage.from('images').remove(['a.jpg', 'b.jpg'])
|
|
582
|
+
*/
|
|
583
|
+
async remove(paths) {
|
|
584
|
+
const results = [];
|
|
585
|
+
for (const path of paths) {
|
|
586
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/delete`;
|
|
587
|
+
const response = await this.http.post(apiPath, {
|
|
588
|
+
bucket: this.bucketName,
|
|
589
|
+
path
|
|
590
|
+
});
|
|
591
|
+
if (response.error) {
|
|
592
|
+
return { data: null, error: response.error };
|
|
593
|
+
}
|
|
594
|
+
results.push({ success: response.data?.success || false });
|
|
595
|
+
}
|
|
596
|
+
return { data: { success: true }, error: null };
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* List files in the bucket
|
|
600
|
+
*
|
|
601
|
+
* @param prefix - Filter files by path prefix
|
|
602
|
+
* @param options - List options
|
|
603
|
+
*
|
|
604
|
+
* @example
|
|
605
|
+
* // List all files
|
|
606
|
+
* const { data, error } = await krisspy.storage.from('uploads').list()
|
|
607
|
+
*
|
|
608
|
+
* // List files in a folder
|
|
609
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
610
|
+
*/
|
|
611
|
+
async list(prefix, options) {
|
|
612
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/list`;
|
|
613
|
+
const response = await this.http.post(apiPath, {
|
|
614
|
+
bucket: this.bucketName,
|
|
615
|
+
prefix,
|
|
616
|
+
limit: options?.limit || 100
|
|
617
|
+
});
|
|
618
|
+
if (response.error) {
|
|
619
|
+
return { data: null, error: response.error };
|
|
620
|
+
}
|
|
621
|
+
return { data: response.data?.files || [], error: null };
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Create a signed URL for temporary access
|
|
625
|
+
*
|
|
626
|
+
* @param path - Path to the file
|
|
627
|
+
* @param expiresIn - Expiration time in seconds (default: 3600)
|
|
628
|
+
*
|
|
629
|
+
* @example
|
|
630
|
+
* const { data, error } = await krisspy.storage
|
|
631
|
+
* .from('private')
|
|
632
|
+
* .createSignedUrl('document.pdf', 3600)
|
|
633
|
+
*/
|
|
634
|
+
async createSignedUrl(path, expiresIn = 3600) {
|
|
635
|
+
const apiPath = `/api/v1/cloud-backends/${this.backendId}/storage/signed-url`;
|
|
636
|
+
const response = await this.http.post(apiPath, {
|
|
637
|
+
bucket: this.bucketName,
|
|
638
|
+
path,
|
|
639
|
+
expiresIn
|
|
640
|
+
});
|
|
641
|
+
if (response.error) {
|
|
642
|
+
return { data: null, error: response.error };
|
|
643
|
+
}
|
|
644
|
+
return {
|
|
645
|
+
data: {
|
|
646
|
+
signedUrl: response.data?.url || "",
|
|
647
|
+
path: response.data?.path || path,
|
|
648
|
+
expiresIn: response.data?.expiresIn || expiresIn
|
|
649
|
+
},
|
|
650
|
+
error: null
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
// Helper: Convert Blob to base64
|
|
654
|
+
blobToBase64(blob) {
|
|
655
|
+
return new Promise((resolve, reject) => {
|
|
656
|
+
const reader = new FileReader();
|
|
657
|
+
reader.onloadend = () => {
|
|
658
|
+
const result = reader.result;
|
|
659
|
+
const base64 = result.includes(",") ? result.split(",")[1] : result;
|
|
660
|
+
resolve(base64);
|
|
661
|
+
};
|
|
662
|
+
reader.onerror = reject;
|
|
663
|
+
reader.readAsDataURL(blob);
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
// Helper: Convert ArrayBuffer to base64
|
|
667
|
+
arrayBufferToBase64(buffer) {
|
|
668
|
+
let binary = "";
|
|
669
|
+
const bytes = new Uint8Array(buffer);
|
|
670
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
671
|
+
binary += String.fromCharCode(bytes[i]);
|
|
672
|
+
}
|
|
673
|
+
return btoa(binary);
|
|
674
|
+
}
|
|
675
|
+
// Helper: Detect MIME type from file extension
|
|
676
|
+
detectMimeType(path) {
|
|
677
|
+
const ext = path.split(".").pop()?.toLowerCase() || "";
|
|
678
|
+
const mimeTypes = {
|
|
679
|
+
// Images
|
|
680
|
+
jpg: "image/jpeg",
|
|
681
|
+
jpeg: "image/jpeg",
|
|
682
|
+
png: "image/png",
|
|
683
|
+
gif: "image/gif",
|
|
684
|
+
webp: "image/webp",
|
|
685
|
+
svg: "image/svg+xml",
|
|
686
|
+
ico: "image/x-icon",
|
|
687
|
+
// Documents
|
|
688
|
+
pdf: "application/pdf",
|
|
689
|
+
doc: "application/msword",
|
|
690
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
691
|
+
xls: "application/vnd.ms-excel",
|
|
692
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
693
|
+
// Text
|
|
694
|
+
txt: "text/plain",
|
|
695
|
+
csv: "text/csv",
|
|
696
|
+
json: "application/json",
|
|
697
|
+
xml: "application/xml",
|
|
698
|
+
html: "text/html",
|
|
699
|
+
css: "text/css",
|
|
700
|
+
js: "application/javascript",
|
|
701
|
+
// Audio/Video
|
|
702
|
+
mp3: "audio/mpeg",
|
|
703
|
+
wav: "audio/wav",
|
|
704
|
+
mp4: "video/mp4",
|
|
705
|
+
webm: "video/webm",
|
|
706
|
+
// Archives
|
|
707
|
+
zip: "application/zip",
|
|
708
|
+
tar: "application/x-tar",
|
|
709
|
+
gz: "application/gzip"
|
|
710
|
+
};
|
|
711
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
var KrisspyStorage = class {
|
|
715
|
+
constructor(http, backendId) {
|
|
716
|
+
this.http = http;
|
|
717
|
+
this.backendId = backendId;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Select a storage bucket
|
|
721
|
+
*
|
|
722
|
+
* @param bucket - Bucket name (e.g., 'avatars', 'documents', 'media')
|
|
723
|
+
* @returns StorageBucket instance for file operations
|
|
724
|
+
*
|
|
725
|
+
* @example
|
|
726
|
+
* const bucket = krisspy.storage.from('avatars')
|
|
727
|
+
* await bucket.upload('profile.jpg', file)
|
|
728
|
+
*/
|
|
729
|
+
from(bucket) {
|
|
730
|
+
return new StorageBucket(this.http, this.backendId, bucket);
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* List all buckets (currently returns predefined buckets)
|
|
734
|
+
*/
|
|
735
|
+
async listBuckets() {
|
|
736
|
+
return {
|
|
737
|
+
data: [
|
|
738
|
+
{ name: "media" },
|
|
739
|
+
{ name: "avatars" },
|
|
740
|
+
{ name: "documents" },
|
|
741
|
+
{ name: "uploads" }
|
|
742
|
+
],
|
|
743
|
+
error: null
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
|
|
451
748
|
// src/query-builder.ts
|
|
452
749
|
var QueryBuilder = class {
|
|
453
750
|
constructor(http, backendId, tableName, useRLS = true) {
|
|
@@ -739,6 +1036,7 @@ var KrisspyClient = class {
|
|
|
739
1036
|
debug: options.debug
|
|
740
1037
|
});
|
|
741
1038
|
this._auth = new KrisspyAuth(this.http, this.backendId);
|
|
1039
|
+
this._storage = new KrisspyStorage(this.http, this.backendId);
|
|
742
1040
|
}
|
|
743
1041
|
/**
|
|
744
1042
|
* Auth module for user authentication
|
|
@@ -765,6 +1063,30 @@ var KrisspyClient = class {
|
|
|
765
1063
|
get auth() {
|
|
766
1064
|
return this._auth;
|
|
767
1065
|
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Storage module for file uploads and downloads
|
|
1068
|
+
*
|
|
1069
|
+
* @example
|
|
1070
|
+
* // Upload a file
|
|
1071
|
+
* const { data, error } = await krisspy.storage
|
|
1072
|
+
* .from('avatars')
|
|
1073
|
+
* .upload('profile.jpg', file)
|
|
1074
|
+
*
|
|
1075
|
+
* // Get public URL
|
|
1076
|
+
* const { data } = krisspy.storage.from('avatars').getPublicUrl('profile.jpg')
|
|
1077
|
+
*
|
|
1078
|
+
* // Download
|
|
1079
|
+
* const { data, error } = await krisspy.storage.from('docs').download('file.pdf')
|
|
1080
|
+
*
|
|
1081
|
+
* // List files
|
|
1082
|
+
* const { data, error } = await krisspy.storage.from('uploads').list('images/')
|
|
1083
|
+
*
|
|
1084
|
+
* // Delete files
|
|
1085
|
+
* const { error } = await krisspy.storage.from('uploads').remove(['old.jpg'])
|
|
1086
|
+
*/
|
|
1087
|
+
get storage() {
|
|
1088
|
+
return this._storage;
|
|
1089
|
+
}
|
|
768
1090
|
/**
|
|
769
1091
|
* Create a query builder for a table
|
|
770
1092
|
*
|
|
@@ -885,6 +1207,8 @@ export {
|
|
|
885
1207
|
HttpClient,
|
|
886
1208
|
KrisspyAuth,
|
|
887
1209
|
KrisspyClient,
|
|
1210
|
+
KrisspyStorage,
|
|
888
1211
|
QueryBuilder,
|
|
1212
|
+
StorageBucket,
|
|
889
1213
|
createClient
|
|
890
1214
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "krisspy-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Krisspy Cloud SDK - Database, Auth, and Functions for your apps",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Krisspy Cloud SDK - Database, Auth, Storage, and Functions for your apps",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -24,6 +24,11 @@
|
|
|
24
24
|
"baas",
|
|
25
25
|
"database",
|
|
26
26
|
"auth",
|
|
27
|
+
"storage",
|
|
28
|
+
"blob",
|
|
29
|
+
"functions",
|
|
30
|
+
"serverless",
|
|
31
|
+
"edge-functions",
|
|
27
32
|
"sdk",
|
|
28
33
|
"supabase-alternative"
|
|
29
34
|
],
|