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.
@@ -7,7 +7,7 @@ import type {
7
7
  StateCreation,
8
8
  StateDisposal,
9
9
  } from "atom.io"
10
- import type { Json } from "atom.io/json"
10
+ import type { Canonical, Json } from "atom.io/json"
11
11
  import { selectJsonFamily, stringifyJson } from "atom.io/json"
12
12
 
13
13
  import { type MutableAtomFamily, prettyPrintTokenType } from ".."
@@ -21,7 +21,7 @@ import type { Transceiver } from "./transceiver"
21
21
  export function createMutableAtomFamily<
22
22
  T extends Transceiver<any>,
23
23
  J extends Json.Serializable,
24
- K extends string,
24
+ K extends Canonical,
25
25
  >(
26
26
  store: Store,
27
27
  options: MutableAtomFamilyOptions<T, J, K>,
@@ -1,5 +1,5 @@
1
1
  import type { MutableAtomFamilyToken } from "atom.io"
2
- import type { Json } from "atom.io/json"
2
+ import type { Canonical, Json } from "atom.io/json"
3
3
 
4
4
  import type { WritableSelectorFamily } from ".."
5
5
  import { newest } from "../lineage"
@@ -9,7 +9,7 @@ import type { Transceiver } from "./transceiver"
9
9
  export const getJsonFamily = <
10
10
  Core extends Transceiver<Json.Serializable>,
11
11
  SerializableCore extends Json.Serializable,
12
- Key extends string,
12
+ Key extends Canonical,
13
13
  >(
14
14
  mutableAtomFamily: MutableAtomFamilyToken<Core, SerializableCore, Key>,
15
15
  store: Store,
@@ -56,7 +56,9 @@ export class Store implements Lineage {
56
56
  })
57
57
  public selectorGraph = new Junction<
58
58
  `upstreamSelectorKey`,
59
+ string,
59
60
  `downstreamSelectorKey`,
61
+ string,
60
62
  { source: string }
61
63
  >(
62
64
  {
@@ -88,7 +90,9 @@ export class Store implements Lineage {
88
90
  public timelines = new Map<string, Timeline<any>>()
89
91
  public timelineTopics = new Junction<
90
92
  `timelineKey`,
93
+ string,
91
94
  `topicKey`,
95
+ string,
92
96
  { topicType: `atom_family` | `atom` | `molecule_family` | `molecule` }
93
97
  >({
94
98
  between: [`timelineKey`, `topicKey`],
@@ -24,5 +24,5 @@ export type TransactionProgress<F extends Func> = {
24
24
 
25
25
  export type TransactionEpoch = {
26
26
  epoch: Map<string, number>
27
- actionContinuities: Junction<`continuity`, `action`>
27
+ actionContinuities: Junction<`continuity`, string, `action`, string>
28
28
  }
@@ -1,5 +1,5 @@
1
- import { createWritableSelectorFamily } from '../../dist/chunk-7PUUHSXC.js';
2
- import '../../dist/chunk-ZKG6ZA4I.js';
1
+ import { createWritableSelectorFamily } from '../../dist/chunk-SMKF3ZNG.js';
2
+ import '../../dist/chunk-ADMEAXYU.js';
3
3
  import '../../dist/chunk-XWL6SNVU.js';
4
4
  import { createStandaloneSelector, IMPLICIT, growMoleculeInStore, initFamilyMemberInStore, withdraw, seekInStore } from 'atom.io/internal';
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atom.io",
3
- "version": "0.30.0",
3
+ "version": "0.30.1",
4
4
  "description": "Composable and testable reactive data library.",
5
5
  "homepage": "https://atom.io.fyi",
6
6
  "sideEffects": false,
@@ -57,34 +57,34 @@
57
57
  "@types/estree": "1.0.6",
58
58
  "@types/http-proxy": "1.17.15",
59
59
  "@types/npmlog": "7.0.0",
60
- "@types/react": "18.3.11",
60
+ "@types/react": "18.3.12",
61
61
  "@types/tmp": "0.2.6",
62
- "@typescript-eslint/parser": "8.8.0",
63
- "@typescript-eslint/rule-tester": "8.8.0",
64
- "@vitest/coverage-v8": "2.1.2",
65
- "@vitest/ui": "2.1.2",
62
+ "@typescript-eslint/parser": "8.10.0",
63
+ "@typescript-eslint/rule-tester": "8.10.0",
64
+ "@vitest/coverage-v8": "2.1.3",
65
+ "@vitest/ui": "2.1.3",
66
66
  "concurrently": "9.0.1",
67
- "drizzle-kit": "0.24.2",
68
- "drizzle-orm": "0.33.0",
69
- "eslint": "9.11.1",
70
- "framer-motion": "11.11.0",
67
+ "drizzle-kit": "0.26.2",
68
+ "drizzle-orm": "0.35.3",
69
+ "eslint": "9.13.0",
70
+ "framer-motion": "11.11.9",
71
71
  "happy-dom": "15.7.4",
72
72
  "http-proxy": "1.18.1",
73
73
  "npmlog": "7.0.1",
74
74
  "postgres": "3.4.4",
75
- "preact": "10.24.2",
75
+ "preact": "10.24.3",
76
76
  "react": "18.3.1",
77
77
  "react-dom": "18.3.1",
78
- "react-router-dom": "6.26.2",
78
+ "react-router-dom": "6.27.0",
79
79
  "socket.io": "4.8.0",
80
80
  "socket.io-client": "4.8.0",
81
81
  "tmp": "0.2.3",
82
82
  "tsup": "8.3.0",
83
83
  "tsx": "4.19.1",
84
- "typescript": "5.6.2",
85
- "vite": "5.4.8",
84
+ "typescript": "5.6.3",
85
+ "vite": "5.4.10",
86
86
  "vite-tsconfig-paths": "5.0.1",
87
- "vitest": "2.1.2",
87
+ "vitest": "2.1.3",
88
88
  "zod": "3.23.8"
89
89
  },
90
90
  "main": "dist/index.js",
@@ -45,7 +45,7 @@ type UserInRoomMeta = {
45
45
  enteredAtEpoch: number;
46
46
  };
47
47
  declare const DEFAULT_USER_IN_ROOM_META: UserInRoomMeta;
48
- declare const usersInRooms: atom_io_data.JoinToken<"room", "user", "1:n", UserInRoomMeta>;
48
+ declare const usersInRooms: atom_io_data.JoinToken<"room", string, "user", string, "1:n", UserInRoomMeta>;
49
49
  declare const usersInMyRoomView: atom_io.ReadonlySelectorFamilyToken<MutableAtomToken<SetRTX<string>, SetRTXJson<string>>[], string>;
50
50
 
51
51
  export { type ContinuityOptions, type ContinuityToken, DEFAULT_USER_IN_ROOM_META, InvariantMap, type PerspectiveToken, SyncGroup, type UserInRoomMeta, continuity, roomIndex, usersInMyRoomView, usersInRooms, usersInThisRoomIndex };
@@ -90,7 +90,9 @@ var usersInRooms = join(
90
90
  {
91
91
  key: `usersInRooms`,
92
92
  between: [`room`, `user`],
93
- cardinality: `1:n`
93
+ cardinality: `1:n`,
94
+ isAType: (input) => typeof input === `string`,
95
+ isBType: (input) => typeof input === `string`
94
96
  },
95
97
  DEFAULT_USER_IN_ROOM_META
96
98
  );
@@ -31,6 +31,8 @@ export const usersInRooms = join(
31
31
  key: `usersInRooms`,
32
32
  between: [`room`, `user`],
33
33
  cardinality: `1:n`,
34
+ isAType: (input): input is string => typeof input === `string`,
35
+ isBType: (input): input is string => typeof input === `string`,
34
36
  },
35
37
  DEFAULT_USER_IN_ROOM_META,
36
38
  )
@@ -2,7 +2,7 @@ import { Subject, Transceiver, Store } from 'atom.io/internal';
2
2
  import { Json, stringified, JsonIO, Canonical } from 'atom.io/json';
3
3
  import { ChildProcessWithoutNullStreams } from 'node:child_process';
4
4
  import * as AtomIO from 'atom.io';
5
- import { TransactionUpdateContent, TransactionUpdate, WritableToken } from 'atom.io';
5
+ import { TransactionUpdateContent, TransactionUpdate, Hierarchy, WritableToken } from 'atom.io';
6
6
  import { ContinuityToken, UserInRoomMeta } from 'atom.io/realtime';
7
7
  import * as atom_io_data from 'atom.io/data';
8
8
  import { Loadable } from 'atom.io/data';
@@ -112,10 +112,19 @@ declare const actionOcclusionAtoms: AtomIO.RegularAtomFamilyToken<{
112
112
  }, string>;
113
113
  declare const userUnacknowledgedQueues: AtomIO.RegularAtomFamilyToken<Pick<TransactionUpdate<any>, "key" | "epoch" | "id" | "updates" | "output">[], string>;
114
114
 
115
- declare const socketAtoms: AtomIO.RegularAtomFamilyToken<Socket | null, string>;
115
+ type SocketKey = `socket::${string}`;
116
+ type UserKey = `user::${string}`;
117
+ type RoomKey = `room::${string}`;
118
+ type SocketSystemHierarchy = Hierarchy<[
119
+ {
120
+ above: `root`;
121
+ below: [UserKey, SocketKey, RoomKey];
122
+ }
123
+ ]>;
124
+ declare const socketAtoms: AtomIO.RegularAtomFamilyToken<Socket | null, `socket::${string}`>;
116
125
  declare const socketIndex: AtomIO.MutableAtomToken<SetRTX<string>, SetRTXJson<string>>;
117
126
  declare const userIndex: AtomIO.MutableAtomToken<SetRTX<string>, SetRTXJson<string>>;
118
- declare const usersOfSockets: atom_io_data.JoinToken<"user", "socket", "1:1", null>;
127
+ declare const usersOfSockets: atom_io_data.JoinToken<"user", `user::${string}`, "socket", `socket::${string}`, "1:1", null>;
119
128
 
120
129
  type StateProvider = ReturnType<typeof realtimeStateProvider>;
121
130
  declare function realtimeStateProvider({ socket, store, }: ServerConfig): <J extends Json.Serializable>(token: AtomIO.WritableToken<J>) => () => void;
@@ -136,4 +145,4 @@ type ServerConfig = {
136
145
  store?: Store;
137
146
  };
138
147
 
139
- export { type ActionReceiver, ChildSocket, type CreateRoomIO, CustomSocket, type EventBuffer, type Events, type FamilyProvider, type JoinRoomIO, type LeaveRoomIO, type MutableFamilyProvider, type MutableProvider, ParentSocket, type RealtimeContinuitySynchronizer, type RoomArguments, type ServerConfig, type Socket, type StateProvider, type StateReceiver, type StringifiedEvent, SubjectSocket, actionOcclusionAtoms, createRoomTX, destroyRoomTX, joinRoomTX, leaveRoomTX, realtimeActionReceiver, realtimeAtomFamilyProvider, realtimeContinuitySynchronizer, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, redactTransactionUpdateContent, roomArgumentsAtoms, roomSelectors, socketAtoms, socketIndex, userIndex, userUnacknowledgedQueues, usersOfSockets };
148
+ export { type ActionReceiver, ChildSocket, type CreateRoomIO, CustomSocket, type EventBuffer, type Events, type FamilyProvider, type JoinRoomIO, type LeaveRoomIO, type MutableFamilyProvider, type MutableProvider, ParentSocket, type RealtimeContinuitySynchronizer, type RoomArguments, type RoomKey, type ServerConfig, type Socket, type SocketKey, type SocketSystemHierarchy, type StateProvider, type StateReceiver, type StringifiedEvent, SubjectSocket, type UserKey, actionOcclusionAtoms, createRoomTX, destroyRoomTX, joinRoomTX, leaveRoomTX, realtimeActionReceiver, realtimeAtomFamilyProvider, realtimeContinuitySynchronizer, realtimeMutableFamilyProvider, realtimeMutableProvider, realtimeStateProvider, realtimeStateReceiver, redactTransactionUpdateContent, roomArgumentsAtoms, roomSelectors, socketAtoms, socketIndex, userIndex, userUnacknowledgedQueues, usersOfSockets };
@@ -468,7 +468,9 @@ var userIndex = atom({
468
468
  var usersOfSockets = join({
469
469
  key: `usersOfSockets`,
470
470
  between: [`user`, `socket`],
471
- cardinality: `1:1`
471
+ cardinality: `1:1`,
472
+ isAType: (s) => s.startsWith(`user::`),
473
+ isBType: (s) => s.startsWith(`socket::`)
472
474
  });
473
475
 
474
476
  // realtime-server/src/realtime-continuity-synchronizer.ts
@@ -481,7 +483,7 @@ function realtimeContinuitySynchronizer({
481
483
  const continuityKey = continuity.key;
482
484
  const userKeyState = findRelationsInStore(
483
485
  usersOfSockets,
484
- socket.id,
486
+ `socket::${socket.id}`,
485
487
  store
486
488
  ).userKeyOfSocket;
487
489
  const userKey = getFromStore(store, userKeyState);
@@ -15,7 +15,7 @@ import {
15
15
  import type { Json, JsonIO } from "atom.io/json"
16
16
  import type { ContinuityToken } from "atom.io/realtime"
17
17
 
18
- import type { ServerConfig, Socket } from "."
18
+ import type { ServerConfig, Socket, SocketKey } from "."
19
19
  import { socketAtoms, usersOfSockets } from "."
20
20
  import {
21
21
  redactTransactionUpdateContent,
@@ -35,7 +35,7 @@ export function realtimeContinuitySynchronizer({
35
35
  const continuityKey = continuity.key
36
36
  const userKeyState = findRelationsInStore(
37
37
  usersOfSockets,
38
- socket.id,
38
+ `socket::${socket.id}`,
39
39
  store,
40
40
  ).userKeyOfSocket
41
41
  const userKey = getFromStore(store, userKeyState)
@@ -1,3 +1,4 @@
1
+ import type { Hierarchy } from "atom.io"
1
2
  import { atom, atomFamily } from "atom.io"
2
3
  import { join } from "atom.io/data"
3
4
  import type { SetRTXJson } from "atom.io/transceivers/set-rtx"
@@ -5,7 +6,20 @@ import { SetRTX } from "atom.io/transceivers/set-rtx"
5
6
 
6
7
  import type { Socket } from ".."
7
8
 
8
- export const socketAtoms = atomFamily<Socket | null, string>({
9
+ export type SocketKey = `socket::${string}`
10
+ export type UserKey = `user::${string}`
11
+ export type RoomKey = `room::${string}`
12
+
13
+ export type SocketSystemHierarchy = Hierarchy<
14
+ [
15
+ {
16
+ above: `root`
17
+ below: [UserKey, SocketKey, RoomKey]
18
+ },
19
+ ]
20
+ >
21
+
22
+ export const socketAtoms = atomFamily<Socket | null, SocketKey>({
9
23
  key: `sockets`,
10
24
  default: null,
11
25
  })
@@ -28,4 +42,6 @@ export const usersOfSockets = join({
28
42
  key: `usersOfSockets`,
29
43
  between: [`user`, `socket`],
30
44
  cardinality: `1:1`,
45
+ isAType: (s): s is UserKey => s.startsWith(`user::`),
46
+ isBType: (s): s is SocketKey => s.startsWith(`socket::`),
31
47
  })
@@ -6,6 +6,9 @@ import { Socket } from 'socket.io-client';
6
6
 
7
7
  type TestSetupOptions = {
8
8
  port: number;
9
+ immortal?: {
10
+ server?: boolean;
11
+ };
9
12
  server: (tools: {
10
13
  socket: SocketIO.Socket;
11
14
  silo: AtomIO.Silo;
@@ -2,6 +2,7 @@ import '../../dist/chunk-XWL6SNVU.js';
2
2
  import * as http from 'node:http';
3
3
  import { render, prettyDOM } from '@testing-library/react';
4
4
  import * as AtomIO from 'atom.io';
5
+ import { realm } from 'atom.io';
5
6
  import { editRelationsInStore, findRelationsInStore } from 'atom.io/data';
6
7
  import { IMPLICIT, findInStore, setIntoStore, getFromStore, clearStore } from 'atom.io/internal';
7
8
  import { toEntries } from 'atom.io/json';
@@ -32,9 +33,13 @@ function prefixLogger(store, prefix) {
32
33
  var setupRealtimeTestServer = (options) => {
33
34
  ++testNumber;
34
35
  const silo = new AtomIO.Silo(
35
- { name: `SERVER-${testNumber}`, lifespan: `ephemeral` },
36
+ {
37
+ name: `SERVER-${testNumber}`,
38
+ lifespan: options.immortal?.server ? `immortal` : `ephemeral`
39
+ },
36
40
  IMPLICIT.STORE
37
41
  );
42
+ const socketRealm = realm(silo.store);
38
43
  const httpServer = http.createServer((_, res) => res.end(`Hello World!`));
39
44
  const address = httpServer.listen(options.port).address();
40
45
  const port = typeof address === `string` ? null : address === null ? null : address.port;
@@ -42,12 +47,14 @@ var setupRealtimeTestServer = (options) => {
42
47
  const server = new SocketIO.Server(httpServer).use((socket, next) => {
43
48
  const { token, username } = socket.handshake.auth;
44
49
  if (token === `test` && socket.id) {
45
- const socketState = findInStore(silo.store, RTS.socketAtoms, socket.id);
50
+ const userClaim = socketRealm.allocate(`root`, `user::${username}`);
51
+ const socketClaim = socketRealm.allocate(`root`, `socket::${socket.id}`);
52
+ const socketState = findInStore(silo.store, RTS.socketAtoms, socketClaim);
46
53
  setIntoStore(silo.store, socketState, socket);
47
54
  editRelationsInStore(
48
55
  RTS.usersOfSockets,
49
56
  (relations) => {
50
- relations.set(socket.id, username);
57
+ relations.set(userClaim, socketClaim);
51
58
  },
52
59
  silo.store
53
60
  );
@@ -64,7 +71,7 @@ var setupRealtimeTestServer = (options) => {
64
71
  function enableLogging() {
65
72
  const userKeyState = findRelationsInStore(
66
73
  RTS.usersOfSockets,
67
- socket.id,
74
+ `socket::${socket.id}`,
68
75
  silo.store
69
76
  ).userKeyOfSocket;
70
77
  userKey = getFromStore(silo.store, userKeyState);
@@ -3,6 +3,7 @@ import * as http from "node:http"
3
3
  import type { RenderResult } from "@testing-library/react"
4
4
  import { prettyDOM, render } from "@testing-library/react"
5
5
  import * as AtomIO from "atom.io"
6
+ import { realm } from "atom.io"
6
7
  import { editRelationsInStore, findRelationsInStore } from "atom.io/data"
7
8
  import type { Store } from "atom.io/internal"
8
9
  import {
@@ -44,6 +45,7 @@ function prefixLogger(store: Store, prefix: string) {
44
45
 
45
46
  export type TestSetupOptions = {
46
47
  port: number
48
+ immortal?: { server?: boolean }
47
49
  server: (tools: {
48
50
  socket: SocketIO.Socket
49
51
  silo: AtomIO.Silo
@@ -97,9 +99,13 @@ export const setupRealtimeTestServer = (
97
99
  ): RealtimeTestServer => {
98
100
  ++testNumber
99
101
  const silo = new AtomIO.Silo(
100
- { name: `SERVER-${testNumber}`, lifespan: `ephemeral` },
102
+ {
103
+ name: `SERVER-${testNumber}`,
104
+ lifespan: options.immortal?.server ? `immortal` : `ephemeral`,
105
+ },
101
106
  IMPLICIT.STORE,
102
107
  )
108
+ const socketRealm = realm<RTS.SocketSystemHierarchy>(silo.store)
103
109
 
104
110
  const httpServer = http.createServer((_, res) => res.end(`Hello World!`))
105
111
  const address = httpServer.listen(options.port).address()
@@ -110,12 +116,14 @@ export const setupRealtimeTestServer = (
110
116
  const server = new SocketIO.Server(httpServer).use((socket, next) => {
111
117
  const { token, username } = socket.handshake.auth
112
118
  if (token === `test` && socket.id) {
113
- const socketState = findInStore(silo.store, RTS.socketAtoms, socket.id)
119
+ const userClaim = socketRealm.allocate(`root`, `user::${username}`)
120
+ const socketClaim = socketRealm.allocate(`root`, `socket::${socket.id}`)
121
+ const socketState = findInStore(silo.store, RTS.socketAtoms, socketClaim)
114
122
  setIntoStore(silo.store, socketState, socket)
115
123
  editRelationsInStore(
116
124
  RTS.usersOfSockets,
117
125
  (relations) => {
118
- relations.set(socket.id, username)
126
+ relations.set(userClaim, socketClaim)
119
127
  },
120
128
  silo.store,
121
129
  )
@@ -133,7 +141,7 @@ export const setupRealtimeTestServer = (
133
141
  function enableLogging() {
134
142
  const userKeyState = findRelationsInStore(
135
143
  RTS.usersOfSockets,
136
- socket.id,
144
+ `socket::${socket.id}`,
137
145
  silo.store,
138
146
  ).userKeyOfSocket
139
147
  userKey = getFromStore(silo.store, userKeyState)
package/src/allocate.ts CHANGED
@@ -29,7 +29,6 @@ export function allocateIntoStore<
29
29
  A extends Above<V, H>,
30
30
  >(store: Store, provenance: A, key: V): Claim<H, V, A> {
31
31
  const stringKey = stringifyJson(key)
32
-
33
32
  try {
34
33
  const above: Molecule<any>[] = []
35
34
 
@@ -38,7 +37,7 @@ export function allocateIntoStore<
38
37
  // biome-ignore lint/style/noNonNullAssertion: let's assume we made the root molecule to get here
39
38
  above.push(store.molecules.get(`"root"`)!)
40
39
  allocationAttachmentStyle = `all`
41
- } else if (provenance[0][0] === T$) {
40
+ } else if (typeof provenance === `string` && provenance.startsWith(T$)) {
42
41
  allocationAttachmentStyle = `any`
43
42
  const provenanceKey = stringifyJson(provenance as Canonical)
44
43
  const provenanceMolecule = store.molecules.get(provenanceKey)
@@ -49,7 +48,7 @@ export function allocateIntoStore<
49
48
  }
50
49
  above.push(provenanceMolecule)
51
50
  } else {
52
- const allocationIsCompound = key[0][0] === T$
51
+ const allocationIsCompound = key.startsWith(`T$--`)
53
52
  if (allocationIsCompound) {
54
53
  allocationAttachmentStyle = `all`
55
54
  for (const claim of provenance as SingularTypedKey[]) {
@@ -150,11 +149,11 @@ export function deallocateFromStore<
150
149
  }
151
150
  for (const child of molecule.below.values()) {
152
151
  if (child.dependsOn === `all`) {
153
- deallocateFromStore(store, child.key)
152
+ deallocateFromStore<any, any, any>(store, child.key)
154
153
  } else {
155
154
  child.above.delete(molecule.stringKey)
156
155
  if (child.above.size === 0) {
157
- deallocateFromStore(store, child.key)
156
+ deallocateFromStore<any, any, any>(store, child.key)
158
157
  }
159
158
  }
160
159
  }
@@ -203,13 +202,13 @@ export function realm<H extends Hierarchy>(store: Store) {
203
202
 
204
203
  export const T$ = `T$`
205
204
  export type T$ = typeof T$
206
- export type TypeTag<T extends string> = [T$, T]
207
- export type SingularTypedKey<T extends string = string> = [T, string]
205
+ export type TypeTag<T extends string> = `${T$}--${T}`
206
+ export type SingularTypedKey<T extends string = string> = `${T}::${string}`
208
207
  export type CompoundTypedKey<
209
208
  A extends string = string,
210
209
  B extends string = string,
211
210
  C extends string = string,
212
- > = [TypeTag<A>, TypedKey<B>, TypedKey<C>]
211
+ > = `${TypeTag<A>}==${SingularTypedKey<B>}++${SingularTypedKey<C>}`
213
212
  export type TypedKey<
214
213
  A extends string = string,
215
214
  B extends string = string,
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ import type {
7
7
  WritableSelectorFamilyToken,
8
8
  } from "./selector"
9
9
 
10
+ export * from "./allocate"
10
11
  export * from "./atom"
11
12
  export * from "./dispose-state"
12
13
  export * from "./get-state"
package/src/molecule.ts CHANGED
@@ -38,12 +38,14 @@ export type CtorToolkit<K extends Canonical> = Flat<
38
38
  bond<T>(family: ReadonlySelectorFamilyToken<T, K>): ReadonlySelectorToken<T>
39
39
  bond<T>(family: WritableFamilyToken<T, K>): WritableToken<T>
40
40
  bond<T>(family: ReadableFamilyToken<T, K>): ReadableToken<T>
41
- bond<J extends JoinToken<any, any, any, any>>(
41
+ bond<J extends JoinToken<any, any, any, any, any, any>>(
42
42
  joinToken: J,
43
43
  role: {
44
- as: J extends JoinToken<infer A, infer B, any, any> ? A | B : never
44
+ as: J extends JoinToken<infer A, string, infer B, string, any, any>
45
+ ? A | B
46
+ : never
45
47
  },
46
- ): J extends JoinToken<any, any, any, infer Content>
48
+ ): J extends JoinToken<any, any, any, any, any, infer Content>
47
49
  ? Content extends null
48
50
  ? { relatedKeys: ReadonlySelectorToken<string[]> }
49
51
  : {
@@ -1,20 +0,0 @@
1
- import { createMoleculeFamily, IMPLICIT, makeMoleculeInStore, Molecule } from 'atom.io/internal';
2
- import { stringifyJson } from 'atom.io/json';
3
-
4
- // src/molecule.ts
5
- function moleculeFamily(options) {
6
- return createMoleculeFamily(IMPLICIT.STORE, options);
7
- }
8
- function makeMolecule(context, family, key, ...params) {
9
- return makeMoleculeInStore(IMPLICIT.STORE, context, family, key, ...params);
10
- }
11
- function makeRootMoleculeInStore(key, store = IMPLICIT.STORE) {
12
- const molecule = new Molecule(void 0, key);
13
- store.molecules.set(stringifyJson(key), molecule);
14
- return {
15
- key,
16
- type: `molecule`
17
- };
18
- }
19
-
20
- export { makeMolecule, makeRootMoleculeInStore, moleculeFamily };