@xstate/effect 1.0.0-alpha.8 → 1.0.0-beta.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.
@@ -0,0 +1,126 @@
1
+ import { defineRule, definePlugin } from '@oxlint/plugins';
2
+
3
+ const ENQUEUE_NAMES = new Set(['enq', 'enqueue']);
4
+ const EFFECT_LOGIC_CONSTRUCTORS = new Set(['createEffectLogic', 'createEffectStreamLogic', 'createEffectEventStreamLogic']);
5
+ const isNode = value => typeof value === 'object' && value !== null && 'type' in value && typeof value.type === 'string';
6
+ const rootIdentifier = node => {
7
+ let current = node;
8
+ for (;;) {
9
+ if (current.type === 'CallExpression') {
10
+ current = current.callee;
11
+ } else if (current.type === 'MemberExpression') {
12
+ current = current.object;
13
+ } else if (current.type === 'Identifier') {
14
+ return current.name;
15
+ } else {
16
+ return undefined;
17
+ }
18
+ }
19
+ };
20
+ const returnedExpressions = fn => {
21
+ if (fn.body === null) {
22
+ return [];
23
+ }
24
+ if (fn.body.type !== 'BlockStatement') {
25
+ return [fn.body];
26
+ }
27
+ const found = [];
28
+ const visit = node => {
29
+ if (node.type === 'ReturnStatement') {
30
+ if (node.argument) {
31
+ found.push(node.argument);
32
+ }
33
+ return;
34
+ }
35
+ if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression' || node.type === 'FunctionDeclaration') {
36
+ return;
37
+ }
38
+ for (const [key, value] of Object.entries(node)) {
39
+ if (key === 'parent') {
40
+ continue;
41
+ }
42
+ if (Array.isArray(value)) {
43
+ for (const item of value) {
44
+ if (isNode(item)) {
45
+ visit(item);
46
+ }
47
+ }
48
+ } else if (isNode(value)) {
49
+ visit(value);
50
+ }
51
+ }
52
+ };
53
+ visit(fn.body);
54
+ return found;
55
+ };
56
+ const isPromiseResolve = node => node.callee.type === 'MemberExpression' && node.callee.object.type === 'Identifier' && node.callee.object.name === 'Promise' && node.callee.property.type === 'Identifier' && node.callee.property.name === 'resolve';
57
+ const isEffectExpression = node => {
58
+ if (node.type !== 'CallExpression') {
59
+ return false;
60
+ }
61
+ if (isPromiseResolve(node)) {
62
+ const [argument] = node.arguments;
63
+ return argument !== undefined && isEffectExpression(argument);
64
+ }
65
+ return rootIdentifier(node) === 'Effect';
66
+ };
67
+ const isInlineEffectLogic = node => node.type === 'CallExpression' && node.callee.type === 'Identifier' && EFFECT_LOGIC_CONSTRUCTORS.has(node.callee.name);
68
+ const isFunctionNode = node => node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression';
69
+ const noInlineEffect = defineRule({
70
+ create(context) {
71
+ return {
72
+ CallExpression(node) {
73
+ const {
74
+ callee
75
+ } = node;
76
+ if (callee.type === 'MemberExpression' && callee.object.type === 'Identifier' && ENQUEUE_NAMES.has(callee.object.name) && callee.property.type === 'Identifier' && callee.property.name === 'spawn') {
77
+ const [logic] = node.arguments;
78
+ if (logic !== undefined && isInlineEffectLogic(logic)) {
79
+ context.report({
80
+ messageId: 'inlineSpawn',
81
+ node: logic
82
+ });
83
+ }
84
+ return;
85
+ }
86
+ if (callee.type !== 'Identifier' || !ENQUEUE_NAMES.has(callee.name)) {
87
+ return;
88
+ }
89
+ const [action] = node.arguments;
90
+ if (action === undefined || !isFunctionNode(action)) {
91
+ return;
92
+ }
93
+ for (const expression of returnedExpressions(action)) {
94
+ if (isEffectExpression(expression)) {
95
+ context.report({
96
+ messageId: 'inlineAction',
97
+ node: expression
98
+ });
99
+ }
100
+ }
101
+ }
102
+ };
103
+ },
104
+ meta: {
105
+ docs: {
106
+ description: 'Disallow Effects in inline enqueue callbacks and inline Effect logic in enq.spawn; declare them in setupEffect({ actions }) or actors.'
107
+ },
108
+ messages: {
109
+ inlineAction: 'An Effect returned from an inline action is discarded. Declare it in setupEffect({ actions }) and run it with enq(args.actions.name, args).',
110
+ inlineSpawn: 'Inline Effect logic passed to enq.spawn is invisible to RequirementsFrom and rejected at runtime. Declare it in actors and spawn args.actors.name.'
111
+ },
112
+ type: 'problem'
113
+ }
114
+ });
115
+
116
+ /** @experimental */
117
+ var oxlint = definePlugin({
118
+ meta: {
119
+ name: 'xstate-effect'
120
+ },
121
+ rules: {
122
+ 'no-inline-effect': noInlineEffect
123
+ }
124
+ });
125
+
126
+ export { oxlint as default };
@@ -0,0 +1,2 @@
1
+ export * from "./declarations/src/test.js";
2
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieHN0YXRlLWVmZmVjdC10ZXN0LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuL2RlY2xhcmF0aW9ucy9zcmMvdGVzdC5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIn0=
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Sends one mailbox item and awaits its macrostep publication and immediate
3
+ * effect scheduling. Ignored events are acknowledged too. Does not await
4
+ * invoked work, background actions or future timers. Interrupting the waiter
5
+ * detaches its receipt without retracting the event.
6
+ *
7
+ * @experimental
8
+ */
9
+ function sendAndAwait(actor, event) {
10
+ return actor._sendAndAwait(event);
11
+ }
12
+
13
+ export { sendAndAwait };