@ersbeth/picoflow 0.0.1

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 (90) hide show
  1. package/.vscode/settings.json +5 -0
  2. package/README.md +151 -0
  3. package/api/doc/index.md +31 -0
  4. package/api/doc/picoflow.derivation.md +55 -0
  5. package/api/doc/picoflow.effect.md +55 -0
  6. package/api/doc/picoflow.flowderivation._constructor_.md +49 -0
  7. package/api/doc/picoflow.flowderivation.get.md +23 -0
  8. package/api/doc/picoflow.flowderivation.md +86 -0
  9. package/api/doc/picoflow.flowdisposer.md +13 -0
  10. package/api/doc/picoflow.floweffect._constructor_.md +49 -0
  11. package/api/doc/picoflow.floweffect.dispose.md +21 -0
  12. package/api/doc/picoflow.floweffect.disposed.md +13 -0
  13. package/api/doc/picoflow.floweffect.md +131 -0
  14. package/api/doc/picoflow.flowgetter.md +15 -0
  15. package/api/doc/picoflow.flowmap._lastdeleted.md +21 -0
  16. package/api/doc/picoflow.flowmap._lastset.md +21 -0
  17. package/api/doc/picoflow.flowmap.delete.md +57 -0
  18. package/api/doc/picoflow.flowmap.md +135 -0
  19. package/api/doc/picoflow.flowmap.setat.md +73 -0
  20. package/api/doc/picoflow.flowobservable.get.md +19 -0
  21. package/api/doc/picoflow.flowobservable.md +54 -0
  22. package/api/doc/picoflow.flowresource._constructor_.md +65 -0
  23. package/api/doc/picoflow.flowresource.fetch.md +27 -0
  24. package/api/doc/picoflow.flowresource.get.md +23 -0
  25. package/api/doc/picoflow.flowresource.md +100 -0
  26. package/api/doc/picoflow.flowsetter.md +13 -0
  27. package/api/doc/picoflow.flowsignal.dispose.md +25 -0
  28. package/api/doc/picoflow.flowsignal.disposed.md +18 -0
  29. package/api/doc/picoflow.flowsignal.md +111 -0
  30. package/api/doc/picoflow.flowsignal.trigger.md +25 -0
  31. package/api/doc/picoflow.flowstate._constructor_.md +49 -0
  32. package/api/doc/picoflow.flowstate.get.md +23 -0
  33. package/api/doc/picoflow.flowstate.md +100 -0
  34. package/api/doc/picoflow.flowstate.set.md +61 -0
  35. package/api/doc/picoflow.flowstream._constructor_.md +65 -0
  36. package/api/doc/picoflow.flowstream.dispose.md +21 -0
  37. package/api/doc/picoflow.flowstream.get.md +23 -0
  38. package/api/doc/picoflow.flowstream.md +100 -0
  39. package/api/doc/picoflow.flowupdater.md +19 -0
  40. package/api/doc/picoflow.flowwatcher.md +15 -0
  41. package/api/doc/picoflow.map.md +59 -0
  42. package/api/doc/picoflow.md +287 -0
  43. package/api/doc/picoflow.resource.md +71 -0
  44. package/api/doc/picoflow.signal.md +19 -0
  45. package/api/doc/picoflow.state.md +55 -0
  46. package/api/doc/picoflow.stream.md +71 -0
  47. package/api/picoflow.api.md +145 -0
  48. package/api-extractor.json +60 -0
  49. package/biome.json +34 -0
  50. package/dist/picoflow.js +572 -0
  51. package/dist/types/creators.d.ts +70 -0
  52. package/dist/types/creators.d.ts.map +1 -0
  53. package/dist/types/derivation.d.ts +58 -0
  54. package/dist/types/derivation.d.ts.map +1 -0
  55. package/dist/types/effect.d.ts +108 -0
  56. package/dist/types/effect.d.ts.map +1 -0
  57. package/dist/types/index.d.ts +18 -0
  58. package/dist/types/index.d.ts.map +1 -0
  59. package/dist/types/map.d.ts +75 -0
  60. package/dist/types/map.d.ts.map +1 -0
  61. package/dist/types/observable.d.ts +40 -0
  62. package/dist/types/observable.d.ts.map +1 -0
  63. package/dist/types/resource.d.ts +46 -0
  64. package/dist/types/resource.d.ts.map +1 -0
  65. package/dist/types/signal.d.ts +111 -0
  66. package/dist/types/signal.d.ts.map +1 -0
  67. package/dist/types/state.d.ts +39 -0
  68. package/dist/types/state.d.ts.map +1 -0
  69. package/dist/types/stream.d.ts +71 -0
  70. package/dist/types/stream.d.ts.map +1 -0
  71. package/package.json +40 -0
  72. package/src/creators.ts +101 -0
  73. package/src/derivation.ts +96 -0
  74. package/src/effect.ts +152 -0
  75. package/src/index.ts +30 -0
  76. package/src/map.ts +83 -0
  77. package/src/observable.ts +50 -0
  78. package/src/resource.ts +64 -0
  79. package/src/signal.ts +166 -0
  80. package/src/state.ts +52 -0
  81. package/src/stream.ts +99 -0
  82. package/test/derivation.test.ts +422 -0
  83. package/test/map.test.ts +106 -0
  84. package/test/resource.test.ts +127 -0
  85. package/test/signal.test.ts +59 -0
  86. package/test/state.test.ts +89 -0
  87. package/test/stream.test.ts +171 -0
  88. package/tsconfig.json +22 -0
  89. package/vite.config.ts +26 -0
  90. package/vitest.config.ts +11 -0
