@effect-atom/atom 0.1.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.
- package/Atom/package.json +6 -0
- package/AtomRef/package.json +6 -0
- package/Hydration/package.json +6 -0
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/Registry/package.json +6 -0
- package/Result/package.json +6 -0
- package/dist/cjs/Atom.js +1079 -0
- package/dist/cjs/Atom.js.map +1 -0
- package/dist/cjs/AtomRef.js +261 -0
- package/dist/cjs/AtomRef.js.map +1 -0
- package/dist/cjs/Hydration.js +100 -0
- package/dist/cjs/Hydration.js.map +1 -0
- package/dist/cjs/Registry.js +128 -0
- package/dist/cjs/Registry.js.map +1 -0
- package/dist/cjs/Result.js +454 -0
- package/dist/cjs/Result.js.map +1 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/internal/registry.js +701 -0
- package/dist/cjs/internal/registry.js.map +1 -0
- package/dist/cjs/internal/runtime.js +92 -0
- package/dist/cjs/internal/runtime.js.map +1 -0
- package/dist/dts/Atom.d.ts +597 -0
- package/dist/dts/Atom.d.ts.map +1 -0
- package/dist/dts/AtomRef.d.ts +55 -0
- package/dist/dts/AtomRef.d.ts.map +1 -0
- package/dist/dts/Hydration.d.ts +27 -0
- package/dist/dts/Hydration.d.ts.map +1 -0
- package/dist/dts/Registry.d.ts +115 -0
- package/dist/dts/Registry.d.ts.map +1 -0
- package/dist/dts/Result.d.ts +351 -0
- package/dist/dts/Result.d.ts.map +1 -0
- package/dist/dts/index.d.ts +21 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/internal/registry.d.ts +2 -0
- package/dist/dts/internal/registry.d.ts.map +1 -0
- package/dist/dts/internal/runtime.d.ts +2 -0
- package/dist/dts/internal/runtime.d.ts.map +1 -0
- package/dist/esm/Atom.js +1029 -0
- package/dist/esm/Atom.js.map +1 -0
- package/dist/esm/AtomRef.js +232 -0
- package/dist/esm/AtomRef.js.map +1 -0
- package/dist/esm/Hydration.js +71 -0
- package/dist/esm/Hydration.js.map +1 -0
- package/dist/esm/Registry.js +98 -0
- package/dist/esm/Registry.js.map +1 -0
- package/dist/esm/Result.js +403 -0
- package/dist/esm/Result.js.map +1 -0
- package/dist/esm/index.js +21 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/registry.js +672 -0
- package/dist/esm/internal/registry.js.map +1 -0
- package/dist/esm/internal/runtime.js +64 -0
- package/dist/esm/internal/runtime.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/package.json +72 -0
- package/src/Atom.ts +1865 -0
- package/src/AtomRef.ts +282 -0
- package/src/Hydration.ts +98 -0
- package/src/Registry.ts +204 -0
- package/src/Result.ts +767 -0
- package/src/index.ts +24 -0
- package/src/internal/registry.ts +810 -0
- package/src/internal/runtime.ts +63 -0
package/dist/cjs/Atom.js
ADDED
|
@@ -0,0 +1,1079 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.writable = exports.withServerValueInitial = exports.withServerValue = exports.withLabel = exports.withFallback = exports.windowFocusSignal = exports.update = exports.transform = exports.toStreamResult = exports.toStream = exports.subscriptionRef = exports.subscribable = exports.setLazy = exports.setIdleTTL = exports.set = exports.serializable = exports.searchParam = exports.runtime = exports.refreshOnWindowFocus = exports.refresh = exports.readable = exports.pull = exports.optimisticFn = exports.optimistic = exports.modify = exports.mapResult = exports.map = exports.makeRefreshOnSignal = exports.make = exports.kvs = exports.keepAlive = exports.isWritable = exports.isSerializable = exports.initialValue = exports.getServerValue = exports.getResult = exports.get = exports.fnSync = exports.fn = exports.family = exports.defaultMemoMap = exports.debounce = exports.context = exports.batch = exports.autoDispose = exports.WritableTypeId = exports.TypeId = exports.ServerValueTypeId = exports.SerializableTypeId = exports.Reset = void 0;
|
|
7
|
+
var KeyValueStore = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("@effect/platform/KeyValueStore"));
|
|
8
|
+
var Arr = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Array"));
|
|
9
|
+
var _Cause = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Cause"));
|
|
10
|
+
var Cause = _Cause;
|
|
11
|
+
var Channel = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Channel"));
|
|
12
|
+
var Chunk = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Chunk"));
|
|
13
|
+
var EffectContext = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Context"));
|
|
14
|
+
var Duration = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Duration"));
|
|
15
|
+
var Effect = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Effect"));
|
|
16
|
+
var Either = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Either"));
|
|
17
|
+
var Exit = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Exit"));
|
|
18
|
+
var Fiber = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Fiber"));
|
|
19
|
+
var FiberRef = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/FiberRef"));
|
|
20
|
+
var _Function = /*#__PURE__*/require("effect/Function");
|
|
21
|
+
var _GlobalValue = /*#__PURE__*/require("effect/GlobalValue");
|
|
22
|
+
var Inspectable = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Inspectable"));
|
|
23
|
+
var Layer = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Layer"));
|
|
24
|
+
var MutableHashMap = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/MutableHashMap"));
|
|
25
|
+
var Option = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Option"));
|
|
26
|
+
var _Pipeable = /*#__PURE__*/require("effect/Pipeable");
|
|
27
|
+
var Runtime = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Runtime"));
|
|
28
|
+
var Schema = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Schema"));
|
|
29
|
+
var Scope = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Scope"));
|
|
30
|
+
var Stream = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Stream"));
|
|
31
|
+
var Subscribable = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/Subscribable"));
|
|
32
|
+
var SubscriptionRef = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("effect/SubscriptionRef"));
|
|
33
|
+
var internalRegistry = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("./internal/registry.js"));
|
|
34
|
+
var _runtime = /*#__PURE__*/require("./internal/runtime.js");
|
|
35
|
+
var _Registry = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("./Registry.js"));
|
|
36
|
+
var Registry = _Registry;
|
|
37
|
+
var Result = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("./Result.js"));
|
|
38
|
+
function _interopRequireWildcard(e, t) {
|
|
39
|
+
if ("function" == typeof WeakMap) var r = new WeakMap(),
|
|
40
|
+
n = new WeakMap();
|
|
41
|
+
return (_interopRequireWildcard = function (e, t) {
|
|
42
|
+
if (!t && e && e.__esModule) return e;
|
|
43
|
+
var o,
|
|
44
|
+
i,
|
|
45
|
+
f = {
|
|
46
|
+
__proto__: null,
|
|
47
|
+
default: e
|
|
48
|
+
};
|
|
49
|
+
if (null === e || "object" != typeof e && "function" != typeof e) return f;
|
|
50
|
+
if (o = t ? n : r) {
|
|
51
|
+
if (o.has(e)) return o.get(e);
|
|
52
|
+
o.set(e, f);
|
|
53
|
+
}
|
|
54
|
+
for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]);
|
|
55
|
+
return f;
|
|
56
|
+
})(e, t);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* @since 1.0.0
|
|
60
|
+
*/
|
|
61
|
+
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @since 1.0.0
|
|
65
|
+
* @category type ids
|
|
66
|
+
*/
|
|
67
|
+
const TypeId = exports.TypeId = "~effect-atom/atom/Atom";
|
|
68
|
+
/**
|
|
69
|
+
* @since 1.0.0
|
|
70
|
+
* @category type ids
|
|
71
|
+
*/
|
|
72
|
+
const WritableTypeId = exports.WritableTypeId = "~effect-atom/atom/Atom/Writable";
|
|
73
|
+
const AtomProto = {
|
|
74
|
+
[TypeId]: TypeId,
|
|
75
|
+
pipe() {
|
|
76
|
+
return (0, _Pipeable.pipeArguments)(this, arguments);
|
|
77
|
+
},
|
|
78
|
+
toJSON() {
|
|
79
|
+
return {
|
|
80
|
+
_id: "Atom",
|
|
81
|
+
keepAlive: this.keepAlive,
|
|
82
|
+
lazy: this.lazy,
|
|
83
|
+
label: this.label
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
toString() {
|
|
87
|
+
return Inspectable.format(this);
|
|
88
|
+
},
|
|
89
|
+
[Inspectable.NodeInspectSymbol]() {
|
|
90
|
+
return this.toJSON();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const RuntimeProto = {
|
|
94
|
+
...AtomProto,
|
|
95
|
+
atom(arg, options) {
|
|
96
|
+
const read = makeRead(arg, options);
|
|
97
|
+
return readable(get => {
|
|
98
|
+
const previous = get.self();
|
|
99
|
+
const runtimeResult = get(this);
|
|
100
|
+
if (runtimeResult._tag !== "Success") {
|
|
101
|
+
return Result.replacePrevious(runtimeResult, previous);
|
|
102
|
+
}
|
|
103
|
+
return read(get, runtimeResult.value);
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
fn(arg, options) {
|
|
107
|
+
if (arguments.length === 0) {
|
|
108
|
+
return (arg, options) => makeFnRuntime(this, arg, options);
|
|
109
|
+
}
|
|
110
|
+
return makeFnRuntime(this, arg, options);
|
|
111
|
+
},
|
|
112
|
+
pull(arg, options) {
|
|
113
|
+
const pullSignal = state(0);
|
|
114
|
+
const pullAtom = readable(get => {
|
|
115
|
+
const previous = get.self();
|
|
116
|
+
const runtimeResult = get(this);
|
|
117
|
+
if (runtimeResult._tag !== "Success") {
|
|
118
|
+
return Result.replacePrevious(runtimeResult, previous);
|
|
119
|
+
}
|
|
120
|
+
return makeEffect(get, makeStreamPullEffect(get, pullSignal, arg, options), Result.initial(true), runtimeResult.value);
|
|
121
|
+
});
|
|
122
|
+
return makeStreamPull(pullSignal, pullAtom);
|
|
123
|
+
},
|
|
124
|
+
subscriptionRef(ref) {
|
|
125
|
+
return makeSubRef(readable(get => {
|
|
126
|
+
const previous = get.self();
|
|
127
|
+
const runtimeResult = get(this);
|
|
128
|
+
if (runtimeResult._tag !== "Success") {
|
|
129
|
+
return Result.replacePrevious(runtimeResult, previous);
|
|
130
|
+
}
|
|
131
|
+
const value = typeof ref === "function" ? ref(get) : ref;
|
|
132
|
+
return SubscriptionRef.SubscriptionRefTypeId in value ? value : makeEffect(get, value, Result.initial(true), runtimeResult.value);
|
|
133
|
+
}), (get, ref) => {
|
|
134
|
+
const runtime = Result.getOrThrow(get(this));
|
|
135
|
+
return readSubscribable(get, ref, runtime);
|
|
136
|
+
});
|
|
137
|
+
},
|
|
138
|
+
subscribable(arg) {
|
|
139
|
+
return makeSubscribable(readable(get => {
|
|
140
|
+
const previous = get.self();
|
|
141
|
+
const runtimeResult = get(this);
|
|
142
|
+
if (runtimeResult._tag !== "Success") {
|
|
143
|
+
return Result.replacePrevious(runtimeResult, previous);
|
|
144
|
+
}
|
|
145
|
+
const value = typeof arg === "function" ? arg(get) : arg;
|
|
146
|
+
return Subscribable.isSubscribable(value) ? value : makeEffect(get, value, Result.initial(true), runtimeResult.value);
|
|
147
|
+
}), (get, ref) => {
|
|
148
|
+
const runtime = Result.getOrThrow(get(this));
|
|
149
|
+
return readSubscribable(get, ref, runtime);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const makeFnRuntime = (self, arg, options) => {
|
|
154
|
+
const [read, write, argAtom] = makeResultFn(arg, options);
|
|
155
|
+
return writable(get => {
|
|
156
|
+
get.get(argAtom);
|
|
157
|
+
const previous = get.self();
|
|
158
|
+
const runtimeResult = get.get(self);
|
|
159
|
+
if (runtimeResult._tag !== "Success") {
|
|
160
|
+
return Result.replacePrevious(runtimeResult, previous);
|
|
161
|
+
}
|
|
162
|
+
return read(get, runtimeResult.value);
|
|
163
|
+
}, write);
|
|
164
|
+
};
|
|
165
|
+
const WritableProto = {
|
|
166
|
+
...AtomProto,
|
|
167
|
+
[WritableTypeId]: WritableTypeId
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* @since 1.0.0
|
|
171
|
+
* @category refinements
|
|
172
|
+
*/
|
|
173
|
+
const isWritable = atom => WritableTypeId in atom;
|
|
174
|
+
/**
|
|
175
|
+
* @since 1.0.0
|
|
176
|
+
* @category constructors
|
|
177
|
+
*/
|
|
178
|
+
exports.isWritable = isWritable;
|
|
179
|
+
const readable = (read, refresh) => {
|
|
180
|
+
const self = Object.create(AtomProto);
|
|
181
|
+
self.keepAlive = false;
|
|
182
|
+
self.lazy = true;
|
|
183
|
+
self.read = read;
|
|
184
|
+
self.refresh = refresh;
|
|
185
|
+
return self;
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* @since 1.0.0
|
|
189
|
+
* @category constructors
|
|
190
|
+
*/
|
|
191
|
+
exports.readable = readable;
|
|
192
|
+
const writable = (read, write, refresh) => {
|
|
193
|
+
const self = Object.create(WritableProto);
|
|
194
|
+
self.keepAlive = false;
|
|
195
|
+
self.lazy = true;
|
|
196
|
+
self.read = read;
|
|
197
|
+
self.write = write;
|
|
198
|
+
self.refresh = refresh;
|
|
199
|
+
return self;
|
|
200
|
+
};
|
|
201
|
+
exports.writable = writable;
|
|
202
|
+
function constSetSelf(ctx, value) {
|
|
203
|
+
ctx.setSelf(value);
|
|
204
|
+
}
|
|
205
|
+
// -----------------------------------------------------------------------------
|
|
206
|
+
// constructors
|
|
207
|
+
// -----------------------------------------------------------------------------
|
|
208
|
+
/**
|
|
209
|
+
* @since 1.0.0
|
|
210
|
+
* @category constructors
|
|
211
|
+
*/
|
|
212
|
+
const make = (arg, options) => {
|
|
213
|
+
const readOrAtom = makeRead(arg, options);
|
|
214
|
+
if (TypeId in readOrAtom) {
|
|
215
|
+
return readOrAtom;
|
|
216
|
+
}
|
|
217
|
+
return readable(readOrAtom);
|
|
218
|
+
};
|
|
219
|
+
// -----------------------------------------------------------------------------
|
|
220
|
+
// constructors - effect
|
|
221
|
+
// -----------------------------------------------------------------------------
|
|
222
|
+
exports.make = make;
|
|
223
|
+
const isDataType = u => Option.TypeId in u || Either.TypeId in u;
|
|
224
|
+
const makeRead = (arg, options) => {
|
|
225
|
+
if (typeof arg === "function") {
|
|
226
|
+
const create = arg;
|
|
227
|
+
return function (get, providedRuntime) {
|
|
228
|
+
const value = create(get);
|
|
229
|
+
if (typeof value === "object" && value !== null) {
|
|
230
|
+
if (isDataType(value)) {
|
|
231
|
+
return value;
|
|
232
|
+
} else if (Effect.EffectTypeId in value) {
|
|
233
|
+
return effect(get, value, options, providedRuntime);
|
|
234
|
+
} else if (Stream.StreamTypeId in value) {
|
|
235
|
+
return stream(get, value, options, providedRuntime);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return value;
|
|
239
|
+
};
|
|
240
|
+
} else if (typeof arg === "object" && arg !== null) {
|
|
241
|
+
if (isDataType(arg)) {
|
|
242
|
+
return state(arg);
|
|
243
|
+
} else if (Effect.EffectTypeId in arg) {
|
|
244
|
+
return function (get, providedRuntime) {
|
|
245
|
+
return effect(get, arg, options, providedRuntime);
|
|
246
|
+
};
|
|
247
|
+
} else if (Stream.StreamTypeId in arg) {
|
|
248
|
+
return function (get, providedRuntime) {
|
|
249
|
+
return stream(get, arg, options, providedRuntime);
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return state(arg);
|
|
254
|
+
};
|
|
255
|
+
const state = initialValue => writable(function (_get) {
|
|
256
|
+
return initialValue;
|
|
257
|
+
}, constSetSelf);
|
|
258
|
+
const effect = (get, effect, options, runtime) => {
|
|
259
|
+
const initialValue = options?.initialValue !== undefined ? Result.success(options.initialValue) : Result.initial();
|
|
260
|
+
return makeEffect(get, effect, initialValue, runtime, options?.uninterruptible);
|
|
261
|
+
};
|
|
262
|
+
function makeEffect(ctx, effect, initialValue, runtime = Runtime.defaultRuntime, uninterruptible = false) {
|
|
263
|
+
const previous = ctx.self();
|
|
264
|
+
const scope = Effect.runSync(Scope.make());
|
|
265
|
+
ctx.addFinalizer(() => {
|
|
266
|
+
Effect.runFork(Scope.close(scope, Exit.void));
|
|
267
|
+
});
|
|
268
|
+
const contextMap = new Map(runtime.context.unsafeMap);
|
|
269
|
+
contextMap.set(Scope.Scope.key, scope);
|
|
270
|
+
contextMap.set(_Registry.AtomRegistry.key, ctx.registry);
|
|
271
|
+
const scopedRuntime = Runtime.make({
|
|
272
|
+
context: EffectContext.unsafeMake(contextMap),
|
|
273
|
+
fiberRefs: runtime.fiberRefs,
|
|
274
|
+
runtimeFlags: runtime.runtimeFlags
|
|
275
|
+
});
|
|
276
|
+
let syncResult;
|
|
277
|
+
let isAsync = false;
|
|
278
|
+
const cancel = (0, _runtime.runCallbackSync)(scopedRuntime)(effect, function (exit) {
|
|
279
|
+
syncResult = Result.fromExitWithPrevious(exit, previous);
|
|
280
|
+
if (isAsync) ctx.setSelf(syncResult);
|
|
281
|
+
}, uninterruptible);
|
|
282
|
+
isAsync = true;
|
|
283
|
+
if (cancel !== undefined) {
|
|
284
|
+
ctx.addFinalizer(cancel);
|
|
285
|
+
}
|
|
286
|
+
if (syncResult !== undefined) {
|
|
287
|
+
return syncResult;
|
|
288
|
+
} else if (previous._tag === "Some") {
|
|
289
|
+
return Result.waitingFrom(previous);
|
|
290
|
+
}
|
|
291
|
+
return Result.waiting(initialValue);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* @since 1.0.0
|
|
295
|
+
* @category constructors
|
|
296
|
+
*/
|
|
297
|
+
const context = options => {
|
|
298
|
+
let globalLayer;
|
|
299
|
+
function factory(create) {
|
|
300
|
+
const self = Object.create(RuntimeProto);
|
|
301
|
+
self.keepAlive = false;
|
|
302
|
+
self.lazy = true;
|
|
303
|
+
self.refresh = undefined;
|
|
304
|
+
const layerAtom = keepAlive(typeof create === "function" ? readable(get => globalLayer ? Layer.provideMerge(create(get), globalLayer) : create(get)) : readable(() => globalLayer ? Layer.provideMerge(create, globalLayer) : create));
|
|
305
|
+
self.layer = layerAtom;
|
|
306
|
+
self.read = function read(get) {
|
|
307
|
+
const layer = get(layerAtom);
|
|
308
|
+
const build = Effect.flatMap(Effect.flatMap(Effect.scope, scope => Layer.buildWithMemoMap(layer, options.memoMap, scope)), context => Effect.provide(Effect.runtime(), context));
|
|
309
|
+
return effect(get, build, {
|
|
310
|
+
uninterruptible: true
|
|
311
|
+
});
|
|
312
|
+
};
|
|
313
|
+
return self;
|
|
314
|
+
}
|
|
315
|
+
factory.memoMap = options.memoMap;
|
|
316
|
+
factory.addGlobalLayer = layer => {
|
|
317
|
+
if (globalLayer === undefined) {
|
|
318
|
+
globalLayer = layer;
|
|
319
|
+
} else {
|
|
320
|
+
globalLayer = Layer.provideMerge(globalLayer, layer);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
return factory;
|
|
324
|
+
};
|
|
325
|
+
/**
|
|
326
|
+
* @since 1.0.0
|
|
327
|
+
* @category context
|
|
328
|
+
*/
|
|
329
|
+
exports.context = context;
|
|
330
|
+
const defaultMemoMap = exports.defaultMemoMap = /*#__PURE__*/(0, _GlobalValue.globalValue)("@effect-atom/atom/Atom/defaultMemoMap", () => Effect.runSync(Layer.makeMemoMap));
|
|
331
|
+
/**
|
|
332
|
+
* @since 1.0.0
|
|
333
|
+
* @category context
|
|
334
|
+
*/
|
|
335
|
+
const runtime = exports.runtime = /*#__PURE__*/(0, _GlobalValue.globalValue)("@effect-atom/atom/Atom/defaultContext", () => context({
|
|
336
|
+
memoMap: defaultMemoMap
|
|
337
|
+
}));
|
|
338
|
+
// -----------------------------------------------------------------------------
|
|
339
|
+
// constructors - stream
|
|
340
|
+
// -----------------------------------------------------------------------------
|
|
341
|
+
const stream = (get, stream, options, runtime) => {
|
|
342
|
+
const initialValue = options?.initialValue !== undefined ? Result.success(options.initialValue) : Result.initial();
|
|
343
|
+
return makeStream(get, stream, initialValue, runtime);
|
|
344
|
+
};
|
|
345
|
+
function makeStream(ctx, stream, initialValue, runtime = Runtime.defaultRuntime) {
|
|
346
|
+
const previous = ctx.self();
|
|
347
|
+
const writer = Channel.readWithCause({
|
|
348
|
+
onInput(input) {
|
|
349
|
+
return Channel.suspend(() => {
|
|
350
|
+
const last = Chunk.last(input);
|
|
351
|
+
if (last._tag === "Some") {
|
|
352
|
+
ctx.setSelf(Result.success(last.value, {
|
|
353
|
+
waiting: true
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
return writer;
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
onFailure(cause) {
|
|
360
|
+
return Channel.sync(() => {
|
|
361
|
+
ctx.setSelf(Result.failureWithPrevious(cause, {
|
|
362
|
+
previous
|
|
363
|
+
}));
|
|
364
|
+
});
|
|
365
|
+
},
|
|
366
|
+
onDone(_done) {
|
|
367
|
+
return Channel.sync(() => {
|
|
368
|
+
(0, _Function.pipe)(ctx.self(), Option.flatMap(Result.value), Option.match({
|
|
369
|
+
onNone: () => ctx.setSelf(Result.failWithPrevious(new _Cause.NoSuchElementException(), {
|
|
370
|
+
previous
|
|
371
|
+
})),
|
|
372
|
+
onSome: a => ctx.setSelf(Result.success(a))
|
|
373
|
+
}));
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
const registryRuntime = Runtime.make({
|
|
378
|
+
context: EffectContext.add(runtime.context, _Registry.AtomRegistry, ctx.registry),
|
|
379
|
+
fiberRefs: runtime.fiberRefs,
|
|
380
|
+
runtimeFlags: runtime.runtimeFlags
|
|
381
|
+
});
|
|
382
|
+
const cancel = (0, _runtime.runCallbackSync)(registryRuntime)(Channel.runDrain(Channel.pipeTo(Stream.toChannel(stream), writer)), _Function.constVoid);
|
|
383
|
+
if (cancel !== undefined) {
|
|
384
|
+
ctx.addFinalizer(cancel);
|
|
385
|
+
}
|
|
386
|
+
if (previous._tag === "Some") {
|
|
387
|
+
return Result.waitingFrom(previous);
|
|
388
|
+
}
|
|
389
|
+
return Result.waiting(initialValue);
|
|
390
|
+
}
|
|
391
|
+
// -----------------------------------------------------------------------------
|
|
392
|
+
// constructors - subscription ref
|
|
393
|
+
// -----------------------------------------------------------------------------
|
|
394
|
+
/** @internal */
|
|
395
|
+
const readSubscribable = (get, sub, runtime = Runtime.defaultRuntime) => {
|
|
396
|
+
if (Subscribable.TypeId in sub) {
|
|
397
|
+
get.addFinalizer(sub.changes.pipe(Stream.runForEach(value => {
|
|
398
|
+
get.setSelf(value);
|
|
399
|
+
return Effect.void;
|
|
400
|
+
}), Runtime.runCallback(runtime)));
|
|
401
|
+
return Runtime.runSync(runtime)(sub.get);
|
|
402
|
+
} else if (sub._tag !== "Success") {
|
|
403
|
+
return sub;
|
|
404
|
+
}
|
|
405
|
+
return makeStream(get, sub.value.changes, Result.initial(true), runtime);
|
|
406
|
+
};
|
|
407
|
+
const makeSubRef = (refAtom, read) => {
|
|
408
|
+
function write(ctx, value) {
|
|
409
|
+
const ref = ctx.get(refAtom);
|
|
410
|
+
if (SubscriptionRef.SubscriptionRefTypeId in ref) {
|
|
411
|
+
Effect.runSync(SubscriptionRef.set(ref, value));
|
|
412
|
+
} else if (Result.isSuccess(ref)) {
|
|
413
|
+
Effect.runSync(SubscriptionRef.set(ref.value, value));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return writable(get => {
|
|
417
|
+
const ref = get(refAtom);
|
|
418
|
+
if (SubscriptionRef.SubscriptionRefTypeId in ref) {
|
|
419
|
+
return read(get, ref);
|
|
420
|
+
} else if (Result.isSuccess(ref)) {
|
|
421
|
+
return read(get, ref);
|
|
422
|
+
}
|
|
423
|
+
return ref;
|
|
424
|
+
}, write);
|
|
425
|
+
};
|
|
426
|
+
/**
|
|
427
|
+
* @since 1.0.0
|
|
428
|
+
* @category constructors
|
|
429
|
+
*/
|
|
430
|
+
const subscriptionRef = ref => makeSubRef(readable(get => {
|
|
431
|
+
const value = typeof ref === "function" ? ref(get) : ref;
|
|
432
|
+
return SubscriptionRef.SubscriptionRefTypeId in value ? value : makeEffect(get, value, Result.initial(true));
|
|
433
|
+
}), readSubscribable);
|
|
434
|
+
// -----------------------------------------------------------------------------
|
|
435
|
+
// constructors - subscribable
|
|
436
|
+
// -----------------------------------------------------------------------------
|
|
437
|
+
/**
|
|
438
|
+
* @since 1.0.0
|
|
439
|
+
* @category constructors
|
|
440
|
+
*/
|
|
441
|
+
exports.subscriptionRef = subscriptionRef;
|
|
442
|
+
const subscribable = ref => makeSubscribable(readable(get => {
|
|
443
|
+
const value = typeof ref === "function" ? ref(get) : ref;
|
|
444
|
+
return Subscribable.isSubscribable(value) ? value : makeEffect(get, value, Result.initial(true));
|
|
445
|
+
}), readSubscribable);
|
|
446
|
+
exports.subscribable = subscribable;
|
|
447
|
+
const makeSubscribable = (subAtom, read) => readable(get => {
|
|
448
|
+
const sub = get(subAtom);
|
|
449
|
+
if (Subscribable.isSubscribable(sub)) {
|
|
450
|
+
return read(get, sub);
|
|
451
|
+
} else if (Result.isSuccess(sub)) {
|
|
452
|
+
return read(get, sub);
|
|
453
|
+
}
|
|
454
|
+
return sub;
|
|
455
|
+
});
|
|
456
|
+
/**
|
|
457
|
+
* @since 1.0.0
|
|
458
|
+
* @category constructors
|
|
459
|
+
*/
|
|
460
|
+
const fnSync = function (...args) {
|
|
461
|
+
if (args.length === 0) {
|
|
462
|
+
return makeFnSync;
|
|
463
|
+
}
|
|
464
|
+
return makeFnSync(...args);
|
|
465
|
+
};
|
|
466
|
+
exports.fnSync = fnSync;
|
|
467
|
+
const makeFnSync = (f, options) => {
|
|
468
|
+
const argAtom = state([0, undefined]);
|
|
469
|
+
const hasInitialValue = options?.initialValue !== undefined;
|
|
470
|
+
return writable(function (get) {
|
|
471
|
+
;
|
|
472
|
+
get.isFn = true;
|
|
473
|
+
const [counter, arg] = get.get(argAtom);
|
|
474
|
+
if (counter === 0) {
|
|
475
|
+
return hasInitialValue ? options.initialValue : Option.none();
|
|
476
|
+
}
|
|
477
|
+
return hasInitialValue ? f(arg, get) : Option.some(f(arg, get));
|
|
478
|
+
}, function (ctx, arg) {
|
|
479
|
+
batch(() => {
|
|
480
|
+
ctx.set(argAtom, [ctx.get(argAtom)[0] + 1, arg]);
|
|
481
|
+
ctx.refreshSelf();
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
};
|
|
485
|
+
/**
|
|
486
|
+
* @since 1.0.0
|
|
487
|
+
* @category symbols
|
|
488
|
+
*/
|
|
489
|
+
const Reset = exports.Reset = /*#__PURE__*/Symbol.for("@effect-atom/atom/Atom/Reset");
|
|
490
|
+
/**
|
|
491
|
+
* @since 1.0.0
|
|
492
|
+
* @category constructors
|
|
493
|
+
*/
|
|
494
|
+
const fn = function (...args) {
|
|
495
|
+
if (args.length === 0) {
|
|
496
|
+
return makeFn;
|
|
497
|
+
}
|
|
498
|
+
return makeFn(...args);
|
|
499
|
+
};
|
|
500
|
+
exports.fn = fn;
|
|
501
|
+
const makeFn = (f, options) => {
|
|
502
|
+
const [read, write] = makeResultFn(f, options);
|
|
503
|
+
return writable(read, write);
|
|
504
|
+
};
|
|
505
|
+
function makeResultFn(f, options) {
|
|
506
|
+
const argAtom = state([0, undefined]);
|
|
507
|
+
const initialValue = options?.initialValue !== undefined ? Result.success(options.initialValue) : Result.initial();
|
|
508
|
+
function read(get, runtime) {
|
|
509
|
+
;
|
|
510
|
+
get.isFn = true;
|
|
511
|
+
const [counter, arg] = get.get(argAtom);
|
|
512
|
+
if (counter === 0) {
|
|
513
|
+
return initialValue;
|
|
514
|
+
}
|
|
515
|
+
const value = f(arg, get);
|
|
516
|
+
if (Effect.EffectTypeId in value) {
|
|
517
|
+
return makeEffect(get, value, initialValue, runtime);
|
|
518
|
+
}
|
|
519
|
+
return makeStream(get, value, initialValue, runtime);
|
|
520
|
+
}
|
|
521
|
+
function write(ctx, arg) {
|
|
522
|
+
batch(() => {
|
|
523
|
+
if (arg === Reset) {
|
|
524
|
+
ctx.set(argAtom, [0, undefined]);
|
|
525
|
+
} else {
|
|
526
|
+
ctx.set(argAtom, [ctx.get(argAtom)[0] + 1, arg]);
|
|
527
|
+
}
|
|
528
|
+
ctx.refreshSelf();
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
return [read, write, argAtom];
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* @since 1.0.0
|
|
535
|
+
* @category constructors
|
|
536
|
+
*/
|
|
537
|
+
const pull = (create, options) => {
|
|
538
|
+
const pullSignal = state(0);
|
|
539
|
+
const pullAtom = readable(makeRead(function (get) {
|
|
540
|
+
return makeStreamPullEffect(get, pullSignal, create, options);
|
|
541
|
+
}));
|
|
542
|
+
return makeStreamPull(pullSignal, pullAtom);
|
|
543
|
+
};
|
|
544
|
+
exports.pull = pull;
|
|
545
|
+
const makeStreamPullEffect = (get, pullSignal, create, options) => Effect.flatMap(Channel.toPull(Stream.toChannel(typeof create === "function" ? create(get) : create)), pullChunk => {
|
|
546
|
+
const semaphore = Effect.unsafeMakeSemaphore(1);
|
|
547
|
+
const fiber = Option.getOrThrow(Fiber.getCurrentFiber());
|
|
548
|
+
const context = fiber.currentContext;
|
|
549
|
+
let acc = Chunk.empty();
|
|
550
|
+
const pull = Effect.flatMap(Effect.locally(Effect.suspend(() => pullChunk), FiberRef.currentContext, context), Either.match({
|
|
551
|
+
onLeft: () => {
|
|
552
|
+
const items = Chunk.toReadonlyArray(acc);
|
|
553
|
+
if (!Arr.isNonEmptyArray(items)) {
|
|
554
|
+
return Effect.fail(new Cause.NoSuchElementException(`Atom.pull: no items`));
|
|
555
|
+
}
|
|
556
|
+
return Effect.succeed({
|
|
557
|
+
done: true,
|
|
558
|
+
items
|
|
559
|
+
});
|
|
560
|
+
},
|
|
561
|
+
onRight(chunk) {
|
|
562
|
+
let items;
|
|
563
|
+
if (options?.disableAccumulation) {
|
|
564
|
+
items = chunk;
|
|
565
|
+
} else {
|
|
566
|
+
items = Chunk.appendAll(acc, chunk);
|
|
567
|
+
acc = items;
|
|
568
|
+
}
|
|
569
|
+
const arr = Chunk.toReadonlyArray(items);
|
|
570
|
+
if (!Arr.isNonEmptyArray(arr)) {
|
|
571
|
+
return pull;
|
|
572
|
+
}
|
|
573
|
+
return Effect.succeed({
|
|
574
|
+
done: false,
|
|
575
|
+
items: arr
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
}));
|
|
579
|
+
const pullWithSemaphore = semaphore.withPermits(1)(pull);
|
|
580
|
+
const runCallback = (0, _runtime.runCallbackSync)(Runtime.make({
|
|
581
|
+
context,
|
|
582
|
+
fiberRefs: fiber.getFiberRefs(),
|
|
583
|
+
runtimeFlags: Runtime.defaultRuntime.runtimeFlags
|
|
584
|
+
}));
|
|
585
|
+
const cancels = new Set();
|
|
586
|
+
get.addFinalizer(() => {
|
|
587
|
+
for (const cancel of cancels) cancel();
|
|
588
|
+
});
|
|
589
|
+
get.once(pullSignal);
|
|
590
|
+
get.subscribe(pullSignal, () => {
|
|
591
|
+
get.setSelf(Result.waitingFrom(get.self()));
|
|
592
|
+
let cancel;
|
|
593
|
+
// eslint-disable-next-line prefer-const
|
|
594
|
+
cancel = runCallback(pullWithSemaphore, exit => {
|
|
595
|
+
if (cancel) cancels.delete(cancel);
|
|
596
|
+
const result = Result.fromExitWithPrevious(exit, get.self());
|
|
597
|
+
const pending = cancels.size > 0;
|
|
598
|
+
get.setSelf(pending ? Result.waiting(result) : result);
|
|
599
|
+
});
|
|
600
|
+
if (cancel) cancels.add(cancel);
|
|
601
|
+
});
|
|
602
|
+
return pull;
|
|
603
|
+
});
|
|
604
|
+
const makeStreamPull = (pullSignal, pullAtom) => writable(pullAtom.read, function (ctx, _) {
|
|
605
|
+
ctx.set(pullSignal, ctx.get(pullSignal) + 1);
|
|
606
|
+
});
|
|
607
|
+
/**
|
|
608
|
+
* @since 1.0.0
|
|
609
|
+
* @category constructors
|
|
610
|
+
*/
|
|
611
|
+
const family = exports.family = typeof WeakRef === "undefined" || typeof FinalizationRegistry === "undefined" ? f => {
|
|
612
|
+
const atoms = MutableHashMap.empty();
|
|
613
|
+
return function (arg) {
|
|
614
|
+
const atomEntry = MutableHashMap.get(atoms, arg);
|
|
615
|
+
if (atomEntry._tag === "Some") {
|
|
616
|
+
return atomEntry.value;
|
|
617
|
+
}
|
|
618
|
+
const newAtom = f(arg);
|
|
619
|
+
MutableHashMap.set(atoms, arg, newAtom);
|
|
620
|
+
return newAtom;
|
|
621
|
+
};
|
|
622
|
+
} : f => {
|
|
623
|
+
const atoms = MutableHashMap.empty();
|
|
624
|
+
const registry = new FinalizationRegistry(arg => {
|
|
625
|
+
MutableHashMap.remove(atoms, arg);
|
|
626
|
+
});
|
|
627
|
+
return function (arg) {
|
|
628
|
+
const atomEntry = MutableHashMap.get(atoms, arg).pipe(Option.flatMapNullable(ref => ref.deref()));
|
|
629
|
+
if (atomEntry._tag === "Some") {
|
|
630
|
+
return atomEntry.value;
|
|
631
|
+
}
|
|
632
|
+
const newAtom = f(arg);
|
|
633
|
+
MutableHashMap.set(atoms, arg, new WeakRef(newAtom));
|
|
634
|
+
registry.register(newAtom, arg);
|
|
635
|
+
return newAtom;
|
|
636
|
+
};
|
|
637
|
+
};
|
|
638
|
+
/**
|
|
639
|
+
* @since 1.0.0
|
|
640
|
+
* @category combinators
|
|
641
|
+
*/
|
|
642
|
+
const withFallback = exports.withFallback = /*#__PURE__*/(0, _Function.dual)(2, (self, fallback) => {
|
|
643
|
+
function withFallback(get) {
|
|
644
|
+
const result = get(self);
|
|
645
|
+
if (result._tag === "Initial") {
|
|
646
|
+
return Result.waiting(get(fallback));
|
|
647
|
+
}
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
650
|
+
return isWritable(self) ? writable(withFallback, self.write, self.refresh ?? function (refresh) {
|
|
651
|
+
refresh(self);
|
|
652
|
+
}) : readable(withFallback, self.refresh ?? function (refresh) {
|
|
653
|
+
refresh(self);
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
/**
|
|
657
|
+
* @since 1.0.0
|
|
658
|
+
* @category combinators
|
|
659
|
+
*/
|
|
660
|
+
const keepAlive = self => Object.assign(Object.create(Object.getPrototypeOf(self)), {
|
|
661
|
+
...self,
|
|
662
|
+
keepAlive: true
|
|
663
|
+
});
|
|
664
|
+
/**
|
|
665
|
+
* Reverts the `keepAlive` behavior of a reactive value, allowing it to be
|
|
666
|
+
* disposed of when not in use.
|
|
667
|
+
*
|
|
668
|
+
* Note that Atom's have this behavior by default.
|
|
669
|
+
*
|
|
670
|
+
* @since 1.0.0
|
|
671
|
+
* @category combinators
|
|
672
|
+
*/
|
|
673
|
+
exports.keepAlive = keepAlive;
|
|
674
|
+
const autoDispose = self => Object.assign(Object.create(Object.getPrototypeOf(self)), {
|
|
675
|
+
...self,
|
|
676
|
+
keepAlive: false
|
|
677
|
+
});
|
|
678
|
+
/**
|
|
679
|
+
* @since 1.0.0
|
|
680
|
+
* @category combinators
|
|
681
|
+
*/
|
|
682
|
+
exports.autoDispose = autoDispose;
|
|
683
|
+
const setLazy = exports.setLazy = /*#__PURE__*/(0, _Function.dual)(2, (self, lazy) => Object.assign(Object.create(Object.getPrototypeOf(self)), {
|
|
684
|
+
...self,
|
|
685
|
+
lazy
|
|
686
|
+
}));
|
|
687
|
+
/**
|
|
688
|
+
* @since 1.0.0
|
|
689
|
+
* @category combinators
|
|
690
|
+
*/
|
|
691
|
+
const withLabel = exports.withLabel = /*#__PURE__*/(0, _Function.dual)(2, (self, name) => Object.assign(Object.create(Object.getPrototypeOf(self)), {
|
|
692
|
+
...self,
|
|
693
|
+
label: [name, new Error().stack?.split("\n")[5] ?? ""]
|
|
694
|
+
}));
|
|
695
|
+
/**
|
|
696
|
+
* @since 1.0.0
|
|
697
|
+
* @category combinators
|
|
698
|
+
*/
|
|
699
|
+
const setIdleTTL = exports.setIdleTTL = /*#__PURE__*/(0, _Function.dual)(2, (self, duration) => Object.assign(Object.create(Object.getPrototypeOf(self)), {
|
|
700
|
+
...self,
|
|
701
|
+
keepAlive: false,
|
|
702
|
+
idleTTL: Duration.toMillis(duration)
|
|
703
|
+
}));
|
|
704
|
+
/**
|
|
705
|
+
* @since 1.0.0
|
|
706
|
+
* @category combinators
|
|
707
|
+
*/
|
|
708
|
+
const initialValue = exports.initialValue = /*#__PURE__*/(0, _Function.dual)(2, (self, initialValue) => [self, initialValue]);
|
|
709
|
+
/**
|
|
710
|
+
* @since 1.0.0
|
|
711
|
+
* @category combinators
|
|
712
|
+
*/
|
|
713
|
+
const transform = exports.transform = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => isWritable(self) ? writable(f, function (ctx, value) {
|
|
714
|
+
ctx.set(self, value);
|
|
715
|
+
}, self.refresh ?? function (refresh) {
|
|
716
|
+
refresh(self);
|
|
717
|
+
}) : readable(f, self.refresh ?? function (refresh) {
|
|
718
|
+
refresh(self);
|
|
719
|
+
}));
|
|
720
|
+
/**
|
|
721
|
+
* @since 1.0.0
|
|
722
|
+
* @category combinators
|
|
723
|
+
*/
|
|
724
|
+
const map = exports.map = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => transform(self, get => f(get(self))));
|
|
725
|
+
/**
|
|
726
|
+
* @since 1.0.0
|
|
727
|
+
* @category combinators
|
|
728
|
+
*/
|
|
729
|
+
const mapResult = exports.mapResult = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => map(self, Result.map(f)));
|
|
730
|
+
/**
|
|
731
|
+
* @since 1.0.0
|
|
732
|
+
* @category combinators
|
|
733
|
+
*/
|
|
734
|
+
const debounce = exports.debounce = /*#__PURE__*/(0, _Function.dual)(2, (self, duration) => {
|
|
735
|
+
const millis = Duration.toMillis(duration);
|
|
736
|
+
return transform(self, function (get) {
|
|
737
|
+
let timeout;
|
|
738
|
+
let value = get.once(self);
|
|
739
|
+
function update() {
|
|
740
|
+
timeout = undefined;
|
|
741
|
+
get.setSelf(value);
|
|
742
|
+
}
|
|
743
|
+
get.addFinalizer(function () {
|
|
744
|
+
if (timeout) clearTimeout(timeout);
|
|
745
|
+
});
|
|
746
|
+
get.subscribe(self, function (val) {
|
|
747
|
+
value = val;
|
|
748
|
+
if (timeout) clearTimeout(timeout);
|
|
749
|
+
timeout = setTimeout(update, millis);
|
|
750
|
+
});
|
|
751
|
+
return value;
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
/**
|
|
755
|
+
* @since 1.0.0
|
|
756
|
+
* @category Optimistic
|
|
757
|
+
*/
|
|
758
|
+
const optimistic = self => {
|
|
759
|
+
let counter = 0;
|
|
760
|
+
const writeAtom = state([counter, undefined]);
|
|
761
|
+
return writable(get => {
|
|
762
|
+
let lastValue = get.once(self);
|
|
763
|
+
get.subscribe(self, value => {
|
|
764
|
+
lastValue = value;
|
|
765
|
+
if (!Result.isResult(value)) {
|
|
766
|
+
return get.setSelf(value);
|
|
767
|
+
}
|
|
768
|
+
const current = Option.getOrUndefined(get.self());
|
|
769
|
+
if (Result.isSuccess(current) && Result.isSuccess(value)) {
|
|
770
|
+
if (value.timestamp >= current.timestamp) {
|
|
771
|
+
get.setSelf(value);
|
|
772
|
+
}
|
|
773
|
+
} else {
|
|
774
|
+
get.setSelf(value);
|
|
775
|
+
}
|
|
776
|
+
});
|
|
777
|
+
const transitions = new Set();
|
|
778
|
+
const cancels = new Set();
|
|
779
|
+
get.subscribe(writeAtom, ([, atom]) => {
|
|
780
|
+
if (transitions.has(atom)) return;
|
|
781
|
+
transitions.add(atom);
|
|
782
|
+
let cancel;
|
|
783
|
+
// eslint-disable-next-line prefer-const
|
|
784
|
+
cancel = get.registry.subscribe(atom, result => {
|
|
785
|
+
if (Result.isSuccess(result) && result.waiting) {
|
|
786
|
+
return get.setSelf(result.value);
|
|
787
|
+
}
|
|
788
|
+
transitions.delete(atom);
|
|
789
|
+
if (cancel) {
|
|
790
|
+
cancels.delete(cancel);
|
|
791
|
+
cancel();
|
|
792
|
+
}
|
|
793
|
+
if (transitions.size === 0) {
|
|
794
|
+
if (Result.isFailure(result)) {
|
|
795
|
+
get.setSelf(lastValue);
|
|
796
|
+
}
|
|
797
|
+
get.refresh(self);
|
|
798
|
+
}
|
|
799
|
+
}, {
|
|
800
|
+
immediate: true
|
|
801
|
+
});
|
|
802
|
+
if (transitions.has(atom)) {
|
|
803
|
+
cancels.add(cancel);
|
|
804
|
+
} else {
|
|
805
|
+
cancel();
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
get.addFinalizer(() => {
|
|
809
|
+
for (const cancel of cancels) cancel();
|
|
810
|
+
transitions.clear();
|
|
811
|
+
cancels.clear();
|
|
812
|
+
});
|
|
813
|
+
return lastValue;
|
|
814
|
+
}, (ctx, atom) => ctx.set(writeAtom, [++counter, atom]), refresh => refresh(self));
|
|
815
|
+
};
|
|
816
|
+
/**
|
|
817
|
+
* @since 1.0.0
|
|
818
|
+
* @category Optimistic
|
|
819
|
+
*/
|
|
820
|
+
exports.optimistic = optimistic;
|
|
821
|
+
const optimisticFn = exports.optimisticFn = /*#__PURE__*/(0, _Function.dual)(2, (self, options) => {
|
|
822
|
+
const transition = state(Result.initial());
|
|
823
|
+
return fn((arg, get) => {
|
|
824
|
+
let value = options.reducer(get(self), arg);
|
|
825
|
+
if (Result.isResult(value) && !value.waiting) {
|
|
826
|
+
value = Result.waiting(value);
|
|
827
|
+
}
|
|
828
|
+
get.set(transition, Result.success(value, {
|
|
829
|
+
waiting: true
|
|
830
|
+
}));
|
|
831
|
+
get.set(self, transition);
|
|
832
|
+
const fn = typeof options.fn === "function" ? autoDispose(options.fn(value => get.set(transition, Result.success(Result.isResult(value) ? Result.waiting(value) : value, {
|
|
833
|
+
waiting: true
|
|
834
|
+
})))) : options.fn;
|
|
835
|
+
get.set(fn, arg);
|
|
836
|
+
return Effect.onExit(get.result(fn, {
|
|
837
|
+
suspendOnWaiting: true
|
|
838
|
+
}), exit => {
|
|
839
|
+
get.set(transition, Result.fromExit(Exit.as(exit, value)));
|
|
840
|
+
return Effect.void;
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
});
|
|
844
|
+
/**
|
|
845
|
+
* @since 1.0.0
|
|
846
|
+
* @category batching
|
|
847
|
+
*/
|
|
848
|
+
const batch = exports.batch = internalRegistry.batch;
|
|
849
|
+
// -----------------------------------------------------------------------------
|
|
850
|
+
// Focus
|
|
851
|
+
// -----------------------------------------------------------------------------
|
|
852
|
+
/**
|
|
853
|
+
* @since 1.0.0
|
|
854
|
+
* @category Focus
|
|
855
|
+
*/
|
|
856
|
+
const windowFocusSignal = exports.windowFocusSignal = /*#__PURE__*/readable(get => {
|
|
857
|
+
let count = 0;
|
|
858
|
+
function update() {
|
|
859
|
+
if (document.visibilityState === "visible") {
|
|
860
|
+
get.setSelf(++count);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
window.addEventListener("visibilitychange", update);
|
|
864
|
+
get.addFinalizer(() => {
|
|
865
|
+
window.removeEventListener("visibilitychange", update);
|
|
866
|
+
});
|
|
867
|
+
return count;
|
|
868
|
+
});
|
|
869
|
+
/**
|
|
870
|
+
* @since 1.0.0
|
|
871
|
+
* @category Focus
|
|
872
|
+
*/
|
|
873
|
+
const makeRefreshOnSignal = signal => self => transform(self, get => {
|
|
874
|
+
get.subscribe(signal, _ => get.refresh(self));
|
|
875
|
+
get.subscribe(self, value => get.setSelf(value));
|
|
876
|
+
return get.once(self);
|
|
877
|
+
});
|
|
878
|
+
/**
|
|
879
|
+
* @since 1.0.0
|
|
880
|
+
* @category Focus
|
|
881
|
+
*/
|
|
882
|
+
exports.makeRefreshOnSignal = makeRefreshOnSignal;
|
|
883
|
+
const refreshOnWindowFocus = exports.refreshOnWindowFocus = /*#__PURE__*/makeRefreshOnSignal(windowFocusSignal);
|
|
884
|
+
// -----------------------------------------------------------------------------
|
|
885
|
+
// KeyValueStore
|
|
886
|
+
// -----------------------------------------------------------------------------
|
|
887
|
+
/**
|
|
888
|
+
* @since 1.0.0
|
|
889
|
+
* @category KeyValueStore
|
|
890
|
+
*/
|
|
891
|
+
const kvs = options => {
|
|
892
|
+
const setAtom = options.runtime.fn(Effect.fnUntraced(function* (value) {
|
|
893
|
+
const store = (yield* KeyValueStore.KeyValueStore).forSchema(options.schema);
|
|
894
|
+
yield* store.set(options.key, value);
|
|
895
|
+
}));
|
|
896
|
+
const resultAtom = options.runtime.atom(Effect.flatMap(KeyValueStore.KeyValueStore, store => Effect.flatten(store.forSchema(options.schema).get(options.key))));
|
|
897
|
+
return writable(get => {
|
|
898
|
+
get.mount(setAtom);
|
|
899
|
+
return Result.getOrElse(get(resultAtom), options.defaultValue);
|
|
900
|
+
}, (ctx, value) => {
|
|
901
|
+
ctx.set(setAtom, value);
|
|
902
|
+
ctx.setSelf(value);
|
|
903
|
+
});
|
|
904
|
+
};
|
|
905
|
+
// -----------------------------------------------------------------------------
|
|
906
|
+
// URL search params
|
|
907
|
+
// -----------------------------------------------------------------------------
|
|
908
|
+
/**
|
|
909
|
+
* Create an Atom that reads and writes a URL search parameter.
|
|
910
|
+
*
|
|
911
|
+
* Note: If you pass a schema, it has to be synchronous and have no context.
|
|
912
|
+
*
|
|
913
|
+
* @since 1.0.0
|
|
914
|
+
* @category URL search params
|
|
915
|
+
*/
|
|
916
|
+
exports.kvs = kvs;
|
|
917
|
+
const searchParam = (name, options) => {
|
|
918
|
+
const decode = options?.schema && Schema.decodeEither(options.schema);
|
|
919
|
+
const encode = options?.schema && Schema.encodeEither(options.schema);
|
|
920
|
+
return writable(get => {
|
|
921
|
+
const handleUpdate = () => {
|
|
922
|
+
if (searchParamState.updating) return;
|
|
923
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
924
|
+
const newValue = searchParams.get(name) || "";
|
|
925
|
+
if (decode) {
|
|
926
|
+
get.setSelf(Either.getRight(decode(newValue)));
|
|
927
|
+
} else if (newValue !== Option.getOrUndefined(get.self())) {
|
|
928
|
+
get.setSelf(newValue);
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
window.addEventListener("popstate", handleUpdate);
|
|
932
|
+
window.addEventListener("pushstate", handleUpdate);
|
|
933
|
+
get.addFinalizer(() => {
|
|
934
|
+
window.removeEventListener("popstate", handleUpdate);
|
|
935
|
+
window.removeEventListener("pushstate", handleUpdate);
|
|
936
|
+
});
|
|
937
|
+
const value = new URLSearchParams(window.location.search).get(name) || "";
|
|
938
|
+
return decode ? Either.getRight(decode(value)) : value;
|
|
939
|
+
}, (ctx, value) => {
|
|
940
|
+
if (encode) {
|
|
941
|
+
const encoded = Option.flatMap(value, v => Either.getRight(encode(v)));
|
|
942
|
+
searchParamState.updates.set(name, Option.getOrElse(encoded, () => ""));
|
|
943
|
+
value = Option.zipRight(encoded, value);
|
|
944
|
+
} else {
|
|
945
|
+
searchParamState.updates.set(name, value);
|
|
946
|
+
}
|
|
947
|
+
ctx.setSelf(value);
|
|
948
|
+
if (searchParamState.timeout) {
|
|
949
|
+
clearTimeout(searchParamState.timeout);
|
|
950
|
+
}
|
|
951
|
+
searchParamState.timeout = setTimeout(updateSearchParams, 500);
|
|
952
|
+
});
|
|
953
|
+
};
|
|
954
|
+
exports.searchParam = searchParam;
|
|
955
|
+
const searchParamState = {
|
|
956
|
+
timeout: undefined,
|
|
957
|
+
updates: /*#__PURE__*/new Map(),
|
|
958
|
+
updating: false
|
|
959
|
+
};
|
|
960
|
+
function updateSearchParams() {
|
|
961
|
+
searchParamState.timeout = undefined;
|
|
962
|
+
searchParamState.updating = true;
|
|
963
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
964
|
+
for (const [key, value] of searchParamState.updates.entries()) {
|
|
965
|
+
if (value.length > 0) {
|
|
966
|
+
searchParams.set(key, value);
|
|
967
|
+
} else {
|
|
968
|
+
searchParams.delete(key);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
searchParamState.updates.clear();
|
|
972
|
+
const newUrl = `${window.location.pathname}?${searchParams.toString()}`;
|
|
973
|
+
window.history.pushState({}, "", newUrl);
|
|
974
|
+
searchParamState.updating = false;
|
|
975
|
+
}
|
|
976
|
+
// -----------------------------------------------------------------------------
|
|
977
|
+
// conversions
|
|
978
|
+
// -----------------------------------------------------------------------------
|
|
979
|
+
/**
|
|
980
|
+
* @since 1.0.0
|
|
981
|
+
* @category Conversions
|
|
982
|
+
*/
|
|
983
|
+
const toStream = self => Stream.unwrap(Effect.map(_Registry.AtomRegistry, Registry.toStream(self)));
|
|
984
|
+
/**
|
|
985
|
+
* @since 1.0.0
|
|
986
|
+
* @category Conversions
|
|
987
|
+
*/
|
|
988
|
+
exports.toStream = toStream;
|
|
989
|
+
const toStreamResult = self => Stream.unwrap(Effect.map(_Registry.AtomRegistry, Registry.toStreamResult(self)));
|
|
990
|
+
/**
|
|
991
|
+
* @since 1.0.0
|
|
992
|
+
* @category Conversions
|
|
993
|
+
*/
|
|
994
|
+
exports.toStreamResult = toStreamResult;
|
|
995
|
+
const get = self => Effect.map(_Registry.AtomRegistry, _ => _.get(self));
|
|
996
|
+
/**
|
|
997
|
+
* @since 1.0.0
|
|
998
|
+
* @category Conversions
|
|
999
|
+
*/
|
|
1000
|
+
exports.get = get;
|
|
1001
|
+
const modify = exports.modify = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => Effect.map(_Registry.AtomRegistry, _ => _.modify(self, f)));
|
|
1002
|
+
/**
|
|
1003
|
+
* @since 1.0.0
|
|
1004
|
+
* @category Conversions
|
|
1005
|
+
*/
|
|
1006
|
+
const set = exports.set = /*#__PURE__*/(0, _Function.dual)(2, (self, value) => Effect.map(_Registry.AtomRegistry, _ => _.set(self, value)));
|
|
1007
|
+
/**
|
|
1008
|
+
* @since 1.0.0
|
|
1009
|
+
* @category Conversions
|
|
1010
|
+
*/
|
|
1011
|
+
const update = exports.update = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => Effect.map(_Registry.AtomRegistry, _ => _.update(self, f)));
|
|
1012
|
+
/**
|
|
1013
|
+
* @since 1.0.0
|
|
1014
|
+
* @category Conversions
|
|
1015
|
+
*/
|
|
1016
|
+
const getResult = (self, options) => Effect.flatMap(_Registry.AtomRegistry, Registry.getResult(self, options));
|
|
1017
|
+
/**
|
|
1018
|
+
* @since 1.0.0
|
|
1019
|
+
* @category Conversions
|
|
1020
|
+
*/
|
|
1021
|
+
exports.getResult = getResult;
|
|
1022
|
+
const refresh = self => Effect.map(_Registry.AtomRegistry, _ => _.refresh(self));
|
|
1023
|
+
// -----------------------------------------------------------------------------
|
|
1024
|
+
// Serializable
|
|
1025
|
+
// -----------------------------------------------------------------------------
|
|
1026
|
+
/**
|
|
1027
|
+
* @since 1.0.0
|
|
1028
|
+
* @category Serializable
|
|
1029
|
+
*/
|
|
1030
|
+
exports.refresh = refresh;
|
|
1031
|
+
const SerializableTypeId = exports.SerializableTypeId = "~effect-atom/atom/Atom/Serializable";
|
|
1032
|
+
/**
|
|
1033
|
+
* @since 1.0.0
|
|
1034
|
+
* @category Serializable
|
|
1035
|
+
*/
|
|
1036
|
+
const isSerializable = self => SerializableTypeId in self;
|
|
1037
|
+
/**
|
|
1038
|
+
* @since 1.0.0
|
|
1039
|
+
* @category combinators
|
|
1040
|
+
*/
|
|
1041
|
+
exports.isSerializable = isSerializable;
|
|
1042
|
+
const serializable = exports.serializable = /*#__PURE__*/(0, _Function.dual)(2, (self, options) => Object.assign(Object.create(Object.getPrototypeOf(self)), {
|
|
1043
|
+
...self,
|
|
1044
|
+
label: self.label ?? [options.key, new Error().stack?.split("\n")[5] ?? ""],
|
|
1045
|
+
[SerializableTypeId]: {
|
|
1046
|
+
key: options.key,
|
|
1047
|
+
encode: Schema.encodeSync(options.schema),
|
|
1048
|
+
decode: Schema.decodeSync(options.schema)
|
|
1049
|
+
}
|
|
1050
|
+
}));
|
|
1051
|
+
/**
|
|
1052
|
+
* @since 1.0.0
|
|
1053
|
+
* @category ServerValue
|
|
1054
|
+
*/
|
|
1055
|
+
const ServerValueTypeId = exports.ServerValueTypeId = "~effect-atom/atom/Atom/ServerValue";
|
|
1056
|
+
/**
|
|
1057
|
+
* Overrides the value of an Atom when read on the server.
|
|
1058
|
+
*
|
|
1059
|
+
* @since 1.0.0
|
|
1060
|
+
* @category ServerValue
|
|
1061
|
+
*/
|
|
1062
|
+
const withServerValue = exports.withServerValue = /*#__PURE__*/(0, _Function.dual)(2, (self, read) => Object.assign(Object.create(Object.getPrototypeOf(self)), {
|
|
1063
|
+
...self,
|
|
1064
|
+
[ServerValueTypeId]: read
|
|
1065
|
+
}));
|
|
1066
|
+
/**
|
|
1067
|
+
* Sets the Atom's server value to `Result.initial(true)`.
|
|
1068
|
+
*
|
|
1069
|
+
* @since 1.0.0
|
|
1070
|
+
* @category ServerValue
|
|
1071
|
+
*/
|
|
1072
|
+
const withServerValueInitial = self => withServerValue(self, (0, _Function.constant)(Result.initial(true)));
|
|
1073
|
+
/**
|
|
1074
|
+
* @since 1.0.0
|
|
1075
|
+
* @category ServerValue
|
|
1076
|
+
*/
|
|
1077
|
+
exports.withServerValueInitial = withServerValueInitial;
|
|
1078
|
+
const getServerValue = exports.getServerValue = /*#__PURE__*/(0, _Function.dual)(2, (self, registry) => ServerValueTypeId in self ? self[ServerValueTypeId](atom => registry.get(atom)) : registry.get(self));
|
|
1079
|
+
//# sourceMappingURL=Atom.js.map
|