@voltro/testing 0.86.0 → 0.88.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.
package/dist/client.d.ts CHANGED
@@ -6,6 +6,7 @@ import { FormBinding } from '@voltro/client';
6
6
  import { FormStateSnapshot } from '@voltro/client';
7
7
  import { ReactElement } from 'react';
8
8
  import { ReactNode } from 'react';
9
+ import { RecoveryOptions } from '@voltro/client';
9
10
  import { UseFormBindingOptions } from '@voltro/client';
10
11
 
11
12
  /** The snapshot shape `useConnectionStatus` subscribes to. */
@@ -177,6 +178,10 @@ export declare interface VoltroTestClientConfig {
177
178
  readonly mutations?: Readonly<Record<string, Handler>>;
178
179
  /** Action handlers per tag. */
179
180
  readonly actions?: Readonly<Record<string, Handler>>;
181
+ /** The client's recovery options, as an app passes them — `replayWindowMs` is how
182
+ * long an action waits for a disconnected transport before it is refused
183
+ * (default 10 s, at least 250 ms). */
184
+ readonly recovery?: RecoveryOptions;
180
185
  }
181
186
 
182
187
  export { }
package/dist/client.js CHANGED
@@ -1,47 +1,47 @@
1
1
  import { renderFormBinding as e } from "./formBindingHarness.js";
2
2
  import { Effect as t } from "effect";
3
3
  import { createElement as n } from "react";
