@almadar/std 1.0.0 → 1.0.9

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 (40) hide show
  1. package/dist/behaviors/async.d.ts +8 -8
  2. package/dist/behaviors/async.js +548 -500
  3. package/dist/behaviors/async.js.map +1 -1
  4. package/dist/behaviors/data-management.d.ts +11 -19
  5. package/dist/behaviors/data-management.js +468 -449
  6. package/dist/behaviors/data-management.js.map +1 -1
  7. package/dist/behaviors/feedback.d.ts +6 -6
  8. package/dist/behaviors/feedback.js +312 -278
  9. package/dist/behaviors/feedback.js.map +1 -1
  10. package/dist/behaviors/game-core.d.ts +11 -12
  11. package/dist/behaviors/game-core.js +357 -406
  12. package/dist/behaviors/game-core.js.map +1 -1
  13. package/dist/behaviors/game-entity.d.ts +13 -14
  14. package/dist/behaviors/game-entity.js +622 -592
  15. package/dist/behaviors/game-entity.js.map +1 -1
  16. package/dist/behaviors/game-ui.d.ts +9 -10
  17. package/dist/behaviors/game-ui.js +522 -459
  18. package/dist/behaviors/game-ui.js.map +1 -1
  19. package/dist/behaviors/index.d.ts +3 -3
  20. package/dist/behaviors/index.js +3876 -3843
  21. package/dist/behaviors/index.js.map +1 -1
  22. package/dist/behaviors/registry.d.ts +14 -24
  23. package/dist/behaviors/registry.js +3868 -3803
  24. package/dist/behaviors/registry.js.map +1 -1
  25. package/dist/behaviors/types.d.ts +14 -138
  26. package/dist/behaviors/types.js +10 -47
  27. package/dist/behaviors/types.js.map +1 -1
  28. package/dist/behaviors/ui-interaction.d.ts +13 -20
  29. package/dist/behaviors/ui-interaction.js +961 -1043
  30. package/dist/behaviors/ui-interaction.js.map +1 -1
  31. package/dist/index.d.ts +44 -11
  32. package/dist/index.js +3913 -3870
  33. package/dist/index.js.map +1 -1
  34. package/dist/modules/index.js +11 -0
  35. package/dist/modules/index.js.map +1 -1
  36. package/dist/modules/str.js +11 -0
  37. package/dist/modules/str.js.map +1 -1
  38. package/dist/registry.js +11 -0
  39. package/dist/registry.js.map +1 -1
  40. package/package.json +3 -2
@@ -1,533 +1,581 @@
1
1
  // behaviors/async.ts
