@defold-typescript/transpiler 0.47.0 → 0.48.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 (2) hide show
  1. package/dist/hsm/index.ts +216 -121
  2. package/package.json +2 -2
package/dist/hsm/index.ts CHANGED
@@ -168,6 +168,22 @@ export type AlwaysSpec<Ctx, To extends string = string> =
168
168
  | AlwaysConfig<Ctx, To>
169
169
  | RuleList<AlwaysConfig<Ctx, To>>;
170
170
 
171
+ /**
172
+ * One entry of the list form of `after`: a `delay` and the `to` its timer leads to.
173
+ * @noSelf
174
+ */
175
+ export interface AfterConfig<Ctx, To extends string = string> {
176
+ /**
177
+ * The delay in seconds of game time: a number, or a function of the context that returns one.
178
+ * A function is read once each time the state is entered, after its `enter` hook, and again on
179
+ * a hot reload, so the delay is fixed for that stay. A result that is not a non-negative number
180
+ * throws, naming the state.
181
+ */
182
+ readonly delay: number | ((ctx: Ctx) => number);
183
+ /** The full path of the state to move to when the delay has passed. */
184
+ readonly to: To;
185
+ }
186
+
171
187
  /**
172
188
  * A state's rules by event `type`. Only the machine's event types are keys, and each rule's
173
189
  * `when` and `run` see the event variant its key names.
@@ -304,11 +320,15 @@ interface StateBase<Ctx, E extends EventObject, T, Self extends string, To exten
304
320
  */
305
321
  readonly on?: NoInfer<OnConfig<Ctx, E, To>>;
306
322
  /**
307
- * Targets by delay in seconds of game time. The delay is counted by `update(dt)` while the
308
- * state is active, from zero on each entry. One `update` call fires at most one timer, and
309
- * none when an `update` hook moved the machine.
323
+ * Timers, in one of two forms: targets by delay in seconds of game time, such as
324
+ * `{ 2: "/idle" }`, or a list of `AfterConfig` entries, such as
325
+ * `[{ delay: (ctx) => ctx.patrolFor, to: "/rest" }]`, whose `delay` is a number or a function
326
+ * of the context. A delay function is read once each time the state is entered, after its
327
+ * `enter` hook, and again on a hot reload. The delay is counted by `update(dt)` while the state
328
+ * is active, from zero on each entry. One `update` call fires at most one timer, and none when
329
+ * an `update` hook moved the machine.
310
330
  */
