snowtransfer 0.18.1 → 0.19.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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
+ # 0.19.0
2
+ Idk why I didn't make 0.18.1 this version number. Anyways, the StateMachine now queues doTransition calls so that ones pushed on the same tick dont go in a confusing order.
3
+ i.e. doTransition from inside of a transition callback.
4
+
1
5
  # 0.18.1
2
- A few bugs I failed to catch last round. Sorry about that.
6
+ Another really big update which started out as some simple bug fixes, but surprisingly non breaking.
3
7
 
4
8
  - Fixed request retries with retryRequests/retryFailed deadlocking the route's rate limit bucket.
5
9
  - The retry was enqueued into the same bucket that was blocked waiting for the retry to finish, so the request promise never settled and every later request on that route hung forever. Retries now free the bucket before re-queueing.
@@ -13,6 +13,10 @@ declare class StateMachine extends EventEmitter<StateMachineEvents> {
13
13
  private editable;
14
14
  private readonly deferredTransitionCreators;
15
15
  private readonly history;
16
+ /** Transitions requested while another transition was still running. Drained in order once the running transition completes. */
17
+ private readonly pendingTransitions;
18
+ /** Whether a transition is currently being executed, making new transition requests queue instead of nesting. */
19
+ private transitioning;
16
20
  /**
17
21
  * Create a new StateMachine
18
22
  * @param currentStateName The state this state machine is currently in. When constructing the StateMachine, this is the entry state.
@@ -65,11 +69,22 @@ declare class StateMachine extends EventEmitter<StateMachineEvents> {
65
69
  * Trigger an event to do a transition from the current state to another as defined previously.
66
70
  *
67
71
  * Will throw an Error if there is no transition from the current state to another based off the event.
72
+ *
73
+ * If called while another transition is still running (from an onLeave/onTransition/onEnter callback or
74
+ * something those callbacks synchronously invoke), the transition is queued and runs once the current one
75
+ * has fully completed, instead of nesting. Nested execution used to corrupt the enter sequence: the outer
76
+ * transition would re-emit "enter" for whatever state the nested transition landed in, re-running that
77
+ * state's onEnter callbacks and cancelling doTransitionLater timers that were still supposed to be pending.
68
78
  * @since 0.16.0
69
79
  * @param event The event that occurred.
70
80
  * @param args Arguments to pass to the callback of the transition's onTransition functions if any.
71
81
  */
72
82
  doTransition(event: string, ...args: any[]): void;
83
+ /**
84
+ * Runs a single transition to completion: onLeave, state change, onTransition, "enter", onEnter.
85
+ * Only ever called from doTransition's drain loop so transitions cannot nest.
86
+ */
87
+ private _transition;
73
88
  /**
74
89
  * Trigger an event to do a transition from the current state to another as defined previously at a later point in time.
75
90
  *
@@ -10,6 +10,10 @@ class StateMachine extends node_events_1.EventEmitter {
10
10
  editable = true;
11
11
  deferredTransitionCreators = [];
12
12
  history = [];
13
+ /** Transitions requested while another transition was still running. Drained in order once the running transition completes. */
14
+ pendingTransitions = [];
15
+ /** Whether a transition is currently being executed, making new transition requests queue instead of nesting. */
16
+ transitioning = false;
13
17
  /**
14
18
  * Create a new StateMachine
15
19
  * @param currentStateName The state this state machine is currently in. When constructing the StateMachine, this is the entry state.
@@ -122,12 +126,38 @@ class StateMachine extends node_events_1.EventEmitter {
122
126
  * Trigger an event to do a transition from the current state to another as defined previously.
123
127
  *
124
128
  * Will throw an Error if there is no transition from the current state to another based off the event.
129
+ *
130
+ * If called while another transition is still running (from an onLeave/onTransition/onEnter callback or
131
+ * something those callbacks synchronously invoke), the transition is queued and runs once the current one
132
+ * has fully completed, instead of nesting. Nested execution used to corrupt the enter sequence: the outer
133
+ * transition would re-emit "enter" for whatever state the nested transition landed in, re-running that
134
+ * state's onEnter callbacks and cancelling doTransitionLater timers that were still supposed to be pending.
125
135
  * @since 0.16.0
126
136
  * @param event The event that occurred.
127
137
  * @param args Arguments to pass to the callback of the transition's onTransition functions if any.
128
138
  */
129
139
  doTransition(event, ...args) {
130
140
  this.guardNotEditable();
141
+ this.pendingTransitions.push({ event, args });
142
+ if (this.transitioning)
143
+ return; // the drain loop below picks it up once the current transition has fully completed
144
+ this.transitioning = true;
145
+ try {
146
+ while (this.pendingTransitions.length) {
147
+ const next = this.pendingTransitions.shift();
148
+ this._transition(next.event, next.args);
149
+ }
150
+ }
151
+ finally {
152
+ this.transitioning = false;
153
+ this.pendingTransitions.length = 0; // if a transition threw, queued followers must not leak into an unrelated later call
154
+ }
155
+ }
156
+ /**
157
+ * Runs a single transition to completion: onLeave, state change, onTransition, "enter", onEnter.
158
+ * Only ever called from doTransition's drain loop so transitions cannot nest.
159
+ */
160
+ _transition(event, args) {
131
161
  const from = this.currentStateName;
132
162
  const currentState = this.states.get(this.currentStateName);
133
163
  const transition = currentState.transitions.get(event);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snowtransfer",
3
- "version": "0.18.1",
3
+ "version": "0.19.0",
4
4
  "description": "Minimalistic Rest client for the Discord Api",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -37,8 +37,8 @@
37
37
  "devDependencies": {
38
38
  "@eslint/js": "^10.0.1",
39
39
  "@types/node": "^26.1.0",
40
- "@typescript-eslint/eslint-plugin": "^8.62.1",
41
- "@typescript-eslint/parser": "^8.62.1",
40
+ "@typescript-eslint/eslint-plugin": "^8.63.0",
41
+ "@typescript-eslint/parser": "^8.63.0",
42
42
  "eslint": "^10.6.0",
43
43
  "globals": "^17.7.0",
44
44
  "typedoc": "^0.28.20",