tempest.games 0.2.67 → 0.2.69
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/CHANGELOG.md +14 -0
- package/app/assets/{index-t5Kphr7m.js → index-CCuiNaIa.js} +22 -22
- package/app/index.html +1 -1
- package/bin/backend.bun.js +83218 -347
- package/bin/backend.worker.game.bun.js +3936 -17
- package/bin/backend.worker.tribunal.bun.js +45694 -183
- package/bin/frontend.bun.js +19929 -66
- package/package.json +6 -6
|
@@ -1,21 +1,3940 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var SQ=Object.create;var{getPrototypeOf:vQ,defineProperty:B0,getOwnPropertyNames:TQ}=Object;var gQ=Object.prototype.hasOwnProperty;var MZ=(Q,Z,q)=>{q=Q!=null?SQ(vQ(Q)):{};let z=Z||!Q||!Q.__esModule?B0(q,"default",{value:Q,enumerable:!0}):q;for(let H of TQ(Q))if(!gQ.call(z,H))B0(z,H,{get:()=>Q[H],enumerable:!0});return z};var RZ=(Q,Z)=>()=>(Z||Q((Z={exports:{}}).exports,Z),Z.exports);var FZ=(Q,Z)=>{for(var q in Z)B0(Q,q,{get:Z[q],enumerable:!0,configurable:!0,set:(z)=>Z[q]=()=>z})};var UZ=(Q,Z)=>()=>(Q&&(Z=Q(Q=0)),Z);var xZ=import.meta.require;function m(Q){return _0(A.STORE,Q,void 0)}function c(Q){return G0(A.STORE,Q)}function IZ(...Q){return I(A.STORE,...Q)}function H0(Q){return HQ(A.STORE,Q)}function o0(Q){return XQ(Q,A.STORE)}var S={atom_family:"atom family",atom:"atom",continuity:"continuity",key:"key",mutable_atom_family:"atom family [m]",mutable_atom:"atom [m]",readonly_held_selector_family:"selector family [h]",readonly_held_selector:"selector [h]",readonly_pure_selector_family:"selector family",readonly_pure_selector:"selector",state:"state",timeline:"timeline",transaction:"transaction",unknown:"unknown",writable_held_selector_family:"selector family [wh]",writable_held_selector:"selector [wh]",writable_pure_selector_family:"selector family [w]",writable_pure_selector:"selector [w]"};var h0=(Q)=>(Z,q,z,H,...X)=>{console[Q](`${Z} ${S[q]} \`${z}\` ${H}`,...X)},bQ={error:h0("error"),info:h0("info"),warn:h0("warn")},t0=class{logLevel;filter;logger;constructor(Q,Z,q=bQ){this.logLevel=Q,this.filter=Z,this.logger=q}error=(...Q)=>{if(this.logLevel!==null){let Z=this.filter?.(...Q)??!0;if(Z===!0)this.logger.error(...Q);else if(Z)this.logger.error(...Z)}};info=(...Q)=>{if(this.logLevel==="info"){let Z=this.filter?.(...Q)??!0;if(Z===!0)this.logger.info(...Q);else if(Z)this.logger.info(...Z)}};warn=(...Q)=>{if(this.logLevel!=="error"&&this.logLevel!==null){let Z=this.filter?.(...Q)??!0;if(Z===!0)this.logger.warn(...Q);else if(Z)this.logger.warn(...Z)}}};function a(Q,Z){return[Q,Z].sort().join("\x1F")}function e0(Q){if(typeof Q==="string"===!1)return null;let[Z,q]=Q.split("==");if(!q)return null;let z=Z.slice(4),[H,X]=q.split("++");if(z&&H&&X)return[z,H,X];return null}function X0(Q){return qQ(A.STORE,Q)}function Y0(Q){return M0(A.STORE,Q)}function R(Q){return JSON.parse(Q)}var h=(Q)=>JSON.stringify(Q),yZ=[Array.prototype,Boolean.prototype,Number.prototype,Object.prototype,String.prototype];function YQ(Q){let Z={},q=0;for(let z of Q)Z[z]=q,Z[q]=z,++q;return Z}var GQ="\x01",WQ="\x02",_Q="\x03",NQ="\x04",F0=(Q)=>{switch(typeof Q){case"string":return _Q+Q;case"number":return NQ+Q;case"boolean":return GQ+ +Q;case"object":return WQ}},U0=(Q)=>{switch(Q[0]){case _Q:return Q.slice(1);case NQ:return+Q.slice(1);case GQ:return Q.slice(1)==="1";case WQ:return null}};var jQ=YQ(["add","delete","clear"]),v=class Q extends Set{mode="record";subject=new E;constructor(Z){super(Z);if(Z instanceof Q);}READONLY_VIEW=this;toJSON(){return[...this]}static fromJSON(Z){return new Q(Z)}add(Z){let q=super.add(Z);if(this.mode==="record")this.emit({type:"add",value:Z});return q}clear(){let Z=this.mode==="record"?[...this]:null;if(super.clear(),Z)this.emit({type:"clear",values:Z})}delete(Z){let q=super.delete(Z);if(this.mode==="record")this.emit({type:"delete",value:Z});return q}subscribe(Z,q){return this.subject.subscribe(Z,q)}emit(Z){this.subject.next(Q.packUpdate(Z))}do(Z){this.mode="playback";let q=Q.unpackUpdate(Z);switch(q.type){case"add":this.add(q.value);break;case"delete":this.delete(q.value);break;case"clear":this.clear()}return this.mode="record",null}undo(Z){let q=Q.unpackUpdate(Z);switch(this.mode="playback",q.type){case"add":this.delete(q.value);break;case"delete":this.add(q.value);break;case"clear":{let z=q.values;for(let H of z)this.add(H)}}return this.mode="record",null}static packUpdate(Z){let q=jQ[Z.type]+"\x1F";if(Z.type==="clear")return q+Z.values.map(F0).join("\x1E");return q+F0(Z.value)}static unpackUpdate(Z){let[q,z]=Z.split("\x1F"),H=jQ[q];if(H==="clear")return{type:"clear",values:z.split("\x1E").map(U0)};return{type:H,value:U0(z)}}};function QQ(Q=Math.random){return Q().toString(36).slice(2)}function C(Q){while(Q.child!==null)Q=Q.child;return Q}function v0(Q){while(Q.parent!==null)Q=Q.parent;return Q}var yQ=/^\[object (?:Async|Generator|AsyncGenerator)?Function\]$/;function s(Q){let Z=Object.prototype.toString.call(Q);return yQ.test(Z)}function A0(Q,Z){if(s(Q))return Q(Z);return Q}var I0=class extends Promise{fate;resolve;reject;done=!1;constructor(Q){let Z,q;super((z,H)=>{Z=z,q=H});this.resolve=Z,this.reject=q,this.use(Q instanceof Promise?Q:new Promise(Q))}pass(Q,Z){if(Q===this.fate)this.resolve(Z),this.done=!0}fail(Q,Z){if(Q===this.fate)this.reject(Z),this.done=!0}use(Q){if(this===Q)return;if(Q instanceof Promise){let Z=Q;this.fate=Z,Z.then((q)=>{this.pass(Z,q)},(q)=>{this.fail(Z,q)})}else this.resolve(Q),this.fate=void 0}},E=class{Subscriber;subscribers=new Map;subscribe(Q,Z){return this.subscribers.set(Q,Z),()=>{this.unsubscribe(Q)}}unsubscribe(Q){this.subscribers.delete(Q)}next(Q){let Z=this.subscribers.values();for(let q of Z)q(Q)}},pQ=class extends E{state;constructor(Q){super();this.state=Q}next(Q){this.state=Q,super.next(Q)}},mQ=class Q{_buffer;_index=0;constructor(Z){let q;if(typeof Z==="number")q=Z;else q=Z.length;this._buffer=Array.from({length:q})}get buffer(){return this._buffer}get index(){return this._index}add(Z){this._buffer[this._index]=Z,this._index=(this._index+1)%this._buffer.length}copy(){let Z=new Q([...this._buffer]);return Z._index=this._index,Z}};function b(Q){let Z={key:Q.key,type:Q.type};if("family"in Q)Z.family=Q.family;return Z}var K=class extends Map{deleted=new Set;changed=new Set;source;constructor(Q){super();this.source=Q}get(Q){if(super.has(Q))return super.get(Q);if(!this.deleted.has(Q)&&this.source.has(Q))return this.source.get(Q)}set(Q,Z){if(this.deleted.delete(Q),this.source.has(Q))this.changed.add(Q);return super.set(Q,Z)}hasOwn(Q){return super.has(Q)}has(Q){return!this.deleted.has(Q)&&(super.has(Q)||this.source.has(Q))}delete(Q){if(this.source.has(Q))this.deleted.add(Q),this.changed.delete(Q);return super.delete(Q)}clear(){this.deleted=new Set(this.source.keys()),this.changed.clear(),super.clear()}*[Symbol.iterator](){yield*super[Symbol.iterator]();for(let[Q,Z]of this.source)if(!this.deleted.has(Q)&&!this.changed.has(Q))yield[Q,Z]}*entries(){yield*this[Symbol.iterator]()}*keys(){yield*super.keys();for(let Q of this.source.keys())if(!this.deleted.has(Q)&&!this.changed.has(Q))yield Q}*values(){for(let[,Q]of this[Symbol.iterator]())yield Q}forEach(Q){for(let[Z,q]of this[Symbol.iterator]())Q(q,Z,this)}get size(){return super.size+this.source.size-this.changed.size-this.deleted.size}},VQ=class extends Set{deleted=new Set;source;constructor(Q){super();this.source=Q}add(Q){if(this.source.has(Q))return this.deleted.delete(Q),this;return super.add(Q)}hasOwn(Q){return super.has(Q)}has(Q){return!this.deleted.has(Q)&&(super.has(Q)||this.source.has(Q))}delete(Q){if(this.source.has(Q))return this.deleted.add(Q),!0;return super.delete(Q)}clear(){this.deleted=new Set(this.source),super.clear()}*[Symbol.iterator](){yield*super[Symbol.iterator]();for(let Q of this.source)if(!this.deleted.has(Q))yield Q}*iterateOwn(){yield*super[Symbol.iterator]()}get size(){return super.size+this.source.size-this.deleted.size}},cQ=class extends Map{deleted=new Set;source;constructor(Q){super();this.source=Q}get(Q){if(super.has(Q))return super.get(Q);if(!this.deleted.has(Q)&&this.source.has(Q)){let Z=new VQ(this.source.get(Q));return super.set(Q,Z),Z}}set(Q,Z){return this.deleted.delete(Q),super.set(Q,Z)}has(Q){return!this.deleted.has(Q)&&(super.has(Q)||this.source.has(Q))}delete(Q){return this.deleted.add(Q),super.delete(Q)}},T=class Q{a;b;cardinality;relations=new Map;contents=new Map;isAType;isBType;isContent;makeContentKey=(Z,q)=>`${Z}:${q}`;warn;getRelatedKeys(Z){return this.relations.get(Z)}addRelation(Z,q){let z=this.relations.get(Z),H=this.relations.get(q);if(z)z.add(q);else z=new Set([q]),this.relations.set(Z,z);if(H)H.add(Z);else H=new Set([Z]),this.relations.set(q,H)}deleteRelation(Z,q){let z=this.relations.get(Z);if(z){if(z.delete(q),z.size===0)this.relations.delete(Z);let H=this.relations.get(q);if(H){if(H.delete(Z),H.size===0)this.relations.delete(q)}}}replaceRelationsUnsafely(Z,q){this.relations.set(Z,new Set(q));for(let z of q){let H=new Set().add(Z);this.relations.set(z,H)}}replaceRelationsSafely(Z,q){let z=this.relations.get(Z),H=this.isAType?.(Z)?Z:void 0,X=H===void 0?Z:void 0;if(z)for(let Y of z){H??=Y,X??=Y;let G=this.relations.get(Y);if(G){if(G.size===1)this.relations.delete(Y);else G.delete(Z);this.contents.delete(this.makeContentKey(H,X))}}this.relations.set(Z,new Set(q));for(let Y of q){let G=this.relations.get(Y);if(G)G.add(Z);else G=new Set().add(Z),this.relations.set(Y,G)}}getContentInternal(Z){return this.contents.get(Z)}setContent(Z,q){this.contents.set(Z,q)}deleteContent(Z){this.contents.delete(Z)}constructor(Z,q){if(this.a=Z.between[0],this.b=Z.between[1],this.cardinality=Z.cardinality,this.isAType=q?.isAType??null,this.isBType=q?.isBType??null,this.isContent=q?.isContent??null,q?.makeContentKey)this.makeContentKey=q.makeContentKey;if(!q?.externalStore){let z=q?.source;if(z===void 0)this.relations=new Map(Z.relations?.map(([H,X])=>[H,new Set(X)])),this.contents=new Map(Z.contents);if(z)this.relations=new cQ(z.relations),this.contents=new K(z.contents)}if(q?.externalStore){let z=q.externalStore;if(this.has=(H,X)=>z.has(H,X),this.addRelation=(H,X)=>{z.addRelation(H,X)},this.deleteRelation=(H,X)=>{z.deleteRelation(H,X)},this.replaceRelationsSafely=(H,X)=>{z.replaceRelationsSafely(H,X)},this.replaceRelationsUnsafely=(H,X)=>{z.replaceRelationsUnsafely(H,X)},this.getRelatedKeys=(H)=>z.getRelatedKeys(H),z.getContent)this.getContentInternal=(H)=>{return z.getContent(H)},this.setContent=(H,X)=>{z.setContent(H,X)},this.deleteContent=(H)=>{z.deleteContent(H)};for(let[H,X]of Z.relations??[]){let Y=this.isAType?.(H)?H:void 0,G=Y===void 0?H:void 0;for(let N of X)Y??=N,G??=N,this.addRelation(Y,G)}for(let[H,X]of Z.contents??[])this.setContent(H,X)}if(q?.warn)this.warn=q.warn}toJSON(){return{between:[this.a,this.b],cardinality:this.cardinality,relations:[...this.relations.entries()].map(([Z,q])=>[Z,[...q]]),contents:[...this.contents.entries()]}}set(...Z){let q,z,H;switch(Z.length){case 1:{let X=Z[0];q=X[this.a],z=X[this.b],H=void 0;break}case 2:{let X=Z[0];if(typeof X==="string")[q,z]=Z;else q=X[this.a],z=X[this.b],H=Z[1];break}default:q=Z[0],z=Z[1],H=Z[2];break}switch(this.cardinality){case"1:1":{let X=this.getRelatedKey(q);if(X&&X!==z)this.delete(q,X)}case"1:n":{let X=this.getRelatedKey(z);if(X&&X!==q)this.delete(X,z)}break;case"n:n":}if(H){let X=this.makeContentKey(q,z);this.setContent(X,H)}return this.addRelation(q,z),this}delete(Z,q){q=typeof q==="string"?q:Z[this.b];let z=typeof Z==="string"?Z:Z[this.a];if(z===void 0&&typeof q==="string"){let H=this.getRelatedKeys(q);if(H)for(let X of H)this.delete(X,q)}else if(typeof z==="string"&&q===void 0){let H=this.getRelatedKeys(z);if(H)for(let X of H)this.delete(z,X)}else if(typeof z==="string"&&typeof q==="string"){this.deleteRelation(z,q);let H=this.makeContentKey(z,q);this.deleteContent(H)}return this}getRelatedKey(Z){let q=this.getRelatedKeys(Z);if(q){if(q.size>1)this.warn?.(`${q.size} related keys were found for key "${Z}": (${[...q].map((H)=>`"${H}"`).join(", ")}). Only one related key was expected.`);let z;for(let H of q){z=H;break}return z}}replaceRelations(Z,q,z){let H=!Array.isArray(q),X=H?Object.keys(q):q;if(z?.reckless)this.replaceRelationsUnsafely(Z,X);else this.replaceRelationsSafely(Z,X);if(H)for(let Y of X){let G=this.makeContentKey(Z,Y),N=q[Y];this.setContent(G,N)}return this}getContent(Z,q){let z=this.makeContentKey(Z,q);return this.getContentInternal(z)}getRelationEntries(Z){let q=Z[this.a],z=Z[this.b];if(q!==void 0&&z===void 0){let H=this.getRelatedKeys(q);if(H)return[...H].map((X)=>{return[X,this.getContent(q,X)]})}if(q===void 0&&z!==void 0){let H=this.getRelatedKeys(z);if(H)return[...H].map((X)=>{return[X,this.getContent(X,z)]})}return[]}has(Z,q){if(q)return this.getRelatedKeys(Z)?.has(q)??!1;return this.relations.has(Z)}overlay(){let Z={source:this,makeContentKey:this.makeContentKey};if(this.isAType)Z.isAType=this.isAType;if(this.isBType)Z.isBType=this.isBType;if(this.isContent)Z.isContent=this.isContent;if(this.warn)Z.warn=this.warn;return new Q({between:[this.a,this.b],cardinality:this.cardinality},Z)}incorporate(Z){let{relations:q,contents:z}=Z;for(let[H,X]of q)if(X instanceof VQ){let{source:Y}=X;for(let G of X.iterateOwn())Y.add(G)}else this.relations.set(H,X);for(let H of q.deleted)this.relations.delete(H);for(let[H,X]of z)this.contents.set(H,X);for(let H of z.deleted)this.contents.delete(H)}};function uQ(Q){return Q.startsWith("\uD83D\uDD0D ")}var lQ=(Q)=>{Q.logger.info("\uD83E\uDE82","transaction",Q.transactionMeta.update.token.key,"Aborting transaction"),Q.parent.child=null};function L0(Q,Z,q){return(...z)=>{return B(Q,Z).run(z,q)}}function iQ(Q,Z,q){let{token:z,update:{newValue:H,oldValue:X}}=Z;f(Q,z,q==="newValue"?H:X)}function aQ(Q){let{stack:Z}=Q;if(Z)return`
|
|
4
|
-
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
+
for (let key of __getOwnPropNames(mod))
|
|
12
|
+
if (!__hasOwnProp.call(to, key))
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: () => mod[key],
|
|
15
|
+
enumerable: true
|
|
16
|
+
});
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, {
|
|
23
|
+
get: all[name],
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
30
|
+
var __require = import.meta.require;
|
|
31
|
+
|
|
32
|
+
// ../../packages/atom.io/dist/main/index.js
|
|
33
|
+
function mutableAtom(options) {
|
|
34
|
+
return createMutableAtom(IMPLICIT.STORE, options, undefined);
|
|
35
|
+
}
|
|
36
|
+
function atomFamily(options) {
|
|
37
|
+
return createRegularAtomFamily(IMPLICIT.STORE, options);
|
|
38
|
+
}
|
|
39
|
+
function getState(...params) {
|
|
40
|
+
return getFromStore(IMPLICIT.STORE, ...params);
|
|
41
|
+
}
|
|
42
|
+
function join(options) {
|
|
43
|
+
return createJoin(IMPLICIT.STORE, options);
|
|
44
|
+
}
|
|
45
|
+
function getInternalRelations(token) {
|
|
46
|
+
return getInternalRelationsFromStore(token, IMPLICIT.STORE);
|
|
47
|
+
}
|
|
48
|
+
var PRETTY_TOKEN_TYPES = {
|
|
49
|
+
atom_family: `atom family`,
|
|
50
|
+
atom: `atom`,
|
|
51
|
+
continuity: `continuity`,
|
|
52
|
+
key: `key`,
|
|
53
|
+
mutable_atom_family: `atom family [m]`,
|
|
54
|
+
mutable_atom: `atom [m]`,
|
|
55
|
+
readonly_held_selector_family: `selector family [h]`,
|
|
56
|
+
readonly_held_selector: `selector [h]`,
|
|
57
|
+
readonly_pure_selector_family: `selector family`,
|
|
58
|
+
readonly_pure_selector: `selector`,
|
|
59
|
+
state: `state`,
|
|
60
|
+
timeline: `timeline`,
|
|
61
|
+
transaction: `transaction`,
|
|
62
|
+
unknown: `unknown`,
|
|
63
|
+
writable_held_selector_family: `selector family [wh]`,
|
|
64
|
+
writable_held_selector: `selector [wh]`,
|
|
65
|
+
writable_pure_selector_family: `selector family [w]`,
|
|
66
|
+
writable_pure_selector: `selector [w]`
|
|
67
|
+
};
|
|
68
|
+
var simpleLog = (logLevel) => (icon, denomination, tokenKey, message, ...rest) => {
|
|
69
|
+
console[logLevel](`${icon} ${PRETTY_TOKEN_TYPES[denomination]} \`${tokenKey}\` ${message}`, ...rest);
|
|
70
|
+
};
|
|
71
|
+
var simpleLogger = {
|
|
72
|
+
error: simpleLog(`error`),
|
|
73
|
+
info: simpleLog(`info`),
|
|
74
|
+
warn: simpleLog(`warn`)
|
|
75
|
+
};
|
|
76
|
+
var AtomIOLogger = class {
|
|
77
|
+
logLevel;
|
|
78
|
+
filter;
|
|
79
|
+
logger;
|
|
80
|
+
constructor(logLevel, filter, logger = simpleLogger) {
|
|
81
|
+
this.logLevel = logLevel;
|
|
82
|
+
this.filter = filter;
|
|
83
|
+
this.logger = logger;
|
|
84
|
+
}
|
|
85
|
+
error = (...args) => {
|
|
86
|
+
if (this.logLevel !== null) {
|
|
87
|
+
const filterResult = this.filter?.(...args) ?? true;
|
|
88
|
+
if (filterResult === true)
|
|
89
|
+
this.logger.error(...args);
|
|
90
|
+
else if (filterResult)
|
|
91
|
+
this.logger.error(...filterResult);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
info = (...args) => {
|
|
95
|
+
if (this.logLevel === `info`) {
|
|
96
|
+
const filterResult = this.filter?.(...args) ?? true;
|
|
97
|
+
if (filterResult === true)
|
|
98
|
+
this.logger.info(...args);
|
|
99
|
+
else if (filterResult)
|
|
100
|
+
this.logger.info(...filterResult);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
warn = (...args) => {
|
|
104
|
+
if (this.logLevel !== `error` && this.logLevel !== null) {
|
|
105
|
+
const filterResult = this.filter?.(...args) ?? true;
|
|
106
|
+
if (filterResult === true)
|
|
107
|
+
this.logger.warn(...args);
|
|
108
|
+
else if (filterResult)
|
|
109
|
+
this.logger.warn(...filterResult);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
var $validatedKey = Symbol.for(`claim`);
|
|
114
|
+
function simpleCompound(a, b) {
|
|
115
|
+
return [a, b].sort().join(`\x1F`);
|
|
116
|
+
}
|
|
117
|
+
function decomposeCompound(compound) {
|
|
118
|
+
if (typeof compound === `string` === false)
|
|
119
|
+
return null;
|
|
120
|
+
const [typeTag, components] = compound.split(`==`);
|
|
121
|
+
if (!components)
|
|
122
|
+
return null;
|
|
123
|
+
const type = typeTag.slice(4);
|
|
124
|
+
const [a, b] = components.split(`++`);
|
|
125
|
+
if (type && a && b)
|
|
126
|
+
return [
|
|
127
|
+
type,
|
|
128
|
+
a,
|
|
129
|
+
b
|
|
130
|
+
];
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
function selectorFamily(options) {
|
|
134
|
+
return createSelectorFamily(IMPLICIT.STORE, options);
|
|
135
|
+
}
|
|
136
|
+
function transaction(options) {
|
|
137
|
+
return createTransaction(IMPLICIT.STORE, options);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ../../packages/atom.io/dist/json/index.js
|
|
141
|
+
function parseJson(str) {
|
|
142
|
+
return JSON.parse(str);
|
|
143
|
+
}
|
|
144
|
+
var stringifyJson = (json) => JSON.stringify(json);
|
|
145
|
+
var JSON_PROTOTYPES = [
|
|
146
|
+
Array.prototype,
|
|
147
|
+
Boolean.prototype,
|
|
148
|
+
Number.prototype,
|
|
149
|
+
Object.prototype,
|
|
150
|
+
String.prototype
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
// ../../packages/atom.io/dist/struct/index.js
|
|
154
|
+
function enumeration(values) {
|
|
155
|
+
const result = {};
|
|
156
|
+
let i = 0;
|
|
157
|
+
for (const value of values) {
|
|
158
|
+
result[value] = i;
|
|
159
|
+
result[i] = value;
|
|
160
|
+
++i;
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
var BOOL = `\x01`;
|
|
165
|
+
var NULL = `\x02`;
|
|
166
|
+
var STRING = `\x03`;
|
|
167
|
+
var NUMBER = `\x04`;
|
|
168
|
+
var packValue = (value) => {
|
|
169
|
+
switch (typeof value) {
|
|
170
|
+
case `string`:
|
|
171
|
+
return STRING + value;
|
|
172
|
+
case `number`:
|
|
173
|
+
return NUMBER + value;
|
|
174
|
+
case `boolean`:
|
|
175
|
+
return BOOL + +value;
|
|
176
|
+
case `object`:
|
|
177
|
+
return NULL;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
var unpackValue = (value) => {
|
|
181
|
+
switch (value[0]) {
|
|
182
|
+
case STRING:
|
|
183
|
+
return value.slice(1);
|
|
184
|
+
case NUMBER:
|
|
185
|
+
return +value.slice(1);
|
|
186
|
+
case BOOL:
|
|
187
|
+
return value.slice(1) === `1`;
|
|
188
|
+
case NULL:
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// ../../packages/atom.io/dist/transceivers/u-list/index.js
|
|
194
|
+
var SET_UPDATE_ENUM = enumeration([
|
|
195
|
+
`add`,
|
|
196
|
+
`delete`,
|
|
197
|
+
`clear`
|
|
198
|
+
]);
|
|
199
|
+
var UList = class UList2 extends Set {
|
|
200
|
+
mode = `record`;
|
|
201
|
+
subject = new Subject;
|
|
202
|
+
constructor(values) {
|
|
203
|
+
super(values);
|
|
204
|
+
if (values instanceof UList2) {}
|
|
205
|
+
}
|
|
206
|
+
READONLY_VIEW = this;
|
|
207
|
+
toJSON() {
|
|
208
|
+
return [...this];
|
|
209
|
+
}
|
|
210
|
+
static fromJSON(json) {
|
|
211
|
+
return new UList2(json);
|
|
212
|
+
}
|
|
213
|
+
add(value) {
|
|
214
|
+
const result = super.add(value);
|
|
215
|
+
if (this.mode === `record`)
|
|
216
|
+
this.emit({
|
|
217
|
+
type: `add`,
|
|
218
|
+
value
|
|
219
|
+
});
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
clear() {
|
|
223
|
+
const capturedContents = this.mode === `record` ? [...this] : null;
|
|
224
|
+
super.clear();
|
|
225
|
+
if (capturedContents)
|
|
226
|
+
this.emit({
|
|
227
|
+
type: `clear`,
|
|
228
|
+
values: capturedContents
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
delete(value) {
|
|
232
|
+
const result = super.delete(value);
|
|
233
|
+
if (this.mode === `record`)
|
|
234
|
+
this.emit({
|
|
235
|
+
type: `delete`,
|
|
236
|
+
value
|
|
237
|
+
});
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
subscribe(key, fn) {
|
|
241
|
+
return this.subject.subscribe(key, fn);
|
|
242
|
+
}
|
|
243
|
+
emit(update) {
|
|
244
|
+
this.subject.next(UList2.packUpdate(update));
|
|
245
|
+
}
|
|
246
|
+
do(packed) {
|
|
247
|
+
this.mode = `playback`;
|
|
248
|
+
const update = UList2.unpackUpdate(packed);
|
|
249
|
+
switch (update.type) {
|
|
250
|
+
case `add`:
|
|
251
|
+
this.add(update.value);
|
|
252
|
+
break;
|
|
253
|
+
case `delete`:
|
|
254
|
+
this.delete(update.value);
|
|
255
|
+
break;
|
|
256
|
+
case `clear`:
|
|
257
|
+
this.clear();
|
|
258
|
+
}
|
|
259
|
+
this.mode = `record`;
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
undo(packed) {
|
|
263
|
+
const update = UList2.unpackUpdate(packed);
|
|
264
|
+
this.mode = `playback`;
|
|
265
|
+
switch (update.type) {
|
|
266
|
+
case `add`:
|
|
267
|
+
this.delete(update.value);
|
|
268
|
+
break;
|
|
269
|
+
case `delete`:
|
|
270
|
+
this.add(update.value);
|
|
271
|
+
break;
|
|
272
|
+
case `clear`: {
|
|
273
|
+
const values = update.values;
|
|
274
|
+
for (const v of values)
|
|
275
|
+
this.add(v);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
this.mode = `record`;
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
static packUpdate(update) {
|
|
282
|
+
const head = SET_UPDATE_ENUM[update.type] + `\x1F`;
|
|
283
|
+
if (update.type === `clear`)
|
|
284
|
+
return head + update.values.map(packValue).join(`\x1E`);
|
|
285
|
+
return head + packValue(update.value);
|
|
286
|
+
}
|
|
287
|
+
static unpackUpdate(packed) {
|
|
288
|
+
const [type, tail] = packed.split(`\x1F`);
|
|
289
|
+
const head = SET_UPDATE_ENUM[type];
|
|
290
|
+
if (head === `clear`)
|
|
291
|
+
return {
|
|
292
|
+
type: `clear`,
|
|
293
|
+
values: tail.split(`\x1E`).map(unpackValue)
|
|
294
|
+
};
|
|
295
|
+
return {
|
|
296
|
+
type: head,
|
|
297
|
+
value: unpackValue(tail)
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// ../../packages/atom.io/dist/internal/index.js
|
|
303
|
+
function arbitrary(random = Math.random) {
|
|
304
|
+
return random().toString(36).slice(2);
|
|
305
|
+
}
|
|
306
|
+
function newest(scion) {
|
|
307
|
+
while (scion.child !== null)
|
|
308
|
+
scion = scion.child;
|
|
309
|
+
return scion;
|
|
310
|
+
}
|
|
311
|
+
function eldest(scion) {
|
|
312
|
+
while (scion.parent !== null)
|
|
313
|
+
scion = scion.parent;
|
|
314
|
+
return scion;
|
|
315
|
+
}
|
|
316
|
+
var NON_CTOR_FN_REGEX = /^\[object (?:Async|Generator|AsyncGenerator)?Function\]$/;
|
|
317
|
+
function isFn(input) {
|
|
318
|
+
const protoString = Object.prototype.toString.call(input);
|
|
319
|
+
return NON_CTOR_FN_REGEX.test(protoString);
|
|
320
|
+
}
|
|
321
|
+
function become(nextVersionOfThing, originalThing) {
|
|
322
|
+
if (isFn(nextVersionOfThing))
|
|
323
|
+
return nextVersionOfThing(originalThing);
|
|
324
|
+
return nextVersionOfThing;
|
|
325
|
+
}
|
|
326
|
+
var Future = class extends Promise {
|
|
327
|
+
fate;
|
|
328
|
+
resolve;
|
|
329
|
+
reject;
|
|
330
|
+
done = false;
|
|
331
|
+
constructor(executor) {
|
|
332
|
+
let superResolve;
|
|
333
|
+
let superReject;
|
|
334
|
+
super((resolve, reject) => {
|
|
335
|
+
superResolve = resolve;
|
|
336
|
+
superReject = reject;
|
|
337
|
+
});
|
|
338
|
+
this.resolve = superResolve;
|
|
339
|
+
this.reject = superReject;
|
|
340
|
+
this.use(executor instanceof Promise ? executor : new Promise(executor));
|
|
341
|
+
}
|
|
342
|
+
pass(promise, value) {
|
|
343
|
+
if (promise === this.fate) {
|
|
344
|
+
this.resolve(value);
|
|
345
|
+
this.done = true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
fail(promise, reason) {
|
|
349
|
+
if (promise === this.fate) {
|
|
350
|
+
this.reject(reason);
|
|
351
|
+
this.done = true;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
use(value) {
|
|
355
|
+
if (this === value)
|
|
356
|
+
return;
|
|
357
|
+
if (value instanceof Promise) {
|
|
358
|
+
const promise = value;
|
|
359
|
+
this.fate = promise;
|
|
360
|
+
promise.then((resolved) => {
|
|
361
|
+
this.pass(promise, resolved);
|
|
362
|
+
}, (reason) => {
|
|
363
|
+
this.fail(promise, reason);
|
|
364
|
+
});
|
|
365
|
+
} else {
|
|
366
|
+
this.resolve(value);
|
|
367
|
+
this.fate = undefined;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
var Subject = class {
|
|
372
|
+
Subscriber;
|
|
373
|
+
subscribers = /* @__PURE__ */ new Map;
|
|
374
|
+
subscribe(key, subscriber) {
|
|
375
|
+
this.subscribers.set(key, subscriber);
|
|
376
|
+
const unsubscribe = () => {
|
|
377
|
+
this.unsubscribe(key);
|
|
378
|
+
};
|
|
379
|
+
return unsubscribe;
|
|
380
|
+
}
|
|
381
|
+
unsubscribe(key) {
|
|
382
|
+
this.subscribers.delete(key);
|
|
383
|
+
}
|
|
384
|
+
next(value) {
|
|
385
|
+
const subscribers = this.subscribers.values();
|
|
386
|
+
for (const subscriber of subscribers)
|
|
387
|
+
subscriber(value);
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
var StatefulSubject = class extends Subject {
|
|
391
|
+
state;
|
|
392
|
+
constructor(initialState) {
|
|
393
|
+
super();
|
|
394
|
+
this.state = initialState;
|
|
395
|
+
}
|
|
396
|
+
next(value) {
|
|
397
|
+
this.state = value;
|
|
398
|
+
super.next(value);
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
var CircularBuffer = class CircularBuffer2 {
|
|
402
|
+
_buffer;
|
|
403
|
+
_index = 0;
|
|
404
|
+
constructor(lengthOrArray) {
|
|
405
|
+
let length;
|
|
406
|
+
if (typeof lengthOrArray === `number`)
|
|
407
|
+
length = lengthOrArray;
|
|
408
|
+
else
|
|
409
|
+
length = lengthOrArray.length;
|
|
410
|
+
this._buffer = Array.from({ length });
|
|
411
|
+
}
|
|
412
|
+
get buffer() {
|
|
413
|
+
return this._buffer;
|
|
414
|
+
}
|
|
415
|
+
get index() {
|
|
416
|
+
return this._index;
|
|
417
|
+
}
|
|
418
|
+
add(item) {
|
|
419
|
+
this._buffer[this._index] = item;
|
|
420
|
+
this._index = (this._index + 1) % this._buffer.length;
|
|
421
|
+
}
|
|
422
|
+
copy() {
|
|
423
|
+
const copy = new CircularBuffer2([...this._buffer]);
|
|
424
|
+
copy._index = this._index;
|
|
425
|
+
return copy;
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
function deposit(state) {
|
|
429
|
+
const token = {
|
|
430
|
+
key: state.key,
|
|
431
|
+
type: state.type
|
|
432
|
+
};
|
|
433
|
+
if (`family` in state)
|
|
434
|
+
token.family = state.family;
|
|
435
|
+
return token;
|
|
436
|
+
}
|
|
437
|
+
var MapOverlay = class extends Map {
|
|
438
|
+
deleted = /* @__PURE__ */ new Set;
|
|
439
|
+
changed = /* @__PURE__ */ new Set;
|
|
440
|
+
source;
|
|
441
|
+
constructor(source) {
|
|
442
|
+
super();
|
|
443
|
+
this.source = source;
|
|
444
|
+
}
|
|
445
|
+
get(key) {
|
|
446
|
+
if (super.has(key))
|
|
447
|
+
return super.get(key);
|
|
448
|
+
if (!this.deleted.has(key) && this.source.has(key))
|
|
449
|
+
return this.source.get(key);
|
|
450
|
+
}
|
|
451
|
+
set(key, value) {
|
|
452
|
+
this.deleted.delete(key);
|
|
453
|
+
if (this.source.has(key))
|
|
454
|
+
this.changed.add(key);
|
|
455
|
+
return super.set(key, value);
|
|
456
|
+
}
|
|
457
|
+
hasOwn(key) {
|
|
458
|
+
return super.has(key);
|
|
459
|
+
}
|
|
460
|
+
has(key) {
|
|
461
|
+
return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
|
|
462
|
+
}
|
|
463
|
+
delete(key) {
|
|
464
|
+
if (this.source.has(key)) {
|
|
465
|
+
this.deleted.add(key);
|
|
466
|
+
this.changed.delete(key);
|
|
467
|
+
}
|
|
468
|
+
return super.delete(key);
|
|
469
|
+
}
|
|
470
|
+
clear() {
|
|
471
|
+
this.deleted = new Set(this.source.keys());
|
|
472
|
+
this.changed.clear();
|
|
473
|
+
super.clear();
|
|
474
|
+
}
|
|
475
|
+
*[Symbol.iterator]() {
|
|
476
|
+
yield* super[Symbol.iterator]();
|
|
477
|
+
for (const [key, value] of this.source)
|
|
478
|
+
if (!this.deleted.has(key) && !this.changed.has(key))
|
|
479
|
+
yield [key, value];
|
|
480
|
+
}
|
|
481
|
+
*entries() {
|
|
482
|
+
yield* this[Symbol.iterator]();
|
|
483
|
+
}
|
|
484
|
+
*keys() {
|
|
485
|
+
yield* super.keys();
|
|
486
|
+
for (const key of this.source.keys())
|
|
487
|
+
if (!this.deleted.has(key) && !this.changed.has(key))
|
|
488
|
+
yield key;
|
|
489
|
+
}
|
|
490
|
+
*values() {
|
|
491
|
+
for (const [, value] of this[Symbol.iterator]())
|
|
492
|
+
yield value;
|
|
493
|
+
}
|
|
494
|
+
forEach(callbackfn) {
|
|
495
|
+
for (const [key, value] of this[Symbol.iterator]())
|
|
496
|
+
callbackfn(value, key, this);
|
|
497
|
+
}
|
|
498
|
+
get size() {
|
|
499
|
+
return super.size + this.source.size - this.changed.size - this.deleted.size;
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
var SetOverlay = class extends Set {
|
|
503
|
+
deleted = /* @__PURE__ */ new Set;
|
|
504
|
+
source;
|
|
505
|
+
constructor(source) {
|
|
506
|
+
super();
|
|
507
|
+
this.source = source;
|
|
508
|
+
}
|
|
509
|
+
add(value) {
|
|
510
|
+
if (this.source.has(value)) {
|
|
511
|
+
this.deleted.delete(value);
|
|
512
|
+
return this;
|
|
513
|
+
}
|
|
514
|
+
return super.add(value);
|
|
515
|
+
}
|
|
516
|
+
hasOwn(member) {
|
|
517
|
+
return super.has(member);
|
|
518
|
+
}
|
|
519
|
+
has(key) {
|
|
520
|
+
return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
|
|
521
|
+
}
|
|
522
|
+
delete(key) {
|
|
523
|
+
if (this.source.has(key)) {
|
|
524
|
+
this.deleted.add(key);
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
return super.delete(key);
|
|
528
|
+
}
|
|
529
|
+
clear() {
|
|
530
|
+
this.deleted = new Set(this.source);
|
|
531
|
+
super.clear();
|
|
532
|
+
}
|
|
533
|
+
*[Symbol.iterator]() {
|
|
534
|
+
yield* super[Symbol.iterator]();
|
|
535
|
+
for (const value of this.source)
|
|
536
|
+
if (!this.deleted.has(value))
|
|
537
|
+
yield value;
|
|
538
|
+
}
|
|
539
|
+
*iterateOwn() {
|
|
540
|
+
yield* super[Symbol.iterator]();
|
|
541
|
+
}
|
|
542
|
+
get size() {
|
|
543
|
+
return super.size + this.source.size - this.deleted.size;
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
var RelationsOverlay = class extends Map {
|
|
547
|
+
deleted = /* @__PURE__ */ new Set;
|
|
548
|
+
source;
|
|
549
|
+
constructor(source) {
|
|
550
|
+
super();
|
|
551
|
+
this.source = source;
|
|
552
|
+
}
|
|
553
|
+
get(key) {
|
|
554
|
+
if (super.has(key))
|
|
555
|
+
return super.get(key);
|
|
556
|
+
if (!this.deleted.has(key) && this.source.has(key)) {
|
|
557
|
+
const valueOverlay = new SetOverlay(this.source.get(key));
|
|
558
|
+
super.set(key, valueOverlay);
|
|
559
|
+
return valueOverlay;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
set(key, value) {
|
|
563
|
+
this.deleted.delete(key);
|
|
564
|
+
return super.set(key, value);
|
|
565
|
+
}
|
|
566
|
+
has(key) {
|
|
567
|
+
return !this.deleted.has(key) && (super.has(key) || this.source.has(key));
|
|
568
|
+
}
|
|
569
|
+
delete(key) {
|
|
570
|
+
this.deleted.add(key);
|
|
571
|
+
return super.delete(key);
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
var Junction = class Junction2 {
|
|
575
|
+
a;
|
|
576
|
+
b;
|
|
577
|
+
cardinality;
|
|
578
|
+
relations = /* @__PURE__ */ new Map;
|
|
579
|
+
contents = /* @__PURE__ */ new Map;
|
|
580
|
+
isAType;
|
|
581
|
+
isBType;
|
|
582
|
+
isContent;
|
|
583
|
+
makeContentKey = (a, b) => `${a}:${b}`;
|
|
584
|
+
warn;
|
|
585
|
+
getRelatedKeys(key) {
|
|
586
|
+
return this.relations.get(key);
|
|
587
|
+
}
|
|
588
|
+
addRelation(a, b) {
|
|
589
|
+
let aRelations = this.relations.get(a);
|
|
590
|
+
let bRelations = this.relations.get(b);
|
|
591
|
+
if (aRelations)
|
|
592
|
+
aRelations.add(b);
|
|
593
|
+
else {
|
|
594
|
+
aRelations = new Set([b]);
|
|
595
|
+
this.relations.set(a, aRelations);
|
|
596
|
+
}
|
|
597
|
+
if (bRelations)
|
|
598
|
+
bRelations.add(a);
|
|
599
|
+
else {
|
|
600
|
+
bRelations = new Set([a]);
|
|
601
|
+
this.relations.set(b, bRelations);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
deleteRelation(a, b) {
|
|
605
|
+
const aRelations = this.relations.get(a);
|
|
606
|
+
if (aRelations) {
|
|
607
|
+
aRelations.delete(b);
|
|
608
|
+
if (aRelations.size === 0)
|
|
609
|
+
this.relations.delete(a);
|
|
610
|
+
const bRelations = this.relations.get(b);
|
|
611
|
+
if (bRelations) {
|
|
612
|
+
bRelations.delete(a);
|
|
613
|
+
if (bRelations.size === 0)
|
|
614
|
+
this.relations.delete(b);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
replaceRelationsUnsafely(x, ys) {
|
|
619
|
+
this.relations.set(x, new Set(ys));
|
|
620
|
+
for (const y of ys) {
|
|
621
|
+
const yRelations = (/* @__PURE__ */ new Set()).add(x);
|
|
622
|
+
this.relations.set(y, yRelations);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
replaceRelationsSafely(x, ys) {
|
|
626
|
+
const xRelationsPrev = this.relations.get(x);
|
|
627
|
+
let a = this.isAType?.(x) ? x : undefined;
|
|
628
|
+
let b = a === undefined ? x : undefined;
|
|
629
|
+
if (xRelationsPrev)
|
|
630
|
+
for (const y of xRelationsPrev) {
|
|
631
|
+
a ??= y;
|
|
632
|
+
b ??= y;
|
|
633
|
+
const yRelations = this.relations.get(y);
|
|
634
|
+
if (yRelations) {
|
|
635
|
+
if (yRelations.size === 1)
|
|
636
|
+
this.relations.delete(y);
|
|
637
|
+
else
|
|
638
|
+
yRelations.delete(x);
|
|
639
|
+
this.contents.delete(this.makeContentKey(a, b));
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
this.relations.set(x, new Set(ys));
|
|
643
|
+
for (const y of ys) {
|
|
644
|
+
let yRelations = this.relations.get(y);
|
|
645
|
+
if (yRelations)
|
|
646
|
+
yRelations.add(x);
|
|
647
|
+
else {
|
|
648
|
+
yRelations = (/* @__PURE__ */ new Set()).add(x);
|
|
649
|
+
this.relations.set(y, yRelations);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
getContentInternal(contentKey) {
|
|
654
|
+
return this.contents.get(contentKey);
|
|
655
|
+
}
|
|
656
|
+
setContent(contentKey, content) {
|
|
657
|
+
this.contents.set(contentKey, content);
|
|
658
|
+
}
|
|
659
|
+
deleteContent(contentKey) {
|
|
660
|
+
this.contents.delete(contentKey);
|
|
661
|
+
}
|
|
662
|
+
constructor(data, config) {
|
|
663
|
+
this.a = data.between[0];
|
|
664
|
+
this.b = data.between[1];
|
|
665
|
+
this.cardinality = data.cardinality;
|
|
666
|
+
this.isAType = config?.isAType ?? null;
|
|
667
|
+
this.isBType = config?.isBType ?? null;
|
|
668
|
+
this.isContent = config?.isContent ?? null;
|
|
669
|
+
if (config?.makeContentKey)
|
|
670
|
+
this.makeContentKey = config.makeContentKey;
|
|
671
|
+
if (!config?.externalStore) {
|
|
672
|
+
const source = config?.source;
|
|
673
|
+
if (source === undefined) {
|
|
674
|
+
this.relations = new Map(data.relations?.map(([x, ys]) => [x, new Set(ys)]));
|
|
675
|
+
this.contents = new Map(data.contents);
|
|
676
|
+
}
|
|
677
|
+
if (source) {
|
|
678
|
+
this.relations = new RelationsOverlay(source.relations);
|
|
679
|
+
this.contents = new MapOverlay(source.contents);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
if (config?.externalStore) {
|
|
683
|
+
const externalStore = config.externalStore;
|
|
684
|
+
this.has = (a, b) => externalStore.has(a, b);
|
|
685
|
+
this.addRelation = (a, b) => {
|
|
686
|
+
externalStore.addRelation(a, b);
|
|
687
|
+
};
|
|
688
|
+
this.deleteRelation = (a, b) => {
|
|
689
|
+
externalStore.deleteRelation(a, b);
|
|
690
|
+
};
|
|
691
|
+
this.replaceRelationsSafely = (a, bs) => {
|
|
692
|
+
externalStore.replaceRelationsSafely(a, bs);
|
|
693
|
+
};
|
|
694
|
+
this.replaceRelationsUnsafely = (a, bs) => {
|
|
695
|
+
externalStore.replaceRelationsUnsafely(a, bs);
|
|
696
|
+
};
|
|
697
|
+
this.getRelatedKeys = (key) => externalStore.getRelatedKeys(key);
|
|
698
|
+
if (externalStore.getContent) {
|
|
699
|
+
this.getContentInternal = (contentKey) => {
|
|
700
|
+
return externalStore.getContent(contentKey);
|
|
701
|
+
};
|
|
702
|
+
this.setContent = (contentKey, content) => {
|
|
703
|
+
externalStore.setContent(contentKey, content);
|
|
704
|
+
};
|
|
705
|
+
this.deleteContent = (contentKey) => {
|
|
706
|
+
externalStore.deleteContent(contentKey);
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
for (const [x, ys] of data.relations ?? []) {
|
|
710
|
+
let a = this.isAType?.(x) ? x : undefined;
|
|
711
|
+
let b = a === undefined ? x : undefined;
|
|
712
|
+
for (const y of ys) {
|
|
713
|
+
a ??= y;
|
|
714
|
+
b ??= y;
|
|
715
|
+
this.addRelation(a, b);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
for (const [contentKey, content] of data.contents ?? [])
|
|
719
|
+
this.setContent(contentKey, content);
|
|
720
|
+
}
|
|
721
|
+
if (config?.warn)
|
|
722
|
+
this.warn = config.warn;
|
|
723
|
+
}
|
|
724
|
+
toJSON() {
|
|
725
|
+
return {
|
|
726
|
+
between: [this.a, this.b],
|
|
727
|
+
cardinality: this.cardinality,
|
|
728
|
+
relations: [...this.relations.entries()].map(([a, b]) => [a, [...b]]),
|
|
729
|
+
contents: [...this.contents.entries()]
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
set(...params) {
|
|
733
|
+
let a;
|
|
734
|
+
let b;
|
|
735
|
+
let content;
|
|
736
|
+
switch (params.length) {
|
|
737
|
+
case 1: {
|
|
738
|
+
const relation = params[0];
|
|
739
|
+
a = relation[this.a];
|
|
740
|
+
b = relation[this.b];
|
|
741
|
+
content = undefined;
|
|
742
|
+
break;
|
|
743
|
+
}
|
|
744
|
+
case 2: {
|
|
745
|
+
const zeroth = params[0];
|
|
746
|
+
if (typeof zeroth === `string`)
|
|
747
|
+
[a, b] = params;
|
|
748
|
+
else {
|
|
749
|
+
a = zeroth[this.a];
|
|
750
|
+
b = zeroth[this.b];
|
|
751
|
+
content = params[1];
|
|
752
|
+
}
|
|
753
|
+
break;
|
|
754
|
+
}
|
|
755
|
+
default:
|
|
756
|
+
a = params[0];
|
|
757
|
+
b = params[1];
|
|
758
|
+
content = params[2];
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
switch (this.cardinality) {
|
|
762
|
+
case `1:1`: {
|
|
763
|
+
const bPrev = this.getRelatedKey(a);
|
|
764
|
+
if (bPrev && bPrev !== b)
|
|
765
|
+
this.delete(a, bPrev);
|
|
766
|
+
}
|
|
767
|
+
case `1:n`:
|
|
768
|
+
{
|
|
769
|
+
const aPrev = this.getRelatedKey(b);
|
|
770
|
+
if (aPrev && aPrev !== a)
|
|
771
|
+
this.delete(aPrev, b);
|
|
772
|
+
}
|
|
773
|
+
break;
|
|
774
|
+
case `n:n`:
|
|
775
|
+
}
|
|
776
|
+
if (content) {
|
|
777
|
+
const contentKey = this.makeContentKey(a, b);
|
|
778
|
+
this.setContent(contentKey, content);
|
|
779
|
+
}
|
|
780
|
+
this.addRelation(a, b);
|
|
781
|
+
return this;
|
|
782
|
+
}
|
|
783
|
+
delete(x, b) {
|
|
784
|
+
b = typeof b === `string` ? b : x[this.b];
|
|
785
|
+
const a = typeof x === `string` ? x : x[this.a];
|
|
786
|
+
if (a === undefined && typeof b === `string`) {
|
|
787
|
+
const bRelations = this.getRelatedKeys(b);
|
|
788
|
+
if (bRelations)
|
|
789
|
+
for (const bRelation of bRelations)
|
|
790
|
+
this.delete(bRelation, b);
|
|
791
|
+
} else if (typeof a === `string` && b === undefined) {
|
|
792
|
+
const aRelations = this.getRelatedKeys(a);
|
|
793
|
+
if (aRelations)
|
|
794
|
+
for (const aRelation of aRelations)
|
|
795
|
+
this.delete(a, aRelation);
|
|
796
|
+
} else if (typeof a === `string` && typeof b === `string`) {
|
|
797
|
+
this.deleteRelation(a, b);
|
|
798
|
+
const contentKey = this.makeContentKey(a, b);
|
|
799
|
+
this.deleteContent(contentKey);
|
|
800
|
+
}
|
|
801
|
+
return this;
|
|
802
|
+
}
|
|
803
|
+
getRelatedKey(key) {
|
|
804
|
+
const relations = this.getRelatedKeys(key);
|
|
805
|
+
if (relations) {
|
|
806
|
+
if (relations.size > 1)
|
|
807
|
+
this.warn?.(`${relations.size} related keys were found for key "${key}": (${[...relations].map((k) => `"${k}"`).join(`, `)}). Only one related key was expected.`);
|
|
808
|
+
let singleRelation;
|
|
809
|
+
for (const relation of relations) {
|
|
810
|
+
singleRelation = relation;
|
|
811
|
+
break;
|
|
812
|
+
}
|
|
813
|
+
return singleRelation;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
replaceRelations(x, relations, config) {
|
|
817
|
+
const hasContent = !Array.isArray(relations);
|
|
818
|
+
const ys = hasContent ? Object.keys(relations) : relations;
|
|
819
|
+
if (config?.reckless)
|
|
820
|
+
this.replaceRelationsUnsafely(x, ys);
|
|
821
|
+
else
|
|
822
|
+
this.replaceRelationsSafely(x, ys);
|
|
823
|
+
if (hasContent)
|
|
824
|
+
for (const y of ys) {
|
|
825
|
+
const contentKey = this.makeContentKey(x, y);
|
|
826
|
+
const content = relations[y];
|
|
827
|
+
this.setContent(contentKey, content);
|
|
828
|
+
}
|
|
829
|
+
return this;
|
|
830
|
+
}
|
|
831
|
+
getContent(a, b) {
|
|
832
|
+
const contentKey = this.makeContentKey(a, b);
|
|
833
|
+
return this.getContentInternal(contentKey);
|
|
834
|
+
}
|
|
835
|
+
getRelationEntries(input) {
|
|
836
|
+
const a = input[this.a];
|
|
837
|
+
const b = input[this.b];
|
|
838
|
+
if (a !== undefined && b === undefined) {
|
|
839
|
+
const aRelations = this.getRelatedKeys(a);
|
|
840
|
+
if (aRelations)
|
|
841
|
+
return [...aRelations].map((aRelation) => {
|
|
842
|
+
return [aRelation, this.getContent(a, aRelation)];
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
if (a === undefined && b !== undefined) {
|
|
846
|
+
const bRelations = this.getRelatedKeys(b);
|
|
847
|
+
if (bRelations)
|
|
848
|
+
return [...bRelations].map((bRelation) => {
|
|
849
|
+
return [bRelation, this.getContent(bRelation, b)];
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
return [];
|
|
853
|
+
}
|
|
854
|
+
has(a, b) {
|
|
855
|
+
if (b)
|
|
856
|
+
return this.getRelatedKeys(a)?.has(b) ?? false;
|
|
857
|
+
return this.relations.has(a);
|
|
858
|
+
}
|
|
859
|
+
overlay() {
|
|
860
|
+
const config = {
|
|
861
|
+
source: this,
|
|
862
|
+
makeContentKey: this.makeContentKey
|
|
863
|
+
};
|
|
864
|
+
if (this.isAType)
|
|
865
|
+
config.isAType = this.isAType;
|
|
866
|
+
if (this.isBType)
|
|
867
|
+
config.isBType = this.isBType;
|
|
868
|
+
if (this.isContent)
|
|
869
|
+
config.isContent = this.isContent;
|
|
870
|
+
if (this.warn)
|
|
871
|
+
config.warn = this.warn;
|
|
872
|
+
return new Junction2({
|
|
873
|
+
between: [this.a, this.b],
|
|
874
|
+
cardinality: this.cardinality
|
|
875
|
+
}, config);
|
|
876
|
+
}
|
|
877
|
+
incorporate(overlay) {
|
|
878
|
+
const { relations, contents } = overlay;
|
|
879
|
+
for (const [key, value] of relations)
|
|
880
|
+
if (value instanceof SetOverlay) {
|
|
881
|
+
const { source } = value;
|
|
882
|
+
for (const keyAdded of value.iterateOwn())
|
|
883
|
+
source.add(keyAdded);
|
|
884
|
+
} else
|
|
885
|
+
this.relations.set(key, value);
|
|
886
|
+
for (const key of relations.deleted)
|
|
887
|
+
this.relations.delete(key);
|
|
888
|
+
for (const [key, value] of contents)
|
|
889
|
+
this.contents.set(key, value);
|
|
890
|
+
for (const key of contents.deleted)
|
|
891
|
+
this.contents.delete(key);
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
function isReservedIntrospectionKey(value) {
|
|
895
|
+
return value.startsWith(`\uD83D\uDD0D `);
|
|
896
|
+
}
|
|
897
|
+
var abortTransaction = (target) => {
|
|
898
|
+
target.logger.info(`\uD83E\uDE82`, `transaction`, target.transactionMeta.update.token.key, `Aborting transaction`);
|
|
899
|
+
target.parent.child = null;
|
|
900
|
+
};
|
|
901
|
+
function actUponStore(store, token, id) {
|
|
902
|
+
return (...parameters) => {
|
|
903
|
+
return withdraw(store, token).run(parameters, id);
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
function ingestAtomUpdateEvent(store, event, applying) {
|
|
907
|
+
const { token, update: { newValue, oldValue } } = event;
|
|
908
|
+
setIntoStore(store, token, applying === `newValue` ? newValue : oldValue);
|
|
909
|
+
}
|
|
910
|
+
function getTrace(error) {
|
|
911
|
+
const { stack } = error;
|
|
912
|
+
if (stack)
|
|
913
|
+
return `
|
|
914
|
+
` + stack.split(`
|
|
5
915
|
`)?.slice(1)?.join(`
|
|
6
|
-
`);
|
|
7
|
-
|
|
8
|
-
|
|
916
|
+
`);
|
|
917
|
+
return ``;
|
|
918
|
+
}
|
|
919
|
+
function allocateIntoStore(store, provenance, key, dependsOn = `any`) {
|
|
920
|
+
const origin = provenance;
|
|
921
|
+
const stringKey = stringifyJson(key);
|
|
922
|
+
const invalidKeys = [];
|
|
923
|
+
const target = newest(store);
|
|
924
|
+
if (Array.isArray(origin))
|
|
925
|
+
for (const formerClaim of origin) {
|
|
926
|
+
const claimString = stringifyJson(formerClaim);
|
|
927
|
+
if (target.molecules.get(claimString))
|
|
928
|
+
store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
929
|
+
else
|
|
930
|
+
invalidKeys.push(claimString);
|
|
931
|
+
}
|
|
932
|
+
else {
|
|
933
|
+
const claimString = stringifyJson(origin);
|
|
934
|
+
if (target.molecules.get(claimString))
|
|
935
|
+
store.moleculeGraph.set(claimString, stringKey, { source: claimString });
|
|
936
|
+
else
|
|
937
|
+
invalidKeys.push(claimString);
|
|
938
|
+
}
|
|
939
|
+
const subject = new Subject;
|
|
940
|
+
if (invalidKeys.length === 0)
|
|
941
|
+
target.molecules.set(stringKey, {
|
|
942
|
+
key,
|
|
943
|
+
stringKey,
|
|
944
|
+
dependsOn,
|
|
945
|
+
subject
|
|
946
|
+
});
|
|
947
|
+
const creationEvent = {
|
|
948
|
+
type: `molecule_creation`,
|
|
949
|
+
key,
|
|
950
|
+
provenance: origin,
|
|
951
|
+
timestamp: Date.now()
|
|
952
|
+
};
|
|
953
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`)
|
|
954
|
+
target.transactionMeta.update.subEvents.push(creationEvent);
|
|
955
|
+
else
|
|
956
|
+
target.on.moleculeCreation.next(creationEvent);
|
|
957
|
+
for (const claim of invalidKeys) {
|
|
958
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === claim);
|
|
959
|
+
store.logger.error(`\u274C`, `key`, key, `allocation failed:`, `Could not allocate to ${claim} in store "${store.config.name}".`, disposal ? `
|
|
960
|
+
${claim} was most recently disposed
|
|
961
|
+
${disposal.trace}` : `No previous disposal trace for ${claim} was found.`);
|
|
962
|
+
}
|
|
963
|
+
return key;
|
|
964
|
+
}
|
|
965
|
+
function deallocateFromStore(target, claim) {
|
|
966
|
+
const stringKey = stringifyJson(claim);
|
|
967
|
+
const molecule = target.molecules.get(stringKey);
|
|
968
|
+
if (!molecule) {
|
|
969
|
+
const disposal = target.disposalTraces.buffer.find((item) => item?.key === stringKey);
|
|
970
|
+
target.logger.error(`\u274C`, `key`, claim, `deallocation failed:`, `Could not find allocation for ${stringKey} in store "${target.config.name}".`, disposal ? `
|
|
9
971
|
This state was most recently deallocated
|
|
10
|
-
${
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
${H.trace}`:"(no previous disposal trace found)"),q.type){case"mutable_atom_family":{if(Q.defaults.has(q.key))return Q.defaults.get(q.key);let X=new q.class;return Q.defaults.set(q.key,X),X.READONLY_VIEW}case"atom_family":{if(Q.defaults.has(q.key))return Q.defaults.get(q.key);let X=q.default,Y=X(z);return Q.defaults.set(q.key,Y),Y}case"readonly_pure_selector_family":case"writable_pure_selector_family":case"readonly_held_selector_family":case"writable_held_selector_family":{if(Q.defaults.has(q.key))return Q.defaults.get(q.key);let X=q.default(z);return Q.defaults.set(q.key,X),X}}}function D0(Q,Z){let{type:q,key:z,catch:H}=Z;switch(q){case"readonly_pure_selector":case"writable_pure_selector":{let X;Q.logger.info("\uD83E\uDDEE",q,z,"computing value");try{if(X=Z.getFrom(Q),X instanceof Promise)return X.catch((Y)=>{if(Q.logger.error("\uD83D\uDCA5",q,z,"rejected:",Y),H){for(let G of H)if(Y instanceof G)return Y}throw Y})}catch(Y){if(Q.logger.error("\uD83D\uDCA5",q,z,"rejected:",Y),H){for(let G of H)if(Y instanceof G)return w(Q,Z,Y)}throw Y}return w(Q,Z,X)}case"atom":{let X;if(s(Z.default))try{if(X=Z.default(),X instanceof Promise)X=X.catch((Y)=>{if(Q.logger.error("\uD83D\uDCA5",q,z,"rejected:",Y),H){for(let G of H)if(Y instanceof G)return Y}throw Y})}catch(Y){if(Q.logger.error("\uD83D\uDCA5",q,z,"rejected:",Y),H){for(let G of H)if(Y instanceof G)return X=w(Q,Z,Y),Q.logger.info("\u2728",Z.type,z,"computed default",X),X}throw Y}else X=Z.default,Q.logger.info("\u2728",Z.type,z,"using static default",X);return w(Q,Z,X)}}}function y(Q,Z,q){if(Q.valueMap.has(Z.key))return hZ(Q,Z,q);Q.logger.info("\u2754",Z.type,Z.key,"value not found in cache");let{key:z}=Z;switch(Z.type){case"readonly_held_selector":case"writable_held_selector":return Q.logger.info("\uD83E\uDDEE",Z.type,z,"computing value"),Z.getFrom(Q);case"writable_pure_selector":case"readonly_pure_selector":case"atom":return D0(Q,Z);case"mutable_atom":{let H=new Z.class;return Q.logger.info("\u2728",Z.type,z,"created new instance",H),w(Q,Z,H)}}}function g0(Q,Z){return B(Q,{key:Z.family.key,type:`${Z.type}_family`})}var DQ={atom_family:"atom",molecule_family:"molecule",mutable_atom_family:"mutable_atom",readonly_held_selector_family:"readonly_held_selector",readonly_pure_selector_family:"readonly_pure_selector",writable_held_selector_family:"writable_held_selector",writable_pure_selector_family:"writable_pure_selector"},o=Symbol("MUST_CREATE"),YZ=Symbol("DO_NOT_CREATE");function t(Q,Z,q,z){let H=h(z),X=Z.molecules.get(H);if(!X&&Z.config.lifespan==="immortal"){let{type:G,key:N}=q;return Z.logger.warn("\uD83D\uDCA3","key",H,"was used to mint a counterfeit token for",G,`"${N}"`),{counterfeit:!0,key:`${N}(${H})`,type:DQ[G],family:{key:N,subKey:H}}}let Y;if(Q===o){if(Z.logger.info("\uD83D\uDC6A",q.type,q.key,"adds member",typeof z==="string"?`\`${z}\``:z),Y=q.create(z),X)Z.moleculeData.set(H,q.key)}else{let{type:G,key:N}=q;return{key:`${N}(${H})`,type:DQ[G],family:{key:N,subKey:H}}}return Y}function b0(Q,...Z){let q,z,H,X,Y;if(Z.length===1){if(Y=Z[0],"family"in Y){let N=g0(Q,Y);if(H=B(Q,N),X=R(Y.family.subKey),q=e(Q,N,X),"counterfeit"in Y)return{token:Y,family:H,subKey:X,isNew:!1};if(!q)z=t(o,Q,N,X),Y=z;else Y=q}}else if(H=B(Q,Z[0]),X=Z[1],q=e(Q,H,X),!q)z=t(o,Q,H,X),Y=z;else Y=q;let G="counterfeit"in Y;if(Boolean(z)&&G===!1&&H){let N;switch(Y.type){case"readonly_pure_selector":case"readonly_held_selector":N="readable";break;case"atom":case"mutable_atom":case"writable_pure_selector":case"writable_held_selector":N="writable";break}let j={type:"state_creation",subType:N,token:Y,timestamp:Date.now()};H.subject.next(j);let W=C(Q);if(Y.family){if(u(W))switch(Y.type){case"atom":case"mutable_atom":Q.on.atomCreation.next(Y);break;case"writable_pure_selector":case"readonly_pure_selector":case"writable_held_selector":case"readonly_held_selector":Q.on.selectorCreation.next(Y);break}else if(F(W)&&W.on.transactionApplying.state===null)W.transactionMeta.update.subEvents.push(j)}}return{token:Y,family:H,subKey:X,isNew:Boolean(z)}}function I(Q,...Z){let{token:q,family:z,subKey:H}=b0(Q,...Z);if("counterfeit"in q&&z&&H)return hQ(Q,q,z,H);return y(Q,B(Q,q))}function e(Q,Z,q){let z=h(q),H=`${Z.key}(${z})`,X=C(Q),Y;switch(Z.type){case"atom_family":case"mutable_atom_family":Y=X.atoms.get(H);break;case"writable_held_selector_family":case"writable_pure_selector_family":Y=X.writableSelectors.get(H);break;case"readonly_held_selector_family":case"readonly_pure_selector_family":Y=X.readonlySelectors.get(H);break}if(Y)return b(Y);return Y}function M(Q,Z,q){let z=B(Q,Z),H=e(Q,Z,q);if(H)return H;return t(YZ,Q,z,q)}function $0(Q,Z,q){let z=Z.key,H="readonly_pure_selector_family",X={key:z,type:"readonly_pure_selector_family"},Y=Q.families.get(z);if(Y&&Q.config.isProduction===!0)Q.logger.error("\u2757","readonly_pure_selector_family",z,`Overwriting an existing ${S[Y.type]} "${Y.key}" in store "${Q.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);let G=new E,j={...X,create:(W)=>{let _=h(W),D={key:z,subKey:_},$=`${z}(${_})`,J=C(Q),V={key:$,get:Z.get(W)};if(Z.catch)V.catch=Z.catch;return p0(J,V,D)},internalRoles:q,subject:G,install:(W)=>$0(W,Z),default:(W)=>{return Z.get(W)({get:(..._)=>I(Q,..._),find:(..._)=>M(Q,..._),json:(_)=>p(Q,_)})}};return Q.families.set(z,j),X}function G0(Q,Z,q){let z={key:Z.key,type:"atom_family"},H=Q.families.get(Z.key);if(H&&Q.config.isProduction===!0)Q.logger.error("\u2757","atom_family",Z.key,`Overwriting an existing ${S[H.type]} "${H.key}" in store "${Q.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);let X=new E,G={...z,create:(N)=>{let j=h(N),W={key:Z.key,subKey:j},_=`${Z.key}(${j})`,D=C(Q),$=Z.default,J={key:_,default:s($)?()=>$(N):$};if(Z.effects)J.effects=Z.effects(N);if(Z.catch)J.catch=Z.catch;return N0(D,J,W)},default:Z.default,subject:X,install:(N)=>G0(N,Z),internalRoles:q};if(Q.families.set(Z.key,G),s(Z.default)===!1)Q.defaults.set(Z.key,Z.default);return z}function LQ(Q,Z,q){let z=Z.key,H="readonly_held_selector_family",X={key:z,type:"readonly_held_selector_family"},Y=Q.families.get(z);if(Y&&Q.config.isProduction===!0)Q.logger.error("\u2757","readonly_held_selector_family",z,`Overwriting an existing ${S[Y.type]} "${Y.key}" in store "${Q.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);let G=new E,j={...X,create:(W)=>{let _=h(W),D={key:z,subKey:_},$=`${z}(${_})`;return y0(C(Q),{key:$,const:Z.const(W),get:Z.get(W)},D)},internalRoles:q,subject:G,install:(W)=>LQ(W,Z),default:Z.const};return Q.families.set(z,j),X}function PQ(Q,Z,q){let z=Z.key,H="writable_held_selector_family",X={key:z,type:"writable_held_selector_family"},Y=Q.families.get(z);if(Y&&Q.config.isProduction===!0)Q.logger.error("\u2757","writable_held_selector_family",z,`Overwriting an existing ${S[Y.type]} "${Y.key}" in store "${Q.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);let G=new E,j={...X,create:(W)=>{let _=h(W),D={key:z,subKey:_},$=`${z}(${_})`;return m0(C(Q),{key:$,const:Z.const(W),get:Z.get(W),set:Z.set(W)},D)},internalRoles:q,subject:G,install:(W)=>PQ(W,Z),default:Z.const};return Q.families.set(z,j),X}function d0(Q,Z,q){let z=Z.key,H="writable_pure_selector_family",X={key:z,type:"writable_pure_selector_family"},Y=Q.families.get(z);if(Y&&Q.config.isProduction===!0)Q.logger.error("\u2757","writable_pure_selector_family",z,`Overwriting an existing ${S[Y.type]} "${Y.key}" in store "${Q.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);let G=new E,j={...X,create:(W)=>{let _=h(W),D={key:z,subKey:_},$=`${z}(${_})`,J=C(Q),V={key:$,get:Z.get(W),set:Z.set(W)};if(Z.catch)V.catch=Z.catch;return c0(J,V,D)},internalRoles:q,subject:G,install:(W)=>d0(W,Z),default:(W)=>{return Z.get(W)({get:(..._)=>I(Q,..._),find:(..._)=>M(Q,..._),json:(_)=>p(Q,_)})}};return Q.families.set(z,j),X}function qQ(Q,Z){let q="set"in Z,z="const"in Z;if(z&&q)return PQ(Q,Z,void 0);if(z)return LQ(Q,Z,void 0);if(q)return d0(Q,Z);return $0(Q,Z)}function n(Q,...Z){let q;if(Z.length===1)q=Z[0];else{let z=Z[0],H=Z[1];q=M(Q,z,H)}try{B(Q,q)}catch(z){Q.logger.error("\u274C",q.type,q.key,`could not be disposed because it was not found in the store "${Q.config.name}".`);return}switch(q.type){case"atom":case"mutable_atom":wQ(Q,q);break;case"writable_pure_selector":case"readonly_pure_selector":case"writable_held_selector":case"readonly_held_selector":JZ(Q,q);break}}function OQ(Q,Z){if(Q.operation.open){let q=performance.now();return Q.logger.info("\uD83D\uDEAB",Z.type,Z.key,`deferring setState at T-${q} until setState for "${Q.operation.token.key}" is done`),q}return Q.operation={open:!0,done:new Set,prev:new Map,timestamp:Date.now(),token:Z,subEvents:[]},Q.logger.info("\u2B55",Z.type,Z.key,`operation start in store "${Q.config.name}"${F(Q)?` ${Q.transactionMeta.phase} "${Q.transactionMeta.update.token.key}"`:""}`),Q}function MQ(Q){if(Q.operation.open)Q.logger.info("\uD83D\uDD34",Q.operation.token.type,Q.operation.token.key,`operation done in store "${Q.config.name}"`);Q.operation={open:!1},Q.on.operationClose.next(Q.operation)}var RQ=(Q,Z)=>{if(!Q.operation.open)return Q.logger.error("\uD83D\uDC1E","unknown",Z,"isDone called outside of an operation. This is probably a bug in AtomIO."),!0;return Q.operation.done.has(Z)},V0=(Q,Z)=>{if(!Q.operation.open){Q.logger.error("\uD83D\uDC1E","unknown",Z,"markDone called outside of an operation. This is probably a bug in AtomIO.");return}Q.operation.done.add(Z)};function f0(Q,Z,{oldValue:q,newValue:z},H,X){let Y=b(Z);if(H&&X){Z.subject.next({newValue:z});let _={checkpoint:!0,type:"state_creation",subType:"writable",token:Y,timestamp:Date.now(),value:z};Q.operation.subEvents.push(_),X.subject.next(_);let D=C(Q);if(Y.family){if(u(D))switch(Y.type){case"atom":case"mutable_atom":Q.on.atomCreation.next(Y);break;case"writable_pure_selector":case"writable_held_selector":Q.on.selectorCreation.next(Y);break}else if(F(D)&&D.on.transactionApplying.state===null)D.transactionMeta.update.subEvents.push(_)}return}let{key:G,subject:N,type:j}=Z,W={oldValue:w0(q)?q.READONLY_VIEW:q,newValue:w0(z)?z.READONLY_VIEW:z};if(u(Q)){switch(j){case"mutable_atom":Q.logger.info("\uD83D\uDCE2",j,G,"is now (",z,") subscribers:",N.subscribers.keys());break;case"atom":case"writable_pure_selector":case"writable_held_selector":Q.logger.info("\uD83D\uDCE2",j,G,"went (",q,"->",z,") subscribers:",N.subscribers.keys())}N.next(W)}if(F(Q)&&(j==="mutable_atom"||j==="atom")){if(Q.on.transactionApplying.state===null){if(w0(z))return;let{timestamp:_}=Q.operation,D={type:"atom_update",token:Y,timestamp:_,update:W};Q.transactionMeta.update.subEvents.push(D),Q.logger.info("\uD83D\uDCC1","atom",G,"stowed (",q,"->",z,")");return}if(i0(Z,"tracker:signal")){let _=G.slice(1),D=Q.atoms.get(_);if(y(Q,D,"mut").do(W.newValue)===null===!0)l0(Q,D)}}}var K0=(Q,Z,q)=>{let z=y(Q,Z,"mut"),H=A0(q,z);return Q.logger.info("\u2B50","atom",Z.key,"setting value",H),H=w(Q,Z,H),V0(Q,Z.key),l0(Q,Z),{oldValue:z,newValue:H}};function x0(Q,Z){switch(Z.type){case"mutable_atom":return K0(Q,Z,new Z.class);case"atom":{let q;if(s(Z.default))q=D0(Q,Z);else q=Z.default;return K0(Q,Z,q)}}}function GZ(Q,Z){let q;switch(Z.type){case"atom":case"mutable_atom":q=x0(Q,Z);break;case"writable_held_selector":{let z=Q0(Q,Z.key);for(let X of z.values())f0(Q,Z,x0(Q,X),!1);let H=Z.getFrom(Q);q={oldValue:H,newValue:H}}break;case"writable_pure_selector":{let z=D0(Q,Z),H=Q0(Q,Z.key);for(let X of H.values())f0(Q,Z,x0(Q,X),!1);q={oldValue:z,newValue:D0(Q,Z)}}break}return q}function f(Q,...Z){l(J0,Q,...Z)}var S0=Symbol("RESET");function W0(Q,...Z){f(Q,...[...Z,S0])}function WZ(Q,Z,q){let z,H,X,{type:Y,key:G}=Z;switch(Z.type){case"writable_pure_selector":z=y(Q,Z,"mut"),H=A0(q,z),H=w(Q,Z,H);break;case"writable_held_selector":X=Z.const,A0(q,X),z=X,H=X}return Q.logger.info("\u2B50",Y,G,"setting to",H),V0(Q,G),Z.setSelf(H),{oldValue:z,newValue:H}}var _Z=(Q,Z,q)=>{let z;switch(Z.type){case"atom":case"mutable_atom":z=K0(Q,Z,q);break;case"writable_pure_selector":case"writable_held_selector":z=WZ(Q,Z,q);break}return z},J0=Symbol("OWN_OP"),k0=Symbol("JOIN_OP");function l(Q,Z,...q){let z,H,X,Y,G,N;if(q.length===2){if(X=q[0],N=q[1],"family"in X)if(Y=g0(Z,X),G=R(X.family.subKey),z=e(Z,Y,G),!z)X=H=t(o,Z,Y,G);else X=z}else if(Y=B(Z,q[0]),G=q[1],N=q[2],z=e(Z,Y,G),!z)X=H=t(o,Z,Y,G);else X=z;let j=N===S0?"reset":"set",W;if(Q===J0){let $=OQ(Z,X);if(typeof $==="number"){let J=$,V=Z.on.operationClose.subscribe(`waiting to ${j} "${X.key}" at T-${J}`,function(){V(),Z.logger.info("\uD83D\uDFE2",X.type,X.key,"resuming deferred",j,`from T-${J}`),l(Q,Z,X,N)});return}W=$}else W=Z;if("counterfeit"in X&&"family"in X){let $=X.family.subKey,J=Z.disposalTraces.buffer.find((V)=>V?.key===$);Z.logger.error("\u274C",X.type,X.key,"could not be",j,"because key",$,"is not allocated.",J?`this key was previously disposed:${J.trace}`:"(no previous disposal trace found)");return}let _=B(W,X),D;if(N===S0)D=GZ(W,_);else D=_Z(W,_,N);if(f0(W,_,D,Boolean(H),Y),Q===J0)MQ(W)}var FQ=(Q,Z)=>C(Q).atoms.has(Z),NZ=(Q,Z)=>C(Q).writableSelectors.has(Z),jZ=(Q,Z)=>C(Q).readonlySelectors.has(Z),DZ=(Q,Z)=>FQ(Q,Z)||NZ(Q,Z)||jZ(Q,Z);function $Q(Q,Z){return C(Q).selectorGraph.getRelationEntries({downstreamSelectorKey:Z}).filter(([q,{source:z}])=>z!==Z).map(([q,{source:z}])=>z).filter((q)=>DZ(Q,q))}function Q0(Q,Z,q=new Set){let z=$Q(Q,Z),H=new Map;while(z.length>0){let X=z.pop();if(q.has(X))continue;if(q.add(X),FQ(Q,X)){let Y=Q.atoms.get(X);H.set(Y.key,Y)}else z.push(...$Q(Q,X))}return H}function $Z(Q,Z,q,z,H){let X=C(Q),{type:Y,key:G}=z;if(Y==="atom"||Y==="mutable_atom")X.selectorAtoms.set({selectorKey:q,atomKey:G}),Q.logger.info("\uD83D\uDD0D",Z,q,`discovers root atom "${G}"`);else{let N=Q0(Q,G,H);Q.logger.info("\uD83D\uDD0D",Z,q,`discovers root atoms: [ ${[...N.values()].map((j)=>`"${j.key}"`).join(", ")} ]`);for(let{key:j}of N.values())X.selectorAtoms=X.selectorAtoms.set({selectorKey:q,atomKey:j})}H.add(G)}function C0(Q,Z,q,z){return{get:(...H)=>{let X=C(Q),{token:Y,family:G,subKey:N}=b0(Q,...H),j;if("counterfeit"in Y&&G&&N)j=hQ(Q,Y,G,N);else j=y(Q,B(Q,Y));return Q.logger.info("\uD83D\uDD0C",Z,q,`registers dependency ( "${Y.key}" =`,j,")"),X.selectorGraph.set({upstreamSelectorKey:Y.key,downstreamSelectorKey:q},{source:Y.key}),$Z(Q,Z,q,Y,z),j},set:(...H)=>{l(k0,C(Q),...H)},find:(...H)=>M(Q,...H),json:(H)=>p(Q,H)}}function y0(Q,Z,q){let z=C(Q),H=new E,X=new Set,{key:Y,const:G}=Z,N="readonly_held_selector";Q.logger.info("\uD83D\uDD28","readonly_held_selector",Y,"is being created");let{get:j,find:W,json:_}=C0(z,"readonly_held_selector",Y,X),$={...Z,type:"readonly_held_selector",subject:H,getFrom:(V)=>{let P=V.selectorGraph.getRelationEntries({downstreamSelectorKey:Y});for(let[O,{source:L}]of P)if(L!==Y)V.selectorGraph.delete(O,Y);return V.selectorAtoms.delete(Y),Z.get({get:j,find:W,json:_},G),w(V,$,G),Q.logger.info("\u2728","readonly_held_selector",Y,"=",G),X.clear(),G},install:(V)=>y0(V,Z,q)};if(q)$.family=q;z.readonlySelectors.set(Y,$);let J={key:Y,type:"readonly_held_selector"};if(q)J.family=q;return J}function p0(Q,Z,q){let z=C(Q),H=new E,X=new Set,Y=Z.key,G="readonly_pure_selector";Q.logger.info("\uD83D\uDD28","readonly_pure_selector",Y,"is being created");let{get:N,find:j,json:W}=C0(z,"readonly_pure_selector",Y,X),D={...Z,type:"readonly_pure_selector",subject:H,getFrom:()=>{let J=C(Q),V=J.selectorGraph.getRelationEntries({downstreamSelectorKey:Y});for(let[O,{source:L}]of V)if(L!==Y)J.selectorGraph.delete(O,Y);J.selectorAtoms.delete(Y);let P=w(J,D,Z.get({get:N,find:j,json:W}));return Q.logger.info("\u2728","readonly_pure_selector",Y,"=",P),X.clear(),P},install:(J)=>p0(J,Z,q)};if(q)D.family=q;z.readonlySelectors.set(Y,D);let $={key:Y,type:"readonly_pure_selector"};if(q)$.family=q;return $}function m0(Q,Z,q){let z=C(Q),H=new E,X=new Set,{key:Y,const:G}=Z,N="writable_held_selector";Q.logger.info("\uD83D\uDD28","writable_held_selector",Y,"is being created");let j=C0(z,"writable_held_selector",Y,X),{find:W,get:_,json:D}=j,$={find:W,get:_,json:D},P={...Z,type:"writable_held_selector",subject:H,getFrom:(L)=>{let U=L.selectorGraph.getRelationEntries({downstreamSelectorKey:Y});for(let[d,{source:k}]of U)if(k!==Y)L.selectorGraph.delete(d,Y);return L.selectorAtoms.delete(Y),Z.get($,G),w(L,P,G),Q.logger.info("\u2728","writable_held_selector",Y,"=",G),X.clear(),G},setSelf:()=>{Z.set(j,G)},install:(L)=>m0(L,Z,q)};if(q)P.family=q;z.writableSelectors.set(Y,P);let O={key:Y,type:"writable_held_selector"};if(q)O.family=q;return O}function c0(Q,Z,q){let z=C(Q),H=new E,X=new Set,Y=Z.key,G="writable_pure_selector";Q.logger.info("\uD83D\uDD28","writable_pure_selector",Y,"is being created");let N=C0(z,"writable_pure_selector",Y,X),{find:j,get:W,json:_}=N,D={find:j,get:W,json:_},V={...Z,type:"writable_pure_selector",subject:H,getFrom:(O)=>{let L=O.selectorGraph.getRelationEntries({downstreamSelectorKey:Y});for(let[d,{source:k}]of L)if(k!==Y)O.selectorGraph.delete(d,Y);O.selectorAtoms.delete(Y);let U=w(O,V,Z.get(D));return Q.logger.info("\u2728","writable_pure_selector",Y,"=",U),X.clear(),U},setSelf:(O)=>{Z.set(N,O)},install:(O)=>c0(O,Z,q)};if(q)V.family=q;z.writableSelectors.set(Y,V);let P={key:Y,type:"writable_pure_selector"};if(q)P.family=q;return P}function zQ(Q,Z){let q="set"in Z,z="const"in Z;if(z&&q){let X=m0(Q,Z,void 0);return Q.on.selectorCreation.next(X),X}if(z){let X=y0(Q,Z,void 0);return Q.on.selectorCreation.next(X),X}if(q){let X=c0(Q,Z,void 0);return Q.on.selectorCreation.next(X),X}let H=p0(Q,Z,void 0);return Q.on.selectorCreation.next(H),H}function JZ(Q,Z){let q=C(Q),{key:z,type:H,family:X}=Z;if(!X)Q.logger.error("\u274C",H,z,"Standalone selectors cannot be disposed.");else{if(q.molecules.get(X.subKey))q.moleculeData.delete(X.subKey,X.key);let Y;switch(Z.type){case"writable_held_selector":q.writableSelectors.delete(z),Y={key:X.key,type:"writable_held_selector_family"},B(Q,Y).subject.next({type:"state_disposal",subType:"selector",token:Z,timestamp:Date.now()});break;case"writable_pure_selector":q.writableSelectors.delete(z),Y={key:X.key,type:"writable_pure_selector_family"},B(Q,Y).subject.next({type:"state_disposal",subType:"selector",token:Z,timestamp:Date.now()});break;case"readonly_held_selector":q.readonlySelectors.delete(z),Y={key:X.key,type:"readonly_held_selector_family"},B(Q,Y).subject.next({type:"state_disposal",subType:"selector",token:Z,timestamp:Date.now()});break;case"readonly_pure_selector":q.readonlySelectors.delete(z),Y={key:X.key,type:"readonly_pure_selector_family"},B(Q,Y).subject.next({type:"state_disposal",subType:"selector",token:Z,timestamp:Date.now()});break}if(q.valueMap.delete(z),q.selectorAtoms.delete(z),q.selectorGraph.delete(z),q.moleculeData.delete(X.key,X.subKey),Q.logger.info("\uD83D\uDD25",Z.type,z,"deleted"),F(q)&&q.transactionMeta.phase==="building")q.transactionMeta.update.subEvents.push({type:"state_disposal",subType:"selector",token:Z,timestamp:Date.now()});else Q.on.selectorDisposal.next(Z)}}var VZ=(Q,Z)=>{let q=C(Q);if(q.operation.open)return q.operation.prev.get(Z.key);return q.valueMap.get(Z.key)},JQ=(Q,Z,q)=>{return q.subject.subscribe(`${Z.type}:${Z.key}`,(z)=>{Q.logger.info("\uD83D\uDCE2",Z.type,Z.key,"root",q.key,"went",z.oldValue,"->",z.newValue);let H=VZ(Q,Z),X=y(Q,Z);Q.logger.info("\u2728",Z.type,Z.key,"went",H,"->",X),Z.subject.next({newValue:X,oldValue:H})})};function Z0(Q,Z,q,z){function H(_){if(Q.operation.open){if(X?.type==="atom"&&i0(X,"tracker:signal")&&"*"+Q.operation.token.key===Z.key&&"inboundTracker"in z)return;let D=Q.on.operationClose.subscribe(`state subscription ${q}`,()=>{D(),z(_)})}else z(_)}b0(Q,Z);let X=B(Q,Z);Q.logger.info("\uD83D\uDC40",X.type,X.key,`Adding subscription "${q}"`);let Y=X.type==="writable_pure_selector"||X.type==="readonly_pure_selector",G=new Map,N=H;if(Y){y(Q,X);for(let[_,D]of Q0(Q,X.key))G.set(_,JQ(Q,X,D));N=function(D){let $=Q0(Q,X.key);for(let[J,V]of G)if($.get(J))$.delete(J);else V(),G.delete(J);for(let[J,V]of $)G.set(J,JQ(Q,X,V));H(D)}}let j=X.subject.subscribe(q,N);return()=>{Q.logger.info("\uD83D\uDE48",X.type,X.key,`Removing subscription "${q}"`),j();for(let _ of G.values())_()}}var CZ=(Q,Z,q,z)=>{let H=B(Q,Z);Q.logger.info("\uD83D\uDC40","timeline",Z.key,`Adding subscription "${q}"`);let X=H.subject.subscribe(q,z);return()=>{Q.logger.info("\uD83D\uDE48","timeline",Z.key,`Removing subscription "${q}" from timeline`),X()}};var u0=class{initializeSignalAtom(Q,Z){let q=`*${Q.key}`;Z.atoms.delete(q),Z.valueMap.delete(q);let z=Q.family?{key:`*${Q.family.key}`,subKey:Q.family.subKey}:void 0,H=N0(Z,{key:q,default:null},z,["tracker:signal"]);if(Z.parent?.valueMap.has(q)){let X=Z.parent.valueMap.get(q);Z.valueMap.set(q,X)}return H}unsubscribeFromInnerValue;unsubscribeFromState;captureSignalsFromCore(Q,Z,q){let z=Q.key,H=`tracker-from-core:${q.config.name}:${F(q)?q.transactionMeta.update.token.key:"main"}:${z}`,X=(Y)=>{l(k0,q,Z,Y)};this.unsubscribeFromInnerValue=I(q,Q).subscribe(H,X),this.unsubscribeFromState=Z0(q,Q,H,function(G){if(G.newValue!==G.oldValue)this.unsubscribeFromInnerValue(),this.unsubscribeFromInnerValue=G.newValue.subscribe(H,X)}.bind(this))}supplySignalsToCore(Q,Z,q){let z=Q.key,H=`tracker-to-core:${q.config.name}:${F(q)?q.transactionMeta.update.token.key:"main"}:${z}`;Z0(q,Z,H,Object.assign(function({newValue:Y,oldValue:G}){let N=q.timelineTopics.getRelatedKey(Z.key);if(N&&q.timelines.get(N)?.timeTraveling){let j=CZ(q,{key:N,type:"timeline"},H,function(_){j(),f(q,Q,(D)=>{if(_==="redo"&&Y)D.do(Y);else if(_==="undo"&&G)D.undo(G);return D})});return}f(q,Q,(j)=>(j.do(Y),j))},{inboundTracker:!0}))}mutableAtomToken;latestSignalToken;[Symbol.dispose];constructor(Q,Z){let q=C(Z),z=this.initializeSignalAtom(Q,q);this.mutableAtomToken=Q,this.latestSignalToken=z,this.captureSignalsFromCore(Q,z,q),this.supplySignalsToCore(Q,z,q),q.trackers.set(Q.key,this),this[Symbol.dispose]=()=>{this.unsubscribeFromInnerValue(),this.unsubscribeFromState(),q.trackers.delete(Q.key)}}};function _0(Q,Z,q){Q.logger.info("\uD83D\uDD28","atom",Z.key,`creating in store "${Q.config.name}"`);let z=C(Q),{key:H}=Z,X=z.atoms.get(H),Y="mutable_atom";if(X?.type===Y&&Q.config.isProduction===!0)return Q.logger.error("\u274C",Y,H,"Tried to create atom, but it already exists in the store."),b(X);let G=new E,N={...Z,type:Y,install:(W)=>{return W.logger.info("\uD83D\uDEE0\uFE0F","atom",H,`installing in store "${W.config.name}"`),_0(W,Z,q)},subject:G};if(q)N.family=q;z.atoms.set(N.key,N);let j=b(N);if(new u0(j,Q),!q)zQ(Q,{key:`${H}:JSON`,get:({get:W})=>W(j).toJSON(),set:({set:W},_)=>{W(j,Z.class.fromJSON(_))}});if(Z.effects){let W=0,_=[];for(let D of Z.effects){let $=D({resetSelf:()=>{W0(Q,j)},setSelf:(J)=>{f(Q,j,J)},onSet:(J)=>Z0(Q,j,`effect[${W}]`,J),token:j,store:v0(Q)});if($)_.push($);++W}N.cleanup=()=>{for(let D of _)D()}}return Q.on.atomCreation.next(j),j}var EZ=class{trackers=new Map;latestSignalAtoms;mutableAtoms;constructor(Q,Z){this.latestSignalAtoms=B(Z,G0(Z,{key:`*${Q.key}`,default:null},["mutable","updates"])),this.mutableAtoms=Q;let q=(z)=>{let{type:H,token:X}=z;if(X.family){let Y=R(X.family.subKey);switch(H){case"state_creation":this.trackers.set(Y,new u0(X,Z));break;case"state_disposal":{let G=this.trackers.get(Y);if(G)G[Symbol.dispose](),this.trackers.delete(Y)}}}};this.mutableAtoms.subject.subscribe(`store=${Z.config.name}::tracker-atom-family`,q)}};function R0(Q,Z,q){let z={key:Z.key,type:"mutable_atom_family"},H=Q.families.get(Z.key);if(H&&Q.config.isProduction===!0)Q.logger.error("\u2757","mutable_atom_family",Z.key,`Overwriting an existing ${S[H.type]} "${H.key}" in store "${Q.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);let X=new E,G={...z,create:(N)=>{let j=h(N),W={key:Z.key,subKey:j},_=`${Z.key}(${j})`,D=C(Q),$={key:_,class:Z.class};if(Z.effects)$.effects=Z.effects(N);return _0(D,$,W)},class:Z.class,subject:X,install:(N)=>R0(N,Z),internalRoles:q};return Q.families.set(Z.key,G),d0(Q,{key:`${Z.key}:JSON`,get:(N)=>({get:j})=>j(z,N).toJSON(),set:(N)=>({set:j},W)=>{j(z,N,Z.class.fromJSON(W))}},["mutable","json"]),new EZ(G,Q),z}var BZ=(Q,Z)=>{let q=C(Z),z=`${Q.key}:JSON`;return q.families.get(z)},p=(Q,Z)=>{if(Z.family)return M(Q,B(C(Q),{key:`${Z.family.key}:JSON`,type:"writable_pure_selector_family"}),R(Z.family.subKey));return{type:"writable_pure_selector",key:`${Z.key}:JSON`}};var j0=(Q)=>{let Z={type:"atom",key:`*${Q.key}`};if(Q.family)Z.family={key:`*${Q.family.key}`,subKey:Q.family.subKey};return Z};function w0(Q){return typeof Q==="object"&&Q!==null&&"do"in Q&&"undo"in Q&&"subscribe"in Q&&"READONLY_VIEW"in Q&&"toJSON"in Q}function w(Q,Z,q){let{key:z,subject:H,type:X}=Z,Y=Q.valueMap.get(z);if(Y instanceof I0&&!Y.done){let G=Y;if(q instanceof Promise)return G.use(q),G;return Q.valueMap.set(z,q),q}if(q instanceof Promise){let G=new I0(q);return Q.valueMap.set(z,G),G.then(function(j){if(Q.valueMap.get(z)===G){switch(OQ(Q,Z),w(Q,Z,j),X){case"atom":l0(Q,Z);break;case"readonly_pure_selector":case"writable_pure_selector":xQ(Q,z);break}MQ(Q),H.next({newValue:j,oldValue:G})}}).catch((N)=>{Q.logger.error("\uD83D\uDCA5",Z.type,z,"rejected:",N)}),G}return Q.logger.info("\uD83D\uDCDD",Z.type,Z.key,"writing to cache",q),Q.valueMap.set(z,q),q}function hZ(Q,Z,q){Q.logger.info("\uD83D\uDCD6",Z.type,Z.key,"reading cached value");let z=Q.valueMap.get(Z.key);if(q==="mut"&&Z.type==="mutable_atom"&&F(Q)){let H=Z,{parent:X}=Q;if(Q.valueMap.hasOwn(H.key))return z;let Y=X.valueMap.get(H.key);Q.logger.info("\uD83D\uDCC3","atom",H.key,"copying");let G=Y.toJSON(),N=H.class.fromJSON(G);Q.valueMap.set(H.key,N),new u0(H,X),z=N}return z}function UQ(Q,Z){let q=Q.valueMap.get(Z);if(q instanceof I0){let z=Q.writableSelectors.get(Z)??Q.readonlySelectors.get(Z);if(z)z.getFrom(Q);return}if(Q.operation.open)Q.operation.prev.set(Z,q);Q.valueMap.delete(Z),Q.logger.info("\uD83D\uDDD1","state",Z,"evicted")}function l0(Q,Z){let q=C(Q),{key:z,type:H}=Z,X=q.selectorAtoms.getRelatedKeys(z);if(q.logger.info("\uD83E\uDDF9",H,z,X?`evicting ${X.size} states downstream:`:"no downstream states",X??"to evict"),X){if(q.operation.open)q.logger.info("\uD83E\uDDF9",H,z,`[ ${[...q.operation.done].join(", ")} ] already done`);for(let Y of X){if(RQ(q,Y))continue;UQ(q,Y),V0(q,Y)}}}function xQ(Q,Z){let q=C(Q),z=q.selectorGraph.getRelationEntries({upstreamSelectorKey:Z}).filter(([H,{source:X}])=>X===Z);for(let[H]of z){if(RQ(q,H))continue;UQ(q,H),V0(q,H),xQ(Q,H)}}function N0(Q,Z,q,z){let{key:X}=Z;Q.logger.info("\uD83D\uDD28","atom",X,"is being created");let Y=C(Q),G=Y.atoms.get(X);if(G?.type==="atom"&&Q.config.isProduction===!0)return Q.logger.error("\u274C","atom",X,"Tried to create atom, but it already exists in the store."),b(G);let N=new E,j={...Z,type:"atom",install:(_)=>{return _.logger.info("\uD83D\uDEE0\uFE0F","atom",X,`installing in store "${_.config.name}"`),N0(_,Z,q)},subject:N};if(q)j.family=q;if(z)j.internalRoles=z;Y.atoms.set(X,j);let W=b(j);if(Z.effects){let _=0,D=[];for(let $ of Z.effects){let J=$({resetSelf:()=>{W0(Q,W)},setSelf:(V)=>{f(Q,W,V)},onSet:(V)=>Z0(Q,W,`effect[${_}]`,V),token:W,store:v0(Q)});if(J)D.push(J);++_}j.cleanup=()=>{for(let $ of D)$()}}return Q.on.atomCreation.next(W),W}function i0(Q,Z){if("internalRoles"in Q===!1)return!1;return Q.internalRoles.includes(Z)}function wQ(Q,Z){let q=C(Q),{key:z,family:H}=Z,X=B(q,Z);if(!H)Q.logger.error("\u274C","atom",z,"Standalone atoms cannot be disposed.");else{X.cleanup?.();let Y=Q.valueMap.get(X.key),G=B(Q,g0(Q,Z)).subject,N={type:"state_disposal",subType:"atom",token:Z,value:Y,timestamp:Date.now()};G.next(N);let j=F(q);if(q.atoms.delete(z),q.valueMap.delete(z),q.selectorAtoms.delete(z),q.atomsThatAreDefault.delete(z),q.moleculeData.delete(H.key,H.subKey),Q.timelineTopics.delete(z),Z.type==="mutable_atom")wQ(Q,j0(Z)),Q.trackers.delete(z);if(Q.logger.info("\uD83D\uDD25","atom",z,"deleted"),j&&q.transactionMeta.phase==="building"){let W=q.transactionMeta.update.subEvents.at(-1),_=W?.type==="molecule_disposal"&&W.values.some(([$])=>$===X.family?.key),D=i0(X,"tracker:signal");if(!_&&!D)q.transactionMeta.update.subEvents.push(N)}else Q.on.atomDisposal.next(Z)}}function x(Q){return Q[0].toUpperCase()+Q.slice(1)}var AQ=class{toolkit;options;relations;states;relatedKeysAtoms;transact(Q,Z){let q=this.toolkit;this.toolkit=Q,Z(this),this.toolkit=q}store;[Symbol.dispose](){}constructor(Q,Z=A.STORE){this.store=Z,this.options=Q,this.store.miscResources.set(`join:${Q.key}`,this),this.toolkit={get:(...W)=>I(Z,...W),set:(...W)=>{f(Z,...W)},find:(...W)=>M(Z,...W),json:(W)=>p(Z,W)};let q=Q.between[0],z=Q.between[1],H=R0(Z,{key:`${Q.key}/relatedKeys`,class:v},["join","relations"]);this.relatedKeysAtoms=H;let X=(W,_,D)=>{let{find:$,get:J,set:V}=W,P=$(H,_),O=J(P);for(let L of O){if(D.includes(L))continue;V(H,L,(U)=>{return U.delete(_),U})}V(P,(L)=>{L.clear();for(let U of D){let d=$(H,U),k=J(d),r0=k.has(_);if(this.relations.cardinality==="1:n"){let i=[];for(let g of k){if(g===_)continue;let s0;if(l(k0,this.store,H,g,(E0)=>{return E0.delete(U),s0=E0.size,E0}),s0===0)i.push(g)}if(!r0&&k.size>0)V(d,(g)=>{return g.clear(),g});for(let g of i)Z.keyRefsInJoins.delete(a(U,g))}if(!r0)V(d,(i)=>{return i.add(_),i});L.add(U)}return L})},Y=(W,_,D)=>{let{set:$}=W;$(H,_,(J)=>{for(let V of D)J.add(V);return J});for(let J of D)$(H,J,(V)=>{return V.add(_),V});return!0},G=new T(Q,{externalStore:{getRelatedKeys:(W)=>this.toolkit.get(H,W),addRelation:(W,_)=>{this.store.keyRefsInJoins.set(`"${W}"`,Q.key),this.store.keyRefsInJoins.set(`"${_}"`,Q.key),this.store.keyRefsInJoins.set(a(W,_),Q.key),this.toolkit.set(H,W,(D)=>D.add(_)),this.toolkit.set(H,_,(D)=>D.add(W))},deleteRelation:(W,_)=>{this.toolkit.set(H,W,($)=>{return $.delete(_),$}),this.toolkit.set(H,_,($)=>{return $.delete(W),$});let D=a(W,_);this.store.keyRefsInJoins.delete(D)},replaceRelationsSafely:(W,_)=>{X(this.toolkit,W,_)},replaceRelationsUnsafely:(W,_)=>{Y(this.toolkit,W,_)},has:(W,_)=>{let D=this.toolkit.get(H,W);return _?D.has(_):D.size>0}},isAType:Q.isAType,isBType:Q.isBType}),N=()=>$0(Z,{key:`${Q.key}/singleRelatedKey`,get:(W)=>({get:_})=>{let D=_(H,W);for(let $ of D)return $;return null}},["join","keys"]),j=()=>{return $0(Z,{key:`${Q.key}/multipleRelatedKeys`,get:(W)=>({get:_})=>{return _(BZ(H,Z),W)}},["join","keys"])};switch(Q.cardinality){case"1:1":{let W=N(),_=`${q}KeyOf${x(z)}`,D=`${z}KeyOf${x(q)}`;this.relations=G,this.states={[_]:W,[D]:W};break}case"1:n":{let W=N(),_=j(),D=`${q}KeyOf${x(z)}`,$=`${z}KeysOf${x(q)}`,J={[D]:W,[$]:_};this.relations=G,this.states=J;break}case"n:n":{let W=j(),_=`${q}KeysOf${x(z)}`,D=`${z}KeysOf${x(q)}`;this.relations=G,this.states={[_]:W,[D]:W}}}}};function HQ(Q,Z){return Q.joins.set(Z.key,new AQ(Z)),{key:Z.key,type:"join",a:Z.between[0],b:Z.between[1],cardinality:Z.cardinality}}function a0(Q,Z){let q=Z.joins.get(Q.key);if(q===void 0){let z=A.STORE.joins.get(Q.key);if(z===void 0)throw Error(`Join "${Q.key}" not found in store "${Z.config.name}"`);let H=v0(Z);q=new AQ(z.options,H),Z.joins.set(Q.key,q)}return q}function r(Q,Z,q){let z=a0(Q,q),H=C(q);if(F(H)){let{toolkit:X}=H.transactionMeta;z.transact(X,({relations:Y})=>{Z(Y)})}else Z(z.relations)}function kQ(Q,Z,q){let z=a0(Q,q),H;switch(Q.cardinality){case"1:1":{let X=`${Q.a}KeyOf${x(Q.b)}`,Y=`${Q.b}KeyOf${x(Q.a)}`;H={get[X](){let G=z.states[X];return M(q,G,Z)},get[Y](){let G=z.states[Y];return M(q,G,Z)}};break}case"1:n":{let X=`${Q.a}KeyOf${x(Q.b)}`,Y=`${Q.b}KeysOf${x(Q.a)}`;H={get[X](){let G=z.states[X];return M(q,G,Z)},get[Y](){let G=z.states[Y];return M(q,G,Z)}};break}case"n:n":{let X=`${Q.a}KeysOf${x(Q.b)}`,Y=`${Q.b}KeysOf${x(Q.a)}`;H={get[X](){let G=z.states[X];return M(q,G,Z)},get[Y](){let G=z.states[Y];return M(q,G,Z)}}}}return H}function XQ(Q,Z){return a0(Q,Z).relatedKeysAtoms}var LZ=c({key:"mutex",default:!1}),PZ=class extends Map{set(Q,Z){if(this.has(Q))return console.warn("Tried to set a key that already exists in an InvariantMap",{key:Q,value:Z}),this;return super.set(Q,Z)}},_3=class Q{type="continuity";globals=[];actions=[];perspectives=[];key;constructor(Z){this.key=Z}static existing=new PZ;static create(Z,q){let{type:z,globals:H,actions:X,perspectives:Y}=q(new Q(Z)),G={type:z,key:Z,globals:H,actions:X,perspectives:Y};return Q.existing.set(Z,G),G}add(...Z){switch(Z[0].type){case"atom":case"mutable_atom":this.globals.push(...Z);break;case"transaction":this.actions.push(...Z);break;case"atom_family":case"mutable_atom_family":{let[q,z]=Z;this.perspectives.push({type:"realtime_perspective",resourceAtoms:q,viewAtoms:z})}break}return this}};var N3=m({key:"usersInRoomIndex",class:v}),IQ=m({key:"roomIndex",class:v});var q0=H0({key:"usersInRooms",between:["room","user"],cardinality:"1:n",isAType:(Q)=>typeof Q==="string",isBType:(Q)=>typeof Q==="string"}),j3=X0({key:"usersInMyRoomView",get:(Q)=>({find:Z})=>{return[Z(o0(q0),Q)]}});var P3=c({key:"redactor",default:{occlude:(Q)=>Q}}),O3=c({key:"unacknowledgedUpdates",default:()=>[]});var n0=class{listeners;globalListeners;handleEvent(...Q){let[Z,...q]=Q;for(let H of this.globalListeners)H(Z,...q);let z=this.listeners.get(Z);if(z)for(let H of z)H(...q)}id="no_id_retrieved";emit;constructor(Q){this.emit=Q,this.listeners=new Map,this.globalListeners=new Set}on(Q,Z){let q=this.listeners.get(Q);if(q)q.add(Z);else this.listeners.set(Q,new Set([Z]));return this}onAny(Q){return this.globalListeners.add(Q),this}off(Q,Z){let q=this.listeners.get(Q);if(q)if(Z)q.delete(Z);else this.listeners.delete(Q);return this}offAny(Q){return this.globalListeners.delete(Q),this}},M3=class extends n0{incompleteData="";unprocessedEvents=[];incompleteLog="";unprocessedLogs=[];id="#####";proc;key;logger;handleLog(Q){if(Array.isArray(Q)){let[Z,...q]=Q;switch(Z){case"i":this.logger.info(...q);break;case"w":this.logger.warn(...q);break;case"e":this.logger.error(...q);break}}}constructor(Q,Z,q){super((z,...H)=>{let X=JSON.stringify([z,...H])+"\x03",Y=(G)=>{if(G.code==="EPIPE")console.error("EPIPE error during write",this.proc.stdin);this.proc.stdin.removeListener("error",Y)};return this.proc.stdin.once("error",Y),this.proc.stdin.write(X),this});if(this.proc=Q,this.key=Z,this.logger=q??{info:(...z)=>{console.info(this.id,this.key,...z)},warn:(...z)=>{console.warn(this.id,this.key,...z)},error:(...z)=>{console.error(this.id,this.key,...z)}},this.proc.stdout.on("data",(z)=>{let H=z.toString();if(H==="ALIVE"){this.logger.info(H);return}let X=H.split("\x03"),Y=X[0];X[0]=this.incompleteData+Y;let G=0;for(let N of X){if(N==="")continue;try{let j=R(N);this.handleEvent(...j),this.incompleteData=""}catch(j){if(j instanceof Error)console.error(["\u274C Malformed data received from child process","",N,"",j.message].join(`
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
972
|
+
${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
molecule.subject.next();
|
|
976
|
+
const joinKeys = target.keyRefsInJoins.getRelatedKeys(stringKey);
|
|
977
|
+
if (joinKeys)
|
|
978
|
+
for (const joinKey of joinKeys) {
|
|
979
|
+
const join$1 = target.joins.get(joinKey);
|
|
980
|
+
if (join$1)
|
|
981
|
+
join$1.relations.delete(claim);
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
const compound = decomposeCompound(claim);
|
|
985
|
+
if (compound) {
|
|
986
|
+
const [, a, b] = compound;
|
|
987
|
+
const joinKey = target.keyRefsInJoins.getRelatedKey(simpleCompound(a, b));
|
|
988
|
+
if (joinKey) {
|
|
989
|
+
const join$1 = target.joins.get(joinKey);
|
|
990
|
+
if (join$1)
|
|
991
|
+
join$1.relations.delete(a, b);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
target.keyRefsInJoins.delete(stringKey);
|
|
996
|
+
const provenance = [];
|
|
997
|
+
const values = [];
|
|
998
|
+
const relatedMolecules = target.moleculeGraph.getRelationEntries({ downstreamMoleculeKey: stringKey });
|
|
999
|
+
if (relatedMolecules)
|
|
1000
|
+
for (const [relatedStringKey, { source }] of relatedMolecules)
|
|
1001
|
+
if (source === stringKey)
|
|
1002
|
+
deallocateFromStore(target, parseJson(relatedStringKey));
|
|
1003
|
+
else
|
|
1004
|
+
provenance.push(source);
|
|
1005
|
+
const familyKeys = target.moleculeData.getRelatedKeys(molecule.stringKey);
|
|
1006
|
+
if (familyKeys)
|
|
1007
|
+
for (const familyKey of familyKeys) {
|
|
1008
|
+
const family = target.families.get(familyKey);
|
|
1009
|
+
const value = getFromStore(target, family, claim);
|
|
1010
|
+
values.push([family.key, value]);
|
|
1011
|
+
disposeFromStore(target, family, claim);
|
|
1012
|
+
}
|
|
1013
|
+
const disposalEvent = {
|
|
1014
|
+
type: `molecule_disposal`,
|
|
1015
|
+
key: molecule.key,
|
|
1016
|
+
values,
|
|
1017
|
+
provenance,
|
|
1018
|
+
timestamp: Date.now()
|
|
1019
|
+
};
|
|
1020
|
+
target.molecules.delete(stringKey);
|
|
1021
|
+
const isTransaction = isChildStore(target) && target.transactionMeta.phase === `building`;
|
|
1022
|
+
if (isTransaction)
|
|
1023
|
+
target.transactionMeta.update.subEvents.push(disposalEvent);
|
|
1024
|
+
target.moleculeGraph.delete(molecule.stringKey);
|
|
1025
|
+
target.keyRefsInJoins.delete(molecule.stringKey);
|
|
1026
|
+
target.moleculeData.delete(molecule.stringKey);
|
|
1027
|
+
if (!isTransaction)
|
|
1028
|
+
target.on.moleculeDisposal.next(disposalEvent);
|
|
1029
|
+
target.molecules.delete(molecule.stringKey);
|
|
1030
|
+
const trace = getTrace(/* @__PURE__ */ new Error);
|
|
1031
|
+
target.disposalTraces.add({
|
|
1032
|
+
key: stringKey,
|
|
1033
|
+
trace
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
function claimWithinStore(store, newProvenance, claim, exclusive) {
|
|
1037
|
+
const stringKey = stringifyJson(claim);
|
|
1038
|
+
const target = newest(store);
|
|
1039
|
+
const molecule = target.molecules.get(stringKey);
|
|
1040
|
+
if (!molecule) {
|
|
1041
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === stringKey);
|
|
1042
|
+
store.logger.error(`\u274C`, `key`, stringKey, `claim failed:`, `Could not allocate to ${stringKey} in store "${store.config.name}".`, disposal ? `
|
|
1043
|
+
${stringKey} was most recently disposed
|
|
1044
|
+
${disposal.trace}` : `No previous disposal trace for ${stringKey} was found.`);
|
|
1045
|
+
return claim;
|
|
1046
|
+
}
|
|
1047
|
+
const newProvenanceKey = stringifyJson(newProvenance);
|
|
1048
|
+
const newProvenanceMolecule = target.molecules.get(newProvenanceKey);
|
|
1049
|
+
if (!newProvenanceMolecule) {
|
|
1050
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === newProvenanceKey);
|
|
1051
|
+
store.logger.error(`\u274C`, `key`, claim, `claim failed:`, `Could not allocate to ${newProvenanceKey} in store "${store.config.name}".`, disposal ? `
|
|
1052
|
+
${newProvenanceKey} was most recently disposed
|
|
1053
|
+
${disposal.trace}` : `No previous disposal trace for ${newProvenanceKey} was found.`);
|
|
1054
|
+
return claim;
|
|
1055
|
+
}
|
|
1056
|
+
const priorProvenance = store.moleculeGraph.getRelationEntries({ downstreamMoleculeKey: molecule.stringKey }).filter(([, { source }]) => source !== stringKey).map(([key]) => parseJson(key));
|
|
1057
|
+
if (exclusive)
|
|
1058
|
+
target.moleculeGraph.delete(stringKey);
|
|
1059
|
+
target.moleculeGraph.set({
|
|
1060
|
+
upstreamMoleculeKey: newProvenanceMolecule.stringKey,
|
|
1061
|
+
downstreamMoleculeKey: molecule.stringKey
|
|
1062
|
+
}, { source: newProvenanceMolecule.stringKey });
|
|
1063
|
+
const transferEvent = {
|
|
1064
|
+
type: `molecule_transfer`,
|
|
1065
|
+
key: molecule.key,
|
|
1066
|
+
exclusive: Boolean(exclusive),
|
|
1067
|
+
from: priorProvenance,
|
|
1068
|
+
to: [newProvenanceMolecule.key],
|
|
1069
|
+
timestamp: Date.now()
|
|
1070
|
+
};
|
|
1071
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`)
|
|
1072
|
+
target.transactionMeta.update.subEvents.push(transferEvent);
|
|
1073
|
+
return claim;
|
|
1074
|
+
}
|
|
1075
|
+
function ingestCreationEvent(store, event, applying) {
|
|
1076
|
+
switch (applying) {
|
|
1077
|
+
case `newValue`:
|
|
1078
|
+
createInStore(store, event);
|
|
1079
|
+
break;
|
|
1080
|
+
case `oldValue`:
|
|
1081
|
+
disposeFromStore(store, event.token);
|
|
1082
|
+
break;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
function ingestDisposalEvent(store, event, applying) {
|
|
1086
|
+
switch (applying) {
|
|
1087
|
+
case `newValue`:
|
|
1088
|
+
disposeFromStore(store, event.token);
|
|
1089
|
+
break;
|
|
1090
|
+
case `oldValue`:
|
|
1091
|
+
createInStore(store, event);
|
|
1092
|
+
if (event.subType === `atom`)
|
|
1093
|
+
store.valueMap.set(event.token.key, event.value);
|
|
1094
|
+
break;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
function createInStore(store, event) {
|
|
1098
|
+
const { token } = event;
|
|
1099
|
+
if (event.subType === `writable` && event.value)
|
|
1100
|
+
setIntoStore(store, token, event.value);
|
|
1101
|
+
else
|
|
1102
|
+
getFromStore(store, token);
|
|
1103
|
+
}
|
|
1104
|
+
function ingestMoleculeCreationEvent(store, event, applying) {
|
|
1105
|
+
switch (applying) {
|
|
1106
|
+
case `newValue`:
|
|
1107
|
+
allocateIntoStore(store, event.provenance, event.key);
|
|
1108
|
+
break;
|
|
1109
|
+
case `oldValue`:
|
|
1110
|
+
deallocateFromStore(store, event.key);
|
|
1111
|
+
break;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
function ingestMoleculeDisposalEvent(store, event, applying) {
|
|
1115
|
+
switch (applying) {
|
|
1116
|
+
case `newValue`:
|
|
1117
|
+
deallocateFromStore(store, event.key);
|
|
1118
|
+
break;
|
|
1119
|
+
case `oldValue`:
|
|
1120
|
+
allocateIntoStore(store, event.provenance.map(parseJson), event.key);
|
|
1121
|
+
for (const [familyKey, value] of event.values) {
|
|
1122
|
+
const family = store.families.get(familyKey);
|
|
1123
|
+
if (family) {
|
|
1124
|
+
getFromStore(store, family, event.key);
|
|
1125
|
+
const memberKey = `${familyKey}(${stringifyJson(event.key)})`;
|
|
1126
|
+
store.valueMap.set(memberKey, value);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
break;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
function ingestMoleculeTransferEvent(store, event, applying) {
|
|
1133
|
+
switch (applying) {
|
|
1134
|
+
case `newValue`:
|
|
1135
|
+
for (const newOwner of event.to)
|
|
1136
|
+
claimWithinStore(store, newOwner, event.key, event.exclusive ? `exclusive` : undefined);
|
|
1137
|
+
break;
|
|
1138
|
+
case `oldValue`:
|
|
1139
|
+
{
|
|
1140
|
+
let exclusivity = `exclusive`;
|
|
1141
|
+
for (const previousOwner of event.from) {
|
|
1142
|
+
claimWithinStore(store, previousOwner, event.key, exclusivity);
|
|
1143
|
+
exclusivity = undefined;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
break;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
function ingestTransactionOutcomeEvent(store, event, applying) {
|
|
1150
|
+
const subEvents = applying === `newValue` ? event.subEvents : [...event.subEvents].reverse();
|
|
1151
|
+
for (const subEvent of subEvents)
|
|
1152
|
+
switch (subEvent.type) {
|
|
1153
|
+
case `atom_update`:
|
|
1154
|
+
ingestAtomUpdateEvent(store, subEvent, applying);
|
|
1155
|
+
break;
|
|
1156
|
+
case `state_creation`:
|
|
1157
|
+
ingestCreationEvent(store, subEvent, applying);
|
|
1158
|
+
break;
|
|
1159
|
+
case `state_disposal`:
|
|
1160
|
+
ingestDisposalEvent(store, subEvent, applying);
|
|
1161
|
+
break;
|
|
1162
|
+
case `molecule_creation`:
|
|
1163
|
+
ingestMoleculeCreationEvent(store, subEvent, applying);
|
|
1164
|
+
break;
|
|
1165
|
+
case `molecule_disposal`:
|
|
1166
|
+
ingestMoleculeDisposalEvent(store, subEvent, applying);
|
|
1167
|
+
break;
|
|
1168
|
+
case `molecule_transfer`:
|
|
1169
|
+
ingestMoleculeTransferEvent(store, subEvent, applying);
|
|
1170
|
+
break;
|
|
1171
|
+
case `transaction_outcome`:
|
|
1172
|
+
ingestTransactionOutcomeEvent(store, subEvent, applying);
|
|
1173
|
+
break;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
function isRootStore(store) {
|
|
1177
|
+
return `epoch` in store.transactionMeta;
|
|
1178
|
+
}
|
|
1179
|
+
function isChildStore(store) {
|
|
1180
|
+
return `phase` in store.transactionMeta;
|
|
1181
|
+
}
|
|
1182
|
+
function getContinuityKey(store, transactionKey) {
|
|
1183
|
+
return store.transactionMeta.actionContinuities.getRelatedKey(transactionKey);
|
|
1184
|
+
}
|
|
1185
|
+
function getEpochNumberOfContinuity(store, continuityKey) {
|
|
1186
|
+
return store.transactionMeta.epoch.get(continuityKey);
|
|
1187
|
+
}
|
|
1188
|
+
function getEpochNumberOfAction(store, transactionKey) {
|
|
1189
|
+
const continuityKey = getContinuityKey(store, transactionKey);
|
|
1190
|
+
if (continuityKey === undefined)
|
|
1191
|
+
return;
|
|
1192
|
+
return getEpochNumberOfContinuity(store, continuityKey);
|
|
1193
|
+
}
|
|
1194
|
+
function setEpochNumberOfAction(store, transactionKey, newEpoch) {
|
|
1195
|
+
const continuityKey = getContinuityKey(store, transactionKey);
|
|
1196
|
+
if (continuityKey !== undefined)
|
|
1197
|
+
store.transactionMeta.epoch.set(continuityKey, newEpoch);
|
|
1198
|
+
}
|
|
1199
|
+
function applyTransaction(store, output) {
|
|
1200
|
+
const child = newest(store);
|
|
1201
|
+
const { parent } = child;
|
|
1202
|
+
child.transactionMeta.phase = `applying`;
|
|
1203
|
+
child.transactionMeta.update.output = output;
|
|
1204
|
+
parent.child = null;
|
|
1205
|
+
parent.on.transactionApplying.next(child.transactionMeta);
|
|
1206
|
+
const { subEvents: updates } = child.transactionMeta.update;
|
|
1207
|
+
store.logger.info(`\uD83D\uDEC4`, `transaction`, child.transactionMeta.update.token.key, `applying ${updates.length} subEvents:`, updates);
|
|
1208
|
+
ingestTransactionOutcomeEvent(parent, child.transactionMeta.update, `newValue`);
|
|
1209
|
+
if (isRootStore(parent)) {
|
|
1210
|
+
setEpochNumberOfAction(parent, child.transactionMeta.update.token.key, child.transactionMeta.update.epoch);
|
|
1211
|
+
withdraw(store, {
|
|
1212
|
+
key: child.transactionMeta.update.token.key,
|
|
1213
|
+
type: `transaction`
|
|
1214
|
+
})?.subject.next(child.transactionMeta.update);
|
|
1215
|
+
store.logger.info(`\uD83D\uDEEC`, `transaction`, child.transactionMeta.update.token.key, `applied`);
|
|
1216
|
+
} else if (isChildStore(parent))
|
|
1217
|
+
parent.transactionMeta.update.subEvents.push(child.transactionMeta.update);
|
|
1218
|
+
parent.on.transactionApplying.next(null);
|
|
1219
|
+
}
|
|
1220
|
+
function getEnvironmentData(store) {
|
|
1221
|
+
return { store };
|
|
1222
|
+
}
|
|
1223
|
+
var buildTransaction = (store, token, params, id) => {
|
|
1224
|
+
const parent = newest(store);
|
|
1225
|
+
const childBase = {
|
|
1226
|
+
parent,
|
|
1227
|
+
child: null,
|
|
1228
|
+
on: parent.on,
|
|
1229
|
+
loggers: parent.loggers,
|
|
1230
|
+
logger: parent.logger,
|
|
1231
|
+
config: parent.config,
|
|
1232
|
+
atoms: new MapOverlay(parent.atoms),
|
|
1233
|
+
atomsThatAreDefault: new Set(parent.atomsThatAreDefault),
|
|
1234
|
+
families: new MapOverlay(parent.families),
|
|
1235
|
+
joins: new MapOverlay(parent.joins),
|
|
1236
|
+
operation: { open: false },
|
|
1237
|
+
readonlySelectors: new MapOverlay(parent.readonlySelectors),
|
|
1238
|
+
timelines: new MapOverlay(parent.timelines),
|
|
1239
|
+
timelineTopics: parent.timelineTopics.overlay(),
|
|
1240
|
+
trackers: /* @__PURE__ */ new Map,
|
|
1241
|
+
transactions: new MapOverlay(parent.transactions),
|
|
1242
|
+
selectorAtoms: parent.selectorAtoms.overlay(),
|
|
1243
|
+
selectorGraph: parent.selectorGraph.overlay(),
|
|
1244
|
+
writableSelectors: new MapOverlay(parent.writableSelectors),
|
|
1245
|
+
valueMap: new MapOverlay(parent.valueMap),
|
|
1246
|
+
defaults: parent.defaults,
|
|
1247
|
+
disposalTraces: store.disposalTraces.copy(),
|
|
1248
|
+
molecules: new MapOverlay(parent.molecules),
|
|
1249
|
+
moleculeGraph: parent.moleculeGraph.overlay(),
|
|
1250
|
+
moleculeData: parent.moleculeData.overlay(),
|
|
1251
|
+
keyRefsInJoins: parent.keyRefsInJoins.overlay(),
|
|
1252
|
+
miscResources: new MapOverlay(parent.miscResources)
|
|
1253
|
+
};
|
|
1254
|
+
const epoch = getEpochNumberOfAction(store, token.key);
|
|
1255
|
+
const transactionMeta = {
|
|
1256
|
+
phase: `building`,
|
|
1257
|
+
update: {
|
|
1258
|
+
type: `transaction_outcome`,
|
|
1259
|
+
token,
|
|
1260
|
+
id,
|
|
1261
|
+
epoch: epoch === undefined ? NaN : epoch + 1,
|
|
1262
|
+
timestamp: Date.now(),
|
|
1263
|
+
subEvents: [],
|
|
1264
|
+
params,
|
|
1265
|
+
output: undefined
|
|
1266
|
+
},
|
|
1267
|
+
toolkit: {
|
|
1268
|
+
get: (...ps) => getFromStore(child, ...ps),
|
|
1269
|
+
set: (...ps) => {
|
|
1270
|
+
setIntoStore(child, ...ps);
|
|
1271
|
+
},
|
|
1272
|
+
reset: (...ps) => {
|
|
1273
|
+
resetInStore(child, ...ps);
|
|
1274
|
+
},
|
|
1275
|
+
run: (t, identifier = arbitrary()) => actUponStore(child, t, identifier),
|
|
1276
|
+
find: (...ps) => findInStore(store, ...ps),
|
|
1277
|
+
json: (t) => getJsonToken(child, t),
|
|
1278
|
+
dispose: (...ps) => {
|
|
1279
|
+
disposeFromStore(child, ...ps);
|
|
1280
|
+
},
|
|
1281
|
+
env: () => getEnvironmentData(child)
|
|
1282
|
+
}
|
|
1283
|
+
};
|
|
1284
|
+
const child = Object.assign(childBase, { transactionMeta });
|
|
1285
|
+
parent.child = child;
|
|
1286
|
+
store.logger.info(`\uD83D\uDEEB`, `transaction`, token.key, `building with params:`, params);
|
|
1287
|
+
return child;
|
|
1288
|
+
};
|
|
1289
|
+
function createTransaction(store, options) {
|
|
1290
|
+
const { key } = options;
|
|
1291
|
+
const transactionAlreadyExists = store.transactions.has(key);
|
|
1292
|
+
const newTransaction = {
|
|
1293
|
+
key,
|
|
1294
|
+
type: `transaction`,
|
|
1295
|
+
run: (params, id) => {
|
|
1296
|
+
const target = buildTransaction(store, deposit(newTransaction), params, id);
|
|
1297
|
+
try {
|
|
1298
|
+
const { toolkit } = target.transactionMeta;
|
|
1299
|
+
const output = options.do(toolkit, ...params);
|
|
1300
|
+
applyTransaction(target, output);
|
|
1301
|
+
return output;
|
|
1302
|
+
} catch (thrown) {
|
|
1303
|
+
abortTransaction(target);
|
|
1304
|
+
store.logger.warn(`\uD83D\uDCA5`, `transaction`, key, `caught:`, thrown);
|
|
1305
|
+
throw thrown;
|
|
1306
|
+
}
|
|
1307
|
+
},
|
|
1308
|
+
install: (s) => createTransaction(s, options),
|
|
1309
|
+
subject: new Subject
|
|
1310
|
+
};
|
|
1311
|
+
newest(store).transactions.set(key, newTransaction);
|
|
1312
|
+
const token = deposit(newTransaction);
|
|
1313
|
+
if (!transactionAlreadyExists)
|
|
1314
|
+
store.on.transactionCreation.next(token);
|
|
1315
|
+
return token;
|
|
1316
|
+
}
|
|
1317
|
+
var Store = class {
|
|
1318
|
+
parent = null;
|
|
1319
|
+
child = null;
|
|
1320
|
+
valueMap = /* @__PURE__ */ new Map;
|
|
1321
|
+
defaults = /* @__PURE__ */ new Map;
|
|
1322
|
+
atoms = /* @__PURE__ */ new Map;
|
|
1323
|
+
writableSelectors = /* @__PURE__ */ new Map;
|
|
1324
|
+
readonlySelectors = /* @__PURE__ */ new Map;
|
|
1325
|
+
atomsThatAreDefault = /* @__PURE__ */ new Set;
|
|
1326
|
+
selectorAtoms = new Junction({
|
|
1327
|
+
between: [`selectorKey`, `atomKey`],
|
|
1328
|
+
cardinality: `n:n`
|
|
1329
|
+
});
|
|
1330
|
+
selectorGraph = new Junction({
|
|
1331
|
+
between: [`upstreamSelectorKey`, `downstreamSelectorKey`],
|
|
1332
|
+
cardinality: `n:n`
|
|
1333
|
+
}, { makeContentKey: (...keys) => keys.sort().join(`:`) });
|
|
1334
|
+
trackers = /* @__PURE__ */ new Map;
|
|
1335
|
+
families = /* @__PURE__ */ new Map;
|
|
1336
|
+
joins = /* @__PURE__ */ new Map;
|
|
1337
|
+
transactions = /* @__PURE__ */ new Map;
|
|
1338
|
+
transactionMeta = {
|
|
1339
|
+
epoch: /* @__PURE__ */ new Map,
|
|
1340
|
+
actionContinuities: new Junction({
|
|
1341
|
+
between: [`continuity`, `action`],
|
|
1342
|
+
cardinality: `1:n`
|
|
1343
|
+
})
|
|
1344
|
+
};
|
|
1345
|
+
timelines = /* @__PURE__ */ new Map;
|
|
1346
|
+
timelineTopics = new Junction({
|
|
1347
|
+
between: [`timelineKey`, `topicKey`],
|
|
1348
|
+
cardinality: `1:n`
|
|
1349
|
+
});
|
|
1350
|
+
disposalTraces = new CircularBuffer(100);
|
|
1351
|
+
molecules = /* @__PURE__ */ new Map;
|
|
1352
|
+
moleculeGraph = new Junction({
|
|
1353
|
+
between: [`upstreamMoleculeKey`, `downstreamMoleculeKey`],
|
|
1354
|
+
cardinality: `n:n`
|
|
1355
|
+
}, { makeContentKey: (...keys) => keys.sort().join(`:`) });
|
|
1356
|
+
moleculeData = new Junction({
|
|
1357
|
+
between: [`moleculeKey`, `stateFamilyKey`],
|
|
1358
|
+
cardinality: `n:n`
|
|
1359
|
+
}, { makeContentKey: (...keys) => keys.sort().join(`:`) });
|
|
1360
|
+
keyRefsInJoins = new Junction({
|
|
1361
|
+
between: [`moleculeKey`, `joinKey`],
|
|
1362
|
+
cardinality: `n:n`
|
|
1363
|
+
}, { makeContentKey: (...keys) => keys.sort().join(`:`) });
|
|
1364
|
+
miscResources = /* @__PURE__ */ new Map;
|
|
1365
|
+
on = {
|
|
1366
|
+
atomCreation: new Subject,
|
|
1367
|
+
atomDisposal: new Subject,
|
|
1368
|
+
selectorCreation: new Subject,
|
|
1369
|
+
selectorDisposal: new Subject,
|
|
1370
|
+
timelineCreation: new Subject,
|
|
1371
|
+
transactionCreation: new Subject,
|
|
1372
|
+
transactionApplying: new StatefulSubject(null),
|
|
1373
|
+
operationClose: new Subject,
|
|
1374
|
+
moleculeCreation: new Subject,
|
|
1375
|
+
moleculeDisposal: new Subject
|
|
1376
|
+
};
|
|
1377
|
+
operation = { open: false };
|
|
1378
|
+
config = {
|
|
1379
|
+
name: `IMPLICIT_STORE`,
|
|
1380
|
+
lifespan: `ephemeral`,
|
|
1381
|
+
isProduction: globalThis.process?.env?.[`NODE_ENV`] === `production`
|
|
1382
|
+
};
|
|
1383
|
+
loggers = [new AtomIOLogger(`warn`, (_, __, key) => !isReservedIntrospectionKey(key))];
|
|
1384
|
+
logger = {
|
|
1385
|
+
error: (...messages) => {
|
|
1386
|
+
for (const logger of this.loggers)
|
|
1387
|
+
logger.error(...messages);
|
|
1388
|
+
},
|
|
1389
|
+
info: (...messages) => {
|
|
1390
|
+
for (const logger of this.loggers)
|
|
1391
|
+
logger.info(...messages);
|
|
1392
|
+
},
|
|
1393
|
+
warn: (...messages) => {
|
|
1394
|
+
for (const logger of this.loggers)
|
|
1395
|
+
logger.warn(...messages);
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
constructor(config, store = null) {
|
|
1399
|
+
this.config = {
|
|
1400
|
+
...store?.config,
|
|
1401
|
+
...config
|
|
1402
|
+
};
|
|
1403
|
+
if (store !== null) {
|
|
1404
|
+
this.operation = { ...store?.operation };
|
|
1405
|
+
if (isRootStore(store))
|
|
1406
|
+
this.transactionMeta = {
|
|
1407
|
+
epoch: new Map(store?.transactionMeta.epoch),
|
|
1408
|
+
actionContinuities: new Junction(store?.transactionMeta.actionContinuities.toJSON())
|
|
1409
|
+
};
|
|
1410
|
+
for (const [, family] of store.families) {
|
|
1411
|
+
if (family.internalRoles?.includes(`mutable`) || family.internalRoles?.includes(`join`))
|
|
1412
|
+
continue;
|
|
1413
|
+
family.install(this);
|
|
1414
|
+
}
|
|
1415
|
+
const mutableHelpers = /* @__PURE__ */ new Set;
|
|
1416
|
+
for (const [, atom] of store.atoms) {
|
|
1417
|
+
if (mutableHelpers.has(atom.key))
|
|
1418
|
+
continue;
|
|
1419
|
+
atom.install(this);
|
|
1420
|
+
if (atom.type === `mutable_atom`) {
|
|
1421
|
+
const originalJsonToken = getJsonToken(store, atom);
|
|
1422
|
+
const originalUpdateToken = getUpdateToken(atom);
|
|
1423
|
+
mutableHelpers.add(originalJsonToken.key);
|
|
1424
|
+
mutableHelpers.add(originalUpdateToken.key);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
for (const [, selector] of store.readonlySelectors)
|
|
1428
|
+
selector.install(this);
|
|
1429
|
+
for (const [, selector] of store.writableSelectors) {
|
|
1430
|
+
if (mutableHelpers.has(selector.key))
|
|
1431
|
+
continue;
|
|
1432
|
+
selector.install(this);
|
|
1433
|
+
}
|
|
1434
|
+
for (const [, tx] of store.transactions)
|
|
1435
|
+
tx.install(this);
|
|
1436
|
+
for (const [, timeline] of store.timelines)
|
|
1437
|
+
timeline.install(this);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
var IMPLICIT = { get STORE() {
|
|
1442
|
+
globalThis.ATOM_IO_IMPLICIT_STORE ??= new Store({
|
|
1443
|
+
name: `IMPLICIT_STORE`,
|
|
1444
|
+
lifespan: `ephemeral`,
|
|
1445
|
+
isProduction: globalThis.process?.env?.[`NODE_ENV`] === `production`
|
|
1446
|
+
});
|
|
1447
|
+
return globalThis.ATOM_IO_IMPLICIT_STORE;
|
|
1448
|
+
} };
|
|
1449
|
+
var NotFoundError = class extends Error {
|
|
1450
|
+
constructor(token, store) {
|
|
1451
|
+
super(`${PRETTY_TOKEN_TYPES[token.type]} ${stringifyJson(token.key)} not found in store "${store.config.name}".`);
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
function withdraw(store, token) {
|
|
1455
|
+
let withdrawn;
|
|
1456
|
+
let target = store;
|
|
1457
|
+
while (target !== null) {
|
|
1458
|
+
switch (token.type) {
|
|
1459
|
+
case `atom`:
|
|
1460
|
+
case `mutable_atom`:
|
|
1461
|
+
withdrawn = target.atoms.get(token.key);
|
|
1462
|
+
break;
|
|
1463
|
+
case `writable_pure_selector`:
|
|
1464
|
+
case `writable_held_selector`:
|
|
1465
|
+
withdrawn = target.writableSelectors.get(token.key);
|
|
1466
|
+
break;
|
|
1467
|
+
case `readonly_pure_selector`:
|
|
1468
|
+
case `readonly_held_selector`:
|
|
1469
|
+
withdrawn = target.readonlySelectors.get(token.key);
|
|
1470
|
+
break;
|
|
1471
|
+
case `atom_family`:
|
|
1472
|
+
case `mutable_atom_family`:
|
|
1473
|
+
case `writable_pure_selector_family`:
|
|
1474
|
+
case `readonly_pure_selector_family`:
|
|
1475
|
+
case `writable_held_selector_family`:
|
|
1476
|
+
case `readonly_held_selector_family`:
|
|
1477
|
+
withdrawn = target.families.get(token.key);
|
|
1478
|
+
break;
|
|
1479
|
+
case `timeline`:
|
|
1480
|
+
withdrawn = target.timelines.get(token.key);
|
|
1481
|
+
break;
|
|
1482
|
+
case `transaction`:
|
|
1483
|
+
withdrawn = target.transactions.get(token.key);
|
|
1484
|
+
break;
|
|
1485
|
+
}
|
|
1486
|
+
if (withdrawn)
|
|
1487
|
+
return withdrawn;
|
|
1488
|
+
target = target.child;
|
|
1489
|
+
}
|
|
1490
|
+
throw new NotFoundError(token, store);
|
|
1491
|
+
}
|
|
1492
|
+
function getFallback(store, token, family, subKey) {
|
|
1493
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === stringifyJson(subKey));
|
|
1494
|
+
store.logger.error(`\u274C`, token.type, token.key, `gets a fallback value because key`, subKey, `is not allocated`, disposal ? `This key was previously disposed:
|
|
1495
|
+
${disposal.trace}` : `(no previous disposal trace found)`);
|
|
1496
|
+
switch (family.type) {
|
|
1497
|
+
case `mutable_atom_family`: {
|
|
1498
|
+
if (store.defaults.has(family.key))
|
|
1499
|
+
return store.defaults.get(family.key);
|
|
1500
|
+
const defaultValue = new family.class;
|
|
1501
|
+
store.defaults.set(family.key, defaultValue);
|
|
1502
|
+
return defaultValue.READONLY_VIEW;
|
|
1503
|
+
}
|
|
1504
|
+
case `atom_family`: {
|
|
1505
|
+
if (store.defaults.has(family.key))
|
|
1506
|
+
return store.defaults.get(family.key);
|
|
1507
|
+
const def = family.default;
|
|
1508
|
+
const defaultValue = def(subKey);
|
|
1509
|
+
store.defaults.set(family.key, defaultValue);
|
|
1510
|
+
return defaultValue;
|
|
1511
|
+
}
|
|
1512
|
+
case `readonly_pure_selector_family`:
|
|
1513
|
+
case `writable_pure_selector_family`:
|
|
1514
|
+
case `readonly_held_selector_family`:
|
|
1515
|
+
case `writable_held_selector_family`: {
|
|
1516
|
+
if (store.defaults.has(family.key))
|
|
1517
|
+
return store.defaults.get(family.key);
|
|
1518
|
+
const defaultValue = family.default(subKey);
|
|
1519
|
+
store.defaults.set(family.key, defaultValue);
|
|
1520
|
+
return defaultValue;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
function safeCompute(target, state) {
|
|
1525
|
+
const { type, key, catch: canCatch } = state;
|
|
1526
|
+
switch (type) {
|
|
1527
|
+
case `readonly_pure_selector`:
|
|
1528
|
+
case `writable_pure_selector`: {
|
|
1529
|
+
let val;
|
|
1530
|
+
target.logger.info(`\uD83E\uDDEE`, type, key, `computing value`);
|
|
1531
|
+
try {
|
|
1532
|
+
val = state.getFrom(target);
|
|
1533
|
+
if (val instanceof Promise)
|
|
1534
|
+
return val.catch((thrown) => {
|
|
1535
|
+
target.logger.error(`\uD83D\uDCA5`, type, key, `rejected:`, thrown);
|
|
1536
|
+
if (canCatch) {
|
|
1537
|
+
for (const Class of canCatch)
|
|
1538
|
+
if (thrown instanceof Class)
|
|
1539
|
+
return thrown;
|
|
1540
|
+
}
|
|
1541
|
+
throw thrown;
|
|
1542
|
+
});
|
|
1543
|
+
} catch (e) {
|
|
1544
|
+
target.logger.error(`\uD83D\uDCA5`, type, key, `rejected:`, e);
|
|
1545
|
+
if (canCatch) {
|
|
1546
|
+
for (const Class of canCatch)
|
|
1547
|
+
if (e instanceof Class)
|
|
1548
|
+
return writeToCache(target, state, e);
|
|
1549
|
+
}
|
|
1550
|
+
throw e;
|
|
1551
|
+
}
|
|
1552
|
+
return writeToCache(target, state, val);
|
|
1553
|
+
}
|
|
1554
|
+
case `atom`: {
|
|
1555
|
+
let def;
|
|
1556
|
+
if (isFn(state.default))
|
|
1557
|
+
try {
|
|
1558
|
+
def = state.default();
|
|
1559
|
+
if (def instanceof Promise)
|
|
1560
|
+
def = def.catch((thrown) => {
|
|
1561
|
+
target.logger.error(`\uD83D\uDCA5`, type, key, `rejected:`, thrown);
|
|
1562
|
+
if (canCatch) {
|
|
1563
|
+
for (const Class of canCatch)
|
|
1564
|
+
if (thrown instanceof Class)
|
|
1565
|
+
return thrown;
|
|
1566
|
+
}
|
|
1567
|
+
throw thrown;
|
|
1568
|
+
});
|
|
1569
|
+
} catch (e) {
|
|
1570
|
+
target.logger.error(`\uD83D\uDCA5`, type, key, `rejected:`, e);
|
|
1571
|
+
if (canCatch) {
|
|
1572
|
+
for (const Class of canCatch)
|
|
1573
|
+
if (e instanceof Class) {
|
|
1574
|
+
def = writeToCache(target, state, e);
|
|
1575
|
+
target.logger.info(`\u2728`, state.type, key, `computed default`, def);
|
|
1576
|
+
return def;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
throw e;
|
|
1580
|
+
}
|
|
1581
|
+
else {
|
|
1582
|
+
def = state.default;
|
|
1583
|
+
target.logger.info(`\u2728`, state.type, key, `using static default`, def);
|
|
1584
|
+
}
|
|
1585
|
+
return writeToCache(target, state, def);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
function readOrComputeValue(target, state, mut) {
|
|
1590
|
+
if (target.valueMap.has(state.key))
|
|
1591
|
+
return readFromCache(target, state, mut);
|
|
1592
|
+
target.logger.info(`\u2754`, state.type, state.key, `value not found in cache`);
|
|
1593
|
+
const { key } = state;
|
|
1594
|
+
switch (state.type) {
|
|
1595
|
+
case `readonly_held_selector`:
|
|
1596
|
+
case `writable_held_selector`:
|
|
1597
|
+
target.logger.info(`\uD83E\uDDEE`, state.type, key, `computing value`);
|
|
1598
|
+
return state.getFrom(target);
|
|
1599
|
+
case `writable_pure_selector`:
|
|
1600
|
+
case `readonly_pure_selector`:
|
|
1601
|
+
case `atom`:
|
|
1602
|
+
return safeCompute(target, state);
|
|
1603
|
+
case `mutable_atom`: {
|
|
1604
|
+
const instance = new state.class;
|
|
1605
|
+
target.logger.info(`\u2728`, state.type, key, `created new instance`, instance);
|
|
1606
|
+
return writeToCache(target, state, instance);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
function getFamilyOfToken(store, token) {
|
|
1611
|
+
return withdraw(store, {
|
|
1612
|
+
key: token.family.key,
|
|
1613
|
+
type: `${token.type}_family`
|
|
1614
|
+
});
|
|
1615
|
+
}
|
|
1616
|
+
var FAMILY_MEMBER_TOKEN_TYPES = {
|
|
1617
|
+
atom_family: `atom`,
|
|
1618
|
+
molecule_family: `molecule`,
|
|
1619
|
+
mutable_atom_family: `mutable_atom`,
|
|
1620
|
+
readonly_held_selector_family: `readonly_held_selector`,
|
|
1621
|
+
readonly_pure_selector_family: `readonly_pure_selector`,
|
|
1622
|
+
writable_held_selector_family: `writable_held_selector`,
|
|
1623
|
+
writable_pure_selector_family: `writable_pure_selector`
|
|
1624
|
+
};
|
|
1625
|
+
var MUST_CREATE = Symbol(`MUST_CREATE`);
|
|
1626
|
+
var DO_NOT_CREATE = Symbol(`DO_NOT_CREATE`);
|
|
1627
|
+
function mintInStore(mustCreate, store, family, key) {
|
|
1628
|
+
const stringKey = stringifyJson(key);
|
|
1629
|
+
const molecule = store.molecules.get(stringKey);
|
|
1630
|
+
if (!molecule && store.config.lifespan === `immortal`) {
|
|
1631
|
+
const { type: familyType, key: familyKey } = family;
|
|
1632
|
+
store.logger.warn(`\uD83D\uDCA3`, `key`, stringKey, `was used to mint a counterfeit token for`, familyType, `"${familyKey}"`);
|
|
1633
|
+
return {
|
|
1634
|
+
counterfeit: true,
|
|
1635
|
+
key: `${familyKey}(${stringKey})`,
|
|
1636
|
+
type: FAMILY_MEMBER_TOKEN_TYPES[familyType],
|
|
1637
|
+
family: {
|
|
1638
|
+
key: familyKey,
|
|
1639
|
+
subKey: stringKey
|
|
1640
|
+
}
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
let token;
|
|
1644
|
+
if (mustCreate === MUST_CREATE) {
|
|
1645
|
+
store.logger.info(`\uD83D\uDC6A`, family.type, family.key, `adds member`, typeof key === `string` ? `\`${key}\`` : key);
|
|
1646
|
+
token = family.create(key);
|
|
1647
|
+
if (molecule)
|
|
1648
|
+
store.moleculeData.set(stringKey, family.key);
|
|
1649
|
+
} else {
|
|
1650
|
+
const { type: familyType, key: familyKey } = family;
|
|
1651
|
+
return {
|
|
1652
|
+
key: `${familyKey}(${stringKey})`,
|
|
1653
|
+
type: FAMILY_MEMBER_TOKEN_TYPES[familyType],
|
|
1654
|
+
family: {
|
|
1655
|
+
key: familyKey,
|
|
1656
|
+
subKey: stringKey
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
return token;
|
|
1661
|
+
}
|
|
1662
|
+
function reduceReference(store, ...params) {
|
|
1663
|
+
let existingToken;
|
|
1664
|
+
let brandNewToken;
|
|
1665
|
+
let family;
|
|
1666
|
+
let subKey;
|
|
1667
|
+
let token;
|
|
1668
|
+
if (params.length === 1) {
|
|
1669
|
+
token = params[0];
|
|
1670
|
+
if (`family` in token) {
|
|
1671
|
+
const familyToken = getFamilyOfToken(store, token);
|
|
1672
|
+
family = withdraw(store, familyToken);
|
|
1673
|
+
subKey = parseJson(token.family.subKey);
|
|
1674
|
+
existingToken = seekInStore(store, familyToken, subKey);
|
|
1675
|
+
if (`counterfeit` in token)
|
|
1676
|
+
return {
|
|
1677
|
+
token,
|
|
1678
|
+
family,
|
|
1679
|
+
subKey,
|
|
1680
|
+
isNew: false
|
|
1681
|
+
};
|
|
1682
|
+
if (!existingToken) {
|
|
1683
|
+
brandNewToken = mintInStore(MUST_CREATE, store, familyToken, subKey);
|
|
1684
|
+
token = brandNewToken;
|
|
1685
|
+
} else
|
|
1686
|
+
token = existingToken;
|
|
1687
|
+
}
|
|
1688
|
+
} else {
|
|
1689
|
+
family = withdraw(store, params[0]);
|
|
1690
|
+
subKey = params[1];
|
|
1691
|
+
existingToken = seekInStore(store, family, subKey);
|
|
1692
|
+
if (!existingToken) {
|
|
1693
|
+
brandNewToken = mintInStore(MUST_CREATE, store, family, subKey);
|
|
1694
|
+
token = brandNewToken;
|
|
1695
|
+
} else
|
|
1696
|
+
token = existingToken;
|
|
1697
|
+
}
|
|
1698
|
+
const isCounterfeit = `counterfeit` in token;
|
|
1699
|
+
if (Boolean(brandNewToken) && isCounterfeit === false && family) {
|
|
1700
|
+
let subType;
|
|
1701
|
+
switch (token.type) {
|
|
1702
|
+
case `readonly_pure_selector`:
|
|
1703
|
+
case `readonly_held_selector`:
|
|
1704
|
+
subType = `readable`;
|
|
1705
|
+
break;
|
|
1706
|
+
case `atom`:
|
|
1707
|
+
case `mutable_atom`:
|
|
1708
|
+
case `writable_pure_selector`:
|
|
1709
|
+
case `writable_held_selector`:
|
|
1710
|
+
subType = `writable`;
|
|
1711
|
+
break;
|
|
1712
|
+
}
|
|
1713
|
+
const stateCreationEvent = {
|
|
1714
|
+
type: `state_creation`,
|
|
1715
|
+
subType,
|
|
1716
|
+
token,
|
|
1717
|
+
timestamp: Date.now()
|
|
1718
|
+
};
|
|
1719
|
+
family.subject.next(stateCreationEvent);
|
|
1720
|
+
const target = newest(store);
|
|
1721
|
+
if (token.family) {
|
|
1722
|
+
if (isRootStore(target))
|
|
1723
|
+
switch (token.type) {
|
|
1724
|
+
case `atom`:
|
|
1725
|
+
case `mutable_atom`:
|
|
1726
|
+
store.on.atomCreation.next(token);
|
|
1727
|
+
break;
|
|
1728
|
+
case `writable_pure_selector`:
|
|
1729
|
+
case `readonly_pure_selector`:
|
|
1730
|
+
case `writable_held_selector`:
|
|
1731
|
+
case `readonly_held_selector`:
|
|
1732
|
+
store.on.selectorCreation.next(token);
|
|
1733
|
+
break;
|
|
1734
|
+
}
|
|
1735
|
+
else if (isChildStore(target) && target.on.transactionApplying.state === null)
|
|
1736
|
+
target.transactionMeta.update.subEvents.push(stateCreationEvent);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
return {
|
|
1740
|
+
token,
|
|
1741
|
+
family,
|
|
1742
|
+
subKey,
|
|
1743
|
+
isNew: Boolean(brandNewToken)
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
function getFromStore(store, ...params) {
|
|
1747
|
+
const { token, family, subKey } = reduceReference(store, ...params);
|
|
1748
|
+
if (`counterfeit` in token && family && subKey)
|
|
1749
|
+
return getFallback(store, token, family, subKey);
|
|
1750
|
+
return readOrComputeValue(store, withdraw(store, token));
|
|
1751
|
+
}
|
|
1752
|
+
function seekInStore(store, token, key) {
|
|
1753
|
+
const subKey = stringifyJson(key);
|
|
1754
|
+
const fullKey = `${token.key}(${subKey})`;
|
|
1755
|
+
const target = newest(store);
|
|
1756
|
+
let state;
|
|
1757
|
+
switch (token.type) {
|
|
1758
|
+
case `atom_family`:
|
|
1759
|
+
case `mutable_atom_family`:
|
|
1760
|
+
state = target.atoms.get(fullKey);
|
|
1761
|
+
break;
|
|
1762
|
+
case `writable_held_selector_family`:
|
|
1763
|
+
case `writable_pure_selector_family`:
|
|
1764
|
+
state = target.writableSelectors.get(fullKey);
|
|
1765
|
+
break;
|
|
1766
|
+
case `readonly_held_selector_family`:
|
|
1767
|
+
case `readonly_pure_selector_family`:
|
|
1768
|
+
state = target.readonlySelectors.get(fullKey);
|
|
1769
|
+
break;
|
|
1770
|
+
}
|
|
1771
|
+
if (state)
|
|
1772
|
+
return deposit(state);
|
|
1773
|
+
return state;
|
|
1774
|
+
}
|
|
1775
|
+
function findInStore(store, familyToken, key) {
|
|
1776
|
+
const family = withdraw(store, familyToken);
|
|
1777
|
+
const existingStateToken = seekInStore(store, familyToken, key);
|
|
1778
|
+
if (existingStateToken)
|
|
1779
|
+
return existingStateToken;
|
|
1780
|
+
return mintInStore(DO_NOT_CREATE, store, family, key);
|
|
1781
|
+
}
|
|
1782
|
+
function createReadonlyPureSelectorFamily(store, options, internalRoles) {
|
|
1783
|
+
const familyKey = options.key;
|
|
1784
|
+
const type = `readonly_pure_selector_family`;
|
|
1785
|
+
const familyToken = {
|
|
1786
|
+
key: familyKey,
|
|
1787
|
+
type
|
|
1788
|
+
};
|
|
1789
|
+
const existing = store.families.get(familyKey);
|
|
1790
|
+
if (existing && store.config.isProduction === true)
|
|
1791
|
+
store.logger.error(`\u2757`, type, familyKey, `Overwriting an existing ${PRETTY_TOKEN_TYPES[existing.type]} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);
|
|
1792
|
+
const subject = new Subject;
|
|
1793
|
+
const create = (key) => {
|
|
1794
|
+
const subKey = stringifyJson(key);
|
|
1795
|
+
const family = {
|
|
1796
|
+
key: familyKey,
|
|
1797
|
+
subKey
|
|
1798
|
+
};
|
|
1799
|
+
const fullKey = `${familyKey}(${subKey})`;
|
|
1800
|
+
const target = newest(store);
|
|
1801
|
+
const individualOptions = {
|
|
1802
|
+
key: fullKey,
|
|
1803
|
+
get: options.get(key)
|
|
1804
|
+
};
|
|
1805
|
+
if (options.catch)
|
|
1806
|
+
individualOptions.catch = options.catch;
|
|
1807
|
+
return createReadonlyPureSelector(target, individualOptions, family);
|
|
1808
|
+
};
|
|
1809
|
+
const readonlySelectorFamily = {
|
|
1810
|
+
...familyToken,
|
|
1811
|
+
create,
|
|
1812
|
+
internalRoles,
|
|
1813
|
+
subject,
|
|
1814
|
+
install: (s) => createReadonlyPureSelectorFamily(s, options),
|
|
1815
|
+
default: (key) => {
|
|
1816
|
+
return options.get(key)({
|
|
1817
|
+
get: (...args) => getFromStore(store, ...args),
|
|
1818
|
+
find: (...args) => findInStore(store, ...args),
|
|
1819
|
+
json: (token) => getJsonToken(store, token)
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
store.families.set(familyKey, readonlySelectorFamily);
|
|
1824
|
+
return familyToken;
|
|
1825
|
+
}
|
|
1826
|
+
function createRegularAtomFamily(store, options, internalRoles) {
|
|
1827
|
+
const familyToken = {
|
|
1828
|
+
key: options.key,
|
|
1829
|
+
type: `atom_family`
|
|
1830
|
+
};
|
|
1831
|
+
const existing = store.families.get(options.key);
|
|
1832
|
+
if (existing && store.config.isProduction === true)
|
|
1833
|
+
store.logger.error(`\u2757`, `atom_family`, options.key, `Overwriting an existing ${PRETTY_TOKEN_TYPES[existing.type]} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);
|
|
1834
|
+
const subject = new Subject;
|
|
1835
|
+
const create = (key) => {
|
|
1836
|
+
const subKey = stringifyJson(key);
|
|
1837
|
+
const family = {
|
|
1838
|
+
key: options.key,
|
|
1839
|
+
subKey
|
|
1840
|
+
};
|
|
1841
|
+
const fullKey = `${options.key}(${subKey})`;
|
|
1842
|
+
const target = newest(store);
|
|
1843
|
+
const def = options.default;
|
|
1844
|
+
const individualOptions = {
|
|
1845
|
+
key: fullKey,
|
|
1846
|
+
default: isFn(def) ? () => def(key) : def
|
|
1847
|
+
};
|
|
1848
|
+
if (options.effects)
|
|
1849
|
+
individualOptions.effects = options.effects(key);
|
|
1850
|
+
if (options.catch)
|
|
1851
|
+
individualOptions.catch = options.catch;
|
|
1852
|
+
return createRegularAtom(target, individualOptions, family);
|
|
1853
|
+
};
|
|
1854
|
+
const atomFamily$1 = {
|
|
1855
|
+
...familyToken,
|
|
1856
|
+
create,
|
|
1857
|
+
default: options.default,
|
|
1858
|
+
subject,
|
|
1859
|
+
install: (s) => createRegularAtomFamily(s, options),
|
|
1860
|
+
internalRoles
|
|
1861
|
+
};
|
|
1862
|
+
store.families.set(options.key, atomFamily$1);
|
|
1863
|
+
if (isFn(options.default) === false)
|
|
1864
|
+
store.defaults.set(options.key, options.default);
|
|
1865
|
+
return familyToken;
|
|
1866
|
+
}
|
|
1867
|
+
function createReadonlyHeldSelectorFamily(store, options, internalRoles) {
|
|
1868
|
+
const familyKey = options.key;
|
|
1869
|
+
const type = `readonly_held_selector_family`;
|
|
1870
|
+
const familyToken = {
|
|
1871
|
+
key: familyKey,
|
|
1872
|
+
type
|
|
1873
|
+
};
|
|
1874
|
+
const existing = store.families.get(familyKey);
|
|
1875
|
+
if (existing && store.config.isProduction === true)
|
|
1876
|
+
store.logger.error(`\u2757`, type, familyKey, `Overwriting an existing ${PRETTY_TOKEN_TYPES[existing.type]} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);
|
|
1877
|
+
const subject = new Subject;
|
|
1878
|
+
const create = (key) => {
|
|
1879
|
+
const subKey = stringifyJson(key);
|
|
1880
|
+
const family = {
|
|
1881
|
+
key: familyKey,
|
|
1882
|
+
subKey
|
|
1883
|
+
};
|
|
1884
|
+
const fullKey = `${familyKey}(${subKey})`;
|
|
1885
|
+
return createReadonlyHeldSelector(newest(store), {
|
|
1886
|
+
key: fullKey,
|
|
1887
|
+
const: options.const(key),
|
|
1888
|
+
get: options.get(key)
|
|
1889
|
+
}, family);
|
|
1890
|
+
};
|
|
1891
|
+
const readonlySelectorFamily = {
|
|
1892
|
+
...familyToken,
|
|
1893
|
+
create,
|
|
1894
|
+
internalRoles,
|
|
1895
|
+
subject,
|
|
1896
|
+
install: (s) => createReadonlyHeldSelectorFamily(s, options),
|
|
1897
|
+
default: options.const
|
|
1898
|
+
};
|
|
1899
|
+
store.families.set(familyKey, readonlySelectorFamily);
|
|
1900
|
+
return familyToken;
|
|
1901
|
+
}
|
|
1902
|
+
function createWritableHeldSelectorFamily(store, options, internalRoles) {
|
|
1903
|
+
const familyKey = options.key;
|
|
1904
|
+
const type = `writable_held_selector_family`;
|
|
1905
|
+
const familyToken = {
|
|
1906
|
+
key: familyKey,
|
|
1907
|
+
type
|
|
1908
|
+
};
|
|
1909
|
+
const existing = store.families.get(familyKey);
|
|
1910
|
+
if (existing && store.config.isProduction === true)
|
|
1911
|
+
store.logger.error(`\u2757`, type, familyKey, `Overwriting an existing ${PRETTY_TOKEN_TYPES[existing.type]} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);
|
|
1912
|
+
const subject = new Subject;
|
|
1913
|
+
const create = (key) => {
|
|
1914
|
+
const subKey = stringifyJson(key);
|
|
1915
|
+
const family = {
|
|
1916
|
+
key: familyKey,
|
|
1917
|
+
subKey
|
|
1918
|
+
};
|
|
1919
|
+
const fullKey = `${familyKey}(${subKey})`;
|
|
1920
|
+
return createWritableHeldSelector(newest(store), {
|
|
1921
|
+
key: fullKey,
|
|
1922
|
+
const: options.const(key),
|
|
1923
|
+
get: options.get(key),
|
|
1924
|
+
set: options.set(key)
|
|
1925
|
+
}, family);
|
|
1926
|
+
};
|
|
1927
|
+
const selectorFamily$1 = {
|
|
1928
|
+
...familyToken,
|
|
1929
|
+
create,
|
|
1930
|
+
internalRoles,
|
|
1931
|
+
subject,
|
|
1932
|
+
install: (s) => createWritableHeldSelectorFamily(s, options),
|
|
1933
|
+
default: options.const
|
|
1934
|
+
};
|
|
1935
|
+
store.families.set(familyKey, selectorFamily$1);
|
|
1936
|
+
return familyToken;
|
|
1937
|
+
}
|
|
1938
|
+
function createWritablePureSelectorFamily(store, options, internalRoles) {
|
|
1939
|
+
const familyKey = options.key;
|
|
1940
|
+
const type = `writable_pure_selector_family`;
|
|
1941
|
+
const familyToken = {
|
|
1942
|
+
key: familyKey,
|
|
1943
|
+
type
|
|
1944
|
+
};
|
|
1945
|
+
const existing = store.families.get(familyKey);
|
|
1946
|
+
if (existing && store.config.isProduction === true)
|
|
1947
|
+
store.logger.error(`\u2757`, type, familyKey, `Overwriting an existing ${PRETTY_TOKEN_TYPES[existing.type]} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);
|
|
1948
|
+
const subject = new Subject;
|
|
1949
|
+
const create = (key) => {
|
|
1950
|
+
const subKey = stringifyJson(key);
|
|
1951
|
+
const family = {
|
|
1952
|
+
key: familyKey,
|
|
1953
|
+
subKey
|
|
1954
|
+
};
|
|
1955
|
+
const fullKey = `${familyKey}(${subKey})`;
|
|
1956
|
+
const target = newest(store);
|
|
1957
|
+
const individualOptions = {
|
|
1958
|
+
key: fullKey,
|
|
1959
|
+
get: options.get(key),
|
|
1960
|
+
set: options.set(key)
|
|
1961
|
+
};
|
|
1962
|
+
if (options.catch)
|
|
1963
|
+
individualOptions.catch = options.catch;
|
|
1964
|
+
return createWritablePureSelector(target, individualOptions, family);
|
|
1965
|
+
};
|
|
1966
|
+
const selectorFamily$1 = {
|
|
1967
|
+
...familyToken,
|
|
1968
|
+
create,
|
|
1969
|
+
internalRoles,
|
|
1970
|
+
subject,
|
|
1971
|
+
install: (s) => createWritablePureSelectorFamily(s, options),
|
|
1972
|
+
default: (key) => {
|
|
1973
|
+
return options.get(key)({
|
|
1974
|
+
get: (...args) => getFromStore(store, ...args),
|
|
1975
|
+
find: (...args) => findInStore(store, ...args),
|
|
1976
|
+
json: (token) => getJsonToken(store, token)
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
store.families.set(familyKey, selectorFamily$1);
|
|
1981
|
+
return familyToken;
|
|
1982
|
+
}
|
|
1983
|
+
function createSelectorFamily(store, options) {
|
|
1984
|
+
const isWritable = `set` in options;
|
|
1985
|
+
const isHeld = `const` in options;
|
|
1986
|
+
if (isHeld && isWritable)
|
|
1987
|
+
return createWritableHeldSelectorFamily(store, options, undefined);
|
|
1988
|
+
if (isHeld)
|
|
1989
|
+
return createReadonlyHeldSelectorFamily(store, options, undefined);
|
|
1990
|
+
if (isWritable)
|
|
1991
|
+
return createWritablePureSelectorFamily(store, options);
|
|
1992
|
+
return createReadonlyPureSelectorFamily(store, options);
|
|
1993
|
+
}
|
|
1994
|
+
function disposeFromStore(store, ...params) {
|
|
1995
|
+
let token;
|
|
1996
|
+
if (params.length === 1)
|
|
1997
|
+
token = params[0];
|
|
1998
|
+
else {
|
|
1999
|
+
const family = params[0];
|
|
2000
|
+
const key = params[1];
|
|
2001
|
+
token = findInStore(store, family, key);
|
|
2002
|
+
}
|
|
2003
|
+
try {
|
|
2004
|
+
withdraw(store, token);
|
|
2005
|
+
} catch (_) {
|
|
2006
|
+
store.logger.error(`\u274C`, token.type, token.key, `could not be disposed because it was not found in the store "${store.config.name}".`);
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
switch (token.type) {
|
|
2010
|
+
case `atom`:
|
|
2011
|
+
case `mutable_atom`:
|
|
2012
|
+
disposeAtom(store, token);
|
|
2013
|
+
break;
|
|
2014
|
+
case `writable_pure_selector`:
|
|
2015
|
+
case `readonly_pure_selector`:
|
|
2016
|
+
case `writable_held_selector`:
|
|
2017
|
+
case `readonly_held_selector`:
|
|
2018
|
+
disposeSelector(store, token);
|
|
2019
|
+
break;
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
function openOperation(store, token) {
|
|
2023
|
+
if (store.operation.open) {
|
|
2024
|
+
const rejectionTime = performance.now();
|
|
2025
|
+
store.logger.info(`\uD83D\uDEAB`, token.type, token.key, `deferring setState at T-${rejectionTime} until setState for "${store.operation.token.key}" is done`);
|
|
2026
|
+
return rejectionTime;
|
|
2027
|
+
}
|
|
2028
|
+
store.operation = {
|
|
2029
|
+
open: true,
|
|
2030
|
+
done: /* @__PURE__ */ new Set,
|
|
2031
|
+
prev: /* @__PURE__ */ new Map,
|
|
2032
|
+
timestamp: Date.now(),
|
|
2033
|
+
token,
|
|
2034
|
+
subEvents: []
|
|
2035
|
+
};
|
|
2036
|
+
store.logger.info(`\u2B55`, token.type, token.key, `operation start in store "${store.config.name}"${isChildStore(store) ? ` ${store.transactionMeta.phase} "${store.transactionMeta.update.token.key}"` : ``}`);
|
|
2037
|
+
return store;
|
|
2038
|
+
}
|
|
2039
|
+
function closeOperation(store) {
|
|
2040
|
+
if (store.operation.open)
|
|
2041
|
+
store.logger.info(`\uD83D\uDD34`, store.operation.token.type, store.operation.token.key, `operation done in store "${store.config.name}"`);
|
|
2042
|
+
store.operation = { open: false };
|
|
2043
|
+
store.on.operationClose.next(store.operation);
|
|
2044
|
+
}
|
|
2045
|
+
var isDone = (store, key) => {
|
|
2046
|
+
if (!store.operation.open) {
|
|
2047
|
+
store.logger.error(`\uD83D\uDC1E`, `unknown`, key, `isDone called outside of an operation. This is probably a bug in AtomIO.`);
|
|
2048
|
+
return true;
|
|
2049
|
+
}
|
|
2050
|
+
return store.operation.done.has(key);
|
|
2051
|
+
};
|
|
2052
|
+
var markDone = (store, key) => {
|
|
2053
|
+
if (!store.operation.open) {
|
|
2054
|
+
store.logger.error(`\uD83D\uDC1E`, `unknown`, key, `markDone called outside of an operation. This is probably a bug in AtomIO.`);
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
store.operation.done.add(key);
|
|
2058
|
+
};
|
|
2059
|
+
function dispatchOrDeferStateUpdate(target, state, { oldValue, newValue }, stateIsNewlyCreated, family) {
|
|
2060
|
+
const token = deposit(state);
|
|
2061
|
+
if (stateIsNewlyCreated && family) {
|
|
2062
|
+
state.subject.next({ newValue });
|
|
2063
|
+
const stateCreationEvent = {
|
|
2064
|
+
checkpoint: true,
|
|
2065
|
+
type: `state_creation`,
|
|
2066
|
+
subType: `writable`,
|
|
2067
|
+
token,
|
|
2068
|
+
timestamp: Date.now(),
|
|
2069
|
+
value: newValue
|
|
2070
|
+
};
|
|
2071
|
+
target.operation.subEvents.push(stateCreationEvent);
|
|
2072
|
+
family.subject.next(stateCreationEvent);
|
|
2073
|
+
const innerTarget = newest(target);
|
|
2074
|
+
if (token.family) {
|
|
2075
|
+
if (isRootStore(innerTarget))
|
|
2076
|
+
switch (token.type) {
|
|
2077
|
+
case `atom`:
|
|
2078
|
+
case `mutable_atom`:
|
|
2079
|
+
target.on.atomCreation.next(token);
|
|
2080
|
+
break;
|
|
2081
|
+
case `writable_pure_selector`:
|
|
2082
|
+
case `writable_held_selector`:
|
|
2083
|
+
target.on.selectorCreation.next(token);
|
|
2084
|
+
break;
|
|
2085
|
+
}
|
|
2086
|
+
else if (isChildStore(innerTarget) && innerTarget.on.transactionApplying.state === null)
|
|
2087
|
+
innerTarget.transactionMeta.update.subEvents.push(stateCreationEvent);
|
|
2088
|
+
}
|
|
2089
|
+
return;
|
|
2090
|
+
}
|
|
2091
|
+
const { key, subject, type } = state;
|
|
2092
|
+
const update = {
|
|
2093
|
+
oldValue: isTransceiver(oldValue) ? oldValue.READONLY_VIEW : oldValue,
|
|
2094
|
+
newValue: isTransceiver(newValue) ? newValue.READONLY_VIEW : newValue
|
|
2095
|
+
};
|
|
2096
|
+
if (isRootStore(target)) {
|
|
2097
|
+
switch (type) {
|
|
2098
|
+
case `mutable_atom`:
|
|
2099
|
+
target.logger.info(`\uD83D\uDCE2`, type, key, `is now (`, newValue, `) subscribers:`, subject.subscribers.keys());
|
|
2100
|
+
break;
|
|
2101
|
+
case `atom`:
|
|
2102
|
+
case `writable_pure_selector`:
|
|
2103
|
+
case `writable_held_selector`:
|
|
2104
|
+
target.logger.info(`\uD83D\uDCE2`, type, key, `went (`, oldValue, `->`, newValue, `) subscribers:`, subject.subscribers.keys());
|
|
2105
|
+
}
|
|
2106
|
+
subject.next(update);
|
|
2107
|
+
}
|
|
2108
|
+
if (isChildStore(target) && (type === `mutable_atom` || type === `atom`)) {
|
|
2109
|
+
if (target.on.transactionApplying.state === null) {
|
|
2110
|
+
if (isTransceiver(newValue))
|
|
2111
|
+
return;
|
|
2112
|
+
const { timestamp } = target.operation;
|
|
2113
|
+
const atomUpdate = {
|
|
2114
|
+
type: `atom_update`,
|
|
2115
|
+
token,
|
|
2116
|
+
timestamp,
|
|
2117
|
+
update
|
|
2118
|
+
};
|
|
2119
|
+
target.transactionMeta.update.subEvents.push(atomUpdate);
|
|
2120
|
+
target.logger.info(`\uD83D\uDCC1`, `atom`, key, `stowed (`, oldValue, `->`, newValue, `)`);
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
2123
|
+
if (hasRole(state, `tracker:signal`)) {
|
|
2124
|
+
const keyOfMutable = key.slice(1);
|
|
2125
|
+
const mutable = target.atoms.get(keyOfMutable);
|
|
2126
|
+
if (readOrComputeValue(target, mutable, `mut`).do(update.newValue) === null === true)
|
|
2127
|
+
evictDownstreamFromAtom(target, mutable);
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
var setAtom = (target, atom, next) => {
|
|
2132
|
+
const oldValue = readOrComputeValue(target, atom, `mut`);
|
|
2133
|
+
let newValue = become(next, oldValue);
|
|
2134
|
+
target.logger.info(`\u2B50`, `atom`, atom.key, `setting value`, newValue);
|
|
2135
|
+
newValue = writeToCache(target, atom, newValue);
|
|
2136
|
+
markDone(target, atom.key);
|
|
2137
|
+
evictDownstreamFromAtom(target, atom);
|
|
2138
|
+
return {
|
|
2139
|
+
oldValue,
|
|
2140
|
+
newValue
|
|
2141
|
+
};
|
|
2142
|
+
};
|
|
2143
|
+
function resetAtom(target, atom) {
|
|
2144
|
+
switch (atom.type) {
|
|
2145
|
+
case `mutable_atom`:
|
|
2146
|
+
return setAtom(target, atom, new atom.class);
|
|
2147
|
+
case `atom`: {
|
|
2148
|
+
let def;
|
|
2149
|
+
if (isFn(atom.default))
|
|
2150
|
+
def = safeCompute(target, atom);
|
|
2151
|
+
else
|
|
2152
|
+
def = atom.default;
|
|
2153
|
+
return setAtom(target, atom, def);
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
function resetAtomOrSelector(target, state) {
|
|
2158
|
+
let protoUpdate;
|
|
2159
|
+
switch (state.type) {
|
|
2160
|
+
case `atom`:
|
|
2161
|
+
case `mutable_atom`:
|
|
2162
|
+
protoUpdate = resetAtom(target, state);
|
|
2163
|
+
break;
|
|
2164
|
+
case `writable_held_selector`:
|
|
2165
|
+
{
|
|
2166
|
+
const atoms = traceRootSelectorAtoms(target, state.key);
|
|
2167
|
+
for (const atom of atoms.values())
|
|
2168
|
+
dispatchOrDeferStateUpdate(target, state, resetAtom(target, atom), false);
|
|
2169
|
+
const value = state.getFrom(target);
|
|
2170
|
+
protoUpdate = {
|
|
2171
|
+
oldValue: value,
|
|
2172
|
+
newValue: value
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
break;
|
|
2176
|
+
case `writable_pure_selector`:
|
|
2177
|
+
{
|
|
2178
|
+
const oldValue = safeCompute(target, state);
|
|
2179
|
+
const atoms = traceRootSelectorAtoms(target, state.key);
|
|
2180
|
+
for (const atom of atoms.values())
|
|
2181
|
+
dispatchOrDeferStateUpdate(target, state, resetAtom(target, atom), false);
|
|
2182
|
+
protoUpdate = {
|
|
2183
|
+
oldValue,
|
|
2184
|
+
newValue: safeCompute(target, state)
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
break;
|
|
2188
|
+
}
|
|
2189
|
+
return protoUpdate;
|
|
2190
|
+
}
|
|
2191
|
+
function setIntoStore(store, ...params) {
|
|
2192
|
+
operateOnStore(OWN_OP, store, ...params);
|
|
2193
|
+
}
|
|
2194
|
+
var RESET_STATE = Symbol(`RESET`);
|
|
2195
|
+
function resetInStore(store, ...params) {
|
|
2196
|
+
setIntoStore(store, ...[...params, RESET_STATE]);
|
|
2197
|
+
}
|
|
2198
|
+
function setSelector(target, selector, next) {
|
|
2199
|
+
let oldValue;
|
|
2200
|
+
let newValue;
|
|
2201
|
+
let constant;
|
|
2202
|
+
const { type, key } = selector;
|
|
2203
|
+
switch (selector.type) {
|
|
2204
|
+
case `writable_pure_selector`:
|
|
2205
|
+
oldValue = readOrComputeValue(target, selector, `mut`);
|
|
2206
|
+
newValue = become(next, oldValue);
|
|
2207
|
+
newValue = writeToCache(target, selector, newValue);
|
|
2208
|
+
break;
|
|
2209
|
+
case `writable_held_selector`:
|
|
2210
|
+
constant = selector.const;
|
|
2211
|
+
become(next, constant);
|
|
2212
|
+
oldValue = constant;
|
|
2213
|
+
newValue = constant;
|
|
2214
|
+
}
|
|
2215
|
+
target.logger.info(`\u2B50`, type, key, `setting to`, newValue);
|
|
2216
|
+
markDone(target, key);
|
|
2217
|
+
selector.setSelf(newValue);
|
|
2218
|
+
return {
|
|
2219
|
+
oldValue,
|
|
2220
|
+
newValue
|
|
2221
|
+
};
|
|
2222
|
+
}
|
|
2223
|
+
var setAtomOrSelector = (target, state, value) => {
|
|
2224
|
+
let protoUpdate;
|
|
2225
|
+
switch (state.type) {
|
|
2226
|
+
case `atom`:
|
|
2227
|
+
case `mutable_atom`:
|
|
2228
|
+
protoUpdate = setAtom(target, state, value);
|
|
2229
|
+
break;
|
|
2230
|
+
case `writable_pure_selector`:
|
|
2231
|
+
case `writable_held_selector`:
|
|
2232
|
+
protoUpdate = setSelector(target, state, value);
|
|
2233
|
+
break;
|
|
2234
|
+
}
|
|
2235
|
+
return protoUpdate;
|
|
2236
|
+
};
|
|
2237
|
+
var OWN_OP = Symbol(`OWN_OP`);
|
|
2238
|
+
var JOIN_OP = Symbol(`JOIN_OP`);
|
|
2239
|
+
function operateOnStore(opMode, store, ...params) {
|
|
2240
|
+
let existingToken;
|
|
2241
|
+
let brandNewToken;
|
|
2242
|
+
let token;
|
|
2243
|
+
let family;
|
|
2244
|
+
let key;
|
|
2245
|
+
let value;
|
|
2246
|
+
if (params.length === 2) {
|
|
2247
|
+
token = params[0];
|
|
2248
|
+
value = params[1];
|
|
2249
|
+
if (`family` in token) {
|
|
2250
|
+
family = getFamilyOfToken(store, token);
|
|
2251
|
+
key = parseJson(token.family.subKey);
|
|
2252
|
+
existingToken = seekInStore(store, family, key);
|
|
2253
|
+
if (!existingToken)
|
|
2254
|
+
token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
|
|
2255
|
+
else
|
|
2256
|
+
token = existingToken;
|
|
2257
|
+
}
|
|
2258
|
+
} else {
|
|
2259
|
+
family = withdraw(store, params[0]);
|
|
2260
|
+
key = params[1];
|
|
2261
|
+
value = params[2];
|
|
2262
|
+
existingToken = seekInStore(store, family, key);
|
|
2263
|
+
if (!existingToken)
|
|
2264
|
+
token = brandNewToken = mintInStore(MUST_CREATE, store, family, key);
|
|
2265
|
+
else
|
|
2266
|
+
token = existingToken;
|
|
2267
|
+
}
|
|
2268
|
+
const action = value === RESET_STATE ? `reset` : `set`;
|
|
2269
|
+
let target;
|
|
2270
|
+
if (opMode === OWN_OP) {
|
|
2271
|
+
const result = openOperation(store, token);
|
|
2272
|
+
if (typeof result === `number`) {
|
|
2273
|
+
const rejectionTime = result;
|
|
2274
|
+
const unsubscribe = store.on.operationClose.subscribe(`waiting to ${action} "${token.key}" at T-${rejectionTime}`, function waitUntilOperationCloseToSetState() {
|
|
2275
|
+
unsubscribe();
|
|
2276
|
+
store.logger.info(`\uD83D\uDFE2`, token.type, token.key, `resuming deferred`, action, `from T-${rejectionTime}`);
|
|
2277
|
+
operateOnStore(opMode, store, token, value);
|
|
2278
|
+
});
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
target = result;
|
|
2282
|
+
} else
|
|
2283
|
+
target = store;
|
|
2284
|
+
if (`counterfeit` in token && `family` in token) {
|
|
2285
|
+
const subKey = token.family.subKey;
|
|
2286
|
+
const disposal = store.disposalTraces.buffer.find((item) => item?.key === subKey);
|
|
2287
|
+
store.logger.error(`\u274C`, token.type, token.key, `could not be`, action, `because key`, subKey, `is not allocated.`, disposal ? `this key was previously disposed:${disposal.trace}` : `(no previous disposal trace found)`);
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2290
|
+
const state = withdraw(target, token);
|
|
2291
|
+
let protoUpdate;
|
|
2292
|
+
if (value === RESET_STATE)
|
|
2293
|
+
protoUpdate = resetAtomOrSelector(target, state);
|
|
2294
|
+
else
|
|
2295
|
+
protoUpdate = setAtomOrSelector(target, state, value);
|
|
2296
|
+
dispatchOrDeferStateUpdate(target, state, protoUpdate, Boolean(brandNewToken), family);
|
|
2297
|
+
if (opMode === OWN_OP)
|
|
2298
|
+
closeOperation(target);
|
|
2299
|
+
}
|
|
2300
|
+
var isAtomKey = (store, key) => newest(store).atoms.has(key);
|
|
2301
|
+
var isSelectorKey = (store, key) => newest(store).writableSelectors.has(key);
|
|
2302
|
+
var isReadonlySelectorKey = (store, key) => newest(store).readonlySelectors.has(key);
|
|
2303
|
+
var isStateKey = (store, key) => isAtomKey(store, key) || isSelectorKey(store, key) || isReadonlySelectorKey(store, key);
|
|
2304
|
+
function getSelectorDependencyKeys(store, key) {
|
|
2305
|
+
return newest(store).selectorGraph.getRelationEntries({ downstreamSelectorKey: key }).filter(([_, { source }]) => source !== key).map(([_, { source }]) => source).filter((source) => isStateKey(store, source));
|
|
2306
|
+
}
|
|
2307
|
+
function traceRootSelectorAtoms(store, selectorKey, covered = /* @__PURE__ */ new Set) {
|
|
2308
|
+
const dependencies = getSelectorDependencyKeys(store, selectorKey);
|
|
2309
|
+
const roots = /* @__PURE__ */ new Map;
|
|
2310
|
+
while (dependencies.length > 0) {
|
|
2311
|
+
const dependencyKey = dependencies.pop();
|
|
2312
|
+
if (covered.has(dependencyKey))
|
|
2313
|
+
continue;
|
|
2314
|
+
covered.add(dependencyKey);
|
|
2315
|
+
if (isAtomKey(store, dependencyKey)) {
|
|
2316
|
+
const atom = store.atoms.get(dependencyKey);
|
|
2317
|
+
roots.set(atom.key, atom);
|
|
2318
|
+
} else
|
|
2319
|
+
dependencies.push(...getSelectorDependencyKeys(store, dependencyKey));
|
|
2320
|
+
}
|
|
2321
|
+
return roots;
|
|
2322
|
+
}
|
|
2323
|
+
function updateSelectorAtoms(store, selectorType, selectorKey, dependency, covered) {
|
|
2324
|
+
const target = newest(store);
|
|
2325
|
+
const { type: dependencyType, key: dependencyKey } = dependency;
|
|
2326
|
+
if (dependencyType === `atom` || dependencyType === `mutable_atom`) {
|
|
2327
|
+
target.selectorAtoms.set({
|
|
2328
|
+
selectorKey,
|
|
2329
|
+
atomKey: dependencyKey
|
|
2330
|
+
});
|
|
2331
|
+
store.logger.info(`\uD83D\uDD0D`, selectorType, selectorKey, `discovers root atom "${dependencyKey}"`);
|
|
2332
|
+
} else {
|
|
2333
|
+
const rootKeys = traceRootSelectorAtoms(store, dependencyKey, covered);
|
|
2334
|
+
store.logger.info(`\uD83D\uDD0D`, selectorType, selectorKey, `discovers root atoms: [ ${[...rootKeys.values()].map((root) => `"${root.key}"`).join(`, `)} ]`);
|
|
2335
|
+
for (const { key: atomKey } of rootKeys.values())
|
|
2336
|
+
target.selectorAtoms = target.selectorAtoms.set({
|
|
2337
|
+
selectorKey,
|
|
2338
|
+
atomKey
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
covered.add(dependencyKey);
|
|
2342
|
+
}
|
|
2343
|
+
function registerSelector(store, selectorType, selectorKey, covered) {
|
|
2344
|
+
return {
|
|
2345
|
+
get: (...params) => {
|
|
2346
|
+
const target = newest(store);
|
|
2347
|
+
const { token, family, subKey } = reduceReference(store, ...params);
|
|
2348
|
+
let dependencyValue;
|
|
2349
|
+
if (`counterfeit` in token && family && subKey)
|
|
2350
|
+
dependencyValue = getFallback(store, token, family, subKey);
|
|
2351
|
+
else
|
|
2352
|
+
dependencyValue = readOrComputeValue(store, withdraw(store, token));
|
|
2353
|
+
store.logger.info(`\uD83D\uDD0C`, selectorType, selectorKey, `registers dependency ( "${token.key}" =`, dependencyValue, `)`);
|
|
2354
|
+
target.selectorGraph.set({
|
|
2355
|
+
upstreamSelectorKey: token.key,
|
|
2356
|
+
downstreamSelectorKey: selectorKey
|
|
2357
|
+
}, { source: token.key });
|
|
2358
|
+
updateSelectorAtoms(store, selectorType, selectorKey, token, covered);
|
|
2359
|
+
return dependencyValue;
|
|
2360
|
+
},
|
|
2361
|
+
set: (...params) => {
|
|
2362
|
+
operateOnStore(JOIN_OP, newest(store), ...params);
|
|
2363
|
+
},
|
|
2364
|
+
find: (...args) => findInStore(store, ...args),
|
|
2365
|
+
json: (token) => getJsonToken(store, token)
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
function createReadonlyHeldSelector(store, options, family) {
|
|
2369
|
+
const target = newest(store);
|
|
2370
|
+
const subject = new Subject;
|
|
2371
|
+
const covered = /* @__PURE__ */ new Set;
|
|
2372
|
+
const { key, const: constant } = options;
|
|
2373
|
+
const type = `readonly_held_selector`;
|
|
2374
|
+
store.logger.info(`\uD83D\uDD28`, type, key, `is being created`);
|
|
2375
|
+
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
2376
|
+
const getFrom = (innerTarget) => {
|
|
2377
|
+
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
2378
|
+
for (const [downstreamSelectorKey, { source }] of upstreamStates)
|
|
2379
|
+
if (source !== key)
|
|
2380
|
+
innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
2381
|
+
innerTarget.selectorAtoms.delete(key);
|
|
2382
|
+
options.get({
|
|
2383
|
+
get,
|
|
2384
|
+
find,
|
|
2385
|
+
json
|
|
2386
|
+
}, constant);
|
|
2387
|
+
writeToCache(innerTarget, readonlySelector, constant);
|
|
2388
|
+
store.logger.info(`\u2728`, type, key, `=`, constant);
|
|
2389
|
+
covered.clear();
|
|
2390
|
+
return constant;
|
|
2391
|
+
};
|
|
2392
|
+
const readonlySelector = {
|
|
2393
|
+
...options,
|
|
2394
|
+
type,
|
|
2395
|
+
subject,
|
|
2396
|
+
getFrom,
|
|
2397
|
+
install: (s) => createReadonlyHeldSelector(s, options, family)
|
|
2398
|
+
};
|
|
2399
|
+
if (family)
|
|
2400
|
+
readonlySelector.family = family;
|
|
2401
|
+
target.readonlySelectors.set(key, readonlySelector);
|
|
2402
|
+
const token = {
|
|
2403
|
+
key,
|
|
2404
|
+
type
|
|
2405
|
+
};
|
|
2406
|
+
if (family)
|
|
2407
|
+
token.family = family;
|
|
2408
|
+
return token;
|
|
2409
|
+
}
|
|
2410
|
+
function createReadonlyPureSelector(store, options, family) {
|
|
2411
|
+
const target = newest(store);
|
|
2412
|
+
const subject = new Subject;
|
|
2413
|
+
const covered = /* @__PURE__ */ new Set;
|
|
2414
|
+
const key = options.key;
|
|
2415
|
+
const type = `readonly_pure_selector`;
|
|
2416
|
+
store.logger.info(`\uD83D\uDD28`, type, key, `is being created`);
|
|
2417
|
+
const { get, find, json } = registerSelector(target, type, key, covered);
|
|
2418
|
+
const getFrom = () => {
|
|
2419
|
+
const innerTarget = newest(store);
|
|
2420
|
+
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
2421
|
+
for (const [downstreamSelectorKey, { source }] of upstreamStates)
|
|
2422
|
+
if (source !== key)
|
|
2423
|
+
innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
2424
|
+
innerTarget.selectorAtoms.delete(key);
|
|
2425
|
+
const cached = writeToCache(innerTarget, readonlySelector, options.get({
|
|
2426
|
+
get,
|
|
2427
|
+
find,
|
|
2428
|
+
json
|
|
2429
|
+
}));
|
|
2430
|
+
store.logger.info(`\u2728`, type, key, `=`, cached);
|
|
2431
|
+
covered.clear();
|
|
2432
|
+
return cached;
|
|
2433
|
+
};
|
|
2434
|
+
const readonlySelector = {
|
|
2435
|
+
...options,
|
|
2436
|
+
type,
|
|
2437
|
+
subject,
|
|
2438
|
+
getFrom,
|
|
2439
|
+
install: (s) => createReadonlyPureSelector(s, options, family)
|
|
2440
|
+
};
|
|
2441
|
+
if (family)
|
|
2442
|
+
readonlySelector.family = family;
|
|
2443
|
+
target.readonlySelectors.set(key, readonlySelector);
|
|
2444
|
+
const token = {
|
|
2445
|
+
key,
|
|
2446
|
+
type
|
|
2447
|
+
};
|
|
2448
|
+
if (family)
|
|
2449
|
+
token.family = family;
|
|
2450
|
+
return token;
|
|
2451
|
+
}
|
|
2452
|
+
function createWritableHeldSelector(store, options, family) {
|
|
2453
|
+
const target = newest(store);
|
|
2454
|
+
const subject = new Subject;
|
|
2455
|
+
const covered = /* @__PURE__ */ new Set;
|
|
2456
|
+
const { key, const: constant } = options;
|
|
2457
|
+
const type = `writable_held_selector`;
|
|
2458
|
+
store.logger.info(`\uD83D\uDD28`, type, key, `is being created`);
|
|
2459
|
+
const setterToolkit = registerSelector(target, type, key, covered);
|
|
2460
|
+
const { find, get, json } = setterToolkit;
|
|
2461
|
+
const getterToolkit = {
|
|
2462
|
+
find,
|
|
2463
|
+
get,
|
|
2464
|
+
json
|
|
2465
|
+
};
|
|
2466
|
+
const getFrom = (innerTarget) => {
|
|
2467
|
+
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
2468
|
+
for (const [downstreamSelectorKey, { source }] of upstreamStates)
|
|
2469
|
+
if (source !== key)
|
|
2470
|
+
innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
2471
|
+
innerTarget.selectorAtoms.delete(key);
|
|
2472
|
+
options.get(getterToolkit, constant);
|
|
2473
|
+
writeToCache(innerTarget, mySelector, constant);
|
|
2474
|
+
store.logger.info(`\u2728`, type, key, `=`, constant);
|
|
2475
|
+
covered.clear();
|
|
2476
|
+
return constant;
|
|
2477
|
+
};
|
|
2478
|
+
const setSelf = () => {
|
|
2479
|
+
options.set(setterToolkit, constant);
|
|
2480
|
+
};
|
|
2481
|
+
const mySelector = {
|
|
2482
|
+
...options,
|
|
2483
|
+
type,
|
|
2484
|
+
subject,
|
|
2485
|
+
getFrom,
|
|
2486
|
+
setSelf,
|
|
2487
|
+
install: (s) => createWritableHeldSelector(s, options, family)
|
|
2488
|
+
};
|
|
2489
|
+
if (family)
|
|
2490
|
+
mySelector.family = family;
|
|
2491
|
+
target.writableSelectors.set(key, mySelector);
|
|
2492
|
+
const token = {
|
|
2493
|
+
key,
|
|
2494
|
+
type
|
|
2495
|
+
};
|
|
2496
|
+
if (family)
|
|
2497
|
+
token.family = family;
|
|
2498
|
+
return token;
|
|
2499
|
+
}
|
|
2500
|
+
function createWritablePureSelector(store, options, family) {
|
|
2501
|
+
const target = newest(store);
|
|
2502
|
+
const subject = new Subject;
|
|
2503
|
+
const covered = /* @__PURE__ */ new Set;
|
|
2504
|
+
const key = options.key;
|
|
2505
|
+
const type = `writable_pure_selector`;
|
|
2506
|
+
store.logger.info(`\uD83D\uDD28`, type, key, `is being created`);
|
|
2507
|
+
const setterToolkit = registerSelector(target, type, key, covered);
|
|
2508
|
+
const { find, get, json } = setterToolkit;
|
|
2509
|
+
const getterToolkit = {
|
|
2510
|
+
find,
|
|
2511
|
+
get,
|
|
2512
|
+
json
|
|
2513
|
+
};
|
|
2514
|
+
const getFrom = (innerTarget) => {
|
|
2515
|
+
const upstreamStates = innerTarget.selectorGraph.getRelationEntries({ downstreamSelectorKey: key });
|
|
2516
|
+
for (const [downstreamSelectorKey, { source }] of upstreamStates)
|
|
2517
|
+
if (source !== key)
|
|
2518
|
+
innerTarget.selectorGraph.delete(downstreamSelectorKey, key);
|
|
2519
|
+
innerTarget.selectorAtoms.delete(key);
|
|
2520
|
+
const cached = writeToCache(innerTarget, mySelector, options.get(getterToolkit));
|
|
2521
|
+
store.logger.info(`\u2728`, type, key, `=`, cached);
|
|
2522
|
+
covered.clear();
|
|
2523
|
+
return cached;
|
|
2524
|
+
};
|
|
2525
|
+
const setSelf = (newValue) => {
|
|
2526
|
+
options.set(setterToolkit, newValue);
|
|
2527
|
+
};
|
|
2528
|
+
const mySelector = {
|
|
2529
|
+
...options,
|
|
2530
|
+
type,
|
|
2531
|
+
subject,
|
|
2532
|
+
getFrom,
|
|
2533
|
+
setSelf,
|
|
2534
|
+
install: (s) => createWritablePureSelector(s, options, family)
|
|
2535
|
+
};
|
|
2536
|
+
if (family)
|
|
2537
|
+
mySelector.family = family;
|
|
2538
|
+
target.writableSelectors.set(key, mySelector);
|
|
2539
|
+
const token = {
|
|
2540
|
+
key,
|
|
2541
|
+
type
|
|
2542
|
+
};
|
|
2543
|
+
if (family)
|
|
2544
|
+
token.family = family;
|
|
2545
|
+
return token;
|
|
2546
|
+
}
|
|
2547
|
+
function createStandaloneSelector(store, options) {
|
|
2548
|
+
const isWritable = `set` in options;
|
|
2549
|
+
const isHeld = `const` in options;
|
|
2550
|
+
if (isHeld && isWritable) {
|
|
2551
|
+
const state$1 = createWritableHeldSelector(store, options, undefined);
|
|
2552
|
+
store.on.selectorCreation.next(state$1);
|
|
2553
|
+
return state$1;
|
|
2554
|
+
}
|
|
2555
|
+
if (isHeld) {
|
|
2556
|
+
const state$1 = createReadonlyHeldSelector(store, options, undefined);
|
|
2557
|
+
store.on.selectorCreation.next(state$1);
|
|
2558
|
+
return state$1;
|
|
2559
|
+
}
|
|
2560
|
+
if (isWritable) {
|
|
2561
|
+
const state$1 = createWritablePureSelector(store, options, undefined);
|
|
2562
|
+
store.on.selectorCreation.next(state$1);
|
|
2563
|
+
return state$1;
|
|
2564
|
+
}
|
|
2565
|
+
const state = createReadonlyPureSelector(store, options, undefined);
|
|
2566
|
+
store.on.selectorCreation.next(state);
|
|
2567
|
+
return state;
|
|
2568
|
+
}
|
|
2569
|
+
function disposeSelector(store, selectorToken) {
|
|
2570
|
+
const target = newest(store);
|
|
2571
|
+
const { key, type, family: familyMeta } = selectorToken;
|
|
2572
|
+
if (!familyMeta)
|
|
2573
|
+
store.logger.error(`\u274C`, type, key, `Standalone selectors cannot be disposed.`);
|
|
2574
|
+
else {
|
|
2575
|
+
if (target.molecules.get(familyMeta.subKey))
|
|
2576
|
+
target.moleculeData.delete(familyMeta.subKey, familyMeta.key);
|
|
2577
|
+
let familyToken;
|
|
2578
|
+
switch (selectorToken.type) {
|
|
2579
|
+
case `writable_held_selector`:
|
|
2580
|
+
target.writableSelectors.delete(key);
|
|
2581
|
+
familyToken = {
|
|
2582
|
+
key: familyMeta.key,
|
|
2583
|
+
type: `writable_held_selector_family`
|
|
2584
|
+
};
|
|
2585
|
+
withdraw(store, familyToken).subject.next({
|
|
2586
|
+
type: `state_disposal`,
|
|
2587
|
+
subType: `selector`,
|
|
2588
|
+
token: selectorToken,
|
|
2589
|
+
timestamp: Date.now()
|
|
2590
|
+
});
|
|
2591
|
+
break;
|
|
2592
|
+
case `writable_pure_selector`:
|
|
2593
|
+
target.writableSelectors.delete(key);
|
|
2594
|
+
familyToken = {
|
|
2595
|
+
key: familyMeta.key,
|
|
2596
|
+
type: `writable_pure_selector_family`
|
|
2597
|
+
};
|
|
2598
|
+
withdraw(store, familyToken).subject.next({
|
|
2599
|
+
type: `state_disposal`,
|
|
2600
|
+
subType: `selector`,
|
|
2601
|
+
token: selectorToken,
|
|
2602
|
+
timestamp: Date.now()
|
|
2603
|
+
});
|
|
2604
|
+
break;
|
|
2605
|
+
case `readonly_held_selector`:
|
|
2606
|
+
target.readonlySelectors.delete(key);
|
|
2607
|
+
familyToken = {
|
|
2608
|
+
key: familyMeta.key,
|
|
2609
|
+
type: `readonly_held_selector_family`
|
|
2610
|
+
};
|
|
2611
|
+
withdraw(store, familyToken).subject.next({
|
|
2612
|
+
type: `state_disposal`,
|
|
2613
|
+
subType: `selector`,
|
|
2614
|
+
token: selectorToken,
|
|
2615
|
+
timestamp: Date.now()
|
|
2616
|
+
});
|
|
2617
|
+
break;
|
|
2618
|
+
case `readonly_pure_selector`:
|
|
2619
|
+
target.readonlySelectors.delete(key);
|
|
2620
|
+
familyToken = {
|
|
2621
|
+
key: familyMeta.key,
|
|
2622
|
+
type: `readonly_pure_selector_family`
|
|
2623
|
+
};
|
|
2624
|
+
withdraw(store, familyToken).subject.next({
|
|
2625
|
+
type: `state_disposal`,
|
|
2626
|
+
subType: `selector`,
|
|
2627
|
+
token: selectorToken,
|
|
2628
|
+
timestamp: Date.now()
|
|
2629
|
+
});
|
|
2630
|
+
break;
|
|
2631
|
+
}
|
|
2632
|
+
target.valueMap.delete(key);
|
|
2633
|
+
target.selectorAtoms.delete(key);
|
|
2634
|
+
target.selectorGraph.delete(key);
|
|
2635
|
+
target.moleculeData.delete(familyMeta.key, familyMeta.subKey);
|
|
2636
|
+
store.logger.info(`\uD83D\uDD25`, selectorToken.type, key, `deleted`);
|
|
2637
|
+
if (isChildStore(target) && target.transactionMeta.phase === `building`)
|
|
2638
|
+
target.transactionMeta.update.subEvents.push({
|
|
2639
|
+
type: `state_disposal`,
|
|
2640
|
+
subType: `selector`,
|
|
2641
|
+
token: selectorToken,
|
|
2642
|
+
timestamp: Date.now()
|
|
2643
|
+
});
|
|
2644
|
+
else
|
|
2645
|
+
store.on.selectorDisposal.next(selectorToken);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
var recallState = (store, state) => {
|
|
2649
|
+
const target = newest(store);
|
|
2650
|
+
if (target.operation.open)
|
|
2651
|
+
return target.operation.prev.get(state.key);
|
|
2652
|
+
return target.valueMap.get(state.key);
|
|
2653
|
+
};
|
|
2654
|
+
var subscribeToRootDependency = (target, selector, atom) => {
|
|
2655
|
+
return atom.subject.subscribe(`${selector.type}:${selector.key}`, (atomChange) => {
|
|
2656
|
+
target.logger.info(`\uD83D\uDCE2`, selector.type, selector.key, `root`, atom.key, `went`, atomChange.oldValue, `->`, atomChange.newValue);
|
|
2657
|
+
const oldValue = recallState(target, selector);
|
|
2658
|
+
const newValue = readOrComputeValue(target, selector);
|
|
2659
|
+
target.logger.info(`\u2728`, selector.type, selector.key, `went`, oldValue, `->`, newValue);
|
|
2660
|
+
selector.subject.next({
|
|
2661
|
+
newValue,
|
|
2662
|
+
oldValue
|
|
2663
|
+
});
|
|
2664
|
+
});
|
|
2665
|
+
};
|
|
2666
|
+
function subscribeToState(store, token, key, handleUpdate) {
|
|
2667
|
+
function safelyHandleUpdate(update) {
|
|
2668
|
+
if (store.operation.open) {
|
|
2669
|
+
if (state?.type === `atom` && hasRole(state, `tracker:signal`) && `*` + store.operation.token.key === token.key && `inboundTracker` in handleUpdate)
|
|
2670
|
+
return;
|
|
2671
|
+
const unsubscribe$1 = store.on.operationClose.subscribe(`state subscription ${key}`, () => {
|
|
2672
|
+
unsubscribe$1();
|
|
2673
|
+
handleUpdate(update);
|
|
2674
|
+
});
|
|
2675
|
+
} else
|
|
2676
|
+
handleUpdate(update);
|
|
2677
|
+
}
|
|
2678
|
+
reduceReference(store, token);
|
|
2679
|
+
const state = withdraw(store, token);
|
|
2680
|
+
store.logger.info(`\uD83D\uDC40`, state.type, state.key, `Adding subscription "${key}"`);
|
|
2681
|
+
const isSelector = state.type === `writable_pure_selector` || state.type === `readonly_pure_selector`;
|
|
2682
|
+
const rootSubs = /* @__PURE__ */ new Map;
|
|
2683
|
+
let updateHandler = safelyHandleUpdate;
|
|
2684
|
+
if (isSelector) {
|
|
2685
|
+
readOrComputeValue(store, state);
|
|
2686
|
+
for (const [atomKey, atom] of traceRootSelectorAtoms(store, state.key))
|
|
2687
|
+
rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
|
|
2688
|
+
updateHandler = function updateRootsBeforeHandlingUpdate(update) {
|
|
2689
|
+
const dependencies = traceRootSelectorAtoms(store, state.key);
|
|
2690
|
+
for (const [previousRootKey, unsub] of rootSubs)
|
|
2691
|
+
if (dependencies.get(previousRootKey))
|
|
2692
|
+
dependencies.delete(previousRootKey);
|
|
2693
|
+
else {
|
|
2694
|
+
unsub();
|
|
2695
|
+
rootSubs.delete(previousRootKey);
|
|
2696
|
+
}
|
|
2697
|
+
for (const [atomKey, atom] of dependencies)
|
|
2698
|
+
rootSubs.set(atomKey, subscribeToRootDependency(store, state, atom));
|
|
2699
|
+
safelyHandleUpdate(update);
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
const mainUnsubFunction = state.subject.subscribe(key, updateHandler);
|
|
2703
|
+
const unsubscribe = () => {
|
|
2704
|
+
store.logger.info(`\uD83D\uDE48`, state.type, state.key, `Removing subscription "${key}"`);
|
|
2705
|
+
mainUnsubFunction();
|
|
2706
|
+
for (const unsubFromDependency of rootSubs.values())
|
|
2707
|
+
unsubFromDependency();
|
|
2708
|
+
};
|
|
2709
|
+
return unsubscribe;
|
|
2710
|
+
}
|
|
2711
|
+
var subscribeToTimeline = (store, token, key, handleUpdate) => {
|
|
2712
|
+
const tl = withdraw(store, token);
|
|
2713
|
+
store.logger.info(`\uD83D\uDC40`, `timeline`, token.key, `Adding subscription "${key}"`);
|
|
2714
|
+
const unsubscribe = tl.subject.subscribe(key, handleUpdate);
|
|
2715
|
+
return () => {
|
|
2716
|
+
store.logger.info(`\uD83D\uDE48`, `timeline`, token.key, `Removing subscription "${key}" from timeline`);
|
|
2717
|
+
unsubscribe();
|
|
2718
|
+
};
|
|
2719
|
+
};
|
|
2720
|
+
var Tracker = class {
|
|
2721
|
+
initializeSignalAtom(mutableState, store) {
|
|
2722
|
+
const latestSignalStateKey = `*${mutableState.key}`;
|
|
2723
|
+
store.atoms.delete(latestSignalStateKey);
|
|
2724
|
+
store.valueMap.delete(latestSignalStateKey);
|
|
2725
|
+
const familyMetaData = mutableState.family ? {
|
|
2726
|
+
key: `*${mutableState.family.key}`,
|
|
2727
|
+
subKey: mutableState.family.subKey
|
|
2728
|
+
} : undefined;
|
|
2729
|
+
const latestSignalState = createRegularAtom(store, {
|
|
2730
|
+
key: latestSignalStateKey,
|
|
2731
|
+
default: null
|
|
2732
|
+
}, familyMetaData, [`tracker:signal`]);
|
|
2733
|
+
if (store.parent?.valueMap.has(latestSignalStateKey)) {
|
|
2734
|
+
const parentValue = store.parent.valueMap.get(latestSignalStateKey);
|
|
2735
|
+
store.valueMap.set(latestSignalStateKey, parentValue);
|
|
2736
|
+
}
|
|
2737
|
+
return latestSignalState;
|
|
2738
|
+
}
|
|
2739
|
+
unsubscribeFromInnerValue;
|
|
2740
|
+
unsubscribeFromState;
|
|
2741
|
+
captureSignalsFromCore(mutableState, latestSignalState, target) {
|
|
2742
|
+
const stateKey = mutableState.key;
|
|
2743
|
+
const subscriptionKey = `tracker-from-core:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.token.key : `main`}:${stateKey}`;
|
|
2744
|
+
const trackerCapturesOutboundSignal = (update) => {
|
|
2745
|
+
operateOnStore(JOIN_OP, target, latestSignalState, update);
|
|
2746
|
+
};
|
|
2747
|
+
this.unsubscribeFromInnerValue = getFromStore(target, mutableState).subscribe(subscriptionKey, trackerCapturesOutboundSignal);
|
|
2748
|
+
this.unsubscribeFromState = subscribeToState(target, mutableState, subscriptionKey, function trackerLooksForNewReference(update) {
|
|
2749
|
+
if (update.newValue !== update.oldValue) {
|
|
2750
|
+
this.unsubscribeFromInnerValue();
|
|
2751
|
+
this.unsubscribeFromInnerValue = update.newValue.subscribe(subscriptionKey, trackerCapturesOutboundSignal);
|
|
2752
|
+
}
|
|
2753
|
+
}.bind(this));
|
|
2754
|
+
}
|
|
2755
|
+
supplySignalsToCore(mutableState, latestSignalState, target) {
|
|
2756
|
+
const stateKey = mutableState.key;
|
|
2757
|
+
const subscriptionKey = `tracker-to-core:${target.config.name}:${isChildStore(target) ? target.transactionMeta.update.token.key : `main`}:${stateKey}`;
|
|
2758
|
+
subscribeToState(target, latestSignalState, subscriptionKey, Object.assign(function trackerCapturesInboundSignal({ newValue, oldValue }) {
|
|
2759
|
+
const timelineId = target.timelineTopics.getRelatedKey(latestSignalState.key);
|
|
2760
|
+
if (timelineId && target.timelines.get(timelineId)?.timeTraveling) {
|
|
2761
|
+
const unsubscribe = subscribeToTimeline(target, {
|
|
2762
|
+
key: timelineId,
|
|
2763
|
+
type: `timeline`
|
|
2764
|
+
}, subscriptionKey, function trackerWaitsForTimeTravelToFinish(update) {
|
|
2765
|
+
unsubscribe();
|
|
2766
|
+
setIntoStore(target, mutableState, (transceiver) => {
|
|
2767
|
+
if (update === `redo` && newValue)
|
|
2768
|
+
transceiver.do(newValue);
|
|
2769
|
+
else if (update === `undo` && oldValue)
|
|
2770
|
+
transceiver.undo(oldValue);
|
|
2771
|
+
return transceiver;
|
|
2772
|
+
});
|
|
2773
|
+
});
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
setIntoStore(target, mutableState, (transceiver) => (transceiver.do(newValue), transceiver));
|
|
2777
|
+
}, { inboundTracker: true }));
|
|
2778
|
+
}
|
|
2779
|
+
mutableAtomToken;
|
|
2780
|
+
latestSignalToken;
|
|
2781
|
+
[Symbol.dispose];
|
|
2782
|
+
constructor(mutableAtomToken, store) {
|
|
2783
|
+
const target = newest(store);
|
|
2784
|
+
const latestSignalToken = this.initializeSignalAtom(mutableAtomToken, target);
|
|
2785
|
+
this.mutableAtomToken = mutableAtomToken;
|
|
2786
|
+
this.latestSignalToken = latestSignalToken;
|
|
2787
|
+
this.captureSignalsFromCore(mutableAtomToken, latestSignalToken, target);
|
|
2788
|
+
this.supplySignalsToCore(mutableAtomToken, latestSignalToken, target);
|
|
2789
|
+
target.trackers.set(mutableAtomToken.key, this);
|
|
2790
|
+
this[Symbol.dispose] = () => {
|
|
2791
|
+
this.unsubscribeFromInnerValue();
|
|
2792
|
+
this.unsubscribeFromState();
|
|
2793
|
+
target.trackers.delete(mutableAtomToken.key);
|
|
2794
|
+
};
|
|
2795
|
+
}
|
|
2796
|
+
};
|
|
2797
|
+
function createMutableAtom(store, options, family) {
|
|
2798
|
+
store.logger.info(`\uD83D\uDD28`, `atom`, options.key, `creating in store "${store.config.name}"`);
|
|
2799
|
+
const target = newest(store);
|
|
2800
|
+
const { key } = options;
|
|
2801
|
+
const existing = target.atoms.get(key);
|
|
2802
|
+
const type = `mutable_atom`;
|
|
2803
|
+
if (existing?.type === type && store.config.isProduction === true) {
|
|
2804
|
+
store.logger.error(`\u274C`, type, key, `Tried to create atom, but it already exists in the store.`);
|
|
2805
|
+
return deposit(existing);
|
|
2806
|
+
}
|
|
2807
|
+
const subject = new Subject;
|
|
2808
|
+
const newAtom = {
|
|
2809
|
+
...options,
|
|
2810
|
+
type,
|
|
2811
|
+
install: (s) => {
|
|
2812
|
+
s.logger.info(`\uD83D\uDEE0\uFE0F`, `atom`, key, `installing in store "${s.config.name}"`);
|
|
2813
|
+
return createMutableAtom(s, options, family);
|
|
2814
|
+
},
|
|
2815
|
+
subject
|
|
2816
|
+
};
|
|
2817
|
+
if (family)
|
|
2818
|
+
newAtom.family = family;
|
|
2819
|
+
target.atoms.set(newAtom.key, newAtom);
|
|
2820
|
+
const token = deposit(newAtom);
|
|
2821
|
+
new Tracker(token, store);
|
|
2822
|
+
if (!family)
|
|
2823
|
+
createStandaloneSelector(store, {
|
|
2824
|
+
key: `${key}:JSON`,
|
|
2825
|
+
get: ({ get }) => get(token).toJSON(),
|
|
2826
|
+
set: ({ set }, newValue) => {
|
|
2827
|
+
set(token, options.class.fromJSON(newValue));
|
|
2828
|
+
}
|
|
2829
|
+
});
|
|
2830
|
+
if (options.effects) {
|
|
2831
|
+
let effectIndex = 0;
|
|
2832
|
+
const cleanupFunctions = [];
|
|
2833
|
+
for (const effect of options.effects) {
|
|
2834
|
+
const cleanup = effect({
|
|
2835
|
+
resetSelf: () => {
|
|
2836
|
+
resetInStore(store, token);
|
|
2837
|
+
},
|
|
2838
|
+
setSelf: (next) => {
|
|
2839
|
+
setIntoStore(store, token, next);
|
|
2840
|
+
},
|
|
2841
|
+
onSet: (handle) => subscribeToState(store, token, `effect[${effectIndex}]`, handle),
|
|
2842
|
+
token,
|
|
2843
|
+
store: eldest(store)
|
|
2844
|
+
});
|
|
2845
|
+
if (cleanup)
|
|
2846
|
+
cleanupFunctions.push(cleanup);
|
|
2847
|
+
++effectIndex;
|
|
2848
|
+
}
|
|
2849
|
+
newAtom.cleanup = () => {
|
|
2850
|
+
for (const cleanup of cleanupFunctions)
|
|
2851
|
+
cleanup();
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
store.on.atomCreation.next(token);
|
|
2855
|
+
return token;
|
|
2856
|
+
}
|
|
2857
|
+
var FamilyTracker = class {
|
|
2858
|
+
trackers = /* @__PURE__ */ new Map;
|
|
2859
|
+
latestSignalAtoms;
|
|
2860
|
+
mutableAtoms;
|
|
2861
|
+
constructor(mutableAtoms, store) {
|
|
2862
|
+
this.latestSignalAtoms = withdraw(store, createRegularAtomFamily(store, {
|
|
2863
|
+
key: `*${mutableAtoms.key}`,
|
|
2864
|
+
default: null
|
|
2865
|
+
}, [`mutable`, `updates`]));
|
|
2866
|
+
this.mutableAtoms = mutableAtoms;
|
|
2867
|
+
const trackerFamilyWatchesForCreationAndDisposalEvents = (event) => {
|
|
2868
|
+
const { type, token } = event;
|
|
2869
|
+
if (token.family) {
|
|
2870
|
+
const key = parseJson(token.family.subKey);
|
|
2871
|
+
switch (type) {
|
|
2872
|
+
case `state_creation`:
|
|
2873
|
+
this.trackers.set(key, new Tracker(token, store));
|
|
2874
|
+
break;
|
|
2875
|
+
case `state_disposal`: {
|
|
2876
|
+
const tracker = this.trackers.get(key);
|
|
2877
|
+
if (tracker) {
|
|
2878
|
+
tracker[Symbol.dispose]();
|
|
2879
|
+
this.trackers.delete(key);
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
};
|
|
2885
|
+
this.mutableAtoms.subject.subscribe(`store=${store.config.name}::tracker-atom-family`, trackerFamilyWatchesForCreationAndDisposalEvents);
|
|
2886
|
+
}
|
|
2887
|
+
};
|
|
2888
|
+
function createMutableAtomFamily(store, options, internalRoles) {
|
|
2889
|
+
const familyToken = {
|
|
2890
|
+
key: options.key,
|
|
2891
|
+
type: `mutable_atom_family`
|
|
2892
|
+
};
|
|
2893
|
+
const existing = store.families.get(options.key);
|
|
2894
|
+
if (existing && store.config.isProduction === true)
|
|
2895
|
+
store.logger.error(`\u2757`, `mutable_atom_family`, options.key, `Overwriting an existing ${PRETTY_TOKEN_TYPES[existing.type]} "${existing.key}" in store "${store.config.name}". You can safely ignore this warning if it is due to hot module replacement.`);
|
|
2896
|
+
const subject = new Subject;
|
|
2897
|
+
const create = (key) => {
|
|
2898
|
+
const subKey = stringifyJson(key);
|
|
2899
|
+
const family = {
|
|
2900
|
+
key: options.key,
|
|
2901
|
+
subKey
|
|
2902
|
+
};
|
|
2903
|
+
const fullKey = `${options.key}(${subKey})`;
|
|
2904
|
+
const target = newest(store);
|
|
2905
|
+
const individualOptions = {
|
|
2906
|
+
key: fullKey,
|
|
2907
|
+
class: options.class
|
|
2908
|
+
};
|
|
2909
|
+
if (options.effects)
|
|
2910
|
+
individualOptions.effects = options.effects(key);
|
|
2911
|
+
return createMutableAtom(target, individualOptions, family);
|
|
2912
|
+
};
|
|
2913
|
+
const atomFamily$1 = {
|
|
2914
|
+
...familyToken,
|
|
2915
|
+
create,
|
|
2916
|
+
class: options.class,
|
|
2917
|
+
subject,
|
|
2918
|
+
install: (s) => createMutableAtomFamily(s, options),
|
|
2919
|
+
internalRoles
|
|
2920
|
+
};
|
|
2921
|
+
store.families.set(options.key, atomFamily$1);
|
|
2922
|
+
createWritablePureSelectorFamily(store, {
|
|
2923
|
+
key: `${options.key}:JSON`,
|
|
2924
|
+
get: (key) => ({ get }) => get(familyToken, key).toJSON(),
|
|
2925
|
+
set: (key) => ({ set }, newValue) => {
|
|
2926
|
+
set(familyToken, key, options.class.fromJSON(newValue));
|
|
2927
|
+
}
|
|
2928
|
+
}, [`mutable`, `json`]);
|
|
2929
|
+
new FamilyTracker(atomFamily$1, store);
|
|
2930
|
+
return familyToken;
|
|
2931
|
+
}
|
|
2932
|
+
var getJsonFamily = (mutableAtomFamily, store) => {
|
|
2933
|
+
const target = newest(store);
|
|
2934
|
+
const key = `${mutableAtomFamily.key}:JSON`;
|
|
2935
|
+
return target.families.get(key);
|
|
2936
|
+
};
|
|
2937
|
+
var getJsonToken = (store, mutableAtomToken) => {
|
|
2938
|
+
if (mutableAtomToken.family)
|
|
2939
|
+
return findInStore(store, withdraw(newest(store), {
|
|
2940
|
+
key: `${mutableAtomToken.family.key}:JSON`,
|
|
2941
|
+
type: `writable_pure_selector_family`
|
|
2942
|
+
}), parseJson(mutableAtomToken.family.subKey));
|
|
2943
|
+
return {
|
|
2944
|
+
type: `writable_pure_selector`,
|
|
2945
|
+
key: `${mutableAtomToken.key}:JSON`
|
|
2946
|
+
};
|
|
2947
|
+
};
|
|
2948
|
+
var getUpdateToken = (mutableAtomToken) => {
|
|
2949
|
+
const updateToken = {
|
|
2950
|
+
type: `atom`,
|
|
2951
|
+
key: `*${mutableAtomToken.key}`
|
|
2952
|
+
};
|
|
2953
|
+
if (mutableAtomToken.family)
|
|
2954
|
+
updateToken.family = {
|
|
2955
|
+
key: `*${mutableAtomToken.family.key}`,
|
|
2956
|
+
subKey: mutableAtomToken.family.subKey
|
|
2957
|
+
};
|
|
2958
|
+
return updateToken;
|
|
2959
|
+
};
|
|
2960
|
+
function isTransceiver(value) {
|
|
2961
|
+
return typeof value === `object` && value !== null && `do` in value && `undo` in value && `subscribe` in value && `READONLY_VIEW` in value && `toJSON` in value;
|
|
2962
|
+
}
|
|
2963
|
+
function writeToCache(target, state, value) {
|
|
2964
|
+
const { key, subject, type } = state;
|
|
2965
|
+
const currentValue = target.valueMap.get(key);
|
|
2966
|
+
if (currentValue instanceof Future && !currentValue.done) {
|
|
2967
|
+
const future = currentValue;
|
|
2968
|
+
if (value instanceof Promise) {
|
|
2969
|
+
future.use(value);
|
|
2970
|
+
return future;
|
|
2971
|
+
}
|
|
2972
|
+
target.valueMap.set(key, value);
|
|
2973
|
+
return value;
|
|
2974
|
+
}
|
|
2975
|
+
if (value instanceof Promise) {
|
|
2976
|
+
const future = new Future(value);
|
|
2977
|
+
target.valueMap.set(key, future);
|
|
2978
|
+
future.then(function handleResolvedFuture(resolved) {
|
|
2979
|
+
if (target.valueMap.get(key) === future) {
|
|
2980
|
+
openOperation(target, state);
|
|
2981
|
+
writeToCache(target, state, resolved);
|
|
2982
|
+
switch (type) {
|
|
2983
|
+
case `atom`:
|
|
2984
|
+
evictDownstreamFromAtom(target, state);
|
|
2985
|
+
break;
|
|
2986
|
+
case `readonly_pure_selector`:
|
|
2987
|
+
case `writable_pure_selector`:
|
|
2988
|
+
evictDownstreamFromSelector(target, key);
|
|
2989
|
+
break;
|
|
2990
|
+
}
|
|
2991
|
+
closeOperation(target);
|
|
2992
|
+
subject.next({
|
|
2993
|
+
newValue: resolved,
|
|
2994
|
+
oldValue: future
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2997
|
+
}).catch((thrown) => {
|
|
2998
|
+
target.logger.error(`\uD83D\uDCA5`, state.type, key, `rejected:`, thrown);
|
|
2999
|
+
});
|
|
3000
|
+
return future;
|
|
3001
|
+
}
|
|
3002
|
+
target.logger.info(`\uD83D\uDCDD`, state.type, state.key, `writing to cache`, value);
|
|
3003
|
+
target.valueMap.set(key, value);
|
|
3004
|
+
return value;
|
|
3005
|
+
}
|
|
3006
|
+
function readFromCache(target, state, mut) {
|
|
3007
|
+
target.logger.info(`\uD83D\uDCD6`, state.type, state.key, `reading cached value`);
|
|
3008
|
+
let value = target.valueMap.get(state.key);
|
|
3009
|
+
if (mut === `mut` && state.type === `mutable_atom` && isChildStore(target)) {
|
|
3010
|
+
const mutableAtom$1 = state;
|
|
3011
|
+
const { parent } = target;
|
|
3012
|
+
if (target.valueMap.hasOwn(mutableAtom$1.key))
|
|
3013
|
+
return value;
|
|
3014
|
+
const parentValue = parent.valueMap.get(mutableAtom$1.key);
|
|
3015
|
+
target.logger.info(`\uD83D\uDCC3`, `atom`, mutableAtom$1.key, `copying`);
|
|
3016
|
+
const jsonValue = parentValue.toJSON();
|
|
3017
|
+
const copiedValue = mutableAtom$1.class.fromJSON(jsonValue);
|
|
3018
|
+
target.valueMap.set(mutableAtom$1.key, copiedValue);
|
|
3019
|
+
new Tracker(mutableAtom$1, parent);
|
|
3020
|
+
value = copiedValue;
|
|
3021
|
+
}
|
|
3022
|
+
return value;
|
|
3023
|
+
}
|
|
3024
|
+
function evictCachedValue(target, key) {
|
|
3025
|
+
const currentValue = target.valueMap.get(key);
|
|
3026
|
+
if (currentValue instanceof Future) {
|
|
3027
|
+
const selector = target.writableSelectors.get(key) ?? target.readonlySelectors.get(key);
|
|
3028
|
+
if (selector)
|
|
3029
|
+
selector.getFrom(target);
|
|
3030
|
+
return;
|
|
3031
|
+
}
|
|
3032
|
+
if (target.operation.open)
|
|
3033
|
+
target.operation.prev.set(key, currentValue);
|
|
3034
|
+
target.valueMap.delete(key);
|
|
3035
|
+
target.logger.info(`\uD83D\uDDD1`, `state`, key, `evicted`);
|
|
3036
|
+
}
|
|
3037
|
+
function evictDownstreamFromAtom(store, atom) {
|
|
3038
|
+
const target = newest(store);
|
|
3039
|
+
const { key, type } = atom;
|
|
3040
|
+
const downstreamKeys = target.selectorAtoms.getRelatedKeys(key);
|
|
3041
|
+
target.logger.info(`\uD83E\uDDF9`, type, key, downstreamKeys ? `evicting ${downstreamKeys.size} states downstream:` : `no downstream states`, downstreamKeys ?? `to evict`);
|
|
3042
|
+
if (downstreamKeys) {
|
|
3043
|
+
if (target.operation.open)
|
|
3044
|
+
target.logger.info(`\uD83E\uDDF9`, type, key, `[ ${[...target.operation.done].join(`, `)} ] already done`);
|
|
3045
|
+
for (const downstreamKey of downstreamKeys) {
|
|
3046
|
+
if (isDone(target, downstreamKey))
|
|
3047
|
+
continue;
|
|
3048
|
+
evictCachedValue(target, downstreamKey);
|
|
3049
|
+
markDone(target, downstreamKey);
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
function evictDownstreamFromSelector(store, selectorKey) {
|
|
3054
|
+
const target = newest(store);
|
|
3055
|
+
const relationEntries = target.selectorGraph.getRelationEntries({ upstreamSelectorKey: selectorKey }).filter(([_, { source }]) => source === selectorKey);
|
|
3056
|
+
for (const [downstreamSelectorKey] of relationEntries) {
|
|
3057
|
+
if (isDone(target, downstreamSelectorKey))
|
|
3058
|
+
continue;
|
|
3059
|
+
evictCachedValue(target, downstreamSelectorKey);
|
|
3060
|
+
markDone(target, downstreamSelectorKey);
|
|
3061
|
+
evictDownstreamFromSelector(store, downstreamSelectorKey);
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
function createRegularAtom(store, options, family, internalRoles) {
|
|
3065
|
+
const type = `atom`;
|
|
3066
|
+
const { key } = options;
|
|
3067
|
+
store.logger.info(`\uD83D\uDD28`, type, key, `is being created`);
|
|
3068
|
+
const target = newest(store);
|
|
3069
|
+
const existing = target.atoms.get(key);
|
|
3070
|
+
if (existing?.type === type && store.config.isProduction === true) {
|
|
3071
|
+
store.logger.error(`\u274C`, `atom`, key, `Tried to create atom, but it already exists in the store.`);
|
|
3072
|
+
return deposit(existing);
|
|
3073
|
+
}
|
|
3074
|
+
const subject = new Subject;
|
|
3075
|
+
const newAtom = {
|
|
3076
|
+
...options,
|
|
3077
|
+
type,
|
|
3078
|
+
install: (s) => {
|
|
3079
|
+
s.logger.info(`\uD83D\uDEE0\uFE0F`, type, key, `installing in store "${s.config.name}"`);
|
|
3080
|
+
return createRegularAtom(s, options, family);
|
|
3081
|
+
},
|
|
3082
|
+
subject
|
|
3083
|
+
};
|
|
3084
|
+
if (family)
|
|
3085
|
+
newAtom.family = family;
|
|
3086
|
+
if (internalRoles)
|
|
3087
|
+
newAtom.internalRoles = internalRoles;
|
|
3088
|
+
target.atoms.set(key, newAtom);
|
|
3089
|
+
const token = deposit(newAtom);
|
|
3090
|
+
if (options.effects) {
|
|
3091
|
+
let effectIndex = 0;
|
|
3092
|
+
const cleanupFunctions = [];
|
|
3093
|
+
for (const effect of options.effects) {
|
|
3094
|
+
const cleanup = effect({
|
|
3095
|
+
resetSelf: () => {
|
|
3096
|
+
resetInStore(store, token);
|
|
3097
|
+
},
|
|
3098
|
+
setSelf: (next) => {
|
|
3099
|
+
setIntoStore(store, token, next);
|
|
3100
|
+
},
|
|
3101
|
+
onSet: (handle) => subscribeToState(store, token, `effect[${effectIndex}]`, handle),
|
|
3102
|
+
token,
|
|
3103
|
+
store: eldest(store)
|
|
3104
|
+
});
|
|
3105
|
+
if (cleanup)
|
|
3106
|
+
cleanupFunctions.push(cleanup);
|
|
3107
|
+
++effectIndex;
|
|
3108
|
+
}
|
|
3109
|
+
newAtom.cleanup = () => {
|
|
3110
|
+
for (const cleanup of cleanupFunctions)
|
|
3111
|
+
cleanup();
|
|
3112
|
+
};
|
|
3113
|
+
}
|
|
3114
|
+
store.on.atomCreation.next(token);
|
|
3115
|
+
return token;
|
|
3116
|
+
}
|
|
3117
|
+
function hasRole(atom, role) {
|
|
3118
|
+
if (`internalRoles` in atom === false)
|
|
3119
|
+
return false;
|
|
3120
|
+
return atom.internalRoles.includes(role);
|
|
3121
|
+
}
|
|
3122
|
+
function disposeAtom(store, atomToken) {
|
|
3123
|
+
const target = newest(store);
|
|
3124
|
+
const { key, family } = atomToken;
|
|
3125
|
+
const atom = withdraw(target, atomToken);
|
|
3126
|
+
if (!family)
|
|
3127
|
+
store.logger.error(`\u274C`, `atom`, key, `Standalone atoms cannot be disposed.`);
|
|
3128
|
+
else {
|
|
3129
|
+
atom.cleanup?.();
|
|
3130
|
+
const lastValue = store.valueMap.get(atom.key);
|
|
3131
|
+
const subject = withdraw(store, getFamilyOfToken(store, atomToken)).subject;
|
|
3132
|
+
const disposalEvent = {
|
|
3133
|
+
type: `state_disposal`,
|
|
3134
|
+
subType: `atom`,
|
|
3135
|
+
token: atomToken,
|
|
3136
|
+
value: lastValue,
|
|
3137
|
+
timestamp: Date.now()
|
|
3138
|
+
};
|
|
3139
|
+
subject.next(disposalEvent);
|
|
3140
|
+
const isChild = isChildStore(target);
|
|
3141
|
+
target.atoms.delete(key);
|
|
3142
|
+
target.valueMap.delete(key);
|
|
3143
|
+
target.selectorAtoms.delete(key);
|
|
3144
|
+
target.atomsThatAreDefault.delete(key);
|
|
3145
|
+
target.moleculeData.delete(family.key, family.subKey);
|
|
3146
|
+
store.timelineTopics.delete(key);
|
|
3147
|
+
if (atomToken.type === `mutable_atom`) {
|
|
3148
|
+
disposeAtom(store, getUpdateToken(atomToken));
|
|
3149
|
+
store.trackers.delete(key);
|
|
3150
|
+
}
|
|
3151
|
+
store.logger.info(`\uD83D\uDD25`, `atom`, key, `deleted`);
|
|
3152
|
+
if (isChild && target.transactionMeta.phase === `building`) {
|
|
3153
|
+
const mostRecentUpdate = target.transactionMeta.update.subEvents.at(-1);
|
|
3154
|
+
const updateAlreadyCaptured = mostRecentUpdate?.type === `molecule_disposal` && mostRecentUpdate.values.some(([k]) => k === atom.family?.key);
|
|
3155
|
+
const isTracker = hasRole(atom, `tracker:signal`);
|
|
3156
|
+
if (!updateAlreadyCaptured && !isTracker)
|
|
3157
|
+
target.transactionMeta.update.subEvents.push(disposalEvent);
|
|
3158
|
+
} else
|
|
3159
|
+
store.on.atomDisposal.next(atomToken);
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
function capitalize(string) {
|
|
3163
|
+
return string[0].toUpperCase() + string.slice(1);
|
|
3164
|
+
}
|
|
3165
|
+
var Join = class {
|
|
3166
|
+
toolkit;
|
|
3167
|
+
options;
|
|
3168
|
+
relations;
|
|
3169
|
+
states;
|
|
3170
|
+
relatedKeysAtoms;
|
|
3171
|
+
transact(toolkit, run) {
|
|
3172
|
+
const originalToolkit = this.toolkit;
|
|
3173
|
+
this.toolkit = toolkit;
|
|
3174
|
+
run(this);
|
|
3175
|
+
this.toolkit = originalToolkit;
|
|
3176
|
+
}
|
|
3177
|
+
store;
|
|
3178
|
+
[Symbol.dispose]() {}
|
|
3179
|
+
constructor(options, store = IMPLICIT.STORE) {
|
|
3180
|
+
this.store = store;
|
|
3181
|
+
this.options = options;
|
|
3182
|
+
this.store.miscResources.set(`join:${options.key}`, this);
|
|
3183
|
+
this.toolkit = {
|
|
3184
|
+
get: (...ps) => getFromStore(store, ...ps),
|
|
3185
|
+
set: (...ps) => {
|
|
3186
|
+
setIntoStore(store, ...ps);
|
|
3187
|
+
},
|
|
3188
|
+
find: (...ps) => findInStore(store, ...ps),
|
|
3189
|
+
json: (token) => getJsonToken(store, token)
|
|
3190
|
+
};
|
|
3191
|
+
const aSide = options.between[0];
|
|
3192
|
+
const bSide = options.between[1];
|
|
3193
|
+
const relatedKeysAtoms = createMutableAtomFamily(store, {
|
|
3194
|
+
key: `${options.key}/relatedKeys`,
|
|
3195
|
+
class: UList
|
|
3196
|
+
}, [`join`, `relations`]);
|
|
3197
|
+
this.relatedKeysAtoms = relatedKeysAtoms;
|
|
3198
|
+
const replaceRelationsSafely = (toolkit, a, newRelationsOfA) => {
|
|
3199
|
+
const { find, get, set } = toolkit;
|
|
3200
|
+
const relationsOfAState = find(relatedKeysAtoms, a);
|
|
3201
|
+
const currentRelationsOfA = get(relationsOfAState);
|
|
3202
|
+
for (const currentRelationB of currentRelationsOfA) {
|
|
3203
|
+
if (newRelationsOfA.includes(currentRelationB))
|
|
3204
|
+
continue;
|
|
3205
|
+
set(relatedKeysAtoms, currentRelationB, (relationsOfB) => {
|
|
3206
|
+
relationsOfB.delete(a);
|
|
3207
|
+
return relationsOfB;
|
|
3208
|
+
});
|
|
3209
|
+
}
|
|
3210
|
+
set(relationsOfAState, (relationsOfA) => {
|
|
3211
|
+
relationsOfA.clear();
|
|
3212
|
+
for (const newRelationB of newRelationsOfA) {
|
|
3213
|
+
const relationsOfBAtom = find(relatedKeysAtoms, newRelationB);
|
|
3214
|
+
const relationsOfB = get(relationsOfBAtom);
|
|
3215
|
+
const newRelationBIsAlreadyRelated = relationsOfB.has(a);
|
|
3216
|
+
if (this.relations.cardinality === `1:n`) {
|
|
3217
|
+
const previousOwnersToDispose = [];
|
|
3218
|
+
for (const previousOwner of relationsOfB) {
|
|
3219
|
+
if (previousOwner === a)
|
|
3220
|
+
continue;
|
|
3221
|
+
let previousOwnerSize;
|
|
3222
|
+
operateOnStore(JOIN_OP, this.store, relatedKeysAtoms, previousOwner, (relations$1) => {
|
|
3223
|
+
relations$1.delete(newRelationB);
|
|
3224
|
+
previousOwnerSize = relations$1.size;
|
|
3225
|
+
return relations$1;
|
|
3226
|
+
});
|
|
3227
|
+
if (previousOwnerSize === 0)
|
|
3228
|
+
previousOwnersToDispose.push(previousOwner);
|
|
3229
|
+
}
|
|
3230
|
+
if (!newRelationBIsAlreadyRelated && relationsOfB.size > 0)
|
|
3231
|
+
set(relationsOfBAtom, (relations$1) => {
|
|
3232
|
+
relations$1.clear();
|
|
3233
|
+
return relations$1;
|
|
3234
|
+
});
|
|
3235
|
+
for (const previousOwner of previousOwnersToDispose)
|
|
3236
|
+
store.keyRefsInJoins.delete(simpleCompound(newRelationB, previousOwner));
|
|
3237
|
+
}
|
|
3238
|
+
if (!newRelationBIsAlreadyRelated)
|
|
3239
|
+
set(relationsOfBAtom, (relations$1) => {
|
|
3240
|
+
relations$1.add(a);
|
|
3241
|
+
return relations$1;
|
|
3242
|
+
});
|
|
3243
|
+
relationsOfA.add(newRelationB);
|
|
3244
|
+
}
|
|
3245
|
+
return relationsOfA;
|
|
3246
|
+
});
|
|
3247
|
+
};
|
|
3248
|
+
const replaceRelationsUnsafely = (toolkit, a, newRelationsOfA) => {
|
|
3249
|
+
const { set } = toolkit;
|
|
3250
|
+
set(relatedKeysAtoms, a, (relationsOfA) => {
|
|
3251
|
+
for (const newRelationB of newRelationsOfA)
|
|
3252
|
+
relationsOfA.add(newRelationB);
|
|
3253
|
+
return relationsOfA;
|
|
3254
|
+
});
|
|
3255
|
+
for (const newRelationB of newRelationsOfA)
|
|
3256
|
+
set(relatedKeysAtoms, newRelationB, (newRelationsB) => {
|
|
3257
|
+
newRelationsB.add(a);
|
|
3258
|
+
return newRelationsB;
|
|
3259
|
+
});
|
|
3260
|
+
return true;
|
|
3261
|
+
};
|
|
3262
|
+
const relations = new Junction(options, {
|
|
3263
|
+
externalStore: {
|
|
3264
|
+
getRelatedKeys: (key) => this.toolkit.get(relatedKeysAtoms, key),
|
|
3265
|
+
addRelation: (a, b) => {
|
|
3266
|
+
this.store.keyRefsInJoins.set(`"${a}"`, options.key);
|
|
3267
|
+
this.store.keyRefsInJoins.set(`"${b}"`, options.key);
|
|
3268
|
+
this.store.keyRefsInJoins.set(simpleCompound(a, b), options.key);
|
|
3269
|
+
this.toolkit.set(relatedKeysAtoms, a, (aKeys) => aKeys.add(b));
|
|
3270
|
+
this.toolkit.set(relatedKeysAtoms, b, (bKeys) => bKeys.add(a));
|
|
3271
|
+
},
|
|
3272
|
+
deleteRelation: (a, b) => {
|
|
3273
|
+
this.toolkit.set(relatedKeysAtoms, a, (aKeys) => {
|
|
3274
|
+
aKeys.delete(b);
|
|
3275
|
+
return aKeys;
|
|
3276
|
+
});
|
|
3277
|
+
this.toolkit.set(relatedKeysAtoms, b, (bKeys) => {
|
|
3278
|
+
bKeys.delete(a);
|
|
3279
|
+
return bKeys;
|
|
3280
|
+
});
|
|
3281
|
+
const compositeKey = simpleCompound(a, b);
|
|
3282
|
+
this.store.keyRefsInJoins.delete(compositeKey);
|
|
3283
|
+
},
|
|
3284
|
+
replaceRelationsSafely: (a, bs) => {
|
|
3285
|
+
replaceRelationsSafely(this.toolkit, a, bs);
|
|
3286
|
+
},
|
|
3287
|
+
replaceRelationsUnsafely: (a, bs) => {
|
|
3288
|
+
replaceRelationsUnsafely(this.toolkit, a, bs);
|
|
3289
|
+
},
|
|
3290
|
+
has: (a, b) => {
|
|
3291
|
+
const aKeys = this.toolkit.get(relatedKeysAtoms, a);
|
|
3292
|
+
return b ? aKeys.has(b) : aKeys.size > 0;
|
|
3293
|
+
}
|
|
3294
|
+
},
|
|
3295
|
+
isAType: options.isAType,
|
|
3296
|
+
isBType: options.isBType
|
|
3297
|
+
});
|
|
3298
|
+
const createSingleKeySelectorFamily = () => createReadonlyPureSelectorFamily(store, {
|
|
3299
|
+
key: `${options.key}/singleRelatedKey`,
|
|
3300
|
+
get: (key) => ({ get }) => {
|
|
3301
|
+
const relatedKeys = get(relatedKeysAtoms, key);
|
|
3302
|
+
for (const relatedKey of relatedKeys)
|
|
3303
|
+
return relatedKey;
|
|
3304
|
+
return null;
|
|
3305
|
+
}
|
|
3306
|
+
}, [`join`, `keys`]);
|
|
3307
|
+
const getMultipleKeySelectorFamily = () => {
|
|
3308
|
+
return createReadonlyPureSelectorFamily(store, {
|
|
3309
|
+
key: `${options.key}/multipleRelatedKeys`,
|
|
3310
|
+
get: (key) => ({ get }) => {
|
|
3311
|
+
return get(getJsonFamily(relatedKeysAtoms, store), key);
|
|
3312
|
+
}
|
|
3313
|
+
}, [`join`, `keys`]);
|
|
3314
|
+
};
|
|
3315
|
+
switch (options.cardinality) {
|
|
3316
|
+
case `1:1`: {
|
|
3317
|
+
const singleRelatedKeySelectors = createSingleKeySelectorFamily();
|
|
3318
|
+
const stateKeyA = `${aSide}KeyOf${capitalize(bSide)}`;
|
|
3319
|
+
const stateKeyB = `${bSide}KeyOf${capitalize(aSide)}`;
|
|
3320
|
+
this.relations = relations;
|
|
3321
|
+
this.states = {
|
|
3322
|
+
[stateKeyA]: singleRelatedKeySelectors,
|
|
3323
|
+
[stateKeyB]: singleRelatedKeySelectors
|
|
3324
|
+
};
|
|
3325
|
+
break;
|
|
3326
|
+
}
|
|
3327
|
+
case `1:n`: {
|
|
3328
|
+
const singleRelatedKeySelectors = createSingleKeySelectorFamily();
|
|
3329
|
+
const multipleRelatedKeysSelectors = getMultipleKeySelectorFamily();
|
|
3330
|
+
const stateKeyA = `${aSide}KeyOf${capitalize(bSide)}`;
|
|
3331
|
+
const stateKeyB = `${bSide}KeysOf${capitalize(aSide)}`;
|
|
3332
|
+
const baseStates = {
|
|
3333
|
+
[stateKeyA]: singleRelatedKeySelectors,
|
|
3334
|
+
[stateKeyB]: multipleRelatedKeysSelectors
|
|
3335
|
+
};
|
|
3336
|
+
this.relations = relations;
|
|
3337
|
+
this.states = baseStates;
|
|
3338
|
+
break;
|
|
3339
|
+
}
|
|
3340
|
+
case `n:n`: {
|
|
3341
|
+
const multipleRelatedKeysSelectors = getMultipleKeySelectorFamily();
|
|
3342
|
+
const stateKeyA = `${aSide}KeysOf${capitalize(bSide)}`;
|
|
3343
|
+
const stateKeyB = `${bSide}KeysOf${capitalize(aSide)}`;
|
|
3344
|
+
this.relations = relations;
|
|
3345
|
+
this.states = {
|
|
3346
|
+
[stateKeyA]: multipleRelatedKeysSelectors,
|
|
3347
|
+
[stateKeyB]: multipleRelatedKeysSelectors
|
|
3348
|
+
};
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
};
|
|
3353
|
+
function createJoin(store, options) {
|
|
3354
|
+
store.joins.set(options.key, new Join(options));
|
|
3355
|
+
return {
|
|
3356
|
+
key: options.key,
|
|
3357
|
+
type: `join`,
|
|
3358
|
+
a: options.between[0],
|
|
3359
|
+
b: options.between[1],
|
|
3360
|
+
cardinality: options.cardinality
|
|
3361
|
+
};
|
|
3362
|
+
}
|
|
3363
|
+
function getJoin(token, store) {
|
|
3364
|
+
let myJoin = store.joins.get(token.key);
|
|
3365
|
+
if (myJoin === undefined) {
|
|
3366
|
+
const rootJoin = IMPLICIT.STORE.joins.get(token.key);
|
|
3367
|
+
if (rootJoin === undefined)
|
|
3368
|
+
throw new Error(`Join "${token.key}" not found in store "${store.config.name}"`);
|
|
3369
|
+
const root = eldest(store);
|
|
3370
|
+
myJoin = new Join(rootJoin.options, root);
|
|
3371
|
+
store.joins.set(token.key, myJoin);
|
|
3372
|
+
}
|
|
3373
|
+
return myJoin;
|
|
3374
|
+
}
|
|
3375
|
+
function editRelationsInStore(token, change, store) {
|
|
3376
|
+
const myJoin = getJoin(token, store);
|
|
3377
|
+
const target = newest(store);
|
|
3378
|
+
if (isChildStore(target)) {
|
|
3379
|
+
const { toolkit } = target.transactionMeta;
|
|
3380
|
+
myJoin.transact(toolkit, ({ relations }) => {
|
|
3381
|
+
change(relations);
|
|
3382
|
+
});
|
|
3383
|
+
} else
|
|
3384
|
+
change(myJoin.relations);
|
|
3385
|
+
}
|
|
3386
|
+
function findRelationsInStore(token, key, store) {
|
|
3387
|
+
const myJoin = getJoin(token, store);
|
|
3388
|
+
let relations;
|
|
3389
|
+
switch (token.cardinality) {
|
|
3390
|
+
case `1:1`: {
|
|
3391
|
+
const keyAB = `${token.a}KeyOf${capitalize(token.b)}`;
|
|
3392
|
+
const keyBA = `${token.b}KeyOf${capitalize(token.a)}`;
|
|
3393
|
+
relations = {
|
|
3394
|
+
get [keyAB]() {
|
|
3395
|
+
const familyAB = myJoin.states[keyAB];
|
|
3396
|
+
return findInStore(store, familyAB, key);
|
|
3397
|
+
},
|
|
3398
|
+
get [keyBA]() {
|
|
3399
|
+
const familyBA = myJoin.states[keyBA];
|
|
3400
|
+
return findInStore(store, familyBA, key);
|
|
3401
|
+
}
|
|
3402
|
+
};
|
|
3403
|
+
break;
|
|
3404
|
+
}
|
|
3405
|
+
case `1:n`: {
|
|
3406
|
+
const keyAB = `${token.a}KeyOf${capitalize(token.b)}`;
|
|
3407
|
+
const keysBA = `${token.b}KeysOf${capitalize(token.a)}`;
|
|
3408
|
+
relations = {
|
|
3409
|
+
get [keyAB]() {
|
|
3410
|
+
const familyAB = myJoin.states[keyAB];
|
|
3411
|
+
return findInStore(store, familyAB, key);
|
|
3412
|
+
},
|
|
3413
|
+
get [keysBA]() {
|
|
3414
|
+
const familyBA = myJoin.states[keysBA];
|
|
3415
|
+
return findInStore(store, familyBA, key);
|
|
3416
|
+
}
|
|
3417
|
+
};
|
|
3418
|
+
break;
|
|
3419
|
+
}
|
|
3420
|
+
case `n:n`: {
|
|
3421
|
+
const keysAB = `${token.a}KeysOf${capitalize(token.b)}`;
|
|
3422
|
+
const keysBA = `${token.b}KeysOf${capitalize(token.a)}`;
|
|
3423
|
+
relations = {
|
|
3424
|
+
get [keysAB]() {
|
|
3425
|
+
const familyAB = myJoin.states[keysAB];
|
|
3426
|
+
return findInStore(store, familyAB, key);
|
|
3427
|
+
},
|
|
3428
|
+
get [keysBA]() {
|
|
3429
|
+
const familyBA = myJoin.states[keysBA];
|
|
3430
|
+
return findInStore(store, familyBA, key);
|
|
3431
|
+
}
|
|
3432
|
+
};
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
return relations;
|
|
3436
|
+
}
|
|
3437
|
+
function getInternalRelationsFromStore(token, store) {
|
|
3438
|
+
return getJoin(token, store).relatedKeysAtoms;
|
|
3439
|
+
}
|
|
3440
|
+
|
|
3441
|
+
// ../../packages/atom.io/dist/realtime/index.js
|
|
3442
|
+
var mutexAtoms = atomFamily({
|
|
3443
|
+
key: `mutex`,
|
|
3444
|
+
default: false
|
|
3445
|
+
});
|
|
3446
|
+
var InvariantMap = class extends Map {
|
|
3447
|
+
set(key, value) {
|
|
3448
|
+
if (this.has(key)) {
|
|
3449
|
+
console.warn(`Tried to set a key that already exists in an InvariantMap`, {
|
|
3450
|
+
key,
|
|
3451
|
+
value
|
|
3452
|
+
});
|
|
3453
|
+
return this;
|
|
3454
|
+
}
|
|
3455
|
+
return super.set(key, value);
|
|
3456
|
+
}
|
|
3457
|
+
};
|
|
3458
|
+
var SyncGroup = class SyncGroup2 {
|
|
3459
|
+
type = `continuity`;
|
|
3460
|
+
globals = [];
|
|
3461
|
+
actions = [];
|
|
3462
|
+
perspectives = [];
|
|
3463
|
+
key;
|
|
3464
|
+
constructor(key) {
|
|
3465
|
+
this.key = key;
|
|
3466
|
+
}
|
|
3467
|
+
static existing = new InvariantMap;
|
|
3468
|
+
static create(key, builder) {
|
|
3469
|
+
const { type, globals, actions, perspectives } = builder(new SyncGroup2(key));
|
|
3470
|
+
const token = {
|
|
3471
|
+
type,
|
|
3472
|
+
key,
|
|
3473
|
+
globals,
|
|
3474
|
+
actions,
|
|
3475
|
+
perspectives
|
|
3476
|
+
};
|
|
3477
|
+
SyncGroup2.existing.set(key, token);
|
|
3478
|
+
return token;
|
|
3479
|
+
}
|
|
3480
|
+
add(...args) {
|
|
3481
|
+
switch (args[0].type) {
|
|
3482
|
+
case `atom`:
|
|
3483
|
+
case `mutable_atom`:
|
|
3484
|
+
this.globals.push(...args);
|
|
3485
|
+
break;
|
|
3486
|
+
case `transaction`:
|
|
3487
|
+
this.actions.push(...args);
|
|
3488
|
+
break;
|
|
3489
|
+
case `atom_family`:
|
|
3490
|
+
case `mutable_atom_family`:
|
|
3491
|
+
{
|
|
3492
|
+
const [family, index] = args;
|
|
3493
|
+
this.perspectives.push({
|
|
3494
|
+
type: `realtime_perspective`,
|
|
3495
|
+
resourceAtoms: family,
|
|
3496
|
+
viewAtoms: index
|
|
3497
|
+
});
|
|
3498
|
+
}
|
|
3499
|
+
break;
|
|
3500
|
+
}
|
|
3501
|
+
return this;
|
|
3502
|
+
}
|
|
3503
|
+
};
|
|
3504
|
+
var usersInThisRoomIndex = mutableAtom({
|
|
3505
|
+
key: `usersInRoomIndex`,
|
|
3506
|
+
class: UList
|
|
3507
|
+
});
|
|
3508
|
+
var roomIndex = mutableAtom({
|
|
3509
|
+
key: `roomIndex`,
|
|
3510
|
+
class: UList
|
|
3511
|
+
});
|
|
3512
|
+
var usersInRooms = join({
|
|
3513
|
+
key: `usersInRooms`,
|
|
3514
|
+
between: [`room`, `user`],
|
|
3515
|
+
cardinality: `1:n`,
|
|
3516
|
+
isAType: (input) => typeof input === `string`,
|
|
3517
|
+
isBType: (input) => typeof input === `string`
|
|
3518
|
+
});
|
|
3519
|
+
var usersInMyRoomView = selectorFamily({
|
|
3520
|
+
key: `usersInMyRoomView`,
|
|
3521
|
+
get: (myUsername) => ({ find }) => {
|
|
3522
|
+
return [find(getInternalRelations(usersInRooms), myUsername)];
|
|
3523
|
+
}
|
|
3524
|
+
});
|
|
3525
|
+
|
|
3526
|
+
// ../../packages/atom.io/dist/realtime-server/index.js
|
|
3527
|
+
var redactorAtoms = atomFamily({
|
|
3528
|
+
key: `redactor`,
|
|
3529
|
+
default: { occlude: (updates) => updates }
|
|
3530
|
+
});
|
|
3531
|
+
var unacknowledgedUpdatesAtoms = atomFamily({
|
|
3532
|
+
key: `unacknowledgedUpdates`,
|
|
3533
|
+
default: () => []
|
|
3534
|
+
});
|
|
3535
|
+
var CustomSocket = class {
|
|
3536
|
+
listeners;
|
|
3537
|
+
globalListeners;
|
|
3538
|
+
handleEvent(...args) {
|
|
3539
|
+
const [event, ...rest] = args;
|
|
3540
|
+
for (const listener of this.globalListeners)
|
|
3541
|
+
listener(event, ...rest);
|
|
3542
|
+
const listeners = this.listeners.get(event);
|
|
3543
|
+
if (listeners)
|
|
3544
|
+
for (const listener of listeners)
|
|
3545
|
+
listener(...rest);
|
|
3546
|
+
}
|
|
3547
|
+
id = `no_id_retrieved`;
|
|
3548
|
+
emit;
|
|
3549
|
+
constructor(emit) {
|
|
3550
|
+
this.emit = emit;
|
|
3551
|
+
this.listeners = /* @__PURE__ */ new Map;
|
|
3552
|
+
this.globalListeners = /* @__PURE__ */ new Set;
|
|
3553
|
+
}
|
|
3554
|
+
on(event, listener) {
|
|
3555
|
+
const listeners = this.listeners.get(event);
|
|
3556
|
+
if (listeners)
|
|
3557
|
+
listeners.add(listener);
|
|
3558
|
+
else
|
|
3559
|
+
this.listeners.set(event, new Set([listener]));
|
|
3560
|
+
return this;
|
|
3561
|
+
}
|
|
3562
|
+
onAny(listener) {
|
|
3563
|
+
this.globalListeners.add(listener);
|
|
3564
|
+
return this;
|
|
3565
|
+
}
|
|
3566
|
+
off(event, listener) {
|
|
3567
|
+
const listeners = this.listeners.get(event);
|
|
3568
|
+
if (listeners)
|
|
3569
|
+
if (listener)
|
|
3570
|
+
listeners.delete(listener);
|
|
3571
|
+
else
|
|
3572
|
+
this.listeners.delete(event);
|
|
3573
|
+
return this;
|
|
3574
|
+
}
|
|
3575
|
+
offAny(listener) {
|
|
3576
|
+
this.globalListeners.delete(listener);
|
|
3577
|
+
return this;
|
|
3578
|
+
}
|
|
3579
|
+
};
|
|
3580
|
+
var ChildSocket = class extends CustomSocket {
|
|
3581
|
+
incompleteData = ``;
|
|
3582
|
+
unprocessedEvents = [];
|
|
3583
|
+
incompleteLog = ``;
|
|
3584
|
+
unprocessedLogs = [];
|
|
3585
|
+
id = `#####`;
|
|
3586
|
+
proc;
|
|
3587
|
+
key;
|
|
3588
|
+
logger;
|
|
3589
|
+
handleLog(log) {
|
|
3590
|
+
if (Array.isArray(log)) {
|
|
3591
|
+
const [level, ...rest] = log;
|
|
3592
|
+
switch (level) {
|
|
3593
|
+
case `i`:
|
|
3594
|
+
this.logger.info(...rest);
|
|
3595
|
+
break;
|
|
3596
|
+
case `w`:
|
|
3597
|
+
this.logger.warn(...rest);
|
|
3598
|
+
break;
|
|
3599
|
+
case `e`:
|
|
3600
|
+
this.logger.error(...rest);
|
|
3601
|
+
break;
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
constructor(proc, key, logger) {
|
|
3606
|
+
super((event, ...args) => {
|
|
3607
|
+
const stringifiedEvent = JSON.stringify([event, ...args]) + `\x03`;
|
|
3608
|
+
const errorHandler = (err) => {
|
|
3609
|
+
if (err.code === `EPIPE`)
|
|
3610
|
+
console.error(`EPIPE error during write`, this.proc.stdin);
|
|
3611
|
+
this.proc.stdin.removeListener(`error`, errorHandler);
|
|
3612
|
+
};
|
|
3613
|
+
this.proc.stdin.once(`error`, errorHandler);
|
|
3614
|
+
this.proc.stdin.write(stringifiedEvent);
|
|
3615
|
+
return this;
|
|
3616
|
+
});
|
|
3617
|
+
this.proc = proc;
|
|
3618
|
+
this.key = key;
|
|
3619
|
+
this.logger = logger ?? {
|
|
3620
|
+
info: (...args) => {
|
|
3621
|
+
console.info(this.id, this.key, ...args);
|
|
3622
|
+
},
|
|
3623
|
+
warn: (...args) => {
|
|
3624
|
+
console.warn(this.id, this.key, ...args);
|
|
3625
|
+
},
|
|
3626
|
+
error: (...args) => {
|
|
3627
|
+
console.error(this.id, this.key, ...args);
|
|
3628
|
+
}
|
|
3629
|
+
};
|
|
3630
|
+
this.proc.stdout.on(`data`, (buffer) => {
|
|
3631
|
+
const chunk = buffer.toString();
|
|
3632
|
+
if (chunk === `ALIVE`) {
|
|
3633
|
+
this.logger.info(chunk);
|
|
3634
|
+
return;
|
|
3635
|
+
}
|
|
3636
|
+
const pieces = chunk.split(`\x03`);
|
|
3637
|
+
const initialMaybeWellFormed = pieces[0];
|
|
3638
|
+
pieces[0] = this.incompleteData + initialMaybeWellFormed;
|
|
3639
|
+
let idx = 0;
|
|
3640
|
+
for (const piece of pieces) {
|
|
3641
|
+
if (piece === ``)
|
|
3642
|
+
continue;
|
|
3643
|
+
try {
|
|
3644
|
+
const jsonPiece = parseJson(piece);
|
|
3645
|
+
this.handleEvent(...jsonPiece);
|
|
3646
|
+
this.incompleteData = ``;
|
|
3647
|
+
} catch (thrown0) {
|
|
3648
|
+
if (thrown0 instanceof Error)
|
|
3649
|
+
console.error([
|
|
3650
|
+
`\u274C Malformed data received from child process`,
|
|
3651
|
+
``,
|
|
3652
|
+
piece,
|
|
3653
|
+
``,
|
|
3654
|
+
thrown0.message
|
|
3655
|
+
].join(`
|
|
3656
|
+
\u274C `));
|
|
3657
|
+
try {
|
|
3658
|
+
if (idx === 0) {
|
|
3659
|
+
this.incompleteData = piece;
|
|
3660
|
+
const maybeActualJsonPiece = parseJson(initialMaybeWellFormed);
|
|
3661
|
+
this.handleEvent(...maybeActualJsonPiece);
|
|
3662
|
+
this.incompleteData = ``;
|
|
3663
|
+
} else
|
|
3664
|
+
this.incompleteData += piece;
|
|
3665
|
+
} catch (thrown1) {
|
|
3666
|
+
if (thrown1 instanceof Error)
|
|
3667
|
+
console.error([
|
|
3668
|
+
`\u274C Malformed data received from child process`,
|
|
3669
|
+
``,
|
|
3670
|
+
initialMaybeWellFormed,
|
|
3671
|
+
``,
|
|
3672
|
+
thrown1.message
|
|
3673
|
+
].join(`
|
|
3674
|
+
\u274C `));
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
++idx;
|
|
3678
|
+
}
|
|
3679
|
+
});
|
|
3680
|
+
this.proc.stderr.on(`data`, (buffer) => {
|
|
3681
|
+
const pieces = buffer.toString().split(`\x03`);
|
|
3682
|
+
const initialMaybeWellFormed = pieces[0];
|
|
3683
|
+
pieces[0] = this.incompleteData + initialMaybeWellFormed;
|
|
3684
|
+
let idx = 0;
|
|
3685
|
+
for (const piece of pieces) {
|
|
3686
|
+
if (piece === ``)
|
|
3687
|
+
continue;
|
|
3688
|
+
try {
|
|
3689
|
+
const jsonPiece = parseJson(piece);
|
|
3690
|
+
this.handleLog(jsonPiece);
|
|
3691
|
+
this.incompleteData = ``;
|
|
3692
|
+
} catch (thrown0) {
|
|
3693
|
+
if (thrown0 instanceof Error)
|
|
3694
|
+
console.error([
|
|
3695
|
+
`\u274C Malformed log received from child process`,
|
|
3696
|
+
``,
|
|
3697
|
+
piece,
|
|
3698
|
+
``,
|
|
3699
|
+
thrown0.message
|
|
3700
|
+
].join(`
|
|
3701
|
+
\u274C `));
|
|
3702
|
+
try {
|
|
3703
|
+
if (idx === 0) {
|
|
3704
|
+
this.incompleteData = piece;
|
|
3705
|
+
const maybeActualJsonPiece = parseJson(initialMaybeWellFormed);
|
|
3706
|
+
this.handleLog(maybeActualJsonPiece);
|
|
3707
|
+
this.incompleteData = ``;
|
|
3708
|
+
} else
|
|
3709
|
+
this.incompleteData += piece;
|
|
3710
|
+
} catch (thrown1) {
|
|
3711
|
+
if (thrown1 instanceof Error)
|
|
3712
|
+
console.error([
|
|
3713
|
+
`\u274C Malformed log received from child process...`,
|
|
3714
|
+
``,
|
|
3715
|
+
initialMaybeWellFormed,
|
|
3716
|
+
``,
|
|
3717
|
+
thrown1.message
|
|
3718
|
+
].join(`
|
|
3719
|
+
\u274C `));
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
++idx;
|
|
3723
|
+
}
|
|
3724
|
+
});
|
|
3725
|
+
if (proc.pid)
|
|
3726
|
+
this.id = proc.pid.toString();
|
|
3727
|
+
}
|
|
3728
|
+
};
|
|
3729
|
+
var SubjectSocket = class extends CustomSocket {
|
|
3730
|
+
in;
|
|
3731
|
+
out;
|
|
3732
|
+
id = `no_id_retrieved`;
|
|
3733
|
+
disposalFunctions = [];
|
|
3734
|
+
constructor(id) {
|
|
3735
|
+
super((...args) => {
|
|
3736
|
+
this.out.next(args);
|
|
3737
|
+
return this;
|
|
3738
|
+
});
|
|
3739
|
+
this.id = id;
|
|
3740
|
+
this.in = new Subject;
|
|
3741
|
+
this.out = new Subject;
|
|
3742
|
+
this.in.subscribe(`socket`, (event) => {
|
|
3743
|
+
this.handleEvent(...event);
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
dispose() {
|
|
3747
|
+
for (const dispose of this.disposalFunctions)
|
|
3748
|
+
dispose();
|
|
3749
|
+
}
|
|
3750
|
+
};
|
|
3751
|
+
var ParentSocket = class extends CustomSocket {
|
|
3752
|
+
incompleteData = ``;
|
|
3753
|
+
unprocessedEvents = [];
|
|
3754
|
+
relays;
|
|
3755
|
+
relayServices;
|
|
3756
|
+
proc;
|
|
3757
|
+
id = `#####`;
|
|
3758
|
+
log(...args) {
|
|
3759
|
+
this.proc.stderr.write(stringifyJson(args.map((arg) => arg instanceof UList ? `{ ${arg.toJSON().join(` | `)} }` : arg)) + `\x03`);
|
|
3760
|
+
}
|
|
3761
|
+
logger = {
|
|
3762
|
+
info: (...args) => {
|
|
3763
|
+
this.log(`i`, ...args);
|
|
3764
|
+
},
|
|
3765
|
+
warn: (...args) => {
|
|
3766
|
+
this.log(`w`, ...args);
|
|
3767
|
+
},
|
|
3768
|
+
error: (...args) => {
|
|
3769
|
+
this.log(`e`, ...args);
|
|
3770
|
+
}
|
|
3771
|
+
};
|
|
3772
|
+
constructor(proc) {
|
|
3773
|
+
super((event, ...args) => {
|
|
3774
|
+
const stringifiedEvent = JSON.stringify([event, ...args]);
|
|
3775
|
+
this.proc.stdout.write(stringifiedEvent + `\x03`);
|
|
3776
|
+
return this;
|
|
3777
|
+
});
|
|
3778
|
+
this.proc = proc;
|
|
3779
|
+
this.proc.stdin.resume();
|
|
3780
|
+
this.relays = /* @__PURE__ */ new Map;
|
|
3781
|
+
this.relayServices = [];
|
|
3782
|
+
this.proc.stdin.on(`data`, (buffer) => {
|
|
3783
|
+
const pieces = buffer.toString().split(`\x03`);
|
|
3784
|
+
const initialMaybeWellFormed = pieces[0];
|
|
3785
|
+
pieces[0] = this.incompleteData + initialMaybeWellFormed;
|
|
3786
|
+
let idx = 0;
|
|
3787
|
+
for (const piece of pieces) {
|
|
3788
|
+
if (piece === ``)
|
|
3789
|
+
continue;
|
|
3790
|
+
try {
|
|
3791
|
+
const jsonPiece = parseJson(piece);
|
|
3792
|
+
this.logger.info(`\uD83C\uDFB0`, `received`, jsonPiece);
|
|
3793
|
+
this.handleEvent(...jsonPiece);
|
|
3794
|
+
this.incompleteData = ``;
|
|
3795
|
+
} catch (thrown0) {
|
|
3796
|
+
if (thrown0 instanceof Error)
|
|
3797
|
+
this.logger.error([
|
|
3798
|
+
`received malformed data from parent process:`,
|
|
3799
|
+
``,
|
|
3800
|
+
piece,
|
|
3801
|
+
``,
|
|
3802
|
+
thrown0.message
|
|
3803
|
+
].join(`
|
|
3804
|
+
\u274C `));
|
|
3805
|
+
try {
|
|
3806
|
+
if (idx === 0) {
|
|
3807
|
+
this.incompleteData = piece;
|
|
3808
|
+
const maybeActualJsonPiece = parseJson(initialMaybeWellFormed);
|
|
3809
|
+
this.logger.info(`\uD83C\uDFB0`, `received`, maybeActualJsonPiece);
|
|
3810
|
+
this.handleEvent(...maybeActualJsonPiece);
|
|
3811
|
+
this.incompleteData = ``;
|
|
3812
|
+
} else
|
|
3813
|
+
this.incompleteData += piece;
|
|
3814
|
+
} catch (thrown1) {
|
|
3815
|
+
if (thrown1 instanceof Error)
|
|
3816
|
+
this.logger.error([
|
|
3817
|
+
`received malformed data from parent process:`,
|
|
3818
|
+
``,
|
|
3819
|
+
initialMaybeWellFormed,
|
|
3820
|
+
``,
|
|
3821
|
+
thrown1.message
|
|
3822
|
+
].join(`
|
|
3823
|
+
\u274C `));
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
++idx;
|
|
3827
|
+
}
|
|
3828
|
+
});
|
|
3829
|
+
this.on(`exit`, () => {
|
|
3830
|
+
this.logger.info(`\uD83D\uDD25`, this.id, `received "exit"`);
|
|
3831
|
+
this.proc.exit(0);
|
|
3832
|
+
});
|
|
3833
|
+
if (this.proc.pid)
|
|
3834
|
+
this.id = this.proc.pid?.toString();
|
|
3835
|
+
this.on(`user-joins`, (username) => {
|
|
3836
|
+
this.logger.info(`\uD83D\uDC64`, `user`, username, `joined`);
|
|
3837
|
+
const userKey = `user::${username}`;
|
|
3838
|
+
const relay = new SubjectSocket(userKey);
|
|
3839
|
+
this.relays.set(username, relay);
|
|
3840
|
+
this.logger.info(`\uD83D\uDD17`, `attaching services:`, `[${[...this.relayServices.keys()].join(`, `)}]`);
|
|
3841
|
+
for (const attachRelay of this.relayServices) {
|
|
3842
|
+
const cleanupRelay = attachRelay(relay, userKey);
|
|
3843
|
+
if (cleanupRelay)
|
|
3844
|
+
relay.disposalFunctions.push(cleanupRelay);
|
|
3845
|
+
}
|
|
3846
|
+
this.on(userKey, (...data) => {
|
|
3847
|
+
relay.in.next(data);
|
|
3848
|
+
});
|
|
3849
|
+
relay.out.subscribe(`socket`, (data) => {
|
|
3850
|
+
this.emit(...data);
|
|
3851
|
+
});
|
|
3852
|
+
});
|
|
3853
|
+
this.on(`user-leaves`, (username) => {
|
|
3854
|
+
const relay = this.relays.get(username);
|
|
3855
|
+
this.off(`relay:${username}`);
|
|
3856
|
+
if (relay) {
|
|
3857
|
+
relay.dispose();
|
|
3858
|
+
this.relays.delete(username);
|
|
3859
|
+
}
|
|
3860
|
+
});
|
|
3861
|
+
this.proc.stdout.write(`ALIVE`);
|
|
3862
|
+
}
|
|
3863
|
+
receiveRelay(attachServices) {
|
|
3864
|
+
this.logger.info(`\uD83D\uDD17`, `running relay method`);
|
|
3865
|
+
this.relayServices.push(attachServices);
|
|
3866
|
+
}
|
|
3867
|
+
};
|
|
3868
|
+
var ROOMS = /* @__PURE__ */ new Map;
|
|
3869
|
+
var joinRoomTX = transaction({
|
|
3870
|
+
key: `joinRoom`,
|
|
3871
|
+
do: (tools, roomId, userId, enteredAtEpoch) => {
|
|
3872
|
+
const meta = { enteredAtEpoch };
|
|
3873
|
+
editRelationsInStore(usersInRooms, (relations) => {
|
|
3874
|
+
relations.set({
|
|
3875
|
+
room: roomId,
|
|
3876
|
+
user: userId
|
|
3877
|
+
});
|
|
3878
|
+
}, tools.env().store);
|
|
3879
|
+
return meta;
|
|
3880
|
+
}
|
|
3881
|
+
});
|
|
3882
|
+
var leaveRoomTX = transaction({
|
|
3883
|
+
key: `leaveRoom`,
|
|
3884
|
+
do: ({ env }, roomId, userId) => {
|
|
3885
|
+
editRelationsInStore(usersInRooms, (relations) => {
|
|
3886
|
+
relations.delete({
|
|
3887
|
+
room: roomId,
|
|
3888
|
+
user: userId
|
|
3889
|
+
});
|
|
3890
|
+
}, env().store);
|
|
3891
|
+
}
|
|
3892
|
+
});
|
|
3893
|
+
var destroyRoomTX = transaction({
|
|
3894
|
+
key: `destroyRoom`,
|
|
3895
|
+
do: ({ set, env }, roomId) => {
|
|
3896
|
+
editRelationsInStore(usersInRooms, (relations) => {
|
|
3897
|
+
relations.delete({ room: roomId });
|
|
3898
|
+
}, env().store);
|
|
3899
|
+
set(roomIndex, (s) => (s.delete(roomId), s));
|
|
3900
|
+
const room = ROOMS.get(roomId);
|
|
3901
|
+
if (room) {
|
|
3902
|
+
room.emit(`exit`);
|
|
3903
|
+
ROOMS.delete(roomId);
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
});
|
|
3907
|
+
var socketAtoms = atomFamily({
|
|
3908
|
+
key: `sockets`,
|
|
3909
|
+
default: null
|
|
3910
|
+
});
|
|
3911
|
+
var socketIndex = mutableAtom({
|
|
3912
|
+
key: `socketsIndex`,
|
|
3913
|
+
class: UList
|
|
3914
|
+
});
|
|
3915
|
+
var userIndex = mutableAtom({
|
|
3916
|
+
key: `usersIndex`,
|
|
3917
|
+
class: UList
|
|
3918
|
+
});
|
|
3919
|
+
var usersOfSockets = join({
|
|
3920
|
+
key: `usersOfSockets`,
|
|
3921
|
+
between: [`user`, `socket`],
|
|
3922
|
+
cardinality: `1:1`,
|
|
3923
|
+
isAType: (s) => s.startsWith(`user::`),
|
|
3924
|
+
isBType: (s) => s.startsWith(`socket::`)
|
|
3925
|
+
});
|
|
3926
|
+
var userMutualSituationalAwarenessIndexes = selectorFamily({
|
|
3927
|
+
key: `userMutualSituationalAwarenessIndexes`,
|
|
3928
|
+
get: (userId) => () => {
|
|
3929
|
+
return [userId];
|
|
3930
|
+
}
|
|
3931
|
+
});
|
|
3932
|
+
|
|
3933
|
+
// src/backend.worker.game.bun.ts
|
|
3934
|
+
var parent = new ParentSocket(process);
|
|
3935
|
+
Object.assign(console, parent.logger, { log: parent.logger.info });
|
|
3936
|
+
parent.on(`timeToStop`, function gracefulExit() {
|
|
3937
|
+
parent.logger.info(`\uD83D\uDEEC game worker exiting`);
|
|
3938
|
+
process.exit(0);
|
|
3939
|
+
});
|
|
3940
|
+
parent.logger.info(`\uD83D\uDEEB game worker ready`);
|