statewire 0.8.0 → 0.8.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","names":[],"sources":["../../src/client/core.ts"],"mappings":";;;cAYa,iBAAiB,gBAAgB;cA2TjC,mBACX,kBAAkB,gBAAgB,wBAClC,OAAO;EAjFe,SAAA,MAAA;;;;EAsEE,YAAA"}
1
+ {"version":3,"file":"core.d.ts","names":[],"sources":["../../src/client/core.ts"],"mappings":";;;cAYa,iBAAiB,gBAAgB;cA6TjC,mBACX,kBAAkB,gBAAgB,wBAClC,OAAO;EAnFe,SAAA,MAAA;;;;EAwEE,YAAA"}
@@ -200,6 +200,7 @@ const createCore = (getOptions) => {
200
200
  source?.setOnChange(null);
201
201
  source = nextSource;
202
202
  source?.setOnChange(markStale);
203
+ everAttached = false;
203
204
  markStale();
204
205
  }
205
206
  if (next.commands !== prev?.commands) {
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","names":["useEffect","useState","createChanges","getCommandsHost","getEmitHost","getStateHost","CommandsInvocation","CommandsListener","recordMutations","createMacrotaskPoster","createMethodProxy","StatewirePath","StatewireSendError","Statewire","StatewireClient","LIVE_CONNECTION","Connection","status","reconnect","failureOf","error","SendFailure","failure","fate","cause","message","Error","String","Overlay","inv","dropped","createCore","getOptions","Options","value","source","StateSource","overlays","updates","CommandUpdate","events","pendingChanged","canonical","published","overlayPaths","notifiedPublished","notifiedOverlayPaths","notifiedConnection","stale","everAttached","overlaysDirty","flushing","listeners","Set","post","scheduled","flush","schedule","markStale","drainCanonical","push","takeChanged","snapshot","undefined","next","initialState","state","recompute","prevCanonical","optimistic","materialize","paths","overlay","ctx","OptimisticContext","ts","seq","clientId","recorded","draft","method","params","Command","changedPaths","console","getConnection","connection","options","stateChanged","prev","changed","onStateChange","changes","length","batch","update","onCommandChange","event","onEvent","connectionChanged","onConnectionChange","listener","note","extra","result","commandsListener","onStart","onPosted","onAck","onCovered","some","o","filter","onSettle","outcome","type","payload","eventSink","attach","nextSource","setOnChange","commands","setListener","emit","setSink","detach","CommandsProxy","Promise","reject","send","Record","args","promise","getState","subscribe","add","delete","useStatewireCore","$","_c","t0","core","t1","t2","t3"],"sources":["../../src/client/core.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { createChanges } from \"./changes\";\nimport { getCommandsHost, getEmitHost, getStateHost } from \"../host/host\";\nimport type { CommandsInvocation, CommandsListener } from \"../host/host\";\nimport { recordMutations } from \"../util/recordMutations\";\nimport { createMacrotaskPoster } from \"../util/macrotask\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\n\nexport const LIVE_CONNECTION: StatewireClient.Connection = {\n status: \"live\",\n reconnect: () => {},\n};\n\nconst failureOf = (error: unknown): StatewireClient.SendFailure =>\n error instanceof StatewireSendError\n ? error.failure\n : {\n fate: \"rejected\",\n cause: \"server\",\n message: error instanceof Error ? error.message : String(error),\n };\n\ntype Overlay = { inv: CommandsInvocation; dropped: boolean };\n\nconst createCore = (\n getOptions: () => StatewireClient.Options<any, any, any>,\n) => {\n let value: Statewire<unknown> | null = null;\n let source: Statewire.StateSource | null = null;\n let overlays: Overlay[] = [];\n let updates: Statewire.CommandUpdate[] = [];\n let events: unknown[] = [];\n let pendingChanged: StatewirePath[] = [];\n let canonical: unknown;\n let published: unknown;\n let overlayPaths: readonly StatewirePath[] = [];\n let notifiedPublished: unknown;\n let notifiedOverlayPaths: readonly StatewirePath[] = [];\n let notifiedConnection: StatewireClient.Connection | null = null;\n let stale = false;\n let everAttached = false;\n let overlaysDirty = false;\n let flushing = false;\n const listeners = new Set<() => void>();\n\n const post = createMacrotaskPoster(() => {\n scheduled = false;\n flush();\n });\n let scheduled = false;\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n post();\n };\n\n const markStale = () => {\n stale = true;\n schedule();\n };\n\n // initialState stands in for the canonical state only before the first\n // attach snapshot; replay boundaries after that read as loading, not preload.\n const drainCanonical = () => {\n if (source) {\n pendingChanged.push(...source.takeChanged());\n const snapshot = source.snapshot();\n if (snapshot !== undefined) {\n everAttached = true;\n canonical = snapshot;\n return;\n }\n const next = everAttached ? undefined : getOptions().initialState;\n if (next !== canonical) pendingChanged.push([]);\n canonical = next;\n } else if (value) {\n if (value.state !== undefined) everAttached = true;\n const next = everAttached ? value.state : getOptions().initialState;\n if (next !== canonical) {\n pendingChanged.push([]);\n canonical = next;\n }\n }\n };\n\n const recompute = () => {\n if (!stale || !value) return;\n stale = false;\n const prevCanonical = canonical;\n drainCanonical();\n if (canonical === prevCanonical && !overlaysDirty) return;\n overlaysDirty = false;\n const { optimistic, materialize } = getOptions();\n let next = canonical;\n let paths: readonly StatewirePath[] = [];\n if (optimistic && canonical !== undefined) {\n for (const overlay of overlays) {\n if (overlay.dropped) continue;\n const { inv } = overlay;\n const ctx: StatewireClient.OptimisticContext = {\n ts: inv.ts,\n seq: inv.seq,\n ...(inv.clientId !== undefined && { clientId: inv.clientId }),\n };\n try {\n const recorded = recordMutations(next, (draft) =>\n optimistic(\n draft as never,\n { method: inv.method, params: inv.params } as Statewire.Command,\n ctx,\n ),\n );\n next = recorded.state;\n paths = [...paths, ...recorded.changedPaths];\n } catch (error) {\n overlay.dropped = true;\n console.error(\n `statewire: optimistic reducer threw for \"${inv.method}\"; dropping its optimistic update`,\n error,\n );\n }\n }\n }\n if (materialize && next !== undefined) {\n try {\n const recorded = recordMutations(next, (draft) =>\n materialize(draft as never),\n );\n next = recorded.state;\n paths = [...paths, ...recorded.changedPaths];\n } catch (error) {\n console.error(\n \"statewire: materialize threw; publishing without its update\",\n error,\n );\n }\n }\n published = next;\n overlayPaths = paths;\n };\n\n const getConnection = (): StatewireClient.Connection =>\n value?.connection ?? LIVE_CONNECTION;\n\n const flush = () => {\n if (!value) return;\n if (flushing) {\n schedule();\n return;\n }\n flushing = true;\n try {\n recompute();\n const options = getOptions();\n const stateChanged = published !== notifiedPublished;\n if (stateChanged) {\n const prev = notifiedPublished;\n const changed = [\n ...pendingChanged,\n ...notifiedOverlayPaths,\n ...overlayPaths,\n ];\n pendingChanged = [];\n notifiedPublished = published;\n notifiedOverlayPaths = overlayPaths;\n options.onStateChange?.(published as never, {\n changes: createChanges(prev, published, changed),\n });\n }\n if (updates.length > 0 && published !== undefined) {\n const batch = updates;\n updates = [];\n for (const update of batch) {\n options.onCommandChange?.(update, { state: published as never });\n }\n }\n if (events.length > 0 && published !== undefined) {\n const batch = events;\n events = [];\n for (const event of batch) {\n options.onEvent?.(event, { state: published as never });\n }\n }\n const connection = getConnection();\n const connectionChanged = connection !== notifiedConnection;\n notifiedConnection = connection;\n if (connectionChanged) options.onConnectionChange?.(connection);\n if (stateChanged || connectionChanged) {\n for (const listener of [...listeners]) listener();\n }\n } finally {\n flushing = false;\n }\n };\n\n const note = (\n inv: CommandsInvocation,\n status: Statewire.CommandUpdate[\"status\"],\n extra?: { result?: unknown; failure?: StatewireClient.SendFailure },\n ) => {\n if (!getOptions().onCommandChange) return;\n updates.push({\n method: inv.method,\n params: inv.params as never[],\n seq: inv.seq,\n status,\n ...extra,\n });\n schedule();\n };\n\n const commandsListener: CommandsListener = {\n onStart: (inv) => {\n overlays.push({ inv, dropped: false });\n overlaysDirty = true;\n markStale();\n note(inv, \"queued\");\n },\n onPosted: (inv) => note(inv, \"posted\"),\n onAck: (inv) => note(inv, \"acked\"),\n onCovered: (inv) => {\n if (!overlays.some((o) => o.inv === inv)) return;\n overlays = overlays.filter((o) => o.inv !== inv);\n overlaysDirty = true;\n markStale();\n },\n onSettle: (inv, outcome) => {\n note(\n inv,\n \"settled\",\n outcome.type === \"accepted\"\n ? { result: outcome.payload }\n : { failure: failureOf(outcome.error) },\n );\n flush();\n },\n };\n\n const eventSink = (event: unknown) => {\n if (!getOptions().onEvent) return;\n events.push(event);\n schedule();\n };\n\n const attach = (next: Statewire<unknown>) => {\n if (next === value) return;\n const prev = value;\n value = next;\n const nextSource =\n next.source ??\n (typeof next.state === \"object\" && next.state !== null\n ? getStateHost(next.state)\n : undefined) ??\n null;\n if (nextSource !== source) {\n source?.setOnChange(null);\n source = nextSource;\n source?.setOnChange(markStale);\n markStale();\n }\n if (next.commands !== prev?.commands) {\n if (prev) getCommandsHost(prev.commands)?.setListener(null);\n getCommandsHost(next.commands)?.setListener(commandsListener);\n if (overlays.length > 0) {\n overlays = [];\n overlaysDirty = true;\n }\n markStale();\n }\n if (next.emit !== prev?.emit) {\n if (prev) getEmitHost(prev.emit)?.setSink(null);\n getEmitHost(next.emit)?.setSink(eventSink);\n }\n if (!source) markStale();\n schedule();\n };\n\n const detach = () => {\n source?.setOnChange(null);\n source = null;\n if (value) {\n getCommandsHost(value.commands)?.setListener(null);\n getEmitHost(value.emit)?.setSink(null);\n value = null;\n }\n };\n\n const commands = createMethodProxy<Statewire.CommandsProxy<any>>(\n (method, params) => {\n if (!value) {\n return Promise.reject(\n new StatewireSendError({ fate: \"aborted\", cause: \"unmount\" }),\n );\n }\n const send = (\n value.commands as Record<\n string,\n (...args: unknown[]) => Promise<unknown>\n >\n )[method]!;\n const promise = send(...params);\n flush();\n return promise;\n },\n );\n\n return {\n attach,\n detach,\n getState: () => {\n recompute();\n return published;\n },\n commands,\n subscribe: (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n};\n\nexport const useStatewireCore = (\n getOptions: () => StatewireClient.Options<any, any, any>,\n value: Statewire<unknown>,\n) => {\n const [core] = useState(() => createCore(getOptions));\n // Attach during render so the first snapshot reads the transport's state;\n // re-attaching the same transport is a no-op and the single-slot host\n // listeners make a swap land on the last writer.\n core.attach(value);\n useEffect(() => {\n core.attach(value);\n });\n useEffect(() => () => core.detach(), [core]);\n return core;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"core.js","names":["useEffect","useState","createChanges","getCommandsHost","getEmitHost","getStateHost","CommandsInvocation","CommandsListener","recordMutations","createMacrotaskPoster","createMethodProxy","StatewirePath","StatewireSendError","Statewire","StatewireClient","LIVE_CONNECTION","Connection","status","reconnect","failureOf","error","SendFailure","failure","fate","cause","message","Error","String","Overlay","inv","dropped","createCore","getOptions","Options","value","source","StateSource","overlays","updates","CommandUpdate","events","pendingChanged","canonical","published","overlayPaths","notifiedPublished","notifiedOverlayPaths","notifiedConnection","stale","everAttached","overlaysDirty","flushing","listeners","Set","post","scheduled","flush","schedule","markStale","drainCanonical","push","takeChanged","snapshot","undefined","next","initialState","state","recompute","prevCanonical","optimistic","materialize","paths","overlay","ctx","OptimisticContext","ts","seq","clientId","recorded","draft","method","params","Command","changedPaths","console","getConnection","connection","options","stateChanged","prev","changed","onStateChange","changes","length","batch","update","onCommandChange","event","onEvent","connectionChanged","onConnectionChange","listener","note","extra","result","commandsListener","onStart","onPosted","onAck","onCovered","some","o","filter","onSettle","outcome","type","payload","eventSink","attach","nextSource","setOnChange","commands","setListener","emit","setSink","detach","CommandsProxy","Promise","reject","send","Record","args","promise","getState","subscribe","add","delete","useStatewireCore","$","_c","t0","core","t1","t2","t3"],"sources":["../../src/client/core.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { createChanges } from \"./changes\";\nimport { getCommandsHost, getEmitHost, getStateHost } from \"../host/host\";\nimport type { CommandsInvocation, CommandsListener } from \"../host/host\";\nimport { recordMutations } from \"../util/recordMutations\";\nimport { createMacrotaskPoster } from \"../util/macrotask\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport { StatewireSendError } from \"../types\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\n\nexport const LIVE_CONNECTION: StatewireClient.Connection = {\n status: \"live\",\n reconnect: () => {},\n};\n\nconst failureOf = (error: unknown): StatewireClient.SendFailure =>\n error instanceof StatewireSendError\n ? error.failure\n : {\n fate: \"rejected\",\n cause: \"server\",\n message: error instanceof Error ? error.message : String(error),\n };\n\ntype Overlay = { inv: CommandsInvocation; dropped: boolean };\n\nconst createCore = (\n getOptions: () => StatewireClient.Options<any, any, any>,\n) => {\n let value: Statewire<unknown> | null = null;\n let source: Statewire.StateSource | null = null;\n let overlays: Overlay[] = [];\n let updates: Statewire.CommandUpdate[] = [];\n let events: unknown[] = [];\n let pendingChanged: StatewirePath[] = [];\n let canonical: unknown;\n let published: unknown;\n let overlayPaths: readonly StatewirePath[] = [];\n let notifiedPublished: unknown;\n let notifiedOverlayPaths: readonly StatewirePath[] = [];\n let notifiedConnection: StatewireClient.Connection | null = null;\n let stale = false;\n let everAttached = false;\n let overlaysDirty = false;\n let flushing = false;\n const listeners = new Set<() => void>();\n\n const post = createMacrotaskPoster(() => {\n scheduled = false;\n flush();\n });\n let scheduled = false;\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n post();\n };\n\n const markStale = () => {\n stale = true;\n schedule();\n };\n\n // initialState stands in for the canonical state only before the first\n // attach snapshot; replay boundaries after that read as loading, not preload.\n const drainCanonical = () => {\n if (source) {\n pendingChanged.push(...source.takeChanged());\n const snapshot = source.snapshot();\n if (snapshot !== undefined) {\n everAttached = true;\n canonical = snapshot;\n return;\n }\n const next = everAttached ? undefined : getOptions().initialState;\n if (next !== canonical) pendingChanged.push([]);\n canonical = next;\n } else if (value) {\n if (value.state !== undefined) everAttached = true;\n const next = everAttached ? value.state : getOptions().initialState;\n if (next !== canonical) {\n pendingChanged.push([]);\n canonical = next;\n }\n }\n };\n\n const recompute = () => {\n if (!stale || !value) return;\n stale = false;\n const prevCanonical = canonical;\n drainCanonical();\n if (canonical === prevCanonical && !overlaysDirty) return;\n overlaysDirty = false;\n const { optimistic, materialize } = getOptions();\n let next = canonical;\n let paths: readonly StatewirePath[] = [];\n if (optimistic && canonical !== undefined) {\n for (const overlay of overlays) {\n if (overlay.dropped) continue;\n const { inv } = overlay;\n const ctx: StatewireClient.OptimisticContext = {\n ts: inv.ts,\n seq: inv.seq,\n ...(inv.clientId !== undefined && { clientId: inv.clientId }),\n };\n try {\n const recorded = recordMutations(next, (draft) =>\n optimistic(\n draft as never,\n { method: inv.method, params: inv.params } as Statewire.Command,\n ctx,\n ),\n );\n next = recorded.state;\n paths = [...paths, ...recorded.changedPaths];\n } catch (error) {\n overlay.dropped = true;\n console.error(\n `statewire: optimistic reducer threw for \"${inv.method}\"; dropping its optimistic update`,\n error,\n );\n }\n }\n }\n if (materialize && next !== undefined) {\n try {\n const recorded = recordMutations(next, (draft) =>\n materialize(draft as never),\n );\n next = recorded.state;\n paths = [...paths, ...recorded.changedPaths];\n } catch (error) {\n console.error(\n \"statewire: materialize threw; publishing without its update\",\n error,\n );\n }\n }\n published = next;\n overlayPaths = paths;\n };\n\n const getConnection = (): StatewireClient.Connection =>\n value?.connection ?? LIVE_CONNECTION;\n\n const flush = () => {\n if (!value) return;\n if (flushing) {\n schedule();\n return;\n }\n flushing = true;\n try {\n recompute();\n const options = getOptions();\n const stateChanged = published !== notifiedPublished;\n if (stateChanged) {\n const prev = notifiedPublished;\n const changed = [\n ...pendingChanged,\n ...notifiedOverlayPaths,\n ...overlayPaths,\n ];\n pendingChanged = [];\n notifiedPublished = published;\n notifiedOverlayPaths = overlayPaths;\n options.onStateChange?.(published as never, {\n changes: createChanges(prev, published, changed),\n });\n }\n if (updates.length > 0 && published !== undefined) {\n const batch = updates;\n updates = [];\n for (const update of batch) {\n options.onCommandChange?.(update, { state: published as never });\n }\n }\n if (events.length > 0 && published !== undefined) {\n const batch = events;\n events = [];\n for (const event of batch) {\n options.onEvent?.(event, { state: published as never });\n }\n }\n const connection = getConnection();\n const connectionChanged = connection !== notifiedConnection;\n notifiedConnection = connection;\n if (connectionChanged) options.onConnectionChange?.(connection);\n if (stateChanged || connectionChanged) {\n for (const listener of [...listeners]) listener();\n }\n } finally {\n flushing = false;\n }\n };\n\n const note = (\n inv: CommandsInvocation,\n status: Statewire.CommandUpdate[\"status\"],\n extra?: { result?: unknown; failure?: StatewireClient.SendFailure },\n ) => {\n if (!getOptions().onCommandChange) return;\n updates.push({\n method: inv.method,\n params: inv.params as never[],\n seq: inv.seq,\n status,\n ...extra,\n });\n schedule();\n };\n\n const commandsListener: CommandsListener = {\n onStart: (inv) => {\n overlays.push({ inv, dropped: false });\n overlaysDirty = true;\n markStale();\n note(inv, \"queued\");\n },\n onPosted: (inv) => note(inv, \"posted\"),\n onAck: (inv) => note(inv, \"acked\"),\n onCovered: (inv) => {\n if (!overlays.some((o) => o.inv === inv)) return;\n overlays = overlays.filter((o) => o.inv !== inv);\n overlaysDirty = true;\n markStale();\n },\n onSettle: (inv, outcome) => {\n note(\n inv,\n \"settled\",\n outcome.type === \"accepted\"\n ? { result: outcome.payload }\n : { failure: failureOf(outcome.error) },\n );\n flush();\n },\n };\n\n const eventSink = (event: unknown) => {\n if (!getOptions().onEvent) return;\n events.push(event);\n schedule();\n };\n\n const attach = (next: Statewire<unknown>) => {\n if (next === value) return;\n const prev = value;\n value = next;\n const nextSource =\n next.source ??\n (typeof next.state === \"object\" && next.state !== null\n ? getStateHost(next.state)\n : undefined) ??\n null;\n if (nextSource !== source) {\n source?.setOnChange(null);\n source = nextSource;\n source?.setOnChange(markStale);\n // A new source is a new attach lifecycle: initialState preloads again.\n everAttached = false;\n markStale();\n }\n if (next.commands !== prev?.commands) {\n if (prev) getCommandsHost(prev.commands)?.setListener(null);\n getCommandsHost(next.commands)?.setListener(commandsListener);\n if (overlays.length > 0) {\n overlays = [];\n overlaysDirty = true;\n }\n markStale();\n }\n if (next.emit !== prev?.emit) {\n if (prev) getEmitHost(prev.emit)?.setSink(null);\n getEmitHost(next.emit)?.setSink(eventSink);\n }\n if (!source) markStale();\n schedule();\n };\n\n const detach = () => {\n source?.setOnChange(null);\n source = null;\n if (value) {\n getCommandsHost(value.commands)?.setListener(null);\n getEmitHost(value.emit)?.setSink(null);\n value = null;\n }\n };\n\n const commands = createMethodProxy<Statewire.CommandsProxy<any>>(\n (method, params) => {\n if (!value) {\n return Promise.reject(\n new StatewireSendError({ fate: \"aborted\", cause: \"unmount\" }),\n );\n }\n const send = (\n value.commands as Record<\n string,\n (...args: unknown[]) => Promise<unknown>\n >\n )[method]!;\n const promise = send(...params);\n flush();\n return promise;\n },\n );\n\n return {\n attach,\n detach,\n getState: () => {\n recompute();\n return published;\n },\n commands,\n subscribe: (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n};\n\nexport const useStatewireCore = (\n getOptions: () => StatewireClient.Options<any, any, any>,\n value: Statewire<unknown>,\n) => {\n const [core] = useState(() => createCore(getOptions));\n // Attach during render so the first snapshot reads the transport's state;\n // re-attaching the same transport is a no-op and the single-slot host\n // listeners make a swap land on the last writer.\n core.attach(value);\n useEffect(() => {\n core.attach(value);\n });\n useEffect(() => () => core.detach(), [core]);\n return core;\n};\n"],"mappings":";;;;;;;;;AAYA,MAAae,kBAA8C;CACzDE,QAAQ;CACRC,iBAAiB,CAAC;AACpB;AAEA,MAAMC,aAAaC,UACjBA,iBAAiBR,qBACbQ,MAAME,UACN;CACEC,MAAM;CACNC,OAAO;CACPC,SAASL,iBAAiBM,QAAQN,MAAMK,UAAUE,OAAOP,KAAK;AAChE;AAIN,MAAMW,cACJC,eACG;CACH,IAAIE,QAAmC;CACvC,IAAIC,SAAuC;CAC3C,IAAIE,WAAsB,CAAA;CAC1B,IAAIC,UAAqC,CAAA;CACzC,IAAIE,SAAoB,CAAA;CACxB,IAAIC,iBAAkC,CAAA;CACtC,IAAIC;CACJ,IAAIC;CACJ,IAAIC,eAAyC,CAAA;CAC7C,IAAIC;CACJ,IAAIC,uBAAiD,CAAA;CACrD,IAAIC,qBAAwD;CAC5D,IAAIC,QAAQ;CACZ,IAAIC,eAAe;CACnB,IAAIC,gBAAgB;CACpB,IAAIC,WAAW;CACf,MAAMC,4BAAY,IAAIC,IAAgB;CAEtC,MAAMC,OAAO7C,4BAA4B;EACvC8C,YAAY;EACZC,MAAM;CACR,CAAC;CACD,IAAID,YAAY;CAChB,MAAME,iBAAiB;EACrB,IAAIF,WAAW;EACfA,YAAY;EACZD,KAAK;CACP;CAEA,MAAMI,kBAAkB;EACtBV,QAAQ;EACRS,SAAS;CACX;CAIA,MAAME,uBAAuB;EAC3B,IAAIxB,QAAQ;GACVM,eAAemB,KAAK,GAAGzB,OAAO0B,YAAY,CAAC;GAC3C,MAAMC,WAAW3B,OAAO2B,SAAS;GACjC,IAAIA,aAAaC,KAAAA,GAAW;IAC1Bd,eAAe;IACfP,YAAYoB;IACZ;GACF;GACA,MAAME,OAAOf,eAAec,KAAAA,IAAY/B,WAAW,CAAC,CAACiC;GACrD,IAAID,SAAStB,WAAWD,eAAemB,KAAK,CAAA,CAAE;GAC9ClB,YAAYsB;EACd,OAAO,IAAI9B,OAAO;GAChB,IAAIA,MAAMgC,UAAUH,KAAAA,GAAWd,eAAe;GAC9C,MAAMe,OAAOf,eAAef,MAAMgC,QAAQlC,WAAW,CAAC,CAACiC;GACvD,IAAID,SAAStB,WAAW;IACtBD,eAAemB,KAAK,CAAA,CAAE;IACtBlB,YAAYsB;GACd;EACF;CACF;CAEA,MAAMG,kBAAkB;EACtB,IAAI,CAACnB,SAAS,CAACd,OAAO;EACtBc,QAAQ;EACR,MAAMoB,gBAAgB1B;EACtBiB,eAAe;EACf,IAAIjB,cAAc0B,iBAAiB,CAAClB,eAAe;EACnDA,gBAAgB;EAChB,MAAM,EAAEmB,YAAYC,gBAAgBtC,WAAW;EAC/C,IAAIgC,OAAOtB;EACX,IAAI6B,QAAkC,CAAA;EACtC,IAAIF,cAAc3B,cAAcqB,KAAAA,GAC9B,KAAK,MAAMS,WAAWnC,UAAU;GAC9B,IAAImC,QAAQ1C,SAAS;GACrB,MAAM,EAAED,QAAQ2C;GAChB,MAAMC,MAAyC;IAC7CE,IAAI9C,IAAI8C;IACRC,KAAK/C,IAAI+C;IACT,GAAI/C,IAAIgD,aAAad,KAAAA,KAAa,EAAEc,UAAUhD,IAAIgD,SAAS;GAC7D;GACA,IAAI;IACF,MAAMC,WAAWtE,gBAAgBwD,OAAOe,UACtCV,WACEU,OACA;KAAEC,QAAQnD,IAAImD;KAAQC,QAAQpD,IAAIoD;IAAO,GACzCR,GACF,CACF;IACAT,OAAOc,SAASZ;IAChBK,QAAQ,CAAC,GAAGA,OAAO,GAAGO,SAASK,YAAY;GAC7C,SAAS/D,OAAO;IACdoD,QAAQ1C,UAAU;IAClBsD,QAAQhE,MACN,4CAA4CS,IAAImD,OAAM,oCACtD5D,KACF;GACF;EACF;EAEF,IAAIkD,eAAeN,SAASD,KAAAA,GAC1B,IAAI;GACF,MAAMe,WAAWtE,gBAAgBwD,OAAOe,UACtCT,YAAYS,KAAc,CAC5B;GACAf,OAAOc,SAASZ;GAChBK,QAAQ,CAAC,GAAGA,OAAO,GAAGO,SAASK,YAAY;EAC7C,SAAS/D,OAAO;GACdgE,QAAQhE,MACN,+DACAA,KACF;EACF;EAEFuB,YAAYqB;EACZpB,eAAe2B;CACjB;CAEA,MAAMc,sBACJnD,OAAOoD,cAAcvE;CAEvB,MAAMyC,cAAc;EAClB,IAAI,CAACtB,OAAO;EACZ,IAAIiB,UAAU;GACZM,SAAS;GACT;EACF;EACAN,WAAW;EACX,IAAI;GACFgB,UAAU;GACV,MAAMoB,UAAUvD,WAAW;GAC3B,MAAMwD,eAAe7C,cAAcE;GACnC,IAAI2C,cAAc;IAChB,MAAMC,OAAO5C;IACb,MAAM6C,UAAU;KACd,GAAGjD;KACH,GAAGK;KACH,GAAGF;IAAY;IAEjBH,iBAAiB,CAAA;IACjBI,oBAAoBF;IACpBG,uBAAuBF;IACvB2C,QAAQI,gBAAgBhD,WAAoB,EAC1CiD,SAAS1F,cAAcuF,MAAM9C,WAAW+C,OAAO,EACjD,CAAC;GACH;GACA,IAAIpD,QAAQuD,SAAS,KAAKlD,cAAcoB,KAAAA,GAAW;IACjD,MAAM+B,QAAQxD;IACdA,UAAU,CAAA;IACV,KAAK,MAAMyD,UAAUD,OACnBP,QAAQS,kBAAkBD,QAAQ,EAAE7B,OAAOvB,UAAmB,CAAC;GAEnE;GACA,IAAIH,OAAOqD,SAAS,KAAKlD,cAAcoB,KAAAA,GAAW;IAChD,MAAM+B,QAAQtD;IACdA,SAAS,CAAA;IACT,KAAK,MAAMyD,SAASH,OAClBP,QAAQW,UAAUD,OAAO,EAAE/B,OAAOvB,UAAmB,CAAC;GAE1D;GACA,MAAM2C,aAAaD,cAAc;GACjC,MAAMc,oBAAoBb,eAAevC;GACzCA,qBAAqBuC;GACrB,IAAIa,mBAAmBZ,QAAQa,qBAAqBd,UAAU;GAC9D,IAAIE,gBAAgBW,mBAClB,KAAK,MAAME,YAAY,CAAC,GAAGjD,SAAS,GAAGiD,SAAS;EAEpD,UAAU;GACRlD,WAAW;EACb;CACF;CAEA,MAAMmD,QACJzE,KACAZ,QACAsF,UACG;EACH,IAAI,CAACvE,WAAW,CAAC,CAACgE,iBAAiB;EACnC1D,QAAQsB,KAAK;GACXoB,QAAQnD,IAAImD;GACZC,QAAQpD,IAAIoD;GACZL,KAAK/C,IAAI+C;GACT3D;GACA,GAAGsF;EACL,CAAC;EACD9C,SAAS;CACX;CAEA,MAAMgD,mBAAqC;EACzCC,UAAU7E,QAAQ;GAChBQ,SAASuB,KAAK;IAAE/B;IAAKC,SAAS;GAAM,CAAC;GACrCoB,gBAAgB;GAChBQ,UAAU;GACV4C,KAAKzE,KAAK,QAAQ;EACpB;EACA8E,WAAW9E,QAAQyE,KAAKzE,KAAK,QAAQ;EACrC+E,QAAQ/E,QAAQyE,KAAKzE,KAAK,OAAO;EACjCgF,YAAYhF,QAAQ;GAClB,IAAI,CAACQ,SAASyE,MAAMC,MAAMA,EAAElF,QAAQA,GAAG,GAAG;GAC1CQ,WAAWA,SAAS2E,QAAQD,MAAMA,EAAElF,QAAQA,GAAG;GAC/CqB,gBAAgB;GAChBQ,UAAU;EACZ;EACAuD,WAAWpF,KAAKqF,YAAY;GAC1BZ,KACEzE,KACA,WACAqF,QAAQC,SAAS,aACb,EAAEX,QAAQU,QAAQE,QAAQ,IAC1B,EAAE9F,SAASH,UAAU+F,QAAQ9F,KAAK,EAAE,CAC1C;GACAoC,MAAM;EACR;CACF;CAEA,MAAM6D,aAAapB,UAAmB;EACpC,IAAI,CAACjE,WAAW,CAAC,CAACkE,SAAS;EAC3B1D,OAAOoB,KAAKqC,KAAK;EACjBxC,SAAS;CACX;CAEA,MAAM6D,UAAUtD,SAA6B;EAC3C,IAAIA,SAAS9B,OAAO;EACpB,MAAMuD,OAAOvD;EACbA,QAAQ8B;EACR,MAAMuD,aACJvD,KAAK7B,WACJ,OAAO6B,KAAKE,UAAU,YAAYF,KAAKE,UAAU,OAC9C7D,aAAa2D,KAAKE,KAAK,IACvBH,KAAAA,MACJ;EACF,IAAIwD,eAAepF,QAAQ;GACzBA,QAAQqF,YAAY,IAAI;GACxBrF,SAASoF;GACTpF,QAAQqF,YAAY9D,SAAS;GAE7BT,eAAe;GACfS,UAAU;EACZ;EACA,IAAIM,KAAKyD,aAAahC,MAAMgC,UAAU;GACpC,IAAIhC,MAAMtF,gBAAgBsF,KAAKgC,QAAQ,CAAC,EAAEC,YAAY,IAAI;GAC1DvH,gBAAgB6D,KAAKyD,QAAQ,CAAC,EAAEC,YAAYjB,gBAAgB;GAC5D,IAAIpE,SAASwD,SAAS,GAAG;IACvBxD,WAAW,CAAA;IACXa,gBAAgB;GAClB;GACAQ,UAAU;EACZ;EACA,IAAIM,KAAK2D,SAASlC,MAAMkC,MAAM;GAC5B,IAAIlC,MAAMrF,YAAYqF,KAAKkC,IAAI,CAAC,EAAEC,QAAQ,IAAI;GAC9CxH,YAAY4D,KAAK2D,IAAI,CAAC,EAAEC,QAAQP,SAAS;EAC3C;EACA,IAAI,CAAClF,QAAQuB,UAAU;EACvBD,SAAS;CACX;CAEA,MAAMoE,eAAe;EACnB1F,QAAQqF,YAAY,IAAI;EACxBrF,SAAS;EACT,IAAID,OAAO;GACT/B,gBAAgB+B,MAAMuF,QAAQ,CAAC,EAAEC,YAAY,IAAI;GACjDtH,YAAY8B,MAAMyF,IAAI,CAAC,EAAEC,QAAQ,IAAI;GACrC1F,QAAQ;EACV;CACF;CAqBA,OAAO;EACLoF;EACAO;EACAQ,gBAAgB;GACdlE,UAAU;GACV,OAAOxB;EACT;EACA8E,UA1Be/G,mBACdsE,QAAQC,WAAW;GAClB,IAAI,CAAC/C,OACH,OAAO6F,QAAQC,OACb,IAAIpH,mBAAmB;IAAEW,MAAM;IAAWC,OAAO;GAAU,CAAC,CAC9D;GAEF,MAAMyG,OACJ/F,MAAMuF,SAINzC;GACF,MAAMoD,UAAUH,KAAK,GAAGhD,MAAM;GAC9BzB,MAAM;GACN,OAAO4E;EACT,CAUAX;EACAa,YAAYjC,aAAyB;GACnCjD,UAAUmF,IAAIlC,QAAQ;GACtB,aAAa;IACXjD,UAAUoF,OAAOnC,QAAQ;GAC3B;EACF;CACF;AACF;AAEA,MAAaoC,oBAAmBzG,YAAAE,UAAA;CAAA,MAAAwG,IAAAC,EAAA,CAAA;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAA1G,YAAA;EAIN4G,WAAM7G,WAAWC,UAAU;EAAC0G,EAAA,KAAA1G;EAAA0G,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAApD,MAAA,CAAAG,QAAe5I,SAAS2I,EAA4B;CAIpDC,KAAIvB,OAAQpF,KAAK;CAAC,IAAA4G;CAAA,IAAAJ,EAAA,OAAAG,QAAAH,EAAA,OAAAxG,OAAA;EACR4G,WAAA;GACRD,KAAIvB,OAAQpF,KAAK;EAAC;EACnBwG,EAAA,KAAAG;EAAAH,EAAA,KAAAxG;EAAAwG,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAFD1I,UAAU8I,EAET;CAAC,IAAAC;CAAA,IAAAC;CAAA,IAAAN,EAAA,OAAAG,MAAA;EACQE,iBAAYF,KAAIhB,OAAQ;EAAGmB,KAAA,CAACH,IAAI;EAACH,EAAA,KAAAG;EAAAH,EAAA,KAAAK;EAAAL,EAAA,KAAAM;CAAA,OAAA;EAAAD,KAAAL,EAAA;EAAAM,KAAAN,EAAA;CAAA;CAA3C1I,UAAU+I,IAA2BC,EAAM;CAAC,OACrCH;AAAI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "statewire",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "State over the wire: snapshot-first delta streaming and command submission for any state and any command",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -260,6 +260,8 @@ const createCore = (
260
260
  source?.setOnChange(null);
261
261
  source = nextSource;
262
262
  source?.setOnChange(markStale);
263
+ // A new source is a new attach lifecycle: initialState preloads again.
264
+ everAttached = false;
263
265
  markStale();
264
266
  }
265
267
  if (next.commands !== prev?.commands) {