xstate 6.0.0-alpha.39 → 6.0.0-alpha.40

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.
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var dist_xstateActors = require('./index-21d08fff.cjs.js');
6
6
  var createActor = require('./createActor-d5305cc9.cjs.js');
7
- var StateMachine = require('./StateMachine-94084ac7.cjs.js');
7
+ var StateMachine = require('./StateMachine-1464d5e4.cjs.js');
8
8
  var transition = require('./transition-2dcabac8.cjs.js');
9
9
 
10
10
  /**
@@ -1969,6 +1969,15 @@ function mapState(snapshot, mapper) {
1969
1969
  function isObject(value) {
1970
1970
  return value !== null && typeof value === 'object';
1971
1971
  }
1972
+ function isVersionedStateMachine(entry) {
1973
+ return 'transition' in entry && typeof entry.transition === 'function';
1974
+ }
1975
+ function hasSnapshotSchema(entry) {
1976
+ return 'snapshotSchema' in entry && entry.snapshotSchema !== undefined;
1977
+ }
1978
+ function hasEventSchema(entry) {
1979
+ return 'eventSchema' in entry && entry.eventSchema !== undefined;
1980
+ }
1972
1981
  function getSnapshotSource(raw, defaultId) {
1973
1982
  if (!isObject(raw)) {
1974
1983
  return {};
@@ -1995,65 +2004,57 @@ async function validate(schema, value, description) {
1995
2004
  return result.value;
1996
2005
  }
1997
2006
  async function finalizeSnapshot(snapshot, target) {
1998
- const context = await validate(target.schemas?.context, snapshot.context, `context for machine '${target.id}' version '${target.version}'`);
1999
- return {
2007
+ return await validate(target.snapshotSchema, {
2000
2008
  ...snapshot,
2001
- context,
2002
2009
  machine: {
2003
2010
  id: target.id,
2004
2011
  version: target.version
2005
2012
  },
2006
2013
  version: target.version
2007
- };
2014
+ }, `snapshot for machine '${target.id}' version '${target.version}'`);
2008
2015
  }
2009
- async function validateEvents(events, machine) {
2016
+ async function validateEvents(events, source) {
2010
2017
  return Promise.all(events.map(async (event, index) => {
2011
- if (!isObject(event) || typeof event.type !== 'string') {
2012
- throw new Error(`Invalid event at index ${index}.`);
2013
- }
2014
- const eventSchemas = machine.schemas?.events;
2015
- const isFrameworkEvent = event.type.startsWith('xstate.') || event.type.startsWith('@xstate.');
2016
- const schema = eventSchemas && Object.hasOwn(eventSchemas, event.type) ? eventSchemas[event.type] : undefined;
2017
- if (eventSchemas && !schema && !isFrameworkEvent) {
2018
- throw new Error(`Unknown event '${event.type}' for machine '${machine.id}' version '${machine.version}'.`);
2019
- }
2020
- if (!schema) {
2021
- return event;
2018
+ const result = await source.eventSchema['~standard'].validate(event);
2019
+ if (result.issues) {
2020
+ const message = result.issues[0]?.message;
2021
+ if (message?.startsWith('Unknown event ')) {
2022
+ throw new Error(message);
2023
+ }
2024
+ const type = isObject(event) ? event.type : undefined;
2025
+ throw new Error(typeof type === 'string' ? `Invalid event '${type}' at index ${index}${message ? `: ${message}` : '.'}` : `Invalid event at index ${index}${message ? `: ${message}` : '.'}`);
2022
2026
  }
2023
- const {
2024
- type,
2025
- ...payload
2026
- } = event;
2027
- const validatedPayload = await validate(schema, payload, `event '${type}' at index ${index}`);
2028
- if (!isObject(validatedPayload)) {
2029
- throw new Error(`Invalid event '${type}' at index ${index}.`);
2027
+ const validated = result.value;
2028
+ if (!isObject(validated) || typeof validated.type !== 'string') {
2029
+ throw new Error(`Invalid event at index ${index}.`);
2030
2030
  }
2031
- return {
2032
- ...validatedPayload,
2033
- type
2034
- };
2031
+ return validated;
2035
2032
  }));
2036
2033
  }
2037
2034
 
2038
- /** Creates migration and adaptation utilities backed by retained versions of one machine. */
2039
- function machineVersions(machines, options) {
2035
+ /** Creates migration and adaptation utilities for versions of one machine. */
2036
+ function machineVersions(entries, options) {
2040
2037
  const byIdentity = new Map();
2041
- const machineId = machines[0].id;
2042
- for (const machine of machines) {
2043
- if (machine.version === undefined) {
2044
- throw new Error(`Machine '${machine.id}' must define a version.`);
2038
+ const machinesByIdentity = new Map();
2039
+ const machineId = entries[0].id;
2040
+ for (const entry of entries) {
2041
+ if (entry.version === undefined) {
2042
+ throw new Error(`Machine '${entry.id}' must define a version.`);
2045
2043
  }
2046
- if (machine.version === '*') {
2044
+ if (entry.version === '*') {
2047
2045
  throw new Error("Machine version '*' is reserved for wildcard migrations.");
2048
2046
  }
2049
- if (machine.id !== machineId) {
2050
- throw new Error(`Machine '${machine.id}' does not match machine ID '${machineId}'.`);
2047
+ if (entry.id !== machineId) {
2048
+ throw new Error(`Machine '${entry.id}' does not match machine ID '${machineId}'.`);
2051
2049
  }
2052
- const key = `${machine.id}\0${machine.version}`;
2050
+ const key = `${entry.id}\0${entry.version}`;
2053
2051
  if (byIdentity.has(key)) {
2054
- throw new Error(`Duplicate machine identity '${machine.id}' version '${machine.version}'.`);
2052
+ throw new Error(`Duplicate machine identity '${entry.id}' version '${entry.version}'.`);
2053
+ }
2054
+ byIdentity.set(key, entry);
2055
+ if (isVersionedStateMachine(entry)) {
2056
+ machinesByIdentity.set(key, entry);
2055
2057
  }
2056
- byIdentity.set(key, machine);
2057
2058
  }
2058
2059
  if (options?.unversioned !== undefined && !byIdentity.has(`${machineId}\0${options.unversioned}`)) {
2059
2060
  throw new Error(`Unversioned snapshot version '${options.unversioned}' is not retained for machine '${machineId}'.`);
@@ -2087,16 +2088,21 @@ function machineVersions(machines, options) {
2087
2088
  if (raw.version !== undefined && raw.version !== version) {
2088
2089
  throw new Error(`Persisted snapshot version '${raw.version}' conflicts with machine version '${version}'.`);
2089
2090
  }
2090
- const machine = byIdentity.get(`${id}\0${version}`);
2091
- if (!machine) {
2091
+ const source = byIdentity.get(`${id}\0${version}`);
2092
+ if (!source) {
2092
2093
  throw new Error(`Unknown machine identity '${id}' version '${version}'.`);
2093
2094
  }
2094
- const context = await validate(machine.schemas?.context, raw.context, `context for machine '${id}' version '${version}'`);
2095
+ if (!hasSnapshotSchema(source)) {
2096
+ throw new Error(`Machine version '${version}' does not define a snapshot schema.`);
2097
+ }
2098
+ const snapshot = await validate(source.snapshotSchema, raw, `snapshot for machine '${id}' version '${version}'`);
2095
2099
  return {
2096
- machine,
2100
+ source,
2101
+ ...(isVersionedStateMachine(source) && {
2102
+ machine: source
2103
+ }),
2097
2104
  snapshot: {
2098
- ...raw,
2099
- context,
2105
+ ...snapshot,
2100
2106
  machine: {
2101
2107
  id,
2102
2108
  version
@@ -2107,15 +2113,16 @@ function machineVersions(machines, options) {
2107
2113
  return {
2108
2114
  parseSnapshot,
2109
2115
  async adaptEvents(events, adaptationOptions) {
2110
- const target = byIdentity.get(`${machineId}\0${adaptationOptions.to}`);
2116
+ const target = machinesByIdentity.get(`${machineId}\0${adaptationOptions.to}`);
2111
2117
  if (!target) {
2112
- throw new Error(`Target version '${adaptationOptions.to}' is not retained for machine '${machineId}'.`);
2118
+ throw new Error(`Target version '${adaptationOptions.to}' is not backed by a machine for '${machineId}'.`);
2113
2119
  }
2114
2120
  const sourceId = adaptationOptions.from.id ?? machineId;
2115
2121
  const source = byIdentity.get(`${sourceId}\0${adaptationOptions.from.version}`);
2116
2122
  let sourceError;
2117
2123
  let sourceValidationFailed = false;
2118
- if (source) {
2124
+ const hasTypedSource = source && hasEventSchema(source);
2125
+ if (hasTypedSource) {
2119
2126
  let sourceEvents;
2120
2127
  try {
2121
2128
  sourceEvents = await validateEvents(events, source);
@@ -2137,7 +2144,7 @@ function machineVersions(machines, options) {
2137
2144
  if (wildcardAdapter) {
2138
2145
  return validateEvents(await wildcardAdapter(events, adaptationOptions.from), target);
2139
2146
  }
2140
- if (source) {
2147
+ if (hasTypedSource) {
2141
2148
  if (sourceValidationFailed) {
2142
2149
  throw sourceError instanceof Error ? sourceError : new Error(`Unable to validate event history for machine '${source.id}' version '${source.version}'.`, {
2143
2150
  cause: sourceError
@@ -2145,12 +2152,15 @@ function machineVersions(machines, options) {
2145
2152
  }
2146
2153
  throw new Error(`No event adapter from version '${source.version}' to '${target.version}' for machine '${target.id}'.`);
2147
2154
  }
2155
+ if (source) {
2156
+ throw new Error(`Machine version '${source.version}' does not define an event schema; only the '*' adapter can handle its event history.`);
2157
+ }
2148
2158
  throw new Error(`Unknown event history source '${sourceId}' version '${adaptationOptions.from.version}'.`);
2149
2159
  },
2150
2160
  async migrateSnapshot(raw, migrationOptions) {
2151
- const target = byIdentity.get(`${machineId}\0${migrationOptions.to}`);
2161
+ const target = machinesByIdentity.get(`${machineId}\0${migrationOptions.to}`);
2152
2162
  if (!target) {
2153
- throw new Error(`Target version '${migrationOptions.to}' is not retained for machine '${machineId}'.`);
2163
+ throw new Error(`Target version '${migrationOptions.to}' is not backed by a machine for '${machineId}'.`);
2154
2164
  }
2155
2165
  let source;
2156
2166
  let parseError;
@@ -2160,10 +2170,10 @@ function machineVersions(machines, options) {
2160
2170
  parseError = error;
2161
2171
  }
2162
2172
  if (source) {
2163
- if (source.machine.version === target.version) {
2173
+ if (source.source.version === target.version) {
2164
2174
  return finalizeSnapshot(source.snapshot, target);
2165
2175
  }
2166
- const exactMigration = migrationOptions.migrations[source.machine.version];
2176
+ const exactMigration = migrationOptions.migrations[source.source.version];
2167
2177
  if (exactMigration) {
2168
2178
  return finalizeSnapshot(await exactMigration(source.snapshot), target);
2169
2179
  }
@@ -2171,7 +2181,7 @@ function machineVersions(machines, options) {
2171
2181
  const wildcardMigration = migrationOptions.migrations['*'];
2172
2182
  if (!wildcardMigration) {
2173
2183
  if (source) {
2174
- throw new Error(`No snapshot migration from version '${source.machine.version}' to '${target.version}' for machine '${target.id}'.`);
2184
+ throw new Error(`No snapshot migration from version '${source.source.version}' to '${target.version}' for machine '${target.id}'.`);
2175
2185
  }
2176
2186
  throw parseError;
2177
2187
  }
@@ -2633,6 +2643,12 @@ let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
2633
2643
 
2634
2644
  /** A persisted snapshot tied to a versioned actor logic identity. */
2635
2645
 
2646
+ /**
2647
+ * A persisted snapshot restorable into the given actor logic: any snapshot
2648
+ * created by logic with the same machine `id` is accepted, regardless of
2649
+ * version (version mismatches are handled at runtime, e.g. by `migrate`).
2650
+ */
2651
+
2636
2652
  /** @deprecated Use `AnyActor` instead. */
2637
2653
 
2638
2654
  // Based on RxJS types
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var dist_xstateActors = require('./index-3d1368f7.development.cjs.js');
6
6
  var createActor = require('./createActor-c0f78b8a.development.cjs.js');
7
- var StateMachine = require('./StateMachine-144215d2.development.cjs.js');
7
+ var StateMachine = require('./StateMachine-76ee1d6e.development.cjs.js');
8
8
  var transition = require('./transition-4ba58b71.development.cjs.js');
9
9
 
10
10
  /**
@@ -1969,6 +1969,15 @@ function mapState(snapshot, mapper) {
1969
1969
  function isObject(value) {
1970
1970
  return value !== null && typeof value === 'object';
1971
1971
  }
1972
+ function isVersionedStateMachine(entry) {
1973
+ return 'transition' in entry && typeof entry.transition === 'function';
1974
+ }
1975
+ function hasSnapshotSchema(entry) {
1976
+ return 'snapshotSchema' in entry && entry.snapshotSchema !== undefined;
1977
+ }
1978
+ function hasEventSchema(entry) {
1979
+ return 'eventSchema' in entry && entry.eventSchema !== undefined;
1980
+ }
1972
1981
  function getSnapshotSource(raw, defaultId) {
1973
1982
  if (!isObject(raw)) {
1974
1983
  return {};
@@ -1995,65 +2004,57 @@ async function validate(schema, value, description) {
1995
2004
  return result.value;
1996
2005
  }
1997
2006
  async function finalizeSnapshot(snapshot, target) {
1998
- const context = await validate(target.schemas?.context, snapshot.context, `context for machine '${target.id}' version '${target.version}'`);
1999
- return {
2007
+ return await validate(target.snapshotSchema, {
2000
2008
  ...snapshot,
2001
- context,
2002
2009
  machine: {
2003
2010
  id: target.id,
2004
2011
  version: target.version
2005
2012
  },
2006
2013
  version: target.version
2007
- };
2014
+ }, `snapshot for machine '${target.id}' version '${target.version}'`);
2008
2015
  }
2009
- async function validateEvents(events, machine) {
2016
+ async function validateEvents(events, source) {
2010
2017
  return Promise.all(events.map(async (event, index) => {
2011
- if (!isObject(event) || typeof event.type !== 'string') {
2012
- throw new Error(`Invalid event at index ${index}.`);
2013
- }
2014
- const eventSchemas = machine.schemas?.events;
2015
- const isFrameworkEvent = event.type.startsWith('xstate.') || event.type.startsWith('@xstate.');
2016
- const schema = eventSchemas && Object.hasOwn(eventSchemas, event.type) ? eventSchemas[event.type] : undefined;
2017
- if (eventSchemas && !schema && !isFrameworkEvent) {
2018
- throw new Error(`Unknown event '${event.type}' for machine '${machine.id}' version '${machine.version}'.`);
2019
- }
2020
- if (!schema) {
2021
- return event;
2018
+ const result = await source.eventSchema['~standard'].validate(event);
2019
+ if (result.issues) {
2020
+ const message = result.issues[0]?.message;
2021
+ if (message?.startsWith('Unknown event ')) {
2022
+ throw new Error(message);
2023
+ }
2024
+ const type = isObject(event) ? event.type : undefined;
2025
+ throw new Error(typeof type === 'string' ? `Invalid event '${type}' at index ${index}${message ? `: ${message}` : '.'}` : `Invalid event at index ${index}${message ? `: ${message}` : '.'}`);
2022
2026
  }
2023
- const {
2024
- type,
2025
- ...payload
2026
- } = event;
2027
- const validatedPayload = await validate(schema, payload, `event '${type}' at index ${index}`);
2028
- if (!isObject(validatedPayload)) {
2029
- throw new Error(`Invalid event '${type}' at index ${index}.`);
2027
+ const validated = result.value;
2028
+ if (!isObject(validated) || typeof validated.type !== 'string') {
2029
+ throw new Error(`Invalid event at index ${index}.`);
2030
2030
  }
2031
- return {
2032
- ...validatedPayload,
2033
- type
2034
- };
2031
+ return validated;
2035
2032
  }));
2036
2033
  }
2037
2034
 
2038
- /** Creates migration and adaptation utilities backed by retained versions of one machine. */
2039
- function machineVersions(machines, options) {
2035
+ /** Creates migration and adaptation utilities for versions of one machine. */
2036
+ function machineVersions(entries, options) {
2040
2037
  const byIdentity = new Map();
2041
- const machineId = machines[0].id;
2042
- for (const machine of machines) {
2043
- if (machine.version === undefined) {
2044
- throw new Error(`Machine '${machine.id}' must define a version.`);
2038
+ const machinesByIdentity = new Map();
2039
+ const machineId = entries[0].id;
2040
+ for (const entry of entries) {
2041
+ if (entry.version === undefined) {
2042
+ throw new Error(`Machine '${entry.id}' must define a version.`);
2045
2043
  }
2046
- if (machine.version === '*') {
2044
+ if (entry.version === '*') {
2047
2045
  throw new Error("Machine version '*' is reserved for wildcard migrations.");
2048
2046
  }
2049
- if (machine.id !== machineId) {
2050
- throw new Error(`Machine '${machine.id}' does not match machine ID '${machineId}'.`);
2047
+ if (entry.id !== machineId) {
2048
+ throw new Error(`Machine '${entry.id}' does not match machine ID '${machineId}'.`);
2051
2049
  }
2052
- const key = `${machine.id}\0${machine.version}`;
2050
+ const key = `${entry.id}\0${entry.version}`;
2053
2051
  if (byIdentity.has(key)) {
2054
- throw new Error(`Duplicate machine identity '${machine.id}' version '${machine.version}'.`);
2052
+ throw new Error(`Duplicate machine identity '${entry.id}' version '${entry.version}'.`);
2053
+ }
2054
+ byIdentity.set(key, entry);
2055
+ if (isVersionedStateMachine(entry)) {
2056
+ machinesByIdentity.set(key, entry);
2055
2057
  }
2056
- byIdentity.set(key, machine);
2057
2058
  }
2058
2059
  if (options?.unversioned !== undefined && !byIdentity.has(`${machineId}\0${options.unversioned}`)) {
2059
2060
  throw new Error(`Unversioned snapshot version '${options.unversioned}' is not retained for machine '${machineId}'.`);
@@ -2087,16 +2088,21 @@ function machineVersions(machines, options) {
2087
2088
  if (raw.version !== undefined && raw.version !== version) {
2088
2089
  throw new Error(`Persisted snapshot version '${raw.version}' conflicts with machine version '${version}'.`);
2089
2090
  }
2090
- const machine = byIdentity.get(`${id}\0${version}`);
2091
- if (!machine) {
2091
+ const source = byIdentity.get(`${id}\0${version}`);
2092
+ if (!source) {
2092
2093
  throw new Error(`Unknown machine identity '${id}' version '${version}'.`);
2093
2094
  }
2094
- const context = await validate(machine.schemas?.context, raw.context, `context for machine '${id}' version '${version}'`);
2095
+ if (!hasSnapshotSchema(source)) {
2096
+ throw new Error(`Machine version '${version}' does not define a snapshot schema.`);
2097
+ }
2098
+ const snapshot = await validate(source.snapshotSchema, raw, `snapshot for machine '${id}' version '${version}'`);
2095
2099
  return {
2096
- machine,
2100
+ source,
2101
+ ...(isVersionedStateMachine(source) && {
2102
+ machine: source
2103
+ }),
2097
2104
  snapshot: {
2098
- ...raw,
2099
- context,
2105
+ ...snapshot,
2100
2106
  machine: {
2101
2107
  id,
2102
2108
  version
@@ -2107,15 +2113,16 @@ function machineVersions(machines, options) {
2107
2113
  return {
2108
2114
  parseSnapshot,
2109
2115
  async adaptEvents(events, adaptationOptions) {
2110
- const target = byIdentity.get(`${machineId}\0${adaptationOptions.to}`);
2116
+ const target = machinesByIdentity.get(`${machineId}\0${adaptationOptions.to}`);
2111
2117
  if (!target) {
2112
- throw new Error(`Target version '${adaptationOptions.to}' is not retained for machine '${machineId}'.`);
2118
+ throw new Error(`Target version '${adaptationOptions.to}' is not backed by a machine for '${machineId}'.`);
2113
2119
  }
2114
2120
  const sourceId = adaptationOptions.from.id ?? machineId;
2115
2121
  const source = byIdentity.get(`${sourceId}\0${adaptationOptions.from.version}`);
2116
2122
  let sourceError;
2117
2123
  let sourceValidationFailed = false;
2118
- if (source) {
2124
+ const hasTypedSource = source && hasEventSchema(source);
2125
+ if (hasTypedSource) {
2119
2126
  let sourceEvents;
2120
2127
  try {
2121
2128
  sourceEvents = await validateEvents(events, source);
@@ -2137,7 +2144,7 @@ function machineVersions(machines, options) {
2137
2144
  if (wildcardAdapter) {
2138
2145
  return validateEvents(await wildcardAdapter(events, adaptationOptions.from), target);
2139
2146
  }
2140
- if (source) {
2147
+ if (hasTypedSource) {
2141
2148
  if (sourceValidationFailed) {
2142
2149
  throw sourceError instanceof Error ? sourceError : new Error(`Unable to validate event history for machine '${source.id}' version '${source.version}'.`, {
2143
2150
  cause: sourceError
@@ -2145,12 +2152,15 @@ function machineVersions(machines, options) {
2145
2152
  }
2146
2153
  throw new Error(`No event adapter from version '${source.version}' to '${target.version}' for machine '${target.id}'.`);
2147
2154
  }
2155
+ if (source) {
2156
+ throw new Error(`Machine version '${source.version}' does not define an event schema; only the '*' adapter can handle its event history.`);
2157
+ }
2148
2158
  throw new Error(`Unknown event history source '${sourceId}' version '${adaptationOptions.from.version}'.`);
2149
2159
  },
2150
2160
  async migrateSnapshot(raw, migrationOptions) {
2151
- const target = byIdentity.get(`${machineId}\0${migrationOptions.to}`);
2161
+ const target = machinesByIdentity.get(`${machineId}\0${migrationOptions.to}`);
2152
2162
  if (!target) {
2153
- throw new Error(`Target version '${migrationOptions.to}' is not retained for machine '${machineId}'.`);
2163
+ throw new Error(`Target version '${migrationOptions.to}' is not backed by a machine for '${machineId}'.`);
2154
2164
  }
2155
2165
  let source;
2156
2166
  let parseError;
@@ -2160,10 +2170,10 @@ function machineVersions(machines, options) {
2160
2170
  parseError = error;
2161
2171
  }
2162
2172
  if (source) {
2163
- if (source.machine.version === target.version) {
2173
+ if (source.source.version === target.version) {
2164
2174
  return finalizeSnapshot(source.snapshot, target);
2165
2175
  }
2166
- const exactMigration = migrationOptions.migrations[source.machine.version];
2176
+ const exactMigration = migrationOptions.migrations[source.source.version];
2167
2177
  if (exactMigration) {
2168
2178
  return finalizeSnapshot(await exactMigration(source.snapshot), target);
2169
2179
  }
@@ -2171,7 +2181,7 @@ function machineVersions(machines, options) {
2171
2181
  const wildcardMigration = migrationOptions.migrations['*'];
2172
2182
  if (!wildcardMigration) {
2173
2183
  if (source) {
2174
- throw new Error(`No snapshot migration from version '${source.machine.version}' to '${target.version}' for machine '${target.id}'.`);
2184
+ throw new Error(`No snapshot migration from version '${source.source.version}' to '${target.version}' for machine '${target.id}'.`);
2175
2185
  }
2176
2186
  throw parseError;
2177
2187
  }
@@ -2633,6 +2643,12 @@ let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
2633
2643
 
2634
2644
  /** A persisted snapshot tied to a versioned actor logic identity. */
2635
2645
 
2646
+ /**
2647
+ * A persisted snapshot restorable into the given actor logic: any snapshot
2648
+ * created by logic with the same machine `id` is accepted, regardless of
2649
+ * version (version mismatches are handled at runtime, e.g. by `migrate`).
2650
+ */
2651
+
2636
2652
  /** @deprecated Use `AnyActor` instead. */
2637
2653
 
2638
2654
  // Based on RxJS types