supastash 0.1.13 → 0.1.14

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.
@@ -48,7 +48,7 @@ export function useSupastash() {
48
48
  initialized.current = true;
49
49
  async function init() {
50
50
  try {
51
- // Create tables
51
+ // Create supastash metadata tables
52
52
  await createSyncStatusTable();
53
53
  await createDeletedStatusTable();
54
54
  // On schema init
@@ -5,11 +5,11 @@ import { getSupastashDb } from "../../db/dbInitializer";
5
5
  export async function createSyncStatusTable() {
6
6
  const db = await getSupastashDb();
7
7
  const sql = `CREATE TABLE IF NOT EXISTS supastash_sync_status (
8
- table_name TEXT NOT NULL,
8
+ table_name TEXT PRIMARY KEY,
9
9
  last_synced_at TEXT NOT NULL
10
10
  );`;
11
11
  const sql2 = `CREATE TABLE IF NOT EXISTS supastash_last_created (
12
- table_name TEXT NOT NULL,
12
+ table_name TEXT PRIMARY KEY,
13
13
  last_created_at TEXT NOT NULL
14
14
  );`;
15
15
  await db.execAsync(sql);
@@ -21,7 +21,7 @@ export async function createSyncStatusTable() {
21
21
  export async function createDeletedStatusTable() {
22
22
  const db = await getSupastashDb();
23
23
  const sql = `CREATE TABLE IF NOT EXISTS supastash_deleted_status (
24
- table_name TEXT NOT NULL,
24
+ table_name TEXT PRIMARY KEY,
25
25
  last_deleted_at TEXT DEFAULT NULL
26
26
  );`;
27
27
  await db.execAsync(sql);
@@ -6,4 +6,6 @@ import { RealtimeFilter } from "../../../types/realtimeData.types";
6
6
  * @returns The data from the table
7
7
  */
8
8
  export declare function pullData(table: string, filter?: RealtimeFilter): Promise<PayloadData[] | null>;
9
+ export declare function getMaxCreatedDate(data: PayloadData[]): string | null;
10
+ export declare function getMaxUpdatedDate(data: PayloadData[]): string | null;
9
11
  //# sourceMappingURL=pullData.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pullData.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/pullData.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AA2BnE;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,CAmF/B"}
1
+ {"version":3,"file":"pullData.d.ts","sourceRoot":"","sources":["../../../../src/utils/sync/pullFromRemote/pullData.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AA2BnE;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,cAAc,GACtB,OAAO,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,CAqH/B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,GAAG,IAAI,CAgBpE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,GAAG,IAAI,CAgBpE"}
@@ -1,5 +1,5 @@
1
1
  import { getSupastashConfig } from "../../../core/config";
2
- import log from "../../logs";
2
+ import log, { logWarn } from "../../logs";
3
3
  import { supabaseClientErr } from "../../supabaseClientErr";
4
4
  import { getLastCreatedInfo, updateLastCreatedInfo, } from "./getLastCreatedInfo";
5
5
  import { getLastPulledInfo, updateLastPulledInfo } from "./getLastPulledInfo";
@@ -30,10 +30,16 @@ export async function pullData(table, filter) {
30
30
  const supabase = getSupastashConfig().supabaseClient;
31
31
  if (!supabase)
32
32
  throw new Error(`No supabase client found: ${supabaseClientErr}`);
33
- let filteredQuery = supabase
33
+ let filteredLastCreatedQuery = supabase
34
34
  .from(table)
35
35
  .select("*")
36
- .or(`created_at.gte.${lastCreatedAt},updated_at.gte.${lastSyncedAt}`)
36
+ .gte("created_at", lastCreatedAt || RANDOM_OLD_DATE)
37
+ .is("deleted_at", null)
38
+ .order("updated_at", { ascending: false, nullsFirst: false });
39
+ let filteredLastSyncedQuery = supabase
40
+ .from(table)
41
+ .select("*")
42
+ .gte("updated_at", lastSyncedAt || RANDOM_OLD_DATE)
37
43
  .is("deleted_at", null)
38
44
  .order("updated_at", { ascending: false, nullsFirst: false });
39
45
  if (filter &&
@@ -51,14 +57,27 @@ export async function pullData(table, filter) {
51
57
  validOperators.has(filter.operator) &&
52
58
  filter.column &&
53
59
  isValidValue) {
54
- filteredQuery = filteredQuery[filter.operator](filter.column, filter.value);
60
+ filteredLastCreatedQuery = filteredLastCreatedQuery[filter.operator](filter.column, filter.value);
61
+ filteredLastSyncedQuery = filteredLastSyncedQuery[filter.operator](filter.column, filter.value);
55
62
  }
56
63
  // Fetch records where created_at >= lastCreatedAt OR updated_at >= lastSyncedAt
57
- const { data, error } = await filteredQuery;
58
- if (error) {
59
- log(`[Supastash] Error fetching from ${table}:`, error.message);
64
+ const { data: lastCreatedData, error: lastCreatedError, } = await filteredLastCreatedQuery;
65
+ const { data: lastSyncedData, error: lastSyncedError, } = await filteredLastSyncedQuery;
66
+ if (lastCreatedError || lastSyncedError) {
67
+ log(`[Supastash] Error fetching from ${table}:`, lastCreatedError?.message || lastSyncedError?.message);
60
68
  return null;
61
69
  }
70
+ const allRows = [...(lastCreatedData ?? []), ...(lastSyncedData ?? [])];
71
+ const merged = {};
72
+ for (const row of allRows) {
73
+ if (!row.id) {
74
+ logWarn(`[Supastash] Skipped row without id from "${table}":`, row);
75
+ continue;
76
+ }
77
+ const id = row.id;
78
+ merged[id] = row;
79
+ }
80
+ const data = Object.values(merged);
62
81
  if (!data || data.length === 0) {
63
82
  timesPulled.set(table, (timesPulled.get(table) || 0) + 1);
64
83
  if ((timesPulled.get(table) || 0) >= DEFAULT_MAX_PULL_ATTEMPTS) {
@@ -71,7 +90,8 @@ export async function pullData(table, filter) {
71
90
  }
72
91
  log(`Received ${data.length} updates for ${table}`);
73
92
  // Update the sync status tables with the latest timestamps
74
- const { createdMaxDate, updatedMaxDate } = getMaxDate(data);
93
+ const createdMaxDate = getMaxCreatedDate(lastCreatedData ?? []);
94
+ const updatedMaxDate = getMaxUpdatedDate(lastSyncedData ?? []);
75
95
  if (updatedMaxDate) {
76
96
  await updateLastPulledInfo(table, updatedMaxDate);
77
97
  }
@@ -80,23 +100,35 @@ export async function pullData(table, filter) {
80
100
  }
81
101
  return data;
82
102
  }
83
- function getMaxDate(data) {
84
- let createdMaxDate = RANDOM_OLD_DATE;
85
- let updatedMaxDate = RANDOM_OLD_DATE;
103
+ export function getMaxCreatedDate(data) {
104
+ if (!data || data.length === 0)
105
+ return null;
86
106
  const createdColumn = "created_at";
87
- const updatedColumn = "updated_at";
107
+ let maxDate = RANDOM_OLD_DATE;
88
108
  for (const item of data) {
89
109
  const createdValue = item[createdColumn];
90
- const updatedValue = item[updatedColumn];
91
110
  if (typeof createdValue === "string" && !isNaN(Date.parse(createdValue))) {
92
- createdMaxDate = new Date(Math.max(new Date(createdMaxDate).getTime(), new Date(createdValue).getTime())).toISOString();
111
+ const createdTime = new Date(createdValue).getTime();
112
+ if (createdTime > new Date(maxDate).getTime()) {
113
+ maxDate = new Date(createdTime).toISOString();
114
+ }
93
115
  }
116
+ }
117
+ return maxDate === RANDOM_OLD_DATE ? null : maxDate;
118
+ }
119
+ export function getMaxUpdatedDate(data) {
120
+ if (!data || data.length === 0)
121
+ return null;
122
+ const updatedColumn = "updated_at";
123
+ let maxDate = RANDOM_OLD_DATE;
124
+ for (const item of data) {
125
+ const updatedValue = item[updatedColumn];
94
126
  if (typeof updatedValue === "string" && !isNaN(Date.parse(updatedValue))) {
95
- updatedMaxDate = new Date(Math.max(new Date(updatedMaxDate).getTime(), new Date(updatedValue).getTime())).toISOString();
127
+ const updatedTime = new Date(updatedValue).getTime();
128
+ if (updatedTime > new Date(maxDate).getTime()) {
129
+ maxDate = new Date(updatedTime).toISOString();
130
+ }
96
131
  }
97
132
  }
98
- return {
99
- createdMaxDate: createdMaxDate === RANDOM_OLD_DATE ? null : createdMaxDate,
100
- updatedMaxDate: updatedMaxDate === RANDOM_OLD_DATE ? null : updatedMaxDate,
101
- };
133
+ return maxDate === RANDOM_OLD_DATE ? null : maxDate;
102
134
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "supastash",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",