tinybase 8.5.0 → 9.0.0-beta.0

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.
Files changed (161) hide show
  1. package/@types/_internal/queries/with-schemas/index.d.ts +1 -2
  2. package/@types/_internal/ui/with-schemas/index.d.ts +8 -16
  3. package/@types/persisters/index.d.ts +32 -12
  4. package/@types/persisters/persister-durable-object-sql-storage/index.d.ts +9 -8
  5. package/@types/persisters/persister-durable-object-sql-storage/with-schemas/index.d.ts +10 -10
  6. package/@types/persisters/with-schemas/index.d.ts +56 -20
  7. package/@types/queries/index.d.ts +1 -7
  8. package/@types/queries/with-schemas/index.d.ts +5 -15
  9. package/@types/store/index.d.ts +1 -2
  10. package/@types/store/with-schemas/index.d.ts +19 -29
  11. package/@types/synchronizers/synchronizer-ws-client/index.d.ts +9 -3
  12. package/@types/synchronizers/synchronizer-ws-client/with-schemas/index.d.ts +10 -3
  13. package/@types/synchronizers/synchronizer-ws-server/index.d.ts +15 -2
  14. package/@types/synchronizers/synchronizer-ws-server/with-schemas/index.d.ts +17 -2
  15. package/@types/synchronizers/synchronizer-ws-server-durable-object/index.d.ts +51 -0
  16. package/@types/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.d.ts +51 -0
  17. package/@types/ui-react/with-schemas/index.d.ts +3 -6
  18. package/@types/ui-react-dom/index.d.ts +10 -10
  19. package/@types/ui-react-dom/with-schemas/index.d.ts +16 -22
  20. package/@types/ui-react-dom-charts/index.d.ts +7 -7
  21. package/@types/ui-react-dom-charts/with-schemas/index.d.ts +10 -11
  22. package/@types/ui-react-inspector/index.d.ts +1 -1
  23. package/@types/ui-react-inspector/with-schemas/index.d.ts +1 -1
  24. package/@types/ui-solid/with-schemas/index.d.ts +4 -8
  25. package/@types/ui-solid-dom/index.d.ts +10 -10
  26. package/@types/ui-solid-dom/with-schemas/index.d.ts +16 -22
  27. package/@types/ui-solid-inspector/index.d.ts +1 -1
  28. package/@types/ui-solid-inspector/with-schemas/index.d.ts +1 -1
  29. package/@types/ui-svelte-dom/index.d.ts +10 -10
  30. package/@types/ui-svelte-dom/with-schemas/index.d.ts +16 -22
  31. package/@types/ui-svelte-inspector/index.d.ts +1 -1
  32. package/@types/ui-svelte-inspector/with-schemas/index.d.ts +1 -1
  33. package/index.js +21 -19
  34. package/indexes/index.js +6 -8
  35. package/indexes/with-schemas/index.js +6 -8
  36. package/metrics/index.js +6 -8
  37. package/metrics/with-schemas/index.js +6 -8
  38. package/min/index.js +1 -1
  39. package/min/index.js.gz +0 -0
  40. package/min/omni/index.js +1 -1
  41. package/min/omni/index.js.gz +0 -0
  42. package/min/omni/with-schemas/index.js +1 -1
  43. package/min/omni/with-schemas/index.js.gz +0 -0
  44. package/min/persisters/index.js +1 -1
  45. package/min/persisters/index.js.gz +0 -0
  46. package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
  47. package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
  48. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
  49. package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
  50. package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
  51. package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
  52. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
  53. package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
  54. package/min/persisters/persister-electric-sql/index.js +1 -1
  55. package/min/persisters/persister-electric-sql/index.js.gz +0 -0
  56. package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
  57. package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
  58. package/min/persisters/persister-expo-sqlite/index.js +1 -1
  59. package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
  60. package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
  61. package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
  62. package/min/persisters/persister-libsql/index.js +1 -1
  63. package/min/persisters/persister-libsql/index.js.gz +0 -0
  64. package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
  65. package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
  66. package/min/persisters/persister-pglite/index.js +1 -1
  67. package/min/persisters/persister-pglite/index.js.gz +0 -0
  68. package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
  69. package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
  70. package/min/persisters/persister-postgres/index.js +1 -1
  71. package/min/persisters/persister-postgres/index.js.gz +0 -0
  72. package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
  73. package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
  74. package/min/persisters/persister-powersync/index.js +1 -1
  75. package/min/persisters/persister-powersync/index.js.gz +0 -0
  76. package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
  77. package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
  78. package/min/persisters/persister-react-native-sqlite/index.js +1 -1
  79. package/min/persisters/persister-react-native-sqlite/index.js.gz +0 -0
  80. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js +1 -1
  81. package/min/persisters/persister-react-native-sqlite/with-schemas/index.js.gz +0 -0
  82. package/min/persisters/persister-sqlite-bun/index.js +1 -1
  83. package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
  84. package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
  85. package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
  86. package/min/persisters/persister-sqlite-wasm/index.js +1 -1
  87. package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
  88. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
  89. package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
  90. package/min/persisters/persister-sqlite3/index.js +1 -1
  91. package/min/persisters/persister-sqlite3/index.js.gz +0 -0
  92. package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
  93. package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
  94. package/min/persisters/with-schemas/index.js +1 -1
  95. package/min/persisters/with-schemas/index.js.gz +0 -0
  96. package/min/queries/index.js +1 -1
  97. package/min/queries/index.js.gz +0 -0
  98. package/min/queries/with-schemas/index.js +1 -1
  99. package/min/queries/with-schemas/index.js.gz +0 -0
  100. package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
  101. package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
  102. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
  103. package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
  104. package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
  105. package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
  106. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
  107. package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
  108. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
  109. package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
  110. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
  111. package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
  112. package/min/with-schemas/index.js +1 -1
  113. package/min/with-schemas/index.js.gz +0 -0
  114. package/omni/index.js +311 -141
  115. package/omni/with-schemas/index.js +311 -141
  116. package/package.json +7 -7
  117. package/persisters/index.js +129 -37
  118. package/persisters/persister-cr-sqlite-wasm/index.js +129 -37
  119. package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +129 -37
  120. package/persisters/persister-durable-object-sql-storage/index.js +271 -110
  121. package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +271 -110
  122. package/persisters/persister-electric-sql/index.js +129 -37
  123. package/persisters/persister-electric-sql/with-schemas/index.js +129 -37
  124. package/persisters/persister-expo-sqlite/index.js +129 -37
  125. package/persisters/persister-expo-sqlite/with-schemas/index.js +129 -37
  126. package/persisters/persister-libsql/index.js +129 -37
  127. package/persisters/persister-libsql/with-schemas/index.js +129 -37
  128. package/persisters/persister-pglite/index.js +130 -37
  129. package/persisters/persister-pglite/with-schemas/index.js +130 -37
  130. package/persisters/persister-postgres/index.js +130 -37
  131. package/persisters/persister-postgres/with-schemas/index.js +130 -37
  132. package/persisters/persister-powersync/index.js +182 -117
  133. package/persisters/persister-powersync/with-schemas/index.js +182 -117
  134. package/persisters/persister-react-native-sqlite/index.js +129 -37
  135. package/persisters/persister-react-native-sqlite/with-schemas/index.js +129 -37
  136. package/persisters/persister-sqlite-bun/index.js +129 -37
  137. package/persisters/persister-sqlite-bun/with-schemas/index.js +129 -37
  138. package/persisters/persister-sqlite-wasm/index.js +129 -37
  139. package/persisters/persister-sqlite-wasm/with-schemas/index.js +129 -37
  140. package/persisters/persister-sqlite3/index.js +129 -37
  141. package/persisters/persister-sqlite3/with-schemas/index.js +129 -37
  142. package/persisters/with-schemas/index.js +129 -37
  143. package/queries/index.js +21 -19
  144. package/queries/with-schemas/index.js +21 -19
  145. package/readme.md +14 -14
  146. package/relationships/index.js +6 -8
  147. package/relationships/with-schemas/index.js +6 -8
  148. package/releases.md +57 -57
  149. package/synchronizers/synchronizer-ws-client/index.js +116 -42
  150. package/synchronizers/synchronizer-ws-client/with-schemas/index.js +116 -42
  151. package/synchronizers/synchronizer-ws-server/index.js +109 -28
  152. package/synchronizers/synchronizer-ws-server/with-schemas/index.js +109 -28
  153. package/synchronizers/synchronizer-ws-server-durable-object/index.js +122 -38
  154. package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +122 -38
  155. package/ui-svelte/index.js +1 -1
  156. package/ui-svelte/with-schemas/index.js +1 -1
  157. package/ui-svelte-dom/index.js +2 -2
  158. package/ui-svelte-dom/with-schemas/index.js +2 -2
  159. package/ui-svelte-inspector/index.js +2 -2
  160. package/ui-svelte-inspector/with-schemas/index.js +2 -2
  161. package/with-schemas/index.js +21 -19
