atom.io 0.30.0 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,20 +22,24 @@ declare function counterfeit<T, K extends Canonical, Key extends K>(token: Writa
22
22
  declare function counterfeit<T, K extends Canonical, Key extends K>(token: ReadableFamilyToken<T, K>, key: Key): ReadableToken<T>;
23
23
  declare function counterfeit<M extends MoleculeConstructor>(token: MoleculeFamilyToken<M>, key: MoleculeKey<M>): MoleculeKey<M>;
24
24
 
25
- interface JunctionEntries<Content extends Json.Object | null> extends Json.Object {
26
- readonly relations: [string, string[]][];
25
+ type JunctionEntriesBase<AType extends string, BType extends string, Content extends Json.Object | null> = {
26
+ readonly relations: ([AType, BType[]] | [BType, AType[]])[];
27
27
  readonly contents: [string, Content][];
28
+ };
29
+ interface JunctionEntries<AType extends string, BType extends string, Content extends Json.Object | null> extends Json.Object, JunctionEntriesBase<AType, BType, Content> {
28
30
  }
29
- interface JunctionSchema<ASide extends string, BSide extends string> extends Json.Object {
31
+ type JunctionSchemaBase<ASide extends string, BSide extends string> = {
30
32
  readonly between: [a: ASide, b: BSide];
31
33
  readonly cardinality: `1:1` | `1:n` | `n:n`;
34
+ };
35
+ interface JunctionSchema<ASide extends string, BSide extends string> extends Json.Object, JunctionSchemaBase<ASide, BSide> {
32
36
  }
33
37
  type BaseExternalStoreConfiguration = {
34
38
  addRelation: (a: string, b: string) => void;
35
39
  deleteRelation: (a: string, b: string) => void;
36
40
  replaceRelationsSafely: (a: string, bs: string[]) => void;
37
41
  replaceRelationsUnsafely: (a: string, bs: string[]) => void;
38
- getRelatedKeys: (key: string) => Set<string> | undefined;
42
+ getRelatedKeys(key: string): Set<string> | undefined;
39
43
  has: (a: string, b?: string) => boolean;
40
44
  };
41
45
  type ExternalStoreWithContentConfiguration<Content extends Json.Object> = {
@@ -47,45 +51,68 @@ type Empty<Obj extends object> = {
47
51
  [Key in keyof Obj]?: undefined;
48
52
  };
49
53
  type ExternalStoreConfiguration<Content extends Json.Object | null> = Content extends Json.Object ? BaseExternalStoreConfiguration & ExternalStoreWithContentConfiguration<Content> : BaseExternalStoreConfiguration & Empty<ExternalStoreWithContentConfiguration<Json.Object>>;
50
- type JunctionAdvancedConfiguration<Content extends Json.Object | null> = {
54
+ type JunctionAdvancedConfiguration<AType extends string, BType extends string, Content extends Json.Object | null> = {
51
55
  warn?: (...args: any[]) => void;
52
56
  externalStore?: ExternalStoreConfiguration<Content>;
57
+ isAType?: Refinement<string, AType>;
58
+ isBType?: Refinement<string, BType>;
53
59
  isContent?: Refinement<unknown, Content>;
54
- makeContentKey?: (a: string, b: string) => string;
60
+ makeContentKey?: (a: AType, b: BType) => string;
55
61
  };
56
- type JunctionJSON<ASide extends string, BSide extends string, Content extends Json.Object | null> = JunctionEntries<Content> & JunctionSchema<ASide, BSide>;
57
- declare class Junction<const ASide extends string, const BSide extends string, const Content extends Json.Object | null = null> {
62
+ type JunctionJSON<ASide extends string, AType extends string, BSide extends string, BType extends string, Content extends Json.Object | null> = JunctionEntries<AType, BType, Content> & JunctionSchema<ASide, BSide>;
63
+ declare class Junction<const ASide extends string, const AType extends string, const BSide extends string, const BType extends string, const Content extends Json.Object | null = null> {
58
64
  readonly a: ASide;
59
65
  readonly b: BSide;
60
66
  readonly cardinality: `1:1` | `1:n` | `n:n`;
61
- readonly relations: Map<string, Set<string>>;
67
+ readonly relations: Map<AType | BType, Set<AType> | Set<BType>>;
62
68
  readonly contents: Map<string, Content>;
63
69
  isContent: Refinement<unknown, Content> | null;
64
- makeContentKey: (a: string, b: string) => string;
70
+ makeContentKey: (a: AType, b: BType) => string;
65
71
  warn?: (...args: any[]) => void;
66
- getRelatedKeys(key: string): Set<string> | undefined;
67
- protected addRelation(a: string, b: string): void;
68
- protected deleteRelation(a: string, b: string): void;
69
- protected replaceRelationsUnsafely(a: string, bs: string[]): void;
70
- protected replaceRelationsSafely(a: string, bs: string[]): void;
72
+ getRelatedKeys(key: AType): Set<BType> | undefined;
73
+ getRelatedKeys(key: BType): Set<AType> | undefined;
74
+ getRelatedKeys(key: AType | BType): Set<AType> | Set<BType> | undefined;
75
+ protected addRelation(a: AType, b: BType): void;
76
+ protected deleteRelation(a: AType, b: BType): void;
77
+ protected replaceRelationsUnsafely(a: AType, bs: BType[]): void;
78
+ protected replaceRelationsUnsafely(b: BType, as: AType[]): void;
79
+ protected replaceRelationsSafely(a: AType, bs: BType[]): void;
80
+ protected replaceRelationsSafely(b: BType, as: AType[]): void;
71
81
  protected getContentInternal(contentKey: string): Content | undefined;
72
82
  protected setContent(contentKey: string, content: Content): void;
73
83
  protected deleteContent(contentKey: string): void;
74
- constructor(data: JunctionSchema<ASide, BSide> & Partial<JunctionEntries<Content>>, config?: JunctionAdvancedConfiguration<Content>);
75
- toJSON(): JunctionJSON<ASide, BSide, Content>;
76
- set(a: string, ...rest: Content extends null ? [b: string] : [b: string, content: Content]): this;
84
+ constructor(data: JunctionSchema<ASide, BSide> & Partial<JunctionEntries<AType, BType, Content>>, config?: JunctionAdvancedConfiguration<AType, BType, Content>);
85
+ toJSON(): JunctionJSON<ASide, AType, BSide, BType, Content>;
86
+ set(a: AType, ...rest: Content extends null ? [b: BType] : [b: BType, content: Content]): this;
77
87
  set(relation: {
78
- [Key in ASide | BSide]: string;
79
- }, ...rest: Content extends null ? [] | [b?: undefined] : [content: Content]): this;
80
- delete(a: string, b?: string): this;
81
- delete(relation: Record<ASide | BSide, string> | Record<ASide, string> | Record<BSide, string>, b?: undefined): this;
82
- getRelatedKey(key: string): string | undefined;
83
- replaceRelations(a: string, relations: Content extends null ? string[] : Record<string, Content>, config?: {
88
+ [Key in ASide]: AType;
89
+ } & {
90
+ [Key in BSide]: BType;
91
+ }, ...rest: Content extends null ? [] | [void?: undefined] : [content: Content]): this;
92
+ delete(a: AType, b?: BType): this;
93
+ delete(b: BType, a?: AType): this;
94
+ delete(relation: {
95
+ [Key in ASide]: AType;
96
+ } | {
97
+ [Key in BSide]: BType;
98
+ } | ({
99
+ [Key in ASide]: AType;
100
+ } & {
101
+ [Key in BSide]: BType;
102
+ }), b?: undefined): this;
103
+ getRelatedKey(key: AType): BType | undefined;
104
+ getRelatedKey(key: BType): AType | undefined;
105
+ replaceRelations(a: AType, relations: Content extends null ? BType[] : Record<BType, Content>, config?: {
106
+ reckless: boolean;
107
+ }): this;
108
+ replaceRelations(b: BType, relations: Content extends null ? AType[] : Record<AType, Content>, config?: {
84
109
  reckless: boolean;
85
110
  }): this;
86
- getContent(a: string, b: string): Content | undefined;
87
- getRelationEntries(input: Record<ASide, string> | Record<BSide, string>): [string, Content][];
88
- has(a: string, b?: string): boolean;
111
+ getContent(a: AType, b: BType): Content | undefined;
112
+ getRelationEntries(input: Record<ASide, AType>): [BType, Content][];
113
+ getRelationEntries(input: Record<BSide, BType>): [AType, Content][];
114
+ has(a: AType, b?: BType): boolean;
115
+ has(b: BType, a?: AType): boolean;
89
116
  }
90
117
 
91
118
  type Func = (...parameters: any[]) => any;
@@ -163,7 +190,7 @@ type TransactionProgress<F extends Func> = {
163
190
  };
164
191
  type TransactionEpoch = {
165
192
  epoch: Map<string, number>;
166
- actionContinuities: Junction<`continuity`, `action`>;
193
+ actionContinuities: Junction<`continuity`, string, `action`, string>;
167
194
  };
168
195
 
169
196
  declare function deposit<T>(state: RegularAtom<T>): RegularAtomToken<T>;
@@ -210,7 +237,7 @@ declare class Molecule<M extends MoleculeConstructor> implements MoleculeToken<M
210
237
  tokens: Map<string, ReadableToken<any>>;
211
238
  above: Map<string, Molecule<any>>;
212
239
  below: Map<string, Molecule<any>>;
213
- joins: Map<string, Join<any, any, any, any>>;
240
+ joins: Map<string, Join<any, any, any, any, any, any>>;
214
241
  instance: InstanceType<M>;
215
242
  constructor(ctx: Molecule<any>[] | undefined, key: MoleculeKey<M>, family?: MoleculeFamilyToken<M>);
216
243
  }
@@ -306,8 +333,8 @@ declare class Store implements Lineage {
306
333
  selectors: Map<string, WritableSelector<any>>;
307
334
  readonlySelectors: Map<string, ReadonlySelector<any>>;
308
335
  atomsThatAreDefault: Set<string>;
309
- selectorAtoms: Junction<"selectorKey", "atomKey", null>;
310
- selectorGraph: Junction<"upstreamSelectorKey", "downstreamSelectorKey", {
336
+ selectorAtoms: Junction<"selectorKey", string, "atomKey", string, null>;
337
+ selectorGraph: Junction<"upstreamSelectorKey", string, "downstreamSelectorKey", string, {
311
338
  source: string;
312
339
  }>;
313
340
  trackers: Map<string, Tracker<Transceiver<any>>>;
@@ -315,7 +342,7 @@ declare class Store implements Lineage {
315
342
  transactions: Map<string, Transaction<Func>>;
316
343
  transactionMeta: TransactionEpoch | TransactionProgress<Func>;
317
344
  timelines: Map<string, Timeline<any>>;
318
- timelineTopics: Junction<"timelineKey", "topicKey", {
345
+ timelineTopics: Junction<"timelineKey", string, "topicKey", string, {
319
346
  topicType: `atom_family` | `atom` | `molecule_family` | `molecule`;
320
347
  }>;
321
348
  disposalTraces: CircularBuffer<{
@@ -393,9 +420,9 @@ type Signal<TVR extends Transceiver<any>> = TVR extends Transceiver<infer S> ? S
393
420
 
394
421
  declare function createMutableAtom<T extends Transceiver<any>, J extends Json.Serializable>(store: Store, options: MutableAtomOptions<T, J>, family: FamilyMetadata | undefined): MutableAtomToken<T, J>;
395
422
 
396
- declare function createMutableAtomFamily<T extends Transceiver<any>, J extends Json.Serializable, K extends string>(store: Store, options: MutableAtomFamilyOptions<T, J, K>, internalRoles?: string[]): MutableAtomFamilyToken<T, J, K>;
423
+ declare function createMutableAtomFamily<T extends Transceiver<any>, J extends Json.Serializable, K extends Canonical>(store: Store, options: MutableAtomFamilyOptions<T, J, K>, internalRoles?: string[]): MutableAtomFamilyToken<T, J, K>;
397
424
 
398
- declare const getJsonFamily: <Core extends Transceiver<Json.Serializable>, SerializableCore extends Json.Serializable, Key extends string>(mutableAtomFamily: MutableAtomFamilyToken<Core, SerializableCore, Key>, store: Store) => WritableSelectorFamily<SerializableCore, Key>;
425
+ declare const getJsonFamily: <Core extends Transceiver<Json.Serializable>, SerializableCore extends Json.Serializable, Key extends Canonical>(mutableAtomFamily: MutableAtomFamilyToken<Core, SerializableCore, Key>, store: Store) => WritableSelectorFamily<SerializableCore, Key>;
399
426
 
400
427
  declare const getJsonToken: <Core extends Transceiver<any>, SerializableCore extends Json.Serializable>(store: Store, mutableAtomToken: MutableAtomToken<Core, SerializableCore>) => WritableSelectorToken<SerializableCore>;
401
428
 
@@ -672,4 +699,4 @@ type SelectorFamily<T, K extends Canonical> = ReadonlySelectorFamily<T, K> | Wri
672
699
  type WritableFamily<T, K extends Canonical> = AtomFamily<T, K> | WritableSelectorFamily<T, K>;
673
700
  type ReadableFamily<T, K extends Canonical> = AtomFamily<T, K> | SelectorFamily<T, K>;
674
701
 
675
- export { type Atom, type AtomFamily, type AtomIOState, type AtomIOToken, type AtomKey, type BaseExternalStoreConfiguration, type ChildStore, type Count, type Each, type Empty, type EnvironmentData, type ExternalStoreConfiguration, type ExternalStoreWithContentConfiguration, FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, type Flat, type Func, Future, IMPLICIT, Junction, type JunctionAdvancedConfiguration, type JunctionEntries, type JunctionJSON, type JunctionSchema, LazyMap, type Lineage, type Modify, Molecule, type MutableAtom, type MutableAtomFamily, NotFoundError, type OperationProgress, type ReadableFamily, type ReadableState, type ReadonlySelector, type ReadonlySelectorFamily, type ReadonlySelectorKey, type RegularAtom, type RegularAtomFamily, type RootStore, type Selector, type SelectorFamily, type SelectorKey, type Signal, type StateKey, StatefulSubject, Store, Subject, TRANSACTION_PHASES, type Timeline, type TimelineAtomUpdate, type TimelineMoleculeCreation, type TimelineMoleculeDisposal, type TimelineSelectorUpdate, type TimelineStateCreation, type TimelineStateDisposal, type TimelineTransactionUpdate, Tracker, type Transaction, type TransactionEpoch, type TransactionPhase, type TransactionProgress, type Transceiver, type TransceiverMode, type Withdrawable, type WritableFamily, type WritableSelector, type WritableSelectorFamily, type WritableState, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, counterfeit, createAtomFamily, createMoleculeFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom, disposeFromStore, disposeMolecule, disposeSelector, eldest, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateFamily, getUpdateToken, growMoleculeInStore, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeMoleculeInStore, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, recallState, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw };
702
+ export { type Atom, type AtomFamily, type AtomIOState, type AtomIOToken, type AtomKey, type BaseExternalStoreConfiguration, type ChildStore, type Count, type Each, type Empty, type EnvironmentData, type ExternalStoreConfiguration, type ExternalStoreWithContentConfiguration, FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, type Flat, type Func, Future, IMPLICIT, Junction, type JunctionAdvancedConfiguration, type JunctionEntries, type JunctionEntriesBase, type JunctionJSON, type JunctionSchema, type JunctionSchemaBase, LazyMap, type Lineage, type Modify, Molecule, type MutableAtom, type MutableAtomFamily, NotFoundError, type OperationProgress, type ReadableFamily, type ReadableState, type ReadonlySelector, type ReadonlySelectorFamily, type ReadonlySelectorKey, type RegularAtom, type RegularAtomFamily, type RootStore, type Selector, type SelectorFamily, type SelectorKey, type Signal, type StateKey, StatefulSubject, Store, Subject, TRANSACTION_PHASES, type Timeline, type TimelineAtomUpdate, type TimelineMoleculeCreation, type TimelineMoleculeDisposal, type TimelineSelectorUpdate, type TimelineStateCreation, type TimelineStateDisposal, type TimelineTransactionUpdate, Tracker, type Transaction, type TransactionEpoch, type TransactionPhase, type TransactionProgress, type Transceiver, type TransceiverMode, type Withdrawable, type WritableFamily, type WritableSelector, type WritableSelectorFamily, type WritableState, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, counterfeit, createAtomFamily, createMoleculeFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom, disposeFromStore, disposeMolecule, disposeSelector, eldest, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateFamily, getUpdateToken, growMoleculeInStore, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeMoleculeInStore, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, recallState, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw };
@@ -1,3 +1,3 @@
1
- export { FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, Junction, LazyMap, Molecule, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, counterfeit, createAtomFamily, createMoleculeFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom, disposeFromStore, disposeMolecule, disposeSelector, eldest, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateFamily, getUpdateToken, growMoleculeInStore, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeMoleculeInStore, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, recallState, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw } from '../../dist/chunk-7PUUHSXC.js';
2
- import '../../dist/chunk-ZKG6ZA4I.js';
1
+ export { FAMILY_MEMBER_TOKEN_TYPES, FamilyTracker, Future, IMPLICIT, Junction, LazyMap, Molecule, NotFoundError, StatefulSubject, Store, Subject, TRANSACTION_PHASES, Tracker, abortTransaction, actUponStore, applyTransaction, arbitrary, assignTransactionToContinuity, become, buildTransaction, cacheValue, clearStore, closeOperation, counterfeit, createAtomFamily, createMoleculeFamily, createMutableAtom, createMutableAtomFamily, createReadonlySelector, createReadonlySelectorFamily, createRegularAtom, createRegularAtomFamily, createSelectorFamily, createStandaloneAtom, createStandaloneSelector, createTimeline, createTransaction, createWritableSelector, deposit, disposeAtom, disposeFromStore, disposeMolecule, disposeSelector, eldest, evictCachedValue, findInStore, getContinuityKey, getEnvironmentData, getEpochNumberOfAction, getEpochNumberOfContinuity, getFromStore, getJsonFamily, getJsonToken, getSelectorDependencyKeys, getUpdateFamily, getUpdateToken, growMoleculeInStore, ingestAtomUpdate, ingestCreationEvent, ingestDisposalEvent, ingestMoleculeCreationEvent, ingestMoleculeDisposalEvent, ingestSelectorUpdate, ingestTransactionUpdate, initFamilyMemberInStore, isAtomDefault, isAtomKey, isChildStore, isDone, isReadonlySelectorKey, isRootStore, isSelectorKey, isStateKey, isTransceiver, makeMoleculeInStore, markAtomAsDefault, markAtomAsNotDefault, markDone, newest, openOperation, prettyPrintTokenType, readCachedValue, readOrComputeValue, recallState, registerSelector, seekInStore, setAtomOrSelector, setEpochNumberOfAction, setEpochNumberOfContinuity, setIntoStore, subscribeInStore, subscribeToRootAtoms, subscribeToState, subscribeToTimeline, subscribeToTransaction, timeTravel, traceAllSelectorAtoms, traceSelectorAtoms, updateSelectorAtoms, withdraw } from '../../dist/chunk-SMKF3ZNG.js';
2
+ import '../../dist/chunk-ADMEAXYU.js';
3
3
  import '../../dist/chunk-XWL6SNVU.js';
@@ -1,23 +1,36 @@
1
1
  import type { Refinement } from "atom.io/introspection"
2
2
  import type { Json } from "atom.io/json"
3
+ import { B } from "vitest/dist/chunks/benchmark.JVlTzojj.js"
3
4
 
4
- export interface JunctionEntries<Content extends Json.Object | null>
5
- extends Json.Object {
6
- readonly relations: [string, string[]][]
5
+ export type JunctionEntriesBase<
6
+ AType extends string,
7
+ BType extends string,
8
+ Content extends Json.Object | null,
9
+ > = {
10
+ readonly relations: ([AType, BType[]] | [BType, AType[]])[]
7
11
  readonly contents: [string, Content][]
8
12
  }
9
- export interface JunctionSchema<ASide extends string, BSide extends string>
10
- extends Json.Object {
13
+ export interface JunctionEntries<
14
+ AType extends string,
15
+ BType extends string,
16
+ Content extends Json.Object | null,
17
+ > extends Json.Object,
18
+ JunctionEntriesBase<AType, BType, Content> {}
19
+
20
+ export type JunctionSchemaBase<ASide extends string, BSide extends string> = {
11
21
  readonly between: [a: ASide, b: BSide]
12
22
  readonly cardinality: `1:1` | `1:n` | `n:n`
13
23
  }
24
+ export interface JunctionSchema<ASide extends string, BSide extends string>
25
+ extends Json.Object,
26
+ JunctionSchemaBase<ASide, BSide> {}
14
27
 
15
28
  export type BaseExternalStoreConfiguration = {
16
29
  addRelation: (a: string, b: string) => void
17
30
  deleteRelation: (a: string, b: string) => void
18
31
  replaceRelationsSafely: (a: string, bs: string[]) => void
19
32
  replaceRelationsUnsafely: (a: string, bs: string[]) => void
20
- getRelatedKeys: (key: string) => Set<string> | undefined
33
+ getRelatedKeys(key: string): Set<string> | undefined
21
34
  has: (a: string, b?: string) => boolean
22
35
  }
23
36
 
@@ -39,41 +52,56 @@ export type ExternalStoreConfiguration<Content extends Json.Object | null> =
39
52
  : BaseExternalStoreConfiguration &
40
53
  Empty<ExternalStoreWithContentConfiguration<Json.Object>>
41
54
 
42
- export type JunctionAdvancedConfiguration<Content extends Json.Object | null> = {
55
+ export type JunctionAdvancedConfiguration<
56
+ AType extends string,
57
+ BType extends string,
58
+ Content extends Json.Object | null,
59
+ > = {
43
60
  warn?: (...args: any[]) => void
44
61
  externalStore?: ExternalStoreConfiguration<Content>
62
+ isAType?: Refinement<string, AType>
63
+ isBType?: Refinement<string, BType>
45
64
  isContent?: Refinement<unknown, Content>
46
- makeContentKey?: (a: string, b: string) => string
65
+ makeContentKey?: (a: AType, b: BType) => string
47
66
  }
48
67
 
49
68
  export type JunctionJSON<
50
69
  ASide extends string,
70
+ AType extends string,
51
71
  BSide extends string,
72
+ BType extends string,
52
73
  Content extends Json.Object | null,
53
- > = JunctionEntries<Content> & JunctionSchema<ASide, BSide>
74
+ > = JunctionEntries<AType, BType, Content> & JunctionSchema<ASide, BSide>
54
75
 
55
76
  export class Junction<
56
77
  const ASide extends string,
78
+ const AType extends string,
57
79
  const BSide extends string,
80
+ const BType extends string,
58
81
  const Content extends Json.Object | null = null,
59
82
  > {
60
83
  public readonly a: ASide
61
84
  public readonly b: BSide
62
85
  public readonly cardinality: `1:1` | `1:n` | `n:n`
63
- public readonly relations = new Map<string, Set<string>>()
86
+ public readonly relations = new Map<AType | BType, Set<AType> | Set<BType>>()
64
87
  public readonly contents = new Map<string, Content>()
65
88
 
66
89
  public isContent: Refinement<unknown, Content> | null
67
- public makeContentKey = (a: string, b: string): string => `${a}:${b}`
90
+ public makeContentKey = (a: AType, b: BType): string => `${a}:${b}`
68
91
 
69
92
  public warn?: (...args: any[]) => void
70
93
 
71
- public getRelatedKeys(key: string): Set<string> | undefined {
94
+ public getRelatedKeys(key: AType): Set<BType> | undefined
95
+ public getRelatedKeys(key: BType): Set<AType> | undefined
96
+ public getRelatedKeys(key: AType | BType): Set<AType> | Set<BType> | undefined
97
+ public getRelatedKeys(
98
+ key: AType | BType,
99
+ ): Set<AType> | Set<BType> | undefined {
72
100
  return this.relations.get(key)
73
101
  }
74
- protected addRelation(a: string, b: string): void {
75
- let aRelations = this.relations.get(a)
76
- let bRelations = this.relations.get(b)
102
+ protected addRelation(a: AType, b: BType): void {
103
+ let aRelations = this.relations.get(a) as Set<BType> | undefined
104
+ let bRelations = this.relations.get(b) as Set<AType> | undefined
77
105
  if (aRelations) {
78
106
  aRelations.add(b)
79
107
  } else {
@@ -87,14 +115,14 @@ export class Junction<
87
115
  this.relations.set(b, bRelations)
88
116
  }
89
117
  }
90
- protected deleteRelation(a: string, b: string): void {
91
- const aRelations = this.relations.get(a)
118
+ protected deleteRelation(a: AType, b: BType): void {
119
+ const aRelations = this.relations.get(a) as Set<BType> | undefined
92
120
  if (aRelations) {
93
121
  aRelations.delete(b)
94
122
  if (aRelations.size === 0) {
95
123
  this.relations.delete(a)
96
124
  }
97
- const bRelations = this.relations.get(b)
125
+ const bRelations = this.relations.get(b) as Set<AType> | undefined
98
126
  if (bRelations) {
99
127
  bRelations.delete(a)
100
128
  if (bRelations.size === 0) {
@@ -104,36 +132,46 @@ export class Junction<
104
132
  }
105
133
  }
106
134
 
107
- protected replaceRelationsUnsafely(a: string, bs: string[]): void {
108
- this.relations.set(a, new Set(bs))
109
- for (const b of bs) {
110
- const bRelations = new Set([a])
111
- this.relations.set(b, bRelations)
135
+ protected replaceRelationsUnsafely(a: AType, bs: BType[]): void
136
+ protected replaceRelationsUnsafely(b: BType, as: AType[]): void
137
+ protected replaceRelationsUnsafely(
138
+ x: AType | BType,
139
+ ys: AType[] | BType[],
140
+ ): void {
141
+ this.relations.set(x as AType, new Set(ys as BType[]))
142
+ for (const y of ys) {
143
+ const yRelations = new Set<AType>().add(x as AType)
144
+ this.relations.set(y, yRelations)
112
145
  }
113
146
  }
114
- protected replaceRelationsSafely(a: string, bs: string[]): void {
115
- const aRelationsPrev = this.relations.get(a)
116
- if (aRelationsPrev) {
117
- for (const b of aRelationsPrev) {
118
- const bRelations = this.relations.get(b)
119
- if (bRelations) {
120
- if (bRelations.size === 1) {
121
- this.relations.delete(b)
147
+ protected replaceRelationsSafely(a: AType, bs: BType[]): void
148
+ protected replaceRelationsSafely(b: BType, as: AType[]): void
149
+ protected replaceRelationsSafely<
150
+ XType extends AType | BType,
151
+ YType extends XType extends AType ? BType : AType,
152
+ >(x: XType, ys: YType[]): void {
153
+ const xRelationsPrev = this.relations.get(x)
154
+ if (xRelationsPrev) {
155
+ for (const y of xRelationsPrev) {
156
+ const yRelations = this.relations.get(y) as Set<XType> | undefined
157
+ if (yRelations) {
158
+ if (yRelations.size === 1) {
159
+ this.relations.delete(y)
122
160
  } else {
123
- bRelations.delete(a)
161
+ yRelations.delete(x)
124
162
  }
125
- this.contents.delete(this.makeContentKey(a, b))
163
+ this.contents.delete(this.makeContentKey(x as any, y as any)) // sort XY to AB ❗
126
164
  }
127
165
  }
128
166
  }
129
- this.relations.set(a, new Set(bs))
130
- for (const b of bs) {
131
- let bRelations = this.relations.get(b)
132
- if (bRelations) {
133
- bRelations.add(a)
167
+ this.relations.set(x, new Set(ys) as any)
168
+ for (const y of ys) {
169
+ let yRelations = this.relations.get(y) as Set<XType> | undefined
170
+ if (yRelations) {
171
+ yRelations.add(x)
134
172
  } else {
135
- bRelations = new Set([a])
136
- this.relations.set(b, bRelations)
173
+ yRelations = new Set<XType>().add(x)
174
+ this.relations.set(y, yRelations as any)
137
175
  }
138
176
  }
139
177
  }
@@ -149,15 +187,18 @@ export class Junction<
149
187
  }
150
188
 
151
189
  public constructor(
152
- data: JunctionSchema<ASide, BSide> & Partial<JunctionEntries<Content>>,
153
- config?: JunctionAdvancedConfiguration<Content>,
190
+ data: JunctionSchema<ASide, BSide> &
191
+ Partial<JunctionEntries<AType, BType, Content>>,
192
+ config?: JunctionAdvancedConfiguration<AType, BType, Content>,
154
193
  ) {
155
194
  this.a = data.between[0]
156
195
  this.b = data.between[1]
157
196
 
158
197
  this.cardinality = data.cardinality
159
198
  if (!config?.externalStore) {
160
- this.relations = new Map(data.relations?.map(([a, b]) => [a, new Set(b)]))
199
+ this.relations = new Map(
200
+ data.relations?.map(([x, ys]) => [x, new Set(ys as AType[])]),
201
+ )
161
202
  this.contents = new Map(data.contents)
162
203
  }
163
204
  this.isContent = config?.isContent ?? null
@@ -179,7 +220,10 @@ export class Junction<
179
220
  this.replaceRelationsUnsafely = (a, bs) => {
180
221
  externalStore.replaceRelationsUnsafely(a, bs)
181
222
  }
182
- this.getRelatedKeys = (key) => externalStore.getRelatedKeys(key)
223
+ this.getRelatedKeys = ((key) =>
224
+ externalStore.getRelatedKeys(
225
+ key,
226
+ )) as typeof Junction.prototype.getRelatedKeys
183
227
  if (externalStore.getContent) {
184
228
  this.getContentInternal = (contentKey) => {
185
229
  return externalStore.getContent(contentKey) as any
@@ -192,7 +236,7 @@ export class Junction<
192
236
  }
193
237
  }
194
238
  for (const [x, ys] of data.relations ?? []) {
195
- for (const y of ys) this.addRelation(x, y)
239
+ for (const y of ys) this.addRelation(x as AType, y as BType) // sort XY to AB ❗
196
240
  }
197
241
  for (const [contentKey, content] of data.contents ?? []) {
198
242
  this.setContent(contentKey, content)
@@ -202,33 +246,35 @@ export class Junction<
202
246
  this.warn = config.warn
203
247
  }
204
248
  }
205
- public toJSON(): JunctionJSON<ASide, BSide, Content> {
249
+ public toJSON(): JunctionJSON<ASide, AType, BSide, BType, Content> {
206
250
  return {
207
251
  between: [this.a, this.b],
208
252
  cardinality: this.cardinality,
209
- relations: [...this.relations.entries()].map(([a, b]) => [a, [...b]]),
253
+ relations: [...this.relations.entries()].map(
254
+ ([a, b]) => [a, [...b]] as [AType, BType[]],
255
+ ),
210
256
  contents: [...this.contents.entries()],
211
257
  }
212
258
  }
213
259
 
214
260
  public set(
215
- a: string,
216
- ...rest: Content extends null ? [b: string] : [b: string, content: Content]
261
+ a: AType,
262
+ ...rest: Content extends null ? [b: BType] : [b: BType, content: Content]
217
263
  ): this
218
264
  public set(
219
- relation: { [Key in ASide | BSide]: string },
220
- ...rest: Content extends null ? [] | [b?: undefined] : [content: Content]
265
+ relation: { [Key in ASide]: AType } & { [Key in BSide]: BType },
266
+ ...rest: Content extends null ? [] | [void?: undefined] : [content: Content]
221
267
  ): this
222
268
  public set(
223
- a: string | { [Key in ASide | BSide]: string },
269
+ a: AType | ({ [Key in ASide]: AType } & { [Key in BSide]: BType }),
224
270
  ...rest: Content extends null
225
- ? [] | [b?: string | undefined]
226
- : [b: string, content: Content] | [content: Content]
271
+ ? [] | [b?: BType | undefined]
272
+ : [b: BType, content: Content] | [content: Content]
227
273
  ): this {
228
- const b: string =
274
+ const b: BType =
229
275
  typeof rest[0] === `string`
230
276
  ? rest[0]
231
- : (a[this.b as keyof typeof a] as string)
277
+ : (a[this.b as keyof typeof a] as BType)
232
278
  const content: Content | undefined =
233
279
  (rest[1] ?? typeof rest[0] === `string`) ? undefined : (rest[0] as Content)
234
280
  a = typeof a === `string` ? a : a[this.a]
@@ -236,7 +282,7 @@ export class Junction<
236
282
  // biome-ignore lint/suspicious/noFallthroughSwitchClause: perfect here
237
283
  case `1:1`: {
238
284
  const bPrev = this.getRelatedKey(a)
239
- if (bPrev && bPrev !== b) this.delete(bPrev, a)
285
+ if (bPrev && bPrev !== b) this.delete(a, bPrev)
240
286
  }
241
287
  case `1:n`: {
242
288
  const aPrev = this.getRelatedKey(b)
@@ -251,29 +297,32 @@ export class Junction<
251
297
  return this
252
298
  }
253
299
 
254
- public delete(a: string, b?: string): this
300
+ public delete(a: AType, b?: BType): this
301
+ public delete(b: BType, a?: AType): this
255
302
  public delete(
256
303
  relation:
257
- | Record<ASide | BSide, string>
258
- | Record<ASide, string>
259
- | Record<BSide, string>,
304
+ | { [Key in ASide]: AType }
305
+ | { [Key in BSide]: BType }
306
+ | ({ [Key in ASide]: AType } & { [Key in BSide]: BType }),
260
307
  b?: undefined,
261
308
  ): this
262
309
  public delete(
263
310
  x:
311
+ | AType
312
+ | BType
264
313
  | Record<ASide | BSide, string>
265
314
  | Record<ASide, string>
266
- | Record<BSide, string>
267
- | string,
268
- b?: string,
315
+ | Record<BSide, string>,
316
+ b?: AType | BType,
269
317
  ): this {
270
318
  // @ts-expect-error we deduce that this.b may index x
271
- b = typeof b === `string` ? b : (x[this.b] as string | undefined)
272
- // @ts-expect-error we deduce that this.a may index x
273
- const a = typeof x === `string` ? x : (x[this.a] as string | undefined)
319
+ b = typeof b === `string` ? (b as BType) : (x[this.b] as BType | undefined)
320
+ const a =
321
+ // @ts-expect-error we deduce that this.a may index x
322
+ typeof x === `string` ? (x as AType) : (x[this.a] as AType | undefined)
274
323
 
275
324
  if (a === undefined && typeof b === `string`) {
276
- const bRelations = this.getRelatedKeys(b)
325
+ const bRelations = this.getRelatedKeys(b) as Set<AType>
277
326
  if (bRelations) {
278
327
  for (const bRelation of bRelations) {
279
328
  this.delete(bRelation, b)
@@ -296,7 +345,9 @@ export class Junction<
296
345
  return this
297
346
  }
298
347
 
299
- public getRelatedKey(key: string): string | undefined {
348
+ public getRelatedKey(key: AType): BType | undefined
349
+ public getRelatedKey(key: BType): AType | undefined
350
+ public getRelatedKey(key: AType | BType): AType | BType | undefined {
300
351
  const relations = this.getRelatedKeys(key)
301
352
  if (relations) {
302
353
  if (relations.size > 1) {
@@ -315,37 +366,52 @@ export class Junction<
315
366
  }
316
367
 
317
368
  public replaceRelations(
318
- a: string,
319
- relations: Content extends null ? string[] : Record<string, Content>,
369
+ a: AType,
370
+ relations: Content extends null ? BType[] : Record<BType, Content>,
371
+ config?: { reckless: boolean },
372
+ ): this
373
+ public replaceRelations(
374
+ b: BType,
375
+ relations: Content extends null ? AType[] : Record<AType, Content>,
376
+ config?: { reckless: boolean },
377
+ ): this
378
+ public replaceRelations<
379
+ XType extends AType | BType,
380
+ YType extends XType extends AType ? BType : AType,
381
+ >(
382
+ x: XType,
383
+ relations: Content extends null ? YType[] : Record<YType, Content>,
320
384
  config?: { reckless: boolean },
321
385
  ): this {
322
386
  const hasContent = !Array.isArray(relations)
323
- const bs = hasContent ? Object.keys(relations) : relations
387
+ const ys = (hasContent ? Object.keys(relations) : relations) as YType[]
324
388
  if (config?.reckless) {
325
- this.replaceRelationsUnsafely(a, bs)
389
+ this.replaceRelationsUnsafely(x as any, ys as any)
326
390
  } else {
327
- this.replaceRelationsSafely(a, bs)
391
+ this.replaceRelationsSafely(x as any, ys as any)
328
392
  }
329
393
  if (hasContent) {
330
- for (const b of bs) {
331
- const contentKey = this.makeContentKey(a, b)
332
- const content = relations[b] as Content
394
+ for (const y of ys) {
395
+ const contentKey = this.makeContentKey(x as any, y as any) // sort XY to AB ❗
396
+ const content = (relations as Record<YType, Content>)[y]
333
397
  this.setContent(contentKey, content)
334
398
  }
335
399
  }
336
400
  return this
337
401
  }
338
402
 
339
- public getContent(a: string, b: string): Content | undefined {
403
+ public getContent(a: AType, b: BType): Content | undefined {
340
404
  const contentKey = this.makeContentKey(a, b)
341
405
  return this.getContentInternal(contentKey)
342
406
  }
343
407
 
408
+ public getRelationEntries(input: Record<ASide, AType>): [BType, Content][]
409
+ public getRelationEntries(input: Record<BSide, BType>): [AType, Content][]
344
410
  public getRelationEntries(
345
- input: Record<ASide, string> | Record<BSide, string>,
346
- ): [string, Content][] {
347
- const a: string | undefined = (input as any)[this.a]
348
- const b: string | undefined = (input as any)[this.b]
411
+ input: Record<ASide, AType> | Record<BSide, BType>,
412
+ ): [AType | BType, Content][] {
413
+ const a: AType | undefined = (input as any)[this.a]
414
+ const b: BType | undefined = (input as any)[this.b]
349
415
  if (a !== undefined && b === undefined) {
350
416
  const aRelations = this.getRelatedKeys(a)
351
417
  if (aRelations) {
@@ -365,10 +431,12 @@ export class Junction<
365
431
  return []
366
432
  }
367
433
 
368
- public has(a: string, b?: string): boolean {
434
+ public has(a: AType, b?: BType): boolean
435
+ public has(b: BType, a?: AType): boolean
436
+ public has(a: AType | BType, b?: AType | BType): boolean {
369
437
  if (b) {
370
438
  const setA = this.getRelatedKeys(a)
371
- return setA?.has(b) ?? false
439
+ return setA?.has(b as any) ?? false
372
440
  }
373
441
  return this.relations.has(a)
374
442
  }
@@ -82,7 +82,9 @@ export function makeMoleculeInStore<M extends MoleculeConstructor>(
82
82
  },
83
83
  env: () => getEnvironmentData(newest(rootStore)),
84
84
  bond: ((
85
- token: JoinToken<any, any, any, any> | ReadableFamilyToken<any, any>,
85
+ token:
86
+ | JoinToken<any, any, any, any, any, any>
87
+ | ReadableFamilyToken<any, any>,
86
88
  maybeRole,
87
89
  ) => {
88
90
  if (token.type === `join`) {
@@ -31,7 +31,7 @@ export class Molecule<M extends MoleculeConstructor>
31
31
  public tokens = new Map<string, ReadableToken<any>>()
32
32
  public above = new Map<string, Molecule<any>>()
33
33
  public below = new Map<string, Molecule<any>>()
34
- public joins = new Map<string, Join<any, any, any, any>>()
34
+ public joins = new Map<string, Join<any, any, any, any, any, any>>()
35
35
  public instance: InstanceType<M>
36
36
  public constructor(
37
37
  ctx: Molecule<any>[] | undefined,