@pol-studios/db 1.0.54 → 1.0.56
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/{DataLayerContext-C7cJtiO8.d.ts → DataLayerContext-BYZtDD0g.d.ts} +1 -1
- package/dist/auth/context.js +6 -4
- package/dist/auth/hooks.js +7 -5
- package/dist/auth/index.js +7 -5
- package/dist/{chunk-FIAXWEBK.js → chunk-4EO55YV2.js} +10 -7
- package/dist/chunk-4EO55YV2.js.map +1 -0
- package/dist/{chunk-DP3YEVSX.js → chunk-6SDH7M7J.js} +26 -10
- package/dist/chunk-6SDH7M7J.js.map +1 -0
- package/dist/{chunk-UJWETW36.js → chunk-AKIRHA4Q.js} +527 -418
- package/dist/chunk-AKIRHA4Q.js.map +1 -0
- package/dist/{chunk-2XS2PM62.js → chunk-DDL63KLQ.js} +388 -107
- package/dist/chunk-DDL63KLQ.js.map +1 -0
- package/dist/{chunk-YA6MUTA7.js → chunk-FI6JAD5G.js} +3 -3
- package/dist/{chunk-WQLIGVQR.js → chunk-GWYTROSD.js} +98 -1
- package/dist/chunk-GWYTROSD.js.map +1 -0
- package/dist/chunk-JOULSXOI.js +415 -0
- package/dist/chunk-JOULSXOI.js.map +1 -0
- package/dist/{chunk-OKYHI6JG.js → chunk-LF3V3ERS.js} +3 -3
- package/dist/{chunk-FMYXG4VN.js → chunk-MEBT5YHA.js} +2 -2
- package/dist/{chunk-BZSAPFFB.js → chunk-N4KK5G5T.js} +116 -18
- package/dist/chunk-N4KK5G5T.js.map +1 -0
- package/dist/chunk-QYAFI34Q.js +64 -0
- package/dist/chunk-QYAFI34Q.js.map +1 -0
- package/dist/{chunk-3Q74DK5K.js → chunk-VYFAMTHI.js} +2 -2
- package/dist/chunk-W7PERM66.js +215 -0
- package/dist/chunk-W7PERM66.js.map +1 -0
- package/dist/{chunk-ZGQ7Q4ZU.js → chunk-WM25QE7E.js} +2 -2
- package/dist/{chunk-HZIVE5AZ.js → chunk-YRIPM2AN.js} +253 -338
- package/dist/chunk-YRIPM2AN.js.map +1 -0
- package/dist/chunk-YUX6RGLZ.js +1858 -0
- package/dist/chunk-YUX6RGLZ.js.map +1 -0
- package/dist/{chunk-Z3EJX3VG.js → chunk-Z456IHCB.js} +3 -3
- package/dist/core/index.d.ts +24 -1
- package/dist/{executor-YJw4m7Q7.d.ts → executor-D15yjeMo.d.ts} +20 -0
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/index.js +4 -2
- package/dist/{index-jVYdTeWx.d.ts → index-CFUuTzXO.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +16 -14
- package/dist/index.native.d.ts +62 -8
- package/dist/index.native.js +16 -14
- package/dist/index.web.d.ts +10 -9
- package/dist/index.web.js +30 -19
- package/dist/index.web.js.map +1 -1
- package/dist/mutation/index.js +3 -3
- package/dist/parser/index.js +3 -3
- package/dist/powersync-bridge/index.d.ts +1 -1
- package/dist/query/index.d.ts +4 -83
- package/dist/query/index.js +17 -7
- package/dist/realtime/index.d.ts +80 -1
- package/dist/realtime/index.js +14 -12
- package/dist/realtime/index.js.map +1 -1
- package/dist/select-parser-BAV7fOaM.d.ts +144 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +4 -4
- package/dist/{useDbCount-DHLJzmkO.d.ts → useDbCount-Ckb-FhZk.d.ts} +1 -1
- package/dist/{useResolveFeedback-B0UcYWVI.d.ts → useResolveFeedback-CuUkdHoR.d.ts} +13 -29
- package/dist/with-auth/index.js +9 -7
- package/dist/with-auth/index.js.map +1 -1
- package/package.json +9 -4
- package/dist/chunk-2XS2PM62.js.map +0 -1
- package/dist/chunk-BZSAPFFB.js.map +0 -1
- package/dist/chunk-CTRY7JDP.js +0 -4112
- package/dist/chunk-CTRY7JDP.js.map +0 -1
- package/dist/chunk-DP3YEVSX.js.map +0 -1
- package/dist/chunk-FIAXWEBK.js.map +0 -1
- package/dist/chunk-HZIVE5AZ.js.map +0 -1
- package/dist/chunk-INEUG6MC.js +0 -521
- package/dist/chunk-INEUG6MC.js.map +0 -1
- package/dist/chunk-UJWETW36.js.map +0 -1
- package/dist/chunk-WQLIGVQR.js.map +0 -1
- /package/dist/{chunk-YA6MUTA7.js.map → chunk-FI6JAD5G.js.map} +0 -0
- /package/dist/{chunk-OKYHI6JG.js.map → chunk-LF3V3ERS.js.map} +0 -0
- /package/dist/{chunk-FMYXG4VN.js.map → chunk-MEBT5YHA.js.map} +0 -0
- /package/dist/{chunk-3Q74DK5K.js.map → chunk-VYFAMTHI.js.map} +0 -0
- /package/dist/{chunk-ZGQ7Q4ZU.js.map → chunk-WM25QE7E.js.map} +0 -0
- /package/dist/{chunk-Z3EJX3VG.js.map → chunk-Z456IHCB.js.map} +0 -0
|
@@ -3,17 +3,20 @@ import {
|
|
|
3
3
|
createAdapterRegistry,
|
|
4
4
|
createSupabaseAdapter,
|
|
5
5
|
stripSchemaPrefix
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DDL63KLQ.js";
|
|
7
7
|
import {
|
|
8
8
|
DataLayerContext,
|
|
9
9
|
DataLayerCoreContext,
|
|
10
|
+
DataLayerNestingContext,
|
|
10
11
|
DataLayerStatusContext
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GWYTROSD.js";
|
|
13
|
+
import {
|
|
14
|
+
QueryExecutor
|
|
15
|
+
} from "./chunk-YRIPM2AN.js";
|
|
12
16
|
import {
|
|
13
|
-
QueryExecutor,
|
|
14
17
|
extractRelationNames,
|
|
15
18
|
parseSelect
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-W7PERM66.js";
|
|
17
20
|
import {
|
|
18
21
|
useSupabase
|
|
19
22
|
} from "./chunk-DMVUEJG2.js";
|
|
@@ -1104,19 +1107,27 @@ function transformWithRelations(row, schema, tableName) {
|
|
|
1104
1107
|
}
|
|
1105
1108
|
|
|
1106
1109
|
// src/adapters/powersync-adapter.ts
|
|
1110
|
+
import stringify from "fast-json-stable-stringify";
|
|
1111
|
+
var DEFAULT_MAX_SUBSCRIPTIONS = 100;
|
|
1107
1112
|
var PowerSyncAdapter = class {
|
|
1108
1113
|
/**
|
|
1109
1114
|
* Create a new PowerSyncAdapter
|
|
1110
1115
|
*
|
|
1111
1116
|
* @param db - PowerSync database instance
|
|
1112
1117
|
* @param schema - Database schema for relationship resolution
|
|
1113
|
-
* @param
|
|
1118
|
+
* @param options - Optional configuration (tableNameResolver, maxSubscriptions)
|
|
1114
1119
|
*/
|
|
1115
|
-
constructor(db, schema,
|
|
1120
|
+
constructor(db, schema, options) {
|
|
1116
1121
|
this.db = db;
|
|
1117
1122
|
this.schema = schema;
|
|
1118
1123
|
this.executor = new QueryExecutor(db, schema);
|
|
1119
|
-
|
|
1124
|
+
if (typeof options === "function") {
|
|
1125
|
+
this.tableNameResolver = options;
|
|
1126
|
+
this.maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS;
|
|
1127
|
+
} else {
|
|
1128
|
+
this.tableNameResolver = options?.tableNameResolver;
|
|
1129
|
+
this.maxSubscriptions = options?.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS;
|
|
1130
|
+
}
|
|
1120
1131
|
}
|
|
1121
1132
|
/**
|
|
1122
1133
|
* Unique identifier for this adapter type
|
|
@@ -1140,6 +1151,31 @@ var PowerSyncAdapter = class {
|
|
|
1140
1151
|
* If not provided, uses default auto-alias generation.
|
|
1141
1152
|
*/
|
|
1142
1153
|
tableNameResolver;
|
|
1154
|
+
/**
|
|
1155
|
+
* Maximum number of subscriptions to keep in the registry.
|
|
1156
|
+
*/
|
|
1157
|
+
maxSubscriptions;
|
|
1158
|
+
/**
|
|
1159
|
+
* Subscription deduplication registry.
|
|
1160
|
+
* Maps cache keys (table + serialized options) to shared subscription entries.
|
|
1161
|
+
* This prevents duplicate PowerSync watch() calls when multiple components
|
|
1162
|
+
* subscribe to the same query.
|
|
1163
|
+
*
|
|
1164
|
+
* Uses Map insertion order for LRU eviction - most recently accessed entries
|
|
1165
|
+
* are moved to the end by deleting and re-adding.
|
|
1166
|
+
*/
|
|
1167
|
+
subscriptionRegistry = /* @__PURE__ */ new Map();
|
|
1168
|
+
/**
|
|
1169
|
+
* Move a subscription entry to the end of the Map for LRU tracking.
|
|
1170
|
+
* The most recently accessed entries are at the end; oldest are at the start.
|
|
1171
|
+
*
|
|
1172
|
+
* @param key - The subscription cache key
|
|
1173
|
+
* @param entry - The subscription entry to touch
|
|
1174
|
+
*/
|
|
1175
|
+
touchSubscription(key, entry) {
|
|
1176
|
+
this.subscriptionRegistry.delete(key);
|
|
1177
|
+
this.subscriptionRegistry.set(key, entry);
|
|
1178
|
+
}
|
|
1143
1179
|
/**
|
|
1144
1180
|
* Resolve a table name to its PowerSync alias.
|
|
1145
1181
|
* Schema-qualified names like "chat.Conversation" become "Conversation" (schema stripped).
|
|
@@ -1193,12 +1229,31 @@ var PowerSyncAdapter = class {
|
|
|
1193
1229
|
}
|
|
1194
1230
|
return transformWithRelations(rawResult, this.schema, table);
|
|
1195
1231
|
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Generate a unique cache key for subscription deduplication.
|
|
1234
|
+
* Combines table name and serialized options to identify identical queries.
|
|
1235
|
+
* Uses sorted keys to ensure consistent serialization regardless of property order.
|
|
1236
|
+
*
|
|
1237
|
+
* @param table - The table name
|
|
1238
|
+
* @param options - Query options
|
|
1239
|
+
* @returns A unique string key for the subscription registry
|
|
1240
|
+
*/
|
|
1241
|
+
generateSubscriptionKey(table, options) {
|
|
1242
|
+
return `${table}:${stringify(options)}`;
|
|
1243
|
+
}
|
|
1196
1244
|
/**
|
|
1197
1245
|
* Subscribe to changes on a query using PowerSync's native watch() API.
|
|
1198
1246
|
*
|
|
1199
1247
|
* This uses PowerSync's reactive query watching which efficiently detects
|
|
1200
1248
|
* changes to the underlying data and re-executes the query only when needed.
|
|
1201
1249
|
*
|
|
1250
|
+
* Subscription Deduplication:
|
|
1251
|
+
* Multiple components subscribing to the same query (same table + options)
|
|
1252
|
+
* will share a single underlying PowerSync watch. This optimization:
|
|
1253
|
+
* - Reduces database load by avoiding duplicate watches
|
|
1254
|
+
* - Provides instant data to new subscribers from cached results
|
|
1255
|
+
* - Properly cleans up when all subscribers unsubscribe
|
|
1256
|
+
*
|
|
1202
1257
|
* If the database doesn't support watch(), falls back to polling every 5 seconds.
|
|
1203
1258
|
*
|
|
1204
1259
|
* @param table - The table name to watch
|
|
@@ -1211,6 +1266,33 @@ var PowerSyncAdapter = class {
|
|
|
1211
1266
|
if (!this.db.watch) {
|
|
1212
1267
|
return this.subscribeWithPolling(table, options, callback);
|
|
1213
1268
|
}
|
|
1269
|
+
const cacheKey = this.generateSubscriptionKey(resolvedTable, options);
|
|
1270
|
+
const existingEntry = this.subscriptionRegistry.get(cacheKey);
|
|
1271
|
+
if (existingEntry) {
|
|
1272
|
+
existingEntry.subscribers.add(callback);
|
|
1273
|
+
this.touchSubscription(cacheKey, existingEntry);
|
|
1274
|
+
return () => {
|
|
1275
|
+
existingEntry.subscribers.delete(callback);
|
|
1276
|
+
if (existingEntry.subscribers.size === 0) {
|
|
1277
|
+
existingEntry.unsubscribe();
|
|
1278
|
+
this.subscriptionRegistry.delete(cacheKey);
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
}
|
|
1282
|
+
if (this.subscriptionRegistry.size >= this.maxSubscriptions) {
|
|
1283
|
+
let evicted = false;
|
|
1284
|
+
for (const [key, entry2] of this.subscriptionRegistry) {
|
|
1285
|
+
if (entry2.subscribers.size === 0) {
|
|
1286
|
+
entry2.unsubscribe();
|
|
1287
|
+
this.subscriptionRegistry.delete(key);
|
|
1288
|
+
evicted = true;
|
|
1289
|
+
break;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
if (!evicted && typeof __DEV__ !== "undefined" && __DEV__) {
|
|
1293
|
+
console.warn(`[PowerSyncAdapter] Subscription registry exceeded max (${this.maxSubscriptions}) but all entries have active subscribers. Registry size: ${this.subscriptionRegistry.size + 1}`);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1214
1296
|
const abortController = new AbortController();
|
|
1215
1297
|
const parsed = parseSelect(options.select ?? "*");
|
|
1216
1298
|
const builder = this.executor.getBuilder();
|
|
@@ -1225,16 +1307,22 @@ var PowerSyncAdapter = class {
|
|
|
1225
1307
|
});
|
|
1226
1308
|
let watchTables = [resolvedTable];
|
|
1227
1309
|
if (options.select && options.select !== "*") {
|
|
1228
|
-
const
|
|
1229
|
-
const relationNames = extractRelationNames(parsed2);
|
|
1310
|
+
const relationNames = extractRelationNames(parsed);
|
|
1230
1311
|
watchTables = [resolvedTable, ...relationNames.map((r) => this.resolveTableName(r))];
|
|
1231
1312
|
}
|
|
1313
|
+
const entry = {
|
|
1314
|
+
subscribers: /* @__PURE__ */ new Set([callback]),
|
|
1315
|
+
unsubscribe: () => abortController.abort()
|
|
1316
|
+
};
|
|
1317
|
+
this.subscriptionRegistry.set(cacheKey, entry);
|
|
1232
1318
|
const schema = this.schema;
|
|
1233
1319
|
this.db.watch(sql, params, {
|
|
1234
1320
|
onResult: (results) => {
|
|
1235
1321
|
const rawData = results.rows?._array ?? [];
|
|
1236
1322
|
const data = transformResultsFromStorage(rawData, schema, table);
|
|
1237
|
-
|
|
1323
|
+
for (const subscriber of entry.subscribers) {
|
|
1324
|
+
subscriber(data);
|
|
1325
|
+
}
|
|
1238
1326
|
},
|
|
1239
1327
|
onError: (error) => {
|
|
1240
1328
|
console.error(`PowerSync subscription error for ${resolvedTable}:`, error);
|
|
@@ -1246,7 +1334,11 @@ var PowerSyncAdapter = class {
|
|
|
1246
1334
|
// Throttle to prevent excessive re-queries
|
|
1247
1335
|
});
|
|
1248
1336
|
return () => {
|
|
1249
|
-
|
|
1337
|
+
entry.subscribers.delete(callback);
|
|
1338
|
+
if (entry.subscribers.size === 0) {
|
|
1339
|
+
entry.unsubscribe();
|
|
1340
|
+
this.subscriptionRegistry.delete(cacheKey);
|
|
1341
|
+
}
|
|
1250
1342
|
};
|
|
1251
1343
|
}
|
|
1252
1344
|
/**
|
|
@@ -1407,7 +1499,7 @@ function createPowerSyncAdapter(db, schema) {
|
|
|
1407
1499
|
}
|
|
1408
1500
|
|
|
1409
1501
|
// src/providers/DataLayerProvider.tsx
|
|
1410
|
-
import { useState, useEffect, useMemo, useCallback, useRef } from "react";
|
|
1502
|
+
import { useState, useEffect, useMemo, useCallback, useRef, useContext } from "react";
|
|
1411
1503
|
import { jsx } from "react/jsx-runtime";
|
|
1412
1504
|
var defaultSyncStatus = {
|
|
1413
1505
|
isConnected: false,
|
|
@@ -1454,6 +1546,12 @@ function DataLayerProvider({
|
|
|
1454
1546
|
powerSyncSyncStatus,
|
|
1455
1547
|
syncControl: externalSyncControl
|
|
1456
1548
|
}) {
|
|
1549
|
+
const isNested = useContext(DataLayerNestingContext);
|
|
1550
|
+
const hasWarnedNesting = useRef(false);
|
|
1551
|
+
if (isNested && !hasWarnedNesting.current && typeof __DEV__ !== "undefined" && __DEV__) {
|
|
1552
|
+
hasWarnedNesting.current = true;
|
|
1553
|
+
console.warn("[DataLayerProvider] Nested DataLayerProvider detected! This usually indicates a setup issue where DataLayerProvider is wrapped twice. Each DataLayerProvider creates its own registry, which can cause:\n - Queries using wrong adapter (e.g., Supabase instead of PowerSync)\n - Inconsistent cache state\n - Unexpected behavior with sync status\n\nCommon causes:\n - Using both DataLayerWrapper and OfflineDataProvider (OfflineDataProvider already includes DataLayerProvider)\n - Accidentally wrapping layout twice\n\nFix: Remove the outer DataLayerProvider wrapper.");
|
|
1554
|
+
}
|
|
1457
1555
|
const [registry] = useState(() => createAdapterRegistry(config));
|
|
1458
1556
|
const powerSyncInstanceRef = useRef(powerSyncInstance);
|
|
1459
1557
|
powerSyncInstanceRef.current = powerSyncInstance;
|
|
@@ -1699,7 +1797,7 @@ function DataLayerProvider({
|
|
|
1699
1797
|
const resolvedCore = coreContextValue ?? pendingCoreContextValue;
|
|
1700
1798
|
const resolvedStatus = statusContextValue ?? pendingStatusContextValue;
|
|
1701
1799
|
const resolvedContext = contextValue ?? pendingContextValue;
|
|
1702
|
-
return /* @__PURE__ */ jsx(DataLayerContext.Provider, { value: resolvedContext, children: /* @__PURE__ */ jsx(DataLayerCoreContext.Provider, { value: resolvedCore, children: /* @__PURE__ */ jsx(DataLayerStatusContext.Provider, { value: resolvedStatus, children }) }) });
|
|
1800
|
+
return /* @__PURE__ */ jsx(DataLayerNestingContext.Provider, { value: true, children: /* @__PURE__ */ jsx(DataLayerContext.Provider, { value: resolvedContext, children: /* @__PURE__ */ jsx(DataLayerCoreContext.Provider, { value: resolvedCore, children: /* @__PURE__ */ jsx(DataLayerStatusContext.Provider, { value: resolvedStatus, children }) }) }) });
|
|
1703
1801
|
}
|
|
1704
1802
|
|
|
1705
1803
|
// src/storage/use-supabase-upload.tsx
|
|
@@ -4630,9 +4728,9 @@ function _temp(err) {
|
|
|
4630
4728
|
|
|
4631
4729
|
// src/conflicts/useConflictState.ts
|
|
4632
4730
|
import { c as _c2 } from "react/compiler-runtime";
|
|
4633
|
-
import { useContext } from "react";
|
|
4731
|
+
import { useContext as useContext2 } from "react";
|
|
4634
4732
|
function useConflictState() {
|
|
4635
|
-
const context =
|
|
4733
|
+
const context = useContext2(ConflictContext);
|
|
4636
4734
|
if (!context) {
|
|
4637
4735
|
throw new Error("useConflictState must be used within a ConflictProvider. Wrap your app with <ConflictProvider> to enable conflict management.");
|
|
4638
4736
|
}
|
|
@@ -4640,7 +4738,7 @@ function useConflictState() {
|
|
|
4640
4738
|
}
|
|
4641
4739
|
function usePendingConflicts() {
|
|
4642
4740
|
const $ = _c2(2);
|
|
4643
|
-
const context =
|
|
4741
|
+
const context = useContext2(ConflictContext);
|
|
4644
4742
|
let t0;
|
|
4645
4743
|
if ($[0] !== context?.pendingConflicts) {
|
|
4646
4744
|
t0 = context?.pendingConflicts ?? [];
|
|
@@ -4652,7 +4750,7 @@ function usePendingConflicts() {
|
|
|
4652
4750
|
return t0;
|
|
4653
4751
|
}
|
|
4654
4752
|
function useHasConflicts() {
|
|
4655
|
-
const context =
|
|
4753
|
+
const context = useContext2(ConflictContext);
|
|
4656
4754
|
return context?.hasConflicts ?? false;
|
|
4657
4755
|
}
|
|
4658
4756
|
function useConflictForRecord(table, recordId) {
|
|
@@ -4968,4 +5066,4 @@ object-assign/index.js:
|
|
|
4968
5066
|
@license MIT
|
|
4969
5067
|
*)
|
|
4970
5068
|
*/
|
|
4971
|
-
//# sourceMappingURL=chunk-
|
|
5069
|
+
//# sourceMappingURL=chunk-N4KK5G5T.js.map
|