supastash 0.2.12 → 0.2.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.
- package/dist/desktop/utils/sync/pullFromRemote/updateLocalDb.d.ts.map +1 -1
- package/dist/desktop/utils/sync/pullFromRemote/updateLocalDb.js +13 -5
- package/dist/desktop/utils/sync/pushLocal/uploadChunk.d.ts.map +1 -1
- package/dist/desktop/utils/sync/pushLocal/uploadChunk.js +7 -1
- package/dist/native/utils/sync/pullFromRemote/updateLocalDb.d.ts.map +1 -1
- package/dist/native/utils/sync/pullFromRemote/updateLocalDb.js +13 -5
- package/dist/native/utils/sync/pushLocal/uploadChunk.d.ts.map +1 -1
- package/dist/native/utils/sync/pushLocal/uploadChunk.js +7 -1
- package/dist/shared/core/config/index.d.ts.map +1 -1
- package/dist/shared/core/config/index.js +8 -0
- package/dist/shared/types/supastashConfig.types.d.ts +21 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateLocalDb.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pullFromRemote/updateLocalDb.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAiB7E;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,eAAe,EAAE,EAC3B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,iBAmGhD;AAID;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,EAC/B,EAAE,EACF,KAAK,EACL,MAAM,EACN,SAAS,GACV,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"updateLocalDb.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pullFromRemote/updateLocalDb.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAiB7E;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,eAAe,EAAE,EAC3B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,iBAmGhD;AAID;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,EAC/B,EAAE,EACF,KAAK,EACL,MAAM,EACN,SAAS,GACV,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyElC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;EAyBE;AACF,wBAAsB,eAAe,CAAC,EACpC,EAAE,EACF,KAAK,EACL,OAAO,GACR,EAAE;IACD,EAAE,CAAC,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,GAAG,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkGhB"}
|
|
@@ -128,13 +128,17 @@ export async function upsertData({ tx, table, record, doesExist, }) {
|
|
|
128
128
|
}
|
|
129
129
|
try {
|
|
130
130
|
const db = tx ?? (await getSupastashDb());
|
|
131
|
-
const
|
|
131
|
+
const allColumns = await getTableSchema(table);
|
|
132
|
+
const pullFilterColumns = new Set(cfg.filterColumns?.pull?.[table] ?? []);
|
|
133
|
+
const columns = pullFilterColumns.size
|
|
134
|
+
? allColumns.filter((c) => !pullFilterColumns.has(c))
|
|
135
|
+
: allColumns;
|
|
132
136
|
const recordToSave = {
|
|
133
137
|
...record,
|
|
134
138
|
synced_at: new Date().toISOString(),
|
|
135
139
|
};
|
|
136
|
-
if (
|
|
137
|
-
const unknownKeys = Object.keys(record).filter((key) => !
|
|
140
|
+
if (cfg.debugMode) {
|
|
141
|
+
const unknownKeys = Object.keys(record).filter((key) => !allColumns.includes(key));
|
|
138
142
|
if (unknownKeys.length > 0 && !warned.get(table)) {
|
|
139
143
|
warned.set(table, true);
|
|
140
144
|
logWarn(`⚠️ [Supastash] '${table}' payload contains keys not in local schema: ${unknownKeys.join(", ")}. ` + `They will be ignored locally.`);
|
|
@@ -195,10 +199,14 @@ export async function upsertChunkData({ tx, table, records, }) {
|
|
|
195
199
|
if (cfg.supastashMode === "ghost")
|
|
196
200
|
return;
|
|
197
201
|
const db = tx ?? (await getSupastashDb());
|
|
198
|
-
const
|
|
202
|
+
const allColumns = await getTableSchema(table);
|
|
203
|
+
const pullFilterColumns = new Set(cfg.filterColumns?.pull?.[table] ?? []);
|
|
204
|
+
const columns = pullFilterColumns.size
|
|
205
|
+
? allColumns.filter((c) => !pullFilterColumns.has(c))
|
|
206
|
+
: allColumns;
|
|
199
207
|
const syncedAt = new Date().toISOString();
|
|
200
208
|
if (cfg.debugMode) {
|
|
201
|
-
const unknownKeys = Object.keys(records[0]).filter((key) => !
|
|
209
|
+
const unknownKeys = Object.keys(records[0]).filter((key) => !allColumns.includes(key));
|
|
202
210
|
if (unknownKeys.length > 0 && !warned.get(table)) {
|
|
203
211
|
warned.set(table, true);
|
|
204
212
|
logWarn(`⚠️ [Supastash] '${table}' payload contains keys not in local schema: ${unknownKeys.join(", ")}. ` + `They will be ignored locally.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pushLocal/uploadChunk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AA6OnE;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,WAAW,EAAE,EAC9B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../../src/desktop/utils/sync/pushLocal/uploadChunk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AA6OnE;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,WAAW,EAAE,EAC9B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,iBAmBtD"}
|
|
@@ -204,7 +204,13 @@ export async function uploadData(table, unsyncedRecords, onPushToRemote) {
|
|
|
204
204
|
const supabase = cfg.supabaseClient;
|
|
205
205
|
if (!supabase)
|
|
206
206
|
throw new Error("[Supastash] Supabase client not configured");
|
|
207
|
-
const
|
|
207
|
+
const pushFilterColumns = cfg.filterColumns?.push?.[table] ?? [];
|
|
208
|
+
const cleaned = unsyncedRecords.map(({ synced_at, deleted_at, arrived_at, ...rest }) => {
|
|
209
|
+
const row = enforceTimestamps(normalizeForSupabase(rest));
|
|
210
|
+
for (const col of pushFilterColumns)
|
|
211
|
+
delete row[col];
|
|
212
|
+
return row;
|
|
213
|
+
});
|
|
208
214
|
for (let i = 0; i < cleaned.length; i += DEFAULT_CHUNK_SIZE) {
|
|
209
215
|
const chunk = cleaned.slice(i, i + DEFAULT_CHUNK_SIZE);
|
|
210
216
|
await uploadChunk(table, chunk, onPushToRemote);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateLocalDb.d.ts","sourceRoot":"","sources":["../../../../../src/native/utils/sync/pullFromRemote/updateLocalDb.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAiB7E;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,eAAe,EAAE,EAC3B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,iBAkGhD;AAID;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,EAC/B,EAAE,EACF,KAAK,EACL,MAAM,EACN,SAAS,GACV,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"updateLocalDb.d.ts","sourceRoot":"","sources":["../../../../../src/native/utils/sync/pullFromRemote/updateLocalDb.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAiB7E;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,eAAe,EAAE,EAC3B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,iBAkGhD;AAID;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,EAC/B,EAAE,EACF,KAAK,EACL,MAAM,EACN,SAAS,GACV,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyElC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;EAyBE;AACF,wBAAsB,eAAe,CAAC,EACpC,EAAE,EACF,KAAK,EACL,OAAO,GACR,EAAE;IACD,EAAE,CAAC,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,GAAG,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+FhB"}
|
|
@@ -127,13 +127,17 @@ export async function upsertData({ tx, table, record, doesExist, }) {
|
|
|
127
127
|
}
|
|
128
128
|
try {
|
|
129
129
|
const db = tx ?? (await getSupastashDb());
|
|
130
|
-
const
|
|
130
|
+
const allColumns = await getTableSchema(table);
|
|
131
|
+
const pullFilterColumns = new Set(cfg.filterColumns?.pull?.[table] ?? []);
|
|
132
|
+
const columns = pullFilterColumns.size
|
|
133
|
+
? allColumns.filter((c) => !pullFilterColumns.has(c))
|
|
134
|
+
: allColumns;
|
|
131
135
|
const recordToSave = {
|
|
132
136
|
...record,
|
|
133
137
|
synced_at: new Date().toISOString(),
|
|
134
138
|
};
|
|
135
|
-
if (
|
|
136
|
-
const unknownKeys = Object.keys(record).filter((key) => !
|
|
139
|
+
if (cfg.debugMode) {
|
|
140
|
+
const unknownKeys = Object.keys(record).filter((key) => !allColumns.includes(key));
|
|
137
141
|
if (unknownKeys.length > 0 && !warned.get(table)) {
|
|
138
142
|
warned.set(table, true);
|
|
139
143
|
logWarn(`⚠️ [Supastash] '${table}' payload contains keys not in local schema: ${unknownKeys.join(", ")}. ` + `They will be ignored locally.`);
|
|
@@ -194,10 +198,14 @@ export async function upsertChunkData({ tx, table, records, }) {
|
|
|
194
198
|
if (cfg.supastashMode === "ghost")
|
|
195
199
|
return;
|
|
196
200
|
const db = tx ?? (await getSupastashDb());
|
|
197
|
-
const
|
|
201
|
+
const allColumns = await getTableSchema(table);
|
|
202
|
+
const pullFilterColumns = new Set(cfg.filterColumns?.pull?.[table] ?? []);
|
|
203
|
+
const columns = pullFilterColumns.size
|
|
204
|
+
? allColumns.filter((c) => !pullFilterColumns.has(c))
|
|
205
|
+
: allColumns;
|
|
198
206
|
const syncedAt = new Date().toISOString();
|
|
199
207
|
if (cfg.debugMode) {
|
|
200
|
-
const unknownKeys = Object.keys(records[0]).filter((key) => !
|
|
208
|
+
const unknownKeys = Object.keys(records[0]).filter((key) => !allColumns.includes(key));
|
|
201
209
|
if (unknownKeys.length > 0 && !warned.get(table)) {
|
|
202
210
|
warned.set(table, true);
|
|
203
211
|
logWarn(`⚠️ [Supastash] '${table}' payload contains keys not in local schema: ${unknownKeys.join(", ")}. ` + `They will be ignored locally.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../../src/native/utils/sync/pushLocal/uploadChunk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAgPnE;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,WAAW,EAAE,EAC9B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"uploadChunk.d.ts","sourceRoot":"","sources":["../../../../../src/native/utils/sync/pushLocal/uploadChunk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAgPnE;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,WAAW,EAAE,EAC9B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,iBAmBtD"}
|
|
@@ -207,7 +207,13 @@ export async function uploadData(table, unsyncedRecords, onPushToRemote) {
|
|
|
207
207
|
const supabase = cfg.supabaseClient;
|
|
208
208
|
if (!supabase)
|
|
209
209
|
throw new Error("[Supastash] Supabase client not configured");
|
|
210
|
-
const
|
|
210
|
+
const pushFilterColumns = cfg.filterColumns?.push?.[table] ?? [];
|
|
211
|
+
const cleaned = unsyncedRecords.map(({ synced_at, deleted_at, arrived_at, ...rest }) => {
|
|
212
|
+
const row = enforceTimestamps(normalizeForSupabase(rest));
|
|
213
|
+
for (const col of pushFilterColumns)
|
|
214
|
+
delete row[col];
|
|
215
|
+
return row;
|
|
216
|
+
});
|
|
211
217
|
for (let i = 0; i < cleaned.length; i += DEFAULT_CHUNK_SIZE) {
|
|
212
218
|
const chunk = cleaned.slice(i, i + DEFAULT_CHUNK_SIZE);
|
|
213
219
|
await uploadChunk(table, chunk, onPushToRemote);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/shared/core/config/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,0BAA0B,EAC3B,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/shared/core/config/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,0BAA0B,EAC3B,MAAM,mCAAmC,CAAC;AAyC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,0BAA0B,EACrE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG;IAAE,gBAAgB,EAAE,CAAC,CAAA;CAAE,QA4CrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,SAAS,0BAA0B,KACjC,eAAe,CAAC,CAAC,CAAC,CAEtB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,qBAAqB,CACnC,CAAC,SAAS,0BAA0B,EACpC,MAAM,EAAE;IACR,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG;QAC9B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;KAC3B,CAAC;CACH,QAEA"}
|
|
@@ -30,6 +30,10 @@ let _config = {
|
|
|
30
30
|
deleteConflictedRows: false,
|
|
31
31
|
pushRPCPath: undefined,
|
|
32
32
|
supastashMode: "live",
|
|
33
|
+
filterColumns: {
|
|
34
|
+
push: {},
|
|
35
|
+
pull: {},
|
|
36
|
+
},
|
|
33
37
|
};
|
|
34
38
|
let _configured = false;
|
|
35
39
|
/**
|
|
@@ -114,6 +118,10 @@ export function configureSupastash(config) {
|
|
|
114
118
|
..._config.fieldEnforcement,
|
|
115
119
|
...config.fieldEnforcement,
|
|
116
120
|
},
|
|
121
|
+
filterColumns: {
|
|
122
|
+
push: config.filterColumns?.push ?? _config.filterColumns?.push ?? {},
|
|
123
|
+
pull: config.filterColumns?.pull ?? _config.filterColumns?.pull ?? {},
|
|
124
|
+
},
|
|
117
125
|
};
|
|
118
126
|
_configured = true;
|
|
119
127
|
}
|
|
@@ -143,6 +143,27 @@ export type SupastashConfig<T extends SupastashSQLiteClientTypes> = {
|
|
|
143
143
|
push?: string[];
|
|
144
144
|
};
|
|
145
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Per-table column blocklists for upsert operations.
|
|
148
|
+
*
|
|
149
|
+
* Columns listed here are stripped from records **before** they are written,
|
|
150
|
+
* allowing you to prevent specific fields from being synced in either direction
|
|
151
|
+
* without altering your remote or local schema.
|
|
152
|
+
*
|
|
153
|
+
* - `push`: columns removed from each row before it is upserted to Supabase.
|
|
154
|
+
* - `pull`: columns removed from each row before it is written to the local SQLite DB.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* filterColumns: {
|
|
158
|
+
* push: { orders: ["internal_notes", "cost_price"] },
|
|
159
|
+
* pull: { users: ["password_hash", "secret_token"] },
|
|
160
|
+
* }
|
|
161
|
+
*/
|
|
162
|
+
filterColumns?: {
|
|
163
|
+
push?: Record<string, string[]>;
|
|
164
|
+
pull?: Record<string, string[]>;
|
|
165
|
+
};
|
|
166
|
+
|
|
146
167
|
// --------------------------------------------------
|
|
147
168
|
// Sync Polling Intervals
|
|
148
169
|
// --------------------------------------------------
|