@urbackend/sdk 0.4.0 → 0.4.2

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.cts CHANGED
@@ -537,8 +537,8 @@ declare class AuthModule {
537
537
  * Exchanges social authentication rtCode for a refresh token
538
538
  *
539
539
  * @param {SocialExchangePayload} payload - Social exchange data
540
+ * @param {string} payload.token - Access token fragment from social provider
540
541
  * @param {string} payload.rtCode - Return code from social provider
541
- * @param {string} payload.provider - Social provider ('github' or 'google')
542
542
  * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
543
543
  *
544
544
  * @throws {AuthError} If rtCode is invalid or expired
@@ -546,13 +546,14 @@ declare class AuthModule {
546
546
  *
547
547
  * @example
548
548
  * // After user returns from social login
549
- * const rtCode = new URLSearchParams(window.location.search).get('rtCode');
550
- * if (rtCode) {
551
- * const response = await auth.socialExchange({
552
- * rtCode: rtCode,
553
- * provider: 'github'
554
- * });
555
- * console.log('Social login successful:', response.accessToken);
549
+ * const urlParams = new URLSearchParams(window.location.search);
550
+ * const hashParams = new URLSearchParams(window.location.hash.substring(1));
551
+ * const rtCode = urlParams.get('rtCode');
552
+ * const token = hashParams.get('token');
553
+ * if (rtCode && token) {
554
+ * const response = await auth.socialExchange({ token, rtCode });
555
+ * console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);
556
+ * await auth.refreshToken();
556
557
  * }
557
558
  */
558
559
  socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse>;
@@ -670,6 +671,7 @@ declare class DatabaseModule {
670
671
  * @template T - The document type (extends DocumentData)
671
672
  * @param {string} collection - Name of the collection to query
672
673
  * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination
674
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
673
675
  * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)
674
676
  *
675
677
  * @throws {Error} If collection name is invalid
@@ -696,12 +698,13 @@ declare class DatabaseModule {
696
698
  * expand: ['profile']
697
699
  * });
698
700
  */
699
- getAll<T extends DocumentData>(collection: string, params?: QueryParams): Promise<T[]>;
701
+ getAll<T extends DocumentData>(collection: string, params?: QueryParams, token?: string): Promise<T[]>;
700
702
  /**
701
703
  * Counts documents in a collection with optional filters
702
704
  *
703
705
  * @param {string} collection - Name of the collection to count
704
706
  * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters
707
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
705
708
  * @returns {Promise<number>} Promise resolving to the total count of matching documents
706
709
  *
707
710
  * @throws {Error} If collection name is invalid
@@ -725,7 +728,7 @@ declare class DatabaseModule {
725
728
  * });
726
729
  * const totalPages = Math.ceil(total / 10);
727
730
  */
728
- count(collection: string, params?: Omit<QueryParams, 'count'>): Promise<number>;
731
+ count(collection: string, params?: Omit<QueryParams, 'count'>, token?: string): Promise<number>;
729
732
  /**
730
733
  * Fetches a single document by its ID
731
734
  *
@@ -735,6 +738,7 @@ declare class DatabaseModule {
735
738
  * @param {Object} [options={}] - Optional parameters
736
739
  * @param {string|string[]} [options.populate] - Fields to populate with related data
737
740
  * @param {string|string[]} [options.expand] - Fields to expand with nested data
741
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
738
742
  * @returns {Promise<T>} Promise resolving to the document
739
743
  *
740
744
  * @throws {NotFoundError} If document with given ID does not exist
@@ -765,7 +769,7 @@ declare class DatabaseModule {
765
769
  getOne<T extends DocumentData>(collection: string, id: string, options?: {
766
770
  populate?: string | string[];
767
771
  expand?: string | string[];
768
- }): Promise<T>;
772
+ }, token?: string): Promise<T>;
769
773
  /**
770
774
  * Inserts a new document into a collection
771
775
  *
package/dist/index.d.ts CHANGED
@@ -537,8 +537,8 @@ declare class AuthModule {
537
537
  * Exchanges social authentication rtCode for a refresh token
538
538
  *
539
539
  * @param {SocialExchangePayload} payload - Social exchange data
540
+ * @param {string} payload.token - Access token fragment from social provider
540
541
  * @param {string} payload.rtCode - Return code from social provider
541
- * @param {string} payload.provider - Social provider ('github' or 'google')
542
542
  * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
543
543
  *
544
544
  * @throws {AuthError} If rtCode is invalid or expired
@@ -546,13 +546,14 @@ declare class AuthModule {
546
546
  *
547
547
  * @example
548
548
  * // After user returns from social login
549
- * const rtCode = new URLSearchParams(window.location.search).get('rtCode');
550
- * if (rtCode) {
551
- * const response = await auth.socialExchange({
552
- * rtCode: rtCode,
553
- * provider: 'github'
554
- * });
555
- * console.log('Social login successful:', response.accessToken);
549
+ * const urlParams = new URLSearchParams(window.location.search);
550
+ * const hashParams = new URLSearchParams(window.location.hash.substring(1));
551
+ * const rtCode = urlParams.get('rtCode');
552
+ * const token = hashParams.get('token');
553
+ * if (rtCode && token) {
554
+ * const response = await auth.socialExchange({ token, rtCode });
555
+ * console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);
556
+ * await auth.refreshToken();
556
557
  * }
557
558
  */
558
559
  socialExchange(payload: SocialExchangePayload): Promise<SocialExchangeResponse>;
@@ -670,6 +671,7 @@ declare class DatabaseModule {
670
671
  * @template T - The document type (extends DocumentData)
671
672
  * @param {string} collection - Name of the collection to query
672
673
  * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination
674
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
673
675
  * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)
674
676
  *
675
677
  * @throws {Error} If collection name is invalid
@@ -696,12 +698,13 @@ declare class DatabaseModule {
696
698
  * expand: ['profile']
697
699
  * });