311
- readonly after?: NoInfer<{ readonly [seconds: number]: To }>;
331
+ readonly after?: NoInfer<{ readonly [seconds: number]: To } | readonly AfterConfig<Ctx, To>[]>;
312
332
  /**
313
333
  * Targets taken right after any move that leaves this state active; the first whose `when` is
314
334
  * missing or passes wins. It is checked after a move only: not after a rule with no `to`, and
@@ -415,6 +435,8 @@ interface Transition<Ctx, E extends EventObject> {
415
435
  readonly run: readonly MoveAction<Ctx, E>[];
416
436
  }
417
437
 
438
+ type Delay<Ctx> = number | ((ctx: Ctx) => number);
439
+
418
440
  interface Compiled<Ctx, E extends EventObject> {
419
441
  count: number;
420
442
  readonly configs: StateConfig<Ctx, E>[];
@@ -431,6 +453,10 @@ interface Compiled<Ctx, E extends EventObject> {
431
453
  readonly transitions: Transition<Ctx, E>[][];
432
454
  readonly afterDelays: number[][];
433
455
  readonly afterTargets: number[][];
456
+ // Set only for a state whose after list holds a delay function: its entries in list order,
457
+ // for each instance to sort once the function is read.
458
+ readonly afterListDelays: (Delay<Ctx>[] | undefined)[];
459
+ readonly afterListTargets: (number[] | undefined)[];
434
460
  readonly always: Transition<Ctx, E>[][];
435
461
  readonly pathIndex: { [path: string]: number };
436
462
  }
@@ -763,6 +789,25 @@ function parseDelay(key: string | number): number {
763
789
  return delay;
764
790
  }
765
791
 
792
+ // NaN fails the comparison, so it is rejected with the negative numbers.
793
+ function checkDelay(path: string, delay: unknown, written: unknown): void {
794
+ if (typeof delay !== "number" || !(delay >= 0)) {
795
+ throw `hsm: state "${describePath(path)}" has an after delay "${written}" that is not a non-negative number`;
796
+ }
797
+ }
798
+
799
+ // Keeps the delays ascending; timers with one delay stay in the order they were added.
800
+ function insertTimer(delays: number[], targets: number[], delay: number, target: number): void {
801
+ let slot = delays.length;
802
+ while (slot > 0 && (delays[slot - 1] as number) > delay) {
803
+ delays[slot] = delays[slot - 1] as number;
804
+ targets[slot] = targets[slot - 1] as number;
805
+ slot--;
806
+ }
807
+ delays[slot] = delay;
808
+ targets[slot] = target;
809
+ }
810
+
766
811
  function compileAfter<Ctx, E extends EventObject>(compiled: Compiled<Ctx, E>, index: number): void {
767
812
  const delays: number[] = [];
768
813
  const targets: number[] = [];
@@ -773,20 +818,39 @@ function compileAfter<Ctx, E extends EventObject>(compiled: Compiled<Ctx, E>, in
773
818
  return;
774
819
  }
775
820
  const path = compiled.paths[index] as string;
776
- for (const key in after) {
777
- const delay = parseDelay(key);
778
- if (!(delay >= 0)) {
779
- throw `hsm: state "${describePath(path)}" has an after delay "${key}" that is not a non-negative number`;
821
+ // Read as an array type: the transpiler shifts an index to Lua's base 1 only on an array.
822
+ const list = after as readonly AfterConfig<Ctx>[];
823
+ if (typeof list[0] !== "object") {
824
+ const byDelay = after as { readonly [seconds: number]: string };
825
+ for (const key in byDelay) {
826
+ const delay = parseDelay(key);
827
+ checkDelay(path, delay, key);
828
+ const target = resolveTarget(compiled, index, byDelay[key as unknown as number] as string);
829
+ insertTimer(delays, targets, delay, target);
780
830
  }
781
- const target = resolveTarget(compiled, index, after[key as unknown as number] as string);
782
- let slot = delays.length;
783
- while (slot > 0 && (delays[slot - 1] as number) > delay) {
784
- delays[slot] = delays[slot - 1] as number;
785
- targets[slot] = targets[slot - 1] as number;
786
- slot--;
831
+ return;
832
+ }
833
+ const listDelays: Delay<Ctx>[] = [];
834
+ const listTargets: number[] = [];
835
+ let perInstance = false;
836
+ for (let i = 0; i < list.length; i++) {
837
+ const entry = list[i] as AfterConfig<Ctx>;
838
+ const delay = entry.delay;
839
+ if (typeof delay === "function") {
840
+ perInstance = true;
841
+ } else {
842
+ checkDelay(path, delay, delay);
787
843
  }
788
- delays[slot] = delay;
789
- targets[slot] = target;
844
+ listDelays[i] = delay;
845
+ listTargets[i] = resolveTarget(compiled, index, entry.to);
846
+ }
847
+ if (perInstance) {
848
+ compiled.afterListDelays[index] = listDelays;
849
+ compiled.afterListTargets[index] = listTargets;
850
+ return;
851
+ }
852
+ for (let i = 0; i < listDelays.length; i++) {
853
+ insertTimer(delays, targets, listDelays[i] as number, listTargets[i] as number);
790
854
  }
791
855
  }
792
856
 
@@ -807,6 +871,8 @@ function compile<Ctx, E extends EventObject>(config: MachineConfig<Ctx, E>): Com
807
871
  transitions: [],
808
872
  afterDelays: [],
809
873
  afterTargets: [],
874
+ afterListDelays: [],
875
+ afterListTargets: [],
810
876
  always: [],
811
877
  pathIndex: {},
812
878
  };
@@ -865,15 +931,16 @@ interface Registered<Ctx, E extends EventObject> {
865
931
 
866
932
  const registered: { [key: string]: Registered<unknown, EventObject> } = {};
867
933
 
868
- // Adds the fields the root's privateCtx returns to ctx. With onlyMissing, a field ctx already
869
- // has keeps its value: a hot reload adds new private fields and leaves the old ones alone.
934
+ // Adds the fields the root's privateCtx returns to ctx; the factory receives target. With
935
+ // onlyMissing, a field ctx already has keeps its value: a hot reload adds new private fields and
936
+ // leaves the old ones alone.
870
937
  function fillPrivate(
871
938
  target: { [name: string]: unknown },
872
939
  root: unknown,
873
940
  onlyMissing: boolean,
874
941
  ): void {
875
- const factory = (root as Partial<PrivateCtxConfig<unknown, object>>).privateCtx;
876
- const fields = (factory?.() || {}) as { [name: string]: unknown };
942
+ const factory = (root as PrivateCtxConfig<unknown, object>).privateCtx;
943
+ const fields = (factory?.(target) || {}) as { [name: string]: unknown };
877
944
  for (const name in fields) {
878
945
  if (!onlyMissing || target[name] === undefined) {
879
946
  target[name] = fields[name];
@@ -899,11 +966,16 @@ function createMachine<Ctx, E extends EventObject>(
899
966
  let transitions = compiled.transitions;
900
967
  let afterDelays = compiled.afterDelays;
901
968
  let afterTargets = compiled.afterTargets;
969
+ let afterListDelays = compiled.afterListDelays;
970
+ let afterListTargets = compiled.afterListTargets;
902
971
  let always = compiled.always;
903
972
  const activeChild: number[] = [];
904
973
  const isActive: boolean[] = [];
905
974
  const elapsed: number[] = [];
906
975
  const fired: number[] = [];
976
+ // The sorted timers of a state whose after list holds a delay function, read on each entry.
977
+ const ownDelays: (number[] | undefined)[] = [];
978
+ const ownTargets: (number[] | undefined)[] = [];
907
979
  const entryId: number[] = [];
908
980
  const cleanup: ((() => void) | undefined)[] = [];
909
981
  // Keyed by path, not index, so a remembered child outlives a rebind's recompilation.
@@ -937,10 +1009,32 @@ function createMachine<Ctx, E extends EventObject>(
937
1009
  isActive[state] = false;
938
1010
  elapsed[state] = 0;
939
1011
  fired[state] = 0;
1012
+ ownDelays[state] = undefined;
1013
+ ownTargets[state] = undefined;
940
1014
  entryId[state] = 0;
941
1015
  cleanup[state] = undefined;
942
1016
  }
943
1017
 
1018
+ function readDelays(state: number): void {
1019
+ const list = afterListDelays[state];
1020
+ if (list === undefined) {
1021
+ return;
1022
+ }
1023
+ const listTargets = afterListTargets[state] as number[];
1024
+ const delays: number[] = [];
1025
+ const targets: number[] = [];
1026
+ for (let i = 0; i < list.length; i++) {
1027
+ let delay = list[i] as Delay<Ctx>;
1028
+ if (typeof delay === "function") {
1029
+ delay = delay(ctx);
1030
+ checkDelay(paths[state] as string, delay, delay);
1031
+ }
1032
+ insertTimer(delays, targets, delay, listTargets[i] as number);
1033
+ }
1034
+ ownDelays[state] = delays;
1035
+ ownTargets[state] = targets;
1036
+ }
1037
+
944
1038
  function growSlots(): void {
945
1039
  while (slotCount < compiled.count) {
946
1040
  clearSlot(slotCount);
@@ -995,6 +1089,8 @@ function createMachine<Ctx, E extends EventObject>(
995
1089
  transitions = compiled.transitions;
996
1090
  afterDelays = compiled.afterDelays;
997
1091
  afterTargets = compiled.afterTargets;
1092
+ afterListDelays = compiled.afterListDelays;
1093
+ afterListTargets = compiled.afterListTargets;
998
1094
  always = compiled.always;
999
1095
  fillPrivate(ctx as never, configs[ROOT], true);
1000
1096
  growSlots();
@@ -1019,6 +1115,7 @@ function createMachine<Ctx, E extends EventObject>(
1019
1115
  fired[state] = keptFired[i] as number;
1020
1116
  entryId[state] = keptEntryId[i] as number;
1021
1117
  cleanup[state] = keptCleanup[i];
1118
+ readDelays(state);
1022
1119
  }
1023
1120
  for (let i = dropped.length - 1; i >= 0; i--) {
1024
1121
  const run = keptCleanup[dropped[i] as number];
@@ -1121,6 +1218,7 @@ function createMachine<Ctx, E extends EventObject>(
1121
1218
  if (hook !== undefined) {
1122
1219
  hook(ctx, instance);
1123
1220
  }
1221
+ readDelays(state);
1124
1222
  const task = config.task;
1125
1223
  if (task !== undefined) {
1126
1224
  // A path, not an index, so a finish held across a rebind still finds its entry.
@@ -1518,17 +1616,12 @@ function createMachine<Ctx, E extends EventObject>(
1518
1616
  if (child !== NO_STATE && fireTimers(child)) {
1519
1617
  return true;
1520
1618
  }
1521
- const delays = afterDelays[state] as number[];
1619
+ const delays = ownDelays[state] || (afterDelays[state] as number[]);
1522
1620
  const next = fired[state] as number;
1523
1621
  if (next < delays.length && (delays[next] as number) <= (elapsed[state] as number)) {
1524
1622
  fired[state] = next + 1;
1525
- transition(
1526
- state,
1527
- (afterTargets[state] as number[])[next] as number,
1528
- undefined,
1529
- undefined,
1530
- "after",
1531
- );
1623
+ const targets = ownTargets[state] || (afterTargets[state] as number[]);
1624
+ transition(state, targets[next] as number, undefined, undefined, "after");
1532
1625
  return true;
1533
1626
  }
1534
1627
  return false;
@@ -1603,6 +1696,11 @@ function define<Ctx, E extends EventObject>(
1603
1696
  return machine;
1604
1697
  }
1605
1698
 
1699
+ // Ctx for a config without privateCtx, Ctx & Priv for one with it. The tuple test keeps the
1700
+ // context whole while Priv has no inference yet, so a generic helper in a slot, such as
1701
+ // `sequence`, still takes its ctx from the slot.
1702
+ type WithPrivate<Ctx, Priv> = [Priv] extends [never] ? Ctx : Ctx & Priv;
1703
+
1606
1704
  // Ctx and E are given explicitly and the config is inferred, so the config takes a second call.
1607
1705
  // A key makes a later definition under it (a hot-reloaded module re-running) rebind live instances.
1608
1706
  /**
@@ -1611,23 +1709,33 @@ function define<Ctx, E extends EventObject>(
1611
1709
  * when that call runs, and a mistake throws, naming the state path. With a key, a later
1612
1710
  * definition under it puts its states into the machine already built, so every running instance
1613
1711
  * sees the edit; without one, each call builds a separate machine.
1712
+ *
1713
+ * The root config may hold `privateCtx`, for a machine that keeps fields of its own, such as a
1714
+ * counter, a heat level or a list it builds up. Every hook, `when`, `run`, `task` and `update`
1715
+ * then sees those fields beside `Ctx`, while `start` takes only `Ctx` and the instance it returns
1716
+ * shows only `Ctx` in its `ctx`. A machine without fields of its own leaves `privateCtx` out.
1614
1717
  */
