@kiberon-labs/behave-graph-suspendable 1.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.
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "noEmit": true,
6
+ "rootDir": "../",
7
+ "lib": [],
8
+ "paths": {
9
+ "~/*":["../src/*"]
10
+ }
11
+ },
12
+ "include": [
13
+ "**/*.ts"
14
+ ]
15
+ }
@@ -0,0 +1,96 @@
1
+ import type { GraphJSON } from '@kiberon-labs/behave-graph';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { makeTestEngine } from './testUtils';
4
+
5
+ /**
6
+ * onStart -> variable/set writes 1000 into the `counter` variable
7
+ * (initial value -1).
8
+ */
9
+ const variableGraph: GraphJSON = {
10
+ variables: [
11
+ {
12
+ valueTypeName: 'float',
13
+ name: 'counter',
14
+ id: 0,
15
+ initialValue: -1
16
+ }
17
+ ],
18
+ customEvents: [],
19
+ nodes: [
20
+ {
21
+ type: 'lifecycle/onStart',
22
+ id: '0',
23
+ flows: { flow: { nodeId: '1', socket: 'flow' } }
24
+ },
25
+ {
26
+ type: 'variable/set',
27
+ id: '1',
28
+ configuration: { variableId: 0 },
29
+ parameters: { value: { value: 1000 } }
30
+ }
31
+ ]
32
+ } as unknown as GraphJSON;
33
+
34
+ describe('variable serialization across suspension', () => {
35
+ it('serializes the updated variable value, not the initial value', async () => {
36
+ const { engine, graph, start } = makeTestEngine(variableGraph);
37
+
38
+ start();
39
+ await engine.executeAllSync();
40
+ expect(graph.variables['0']!.get()).toBe(1000);
41
+
42
+ const suspension = engine.suspend();
43
+
44
+ expect(suspension.variables['0']).toEqual({
45
+ type: 'float',
46
+ value: 1000
47
+ });
48
+ });
49
+
50
+ it('serializes the latest value when a variable is updated multiple times', async () => {
51
+ const { engine, graph, start } = makeTestEngine(variableGraph);
52
+
53
+ start();
54
+ await engine.executeAllSync();
55
+
56
+ // a later runtime update (e.g. another node firing) must win
57
+ graph.variables['0']!.set(7);
58
+
59
+ const suspension = engine.suspend();
60
+ expect(suspension.variables['0']).toEqual({ type: 'float', value: 7 });
61
+ });
62
+
63
+ it('restores the suspended variable value into a fresh engine', async () => {
64
+ const first = makeTestEngine(variableGraph);
65
+ first.start();
66
+ await first.engine.executeAllSync();
67
+
68
+ const suspension = first.engine.suspend();
69
+ const persisted = JSON.parse(JSON.stringify(suspension));
70
+
71
+ // fresh graph starts back at the initial value...
72
+ const second = makeTestEngine(variableGraph);
73
+ expect(second.graph.variables['0']!.get()).toBe(-1);
74
+
75
+ // ...until the suspension is rehydrated
76
+ second.engine.unsuspend(persisted, undefined);
77
+ expect(second.graph.variables['0']!.get()).toBe(1000);
78
+ });
79
+
80
+ it('throws when the suspension references a variable missing from the graph', async () => {
81
+ const first = makeTestEngine(variableGraph);
82
+ first.start();
83
+ await first.engine.executeAllSync();
84
+ const suspension = first.engine.suspend();
85
+
86
+ const graphWithoutVariables = {
87
+ ...variableGraph,
88
+ variables: []
89
+ } as unknown as GraphJSON;
90
+ const second = makeTestEngine(graphWithoutVariables);
91
+
92
+ expect(() => second.engine.unsuspend(suspension, undefined)).toThrow(
93
+ /missing variable/
94
+ );
95
+ });
96
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "display": "Monorepo shared library",
4
+ "compilerOptions": {
5
+ /* Base Options: */
6
+ "esModuleInterop": true,
7
+ "skipLibCheck": true,
8
+ "target": "esnext",
9
+ "lib": [
10
+ "esnext",
11
+ "ES6"
12
+ ],
13
+ "allowJs": true,
14
+ "resolveJsonModule": true,
15
+ "moduleDetection": "force",
16
+ "isolatedModules": true,
17
+ "verbatimModuleSyntax": true,
18
+ /* Strictness */
19
+ "strict": true,
20
+ "noUncheckedIndexedAccess": true,
21
+ "noImplicitOverride": true,
22
+ "erasableSyntaxOnly": true,
23
+ /* Opinion */
24
+ "incremental": true,
25
+ "tsBuildInfoFile": "./tsconfig.tsbuildinfo",
26
+ "module": "preserve",
27
+ "outDir": "./dist",
28
+ "baseUrl": ".",
29
+ "rootDir": "./src",
30
+ "paths": {
31
+ "~/*": [
32
+ "./src/*"
33
+ ],
34
+ "@/*": [
35
+ "./src/*"
36
+ ]
37
+ },
38
+ /* Required for project references, which provide go-to-definition in your
39
+ IDE without first having to build the module, which is essential during development. */
40
+ "composite": true,
41
+ /* Assuming your bundler will output everything, but we can not have noEmit
42
+ enabled because it is not compatible with composite / project references. Also declaration might be required for references to work fully. Not sure yet... */
43
+ "declaration": true,
44
+ "declarationMap": true,
45
+ },
46
+ "include": [
47
+ "./src",
48
+ "./src/**/*.json"
49
+ ],
50
+ "references": [
51
+ {
52
+ "path": "../core"
53
+ }
54
+ ],
55
+ }
@@ -0,0 +1,13 @@
1
+ import { defineConfig } from 'tsdown';
2
+
3
+ export default defineConfig({
4
+ entry: ['./src/index.ts'],
5
+ outDir: 'dist',
6
+ target: 'es2022',
7
+ sourcemap: true,
8
+ format: ['esm'],
9
+ dts: true,
10
+ logLevel: 'warn',
11
+ unbundle: true,
12
+ platform: 'neutral'
13
+ });
@@ -0,0 +1,15 @@
1
+ import path from 'node:path';
2
+ import { configDefaults, defineConfig } from 'vitest/config';
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ exclude: [...configDefaults.exclude],
7
+ watch: false
8
+ },
9
+ resolve: {
10
+ alias: {
11
+ '~': path.resolve(__dirname, './src'),
12
+ '@': path.resolve(__dirname, './src')
13
+ }
14
+ }
15
+ });