698
700
  */
699
- getAll<T extends DocumentData>(collection: string, params?: QueryParams): Promise<T[]>;
701
+ getAll<T extends DocumentData>(collection: string, params?: QueryParams, token?: string): Promise<T[]>;
700
702
  /**
701
703
  * Counts documents in a collection with optional filters
702
704
  *
703
705
  * @param {string} collection - Name of the collection to count
704
706
  * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters
707
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
705
708
  * @returns {Promise<number>} Promise resolving to the total count of matching documents
706
709
  *
707
710
  * @throws {Error} If collection name is invalid
@@ -725,7 +728,7 @@ declare class DatabaseModule {
725
728
  * });
726
729
  * const totalPages = Math.ceil(total / 10);
727
730
  */
728
- count(collection: string, params?: Omit<QueryParams, 'count'>): Promise<number>;
731
+ count(collection: string, params?: Omit<QueryParams, 'count'>, token?: string): Promise<number>;
729
732
  /**
730
733
  * Fetches a single document by its ID
731
734
  *
@@ -735,6 +738,7 @@ declare class DatabaseModule {
735
738
  * @param {Object} [options={}] - Optional parameters
736
739
  * @param {string|string[]} [options.populate] - Fields to populate with related data
737
740
  * @param {string|string[]} [options.expand] - Fields to expand with nested data
741
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
738
742
  * @returns {Promise<T>} Promise resolving to the document
739
743
  *
740
744
  * @throws {NotFoundError} If document with given ID does not exist
@@ -765,7 +769,7 @@ declare class DatabaseModule {
765
769
  getOne<T extends DocumentData>(collection: string, id: string, options?: {
766
770
  populate?: string | string[];
767
771
  expand?: string | string[];
768
- }): Promise<T>;
772
+ }, token?: string): Promise<T>;
769
773
  /**
770
774
  * Inserts a new document into a collection
771
775
  *
package/dist/index.mjs CHANGED
@@ -45,8 +45,34 @@ async function parseApiError(response) {
45
45
  let data;
46
46
  try {
47
47
  data = await response.json();
48
- if (typeof data === "object" && data !== null && "message" in data) {
49
- message = data.message || message;
48
+ if (typeof data === "object" && data !== null) {
49
+ const errData = data;
50
+ if ("error" in errData) {
51
+ let candidate = "";
52
+ if (typeof errData.error === "string") {
53
+ candidate = errData.error;
54
+ } else if (Array.isArray(errData.error) && errData.error.length > 0) {
55
+ candidate = errData.error.map((e) => {
56
+ if (typeof e === "object" && e !== null && "message" in e) {
57
+ return String(e.message);
58
+ }
59
+ return String(e);
60
+ }).join(", ");
61
+ } else {
62
+ candidate = JSON.stringify(errData.error);
63
+ }
64
+ if (candidate && candidate.trim().length > 0 && candidate !== "[]" && candidate !== "null") {
65
+ message = candidate;
66
+ } else if ("message" in errData) {
67
+ message = typeof errData.message === "string" ? errData.message : JSON.stringify(errData.message);
68
+ }
69
+ } else if ("message" in errData) {
70
+ if (typeof errData.message === "string") {
71
+ message = errData.message;
72
+ } else {
73
+ message = JSON.stringify(errData.message);
74
+ }
75
+ }
50
76
  }
51
77
  } catch {
52
78
  message = response.statusText || message;
@@ -499,8 +525,8 @@ var AuthModule = class {
499
525
  * Exchanges social authentication rtCode for a refresh token
500
526
  *
501
527
  * @param {SocialExchangePayload} payload - Social exchange data
528
+ * @param {string} payload.token - Access token fragment from social provider
502
529
  * @param {string} payload.rtCode - Return code from social provider
503
- * @param {string} payload.provider - Social provider ('github' or 'google')
504
530
  * @returns {Promise<SocialExchangeResponse>} Promise resolving to authentication response
505
531
  *
506
532
  * @throws {AuthError} If rtCode is invalid or expired
@@ -508,13 +534,14 @@ var AuthModule = class {
508
534
  *
509
535
  * @example
510
536
  * // After user returns from social login
511
- * const rtCode = new URLSearchParams(window.location.search).get('rtCode');
512
- * if (rtCode) {
513
- * const response = await auth.socialExchange({
514
- * rtCode: rtCode,
515
- * provider: 'github'
516
- * });
517
- * console.log('Social login successful:', response.accessToken);
537
+ * const urlParams = new URLSearchParams(window.location.search);
538
+ * const hashParams = new URLSearchParams(window.location.hash.substring(1));
539
+ * const rtCode = urlParams.get('rtCode');
540
+ * const token = hashParams.get('token');
541
+ * if (rtCode && token) {
542
+ * const response = await auth.socialExchange({ token, rtCode });
543
+ * console.log('Refresh token exchange successful, proceeding to token refresh:', response.rtToken);
544
+ * await auth.refreshToken();
518
545
  * }
519
546
  */