2
2
  var LOADING_BEHAVIOR = {
3
- name: "std/Loading",
4
- category: "async",
3
+ name: "std-loading",
4
+ version: "1.0.0",
5
5
  description: "Loading state management with success/error handling",
6
- suggestedFor: [
7
- "Async data loading",
8
- "API calls",
9
- "Resource fetching",
10
- "Initial page load"
11
- ],
12
- dataEntities: [
6
+ orbitals: [
13
7
  {
14
- name: "LoadingState",
15
- runtime: true,
16
- singleton: true,
17
- fields: [
18
- { name: "isLoading", type: "boolean", default: false },
19
- { name: "error", type: "object", default: null },
20
- { name: "data", type: "object", default: null },
21
- { name: "startTime", type: "number", default: null }
22
- ]
23
- }
24
- ],
25
- stateMachine: {
26
- initial: "Idle",
27
- states: [
28
- { name: "Idle", isInitial: true },
29
- { name: "Loading" },
30
- { name: "Success" },
31
- { name: "Error" }
32
- ],
33
- events: [
34
- { key: "START" },
35
- { key: "SUCCESS" },
36
- { key: "ERROR" },
37
- { key: "RETRY" },
38
- { key: "RESET" }
39
- ],
40
- transitions: [
41
- {
42
- from: "Idle",
43
- to: "Loading",
44
- event: "START",
45
- effects: [
46
- ["set", "@entity.isLoading", true],
47
- ["set", "@entity.error", null],
48
- ["set", "@entity.startTime", ["time/now"]],
49
- ["render", "content", "loading-state", {}]
50
- ]
51
- },
52
- {
53
- from: "Loading",
54
- to: "Success",
55
- event: "SUCCESS",
56
- effects: [
57
- ["set", "@entity.isLoading", false],
58
- ["set", "@entity.data", "@payload.data"]
59
- ]
60
- },
61
- {
62
- from: "Loading",
63
- to: "Error",
64
- event: "ERROR",
65
- effects: [
66
- ["set", "@entity.isLoading", false],
67
- ["set", "@entity.error", "@payload.error"],
68
- ["render", "content", "error-state", {
69
- error: "@entity.error",
70
- onRetry: "RETRY"
71
- }]
72
- ]
73
- },
74
- {
75
- from: "Error",
76
- to: "Loading",
77
- event: "RETRY",
78
- effects: [
79
- ["set", "@entity.isLoading", true],
80
- ["set", "@entity.error", null],
81
- ["set", "@entity.startTime", ["time/now"]],
82
- ["render", "content", "loading-state", {}]
8
+ name: "LoadingOrbital",
9
+ entity: {
10
+ name: "LoadingState",
11
+ persistence: "runtime",
12
+ fields: [
13
+ { name: "id", type: "string", required: true },
14
+ { name: "isLoading", type: "boolean", default: false },
15
+ { name: "error", type: "object", default: null },
16
+ { name: "data", type: "object", default: null },
17
+ { name: "startTime", type: "number", default: null }
83
18
  ]
84
19
  },
85
- {
86
- from: ["Success", "Error"],
87
- to: "Idle",
88
- event: "RESET",
89
- effects: [
90
- ["set", "@entity.isLoading", false],
91
- ["set", "@entity.error", null],
92
- ["set", "@entity.data", null]
93
- ]
94
- }
95
- ]
96
- },
97
- configSchema: {
98
- required: [],
99
- optional: [
100
- { name: "showLoadingAfterMs", type: "number", description: "Delay before showing loading", default: 200 },
101
- { name: "minLoadingMs", type: "number", description: "Minimum loading display time", default: 500 }
102
- ]
103
- }
20
+ traits: [
21
+ {
22
+ name: "Loading",
23
+ linkedEntity: "LoadingState",
24
+ category: "lifecycle",
25
+ stateMachine: {
26
+ states: [
27
+ { name: "Idle", isInitial: true },
28
+ { name: "Loading" },
29
+ { name: "Success" },
30
+ { name: "Error" }
31
+ ],
32
+ events: [
33
+ { key: "START", name: "Start" },
34
+ { key: "SUCCESS", name: "Success" },
35
+ { key: "ERROR", name: "Error" },
36
+ { key: "RETRY", name: "Retry" },
37
+ { key: "RESET", name: "Reset" }
38
+ ],
39
+ transitions: [
40
+ {
41
+ from: "Idle",
42
+ to: "Loading",
43
+ event: "START",
44
+ effects: [
45
+ ["set", "@entity.isLoading", true],
46
+ ["set", "@entity.error", null],
47
+ ["set", "@entity.startTime", ["time/now"]],
48
+ ["render-ui", "content", {
49
+ type: "loading-state"
50
+ }]
51
+ ]
52
+ },
53
+ {
54
+ from: "Loading",
55
+ to: "Success",
56
+ event: "SUCCESS",
57
+ effects: [
58
+ ["set", "@entity.isLoading", false],
59
+ ["set", "@entity.data", "@payload.data"]
60
+ ]
61
+ },
62
+ {
63
+ from: "Loading",
64
+ to: "Error",
65
+ event: "ERROR",
66
+ effects: [
67
+ ["set", "@entity.isLoading", false],
68
+ ["set", "@entity.error", "@payload.error"],
69
+ ["render-ui", "content", {
70
+ type: "error-state",
71
+ message: "@entity.error",
72
+ onRetry: "RETRY"
73
+ }]
74
+ ]
75
+ },
76
+ {
77
+ from: "Error",
78
+ to: "Loading",
79
+ event: "RETRY",
80
+ effects: [
81
+ ["set", "@entity.isLoading", true],
82
+ ["set", "@entity.error", null],
83
+ ["set", "@entity.startTime", ["time/now"]],
84
+ ["render-ui", "content", {
85
+ type: "loading-state"
86
+ }]
87
+ ]
88
+ },
89
+ {
90
+ from: "Success",
91
+ to: "Idle",
92
+ event: "RESET",
93
+ effects: [
94
+ ["set", "@entity.isLoading", false],
95
+ ["set", "@entity.error", null],
96
+ ["set", "@entity.data", null]
97
+ ]
98
+ },
99
+ {
100
+ from: "Error",
101
+ to: "Idle",
102
+ event: "RESET",
103
+ effects: [
104
+ ["set", "@entity.isLoading", false],
105
+ ["set", "@entity.error", null],
106
+ ["set", "@entity.data", null]
107
+ ]
108
+ }
109
+ ]
110
+ }
111
+ }
112
+ ],
113
+ pages: []
114
+ }
115
+ ]
104
116
  };
105
117
  var FETCH_BEHAVIOR = {
106
- name: "std/Fetch",
107
- category: "async",
118
+ name: "std-fetch",
119
+ version: "1.0.0",
108
120
  description: "Data fetching with caching and refresh capabilities",
109
- suggestedFor: [
110
- "API data fetching",
111
- "Entity loading",
112
- "Remote data",
113
- "Cached queries"
114
- ],
115
- dataEntities: [
121
+ orbitals: [
116
122
  {
117
- name: "FetchState",
118
- runtime: true,
119
- singleton: true,
120
- fields: [
121
- { name: "data", type: "object", default: null },
122
- { name: "error", type: "object", default: null },
123
- { name: "isFetching", type: "boolean", default: false },
124
- { name: "lastFetchedAt", type: "number", default: null }
125
- ]
126
- }
127
- ],
128
- stateMachine: {
129
- initial: "Idle",
130
- states: [
131
- { name: "Idle", isInitial: true },
132
- { name: "Fetching" },
133
- { name: "Stale" },
134
- { name: "Fresh" },
135
- { name: "Error" }
136
- ],
137
- events: [
138
- { key: "FETCH" },
139
- { key: "FETCH_SUCCESS" },
140
- { key: "FETCH_ERROR" },
141
- { key: "REFRESH" },
142
- { key: "INVALIDATE" }
143
- ],
144
- transitions: [
145
- {
146
- from: ["Idle", "Stale"],
147
- to: "Fetching",
148
- event: "FETCH",
149
- effects: [
150
- ["set", "@entity.isFetching", true],
151
- ["set", "@entity.error", null]
152
- ]
153
- },
154
- {
155
- from: "Fetching",
156
- to: "Fresh",
157
- event: "FETCH_SUCCESS",
158
- effects: [
159
- ["set", "@entity.isFetching", false],
160
- ["set", "@entity.data", "@payload.data"],
161
- ["set", "@entity.lastFetchedAt", ["time/now"]]
162
- ]
163
- },
164
- {
165
- from: "Fetching",
166
- to: "Error",
167
- event: "FETCH_ERROR",
168
- effects: [
169
- ["set", "@entity.isFetching", false],
170
- ["set", "@entity.error", "@payload.error"]
171
- ]
172
- },
173
- {
174
- from: "Fresh",
175
- to: "Stale",
176
- event: "INVALIDATE",
177
- effects: [
178
- ["set", "@entity.lastFetchedAt", null]
123
+ name: "FetchOrbital",
124
+ entity: {
125
+ name: "FetchState",
126
+ persistence: "runtime",
127
+ fields: [
128
+ { name: "id", type: "string", required: true },
129
+ { name: "data", type: "object", default: null },
130
+ { name: "error", type: "object", default: null },
131
+ { name: "isFetching", type: "boolean", default: false },
132
+ { name: "lastFetchedAt", type: "number", default: null }
179
133
  ]
180
134
  },
181
- {
182
- from: ["Fresh", "Stale", "Error"],
183
- to: "Fetching",
184
- event: "REFRESH",
185
- effects: [
186
- ["set", "@entity.isFetching", true],
187
- ["set", "@entity.error", null]
188
- ]
189
- }
190
- ]
191
- },
192
- configSchema: {
193
- required: [
194
- { name: "entity", type: "entity", description: "Entity type to fetch" }
195
- ],
196
- optional: [
197
- { name: "staleTimeMs", type: "number", description: "Time until data is stale", default: 6e4 },
198
- { name: "cacheKey", type: "string", description: "Cache key for deduplication" }
199
- ]
200
- }
135
+ traits: [
136
+ {
137
+ name: "Fetch",
138
+ linkedEntity: "FetchState",
139
+ category: "lifecycle",
140
+ stateMachine: {
141
+ states: [
142
+ { name: "Idle", isInitial: true },
143
+ { name: "Fetching" },
144
+ { name: "Stale" },
145
+ { name: "Fresh" },
146
+ { name: "Error" }
147
+ ],
148
+ events: [
149
+ { key: "FETCH", name: "Fetch" },
150
+ { key: "FETCH_SUCCESS", name: "Fetch Success" },
151
+ { key: "FETCH_ERROR", name: "Fetch Error" },
152
+ { key: "REFRESH", name: "Refresh" },
153
+ { key: "INVALIDATE", name: "Invalidate" }
154
+ ],
155
+ transitions: [
156
+ {
157
+ from: "Idle",
158
+ to: "Fetching",
159
+ event: "FETCH",
160
+ effects: [
161
+ ["set", "@entity.isFetching", true],
162
+ ["set", "@entity.error", null]
163
+ ]
164
+ },
165
+ {
166
+ from: "Stale",
167
+ to: "Fetching",
168
+ event: "FETCH",
169
+ effects: [
170
+ ["set", "@entity.isFetching", true],
171
+ ["set", "@entity.error", null]
172
+ ]
173
+ },
174
+ {
175
+ from: "Fetching",
176
+ to: "Fresh",
177
+ event: "FETCH_SUCCESS",
178
+ effects: [
179
+ ["set", "@entity.isFetching", false],
180
+ ["set", "@entity.data", "@payload.data"],
181
+ ["set", "@entity.lastFetchedAt", ["time/now"]]
182
+ ]
183
+ },
184
+ {
185
+ from: "Fetching",
186
+ to: "Error",
187
+ event: "FETCH_ERROR",
188
+ effects: [
189
+ ["set", "@entity.isFetching", false],
190
+ ["set", "@entity.error", "@payload.error"]
191
+ ]
192
+ },
193
+ {
194
+ from: "Fresh",
195
+ to: "Stale",
196
+ event: "INVALIDATE",
197
+ effects: [["set", "@entity.lastFetchedAt", null]]
198
+ },
199
+ {
200
+ from: "Fresh",
201
+ to: "Fetching",
202
+ event: "REFRESH",
203
+ effects: [
204
+ ["set", "@entity.isFetching", true],
205
+ ["set", "@entity.error", null]
206
+ ]
207
+ },
208
+ {
209
+ from: "Stale",
210
+ to: "Fetching",
211
+ event: "REFRESH",
212
+ effects: [
213
+ ["set", "@entity.isFetching", true],
214
+ ["set", "@entity.error", null]
215
+ ]
216
+ },
217
+ {
218
+ from: "Error",
219
+ to: "Fetching",
220
+ event: "REFRESH",
221
+ effects: [
222
+ ["set", "@entity.isFetching", true],
223
+ ["set", "@entity.error", null]
224
+ ]
225
+ }
226
+ ]
227
+ }
228
+ }
229
+ ],
230
+ pages: []
231
+ }
232
+ ]
201
233
  };
202
234
  var SUBMIT_BEHAVIOR = {
203
- name: "std/Submit",
204
- category: "async",
235
+ name: "std-submit",
236
+ version: "1.0.0",
205
237
  description: "Async submission with retry capabilities",
206
- suggestedFor: [
207
- "Form submission",
208
- "Data saving",
209
- "API mutations",
210
- "Actions with confirmation"
211
- ],
212
- dataEntities: [
238
+ orbitals: [
213
239
  {
214
- name: "SubmitState",
215
- runtime: true,
216
- singleton: true,
217
- fields: [
218
- { name: "isSubmitting", type: "boolean", default: false },
219
- { name: "error", type: "object", default: null },
220
- { name: "lastSubmittedData", type: "object", default: null }
221
- ]
222
- }
223
- ],
224
- stateMachine: {
225
- initial: "Idle",
226
- states: [
227
- { name: "Idle", isInitial: true },
228
- { name: "Submitting" },
229
- { name: "Success" },
230
- { name: "Error" }
231
- ],
232
- events: [
233
- { key: "SUBMIT" },
234
- { key: "SUBMIT_SUCCESS" },
235
- { key: "SUBMIT_ERROR" },
236
- { key: "RETRY" },
237
- { key: "RESET" }
238
- ],
239
- transitions: [
240
- {
241
- from: "Idle",
242
- to: "Submitting",
243
- event: "SUBMIT",
244
- effects: [
245
- ["set", "@entity.isSubmitting", true],
246
- ["set", "@entity.error", null],
247
- ["set", "@entity.lastSubmittedData", "@payload.data"]
240
+ name: "SubmitOrbital",
241
+ entity: {
242
+ name: "SubmitState",
243
+ persistence: "runtime",
244
+ fields: [
245
+ { name: "id", type: "string", required: true },
246
+ { name: "isSubmitting", type: "boolean", default: false },
247
+ { name: "error", type: "object", default: null },
248
+ { name: "lastSubmittedData", type: "object", default: null },
249
+ { name: "successMessage", type: "string", default: "Submitted successfully" },
250
+ { name: "errorMessage", type: "string", default: "Submission failed" },
251
+ { name: "resetOnSuccess", type: "boolean", default: false }
248
252
  ]
249
253
  },
250
- {
251
- from: "Submitting",
252
- to: "Success",
253
- event: "SUBMIT_SUCCESS",
254
- effects: [
255
- ["set", "@entity.isSubmitting", false],
256
- ["notify", { type: "success", message: "@config.successMessage" }],
257
- ["when", "@config.resetOnSuccess", ["emit", "RESET"]]
258
- ]
259
- },
260
- {
261
- from: "Submitting",
262
- to: "Error",
263
- event: "SUBMIT_ERROR",
264
- effects: [
265
- ["set", "@entity.isSubmitting", false],
266
- ["set", "@entity.error", "@payload.error"],
267
- ["notify", { type: "error", message: "@config.errorMessage" }]
268
- ]
269
- },
270
- {
271
- from: "Error",
272
- to: "Submitting",
273
- event: "RETRY",
274
- effects: [
275
- ["set", "@entity.isSubmitting", true],
276
- ["set", "@entity.error", null]
277
- ]
278
- },
279
- {
280
- from: ["Success", "Error"],
281
- to: "Idle",
282
- event: "RESET",
283
- effects: [
284
- ["set", "@entity.isSubmitting", false],
285
- ["set", "@entity.error", null],
286
- ["set", "@entity.lastSubmittedData", null]
287
- ]
288
- }
289
- ]
290
- },
291
- configSchema: {
292
- required: [],
293
- optional: [
294
- { name: "successMessage", type: "string", description: "Success notification", default: "Saved successfully" },
295
- { name: "errorMessage", type: "string", description: "Error notification", default: "Failed to save" },
296
- { name: "resetOnSuccess", type: "boolean", description: "Reset to idle on success", default: false }
297
- ]
298
- }
254
+ traits: [
255
+ {
256
+ name: "Submit",
257
+ linkedEntity: "SubmitState",
258
+ category: "lifecycle",
259
+ stateMachine: {
260
+ states: [
261
+ { name: "Idle", isInitial: true },
262
+ { name: "Submitting" },
263
+ { name: "Success" },
264
+ { name: "Error" }
265
+ ],
266
+ events: [
267
+ { key: "SUBMIT", name: "Submit" },
268
+ { key: "SUBMIT_SUCCESS", name: "Submit Success" },
269
+ { key: "SUBMIT_ERROR", name: "Submit Error" },
270
+ { key: "RETRY", name: "Retry" },
271
+ { key: "RESET", name: "Reset" }
272
+ ],
273
+ transitions: [
274
+ {
275
+ from: "Idle",
276
+ to: "Submitting",
277
+ event: "SUBMIT",
278
+ effects: [
279
+ ["set", "@entity.isSubmitting", true],
280
+ ["set", "@entity.error", null],
281
+ ["set", "@entity.lastSubmittedData", "@payload.data"]
282
+ ]
283
+ },
284
+ {
285
+ from: "Submitting",
286
+ to: "Success",
287
+ event: "SUBMIT_SUCCESS",
288
+ effects: [
289
+ ["set", "@entity.isSubmitting", false],
290
+ ["notify", "in_app", "@entity.successMessage"],
291
+ ["when", "@entity.resetOnSuccess", ["emit", "RESET"]]
292
+ ]
293
+ },
294
+ {
295
+ from: "Submitting",
296
+ to: "Error",
297
+ event: "SUBMIT_ERROR",
298
+ effects: [
299
+ ["set", "@entity.isSubmitting", false],
300
+ ["set", "@entity.error", "@payload.error"],
301
+ ["notify", "in_app", "@entity.errorMessage"]
302
+ ]
303
+ },
304
+ {
305
+ from: "Error",
306
+ to: "Submitting",
307
+ event: "RETRY",
308
+ effects: [
309
+ ["set", "@entity.isSubmitting", true],
310
+ ["set", "@entity.error", null]
311
+ ]
312
+ },
313
+ {
314
+ from: "Success",
315
+ to: "Idle",
316
+ event: "RESET",
317
+ effects: [
318
+ ["set", "@entity.isSubmitting", false],
319
+ ["set", "@entity.error", null],
320
+ ["set", "@entity.lastSubmittedData", null]
321
+ ]
322
+ },
323
+ {
324
+ from: "Error",
325
+ to: "Idle",
326
+ event: "RESET",
327
+ effects: [
328
+ ["set", "@entity.isSubmitting", false],
329
+ ["set", "@entity.error", null],
330
+ ["set", "@entity.lastSubmittedData", null]
331
+ ]
332
+ }
333
+ ]
334
+ }
335
+ }
336
+ ],
337
+ pages: []
338
+ }
339
+ ]
299
340
  };
300
341
  var RETRY_BEHAVIOR = {
301
- name: "std/Retry",
302
- category: "async",
342
+ name: "std-retry",
343
+ version: "1.0.0",
303
344
  description: "Automatic retry with exponential backoff",
304
- suggestedFor: [
305
- "Network requests",
306
- "Unreliable operations",
307
- "Transient failures",
308
- "Recovery logic"
309
- ],
310
- dataEntities: [
345
+ orbitals: [
311
346
  {
312
- name: "RetryState",
313
- runtime: true,
314
- singleton: true,
315
- fields: [
316
- { name: "attempt", type: "number", default: 0 },
317
- { name: "error", type: "object", default: null },
318
- { name: "nextRetryAt", type: "number", default: null }
319
- ]
320
- }
321
- ],
322
- stateMachine: {
323
- initial: "Idle",
324
- states: [
325
- { name: "Idle", isInitial: true },
326
- { name: "Attempting" },
327
- { name: "Waiting" },
328
- { name: "Success" },
329
- { name: "Failed" }
330
- ],
331
- events: [
332
- { key: "START" },
333
- { key: "ATTEMPT_SUCCESS" },
334
- { key: "ATTEMPT_ERROR" },
335
- { key: "RETRY_TICK" },
336
- { key: "GIVE_UP" },
337
- { key: "RESET" }
338
- ],
339
- transitions: [
340
- {
341
- from: "Idle",
342
- to: "Attempting",
343
- event: "START",
344
- effects: [
345
- ["set", "@entity.attempt", 1],
346
- ["set", "@entity.error", null]
347
- ]
348
- },
349
- {
350
- from: "Attempting",
351
- to: "Success",
352
- event: "ATTEMPT_SUCCESS",
353
- effects: []
354
- },
355
- {
356
- from: "Attempting",
357
- to: "Waiting",
358
- event: "ATTEMPT_ERROR",
359
- guard: ["<", "@entity.attempt", "@config.maxAttempts"],
360
- effects: [
361
- ["set", "@entity.error", "@payload.error"],
362
- [
363
- "let",
364
- [["delay", [
365
- "math/min",
366
- ["*", "@config.initialDelayMs", ["math/pow", "@config.backoffMultiplier", "@entity.attempt"]],
367
- "@config.maxDelayMs"
368
- ]]],
369
- ["set", "@entity.nextRetryAt", ["+", ["time/now"], "@delay"]],
370
- ["async/delay", "@delay", ["emit", "RETRY_TICK"]]
371
- ]
372
- ]
373
- },
374
- {
375
- from: "Attempting",
376
- to: "Failed",
377
- event: "ATTEMPT_ERROR",
378
- guard: [">=", "@entity.attempt", "@config.maxAttempts"],
379
- effects: [
380
- ["set", "@entity.error", "@payload.error"],
381
- ["notify", { type: "error", message: "All retry attempts failed" }]
347
+ name: "RetryOrbital",
348
+ entity: {
349
+ name: "RetryState",
350
+ persistence: "runtime",
351
+ fields: [
352
+ { name: "id", type: "string", required: true },
353
+ { name: "attempt", type: "number", default: 0 },
354
+ { name: "error", type: "object", default: null },
355
+ { name: "nextRetryAt", type: "number", default: null },
356
+ { name: "maxAttempts", type: "number", default: 3 },
357
+ { name: "initialDelayMs", type: "number", default: 1e3 },
358
+ { name: "backoffMultiplier", type: "number", default: 2 },
359
+ { name: "maxDelayMs", type: "number", default: 3e4 }
382
360
  ]
383
361
  },
384
- {
385
- from: "Waiting",
386
- to: "Attempting",
387
- event: "RETRY_TICK",
388
- effects: [
389
- ["set", "@entity.attempt", ["+", "@entity.attempt", 1]]
390
- ]
391
- },
392
- {
393
- from: "Waiting",
394
- to: "Failed",
395
- event: "GIVE_UP",
396
- effects: [
397
- ["notify", { type: "warning", message: "Retry cancelled" }]
398
- ]
399
- },
400
- {
401
- from: ["Success", "Failed"],
402
- to: "Idle",
403
- event: "RESET",
404
- effects: [
405
- ["set", "@entity.attempt", 0],
406
- ["set", "@entity.error", null],
407
- ["set", "@entity.nextRetryAt", null]
408
- ]
409
- }
410
- ]
411
- },
412
- configSchema: {
413
- required: [],
414
- optional: [
415
- { name: "maxAttempts", type: "number", description: "Maximum retry attempts", default: 3 },
416
- { name: "initialDelayMs", type: "number", description: "Initial retry delay", default: 1e3 },
417
- { name: "maxDelayMs", type: "number", description: "Maximum retry delay", default: 3e4 },
418
- { name: "backoffMultiplier", type: "number", description: "Backoff multiplier", default: 2 }
419
- ]
420
- }
362
+ traits: [
363
+ {
364
+ name: "Retry",
365
+ linkedEntity: "RetryState",
366
+ category: "lifecycle",
367
+ stateMachine: {
368
+ states: [
369
+ { name: "Idle", isInitial: true },
370
+ { name: "Attempting" },
371
+ { name: "Waiting" },
372
+ { name: "Success", isTerminal: true },
373
+ { name: "Failed", isTerminal: true }
374
+ ],
375
+ events: [
376
+ { key: "START", name: "Start" },
377
+ { key: "ATTEMPT_SUCCESS", name: "Attempt Success" },
378
+ { key: "ATTEMPT_ERROR", name: "Attempt Error" },
379
+ { key: "RETRY_TICK", name: "Retry Tick" },
380
+ { key: "GIVE_UP", name: "Give Up" },
381
+ { key: "RESET", name: "Reset" }
382
+ ],
383
+ transitions: [
384
+ {
385
+ from: "Idle",
386
+ to: "Attempting",
387
+ event: "START",
388
+ effects: [
389
+ ["set", "@entity.attempt", 1],
390
+ ["set", "@entity.error", null]
391
+ ]
392
+ },
393
+ {
394
+ from: "Attempting",
395
+ to: "Success",
396
+ event: "ATTEMPT_SUCCESS",
397
+ effects: []
398
+ },
399
+ {
400
+ from: "Attempting",
401
+ to: "Waiting",
402
+ event: "ATTEMPT_ERROR",
403
+ guard: ["<", "@entity.attempt", "@entity.maxAttempts"],
404
+ effects: [
405
+ ["set", "@entity.error", "@payload.error"],
406
+ [
407
+ "let",
408
+ [["delay", [
409
+ "math/min",
410
+ ["*", "@entity.initialDelayMs", ["math/pow", "@entity.backoffMultiplier", "@entity.attempt"]],
411
+ "@entity.maxDelayMs"
412
+ ]]],
413
+ ["set", "@entity.nextRetryAt", ["+", ["time/now"], "@delay"]],
414
+ ["async/delay", "@delay", ["emit", "RETRY_TICK"]]
415
+ ]
416
+ ]
417
+ },
418
+ {
419
+ from: "Attempting",
420
+ to: "Failed",
421
+ event: "ATTEMPT_ERROR",
422
+ guard: [">=", "@entity.attempt", "@entity.maxAttempts"],
423
+ effects: [
424
+ ["set", "@entity.error", "@payload.error"],
425
+ ["notify", "in_app", "All retry attempts failed"]
426
+ ]
427
+ },
428
+ {
429
+ from: "Waiting",
430
+ to: "Attempting",
431
+ event: "RETRY_TICK",
432
+ effects: [["set", "@entity.attempt", ["+", "@entity.attempt", 1]]]
433
+ },
434
+ {
435
+ from: "Waiting",
436
+ to: "Failed",
437
+ event: "GIVE_UP",
438
+ effects: [["notify", "in_app", "Retry cancelled"]]
439
+ },
440
+ {
441
+ from: "Success",
442
+ to: "Idle",
443
+ event: "RESET",
444
+ effects: [
445
+ ["set", "@entity.attempt", 0],
446
+ ["set", "@entity.error", null],
447
+ ["set", "@entity.nextRetryAt", null]
448
+ ]
449
+ },
450
+ {
451
+ from: "Failed",
452
+ to: "Idle",
453
+ event: "RESET",
454
+ effects: [
455
+ ["set", "@entity.attempt", 0],
456
+ ["set", "@entity.error", null],
457
+ ["set", "@entity.nextRetryAt", null]
458
+ ]
459
+ }
460
+ ]
461
+ }
462
+ }
463
+ ],
464
+ pages: []
465
+ }
466
+ ]
421
467
  };
422
468
  var POLL_BEHAVIOR = {
423
- name: "std/Poll",
424
- category: "async",
469
+ name: "std-poll",
470
+ version: "1.0.0",
425
471
  description: "Periodic polling with start/stop control",
426
- suggestedFor: [
427
- "Real-time updates",
428
- "Status checking",
429
- "Live data",
430
- "Notification polling"
431
- ],
432
- dataEntities: [
472
+ orbitals: [
433
473
  {
434
- name: "PollState",
435
- runtime: true,
436
- singleton: true,
437
- fields: [
438
- { name: "isPolling", type: "boolean", default: false },
439
- { name: "pollCount", type: "number", default: 0 },
440
- { name: "lastPollAt", type: "number", default: null },
441
- { name: "error", type: "object", default: null }
442
- ]
443
- }
444
- ],
445
- stateMachine: {
446
- initial: "Stopped",
447
- states: [
448
- { name: "Stopped", isInitial: true },
449
- { name: "Polling" },
450
- { name: "Paused" }
451
- ],
452
- events: [
453
- { key: "START" },
454
- { key: "STOP" },
455
- { key: "PAUSE" },
456
- { key: "RESUME" },
457
- { key: "POLL_TICK" },
458
- { key: "POLL_SUCCESS" },
459
- { key: "POLL_ERROR" }
460
- ],
461
- transitions: [
462
- {
463
- from: "Stopped",
464
- to: "Polling",
465
- event: "START",
466
- effects: [
467
- ["set", "@entity.isPolling", true],
468
- ["set", "@entity.pollCount", 0],
469
- ["async/interval", "@config.intervalMs", ["emit", "POLL_TICK"]]
470
- ]
471
- },
472
- {
473
- from: "Polling",
474
- event: "POLL_TICK",
475
- guard: ["or", ["=", "@config.maxPolls", null], ["<", "@entity.pollCount", "@config.maxPolls"]],
476
- effects: [
477
- ["set", "@entity.lastPollAt", ["time/now"]]
478
- ]
479
- },
480
- {
481
- from: "Polling",
482
- event: "POLL_SUCCESS",
483
- effects: [
484
- ["set", "@entity.pollCount", ["+", "@entity.pollCount", 1]],
485
- ["set", "@entity.error", null]
486
- ]
487
- },
488
- {
489
- from: "Polling",
490
- event: "POLL_ERROR",
491
- effects: [
492
- ["set", "@entity.error", "@payload.error"],
493
- ["when", "@config.stopOnError", ["emit", "STOP"]]
474
+ name: "PollOrbital",
475
+ entity: {
476
+ name: "PollState",
477
+ persistence: "runtime",
478
+ fields: [
479
+ { name: "id", type: "string", required: true },
480
+ { name: "isPolling", type: "boolean", default: false },
481
+ { name: "pollCount", type: "number", default: 0 },
482
+ { name: "lastPollAt", type: "number", default: null },
483
+ { name: "error", type: "object", default: null },
484
+ { name: "intervalMs", type: "number", default: 5e3 },
485
+ { name: "maxPolls", type: "number", default: null },
486
+ { name: "stopOnError", type: "boolean", default: false }
494
487
  ]
495
488
  },
496
- {
497
- from: "Polling",
498
- to: "Paused",
499
- event: "PAUSE",
500
- effects: [
501
- ["set", "@entity.isPolling", false]
502
- ]
503
- },
504
- {
505
- from: "Paused",
506
- to: "Polling",
507
- event: "RESUME",
508
- effects: [
509
- ["set", "@entity.isPolling", true],
510
- ["async/interval", "@config.intervalMs", ["emit", "POLL_TICK"]]
511
- ]
512
- },
513
- {
514
- from: ["Polling", "Paused"],
515
- to: "Stopped",
516
- event: "STOP",
517
- effects: [
518
- ["set", "@entity.isPolling", false]
519
- ]
520
- }
521
- ]
522
- },
523
- configSchema: {
524
- required: [],
525
- optional: [
526
- { name: "intervalMs", type: "number", description: "Poll interval in ms", default: 5e3 },
527
- { name: "stopOnError", type: "boolean", description: "Stop polling on error", default: false },
528
- { name: "maxPolls", type: "number", description: "Maximum poll count (null = infinite)", default: null }
529
- ]
530
- }
489
+ traits: [
490
+ {
491
+ name: "Poll",
492
+ linkedEntity: "PollState",
493
+ category: "lifecycle",
494
+ stateMachine: {
495
+ states: [
496
+ { name: "Stopped", isInitial: true },
497
+ { name: "Polling" },
498
+ { name: "Paused" }
499
+ ],
500
+ events: [
501
+ { key: "START", name: "Start" },
502
+ { key: "STOP", name: "Stop" },
503
+ { key: "PAUSE", name: "Pause" },
504
+ { key: "RESUME", name: "Resume" },
505
+ { key: "POLL_TICK", name: "Poll Tick" },
506
+ { key: "POLL_SUCCESS", name: "Poll Success" },
507
+ { key: "POLL_ERROR", name: "Poll Error" }
508
+ ],
509
+ transitions: [
510
+ {
511
+ from: "Stopped",
512
+ to: "Polling",
513
+ event: "START",
514
+ effects: [
515
+ ["set", "@entity.isPolling", true],
516
+ ["set", "@entity.pollCount", 0],
517
+ ["async/interval", "@entity.intervalMs", ["emit", "POLL_TICK"]]
518
+ ]
519
+ },
520
+ {
521
+ from: "Polling",
522
+ to: "Polling",
523
+ event: "POLL_TICK",
524
+ guard: ["or", ["=", "@entity.maxPolls", null], ["<", "@entity.pollCount", "@entity.maxPolls"]],
525
+ effects: [["set", "@entity.lastPollAt", ["time/now"]]]
526
+ },
527
+ {
528
+ from: "Polling",
529
+ to: "Polling",
530
+ event: "POLL_SUCCESS",
531
+ effects: [
532
+ ["set", "@entity.pollCount", ["+", "@entity.pollCount", 1]],
533
+ ["set", "@entity.error", null]
534
+ ]
535
+ },
536
+ {
537
+ from: "Polling",
538
+ to: "Polling",
539
+ event: "POLL_ERROR",
540
+ effects: [
541
+ ["set", "@entity.error", "@payload.error"],
542
+ ["when", "@entity.stopOnError", ["emit", "STOP"]]
543
+ ]
544
+ },
545
+ {
546
+ from: "Polling",
547
+ to: "Paused",
548
+ event: "PAUSE",
549
+ effects: [["set", "@entity.isPolling", false]]
550
+ },
551
+ {
552
+ from: "Paused",
553
+ to: "Polling",
554
+ event: "RESUME",
555
+ effects: [
556
+ ["set", "@entity.isPolling", true],
557
+ ["async/interval", "@entity.intervalMs", ["emit", "POLL_TICK"]]
558
+ ]
559
+ },
560
+ {
561
+ from: "Polling",
562
+ to: "Stopped",
563
+ event: "STOP",
564
+ effects: [["set", "@entity.isPolling", false]]
565
+ },
566
+ {
567
+ from: "Paused",
568
+ to: "Stopped",
569
+ event: "STOP",
570
+ effects: [["set", "@entity.isPolling", false]]
571
+ }
572
+ ]
573
+ }
574
+ }
575
+ ],
576
+ pages: []
577
+ }
578
+ ]
531
579
  };
532
580
  var ASYNC_BEHAVIORS = [
533
581
  LOADING_BEHAVIOR,