@@ -0,0 +1,59 @@
1
+ import { describe, expect, test, vi } from "vitest";
2
+ import { effect, signal } from "#package";
3
+
4
+ describe("signal", () => {
5
+ test("throws when disposed", () => {
6
+ const $signal = signal();
7
+ const effectFn = vi.fn();
8
+ effect((_, watch) => {
9
+ watch($signal);
10
+ effectFn();
11
+ });
12
+
13
+ expect(effectFn).toHaveBeenCalledTimes(1);
14
+
15
+ $signal.trigger();
16
+ expect(effectFn).toHaveBeenCalledTimes(2);
17
+
18
+ $signal.dispose();
19
+ expect(() => $signal.trigger()).toThrow("Signal is disposed");
20
+ });
21
+ });
22
+
23
+ describe("effect", () => {
24
+ test("called when signal triggered", () => {
25
+ const $signal = signal();
26
+ const effectFn = vi.fn();
27
+ effect((_, watch) => {
28
+ watch($signal);
29
+ effectFn();
30
+ });
31
+
32
+ expect(effectFn).toHaveBeenCalledTimes(1);
33
+
34
+ $signal.trigger();
35
+ expect(effectFn).toHaveBeenCalledTimes(2);
36
+
37
+ $signal.trigger();
38
+ expect(effectFn).toHaveBeenCalledTimes(3);
39
+ });
40
+
41
+ test("NOT called when disposed", () => {
42
+ const $signal = signal();
43
+ const effectFn = vi.fn();
44
+ const $effect = effect((_, watch) => {
45
+ watch($signal);
46
+ effectFn();
47
+ });
48
+
49
+ expect(effectFn).toHaveBeenCalledTimes(1);
50
+
51
+ $signal.trigger();
52
+ expect(effectFn).toHaveBeenCalledTimes(2);
53
+
54
+ $effect.dispose();
55
+
56
+ $signal.trigger();
57
+ expect(effectFn).toHaveBeenCalledTimes(2);
58
+ });
59
+ });
@@ -0,0 +1,89 @@
1
+ import { describe, expect, test, vi } from "vitest";
2
+ import { effect, state } from "#package";
3
+
4
+ describe("state", () => {
5
+ test("is updated", () => {
6
+ const $state = state(1);
7
+ expect($state.get()).toBe(1);
8
+
9
+ $state.set(2);
10
+ expect($state.get()).toBe(2);
11
+ });
12
+
13
+ test("set throws when disposed", () => {
14
+ const $state = state(1);
15
+
16
+ expect($state.get()).toBe(1);
17
+
18
+ $state.set(2);
19
+ expect($state.get()).toBe(2);
20
+
21
+ $state.dispose();
22
+
23
+ expect(() => $state.set(3)).toThrow("State is disposed");
24
+ });
25
+
26
+ test("get throws when disposed", () => {
27
+ const $state = state(1);
28
+
29
+ expect($state.get()).toBe(1);
30
+
31
+ $state.set(2);
32
+ expect($state.get()).toBe(2);
33
+
34
+ $state.dispose();
35
+
36
+ expect(() => $state.get()).toThrow("State is disposed");
37
+ });
38
+ });
39
+
40
+ describe("effect", () => {
41
+ test("called when updated", () => {
42
+ const $state = state(1);
43
+ const effectFn = vi.fn();
44
+ effect((get) => effectFn(get($state)));
45
+
46
+ expect(effectFn).toHaveBeenCalledTimes(1);
47
+ expect(effectFn).toHaveBeenLastCalledWith(1);
48
+
49
+ $state.set(2);
50
+ expect(effectFn).toHaveBeenCalledTimes(2);
51
+ expect(effectFn).toHaveBeenLastCalledWith(2);
52
+ });
53
+
54
+ test("NOT called when updated with the same value", () => {
55
+ const $state = state(1);
56
+ const effectFn = vi.fn();
57
+ effect((get) => effectFn(get($state)));
58
+
59
+ expect(effectFn).toHaveBeenCalledTimes(1);
60
+ expect(effectFn).toHaveBeenLastCalledWith(1);
61
+
62
+ $state.set(2);
63
+ expect(effectFn).toHaveBeenCalledTimes(2);
64
+ expect(effectFn).toHaveBeenLastCalledWith(2);
65
+
66
+ $state.set(2);
67
+ expect(effectFn).toHaveBeenCalledTimes(2);
68
+ expect(effectFn).toHaveBeenLastCalledWith(2);
69
+ });
70
+
71
+ test("NOT called when disposed", () => {
72
+ const $state = state(1);
73
+ const effectFn = vi.fn();
74
+ const $effect = effect((get) => effectFn(get($state)));
75
+
76
+ expect(effectFn).toHaveBeenCalledTimes(1);
77
+ expect(effectFn).toHaveBeenLastCalledWith(1);
78
+
79
+ $state.set(2);
80
+ expect(effectFn).toHaveBeenCalledTimes(2);
81
+ expect(effectFn).toHaveBeenLastCalledWith(2);
82
+
83
+ $effect.dispose();
84
+
85
+ $state.set(3);
86
+ expect(effectFn).toHaveBeenCalledTimes(2);
87
+ expect(effectFn).toHaveBeenLastCalledWith(2);
88
+ });
89
+ });
@@ -0,0 +1,171 @@
1
+ import { describe, expect, test, vi } from "vitest";
2
+ import { stream, effect } from "#package";
3
+
4
+ describe("stream", () => {
5
+ test("is updated (callback)", async () => {
6
+ const counter = {
7
+ count: 0,
8
+ callback: undefined as ((value: number) => void) | undefined,
9
+ increment() {
10
+ this.count++;
11
+ if (this.callback) {
12
+ this.callback(this.count);
13
+ }
14
+ },
15
+ };
16
+
17
+ const $stream = stream((set) => {
18
+ counter.callback = set;
19
+ return () => {
20
+ counter.callback = undefined;
21
+ };
22
+ }, counter.count);
23
+
24
+ expect($stream.get()).toBe(0);
25
+
26
+ counter.increment();
27
+ expect($stream.get()).toBe(1);
28
+
29
+ counter.increment();
30
+ expect($stream.get()).toBe(2);
31
+ });
32
+
33
+ test("stream is updated (interval)", async () => {
34
+ vi.useFakeTimers();
35
+
36
+ const $stream = stream((set) => {
37
+ let counter = 0;
38
+ const interval = setInterval(() => {
39
+ counter++;
40
+ set(counter);
41
+ }, 1000);
42
+ return () => clearInterval(interval);
43
+ }, 0);
44
+
45
+ expect($stream.get()).toBe(0);
46
+
47
+ vi.advanceTimersToNextTimer();
48
+ expect($stream.get()).toBe(1);
49
+
50
+ vi.advanceTimersToNextTimer();
51
+ expect($stream.get()).toBe(2);
52
+ });
53
+
54
+ test("get throws when stream is disposed", async () => {
55
+ vi.useFakeTimers();
56
+
57
+ const $stream = stream((set) => {
58
+ let counter = 0;
59
+ const interval = setInterval(() => {
60
+ counter++;
61
+ set(counter);
62
+ }, 1000);
63
+ return () => clearInterval(interval);
64
+ }, 0);
65
+
66
+ expect($stream.get()).toBe(0);
67
+
68
+ vi.advanceTimersToNextTimer();
69
+ expect($stream.get()).toBe(1);
70
+
71
+ vi.advanceTimersToNextTimer();
72
+ expect($stream.get()).toBe(2);
73
+
74
+ $stream.dispose();
75
+ vi.advanceTimersToNextTimer();
76
+ expect(() => $stream.get()).toThrow("Stream is disposed");
77
+ });
78
+ });
79
+
80
+ describe("effect", () => {
81
+ test("called when stream is updated", async () => {
82
+ vi.useFakeTimers();
83
+
84
+ const $stream = stream((set) => {
85
+ let counter = 0;
86
+ const interval = setInterval(() => {
87
+ counter++;
88
+ set(counter);
89
+ }, 1000);
90
+ return () => clearInterval(interval);
91
+ }, 0);
92
+
93
+ const effectFn = vi.fn();
94
+ effect((get) => effectFn(get($stream)));
95
+
96
+ expect(effectFn).toHaveBeenCalledTimes(1);
97
+ expect(effectFn).toHaveBeenLastCalledWith(0);
98
+
99
+ vi.advanceTimersToNextTimer();
100
+ expect(effectFn).toHaveBeenCalledTimes(2);
101
+ expect(effectFn).toHaveBeenLastCalledWith(1);
102
+
103
+ vi.advanceTimersToNextTimer();
104
+ expect(effectFn).toHaveBeenCalledTimes(3);
105
+ expect(effectFn).toHaveBeenLastCalledWith(2);
106
+ });
107
+
108
+ test("NOT called when disposed", async () => {
109
+ vi.useFakeTimers();
110
+
111
+ const $stream = stream((set) => {
112
+ let counter = 0;
113
+ const interval = setInterval(() => {
114
+ counter++;
115
+ set(counter);
116
+ }, 1000);
117
+ return () => clearInterval(interval);
118
+ }, 0);
119
+
120
+ const effectFn = vi.fn();
121
+ const $effect = effect((get) => effectFn(get($stream)));
122
+
123
+ expect(effectFn).toHaveBeenCalledTimes(1);
124
+ expect(effectFn).toHaveBeenLastCalledWith(0);
125
+
126
+ vi.advanceTimersToNextTimer();
127
+ expect(effectFn).toHaveBeenCalledTimes(2);
128
+ expect(effectFn).toHaveBeenLastCalledWith(1);
129
+
130
+ vi.advanceTimersToNextTimer();
131
+ expect(effectFn).toHaveBeenCalledTimes(3);
132
+ expect(effectFn).toHaveBeenLastCalledWith(2);
133
+
134
+ $effect.dispose();
135
+ vi.advanceTimersToNextTimer();
136
+ expect(effectFn).toHaveBeenCalledTimes(3);
137
+ expect(effectFn).toHaveBeenLastCalledWith(2);
138
+ });
139
+
140
+ test("NOT called when stream is disposed", async () => {
141
+ vi.useFakeTimers();
142
+
143
+ const $stream = stream((set) => {
144
+ let counter = 0;
145
+ const interval = setInterval(() => {
146
+ counter++;
147
+ set(counter);
148
+ }, 1000);
149
+ return () => clearInterval(interval);
150
+ }, 0);
151
+
152
+ const effectFn = vi.fn();
153
+ effect((get) => effectFn(get($stream)));
154
+
155
+ expect(effectFn).toHaveBeenCalledTimes(1);
156
+ expect(effectFn).toHaveBeenLastCalledWith(0);
157
+
158
+ vi.advanceTimersToNextTimer();
159
+ expect(effectFn).toHaveBeenCalledTimes(2);
160
+ expect(effectFn).toHaveBeenLastCalledWith(1);
161
+
162
+ vi.advanceTimersToNextTimer();
163
+ expect(effectFn).toHaveBeenCalledTimes(3);
164
+ expect(effectFn).toHaveBeenLastCalledWith(2);
165
+
166
+ $stream.dispose();
167
+ vi.advanceTimersToNextTimer();
168
+ expect(effectFn).toHaveBeenCalledTimes(3);
169
+ expect(effectFn).toHaveBeenLastCalledWith(2);
170
+ });
171
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "rootDir": ".",
4
+ "target": "ESNext",
5
+
6
+ "module": "ESNext",
7
+ "moduleResolution": "Bundler",
8
+
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "outDir": "dist/types",
12
+
13
+ "strict": true,
14
+ "verbatimModuleSyntax": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "noImplicitOverride": true,
19
+ "noImplicitReturns": true
20
+ },
21
+ "include": ["./src/**/*", "./test/**/*"]
22
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { defineConfig } from "vite";
2
+ import dts from "vite-plugin-dts";
3
+
4
+ export default defineConfig({
5
+ root: "./src",
6
+ build: {
7
+ outDir: "../dist",
8
+ emptyOutDir: true,
9
+ lib: {
10
+ entry: "index.ts",
11
+ formats: ["es"],
12
+ },
13
+ target: "esnext",
14
+ minify: false,
15
+ },
16
+
17
+ plugins: [
18
+ dts({
19
+ include: "**/*",
20
+ outDir: "../dist/types",
21
+ compilerOptions: {
22
+ rootDir: "src",
23
+ },
24
+ }),
25
+ ],
26
+ });
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ include: ["**/*.test.ts"],
6
+ coverage: {
7
+ reporter: ["text"],
8
+ include: ["src/**/*"],
9
+ },
10
+ },
11
+ });