520
547
  async socialExchange(payload) {
@@ -631,6 +658,7 @@ var DatabaseModule = class {
631
658
  * @template T - The document type (extends DocumentData)
632
659
  * @param {string} collection - Name of the collection to query
633
660
  * @param {QueryParams} [params={}] - Optional query parameters for filtering, sorting, pagination
661
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
634
662
  * @returns {Promise<T[]>} Promise resolving to an array of documents (empty array if none found)
635
663
  *
636
664
  * @throws {Error} If collection name is invalid
@@ -657,11 +685,18 @@ var DatabaseModule = class {
657
685
  * expand: ['profile']
658
686
  * });
659
687
  */
660
- async getAll(collection, params = {}) {
688
+ async getAll(collection, params = {}, token) {
661
689
  const queryString = this.buildQueryString(params);
662
690
  const path = `/api/data/${collection}${queryString}`;
663
691
  try {
664
- return await this.client.request("GET", path);
692
+ const result = await this.client.request("GET", path, { token });
693
+ if (Array.isArray(result)) {
694
+ return result;
695
+ }
696
+ if (result && typeof result === "object" && Array.isArray(result.items)) {
697
+ return result.items;
698
+ }
699
+ return [];
665
700
  } catch (e) {
666
701
  if (e instanceof NotFoundError) {
667
702
  return [];
@@ -674,6 +709,7 @@ var DatabaseModule = class {
674
709
  *
675
710
  * @param {string} collection - Name of the collection to count
676
711
  * @param {Omit<QueryParams, 'count'>} [params={}] - Optional filter parameters
712
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
677
713
  * @returns {Promise<number>} Promise resolving to the total count of matching documents
678
714
  *
679
715
  * @throws {Error} If collection name is invalid
@@ -697,10 +733,10 @@ var DatabaseModule = class {
697
733
  * });
698
734
  * const totalPages = Math.ceil(total / 10);
699
735
  */
700
- async count(collection, params = {}) {
736
+ async count(collection, params = {}, token) {
701
737
  const queryString = this.buildQueryString({ ...params, count: "true" });
702
738
  const path = `/api/data/${collection}${queryString}`;
703
- const result = await this.client.request("GET", path);
739
+ const result = await this.client.request("GET", path, { token });
704
740
  return result.count;
705
741
  }
706
742
  /**
@@ -712,6 +748,7 @@ var DatabaseModule = class {
712
748
  * @param {Object} [options={}] - Optional parameters
713
749
  * @param {string|string[]} [options.populate] - Fields to populate with related data
714
750
  * @param {string|string[]} [options.expand] - Fields to expand with nested data
751
+ * @param {string} [token] - Optional authentication token (required for private-mode reads with publishable keys)
715
752
  * @returns {Promise<T>} Promise resolving to the document
716
753
  *
717
754
  * @throws {NotFoundError} If document with given ID does not exist
@@ -739,9 +776,9 @@ var DatabaseModule = class {
739
776
  * }
740
777
  * }
741
778
  */
742
- async getOne(collection, id, options = {}) {
779
+ async getOne(collection, id, options = {}, token) {
743
780
  const queryString = this.buildQueryString(options);
744
- return this.client.request("GET", `/api/data/${collection}/${id}${queryString}`);
781
+ return this.client.request("GET", `/api/data/${collection}/${id}${queryString}`, { token });
745
782
  }
746
783
  /**
747
784
  * Inserts a new document into a collection
@@ -1015,17 +1052,43 @@ var StorageModule = class {
1015
1052
  * }
1016
1053
  */
1017
1054
  async upload(file, filename) {
1018
- const formData = new FormData();
1019
- if (typeof window === "undefined" && typeof Buffer !== "undefined" && Buffer.isBuffer(file)) {
1020
- const blob = new Blob([file]);
1021
- formData.append("file", blob, filename || "file");
1055
+ let resolvedName = filename || "file";
1056
+ let contentType = "application/octet-stream";
1057
+ let fileSize;
1058
+ let fileData;
1059
+ if (typeof File !== "undefined" && file instanceof File) {
1060
+ resolvedName = filename || file.name;
1061
+ contentType = file.type || contentType;
1062
+ fileSize = file.size;
1063
+ fileData = file;
1064
+ } else if (file instanceof Blob) {
1065
+ contentType = file.type || contentType;
1066
+ fileSize = file.size;
1067
+ fileData = file;
1068
+ } else if (typeof Buffer !== "undefined" && Buffer.isBuffer(file)) {
1069
+ fileSize = file.length;
1070
+ fileData = file;
1022
1071
  } else {
1023
- formData.append("file", file, filename);
1072
+ throw new Error("Unsupported file type. Pass a File, Blob, or Buffer.");
1024
1073
  }
1025
- return this.client.request("POST", "/api/storage/upload", {
1026
- body: formData,
1027
- isMultipart: true
1074
+ const { signedUrl, filePath } = await this.client.request(
1075
+ "POST",
1076
+ "/api/storage/upload-request",
1077
+ { body: { filename: resolvedName, contentType, size: fileSize } }
1078
+ );
1079
+ const putResponse = await fetch(signedUrl, {
1080
+ method: "PUT",
1081
+ headers: { "Content-Type": contentType },
1082
+ body: fileData
1028
1083
  });
1084
+ if (!putResponse.ok) {
1085
+ throw new Error(`Direct upload to cloud failed: ${putResponse.status} ${putResponse.statusText}`);
1086
+ }
1087
+ return this.client.request(
1088
+ "POST",
1089
+ "/api/storage/upload-confirm",
1090
+ { body: { filePath, size: fileSize } }
1091
+ );
1029
1092
  }
1030
1093
  /**
1031
1094
  * Deletes a file from storage by its path
@@ -1199,6 +1262,9 @@ var MailModule = class {
1199
1262
  // src/client.ts
1200
1263
  var UrBackendClient = class {
1201
1264
  constructor(config) {
1265
+ if (!config.apiKey) {
1266
+ throw new Error("urbackend-sdk: apiKey is required to initialize the client.");
1267
+ }
1202
1268
  this.apiKey = config.apiKey;
1203
1269
  this.baseUrl = config.baseUrl || "https://api.ub.bitbros.in";
1204
1270
  this.headers = config.headers || {};
@@ -1251,7 +1317,7 @@ var UrBackendClient = class {
1251
1317
  const url = `${this.baseUrl}${path}`;
1252
1318
  const headers = {
1253
1319
  "x-api-key": this.apiKey,
1254
- "User-Agent": `urbackend-sdk-js/0.2.2`,
1320
+ "User-Agent": `urbackend-sdk-js/0.4.2`,
1255
1321
  ...this.headers
1256
1322
  };
1257
1323
  if (options.token) {