@syncular/server 0.21.1 → 0.23.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 (66) hide show
  1. package/README.md +20 -6
  2. package/dist/admin.d.ts +3 -1
  3. package/dist/admin.js +7 -1
  4. package/dist/blob-handlers.js +1 -1
  5. package/dist/context.d.ts +8 -1
  6. package/dist/d1-storage.d.ts +11 -3
  7. package/dist/d1-storage.js +84 -2
  8. package/dist/errors.js +10 -0
  9. package/dist/handler.js +50 -4
  10. package/dist/operations.js +3 -3
  11. package/dist/pg-executor.d.ts +11 -1
  12. package/dist/postgres-storage.d.ts +20 -5
  13. package/dist/postgres-storage.js +345 -9
  14. package/dist/pull.js +9 -5
  15. package/dist/push.js +18 -0
  16. package/dist/readiness.d.ts +9 -2
  17. package/dist/readiness.js +27 -2
  18. package/dist/realtime.d.ts +40 -1
  19. package/dist/realtime.js +116 -19
  20. package/dist/relational-rows.d.ts +20 -0
  21. package/dist/relational-rows.js +29 -0
  22. package/dist/s3-segment-store.d.ts +20 -8
  23. package/dist/s3-segment-store.js +216 -68
  24. package/dist/schema.js +11 -0
  25. package/dist/segment-download.d.ts +1 -1
  26. package/dist/segment-download.js +50 -17
  27. package/dist/segment-store.d.ts +86 -0
  28. package/dist/segment-store.js +156 -17
  29. package/dist/signed-url.d.ts +7 -1
  30. package/dist/signed-url.js +10 -1
  31. package/dist/sqlite-dialect.d.ts +7 -1
  32. package/dist/sqlite-dialect.js +23 -0
  33. package/dist/sqlite-segment-store.js +153 -42
  34. package/dist/sqlite-storage.d.ts +11 -3
  35. package/dist/sqlite-storage.js +346 -34
  36. package/dist/storage-errors.d.ts +1 -1
  37. package/dist/storage-errors.js +4 -0
  38. package/dist/storage.d.ts +152 -2
  39. package/dist/storage.js +40 -1
  40. package/dist/validate.d.ts +20 -1
  41. package/package.json +2 -2
  42. package/src/admin.ts +13 -1
  43. package/src/blob-handlers.ts +1 -1
  44. package/src/context.ts +8 -0
  45. package/src/d1-storage.ts +143 -1
  46. package/src/errors.ts +10 -0
  47. package/src/handler.ts +62 -4
  48. package/src/operations.ts +17 -13
  49. package/src/pg-executor.ts +11 -1
  50. package/src/postgres-storage.ts +520 -5
  51. package/src/pull.ts +9 -1
  52. package/src/push.ts +18 -0
  53. package/src/readiness.ts +39 -4
  54. package/src/realtime.ts +117 -18
  55. package/src/relational-rows.ts +36 -0
  56. package/src/s3-segment-store.ts +275 -84
  57. package/src/schema.ts +15 -0
  58. package/src/segment-download.ts +79 -28
  59. package/src/segment-store.ts +250 -18
  60. package/src/signed-url.ts +12 -2
  61. package/src/sqlite-dialect.ts +23 -0
  62. package/src/sqlite-segment-store.ts +245 -65
  63. package/src/sqlite-storage.ts +494 -36
  64. package/src/storage-errors.ts +13 -1
  65. package/src/storage.ts +243 -1
  66. package/src/validate.ts +20 -1
package/src/operations.ts CHANGED
@@ -415,22 +415,26 @@ export function registerRemoteQuery<Params>(
415
415
  'selected SQL has no generated relation plan; regenerate queries',
416
416
  );
417
417
  }
418
- await ctx.storage.ensureSchema(schema);
418
+ await ctx.storage.ensureSchema(schema, ctx.checkpoints);
419
419
  const prefix = 'SELECT * FROM (';
420
420
  let result;
421
421
  try {
422
- result = await ctx.storage.queryAuthoritative(ctx.partition, {
423
- plan: {
424
- sql: `${prefix}${selectedSql}) AS "_syncular_registered_query" LIMIT ?`,
425
- relations: plan.relations.map((relation) => ({
426
- ...relation,
427
- start: relation.start + prefix.length,
428
- end: relation.end + prefix.length,
429
- })),
422
+ result = await ctx.storage.queryAuthoritative(
423
+ ctx.partition,
424
+ {
425
+ plan: {
426
+ sql: `${prefix}${selectedSql}) AS "_syncular_registered_query" LIMIT ?`,
427
+ relations: plan.relations.map((relation) => ({
428
+ ...relation,
429
+ start: relation.start + prefix.length,
430
+ end: relation.end + prefix.length,
431
+ })),
432
+ },
433
+ params: [...descriptor.bind(params), options.maxRows + 1],
434
+ tables: descriptor.tables,
430
435
  },
431
- params: [...descriptor.bind(params), options.maxRows + 1],
432
- tables: descriptor.tables,
433
- });
436
+ ctx.checkpoints,
437
+ );
434
438
  } catch (error) {
435
439
  if (error instanceof SyncError) throw error;
436
440
  throw syncError(
@@ -603,7 +607,7 @@ export function registerRemoteCommand<Input>(
603
607
  }
604
608
  const resolved: ResolvedScopes = { ok: true, allowed };
605
609
  const schema = compileSchema(ctx.schema);
606
- await ctx.storage.ensureSchema(schema);
610
+ await ctx.storage.ensureSchema(schema, ctx.checkpoints);
607
611
  const processed = await processPushOperationsWithTrace(
608
612
  ctx,
609
613
  schema,
@@ -41,6 +41,14 @@ export type PgRow = Record<string, unknown>;
41
41
  * `params` use Postgres positional placeholders (`$1`, `$2`, ...). `text`
42
42
  * is a single statement (no multi-statement `;`-joined batches — those are
43
43
  * driver-specific and defeat parameterization).
44
+ *
45
+ * Syncular never overlaps statements on one `PgQueryable`. A client pinned
46
+ * to a connection by `PgExecutor.transaction` gets every statement chained
47
+ * on one FIFO by `PostgresServerStorage`, so a host validator that starts
48
+ * independent reads concurrently still reaches the driver one statement at
49
+ * a time. An adapter does not need to queue calls itself, and must not
50
+ * accept two in flight: node-postgres warns about that today and rejects it
51
+ * in node-postgres 9.
44
52
  */
45
53
  export interface PgQueryable {
46
54
  query<Row = PgRow>(
@@ -58,7 +66,9 @@ export interface PgExecutor extends PgQueryable {
58
66
  /**
59
67
  * Run `fn` inside a single Postgres transaction on one pinned connection.
60
68
  * The executor issues `BEGIN` before `fn`, `COMMIT` on resolve, and
61
- * `ROLLBACK` on throw (rethrowing the original error).
69
+ * `ROLLBACK` on throw (rethrowing the original error). The caller
70
+ * serializes the statements `fn` issues on the provided client (see
71
+ * `PgQueryable`), so the driver never sees two of them in flight.
62
72
  */
63
73
  transaction<T>(fn: (client: PgQueryable) => Promise<T>): Promise<T>;
64
74
  /** Release any pooled resources. Optional (pglite/Bun.sql). */