1615
1718
  export function defineMachine<Ctx, E extends EventObject>(
1616
1719
  key?: string,
1617
- ): <T>(config: RootState<Ctx, E, T>) => Machine<Ctx, E, TreePath<T>> {
1720
+ ): <T, Priv extends object = never>(
1721
+ config: RootState<WithPrivate<Ctx, Priv>, E, T> & PrivateCtxConfig<Ctx, Priv>,
1722
+ ) => Machine<Ctx, E, TreePath<T>> {
1618
1723
  return ((config: MachineConfig<Ctx, E>) => define(key, config)) as never;
1619
1724
  }
1620
1725
 
1621
1726
  /**
1622
- * The key a `definePrivateMachine` config adds to the root, beside `initial` and `states`.
1727
+ * The optional key a `defineMachine` root config takes beside `initial` and `states`.
1623
1728
  * @noSelf
1624
1729
  */
1625
1730
  export interface PrivateCtxConfig<Ctx, Priv> {
1626
1731
  /**
1627
1732
  * Builds the fields only the machine uses. It runs once per `start`, before the root's `enter`
1628
1733
  * hook, so every instance gets fresh fields of its own; a value written straight into the
1629
- * config would be one array or table shared by every instance. It takes no arguments: to set
1630
- * a private field from a field of `Ctx`, do it in the root's `enter` hook.
1734
+ * config would be one array or table shared by every instance. It receives the object passed
1735
+ * to `start`, typed `Ctx`, so a private field can start from a field of `Ctx`:
1736
+ * `privateCtx: (ctx: TurretOptions) => ({ heat: ctx.startHeat })`. Give `ctx` its type; without
1737
+ * one TypeScript can type a hook before it knows the private fields, and that hook reports the
1738
+ * field as missing.
1631
1739
  *
1632
1740
  * The fields are added to the object passed to `start`, which stays the instance's `ctx`, so
1633
1741
  * restarting with `start(old.ctx)` keeps the public fields and builds the private ones fresh.
@@ -1637,94 +1745,81 @@ export interface PrivateCtxConfig<Ctx, Priv> {
1637
1745
  *
1638
1746
  * The fields are hidden from callers by type only. At run time `ctx` is one table, and hooks,
1639
1747
  * `hsm-view` and a debugger see every field.
1748
+ *
1749
+ * There are two ways to type the fields.
1750
+ *
1751
+ * @example
1752
+ * **Inferred.** For a few fields, write them inline and let TypeScript infer their types. Add
1753
+ * `as` where the inferred type is wrong: an empty array is `never[]` until it reads
1754
+ * `[] as Hash[]`, and a field holding one of several strings is any `string` until it reads
1755
+ * `"cool" as "cool" | "hot"`.
1756
+ *
1757
+ * ```ts
1758
+ * type TurretEvent = { type: "SPOTTED" } | { type: "LOST" };
1759
+ *
1760
+ * export const turret = defineMachine<{ readonly fireRate: number }, TurretEvent>("turret")({
1761
+ * privateCtx: () => ({ heat: 0, targets: [] as Hash[] }),
1762
+ * initial: "/idle",
1763
+ * states: {
1764
+ * idle: { on: { SPOTTED: "/firing" } },
1765
+ * firing: {
1766
+ * enter: (ctx) => {
1767
+ * ctx.heat += 1 / ctx.fireRate;
1768
+ * },
1769
+ * on: { LOST: "/idle" },
1770
+ * },
1771
+ * },
1772
+ * });
1773
+ *
1774
+ * const gun = turret.start({ fireRate: 2 }); // gun.ctx shows fireRate only
1775
+ * ```
1776
+ *
1777
+ * @example
1778
+ * **A named type.** For more fields, or when a helper outside the config needs the whole
1779
+ * context, declare the fields as an interface and make it the factory's return type. The
1780
+ * fields need no `as`, a misspelled or unknown field is a compile error, and the whole context
1781
+ * is `TurretOptions & TurretPrivate`. `satisfies TurretPrivate` does not do this: it checks the
1782
+ * object but keeps its narrow types, so an empty array stays `never[]`.
1783
+ *
1784
+ * ```ts
1785
+ * interface TurretOptions {
1786
+ * readonly fireRate: number;
1787
+ * }
1788
+ *
1789
+ * interface TurretPrivate {
1790
+ * heat: number;
1791
+ * mode: "cool" | "hot";
1792
+ * }
1793
+ *
1794
+ * type TurretEvent = { type: "SPOTTED" } | { type: "LOST" };
1795
+ *
1796
+ * const overheated = (ctx: TurretOptions & TurretPrivate) => ctx.heat > ctx.fireRate;
1797
+ *
1798
+ * export const turret = defineMachine<TurretOptions, TurretEvent>("turret")({
1799
+ * privateCtx: (): TurretPrivate => ({ heat: 0, mode: "cool" }),
1800
+ * initial: "/idle",
1801
+ * states: {
1802
+ * idle: { on: { SPOTTED: "/firing" } },
1803
+ * firing: {
1804
+ * enter: (ctx) => {
1805
+ * ctx.heat += 1 / ctx.fireRate;
1806
+ * },
1807
+ * always: { to: "/cooling", when: overheated },
1808
+ * on: { LOST: "/idle" },
1809
+ * },
1810
+ * cooling: {
1811
+ * enter: (ctx) => {
1812
+ * ctx.mode = "hot";
1813
+ * },
1814
+ * exit: (ctx) => {
1815
+ * ctx.heat = 0;
1816
+ * ctx.mode = "cool";
1817
+ * },
1818
+ * after: { 2: "/idle" },
1819
+ * },
1820
+ * },
1821
+ * });
1822
+ * ```
1640
1823
  */
1641
- readonly privateCtx: () => Priv & { readonly [K in keyof Ctx & keyof Priv]: never };
1824
+ readonly privateCtx?: (ctx: Ctx) => Priv & { readonly [K in keyof Ctx & keyof Priv]: never };
1642
1825
  }
