synstate 7.0.0 → 7.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.
- package/README.md +1 -1
- package/dist/core/class/child-observable-class.d.mts +0 -12
- package/dist/core/class/child-observable-class.d.mts.map +1 -1
- package/dist/core/class/child-observable-class.mjs +4 -10
- package/dist/core/class/child-observable-class.mjs.map +1 -1
- package/dist/core/utils/index.d.mts +1 -0
- package/dist/core/utils/index.d.mts.map +1 -1
- package/dist/core/utils/index.mjs +1 -0
- package/dist/core/utils/index.mjs.map +1 -1
- package/dist/core/utils/is-development-build.d.mts +15 -0
- package/dist/core/utils/is-development-build.d.mts.map +1 -0
- package/dist/core/utils/is-development-build.mjs +23 -0
- package/dist/core/utils/is-development-build.mjs.map +1 -0
- package/package.json +9 -9
- package/src/core/class/child-observable-class.mts +10 -16
- package/src/core/class/circular-dependency-comparison.test.mts +36 -40
- package/src/core/class/circular-dependency.test.mts +6 -37
- package/src/core/utils/index.mts +1 -0
- package/src/core/utils/is-development-build.mts +32 -0
- package/src/core/utils/is-development-build.test.mts +44 -0
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
- 🎯 **Simple State Management**: Easy-to-use `createState` and `createReducer` similar to React useState/useReducer for global state
|
|
25
25
|
- ⚡ **Glitch-Free Through Every Operator**: Every update is one depth-ordered pass over what it reaches, the ones `debounce` or `switchMap` start later included, so no subscriber sees a half-updated graph, and its cost grows with the nodes it reaches, never with the paths between them ([why SynState](https://noshiro-pf.github.io/mono/synstate/guides/why-synstate/), [benchmark](https://noshiro-pf.github.io/mono/synstate/guides/library-comparison/benchmark/))
|
|
26
26
|
- 🎨 **Type-Safe**: Full TypeScript support with precise type inference
|
|
27
|
-
- 🚀 **Lightweight**: <!-- bundle-size:synstate -->~6.
|
|
27
|
+
- 🚀 **Lightweight**: <!-- bundle-size:synstate -->~6.8 kB min+gzip<!-- /bundle-size:synstate --> with two external runtime dependencies ([ts-data-forge](https://www.npmjs.com/package/ts-data-forge) and [ts-std-forge](https://www.npmjs.com/package/ts-std-forge), and the first depends on the second)
|
|
28
28
|
- 🌐 **Framework Agnostic**: Works with React, Vue, Svelte, or vanilla JavaScript
|
|
29
29
|
- 🔄 **Reactive Updates**: Automatic propagation of state changes to all subscribers
|
|
30
30
|
- 📡 **Event System**: Built-in `createValueEmitter`, `createEventEmitter` for event-driven architecture
|
|
@@ -106,17 +106,5 @@ export declare class InitializedSyncChildObservableClass<A, const P extends NonE
|
|
|
106
106
|
pipe<B>(operator: KeepInitialValueOperator<A, B> | WithInitialValueOperator<A, B>): InitializedObservable<B>;
|
|
107
107
|
pipe<B>(operator: DropInitialValueOperator<A, B>): Observable<B>;
|
|
108
108
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Whether {@link registerChild} checks for a circular dependency: on in
|
|
111
|
-
* development, off in production. The public API cannot make a cycle — a
|
|
112
|
-
* child's parents exist before it and cannot be changed afterwards — so the
|
|
113
|
-
* check is a safety net for what propagation assumes (a DAG, a depth for every
|
|
114
|
-
* node) against code that rewrites an observable's readonly `parents`, and
|
|
115
|
-
* development is where that code runs first. It walks every ancestor of each
|
|
116
|
-
* new observable, a cost production does not pay: the check is off when
|
|
117
|
-
* `NODE_ENV` is `production`, and where there is no `process` (a browser
|
|
118
|
-
* bundle).
|
|
119
|
-
*/
|
|
120
|
-
export declare const checksCircularDependency: boolean;
|
|
121
109
|
export {};
|
|
122
110
|
//# sourceMappingURL=child-observable-class.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"child-observable-class.d.mts","sourceRoot":"","sources":["../../../src/core/class/child-observable-class.mts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"child-observable-class.d.mts","sourceRoot":"","sources":["../../../src/core/class/child-observable-class.mts"],"names":[],"mappings":"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"}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Optional } from 'ts-data-forge';
|
|
6
6
|
import { panic } from 'ts-std-forge';
|
|
7
|
-
import { issueUnqueuedToken, maxDepth } from '../utils/index.mjs';
|
|
7
|
+
import { isDevelopmentBuild, issueUnqueuedToken, maxDepth, } from '../utils/index.mjs';
|
|
8
8
|
import { ManagerObservableClass } from './manager-observable-class.mjs';
|
|
9
9
|
import { ObservableBaseClass } from './observable-base-class.mjs';
|
|
10
10
|
import { toNode } from './observable-node.mjs';
|
|
@@ -272,13 +272,6 @@ const unregisterChild = (child) => {
|
|
|
272
272
|
toNode(p).deleteChild(child);
|
|
273
273
|
}
|
|
274
274
|
};
|
|
275
|
-
const isDevelopmentProcess = () => {
|
|
276
|
-
const proc = Reflect.get(globalThis, 'process');
|
|
277
|
-
return (isRecord(proc) &&
|
|
278
|
-
hasKey(proc, 'env') &&
|
|
279
|
-
isRecord(proc.env) &&
|
|
280
|
-
(!hasKey(proc.env, 'NODE_ENV') || proc.env.NODE_ENV !== 'production'));
|
|
281
|
-
};
|
|
282
275
|
|
|
283
276
|
|
|
284
277
|
|
|
@@ -290,5 +283,6 @@ const isDevelopmentProcess = () => {
|
|
|
290
283
|
|
|
291
284
|
|
|
292
285
|
|
|
293
|
-
|
|
286
|
+
|
|
287
|
+
const checksCircularDependency = isDevelopmentBuild();
|
|
294
288
|
//# sourceMappingURL=child-observable-class.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"child-observable-class.mjs","sourceRoot":"","sources":["../../../src/core/class/child-observable-class.mts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,gDAAgD;AAChD,0DAA0D;AAC1D,kEAAkE;AAClE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"child-observable-class.mjs","sourceRoot":"","sources":["../../../src/core/class/child-observable-class.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/core/utils/index.mts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../src/core/utils/index.mts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/core/utils/index.mts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../src/core/utils/index.mts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this is a development build: `NODE_ENV` is not `production`.
|
|
3
|
+
*
|
|
4
|
+
* `process.env.NODE_ENV` is written out in full because that is the expression
|
|
5
|
+
* bundlers (Vite, webpack, esbuild) replace, in the application's build and in
|
|
6
|
+
* a pre-bundled dependency alike: with the string `"development"` in a
|
|
7
|
+
* development build and `"production"` in a production one. Where nothing
|
|
8
|
+
* replaces it and there is no `process` (an unbundled module in a browser),
|
|
9
|
+
* reading it throws and the answer is `false`.
|
|
10
|
+
*
|
|
11
|
+
* synstate-router reads it the same way
|
|
12
|
+
* (`libs/synstate-router/src/internal/is-development.mts`).
|
|
13
|
+
*/
|
|
14
|
+
export declare const isDevelopmentBuild: () => boolean;
|
|
15
|
+
//# sourceMappingURL=is-development-build.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-development-build.d.mts","sourceRoot":"","sources":["../../../src/core/utils/is-development-build.mts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,QAAO,OAOrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-development-build.mjs","sourceRoot":"","sources":["../../../src/core/utils/is-development-build.mts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAY,EAAE;IAC9C,uCAAuC;IACvC,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "synstate",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "Type-safe State Management Library for TypeScript/JavaScript",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,15 +36,15 @@
|
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@preact/signals-core": "1.14.4",
|
|
38
38
|
"@reduxjs/toolkit": "2.13.0",
|
|
39
|
-
"@sumi-lang/cli": "0.1.
|
|
39
|
+
"@sumi-lang/cli": "0.1.7",
|
|
40
40
|
"@types/react": "19.3.0",
|
|
41
41
|
"@vitest/browser-playwright": "5.0.5",
|
|
42
42
|
"argparse": "3.0.3",
|
|
43
43
|
"eslint": "10.13.0",
|
|
44
|
-
"eslint-config-typed": "7.
|
|
45
|
-
"eslint-plugin-ts-data-forge": "0.10.
|
|
46
|
-
"eslint-plugin-ts-fortress": "1.3.
|
|
47
|
-
"eslint-plugin-ts-type-forge": "0.8.
|
|
44
|
+
"eslint-config-typed": "7.5.0",
|
|
45
|
+
"eslint-plugin-ts-data-forge": "0.10.10",
|
|
46
|
+
"eslint-plugin-ts-fortress": "1.3.14",
|
|
47
|
+
"eslint-plugin-ts-type-forge": "0.8.19",
|
|
48
48
|
"jotai": "3.0.1",
|
|
49
49
|
"mobx": "7.1.0",
|
|
50
50
|
"playwright": "1.64.1",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"react": "19.3.1",
|
|
55
55
|
"rxjs": "7.8.2",
|
|
56
56
|
"solid-js": "1.9.17",
|
|
57
|
-
"synstate-react-hooks": "7.0.
|
|
58
|
-
"synstate-react-hooks-compat": "7.0.
|
|
59
|
-
"ts-repo-utils": "10.7.
|
|
57
|
+
"synstate-react-hooks": "7.0.1",
|
|
58
|
+
"synstate-react-hooks-compat": "7.0.1",
|
|
59
|
+
"ts-repo-utils": "10.7.3",
|
|
60
60
|
"valtio": "2.3.2",
|
|
61
61
|
"zustand": "5.0.15"
|
|
62
62
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
3
3
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
4
4
|
// @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
|
|
5
|
-
import {
|
|
5
|
+
import { Optional, type Some } from 'ts-data-forge';
|
|
6
6
|
import { panic } from 'ts-std-forge';
|
|
7
7
|
import type { MutableSet } from 'ts-type-forge';
|
|
8
8
|
import type {
|
|
@@ -20,7 +20,11 @@ import type {
|
|
|
20
20
|
WithInitialValueOperator,
|
|
21
21
|
Wrap,
|
|
22
22
|
} from '../types/index.mjs';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
isDevelopmentBuild,
|
|
25
|
+
issueUnqueuedToken,
|
|
26
|
+
maxDepth,
|
|
27
|
+
} from '../utils/index.mjs';
|
|
24
28
|
import { ManagerObservableClass } from './manager-observable-class.mjs';
|
|
25
29
|
import { ObservableBaseClass } from './observable-base-class.mjs';
|
|
26
30
|
import { toNode, type ChildNode } from './observable-node.mjs';
|
|
@@ -395,17 +399,6 @@ const unregisterChild = (child: ChildNode): void => {
|
|
|
395
399
|
}
|
|
396
400
|
};
|
|
397
401
|
|
|
398
|
-
const isDevelopmentProcess = (): boolean => {
|
|
399
|
-
const proc: unknown = Reflect.get(globalThis, 'process');
|
|
400
|
-
|
|
401
|
-
return (
|
|
402
|
-
isRecord(proc) &&
|
|
403
|
-
hasKey(proc, 'env') &&
|
|
404
|
-
isRecord(proc.env) &&
|
|
405
|
-
(!hasKey(proc.env, 'NODE_ENV') || proc.env.NODE_ENV !== 'production')
|
|
406
|
-
);
|
|
407
|
-
};
|
|
408
|
-
|
|
409
402
|
/**
|
|
410
403
|
* Whether {@link registerChild} checks for a circular dependency: on in
|
|
411
404
|
* development, off in production. The public API cannot make a cycle — a
|
|
@@ -414,7 +407,8 @@ const isDevelopmentProcess = (): boolean => {
|
|
|
414
407
|
* node) against code that rewrites an observable's readonly `parents`, and
|
|
415
408
|
* development is where that code runs first. It walks every ancestor of each
|
|
416
409
|
* new observable, a cost production does not pay: the check is off when
|
|
417
|
-
* `NODE_ENV` is `production`,
|
|
418
|
-
*
|
|
410
|
+
* `NODE_ENV` is `production`, including a bundle whose bundler replaced
|
|
411
|
+
* `process.env.NODE_ENV`, and where nothing replaced it and there is no
|
|
412
|
+
* `process` (see {@link isDevelopmentBuild}).
|
|
419
413
|
*/
|
|
420
|
-
|
|
414
|
+
const checksCircularDependency: boolean = isDevelopmentBuild();
|
|
@@ -14,7 +14,6 @@ import { Optional } from 'ts-data-forge';
|
|
|
14
14
|
import { combine } from '../combine/index.mjs';
|
|
15
15
|
import { source } from '../create/index.mjs';
|
|
16
16
|
import { map } from '../operators/index.mjs';
|
|
17
|
-
import { checksCircularDependency } from './child-observable-class.mjs';
|
|
18
17
|
import {
|
|
19
18
|
createSyncChildObservable,
|
|
20
19
|
createTryUpdateNotImplemented,
|
|
@@ -23,53 +22,50 @@ import { createRootObservable } from './create-root-observable.mjs';
|
|
|
23
22
|
|
|
24
23
|
describe('circular dependency comparison', () => {
|
|
25
24
|
describe('SynState', () => {
|
|
26
|
-
//
|
|
27
|
-
test
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
() => ({}),
|
|
33
|
-
);
|
|
25
|
+
// The check is on in both test runs: see `circular-dependency.test.mts`.
|
|
26
|
+
test('detects cycle at construction time with a clear error message', () => {
|
|
27
|
+
const root = createRootObservable(
|
|
28
|
+
{ initialValue: Optional.some(0) },
|
|
29
|
+
() => ({}),
|
|
30
|
+
);
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
const mut_childA = createSyncChildObservable(
|
|
33
|
+
{
|
|
34
|
+
parents: [root],
|
|
35
|
+
initialValue: Optional.some(0),
|
|
36
|
+
},
|
|
37
|
+
createTryUpdateNotImplemented,
|
|
38
|
+
);
|
|
42
39
|
|
|
43
|
-
|
|
40
|
+
const childB = createSyncChildObservable(
|
|
41
|
+
{
|
|
42
|
+
parents: [mut_childA],
|
|
43
|
+
initialValue: Optional.some(0),
|
|
44
|
+
},
|
|
45
|
+
createTryUpdateNotImplemented,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Simulate a cycle: mut_childA → childB → mut_childA
|
|
49
|
+
// In normal usage this is impossible — the check runs in every child
|
|
50
|
+
// constructor before the reference becomes available.
|
|
51
|
+
Object.defineProperty(mut_childA, 'parents', {
|
|
52
|
+
value: [childB],
|
|
53
|
+
writable: false,
|
|
54
|
+
configurable: true,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
expect(() => {
|
|
58
|
+
createSyncChildObservable(
|
|
44
59
|
{
|
|
45
60
|
parents: [mut_childA],
|
|
46
61
|
initialValue: Optional.some(0),
|
|
47
62
|
},
|
|
48
63
|
createTryUpdateNotImplemented,
|
|
49
64
|
);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Object.defineProperty(mut_childA, 'parents', {
|
|
55
|
-
value: [childB],
|
|
56
|
-
writable: false,
|
|
57
|
-
configurable: true,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
expect(() => {
|
|
61
|
-
createSyncChildObservable(
|
|
62
|
-
{
|
|
63
|
-
parents: [mut_childA],
|
|
64
|
-
initialValue: Optional.some(0),
|
|
65
|
-
},
|
|
66
|
-
createTryUpdateNotImplemented,
|
|
67
|
-
);
|
|
68
|
-
}).toThrow(
|
|
69
|
-
'Circular dependency detected in observable graph: a child observable cannot be its own ancestor.',
|
|
70
|
-
);
|
|
71
|
-
},
|
|
72
|
-
);
|
|
65
|
+
}).toThrow(
|
|
66
|
+
'Circular dependency detected in observable graph: a child observable cannot be its own ancestor.',
|
|
67
|
+
);
|
|
68
|
+
});
|
|
73
69
|
|
|
74
70
|
test('accepts valid DAG (diamond dependency)', () => {
|
|
75
71
|
const a$ = source(0);
|
|
@@ -2,7 +2,6 @@ import { Optional } from 'ts-data-forge';
|
|
|
2
2
|
import { combine, merge } from '../combine/index.mjs';
|
|
3
3
|
import { source } from '../create/index.mjs';
|
|
4
4
|
import { map } from '../operators/index.mjs';
|
|
5
|
-
import { checksCircularDependency } from './child-observable-class.mjs';
|
|
6
5
|
import {
|
|
7
6
|
createAsyncChildObservable,
|
|
8
7
|
createSyncChildObservable,
|
|
@@ -11,9 +10,12 @@ import {
|
|
|
11
10
|
import { createRootObservable } from './create-root-observable.mjs';
|
|
12
11
|
|
|
13
12
|
describe('circular dependency detection', () => {
|
|
14
|
-
// The check runs only
|
|
15
|
-
//
|
|
16
|
-
|
|
13
|
+
// The check runs only where `NODE_ENV` is not `production`, which is so in
|
|
14
|
+
// both test runs: in the browser run because Vite replaced
|
|
15
|
+
// `process.env.NODE_ENV`, so these tests also fail if it stops being
|
|
16
|
+
// replaced. `test/circular-dependency-check-off.test.mts` loads a production
|
|
17
|
+
// copy.
|
|
18
|
+
describe('cycle in ancestor graph', () => {
|
|
17
19
|
test('should throw when parent chain contains a cycle (A -> B -> A)', () => {
|
|
18
20
|
const root = createRootObservable(
|
|
19
21
|
{ initialValue: Optional.some(0) },
|
|
@@ -183,39 +185,6 @@ describe('circular dependency detection', () => {
|
|
|
183
185
|
});
|
|
184
186
|
});
|
|
185
187
|
|
|
186
|
-
describe.skipIf(checksCircularDependency)('with the check off', () => {
|
|
187
|
-
test('does not walk the ancestors of a new child', () => {
|
|
188
|
-
const root = createRootObservable(
|
|
189
|
-
{ initialValue: Optional.some(0) },
|
|
190
|
-
() => ({}),
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
const mut_childA = createSyncChildObservable(
|
|
194
|
-
{
|
|
195
|
-
parents: [root],
|
|
196
|
-
initialValue: Optional.some(0),
|
|
197
|
-
},
|
|
198
|
-
createTryUpdateNotImplemented,
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
Object.defineProperty(mut_childA, 'parents', {
|
|
202
|
-
value: [mut_childA],
|
|
203
|
-
writable: false,
|
|
204
|
-
configurable: true,
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
expect(() => {
|
|
208
|
-
createSyncChildObservable(
|
|
209
|
-
{
|
|
210
|
-
parents: [mut_childA],
|
|
211
|
-
initialValue: Optional.some(0),
|
|
212
|
-
},
|
|
213
|
-
createTryUpdateNotImplemented,
|
|
214
|
-
);
|
|
215
|
-
}).not.toThrow();
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
|
|
219
188
|
describe('valid DAG patterns should not throw', () => {
|
|
220
189
|
test('diamond dependency is not a cycle', () => {
|
|
221
190
|
const root = createRootObservable(
|
package/src/core/utils/index.mts
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this is a development build: `NODE_ENV` is not `production`.
|
|
3
|
+
*
|
|
4
|
+
* `process.env.NODE_ENV` is written out in full because that is the expression
|
|
5
|
+
* bundlers (Vite, webpack, esbuild) replace, in the application's build and in
|
|
6
|
+
* a pre-bundled dependency alike: with the string `"development"` in a
|
|
7
|
+
* development build and `"production"` in a production one. Where nothing
|
|
8
|
+
* replaces it and there is no `process` (an unbundled module in a browser),
|
|
9
|
+
* reading it throws and the answer is `false`.
|
|
10
|
+
*
|
|
11
|
+
* synstate-router reads it the same way
|
|
12
|
+
* (`libs/synstate-router/src/internal/is-development.mts`).
|
|
13
|
+
*/
|
|
14
|
+
export const isDevelopmentBuild = (): boolean => {
|
|
15
|
+
// @sumi-expect-error exceptions/no-try
|
|
16
|
+
try {
|
|
17
|
+
return process.env.NODE_ENV !== 'production';
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The one part of Node.js's `process` read here, declared in this module so
|
|
25
|
+
* that the dot form type-checks without the Node.js types (which this package's
|
|
26
|
+
* Sumi check does not load) and without the bracket form their index signature
|
|
27
|
+
* asks for, which bundlers do not replace. `declare` emits nothing:
|
|
28
|
+
* the emitted code reads the global `process`.
|
|
29
|
+
*/
|
|
30
|
+
declare const process: Readonly<{
|
|
31
|
+
env: Readonly<{ NODE_ENV?: string | undefined }>;
|
|
32
|
+
}>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// cspell:ignore unstub
|
|
2
|
+
import { isDevelopmentBuild } from './is-development-build.mjs';
|
|
3
|
+
|
|
4
|
+
describe(isDevelopmentBuild, () => {
|
|
5
|
+
test('is true when NODE_ENV is development', () => {
|
|
6
|
+
restoreAfterTest();
|
|
7
|
+
|
|
8
|
+
vi.stubEnv('NODE_ENV', 'development');
|
|
9
|
+
|
|
10
|
+
assert.isTrue(isDevelopmentBuild());
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('is true when NODE_ENV is not set', () => {
|
|
14
|
+
restoreAfterTest();
|
|
15
|
+
|
|
16
|
+
vi.stubEnv('NODE_ENV', undefined);
|
|
17
|
+
|
|
18
|
+
assert.isTrue(isDevelopmentBuild());
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('is false when NODE_ENV is production', () => {
|
|
22
|
+
restoreAfterTest();
|
|
23
|
+
|
|
24
|
+
vi.stubEnv('NODE_ENV', 'production');
|
|
25
|
+
|
|
26
|
+
assert.isFalse(isDevelopmentBuild());
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('is false where there is no process and nothing replaced the expression', () => {
|
|
30
|
+
restoreAfterTest();
|
|
31
|
+
|
|
32
|
+
vi.stubGlobal('process', undefined);
|
|
33
|
+
|
|
34
|
+
assert.isFalse(isDevelopmentBuild());
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const restoreAfterTest = (): void => {
|
|
39
|
+
onTestFinished(() => {
|
|
40
|
+
vi.unstubAllEnvs();
|
|
41
|
+
|
|
42
|
+
vi.unstubAllGlobals();
|
|
43
|
+
});
|
|
44
|
+
};
|