atom.io 0.1.0 → 0.3.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,68 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // ../src/react/index.ts
20
+ var react_exports = {};
21
+ __export(react_exports, {
22
+ composeStoreHooks: () => composeStoreHooks
23
+ });
24
+ module.exports = __toCommonJS(react_exports);
25
+ var import_atom = require("atom.io");
26
+ var composeStoreHooks = ({
27
+ useState,
28
+ useEffect,
29
+ store = import_atom.__INTERNAL__.IMPLICIT.STORE
30
+ }) => {
31
+ function useI(token) {
32
+ const updateState = (next) => (0, import_atom.setState)(token, next, store);
33
+ return updateState;
34
+ }
35
+ function useO(token) {
36
+ const state = import_atom.__INTERNAL__.withdraw(token, store);
37
+ const initialValue = import_atom.__INTERNAL__.getState__INTERNAL(state, store);
38
+ const [current, dispatch] = useState(initialValue);
39
+ useEffect(() => {
40
+ const unsubscribe = (0, import_atom.subscribe)(
41
+ token,
42
+ ({ newValue, oldValue }) => {
43
+ if (oldValue !== newValue) {
44
+ dispatch(newValue);
45
+ }
46
+ },
47
+ store
48
+ );
49
+ return unsubscribe;
50
+ }, []);
51
+ return current;
52
+ }
53
+ function useIO(token) {
54
+ return [useO(token), useI(token)];
55
+ }
56
+ function useStore(token) {
57
+ if (token.type === `readonly_selector`) {
58
+ return useO(token);
59
+ }
60
+ return useIO(token);
61
+ }
62
+ return { useI, useO, useIO, useStore };
63
+ };
64
+ // Annotate the CommonJS export names for ESM import in node:
65
+ 0 && (module.exports = {
66
+ composeStoreHooks
67
+ });
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/index.ts"],"sourcesContent":["import type Preact from \"preact/hooks\"\n\nimport type React from \"react\"\n\nimport { subscribe, setState, __INTERNAL__ } from \"atom.io\"\nimport type { ReadonlyValueToken, StateToken } from \"atom.io\"\n\nimport type { Modifier } from \"~/packages/anvl/src/function\"\n\nexport type AtomStoreReactConfig = {\n useState: typeof Preact.useState | typeof React.useState\n useEffect: typeof Preact.useEffect | typeof React.useEffect\n store?: __INTERNAL__.Store\n}\n\n/* eslint-disable @typescript-eslint/explicit-module-boundary-types */\nexport const composeStoreHooks = ({\n useState,\n useEffect,\n store = __INTERNAL__.IMPLICIT.STORE,\n}: AtomStoreReactConfig) => {\n function useI<T>(token: StateToken<T>): (next: Modifier<T> | T) => void {\n const updateState = (next: Modifier<T> | T) => setState(token, next, store)\n return updateState\n }\n\n function useO<T>(token: ReadonlyValueToken<T> | StateToken<T>): T {\n const state = __INTERNAL__.withdraw(token, store)\n const initialValue = __INTERNAL__.getState__INTERNAL(state, store)\n const [current, dispatch] = useState(initialValue)\n useEffect(() => {\n const unsubscribe = subscribe(\n token,\n ({ newValue, oldValue }) => {\n if (oldValue !== newValue) {\n dispatch(newValue)\n }\n },\n store\n )\n return unsubscribe\n }, [])\n\n return current\n }\n\n function useIO<T>(token: StateToken<T>): [T, (next: Modifier<T> | T) => void] {\n return [useO(token), useI(token)]\n }\n\n function useStore<T>(\n token: StateToken<T>\n ): [T, (next: Modifier<T> | T) => void]\n function useStore<T>(token: ReadonlyValueToken<T>): T\n function useStore<T>(\n token: ReadonlyValueToken<T> | StateToken<T>\n ): T | [T, (next: Modifier<T> | T) => void] {\n if (token.type === `readonly_selector`) {\n return useO(token)\n }\n return useIO(token)\n }\n return { useI, useO, useIO, useStore }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,kBAAkD;AAY3C,IAAM,oBAAoB,CAAC;AAAA,EAChC;AAAA,EACA;AAAA,EACA,QAAQ,yBAAa,SAAS;AAChC,MAA4B;AAC1B,WAAS,KAAQ,OAAuD;AACtE,UAAM,cAAc,CAAC,aAA0B,sBAAS,OAAO,MAAM,KAAK;AAC1E,WAAO;AAAA,EACT;AAEA,WAAS,KAAQ,OAAiD;AAChE,UAAM,QAAQ,yBAAa,SAAS,OAAO,KAAK;AAChD,UAAM,eAAe,yBAAa,mBAAmB,OAAO,KAAK;AACjE,UAAM,CAAC,SAAS,QAAQ,IAAI,SAAS,YAAY;AACjD,cAAU,MAAM;AACd,YAAM,kBAAc;AAAA,QAClB;AAAA,QACA,CAAC,EAAE,UAAU,SAAS,MAAM;AAC1B,cAAI,aAAa,UAAU;AACzB,qBAAS,QAAQ;AAAA,UACnB;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAAG,CAAC,CAAC;AAEL,WAAO;AAAA,EACT;AAEA,WAAS,MAAS,OAA4D;AAC5E,WAAO,CAAC,KAAK,KAAK,GAAG,KAAK,KAAK,CAAC;AAAA,EAClC;AAMA,WAAS,SACP,OAC0C;AAC1C,QAAI,MAAM,SAAS,qBAAqB;AACtC,aAAO,KAAK,KAAK;AAAA,IACnB;AACA,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,SAAO,EAAE,MAAM,MAAM,OAAO,SAAS;AACvC;","names":[]}
@@ -0,0 +1,44 @@
1
+ // ../src/react/index.ts
2
+ import { subscribe, setState, __INTERNAL__ } from "atom.io";
3
+ var composeStoreHooks = ({
4
+ useState,
5
+ useEffect,
6
+ store = __INTERNAL__.IMPLICIT.STORE
7
+ }) => {
8
+ function useI(token) {
9
+ const updateState = (next) => setState(token, next, store);
10
+ return updateState;
11
+ }
12
+ function useO(token) {
13
+ const state = __INTERNAL__.withdraw(token, store);
14
+ const initialValue = __INTERNAL__.getState__INTERNAL(state, store);
15
+ const [current, dispatch] = useState(initialValue);
16
+ useEffect(() => {
17
+ const unsubscribe = subscribe(
18
+ token,
19
+ ({ newValue, oldValue }) => {
20
+ if (oldValue !== newValue) {
21
+ dispatch(newValue);
22
+ }
23
+ },
24
+ store
25
+ );
26
+ return unsubscribe;
27
+ }, []);
28
+ return current;
29
+ }
30
+ function useIO(token) {
31
+ return [useO(token), useI(token)];
32
+ }
33
+ function useStore(token) {
34
+ if (token.type === `readonly_selector`) {
35
+ return useO(token);
36
+ }
37
+ return useIO(token);
38
+ }
39
+ return { useI, useO, useIO, useStore };
40
+ };
41
+ export {
42
+ composeStoreHooks
43
+ };
44
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/index.ts"],"sourcesContent":["import type Preact from \"preact/hooks\"\n\nimport type React from \"react\"\n\nimport { subscribe, setState, __INTERNAL__ } from \"atom.io\"\nimport type { ReadonlyValueToken, StateToken } from \"atom.io\"\n\nimport type { Modifier } from \"~/packages/anvl/src/function\"\n\nexport type AtomStoreReactConfig = {\n useState: typeof Preact.useState | typeof React.useState\n useEffect: typeof Preact.useEffect | typeof React.useEffect\n store?: __INTERNAL__.Store\n}\n\n/* eslint-disable @typescript-eslint/explicit-module-boundary-types */\nexport const composeStoreHooks = ({\n useState,\n useEffect,\n store = __INTERNAL__.IMPLICIT.STORE,\n}: AtomStoreReactConfig) => {\n function useI<T>(token: StateToken<T>): (next: Modifier<T> | T) => void {\n const updateState = (next: Modifier<T> | T) => setState(token, next, store)\n return updateState\n }\n\n function useO<T>(token: ReadonlyValueToken<T> | StateToken<T>): T {\n const state = __INTERNAL__.withdraw(token, store)\n const initialValue = __INTERNAL__.getState__INTERNAL(state, store)\n const [current, dispatch] = useState(initialValue)\n useEffect(() => {\n const unsubscribe = subscribe(\n token,\n ({ newValue, oldValue }) => {\n if (oldValue !== newValue) {\n dispatch(newValue)\n }\n },\n store\n )\n return unsubscribe\n }, [])\n\n return current\n }\n\n function useIO<T>(token: StateToken<T>): [T, (next: Modifier<T> | T) => void] {\n return [useO(token), useI(token)]\n }\n\n function useStore<T>(\n token: StateToken<T>\n ): [T, (next: Modifier<T> | T) => void]\n function useStore<T>(token: ReadonlyValueToken<T>): T\n function useStore<T>(\n token: ReadonlyValueToken<T> | StateToken<T>\n ): T | [T, (next: Modifier<T> | T) => void] {\n if (token.type === `readonly_selector`) {\n return useO(token)\n }\n return useIO(token)\n }\n return { useI, useO, useIO, useStore }\n}\n"],"mappings":";AAIA,SAAS,WAAW,UAAU,oBAAoB;AAY3C,IAAM,oBAAoB,CAAC;AAAA,EAChC;AAAA,EACA;AAAA,EACA,QAAQ,aAAa,SAAS;AAChC,MAA4B;AAC1B,WAAS,KAAQ,OAAuD;AACtE,UAAM,cAAc,CAAC,SAA0B,SAAS,OAAO,MAAM,KAAK;AAC1E,WAAO;AAAA,EACT;AAEA,WAAS,KAAQ,OAAiD;AAChE,UAAM,QAAQ,aAAa,SAAS,OAAO,KAAK;AAChD,UAAM,eAAe,aAAa,mBAAmB,OAAO,KAAK;AACjE,UAAM,CAAC,SAAS,QAAQ,IAAI,SAAS,YAAY;AACjD,cAAU,MAAM;AACd,YAAM,cAAc;AAAA,QAClB;AAAA,QACA,CAAC,EAAE,UAAU,SAAS,MAAM;AAC1B,cAAI,aAAa,UAAU;AACzB,qBAAS,QAAQ;AAAA,UACnB;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAAG,CAAC,CAAC;AAEL,WAAO;AAAA,EACT;AAEA,WAAS,MAAS,OAA4D;AAC5E,WAAO,CAAC,KAAK,KAAK,GAAG,KAAK,KAAK,CAAC;AAAA,EAClC;AAMA,WAAS,SACP,OAC0C;AAC1C,QAAI,MAAM,SAAS,qBAAqB;AACtC,aAAO,KAAK,KAAK;AAAA,IACnB;AACA,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,SAAO,EAAE,MAAM,MAAM,OAAO,SAAS;AACvC;","names":[]}
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "atom.io-react",
3
+ "private": true,
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "module": "dist/index.mjs",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "browser": "./dist/index.mjs",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ }
15
+ }
package/src/atom.ts ADDED
@@ -0,0 +1,43 @@
1
+ import type * as Rx from "rxjs"
2
+
3
+ import type { Serializable } from "~/packages/anvl/src/json"
4
+
5
+ import type { AtomToken } from "."
6
+ import { atomFamily__INTERNAL, atom__INTERNAL } from "./internal"
7
+
8
+ export type Effectors<T> = {
9
+ setSelf: <V extends T>(next: V | ((oldValue: T) => V)) => void
10
+ onSet: (callback: (options: { newValue: T; oldValue: T }) => void) => void
11
+ }
12
+
13
+ export type AtomEffect<T> = (tools: Effectors<T>) => void
14
+
15
+ export type AtomOptions<T> = {
16
+ key: string
17
+ default: T | (() => T)
18
+ effects?: AtomEffect<T>[]
19
+ }
20
+
21
+ export function atom<T>(options: AtomOptions<T>): AtomToken<T> {
22
+ return atom__INTERNAL<T>(options)
23
+ }
24
+
25
+ export type AtomFamilyOptions<T, K extends Serializable> = {
26
+ key: string
27
+ default: T | ((key: K) => T)
28
+ effects?: (key: K) => AtomEffect<T>[]
29
+ }
30
+
31
+ export type AtomFamily<T, K extends Serializable = Serializable> = ((
32
+ key: K
33
+ ) => AtomToken<T>) & {
34
+ key: string
35
+ type: `atom_family`
36
+ subject: Rx.Subject<AtomToken<T>>
37
+ }
38
+
39
+ export function atomFamily<T, K extends Serializable>(
40
+ options: AtomFamilyOptions<T, K>
41
+ ): AtomFamily<T, K> {
42
+ return atomFamily__INTERNAL<T, K>(options)
43
+ }
package/src/index.ts ADDED
@@ -0,0 +1,77 @@
1
+ import {
2
+ IMPLICIT,
3
+ closeOperation,
4
+ openOperation,
5
+ getState__INTERNAL,
6
+ setState__INTERNAL,
7
+ isAtomDefault,
8
+ isSelectorDefault,
9
+ withdraw,
10
+ setLogLevel,
11
+ useLogger,
12
+ } from "./internal"
13
+ import * as __INTERNAL__ from "./internal"
14
+ import type { Store } from "./internal/store"
15
+
16
+ export * from "./atom"
17
+ export * from "./selector"
18
+ export * from "./timeline"
19
+ export * from "./transaction"
20
+ export * from "./subscribe"
21
+ export { __INTERNAL__, setLogLevel, useLogger }
22
+ export type { Serializable } from "~/packages/anvl/src/json"
23
+
24
+ export type AtomToken<_> = {
25
+ key: string
26
+ type: `atom`
27
+ family?: FamilyMetadata
28
+ }
29
+ export type SelectorToken<_> = {
30
+ key: string
31
+ type: `selector`
32
+ family?: FamilyMetadata
33
+ }
34
+ export type StateToken<T> = AtomToken<T> | SelectorToken<T>
35
+
36
+ export type ReadonlyValueToken<_> = {
37
+ key: string
38
+ type: `readonly_selector`
39
+ family?: FamilyMetadata
40
+ }
41
+
42
+ export type FamilyMetadata = {
43
+ key: string
44
+ subKey: string
45
+ }
46
+
47
+ export type TransactionToken<_> = {
48
+ key: string
49
+ type: `transaction`
50
+ }
51
+
52
+ export const getState = <T>(
53
+ token: ReadonlyValueToken<T> | StateToken<T>,
54
+ store: Store = IMPLICIT.STORE
55
+ ): T => {
56
+ const state = withdraw<T>(token, store)
57
+ return getState__INTERNAL(state, store)
58
+ }
59
+
60
+ export const setState = <T, New extends T>(
61
+ token: StateToken<T>,
62
+ value: New | ((oldValue: T) => New),
63
+ store: Store = IMPLICIT.STORE
64
+ ): void => {
65
+ openOperation(store)
66
+ const state = withdraw(token, store)
67
+ setState__INTERNAL(state, value, store)
68
+ closeOperation(store)
69
+ }
70
+
71
+ export const isDefault = (
72
+ token: ReadonlyValueToken<unknown> | StateToken<unknown>,
73
+ store: Store = IMPLICIT.STORE
74
+ ): boolean =>
75
+ token.type === `atom`
76
+ ? isAtomDefault(token.key, store)
77
+ : isSelectorDefault(token.key, store)
@@ -0,0 +1,50 @@
1
+ import * as Rx from "rxjs"
2
+
3
+ import { deposit } from "./get"
4
+ import { markAtomAsDefault } from "./is-default"
5
+ import { cacheValue, hasKeyBeenUsed, storeAtom } from "./operation"
6
+ import type { Store } from "./store"
7
+ import { IMPLICIT } from "./store"
8
+ import { target } from "./transaction-internal"
9
+ import type { AtomToken, FamilyMetadata, UpdateHandler } from ".."
10
+ import { setState, subscribe } from ".."
11
+ import type { AtomOptions } from "../atom"
12
+
13
+ export type Atom<T> = {
14
+ key: string
15
+ type: `atom`
16
+ family?: FamilyMetadata
17
+ subject: Rx.Subject<{ newValue: T; oldValue: T }>
18
+ default: T
19
+ }
20
+
21
+ export function atom__INTERNAL<T>(
22
+ options: AtomOptions<T>,
23
+ family?: FamilyMetadata,
24
+ store: Store = IMPLICIT.STORE
25
+ ): AtomToken<T> {
26
+ const core = target(store)
27
+ if (hasKeyBeenUsed(options.key, store)) {
28
+ store.config.logger?.error?.(
29
+ `Key "${options.key}" already exists in the store.`
30
+ )
31
+ return deposit(core.atoms.get(options.key))
32
+ }
33
+ const subject = new Rx.Subject<{ newValue: T; oldValue: T }>()
34
+ const newAtom = {
35
+ ...options,
36
+ subject,
37
+ type: `atom`,
38
+ ...(family && { family }),
39
+ } as const
40
+ const initialValue =
41
+ options.default instanceof Function ? options.default() : options.default
42
+ storeAtom(newAtom, store)
43
+ markAtomAsDefault(options.key, store)
44
+ cacheValue(options.key, initialValue, store)
45
+ const token = deposit(newAtom)
46
+ const setSelf = (next) => setState(token, next, store)
47
+ const onSet = (handle: UpdateHandler<T>) => subscribe(token, handle, store)
48
+ options.effects?.forEach((effect) => effect({ setSelf, onSet }))
49
+ return token
50
+ }
@@ -0,0 +1,142 @@
1
+ import * as Rx from "rxjs"
2
+
3
+ import type { Serializable } from "~/packages/anvl/src/json"
4
+ import { stringifyJson } from "~/packages/anvl/src/json"
5
+
6
+ import type { Store } from "."
7
+ import {
8
+ atom__INTERNAL,
9
+ withdraw,
10
+ selector__INTERNAL,
11
+ target,
12
+ deposit,
13
+ IMPLICIT,
14
+ } from "."
15
+ import type {
16
+ AtomFamily,
17
+ AtomFamilyOptions,
18
+ AtomToken,
19
+ FamilyMetadata,
20
+ ReadonlySelectorFamily,
21
+ ReadonlySelectorFamilyOptions,
22
+ ReadonlyValueToken,
23
+ SelectorFamily,
24
+ SelectorFamilyOptions,
25
+ SelectorToken,
26
+ } from ".."
27
+
28
+ export function atomFamily__INTERNAL<T, K extends Serializable>(
29
+ options: AtomFamilyOptions<T, K>,
30
+ store: Store = IMPLICIT.STORE
31
+ ): AtomFamily<T, K> {
32
+ const subject = new Rx.Subject<AtomToken<T>>()
33
+ return Object.assign(
34
+ (key: K): AtomToken<T> => {
35
+ const subKey = stringifyJson(key)
36
+ const family: FamilyMetadata = { key: options.key, subKey }
37
+ const fullKey = `${options.key}__${subKey}`
38
+ const existing = withdraw({ key: fullKey, type: `atom` }, store)
39
+ const token = existing
40
+ ? deposit(existing)
41
+ : atom__INTERNAL<T>(
42
+ {
43
+ key: fullKey,
44
+ default:
45
+ options.default instanceof Function
46
+ ? options.default(key)
47
+ : options.default,
48
+ effects: options.effects?.(key),
49
+ },
50
+ family,
51
+ store
52
+ )
53
+ subject.next(token)
54
+ return token
55
+ },
56
+ {
57
+ key: options.key,
58
+ type: `atom_family`,
59
+ subject,
60
+ } as const
61
+ )
62
+ }
63
+
64
+ export function readonlySelectorFamily__INTERNAL<T, K extends Serializable>(
65
+ options: SelectorFamilyOptions<T, K>,
66
+ store?: Store
67
+ ): ReadonlySelectorFamily<T, K> {
68
+ const core = target(store)
69
+ const subject = new Rx.Subject<ReadonlyValueToken<T>>()
70
+ return Object.assign(
71
+ (key: K): ReadonlyValueToken<T> => {
72
+ const subKey = stringifyJson(key)
73
+ const family: FamilyMetadata = { key: options.key, subKey }
74
+ const fullKey = `${options.key}__${subKey}`
75
+ const existing = core.readonlySelectors.get(fullKey)
76
+ if (existing) {
77
+ return deposit(existing)
78
+ }
79
+ return selector__INTERNAL<T>(
80
+ {
81
+ key: fullKey,
82
+ get: options.get(key),
83
+ },
84
+ family,
85
+ store
86
+ ) as ReadonlyValueToken<T>
87
+ },
88
+ {
89
+ key: options.key,
90
+ type: `readonly_selector_family`,
91
+ subject,
92
+ } as const
93
+ ) as ReadonlySelectorFamily<T, K>
94
+ }
95
+
96
+ export function selectorFamily__INTERNAL<T, K extends Serializable>(
97
+ options: SelectorFamilyOptions<T, K>,
98
+ store?: Store
99
+ ): SelectorFamily<T, K>
100
+ export function selectorFamily__INTERNAL<T, K extends Serializable>(
101
+ options: ReadonlySelectorFamilyOptions<T, K>,
102
+ store?: Store
103
+ ): ReadonlySelectorFamily<T, K>
104
+ export function selectorFamily__INTERNAL<T, K extends Serializable>(
105
+ options: ReadonlySelectorFamilyOptions<T, K> | SelectorFamilyOptions<T, K>,
106
+ store: Store = IMPLICIT.STORE
107
+ ): ReadonlySelectorFamily<T, K> | SelectorFamily<T, K> {
108
+ const isReadonly = !(`set` in options)
109
+
110
+ if (isReadonly) {
111
+ return readonlySelectorFamily__INTERNAL(options as any, store)
112
+ }
113
+ const core = target(store)
114
+ const subject = new Rx.Subject<SelectorToken<T>>()
115
+
116
+ return Object.assign(
117
+ (key: K): SelectorToken<T> => {
118
+ const subKey = stringifyJson(key)
119
+ const family: FamilyMetadata = { key: options.key, subKey }
120
+ const fullKey = `${options.key}__${subKey}`
121
+ const existing = core.selectors.get(fullKey)
122
+ if (existing) {
123
+ return deposit(existing)
124
+ }
125
+ const token = selector__INTERNAL<T>(
126
+ {
127
+ key: fullKey,
128
+ get: options.get(key),
129
+ set: options.set(key),
130
+ },
131
+ family,
132
+ store
133
+ )
134
+ subject.next(token)
135
+ return token
136
+ },
137
+ {
138
+ key: options.key,
139
+ type: `selector_family`,
140
+ } as const
141
+ ) as SelectorFamily<T, K>
142
+ }
@@ -0,0 +1,107 @@
1
+ import HAMT from "hamt_plus"
2
+
3
+ import type { Atom, ReadonlySelector, Selector, Store } from "."
4
+ import { target, isValueCached, readCachedValue, IMPLICIT } from "."
5
+ import type {
6
+ AtomToken,
7
+ ReadonlyValueToken,
8
+ SelectorToken,
9
+ StateToken,
10
+ Transaction,
11
+ TransactionToken,
12
+ ƒn,
13
+ } from ".."
14
+
15
+ export const computeSelectorState = <T>(
16
+ selector: ReadonlySelector<T> | Selector<T>
17
+ ): T => selector.get()
18
+
19
+ export function lookup(
20
+ key: string,
21
+ store: Store
22
+ ): AtomToken<unknown> | ReadonlyValueToken<unknown> | SelectorToken<unknown> {
23
+ const core = target(store)
24
+ const type = HAMT.has(key, core.atoms)
25
+ ? `atom`
26
+ : HAMT.has(key, core.selectors)
27
+ ? `selector`
28
+ : `readonly_selector`
29
+ return { key, type }
30
+ }
31
+
32
+ export function withdraw<T>(token: AtomToken<T>, store: Store): Atom<T>
33
+ export function withdraw<T>(token: SelectorToken<T>, store: Store): Selector<T>
34
+ export function withdraw<T>(
35
+ token: StateToken<T>,
36
+ store: Store
37
+ ): Atom<T> | Selector<T>
38
+ export function withdraw<T>(
39
+ token: ReadonlyValueToken<T>,
40
+ store: Store
41
+ ): ReadonlySelector<T>
42
+ export function withdraw<T>(
43
+ token: TransactionToken<T>,
44
+ store: Store
45
+ ): Transaction<T extends ƒn ? T : never>
46
+ export function withdraw<T>(
47
+ token: ReadonlyValueToken<T> | StateToken<T>,
48
+ store: Store
49
+ ): Atom<T> | ReadonlySelector<T> | Selector<T>
50
+ export function withdraw<T>(
51
+ token: ReadonlyValueToken<T> | StateToken<T> | TransactionToken<T>,
52
+ store: Store
53
+ ):
54
+ | Atom<T>
55
+ | ReadonlySelector<T>
56
+ | Selector<T>
57
+ | Transaction<T extends ƒn ? T : never> {
58
+ const core = target(store)
59
+ return (
60
+ HAMT.get(token.key, core.atoms) ??
61
+ HAMT.get(token.key, core.selectors) ??
62
+ HAMT.get(token.key, core.readonlySelectors) ??
63
+ HAMT.get(token.key, core.transactions)
64
+ )
65
+ }
66
+
67
+ export function deposit<T>(state: Atom<T>): AtomToken<T>
68
+ export function deposit<T>(state: Selector<T>): SelectorToken<T>
69
+ export function deposit<T>(state: Atom<T> | Selector<T>): StateToken<T>
70
+ export function deposit<T>(state: ReadonlySelector<T>): ReadonlyValueToken<T>
71
+ export function deposit<T>(
72
+ state: Transaction<T extends ƒn ? T : never>
73
+ ): TransactionToken<T>
74
+ export function deposit<T>(
75
+ state: Atom<T> | ReadonlySelector<T> | Selector<T>
76
+ ): ReadonlyValueToken<T> | StateToken<T>
77
+ export function deposit<T>(
78
+ state:
79
+ | Atom<T>
80
+ | ReadonlySelector<T>
81
+ | Selector<T>
82
+ | Transaction<T extends ƒn ? T : never>
83
+ ): ReadonlyValueToken<T> | StateToken<T> | TransactionToken<T> {
84
+ return {
85
+ key: state.key,
86
+ type: state.type,
87
+ ...(`family` in state && { family: state.family }),
88
+ }
89
+ }
90
+
91
+ export const getState__INTERNAL = <T>(
92
+ state: Atom<T> | ReadonlySelector<T> | Selector<T>,
93
+ store: Store = IMPLICIT.STORE
94
+ ): T => {
95
+ if (isValueCached(state.key, store)) {
96
+ store.config.logger?.info(`>> read "${state.key}"`)
97
+ return readCachedValue(state.key, store)
98
+ }
99
+ if (`get` in state) {
100
+ store.config.logger?.info(`-> calc "${state.key}"`)
101
+ return computeSelectorState(state)
102
+ }
103
+ store.config.logger?.error(
104
+ `Attempted to get atom "${state.key}", which was never initialized in store "${store.config.name}".`
105
+ )
106
+ return state.default
107
+ }
@@ -0,0 +1,12 @@
1
+ export * from "./atom-internal"
2
+ export * from "./families-internal"
3
+ export * from "./get"
4
+ export * from "./is-default"
5
+ export * from "./logger"
6
+ export * from "./operation"
7
+ export * from "./selector-internal"
8
+ export * from "./set"
9
+ export * from "./store"
10
+ export * from "./subscribe-internal"
11
+ export * from "./timeline-internal"
12
+ export * from "./transaction-internal"
@@ -0,0 +1,35 @@
1
+ import type { Store } from "."
2
+ import { target, IMPLICIT, traceAllSelectorAtoms } from "."
3
+
4
+ export const isAtomDefault = (
5
+ key: string,
6
+ store: Store = IMPLICIT.STORE
7
+ ): boolean => {
8
+ const core = target(store)
9
+ return core.atomsThatAreDefault.has(key)
10
+ }
11
+
12
+ export const markAtomAsDefault = (
13
+ key: string,
14
+ store: Store = IMPLICIT.STORE
15
+ ): void => {
16
+ const core = target(store)
17
+ core.atomsThatAreDefault = new Set(core.atomsThatAreDefault).add(key)
18
+ }
19
+
20
+ export const markAtomAsNotDefault = (
21
+ key: string,
22
+ store: Store = IMPLICIT.STORE
23
+ ): void => {
24
+ const core = target(store)
25
+ core.atomsThatAreDefault = new Set(target(store).atomsThatAreDefault)
26
+ core.atomsThatAreDefault.delete(key)
27
+ }
28
+
29
+ export const isSelectorDefault = (
30
+ key: string,
31
+ store: Store = IMPLICIT.STORE
32
+ ): boolean => {
33
+ const roots = traceAllSelectorAtoms(key, store)
34
+ return roots.every((root) => isAtomDefault(root.key, store))
35
+ }
@@ -0,0 +1,46 @@
1
+ import { doNothing } from "~/packages/anvl/src/function"
2
+
3
+ import type { Store } from "./store"
4
+ import { IMPLICIT } from "./store"
5
+
6
+ export type Logger = Pick<Console, `error` | `info` | `warn`>
7
+ export const LOG_LEVELS: ReadonlyArray<keyof Logger> = [
8
+ `info`,
9
+ `warn`,
10
+ `error`,
11
+ ] as const
12
+
13
+ export const setLogLevel = (
14
+ preferredLevel: `error` | `info` | `warn` | null,
15
+ store: Store = IMPLICIT.STORE
16
+ ): void => {
17
+ const { logger__INTERNAL } = store.config
18
+ if (preferredLevel === null) {
19
+ store.config.logger = null
20
+ } else {
21
+ store.config.logger = { ...console }
22
+ LOG_LEVELS.forEach((logLevel) => {
23
+ if (LOG_LEVELS.indexOf(logLevel) < LOG_LEVELS.indexOf(preferredLevel)) {
24
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
25
+ store.config.logger![logLevel] = doNothing
26
+ } else {
27
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
28
+ store.config.logger![logLevel] = logger__INTERNAL[logLevel]
29
+ }
30
+ })
31
+ }
32
+ }
33
+
34
+ export const useLogger = (
35
+ logger: Logger,
36
+ store: Store = IMPLICIT.STORE
37
+ ): void => {
38
+ const currentLogLevel =
39
+ store.config.logger === null
40
+ ? null
41
+ : LOG_LEVELS.find(
42
+ (logLevel) => store.config.logger?.[logLevel] !== doNothing
43
+ ) ?? null
44
+ store.config.logger__INTERNAL = { ...logger }
45
+ setLogLevel(currentLogLevel, store)
46
+ }