1643
-
1644
- /**
1645
- * Like `defineMachine`, for a machine that keeps fields of its own, such as a counter, a heat
1646
- * level or a list it builds up. The config's `privateCtx` returns those fields. Every hook,
1647
- * `when`, `run`, `task` and `update` sees them beside `Ctx`, while `start` takes only `Ctx` and
1648
- * the instance it returns shows only `Ctx` in its `ctx`. A machine without fields of its own
1649
- * uses `defineMachine`.
1650
- *
1651
- * There are two ways to type the fields.
1652
- *
1653
- * @example
1654
- * **Inferred.** For a few fields, write them inline and let TypeScript infer their types. Add
1655
- * `as` where the inferred type is wrong: an empty array is `never[]` until it reads
1656
- * `[] as Hash[]`, and a field holding one of several strings is any `string` until it reads
1657
- * `"cool" as "cool" | "hot"`.
1658
- *
1659
- * ```ts
1660
- * type TurretEvent = { type: "SPOTTED" } | { type: "LOST" };
1661
- *
1662
- * export const turret = definePrivateMachine<{ readonly fireRate: number }, TurretEvent>("turret")({
1663
- * privateCtx: () => ({ heat: 0, targets: [] as Hash[] }),
1664
- * initial: "/idle",
1665
- * states: {
1666
- * idle: { on: { SPOTTED: "/firing" } },
1667
- * firing: {
1668
- * enter: (ctx) => {
1669
- * ctx.heat += 1 / ctx.fireRate;
1670
- * },
1671
- * on: { LOST: "/idle" },
1672
- * },
1673
- * },
1674
- * });
1675
- *
1676
- * const gun = turret.start({ fireRate: 2 }); // gun.ctx shows fireRate only
1677
- * ```
1678
- *
1679
- * @example
1680
- * **A named type.** For more fields, or when a helper outside the config needs the whole
1681
- * context, declare the fields as an interface and make it the factory's return type. The fields
1682
- * need no `as`, a misspelled or unknown field is a compile error, and the whole context is
1683
- * `TurretOptions & TurretPrivate`. `satisfies TurretPrivate` does not do this: it checks the
1684
- * object but keeps its narrow types, so an empty array stays `never[]`.
1685
- *
1686
- * ```ts
1687
- * interface TurretOptions {
1688
- * readonly fireRate: number;
1689
- * }
1690
- *
1691
- * interface TurretPrivate {
1692
- * heat: number;
1693
- * mode: "cool" | "hot";
1694
- * }
1695
- *
1696
- * type TurretEvent = { type: "SPOTTED" } | { type: "LOST" };
1697
- *
1698
- * const overheated = (ctx: TurretOptions & TurretPrivate) => ctx.heat > ctx.fireRate;
1699
- *
1700
- * export const turret = definePrivateMachine<TurretOptions, TurretEvent>("turret")({
1701
- * privateCtx: (): TurretPrivate => ({ heat: 0, mode: "cool" }),
1702
- * initial: "/idle",
1703
- * states: {
1704
- * idle: { on: { SPOTTED: "/firing" } },
1705
- * firing: {
1706
- * enter: (ctx) => {
1707
- * ctx.heat += 1 / ctx.fireRate;
1708
- * },
1709
- * always: { to: "/cooling", when: overheated },
1710
- * on: { LOST: "/idle" },
1711
- * },
1712
- * cooling: {
1713
- * enter: (ctx) => {
1714
- * ctx.mode = "hot";
1715
- * },
1716
- * exit: (ctx) => {
1717
- * ctx.heat = 0;
1718
- * ctx.mode = "cool";
1719
- * },
1720
- * after: { 2: "/idle" },
1721
- * },
1722
- * },
1723
- * });
1724
- * ```
1725
- */
1726
- export const definePrivateMachine: <Ctx, E extends EventObject>(
1727
- key?: string,
1728
- ) => <T, Priv extends object>(
1729
- config: RootState<Ctx & Priv, E, T> & PrivateCtxConfig<Ctx, Priv>,
1730
- ) => Machine<Ctx, E, TreePath<T>> = defineMachine as never;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defold-typescript/transpiler",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "TypeScript-to-Lua build pipeline tuned for Defold's runtime.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -35,7 +35,7 @@
35
35
  "test": "bun test"
36
36
  },
37
37
  "dependencies": {
38
- "@defold-typescript/types": "0.47.0",
38
+ "@defold-typescript/types": "0.48.0",
39
39
  "@typescript-to-lua/language-extensions": "1.19.0",
40
40
  "typescript": "6.0.2",
41
41
  "typescript-to-lua": "^1.36.0"