@@ -79,6 +79,7 @@ const startInterval = (callback, sec, immediate) => {
79
79
  const stopInterval = clearInterval;
80
80
  const startTimeout = (callback, sec = 0) =>
81
81
  setTimeout(callback, sec * THOUSAND);
82
+ const stopTimeout = clearTimeout;
82
83
  const mathMax = math.max;
83
84
  const mathMin = math.min;
84
85
  const mathFloor = math.floor;
@@ -378,14 +379,12 @@ const getDefinableFunctions = (
378
379
  const newRowValue = hasRow(tableId, rowId)
379
380
  ? validateRowValue(getRowValue(getCell, rowId))
380
381
  : void 0;
381
- if (
382
- !(
383
- oldRowValue === newRowValue ||
384
- (isArray(oldRowValue) &&
385
- isArray(newRowValue) &&
386
- arrayIsEqual(oldRowValue, newRowValue))
387
- )
388
- ) {
382
+ if (!(
383
+ oldRowValue === newRowValue ||
384
+ (isArray(oldRowValue) &&
385
+ isArray(newRowValue) &&
386
+ arrayIsEqual(oldRowValue, newRowValue))
387
+ )) {
389
388
  mapSet(changedRowValues, rowId, [oldRowValue, newRowValue]);
390
389
  }
391
390
  if (!isUndefined(getSortKey)) {
@@ -4123,6 +4122,8 @@ const DEFAULT_TABULAR_VALUES_CONFIG = {
4123
4122
  save: 0,
4124
4123
  [TABLE_NAME]: TINYBASE + '_values',
4125
4124
  };
4125
+ const getValuesIn = (config) => (isArray(config) ? config : void 0);
4126
+ const hasValues = (config) => isTrue(config) || isArray(config);
4126
4127
  const getDefaultedConfig = (configOrStoreTableName) =>
4127
4128
  objMerge(
4128
4129
  DEFAULT_CONFIG,
@@ -4173,11 +4174,15 @@ const getConfigStructures = (configOrStoreTableName) => {
4173
4174
  ];
4174
4175
  }
4175
4176
  const {tables: {load = {}, save = {}} = {}, values = {}} = config;
4176
- const valuesConfig = slice(
4177
- objValues(objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values)),
4178
- 0,
4179
- objSize(DEFAULT_TABULAR_VALUES_CONFIG),
4180
- );
4177
+ const valuesConfigObj = objMerge(DEFAULT_TABULAR_VALUES_CONFIG, values);
4178
+ const {load: valuesLoad, save: valuesSave} = valuesConfigObj;
4179
+ const valuesConfig = [
4180
+ hasValues(valuesLoad),
4181
+ hasValues(valuesSave),
4182
+ valuesConfigObj[TABLE_NAME],
4183
+ getValuesIn(valuesLoad),
4184
+ getValuesIn(valuesSave),
4185
+ ];
4181
4186
  const valuesTable = valuesConfig[2];
4182
4187
  const managedTableNames = setNew(valuesTable);
4183
4188
  const excludedTableNames = setNew(valuesTable);
@@ -4239,8 +4244,18 @@ const getCommandFunctions = (
4239
4244
  ({tn, cn}) => setAdd(mapEnsure(schemaMap, tn, setNew), cn),
4240
4245
  );
4241
4246
  };
4242
- const loadTable = async (tableName, rowIdColumnName, condition) =>
4243
- canSelect(tableName, rowIdColumnName)
4247
+ const loadTable = async (
4248
+ tableName,
4249
+ rowIdColumnName,
4250
+ condition,
4251
+ contentSubIds,
4252
+ ) => {
4253
+ const contentSubIdSet = isUndefined(contentSubIds)
4254
+ ? void 0
4255
+ : setNew(contentSubIds);
4256
+ const includeContentSubId = (contentSubId) =>
4257
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
4258
+ return canSelect(tableName, rowIdColumnName)
4244
4259
  ? objNew(
4245
4260
  arrayFilter(
4246
4261
  arrayMap(
@@ -4249,17 +4264,35 @@ const getCommandFunctions = (
4249
4264
  escapeId(tableName) +
4250
4265
  getWhereCondition(tableName, condition),
4251
4266
  ),
4252
- (row) => [
4253
- row[rowIdColumnName],
4254
- decode
4267
+ (row) => {
4268
+ const rowId = row[rowIdColumnName];
4269
+ const rowContent = decode
4255
4270
  ? objMap(objDel(row, rowIdColumnName), decode)
4256
- : objDel(row, rowIdColumnName),
4257
- ],
4271
+ : objDel(row, rowIdColumnName);
4272
+ return [
4273
+ rowId,
4274
+ isUndefined(contentSubIdSet)
4275
+ ? rowContent
4276
+ : objNew(
4277
+ arrayFilter(
4278
+ objToArray(
4279
+ rowContent,
4280
+ (cellOrValue, contentSubId) => [
4281
+ contentSubId,
4282
+ cellOrValue,
4283
+ ],
4284
+ ),
4285
+ ([contentSubId]) => includeContentSubId(contentSubId),
4286
+ ),
4287
+ ),
4288
+ ];
4289
+ },
4258
4290
  ),
4259
4291
  (entry) => !isUndefined(entry[0]) && !objIsEmpty(entry[1]),
4260
4292
  ),
4261
4293
  )
4262
4294
  : {};
4295
+ };
4263
4296
  const saveTable = async (
4264
4297
  tableName,
4265
4298
  rowIdColumnName,
@@ -4268,15 +4301,23 @@ const getCommandFunctions = (
4268
4301
  deleteEmptyTable,
4269
4302
  partial = false,
4270
4303
  condition = TRUE,
4304
+ contentSubIds,
4271
4305
  ) => {
4306
+ const contentSubIdSet = isUndefined(contentSubIds)
4307
+ ? void 0
4308
+ : setNew(contentSubIds);
4309
+ const includeContentSubId = (contentSubId) =>
4310
+ isUndefined(contentSubIdSet) || collHas(contentSubIdSet, contentSubId);
4272
4311
  const settingColumnNameSet = setNew();
4273
4312
  objMap(content ?? {}, (contentRow) =>
4274
- arrayMap(objIds(contentRow ?? {}), (cellOrValueId) =>
4275
- setAdd(settingColumnNameSet, cellOrValueId),
4313
+ arrayMap(
4314
+ arrayFilter(objIds(contentRow ?? {}), includeContentSubId),
4315
+ (cellOrValueId) => setAdd(settingColumnNameSet, cellOrValueId),
4276
4316
  ),
4277
4317
  );
4278
4318
  const settingColumnNames = collValues(settingColumnNameSet);
4279
4319
  if (
4320
+ isUndefined(contentSubIdSet) &&
4280
4321
  !partial &&
4281
4322
  deleteEmptyTable &&
4282
4323
  condition == TRUE &&
@@ -4288,7 +4329,13 @@ const getCommandFunctions = (
4288
4329
  return;
4289
4330
  }
4290
4331
  const currentColumnNames = mapGet(schemaMap, tableName);
4291
- const unaccountedColumnNames = setNew(collValues(currentColumnNames));
4332
+ const unaccountedColumnNames = setNew(
4333
+ arrayFilter(
4334
+ collValues(currentColumnNames),
4335
+ (columnName) =>
4336
+ columnName == rowIdColumnName || includeContentSubId(columnName),
4337
+ ),
4338
+ );
4292
4339
  if (!arrayIsEmpty(settingColumnNames)) {
4293
4340
  if (!collHas(schemaMap, tableName)) {
4294
4341
  await databaseExecuteCommand(
@@ -4354,11 +4401,13 @@ const getCommandFunctions = (
4354
4401
  ]);
4355
4402
  if (partial) {
4356
4403
  if (isUndefined(content)) {
4357
- await databaseExecuteCommand(
4358
- DELETE_FROM +
4359
- escapeId(tableName) +
4360
- getWhereCondition(tableName, condition),
4361
- );
4404
+ if (isUndefined(contentSubIdSet)) {
4405
+ await databaseExecuteCommand(
4406
+ DELETE_FROM +
4407
+ escapeId(tableName) +
4408
+ getWhereCondition(tableName, condition),
4409
+ );
4410
+ }
4362
4411
  } else {
4363
4412
  await promiseAll(
4364
4413
  objToArray(content, async (row, rowId) => {
@@ -4371,18 +4420,24 @@ const getCommandFunctions = (
4371
4420
  [rowId],
4372
4421
  );
4373
4422
  } else if (!arrayIsEmpty(settingColumnNames)) {
4374
- await upsert(
4375
- databaseExecuteCommand,
4376
- tableName,
4377
- rowIdColumnName,
4423
+ const changingColumnNames = arrayFilter(
4378
4424
  objIds(row),
4379
- {
4380
- [rowId]: encode
4381
- ? arrayMap(objValues(row), encode)
4382
- : objValues(row),
4383
- },
4384
- currentColumnNames,
4425
+ includeContentSubId,
4385
4426
  );
4427
+ if (!arrayIsEmpty(changingColumnNames)) {
4428
+ await upsert(
4429
+ databaseExecuteCommand,
4430
+ tableName,
4431
+ rowIdColumnName,
4432
+ changingColumnNames,
4433
+ {
4434
+ [rowId]: arrayMap(changingColumnNames, (cellId) =>
4435
+ encode ? encode(row[cellId]) : row[cellId],
4436
+ ),
4437
+ },
4438
+ currentColumnNames,
4439
+ );
4440
+ }
4386
4441
  }
4387
4442
  }),
4388
4443
  );
@@ -4391,7 +4446,9 @@ const getCommandFunctions = (
4391
4446
  if (!arrayIsEmpty(settingColumnNames)) {
4392
4447
  const changingColumnNames = arrayFilter(
4393
4448
  collValues(mapGet(schemaMap, tableName)),
4394
- (changingColumnName) => changingColumnName != rowIdColumnName,
4449
+ (changingColumnName) =>
4450
+ changingColumnName != rowIdColumnName &&
4451
+ includeContentSubId(changingColumnName),
4395
4452
  );
4396
4453
  const rows = {};
4397
4454
  const deleteRowIds = [];
@@ -4407,6 +4464,7 @@ const getCommandFunctions = (
4407
4464
  rowIdColumnName,
4408
4465
  changingColumnNames,
4409
4466
  rows,
4467
+ currentColumnNames,
4410
4468
  );
4411
4469
  await databaseExecuteCommand(
4412
4470
  DELETE_FROM +
@@ -4415,7 +4473,10 @@ const getCommandFunctions = (
4415
4473
  `AND${escapeId(rowIdColumnName)}NOT IN(${getPlaceholders(deleteRowIds)})`,
4416
4474
  deleteRowIds,
4417
4475
  );
4418
- } else if (collHas(schemaMap, tableName)) {
4476
+ } else if (
4477
+ isUndefined(contentSubIdSet) &&
4478
+ collHas(schemaMap, tableName)
4479
+ ) {
4419
4480
  await databaseExecuteCommand(
4420
4481
  DELETE_FROM +
4421
4482
  escapeId(tableName) +
@@ -4554,7 +4615,13 @@ const createTabularPersister = (
4554
4615
  [
4555
4616
  tablesLoadConfig,
4556
4617
  tablesSaveConfig,
4557
- [valuesLoad, valuesSave, valuesTableName],
4618
+ [
4619
+ valuesLoad,
4620
+ valuesSave,
4621
+ valuesTableName,
4622
+ valuesLoadValueIds,
4623
+ valuesSaveValueIds,
4624
+ ],
4558
4625
  ],
4559
4626
  managedTableNames,
4560
4627
  querySchema,
@@ -4604,15 +4671,33 @@ const createTabularPersister = (
4604
4671
  },
4605
4672
  ),
4606
4673
  );
4674
+ const getValuesSubset = (values, valueIds, partial) =>
4675
+ objNew(
4676
+ partial == true
4677
+ ? arrayFilter(
4678
+ objToArray(values, (value, valueId) => [valueId, value]),
4679
+ ([valueId]) => arrayHas(valueIds, valueId),
4680
+ )
4681
+ : arrayFilter(
4682
+ arrayMap(valueIds, (valueId) => [valueId, values[valueId]]),
4683
+ ([, value]) => !isUndefined(value),
4684
+ ),
4685
+ );
4607
4686
  const saveValues = async (values, partial) =>
4608
4687
  valuesSave
4609
4688
  ? await saveTable(
4610
4689
  valuesTableName,
4611
4690
  DEFAULT_ROW_ID_COLUMN_NAME,
4612
- {[SINGLE_ROW_ID]: values},
4691
+ {
4692
+ [SINGLE_ROW_ID]: isUndefined(valuesSaveValueIds)
4693
+ ? values
4694
+ : getValuesSubset(values, valuesSaveValueIds, partial),
4695
+ },
4613
4696
  true,
4614
4697
  true,
4615
4698
  partial,
4699
+ void 0,
4700
+ valuesSaveValueIds,
4616
4701
  )
4617
4702
  : null;
4618
4703
  const loadTables = async () =>
@@ -4632,9 +4717,14 @@ const createTabularPersister = (
4632
4717
  );
4633
4718
  const loadValues = async () =>
4634
4719
  valuesLoad
4635
- ? (await loadTable(valuesTableName, DEFAULT_ROW_ID_COLUMN_NAME))[
4636
- SINGLE_ROW_ID
4637
- ]
4720
+ ? (
4721
+ await loadTable(
4722
+ valuesTableName,
4723
+ DEFAULT_ROW_ID_COLUMN_NAME,
4724
+ void 0,
4725
+ valuesLoadValueIds,
4726
+ )
4727
+ )[SINGLE_ROW_ID]
4638
4728
  : {};
4639
4729
  const getPersisted = () =>
4640
4730
  transaction(async () => {
@@ -5859,83 +5949,57 @@ const createPowerSyncPersister = (
5859
5949
  // StoreOnly,
5860
5950
  powerSync,
5861
5951
  'getPowerSync',
5862
- viewUpsert,
5952
+ powerSyncUpdateThenInsert,
5863
5953
  );
5864
5954
  };
5865
- const viewUpsert = async (
5955
+ const powerSyncUpdateThenInsert = async (
5866
5956
  executeCommand,
5867
5957
  tableName,
5868
5958
  rowIdColumnName,
5869
5959
  changingColumnNames,
5870
5960
  rows,
5871
- currentColumnNames,
5872
5961
  ) => {
5873
- const offset = [1];
5874
- const changingColumnNamesSet = setNew(changingColumnNames);
5875
- const unchangingColumnNames = currentColumnNames
5876
- ? arrayFilter(
5877
- [...currentColumnNames],
5878
- (currentColumnName) =>
5879
- currentColumnName != rowIdColumnName &&
5880
- !collHas(changingColumnNamesSet, currentColumnName),
5881
- )
5882
- : [];
5883
- if (!arrayIsEmpty(unchangingColumnNames)) {
5884
- const ids = objIds(rows);
5885
- const unchangingData = objNew(
5886
- arrayMap(
5962
+ const assignments = arrayJoin(
5963
+ arrayMap(
5964
+ changingColumnNames,
5965
+ (columnName, index) => escapeId(columnName) + '=$' + (index + 1),
5966
+ ),
5967
+ COMMA,
5968
+ );
5969
+ for (const [id, row] of objToArray(rows, (row2, id2) => [id2, row2])) {
5970
+ const rowParams = arrayMap(row, (value) => value ?? null);
5971
+ if (
5972
+ arrayIsEmpty(
5887
5973
  await executeCommand(
5888
- SELECT +
5889
- escapeColumnNames(rowIdColumnName, ...unchangingColumnNames) +
5890
- FROM +
5974
+ UPDATE +
5891
5975
  escapeId(tableName) +
5976
+ ' SET' +
5977
+ assignments +
5978
+ ' ' +
5892
5979
  WHERE +
5893
5980
  escapeId(rowIdColumnName) +
5894
- 'IN(' +
5895
- getPlaceholders(ids) +
5896
- ')',
5897
- ids,
5981
+ '=$' +
5982
+ (row.length + 1) +
5983
+ ' RETURNING' +
5984
+ escapeId(rowIdColumnName),
5985
+ [...rowParams, id],
5898
5986
  ),
5899
- (unchangingRow) => [unchangingRow[rowIdColumnName], unchangingRow],
5900
- ),
5901
- );
5902
- arrayForEach(ids, (id) =>
5903
- arrayPush(
5904
- rows[id],
5905
- ...arrayMap(
5906
- unchangingColumnNames,
5907
- (unchangingColumnName) =>
5908
- unchangingData?.[id]?.[unchangingColumnName] ?? null,
5909
- ),
5910
- ),
5911
- );
5987
+ )
5988
+ ) {
5989
+ const offset = [1];
5990
+ await executeCommand(
5991
+ INSERT +
5992
+ ' INTO' +
5993
+ escapeId(tableName) +
5994
+ '(' +
5995
+ escapeColumnNames(rowIdColumnName, ...changingColumnNames) +
5996
+ ')VALUES(' +
5997
+ getPlaceholders([id, ...row], offset) +
5998
+ ')',
5999
+ [id, ...rowParams],
6000
+ );
6001
+ }
5912
6002
  }
5913
- await executeCommand(
5914
- INSERT +
5915
- ' ' +
5916
- OR_REPLACE +
5917
- 'INTO' +
5918
- escapeId(tableName) +
5919
- '(' +
5920
- escapeColumnNames(
5921
- rowIdColumnName,
5922
- ...changingColumnNames,
5923
- ...unchangingColumnNames,
5924
- ) +
5925
- ')VALUES' +
5926
- arrayJoin(
5927
- objToArray(
5928
- rows,
5929
- (row) =>
5930
- '($' + offset[0]++ + ',' + getPlaceholders(row, offset) + ')',
5931
- ),
5932
- COMMA,
5933
- ),
5934
- objToArray(rows, (row, id) => [
5935
- id,
5936
- ...arrayMap(row, (value) => value ?? null),
5937
- ]).flat(),
5938
- );
5939
6003
  };
5940
6004
 
5941
6005
  const STORAGE = 'storage';
@@ -6316,9 +6380,9 @@ const PARAMS_TABLE = '_';
6316
6380
  const PARAM_LISTENER_PREFIX = 'p';
6317
6381
  const createQueries = getCreateFunction((store) => {
6318
6382
  const createStore = store._[0];
6319
- const preStore = createStore();
6320
6383
  const paramStore = createStore();
6321
6384
  const resultStore = createStore();
6385
+ const preStores = mapNew();
6322
6386
  const resultStores = mapNew();
6323
6387
  const redefiningQueryIds = setNew();
6324
6388
  const routedResultListeners = mapNew();
@@ -6361,12 +6425,13 @@ const createQueries = getCreateFunction((store) => {
6361
6425
  );
6362
6426
  const getResultStore = (queryId) =>
6363
6427
  mapEnsure(resultStores, queryId, createStore);
6364
- const addPreStoreListener = (preStore2, queryId, ...listenerIds) =>
6428
+ const getPreStore = (queryId) => mapEnsure(preStores, queryId, createStore);
6429
+ const addPreStoreListener = (preStore, queryId, ...listenerIds) =>
6365
6430
  arrayForEach(listenerIds, (listenerId) =>
6366
6431
  setAdd(
6367
6432
  mapEnsure(
6368
6433
  mapEnsure(preStoreListenerIds, queryId, mapNew),
6369
- preStore2,
6434
+ preStore,
6370
6435
  setNew,
6371
6436
  ),
6372
6437
  listenerId,
@@ -6376,16 +6441,17 @@ const createQueries = getCreateFunction((store) => {
6376
6441
  ifNotUndefined(
6377
6442
  mapGet(preStoreListenerIds, queryId),
6378
6443
  (queryPreStoreListenerIds) => {
6379
- mapForEach(queryPreStoreListenerIds, (preStore2, listenerIds) =>
6444
+ mapForEach(queryPreStoreListenerIds, (preStore, listenerIds) =>
6380
6445
  collForEach(listenerIds, (listenerId) =>
6381
- preStore2.delListener(listenerId),
6446
+ preStore.delListener(listenerId),
6382
6447
  ),
6383
6448
  );
6384
6449
  collClear(queryPreStoreListenerIds);
6385
6450
  },
6386
6451
  );
6387
- arrayForEach([getResultStore(queryId), preStore], (store2) =>
6388
- store2.delTable(queryId),
6452
+ arrayForEach(
6453
+ [getResultStore(queryId), mapGet(preStores, queryId)],
6454
+ (store2) => store2?.delTable(queryId),
6389
6455
  );
6390
6456
  };
6391
6457
  const addSourceStoreListeners = (
@@ -6613,10 +6679,12 @@ const createQueries = getCreateFunction((store) => {
6613
6679
  ),
6614
6680
  );
6615
6681
  const groups = mapNew(groupEntries);
6616
- let selectJoinWhereStore = preStore;
6617
- if (collIsEmpty(groups) && arrayIsEmpty(havings)) {
6618
- selectJoinWhereStore = resultStore2;
6619
- } else {
6682
+ const hasGroupsOrHavings =
6683
+ !collIsEmpty(groups) || !arrayIsEmpty(havings);
6684
+ const selectJoinWhereStore = hasGroupsOrHavings
6685
+ ? getPreStore(queryId)
6686
+ : resultStore2;
6687
+ if (hasGroupsOrHavings) {
6620
6688
  synchronizeTransactions(queryId, selectJoinWhereStore, resultStore2);
6621
6689
  const groupedSelectedCellIds = mapNew();
6622
6690
  mapForEach(groups, (groupedCellId, [selectedCellId, aggregators]) =>
@@ -7529,20 +7597,87 @@ const createLocalSynchronizer = (store, onSend, onReceive, onIgnoredError) => {
7529
7597
  };
7530
7598
 
7531
7599
  const MESSAGE_SEPARATOR = '\n';
7600
+ const FRAGMENT = /^(.+)\n(\d+)\n(\d+)\n([\s\S]*)$/;
7532
7601
  const ifPayloadValid = (payload, then) => {
7533
7602
  const splitAt = payload.indexOf(MESSAGE_SEPARATOR);
7534
7603
  if (splitAt !== -1) {
7535
7604
  then(slice(payload, 0, splitAt), slice(payload, splitAt + 1));
7536
7605
  }
7537
7606
  };
7538
- const receivePayload = (payload, receive) =>
7539
- ifPayloadValid(payload, (fromClientId, remainder) =>
7540
- receive(fromClientId, ...jsonParseWithUndefined(remainder)),
7541
- );
7607
+ const receivePayloadRemainder = (fromClientId, remainder, receive) =>
7608
+ receive(fromClientId, ...jsonParseWithUndefined(remainder));
7609
+ const createPayloadReceiver = (receive, fragmentTimeoutSeconds = 1) => {
7610
+ const buffer = mapNew();
7611
+ const setPendingTimeout = (bufferKey) =>
7612
+ startTimeout(() => collDel(buffer, bufferKey), fragmentTimeoutSeconds);
7613
+ const delPending = (bufferKey, pending) => {
7614
+ stopTimeout(pending[3]);
7615
+ collDel(buffer, bufferKey);
7616
+ };
7617
+ return (payload) =>
7618
+ ifPayloadValid(payload, (fromClientId, remainder) => {
7619
+ const [, messageId, indexStr, totalStr, fragment] =
7620
+ strMatch(remainder, FRAGMENT) ?? [];
7621
+ if (messageId) {
7622
+ const index = parseInt(indexStr);
7623
+ const total = parseInt(totalStr);
7624
+ if (total > 0 && index >= 0 && index < total) {
7625
+ const bufferKey = fromClientId + MESSAGE_SEPARATOR + messageId;
7626
+ const pending = mapEnsure(buffer, bufferKey, () => [
7627
+ [],
7628
+ total,
7629
+ total,
7630
+ setPendingTimeout(bufferKey),
7631
+ ]);
7632
+ const [fragments] = pending;
7633
+ if (total == pending[2] && isUndefined(fragments[index])) {
7634
+ stopTimeout(pending[3]);
7635
+ pending[3] = setPendingTimeout(bufferKey);
7636
+ fragments[index] = fragment;
7637
+ pending[1]--;
7638
+ }
7639
+ if (pending[1] == 0) {
7640
+ delPending(bufferKey, pending);
7641
+ receivePayloadRemainder(
7642
+ fromClientId,
7643
+ arrayJoin(fragments),
7644
+ receive,
7645
+ );
7646
+ }
7647
+ }
7648
+ } else {
7649
+ receivePayloadRemainder(fromClientId, remainder, receive);
7650
+ }
7651
+ });
7652
+ };
7542
7653
  const createPayload = (toClientId, ...args) =>
7543
- createRawPayload(toClientId ?? EMPTY_STRING, jsonStringWithUndefined(args));
7654
+ createRawPayload(toClientId, jsonStringWithUndefined(args));
7544
7655
  const createRawPayload = (clientId, remainder) =>
7545
7656
  clientId + MESSAGE_SEPARATOR + remainder;
7657
+ const createPayloads = (toClientId, requestId, message, body, fragmentSize) => {
7658
+ const clientId = toClientId ?? EMPTY_STRING;
7659
+ const remainder = jsonStringWithUndefined([requestId, message, body]);
7660
+ const maxFragmentSize = mathFloor(fragmentSize ?? 0);
7661
+ if (
7662
+ isUndefined(fragmentSize) ||
7663
+ maxFragmentSize < 1 ||
7664
+ size(remainder) <= maxFragmentSize
7665
+ ) {
7666
+ return [createRawPayload(clientId, remainder)];
7667
+ }
7668
+ const fragments = strMatch(
7669
+ remainder,
7670
+ new RegExp(`.{1,${maxFragmentSize}}`, 'g'),
7671
+ );
7672
+ const total = size(fragments ?? []);
7673
+ const messageId = getUniqueId();
7674
+ return arrayMap(fragments ?? [], (fragment, index) =>
7675
+ createRawPayload(
7676
+ clientId,
7677
+ arrayJoin([messageId, index, total, fragment], MESSAGE_SEPARATOR),
7678
+ ),
7679
+ );
7680
+ };
7546
7681
 
7547
7682
  const createWsSynchronizer = async (
7548
7683
  store,
@@ -7551,17 +7686,23 @@ const createWsSynchronizer = async (
7551
7686
  onSend,
7552
7687
  onReceive,
7553
7688
  onIgnoredError,
7689
+ fragmentSize,
7554
7690
  ) => {
7555
7691
  const addEventListener = (event, handler) => {
7556
7692
  webSocket.addEventListener(event, handler);
7557
7693
  return () => webSocket.removeEventListener(event, handler);
7558
7694
  };
7559
- const registerReceive = (receive) =>
7560
- addEventListener(MESSAGE, ({data}) =>
7561
- receivePayload(data.toString(UTF8), receive),
7695
+ const registerReceive = (receive) => {
7696
+ const receivePayload = createPayloadReceiver(
7697
+ receive,
7698
+ requestTimeoutSeconds,
7562
7699
  );
7700
+ addEventListener(MESSAGE, ({data}) => receivePayload(data.toString(UTF8)));
7701
+ };
7563
7702
  const send = (toClientId, ...args) =>
7564
- webSocket.send(createPayload(toClientId, ...args));
7703
+ arrayForEach(createPayloads(toClientId, ...args, fragmentSize), (payload) =>
7704
+ webSocket.send(payload),
7705
+ );
7565
7706
  const destroy = () => {
7566
7707
  webSocket.close();
7567
7708
  };
@@ -7616,18 +7757,27 @@ class WsServerDurableObject extends DurableObject {
7616
7757
  await ifNotUndefined(
7617
7758
  await this.createPersister(),
7618
7759
  async (persister) => {
7760
+ const requestTimeoutSeconds = this.getRequestTimeoutSeconds();
7619
7761
  const synchronizer = createCustomSynchronizer(
7620
7762
  persister.getStore(),
7621
7763
  (toClientId, requestId, message, body) =>
7622
- this.#handleMessage(
7623
- SERVER_CLIENT_ID$1,
7624
- createPayload(toClientId, requestId, message, body),
7764
+ arrayForEach(
7765
+ createPayloads(
7766
+ toClientId,
7767
+ requestId,
7768
+ message,
7769
+ body,
7770
+ this.getFragmentSize(),
7771
+ ),
7772
+ (payload) => this.#handleMessage(SERVER_CLIENT_ID$1, payload),
7625
7773
  ),
7626
7774
  (receive) =>
7627
- (this.#serverClientSend = (payload) =>
7628
- receivePayload(payload, receive)),
7775
+ (this.#serverClientSend = createPayloadReceiver(
7776
+ receive,
7777
+ requestTimeoutSeconds,
7778
+ )),
7629
7779
  noop,
7630
- 1,
7780
+ requestTimeoutSeconds,
7631
7781
  );
7632
7782
  await persister.load();
7633
7783
  await persister.startAutoSave();
@@ -7702,6 +7852,12 @@ class WsServerDurableObject extends DurableObject {
7702
7852
  (client) => this.ctx.getTags(client)[0],
7703
7853
  );
7704
7854
  }
7855
+ getFragmentSize() {
7856
+ return void 0;
7857
+ }
7858
+ getRequestTimeoutSeconds() {
7859
+ return 1;
7860
+ }
7705
7861
  onPathId(_pathId, _addedOrRemoved) {}
7706
7862
  onClientId(_pathId, _clientId, _addedOrRemoved) {}
7707
7863
  onMessage(_fromClientId, _toClientId, _remainder) {}
@@ -7762,6 +7918,8 @@ const createWsServer = (
7762
7918
  webSocketServer,
7763
7919
  createPersisterForPath,
7764
7920
  onIgnoredError,
7921
+ requestTimeoutSeconds = 1,
7922
+ fragmentSize,
7765
7923
  ) => {
7766
7924
  const pathIdListeners = mapNew();
7767
7925
  const clientIdListeners = mapNew();
@@ -7786,12 +7944,24 @@ const createWsServer = (
7786
7944
  serverClient[2 /* Synchronizer */] = createCustomSynchronizer(
7787
7945
  serverClient[1 /* Persister */].getStore(),
7788
7946
  (toClientId, requestId, message, body) =>
7789
- messageHandler(createPayload(toClientId, requestId, message, body)),
7790
- (receive) =>
7791
- (serverClient[3 /* Send */] = (payload) =>
7792
- receivePayload(payload, receive)),
7947
+ arrayForEach(
7948
+ createPayloads(
7949
+ toClientId,
7950
+ requestId,
7951
+ message,
7952
+ body,
7953
+ fragmentSize,
7954
+ ),
7955
+ messageHandler,
7956
+ ),
7957
+ (receive) => {
7958
+ serverClient[3 /* Send */] = createPayloadReceiver(
7959
+ receive,
7960
+ requestTimeoutSeconds,
7961
+ );
7962
+ },
7793
7963
  noop,
7794
- 1,
7964
+ requestTimeoutSeconds,
7795
7965
  void 0,
7796
7966
  void 0,
7797
7967
  onIgnoredError,
@@ -7803,14 +7973,14 @@ const createWsServer = (
7803
7973
  },
7804
7974
  );
7805
7975
  const startServerClient = async (serverClient) => {
7806
- serverClient[0 /* State */] = 2 /* Starting */;
7976
+ serverClient[0 /* State */] = 2; /* Starting */
7807
7977
  await serverClient[1 /* Persister */].schedule(
7808
7978
  serverClient[1 /* Persister */].startAutoLoad,
7809
7979
  serverClient[1 /* Persister */].startAutoSave,
7810
7980
  serverClient[2 /* Synchronizer */].startSync,
7811
7981
  );
7812
7982
  serverClient[5 /* Then */](serverClient[1 /* Persister */].getStore());
7813
- serverClient[0 /* State */] = 0 /* Ready */;
7983
+ serverClient[0 /* State */] = 0; /* Ready */
7814
7984
  };
7815
7985
  const stopServerClient = async (serverClient) => {
7816
7986
  await serverClient[1 /* Persister */]?.destroy();