From b37d7c577c5061e5d2621737d4798418eedcb101 Mon Sep 17 00:00:00 2001 From: chark1es Date: Mon, 10 Feb 2025 22:36:58 -0800 Subject: [PATCH] Add Datatime conversion --- src/components/pocketbase/Get.ts | 62 ++++++++++++++++++++++++--- src/components/pocketbase/Update.ts | 66 ++++++++++++++++++++++------- 2 files changed, 106 insertions(+), 22 deletions(-) diff --git a/src/components/pocketbase/Get.ts b/src/components/pocketbase/Get.ts index 7a6c1c6..c87a159 100644 --- a/src/components/pocketbase/Get.ts +++ b/src/components/pocketbase/Get.ts @@ -12,6 +12,30 @@ interface RequestOptions { disableAutoCancellation?: boolean; } +// Utility function to check if a value is a UTC date string +function isUTCDateString(value: any): boolean { + if (typeof value !== "string") return false; + const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z$/; + return isoDateRegex.test(value); +} + +// Utility function to convert UTC date strings to local time +function convertUTCToLocal(data: T): T { + if (!data || typeof data !== "object") return data; + + const converted = { ...data }; + for (const [key, value] of Object.entries(converted)) { + if (isUTCDateString(value)) { + (converted as any)[key] = new Date(value).toISOString(); + } else if (Array.isArray(value)) { + (converted as any)[key] = value.map((item) => convertUTCToLocal(item)); + } else if (typeof value === "object" && value !== null) { + (converted as any)[key] = convertUTCToLocal(value); + } + } + return converted; +} + export class Get { private auth: Authentication; private static instance: Get; @@ -30,6 +54,24 @@ export class Get { return Get.instance; } + /** + * Convert UTC date strings to local time + * @param data The data to convert + * @returns The converted data + */ + public static convertUTCToLocal(data: T): T { + return convertUTCToLocal(data); + } + + /** + * Check if a value is a UTC date string + * @param value The value to check + * @returns True if the value is a UTC date string + */ + public static isUTCDateString(value: any): boolean { + return isUTCDateString(value); + } + /** * Get a single record by ID * @param collectionName The name of the collection @@ -52,9 +94,10 @@ export class Get { ...(options?.fields && { fields: options.fields.join(",") }), ...(options?.disableAutoCancellation && { requestKey: null }), }; - return await pb + const result = await pb .collection(collectionName) .getOne(recordId, requestOptions); + return convertUTCToLocal(result); } catch (err) { console.error(`Failed to get record from ${collectionName}:`, err); throw err; @@ -90,8 +133,10 @@ export class Get { .collection(collectionName) .getFullList(requestOptions); - // Sort results to match the order of requested IDs - const recordMap = new Map(result.map((record) => [record.id, record])); + // Sort results to match the order of requested IDs and convert times + const recordMap = new Map( + result.map((record) => [record.id, convertUTCToLocal(record)]), + ); return recordIds.map((id) => recordMap.get(id)).filter(Boolean) as T[]; } catch (err) { console.error(`Failed to get records from ${collectionName}:`, err); @@ -145,7 +190,7 @@ export class Get { perPage: result.perPage, totalItems: result.totalItems, totalPages: result.totalPages, - items: result.items, + items: result.items.map((item) => convertUTCToLocal(item)), }; } catch (err) { console.error(`Failed to get list from ${collectionName}:`, err); @@ -180,7 +225,10 @@ export class Get { ...(options?.disableAutoCancellation && { requestKey: null }), }; - return await pb.collection(collectionName).getFullList(requestOptions); + const result = await pb + .collection(collectionName) + .getFullList(requestOptions); + return result.map((item) => convertUTCToLocal(item)); } catch (err) { console.error(`Failed to get all records from ${collectionName}:`, err); throw err; @@ -216,7 +264,9 @@ export class Get { const result = await pb .collection(collectionName) .getList(1, 1, requestOptions); - return result.items.length > 0 ? result.items[0] : null; + return result.items.length > 0 + ? convertUTCToLocal(result.items[0]) + : null; } catch (err) { console.error(`Failed to get first record from ${collectionName}:`, err); throw err; diff --git a/src/components/pocketbase/Update.ts b/src/components/pocketbase/Update.ts index 3c3bf29..b5a77b5 100644 --- a/src/components/pocketbase/Update.ts +++ b/src/components/pocketbase/Update.ts @@ -1,5 +1,29 @@ import { Authentication } from "./Authentication"; +// Utility function to check if a value is a date string +function isLocalDateString(value: any): boolean { + if (typeof value !== "string") return false; + const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/; + return isoDateRegex.test(value); +} + +// Utility function to convert local time to UTC +function convertLocalToUTC(data: T): T { + if (!data || typeof data !== "object") return data; + + const converted = { ...data }; + for (const [key, value] of Object.entries(converted)) { + if (isLocalDateString(value)) { + (converted as any)[key] = new Date(value).toISOString(); + } else if (Array.isArray(value)) { + (converted as any)[key] = value.map((item) => convertLocalToUTC(item)); + } else if (typeof value === "object" && value !== null) { + (converted as any)[key] = convertLocalToUTC(value); + } + } + return converted; +} + export class Update { private auth: Authentication; private static instance: Update; @@ -30,7 +54,7 @@ export class Update { collectionName: string, recordId: string, field: string, - value: any + value: any, ): Promise { if (!this.auth.isAuthenticated()) { throw new Error("User must be authenticated to update records"); @@ -40,7 +64,10 @@ export class Update { this.auth.setUpdating(true); const pb = this.auth.getPocketBase(); const data = { [field]: value }; - const result = await pb.collection(collectionName).update(recordId, data); + const convertedData = convertLocalToUTC(data); + const result = await pb + .collection(collectionName) + .update(recordId, convertedData); return result; } catch (err) { console.error(`Failed to update ${field} in ${collectionName}:`, err); @@ -60,7 +87,7 @@ export class Update { public async updateFields( collectionName: string, recordId: string, - updates: Record + updates: Record, ): Promise { if (!this.auth.isAuthenticated()) { throw new Error("User must be authenticated to update records"); @@ -69,7 +96,10 @@ export class Update { try { this.auth.setUpdating(true); const pb = this.auth.getPocketBase(); - const result = await pb.collection(collectionName).update(recordId, updates); + const convertedUpdates = convertLocalToUTC(updates); + const result = await pb + .collection(collectionName) + .update(recordId, convertedUpdates); return result; } catch (err) { console.error(`Failed to update fields in ${collectionName}:`, err); @@ -91,7 +121,7 @@ export class Update { collectionName: string, recordIds: string[], field: string, - value: any + value: any, ): Promise { if (!this.auth.isAuthenticated()) { throw new Error("User must be authenticated to update records"); @@ -101,15 +131,19 @@ export class Update { this.auth.setUpdating(true); const pb = this.auth.getPocketBase(); const data = { [field]: value }; - - const updates = recordIds.map(id => - pb.collection(collectionName).update(id, data) + const convertedData = convertLocalToUTC(data); + + const updates = recordIds.map((id) => + pb.collection(collectionName).update(id, convertedData), ); - + const results = await Promise.all(updates); return results; } catch (err) { - console.error(`Failed to batch update ${field} in ${collectionName}:`, err); + console.error( + `Failed to batch update ${field} in ${collectionName}:`, + err, + ); throw err; } finally { this.auth.setUpdating(false); @@ -124,7 +158,7 @@ export class Update { */ public async batchUpdateFields( collectionName: string, - updates: Array<{ id: string; data: Record }> + updates: Array<{ id: string; data: Record }>, ): Promise { if (!this.auth.isAuthenticated()) { throw new Error("User must be authenticated to update records"); @@ -133,11 +167,11 @@ export class Update { try { this.auth.setUpdating(true); const pb = this.auth.getPocketBase(); - - const updatePromises = updates.map(({ id, data }) => - pb.collection(collectionName).update(id, data) + + const updatePromises = updates.map(({ id, data }) => + pb.collection(collectionName).update(id, convertLocalToUTC(data)), ); - + const results = await Promise.all(updatePromises); return results; } catch (err) { @@ -147,4 +181,4 @@ export class Update { this.auth.setUpdating(false); } } -} \ No newline at end of file +}