4
- import { FrameworkRuntimesContext as r, INITIAL_RECOVERY_SNAPSHOT as i, RpcErrorBus as a } from "@voltro/client";
5
- //#region src/client.tsx
6
- var o = {
4
+ import { FrameworkRuntimesContext as r, INITIAL_RECOVERY_SNAPSHOT as i, RpcErrorBus as a, resolveRecoveryOptions as o } from "@voltro/client";
5
+ // src/client.tsx
6
+ var s = {
7
7
  runPromise: t.runPromise,
8
8
  runPromiseExit: t.runPromiseExit,
9
9
  runFork: t.runFork,
10
10
  dispose: () => t.void
11
- }, s = (e = {}) => {
12
- let s = e.apiName ?? "app", c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = [];
13
- for (let [t, n] of Object.entries(e.subscriptions ?? {})) c.set(t, {
11
+ }, c = (e = {}) => {
12
+ let c = e.apiName ?? "app", l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = [];
13
+ for (let [t, n] of Object.entries(e.subscriptions ?? {})) l.set(t, {
14
14
  data: n,
15
15
  error: void 0,
16
16
  revision: 0,
17
17
  pendingPatches: 0,
18
18
  emittedAt: void 0
19
19
  });
20
- let f = (e) => c.get(e) ?? {
20
+ let p = (e) => l.get(e) ?? {
21
21
  data: void 0,
22
22
  error: void 0,
23
23
  revision: -1,
24
24
  pendingPatches: 0,
25
25
  emittedAt: void 0
26
- }, p = (e) => {
27
- u.delete(e);
28
- for (let t of l.get(e) ?? []) t();
29
- }, m = (e) => String(e[0] ?? ""), h = {
26
+ }, m = (e) => {
27
+ d.delete(e);
28
+ for (let t of u.get(e) ?? []) t();
29
+ }, h = (e) => String(e[0] ?? ""), g = {
30
30
  peek: (e) => {
31
- let t = m(e), n = u.get(t);
31
+ let t = h(e), n = d.get(t);
32
32
  if (n) return n;
33
- let r = f(t), i = {
33
+ let r = p(t), i = {
34
34
  data: r.data,
35
35
  revision: r.revision,
36
36
  emittedAt: r.emittedAt,
37
37
  error: r.error,
38
38
  pendingPatches: r.pendingPatches
39
39
  };
40
- return u.set(t, i), i;
40
+ return d.set(t, i), i;
41
41
  },
42
42
  subscribe: (e, t, n, r) => {
43
- let i = m(e), a = l.get(i) ?? /* @__PURE__ */ new Set();
44
- return a.add(r), l.set(i, a), { unsubscribe: () => {
43
+ let i = h(e), a = u.get(i) ?? /* @__PURE__ */ new Set();
44
+ return a.add(r), u.set(i, a), { unsubscribe: () => {
45
45
  a.delete(r);
46
46
  } };
47
47
  },
@@ -54,9 +54,9 @@ var o = {
54
54
  update: () => {},
55
55
  forTag: () => ({ patchedCount: 0 }),
56
56
  refreshAll: () => {
57
- g += 1;
57
+ _ += 1;
58
58
  }
59
- }, g = 0, _ = {
59
+ }, _ = 0, v = {
60
60
  rawTransport: "connected",
61
61
  status: "connected",
62
62
  failureCount: 0,
@@ -64,31 +64,44 @@ var o = {
64
64
  failedSubscriptions: [],
65
65
  pendingMutationReplays: 0,
66
66
  mutationReplay: "unknown"
67
- }, v = /* @__PURE__ */ new Set(), y = new a(), b = !0, x = {
68
- subscribe: (e) => (v.add(e), () => {
69
- v.delete(e);
67
+ }, y = /* @__PURE__ */ new Set(), b = o(e.recovery), x = new a(), S = !0, C = {
68
+ options: b,
69
+ subscribe: (e) => (y.add(e), () => {
70
+ y.delete(e);
70
71
  }),
71
- getSnapshot: () => _,
72
+ getSnapshot: () => v,
72
73
  getServerSnapshot: () => i,
73
- getPreloadSeedPermission: () => b,
74
+ getPreloadSeedPermission: () => S,
74
75
  invalidatePreloadSeeds: () => {
75
- if (b) {
76
- b = !1;
77
- for (let e of v) e();
76
+ if (S) {
77
+ S = !1;
78
+ for (let e of y) e();
78
79
  }
79
80
  },
80
- onVisibleError: (e) => y.on(e),
81
- waitForProtocolReady: async (e, t) => !t?.aborted && _.rawTransport === "connected",
81
+ onVisibleError: (e) => x.on(e),
82
+ waitForProtocolReady: (e, t) => {
83
+ if (t?.aborted) return Promise.resolve(!1);
84
+ if (v.rawTransport === "connected") return Promise.resolve(!0);
85
+ let n = b.replayWindowMs - (Date.now() - e);
86
+ return n <= 0 ? Promise.resolve(!1) : new Promise((e) => {
87
+ let r = (n) => {
88
+ y.delete(i), clearTimeout(o), t?.removeEventListener("abort", a), e(n);
89
+ }, i = () => {
90
+ v.rawTransport === "connected" && r(!0);
91
+ }, a = () => r(!1), o = setTimeout(() => r(!1), n);
92
+ y.add(i), t?.addEventListener("abort", a, { once: !0 }), t?.aborted && a();
93
+ });
94
+ },
82
95
  reserveMutationReplay: () => void 0,
83
96
  waitForMutationReplaySupport: async () => !1,
84
97
  replayWindowRemaining: () => 0,
85
98
  reportExternalSuccess: () => {},
86
99
  subjectSignal: new AbortController().signal
87
- }, S = {}, C = (e, n, r) => {
88
- let i = e.split("."), a = S;
100
+ }, w = {}, T = (e, n, r) => {
101
+ let i = e.split("."), a = w;
89
102
  for (let e of i.slice(0, -1)) a[e] = a[e] ?? {}, a = a[e];
90
103
  a[i[i.length - 1]] = (i) => t.tryPromise({
91
- try: async () => (d.push({
104
+ try: async () => (f.push({
92
105
  kind: n,
93
106
  tag: e,
94
107
  input: i
@@ -96,64 +109,63 @@ var o = {
96
109
  catch: (e) => e
97
110
  });
98
111
  };
99
- for (let [t, n] of Object.entries(e.mutations ?? {})) C(t, "mutation", n);
100
- for (let [t, n] of Object.entries(e.actions ?? {})) C(t, "action", n);
101
- let w = {
102
- runtime: o,
103
- cache: h,
104
- recovery: x,
105
- client: S,
112
+ for (let [t, n] of Object.entries(e.mutations ?? {})) T(t, "mutation", n);
113
+ for (let [t, n] of Object.entries(e.actions ?? {})) T(t, "action", n);
114
+ let E = {
115
+ runtime: s,
116
+ cache: g,
117
+ recovery: C,
118
+ client: w,
106
119
  descriptors: {},
107
120
  inspectBaseUrl: "http://test.local",
108
- errorBus: y
109
- }, T = {
121
+ errorBus: x
122
+ }, D = {
110
123
  get: (e) => {
111
- if (e !== s) throw Error(`makeVoltroTestClient: component asked for api '${e}' but the harness was built for '${s}'. Pass { apiName: '${e}' }.`);
112
- return w;
124
+ if (e !== c) throw Error(`makeVoltroTestClient: component asked for api '${e}' but the harness was built for '${c}'. Pass { apiName: '${e}' }.`);
125
+ return E;
113
126
  },
114
- names: [s]
127
+ names: [c]
115
128
  };
116
129
  return {
117
- Provider: ({ children: e }) => n(r.Provider, { value: T }, e),
130
+ Provider: ({ children: e }) => n(r.Provider, { value: D }, e),
118
131
  setSubscription: (e, t, n) => {
119
- let r = f(e);
120
- c.set(e, {
132
+ let r = p(e);
133
+ l.set(e, {
121
134
  data: t,
122
135
  error: void 0,
123
136
  revision: r.revision + 1,
124
137
  pendingPatches: n?.pendingPatches ?? 0,
125
138
  emittedAt: n?.emittedAt
126
- }), p(e);
139
+ }), m(e);
127
140
  },
128
141
  failSubscription: (e, t) => {
129
- c.set(e, {
142
+ l.set(e, {
130
143
  data: void 0,
131
144
  error: t,
132
145
  revision: -1,
133
146
  pendingPatches: 0,
134
147
  emittedAt: void 0
135
- }), p(e);
148
+ }), m(e);
136
149
  },
137
150
  resetSubscription: (e) => {
138
- c.delete(e), p(e);
151
+ l.delete(e), m(e);
139
152
  },
140
- calls: d,
153
+ calls: f,
141
154
  setConnectionStatus: (e, t) => {
142
- _ = {
143
- ..._,
155
+ v = {
156
+ ...v,
144
157
  ...t,
145
158
  status: e,
146
159
  rawTransport: t?.rawTransport ?? (e === "connected" ? "connected" : "disconnected")
147
160
  };
148
- for (let e of v) e();
161
+ for (let e of y) e();
149
162
  },
150
163
  get refreshes() {
151
- return g;
164
+ return _;
152
165
  },
153
166
  emitRpcError: (e) => {
154
- w.errorBus.emit(e);
167
+ E.errorBus.emit(e);
155
168
  }
156
169
  };
157
170
  };
158
- //#endregion
159
- export { o as FAKE_RUNTIME, s as makeVoltroTestClient, e as renderFormBinding };
171
+ export { s as FAKE_RUNTIME, c as makeVoltroTestClient, e as renderFormBinding };
package/dist/crdt.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { describe as e, expect as t, it as n } from "vitest";
2
- //#region src/crdtBackendConformance.ts
2
+ // src/crdtBackendConformance.ts
3
3
  var r = (r, i) => {
4
4
  let a = i.backend, o = (e) => a.createText(e).encodeState(), s = (e, t, n) => {
5
5
  let r = a.createText();
@@ -73,5 +73,4 @@ var r = (r, i) => {
73
73
  });
74
74
  });
75
75
  };
76
- //#endregion
77
76
  export { r as crdtBackendConformance };
package/dist/dialect.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { applySchema } from '@voltro/database/sql';
2
2
  import { DataStore } from '@voltro/database';
3
+ import { DialectId } from '@voltro/database';
3
4
  import { Effect } from 'effect';
4
5
  import { SqlClient } from 'effect/sql';
5
6
  import { SqlDialect } from '@voltro/database';
@@ -48,6 +49,22 @@ export declare interface DialectFixtureSession {
48
49
  readonly dispose: () => Promise<void>;
49
50
  }
50
51
 
52
+ export declare interface HotSqlFixture {
53
+ readonly dialect: DialectId;
54
+ readonly name: string;
55
+ readonly make: () => Promise<HotSqlFixtureSession>;
56
+ }
57
+
58
+ /** A real SQL fixture owns a fresh physical namespace and every connection it opens. */
59
+ export declare interface HotSqlFixtureSession {
60
+ readonly store: DataStore;
61
+ /** Open another independent SQL connection/pool to the same owned tables. */
62
+ readonly connect: () => Promise<DataStore>;
63
+ /** Re-apply the declared tables; SQL fixtures must keep DDL idempotent. */
64
+ readonly migrate: () => Promise<void>;
65
+ readonly dispose: () => Promise<void>;
66
+ }
67
+
51
68
  /**
52
69
  * Register the dialect's parity suite with vitest. Calls
53
70
  * `describe(...)` so the dialect's name appears in test output.
@@ -64,4 +81,7 @@ export declare interface DialectFixtureSession {
64
81
  */
65
82
  export declare const runDialectParity: (fixture: DialectFixture) => void;
66
83
 
84
+ /** Identical HotStore assertions for every live SQL dialect; no fixture opt-outs. */
85
+ export declare const runHotStoreSqlParity: (fixture: HotSqlFixture) => void;
86
+
67
87
  export { }