@plutoframework/frontend 0.1.1 → 0.1.2
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/README.md +10 -0
- package/dist/react/index.js +4 -1
- package/dist/state/machine.js +18 -9
- package/package.json +16 -11
package/README.md
CHANGED
|
@@ -196,3 +196,13 @@ The one-time npm trusted publisher is scoped to:
|
|
|
196
196
|
The workflow uses GitHub-hosted runners with `id-token: write`; npm exchanges the
|
|
197
197
|
workflow identity for a short-lived publish credential. No `NPM_TOKEN` secret is
|
|
198
198
|
needed. See [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/).
|
|
199
|
+
|
|
200
|
+
## Source readability
|
|
201
|
+
|
|
202
|
+
Development tooling uses ESLint Stylistic with an 80-column expanded convention.
|
|
203
|
+
Run `npm run fmt` to apply the canonical Prettier + ESLint result. `npm run check`
|
|
204
|
+
checks formatting without writing, then lint, types, behavior tests and builds.
|
|
205
|
+
Braces, multiline blocks, separated object/type fields and logical blank lines
|
|
206
|
+
are enforced; nested ternaries require explicit branches or named mappings.
|
|
207
|
+
The policy is visible in `scripts/readability.mjs`. These are dev-only tools and
|
|
208
|
+
add no runtime dependencies to state or React entrypoints.
|
package/dist/react/index.js
CHANGED
|
@@ -3,5 +3,8 @@ import { useSyncExternalStore } from "react";
|
|
|
3
3
|
/** Subscribe only. The host owns the controller's reset/disposal lifecycle. */
|
|
4
4
|
export function useMachine(machine) {
|
|
5
5
|
const state = useSyncExternalStore(machine.subscribe, machine.getSnapshot, machine.getInitialSnapshot);
|
|
6
|
-
return {
|
|
6
|
+
return {
|
|
7
|
+
state,
|
|
8
|
+
send: machine.send,
|
|
9
|
+
};
|
|
7
10
|
}
|
package/dist/state/machine.js
CHANGED
|
@@ -8,21 +8,25 @@ export function createMachine(options) {
|
|
|
8
8
|
const listeners = new Set();
|
|
9
9
|
const executions = new Set();
|
|
10
10
|
function notify() {
|
|
11
|
-
for (const listener of [...listeners])
|
|
11
|
+
for (const listener of [...listeners]) {
|
|
12
12
|
listener();
|
|
13
|
+
}
|
|
13
14
|
}
|
|
14
15
|
function cancel() {
|
|
15
16
|
// Fence callbacks BEFORE synchronous abort handlers can send events.
|
|
16
17
|
epoch++;
|
|
17
|
-
for (const controller of executions)
|
|
18
|
+
for (const controller of executions) {
|
|
18
19
|
controller.abort();
|
|
20
|
+
}
|
|
19
21
|
executions.clear();
|
|
20
22
|
}
|
|
21
23
|
async function send(event) {
|
|
22
|
-
if (disposed)
|
|
24
|
+
if (disposed) {
|
|
23
25
|
return false;
|
|
24
|
-
|
|
26
|
+
}
|
|
27
|
+
if (evaluating) {
|
|
25
28
|
throw new Error("Transitions must not send events");
|
|
29
|
+
}
|
|
26
30
|
const generation = epoch;
|
|
27
31
|
evaluating = true;
|
|
28
32
|
let decision;
|
|
@@ -32,8 +36,9 @@ export function createMachine(options) {
|
|
|
32
36
|
finally {
|
|
33
37
|
evaluating = false;
|
|
34
38
|
}
|
|
35
|
-
if (!decision.accepted)
|
|
39
|
+
if (!decision.accepted) {
|
|
36
40
|
return false;
|
|
41
|
+
}
|
|
37
42
|
if (decision.effect !== undefined && !execute) {
|
|
38
43
|
throw new Error("An effect requires an executor");
|
|
39
44
|
}
|
|
@@ -44,8 +49,9 @@ export function createMachine(options) {
|
|
|
44
49
|
try {
|
|
45
50
|
notify();
|
|
46
51
|
// Subscribers may reset/dispose the flow during notification.
|
|
47
|
-
if (generation !== epoch || disposed)
|
|
52
|
+
if (generation !== epoch || disposed) {
|
|
48
53
|
return true;
|
|
54
|
+
}
|
|
49
55
|
if (decision.effect !== undefined && execute) {
|
|
50
56
|
await execute(decision.effect, {
|
|
51
57
|
signal: controller.signal,
|
|
@@ -68,8 +74,9 @@ export function createMachine(options) {
|
|
|
68
74
|
getSnapshot: () => current,
|
|
69
75
|
getInitialSnapshot: () => initial,
|
|
70
76
|
subscribe(listener) {
|
|
71
|
-
if (disposed)
|
|
77
|
+
if (disposed) {
|
|
72
78
|
return () => { };
|
|
79
|
+
}
|
|
73
80
|
listeners.add(listener);
|
|
74
81
|
return () => {
|
|
75
82
|
listeners.delete(listener);
|
|
@@ -77,15 +84,17 @@ export function createMachine(options) {
|
|
|
77
84
|
},
|
|
78
85
|
send,
|
|
79
86
|
reset() {
|
|
80
|
-
if (disposed)
|
|
87
|
+
if (disposed) {
|
|
81
88
|
return;
|
|
89
|
+
}
|
|
82
90
|
cancel();
|
|
83
91
|
current = initial;
|
|
84
92
|
notify();
|
|
85
93
|
},
|
|
86
94
|
dispose() {
|
|
87
|
-
if (disposed)
|
|
95
|
+
if (disposed) {
|
|
88
96
|
return;
|
|
97
|
+
}
|
|
89
98
|
disposed = true;
|
|
90
99
|
cancel();
|
|
91
100
|
listeners.clear();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plutoframework/frontend",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Explicit, typed frontend state transitions and React subscriptions for Pluto applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,22 +38,27 @@
|
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsc -p tsconfig.build.json",
|
|
41
|
-
"fmt": "
|
|
42
|
-
"check": "
|
|
43
|
-
"test": "vitest run",
|
|
41
|
+
"fmt": "node scripts/format.mjs && eslint .",
|
|
42
|
+
"check": "node scripts/format.mjs --check && eslint . && tsc --noEmit && npm test && npm run build",
|
|
43
|
+
"test": "vitest run && node --test scripts/format.test.mjs",
|
|
44
44
|
"test:mutation": "python3 scripts/mutation.py",
|
|
45
45
|
"prepack": "npm run build"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"react": "19.3.1",
|
|
52
|
-
"react-dom": "19.3.1",
|
|
48
|
+
"@eslint/js": "10.0.1",
|
|
49
|
+
"@stylistic/eslint-plugin": "5.10.0",
|
|
50
|
+
"@testing-library/react": "16.3.3",
|
|
53
51
|
"@types/react": "19.3.0",
|
|
54
52
|
"@types/react-dom": "19.3.0",
|
|
55
|
-
"
|
|
53
|
+
"eslint": "10.13.0",
|
|
54
|
+
"eslint-plugin-react-hooks": "7.1.1",
|
|
55
|
+
"fast-check": "4.10.2",
|
|
56
56
|
"jsdom": "30.1.3",
|
|
57
|
-
"prettier": "3.9.10"
|
|
57
|
+
"prettier": "3.9.10",
|
|
58
|
+
"react": "19.3.1",
|
|
59
|
+
"react-dom": "19.3.1",
|
|
60
|
+
"typescript": "5.9.3",
|
|
61
|
+
"typescript-eslint": "8.72.1",
|
|
62
|
+
"vitest": "5.0.5"
|
|
58
63
|
}
|
|
59
64
|
}
|