atom.io 0.44.14 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/eslint-plugin/index.js +1 -1
  2. package/dist/introspection/index.d.ts +3 -2
  3. package/dist/introspection/index.d.ts.map +1 -1
  4. package/dist/introspection/index.js.map +1 -1
  5. package/dist/json/index.d.ts +34 -20
  6. package/dist/json/index.d.ts.map +1 -1
  7. package/dist/json/index.js +40 -2
  8. package/dist/json/index.js.map +1 -1
  9. package/dist/main/index.d.ts +3 -3
  10. package/dist/main/index.d.ts.map +1 -1
  11. package/dist/main/index.js +3 -2
  12. package/dist/main/index.js.map +1 -1
  13. package/dist/react/index.d.ts +4 -4
  14. package/dist/react/index.d.ts.map +1 -1
  15. package/dist/react/index.js.map +1 -1
  16. package/dist/react-devtools/index.js.map +1 -1
  17. package/dist/realtime-client/index.d.ts +1 -1
  18. package/dist/realtime-client/index.d.ts.map +1 -1
  19. package/dist/realtime-client/index.js.map +1 -1
  20. package/dist/realtime-server/index.d.ts +5 -0
  21. package/dist/realtime-server/index.d.ts.map +1 -1
  22. package/dist/realtime-server/index.js +38 -12
  23. package/dist/realtime-server/index.js.map +1 -1
  24. package/dist/realtime-testing/index.d.ts.map +1 -1
  25. package/dist/realtime-testing/index.js +3 -9
  26. package/dist/realtime-testing/index.js.map +1 -1
  27. package/dist/transceivers/o-list/index.d.ts +1 -2
  28. package/dist/transceivers/o-list/index.d.ts.map +1 -1
  29. package/dist/transceivers/o-list/index.js +23 -24
  30. package/dist/transceivers/o-list/index.js.map +1 -1
  31. package/dist/transceivers/u-list/index.d.ts +1 -2
  32. package/dist/transceivers/u-list/index.d.ts.map +1 -1
  33. package/dist/transceivers/u-list/index.js +5 -6
  34. package/dist/transceivers/u-list/index.js.map +1 -1
  35. package/package.json +2 -10
  36. package/src/introspection/attach-introspection-states.ts +1 -1
  37. package/src/introspection/attach-transaction-logs.ts +2 -2
  38. package/src/introspection/index.ts +3 -0
  39. package/src/json/canonical.ts +42 -0
  40. package/src/json/enumeration.ts +36 -0
  41. package/src/json/index.ts +3 -132
  42. package/src/json/json.ts +128 -0
  43. package/src/main/index.ts +9 -2
  44. package/src/main/logger.ts +4 -2
  45. package/src/react/use-loadable.ts +10 -5
  46. package/src/react-devtools/TransactionIndex.tsx +1 -1
  47. package/src/react-devtools/store.ts +3 -3
  48. package/src/realtime-client/continuity/register-and-attempt-confirmed-update.ts +2 -2
  49. package/src/realtime-server/realtime-family-provider.ts +44 -0
  50. package/src/realtime-server/realtime-mutable-family-provider.ts +38 -0
  51. package/src/realtime-server/realtime-mutable-provider.ts +19 -0
  52. package/src/realtime-server/realtime-server-stores/provide-rooms.ts +2 -1
  53. package/src/realtime-server/realtime-state-provider.ts +20 -0
  54. package/src/realtime-server/server-config.ts +2 -1
  55. package/src/realtime-testing/setup-realtime-test.tsx +3 -9
  56. package/src/transceivers/o-list/o-list.ts +27 -28
  57. package/src/transceivers/u-list/u-list.ts +7 -8
  58. package/dist/data/index.d.ts +0 -23
  59. package/dist/data/index.d.ts.map +0 -1
  60. package/dist/data/index.js +0 -63
  61. package/dist/data/index.js.map +0 -1
  62. package/dist/struct/index.d.ts +0 -14
  63. package/dist/struct/index.d.ts.map +0 -1
  64. package/dist/struct/index.js +0 -37
  65. package/dist/struct/index.js.map +0 -1
  66. package/src/data/dict.ts +0 -31
  67. package/src/data/index.ts +0 -3
  68. package/src/data/struct-family.ts +0 -53
  69. package/src/data/struct.ts +0 -54
  70. package/src/struct/index.ts +0 -1
  71. package/src/struct/micro.ts +0 -72
  72. /package/dist/{chunk-D8lmAICg.js → chunk-CKcAJnC7.js} +0 -0
package/src/json/index.ts CHANGED
@@ -1,133 +1,4 @@
1
- import type { ViewOf } from "atom.io"
2
-
1
+ export * from "./canonical"
3
2
  export * from "./entries"
4
-
5
- export type primitive = boolean | number | string | null
6
-
7
- export namespace Json {
8
- export namespace Tree {
9
- // eslint-disable-next-line @typescript-eslint/no-shadow
10
- export type Array<Element = unknown> = ReadonlyArray<Element>
11
- // eslint-disable-next-line @typescript-eslint/no-shadow
12
- export type Object<K extends string = string, V = unknown> = Record<K, V>
13
- export type Fork = Array | Object
14
- export type Leaf = primitive
15
- export type Node = Fork | Leaf
16
- }
17
-
18
- /** A value can survive being {@link JSON.stringify}-ed and {@link JSON.parse}-d fully intact */
19
- export type Serializable =
20
- | primitive
21
- | Readonly<{ [key: string]: Serializable }>
22
- | ReadonlyArray<Serializable>
23
-
24
- export type Object<
25
- Key extends string = string,
26
- Value extends Serializable = Serializable,
27
- > = Record<Key, Value>
28
-
29
- export type Array<Element extends Serializable = Serializable> =
30
- ReadonlyArray<Element>
31
- }
32
-
33
- /** A generic that retains the type information of a {@link Json.Serializable} value while in string form */
34
- // biome-ignore format: long silly ternary
35
- export type stringified<J extends Json.Serializable> = (
36
- J extends string
37
- ? `"${J}"`
38
- : J extends number
39
- ? `${J}`
40
- : J extends true
41
- ? `true`
42
- : J extends false
43
- ? `false`
44
- : J extends boolean
45
- ? `false` | `true`
46
- : J extends null
47
- ? `null`
48
- : J extends []
49
- ? `[]`
50
- : J extends [infer Element extends Json.Serializable]
51
- ? `[${stringified<Element>}]`
52
- : J extends [
53
- infer Element1 extends Json.Serializable,
54
- infer Element2 extends Json.Serializable,
55
- ]
56
- ? `[${stringified<Element1>}, ${stringified<Element2>}]`
57
- : J extends [
58
- infer Element1 extends Json.Serializable,
59
- infer Element2 extends Json.Serializable,
60
- infer Element3 extends Json.Serializable,
61
- ]
62
- ? `[${stringified<Element1>}, ${stringified<Element2>}, ${stringified<Element3>}]`
63
- : J extends any[]
64
- ? `[${string}]` & { __json?: J }
65
- : string & { __json?: J }
66
- )
67
-
68
- /** Type-safe wrapper for {@link JSON.parse} */
69
- export function parseJson<J extends Json.Serializable>(str: stringified<J>): J
70
- /** Type-safe wrapper for {@link JSON.parse} */
71
- export function parseJson(str: string): Json.Serializable
72
- export function parseJson(str: string): Json.Serializable {
73
- return JSON.parse(str)
74
- }
75
-
76
- /** Type-safe wrapper for {@link JSON.stringify} */
77
- export const stringifyJson = <J extends Json.Serializable>(
78
- json: J,
79
- ): stringified<J> => JSON.stringify(json) as stringified<J>
80
-
81
- /** Only Canonical values should be used for keys because they always serialize to the same string */
82
- export type Canonical = primitive | ReadonlyArray<Canonical>
83
-
84
- /** A function whose parameters and return value are {@link Json.Serializable} */
85
- export type JsonIO = (...params: Json.Serializable[]) => Json.Serializable | void
86
-
87
- export type JsonInterface<T, J extends Json.Serializable = Json.Serializable> = {
88
- toJson: (t: ViewOf<T>) => J
89
- fromJson: (json: J) => T
90
- }
91
-
92
- const JSON_PROTOTYPES = [
93
- Array.prototype,
94
- Boolean.prototype,
95
- Number.prototype,
96
- Object.prototype,
97
- String.prototype,
98
- ] as const
99
- export const isJson = (input: unknown): input is Json.Tree.Node => {
100
- if (input === null) return true
101
- if (input === undefined) return false
102
- const prototype = Object.getPrototypeOf(input)
103
- return JSON_PROTOTYPES.includes(prototype)
104
- }
105
-
106
- export const JSON_TYPE_NAMES = [
107
- `array`,
108
- `boolean`,
109
- `null`,
110
- `number`,
111
- `object`,
112
- `string`,
113
- ] as const
114
-
115
- export type JsonTypeName = (typeof JSON_TYPE_NAMES)[number]
116
-
117
- export interface JsonTypes extends Record<JsonTypeName, Json.Serializable> {
118
- array: Json.Array
119
- boolean: boolean
120
- null: null
121
- number: number
122
- object: Json.Object
123
- string: string
124
- }
125
-
126
- export const JSON_DEFAULTS: JsonTypes = {
127
- array: [],
128
- boolean: false,
129
- null: null,
130
- number: 0,
131
- object: {},
132
- string: ``,
133
- }
3
+ export * from "./enumeration"
4
+ export * from "./json"
@@ -0,0 +1,128 @@
1
+ import type { ViewOf } from "atom.io"
2
+
3
+ export type primitive = boolean | number | string | null
4
+
5
+ export namespace Json {
6
+ export namespace Tree {
7
+ // eslint-disable-next-line @typescript-eslint/no-shadow
8
+ export type Array<Element = unknown> = ReadonlyArray<Element>
9
+ // eslint-disable-next-line @typescript-eslint/no-shadow
10
+ export type Object<K extends string = string, V = unknown> = Record<K, V>
11
+ export type Fork = Array | Object
12
+ export type Leaf = primitive
13
+ export type Node = Fork | Leaf
14
+ }
15
+
16
+ /** A value can survive being {@link JSON.stringify}-ed and {@link JSON.parse}-d fully intact */
17
+ export type Serializable =
18
+ | primitive
19
+ | Readonly<{ [key: string]: Serializable }>
20
+ | ReadonlyArray<Serializable>
21
+
22
+ export type Object<
23
+ Key extends string = string,
24
+ Value extends Serializable = Serializable,
25
+ > = Record<Key, Value>
26
+
27
+ export type Array<Element extends Serializable = Serializable> =
28
+ ReadonlyArray<Element>
29
+ }
30
+
31
+ /** A generic that retains the type information of a {@link Json.Serializable} value while in string form */
32
+ // biome-ignore format: long silly ternary
33
+ export type stringified<J extends Json.Serializable> = (
34
+ J extends string
35
+ ? `"${J}"`
36
+ : J extends number
37
+ ? `${J}`
38
+ : J extends true
39
+ ? `true`
40
+ : J extends false
41
+ ? `false`
42
+ : J extends boolean
43
+ ? `false` | `true`
44
+ : J extends null
45
+ ? `null`
46
+ : J extends []
47
+ ? `[]`
48
+ : J extends [infer Element extends Json.Serializable]
49
+ ? `[${stringified<Element>}]`
50
+ : J extends [
51
+ infer Element1 extends Json.Serializable,
52
+ infer Element2 extends Json.Serializable,
53
+ ]
54
+ ? `[${stringified<Element1>}, ${stringified<Element2>}]`
55
+ : J extends [
56
+ infer Element1 extends Json.Serializable,
57
+ infer Element2 extends Json.Serializable,
58
+ infer Element3 extends Json.Serializable,
59
+ ]
60
+ ? `[${stringified<Element1>}, ${stringified<Element2>}, ${stringified<Element3>}]`
61
+ : J extends any[]
62
+ ? `[${string}]` & { __json?: J }
63
+ : string & { __json?: J }
64
+ )
65
+
66
+ /** Type-safe wrapper for {@link JSON.parse} */
67
+ export function parseJson<J extends Json.Serializable>(str: stringified<J>): J
68
+ /** Type-safe wrapper for {@link JSON.parse} */
69
+ export function parseJson(str: string): Json.Serializable
70
+ export function parseJson(str: string): Json.Serializable {
71
+ return JSON.parse(str)
72
+ }
73
+
74
+ /** Type-safe wrapper for {@link JSON.stringify} */
75
+ export const stringifyJson = <J extends Json.Serializable>(
76
+ json: J,
77
+ ): stringified<J> => JSON.stringify(json) as stringified<J>
78
+
79
+ /** A function whose parameters and return value are {@link Json.Serializable} */
80
+ export type JsonIO = (...params: Json.Serializable[]) => Json.Serializable | void
81
+
82
+ export type JsonInterface<T, J extends Json.Serializable = Json.Serializable> = {
83
+ toJson: (t: ViewOf<T>) => J
84
+ fromJson: (json: J) => T
85
+ }
86
+
87
+ const JSON_PROTOTYPES = [
88
+ Array.prototype,
89
+ Boolean.prototype,
90
+ Number.prototype,
91
+ Object.prototype,
92
+ String.prototype,
93
+ ] as const
94
+ export const isJson = (input: unknown): input is Json.Tree.Node => {
95
+ if (input === null) return true
96
+ if (input === undefined) return false
97
+ const prototype = Object.getPrototypeOf(input)
98
+ return JSON_PROTOTYPES.includes(prototype)
99
+ }
100
+
101
+ export const JSON_TYPE_NAMES = [
102
+ `array`,
103
+ `boolean`,
104
+ `null`,
105
+ `number`,
106
+ `object`,
107
+ `string`,
108
+ ] as const
109
+
110
+ export type JsonTypeName = (typeof JSON_TYPE_NAMES)[number]
111
+
112
+ export interface JsonTypes extends Record<JsonTypeName, Json.Serializable> {
113
+ array: Json.Array
114
+ boolean: boolean
115
+ null: null
116
+ number: number
117
+ object: Json.Object
118
+ string: string
119
+ }
120
+
121
+ export const JSON_DEFAULTS: JsonTypes = {
122
+ array: [],
123
+ boolean: false,
124
+ null: null,
125
+ number: 0,
126
+ object: {},
127
+ string: ``,
128
+ }
package/src/main/index.ts CHANGED
@@ -15,7 +15,6 @@ export * from "./timeline"
15
15
  export type * from "./tokens"
16
16
  export * from "./transaction"
17
17
  export * from "./validators"
18
-
19
18
  /**
20
19
  * Loadable is used to type atoms or selectors that may at some point be initialized to or set to a {@link Promise}.
21
20
  *
@@ -25,4 +24,12 @@ export * from "./validators"
25
24
  */
26
25
  export type Loadable<T> = Promise<T> | T
27
26
 
28
- export type ViewOf<T> = T extends { READONLY_VIEW: infer View } ? View : T
27
+ export type ViewOf<T> = T extends { READONLY_VIEW: infer View }
28
+ ? View
29
+ : T extends Array<any>
30
+ ? readonly [...T]
31
+ : T extends Set<infer U>
32
+ ? ReadonlySet<ViewOf<U>>
33
+ : T extends Map<infer K, infer V>
34
+ ? ReadonlyMap<ViewOf<K>, ViewOf<V>>
35
+ : T
@@ -82,6 +82,7 @@ export type EntityDenomination =
82
82
  | `timeline`
83
83
  | `transaction`
84
84
  | `unknown`
85
+ | `user`
85
86
  | `writable_held_selector_family`
86
87
  | `writable_held_selector`
87
88
  | `writable_pure_selector_family`
@@ -103,6 +104,7 @@ export const PRETTY_ENTITY_NAMES: Record<EntityDenomination, string> = {
103
104
  timeline: `timeline`,
104
105
  transaction: `transaction`,
105
106
  unknown: `unknown`,
107
+ user: `👤`,
106
108
  writable_held_selector_family: `selector family [wh]`,
107
109
  writable_held_selector: `selector [wh]`,
108
110
  writable_pure_selector_family: `selector family [w]`,
@@ -126,11 +128,11 @@ export type LogFilter = (
126
128
  export type Logger = Record<LogLevel, LogFn>
127
129
 
128
130
  export const simpleLog =
129
- (logLevel: keyof Logger): LogFn =>
131
+ (logLevel: keyof Logger, prefix?: string): LogFn =>
130
132
  (icon, denomination, tokenKey, message, ...rest) => {
131
133
  /* eslint-disable-next-line no-console */
132
134
  console[logLevel](
133
- `${icon} ${PRETTY_ENTITY_NAMES[denomination]} \`${tokenKey}\` ${message}`,
135
+ `${prefix ? `${prefix} ` : ``}${icon} ${PRETTY_ENTITY_NAMES[denomination]} \`${tokenKey}\` ${message}`,
134
136
  ...rest,
135
137
  )
136
138
  }
@@ -1,5 +1,10 @@
1
1
  /** biome-ignore-all lint/correctness/useHookAtTopLevel: params are used in an invariant way */
2
- import type { Loadable, ReadableFamilyToken, ReadableToken } from "atom.io"
2
+ import type {
3
+ Loadable,
4
+ ReadableFamilyToken,
5
+ ReadableToken,
6
+ ViewOf,
7
+ } from "atom.io"
3
8
  import { findInStore, type ReadableState, withdraw } from "atom.io/internal"
4
9
  import type { Canonical } from "atom.io/json"
5
10
  import { StoreContext, useO } from "atom.io/react"
@@ -7,23 +12,23 @@ import { useContext, useRef } from "react"
7
12
 
8
13
  export function useLoadable<T, E>(
9
14
  token: ReadableToken<Loadable<T>, any, E>,
10
- ): `LOADING` | { loading: boolean; value: E | T }
15
+ ): `LOADING` | { loading: boolean; value: ViewOf<E | T> }
11
16
 
12
17
  export function useLoadable<T, K extends Canonical, E>(
13
18
  token: ReadableFamilyToken<Loadable<T>, K, E>,
14
19
  key: NoInfer<K>,
15
- ): `LOADING` | { loading: boolean; value: E | T }
20
+ ): `LOADING` | { loading: boolean; value: ViewOf<E | T> }
16
21
 
17
22
  export function useLoadable<T, F extends T, E>(
18
23
  token: ReadableToken<Loadable<T>, any, E>,
19
24
  fallback: F,
20
- ): { loading: boolean; value: T; error?: E }
25
+ ): { loading: boolean; value: ViewOf<T>; error?: E }
21
26
 
22
27
  export function useLoadable<T, K extends Canonical, F extends T, E>(
23
28
  token: ReadableFamilyToken<Loadable<T>, K, E>,
24
29
  key: NoInfer<K>,
25
30
  fallback: F,
26
- ): { loading: boolean; value: T; error?: E }
31
+ ): { loading: boolean; value: ViewOf<T>; error?: E }
27
32
 
28
33
  export function useLoadable(
29
34
  ...params:
@@ -16,7 +16,7 @@ export const TransactionLog: FC<{
16
16
  token: TransactionToken<Fn>
17
17
  isOpenState: RegularAtomToken<boolean>
18
18
  logState: ReadonlyPureSelectorToken<
19
- TransactionOutcomeEvent<TransactionToken<Fn>>[]
19
+ readonly TransactionOutcomeEvent<TransactionToken<Fn>>[]
20
20
  >
21
21
  }> = ({ token, isOpenState, logState }) => {
22
22
  const log = useO(logState)
@@ -13,7 +13,7 @@ import {
13
13
  } from "atom.io/internal"
14
14
  import type {
15
15
  IntrospectionStates,
16
- WritableTokenIndex,
16
+ ReadonlyTokenIndex,
17
17
  } from "atom.io/introspection"
18
18
  import { attachIntrospectionStates, isPlainObject } from "atom.io/introspection"
19
19
  import { storageSync } from "atom.io/web"
@@ -131,8 +131,8 @@ export function attachDevtoolsStates(
131
131
  do: ({ get, set }, path, current) => {
132
132
  const currentView = get(devtoolsViewSelectionAtom)
133
133
  let states:
134
- | WritableTokenIndex<AtomToken<unknown, any, any>>
135
- | WritableTokenIndex<SelectorToken<unknown, any, any>>
134
+ | ReadonlyTokenIndex<AtomToken<unknown, any, any>>
135
+ | ReadonlyTokenIndex<SelectorToken<unknown, any, any>>
136
136
  switch (currentView) {
137
137
  case `atoms`:
138
138
  states = get(introspectionStates.atomIndex)
@@ -18,10 +18,10 @@ export const useRegisterAndAttemptConfirmedUpdate =
18
18
  store: RootStore,
19
19
  continuityKey: string,
20
20
  socket: Socket,
21
- optimisticUpdates: AtomIO.TransactionOutcomeEvent<
21
+ optimisticUpdates: readonly AtomIO.TransactionOutcomeEvent<
22
22
  AtomIO.TransactionToken<Fn>
23
23
  >[],
24
- confirmedUpdates: AtomIO.TransactionOutcomeEvent<
24
+ confirmedUpdates: readonly AtomIO.TransactionOutcomeEvent<
25
25
  AtomIO.TransactionToken<Fn>
26
26
  >[],
27
27
  ) =>
@@ -14,6 +14,7 @@ import type { ServerConfig } from "."
14
14
  export type FamilyProvider = ReturnType<typeof realtimeAtomFamilyProvider>
15
15
  export function realtimeAtomFamilyProvider({
16
16
  socket,
17
+ userKey,
17
18
  store = IMPLICIT.STORE,
18
19
  }: ServerConfig) {
19
20
  return function familyProvider<
@@ -66,6 +67,12 @@ export function realtimeAtomFamilyProvider({
66
67
  familyMemberSubscriptions.set(
67
68
  `${token.key}:unsub`,
68
69
  employSocket(socket, `unsub:${token.key}`, () => {
70
+ store.logger.info(
71
+ `🙈`,
72
+ `user`,
73
+ userKey,
74
+ `unsubscribed from state "${token.key}"`,
75
+ )
69
76
  fillUnsubRequest(token.key)
70
77
  }),
71
78
  )
@@ -81,13 +88,35 @@ export function realtimeAtomFamilyProvider({
81
88
  }
82
89
 
83
90
  const start = () => {
91
+ store.logger.info(
92
+ `👀`,
93
+ `user`,
94
+ userKey,
95
+ `can subscribe to family "${family.key}"`,
96
+ )
84
97
  coreSubscriptions.add(
85
98
  employSocket(socket, `sub:${family.key}`, (subKey: K) => {
86
99
  const exposedSubKeys = getFromStore(store, index)
87
100
  const shouldExpose = isAvailable(exposedSubKeys, subKey)
88
101
  if (shouldExpose) {
102
+ store.logger.info(
103
+ `👀`,
104
+ `user`,
105
+ userKey,
106
+ `is approved for a subscription to`,
107
+ subKey,
108
+ `in family "${family.key}"`,
109
+ )
89
110
  exposeFamilyMembers(subKey)
90
111
  } else {
112
+ store.logger.info(
113
+ `❌`,
114
+ `user`,
115
+ userKey,
116
+ `is denied for a subscription to`,
117
+ subKey,
118
+ `in family "${family.key}"`,
119
+ )
91
120
  familyMemberSubscriptionsWanted.add(stringifyJson(subKey))
92
121
  socket.emit(`unavailable:${family.key}`, subKey)
93
122
  }
@@ -99,8 +128,23 @@ export function realtimeAtomFamilyProvider({
99
128
  index,
100
129
  `expose-family:${family.key}:${socket.id}`,
101
130
  ({ newValue: newExposedSubKeys }) => {
131
+ store.logger.info(
132
+ `👀`,
133
+ `user`,
134
+ userKey,
135
+ `has the following keys available for family "${family.key}"`,
136
+ newExposedSubKeys,
137
+ )
102
138
  for (const subKey of newExposedSubKeys) {
103
139
  if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
140
+ store.logger.info(
141
+ `👀`,
142
+ `user`,
143
+ userKey,
144
+ `is retroactively approved for a subscription to`,
145
+ subKey,
146
+ `in family "${family.key}"`,
147
+ )
104
148
  exposeFamilyMembers(subKey)
105
149
  }
106
150
  }
@@ -31,6 +31,7 @@ export type MutableFamilyProvider = ReturnType<
31
31
  >
32
32
  export function realtimeMutableFamilyProvider({
33
33
  socket,
34
+ userKey,
34
35
  store = IMPLICIT.STORE,
35
36
  }: ServerConfig) {
36
37
  return function mutableFamilyProvider<
@@ -91,13 +92,35 @@ export function realtimeMutableFamilyProvider({
91
92
  }
92
93
 
93
94
  const start = () => {
95
+ store.logger.info(
96
+ `👀`,
97
+ `user`,
98
+ userKey,
99
+ `can subscribe to family "${family.key}"`,
100
+ )
94
101
  coreSubscriptions.add(
95
102
  employSocket(socket, `sub:${family.key}`, (subKey: K) => {
96
103
  const exposedSubKeys = getFromStore(store, index)
97
104
  const shouldExpose = isAvailable(exposedSubKeys, subKey)
98
105
  if (shouldExpose) {
106
+ store.logger.info(
107
+ `👀`,
108
+ `user`,
109
+ userKey,
110
+ `is approved for a subscription to`,
111
+ subKey,
112
+ `in family "${family.key}"`,
113
+ )
99
114
  exposeFamilyMembers(subKey)
100
115
  } else {
116
+ store.logger.info(
117
+ `❌`,
118
+ `user`,
119
+ userKey,
120
+ `is denied for a subscription to`,
121
+ subKey,
122
+ `in family "${family.key}"`,
123
+ )
101
124
  familyMemberSubscriptionsWanted.add(stringifyJson(subKey))
102
125
  socket.emit(`unavailable:${family.key}`, subKey)
103
126
  }
@@ -109,8 +132,23 @@ export function realtimeMutableFamilyProvider({
109
132
  index,
110
133
  `expose-family:${family.key}:${socket.id}`,
111
134
  ({ newValue: newExposedSubKeys }) => {
135
+ store.logger.info(
136
+ `👀`,
137
+ `user`,
138
+ userKey,
139
+ `has the following keys available for family "${family.key}"`,
140
+ newExposedSubKeys,
141
+ )
112
142
  for (const subKey of newExposedSubKeys) {
113
143
  if (familyMemberSubscriptionsWanted.has(stringifyJson(subKey))) {
144
+ store.logger.info(
145
+ `👀`,
146
+ `user`,
147
+ userKey,
148
+ `is retroactively approved for a subscription to`,
149
+ subKey,
150
+ `in family "${family.key}"`,
151
+ )
114
152
  exposeFamilyMembers(subKey)
115
153
  }
116
154
  }
@@ -15,6 +15,7 @@ import type { ServerConfig } from "."
15
15
  export type MutableProvider = ReturnType<typeof realtimeMutableProvider>
16
16
  export function realtimeMutableProvider({
17
17
  socket,
18
+ userKey,
18
19
  store = IMPLICIT.STORE,
19
20
  }: ServerConfig) {
20
21
  return function mutableProvider<
@@ -30,8 +31,20 @@ export function realtimeMutableProvider({
30
31
  const trackerToken = getUpdateToken(token)
31
32
 
32
33
  const start = () => {
34
+ store.logger.info(
35
+ `👀`,
36
+ `user`,
37
+ userKey,
38
+ `can subscribe to state "${token.key}"`,
39
+ )
33
40
  subscriptions.add(
34
41
  employSocket(socket, `sub:${token.key}`, () => {
42
+ store.logger.info(
43
+ `👀`,
44
+ `user`,
45
+ userKey,
46
+ `subscribes to state "${token.key}"`,
47
+ )
35
48
  clearSubscriptions()
36
49
  socket.emit(`init:${token.key}`, getFromStore(store, jsonToken))
37
50
  subscriptions.add(
@@ -46,6 +59,12 @@ export function realtimeMutableProvider({
46
59
  )
47
60
  subscriptions.add(
48
61
  employSocket(socket, `unsub:${token.key}`, () => {
62
+ store.logger.info(
63
+ `🙈`,
64
+ `user`,
65
+ userKey,
66
+ `unsubscribes from state "${token.key}"`,
67
+ )
49
68
  clearSubscriptions()
50
69
  start()
51
70
  }),
@@ -252,10 +252,11 @@ export function provideRooms<RoomNames extends string>({
252
252
  createRoomSocketGuard(roomNames),
253
253
  )
254
254
 
255
- const exposeMutable = realtimeMutableProvider({ socket, store })
255
+ const exposeMutable = realtimeMutableProvider({ socket, store, userKey })
256
256
  const exposeMutableFamily = realtimeMutableFamilyProvider({
257
257
  socket,
258
258
  store,
259
+ userKey,
259
260
  })
260
261
 
261
262
  exposeMutable(roomKeysAtom)
@@ -8,8 +8,10 @@ import type { ServerConfig } from "."
8
8
  export type StateProvider = ReturnType<typeof realtimeStateProvider>
9
9
  export function realtimeStateProvider({
10
10
  socket,
11
+ userKey,
11
12
  store = IMPLICIT.STORE,
12
13
  }: ServerConfig) {
14
+ store.logger.info(`🔌`, `user`, userKey, `initialized state provider`)
13
15
  return function stateProvider<J extends Json.Serializable>(
14
16
  token: AtomIO.WritableToken<J>,
15
17
  ): () => void {
@@ -20,8 +22,20 @@ export function realtimeStateProvider({
20
22
  }
21
23
 
22
24
  const start = () => {
25
+ store.logger.info(
26
+ `👀`,
27
+ `user`,
28
+ userKey,
29
+ `can subscribe to state "${token.key}"`,
30
+ )
23
31
  subscriptions.add(
24
32
  employSocket(socket, `sub:${token.key}`, () => {
33
+ store.logger.info(
34
+ `👀`,
35
+ `user`,
36
+ userKey,
37
+ `subscribes to state "${token.key}"`,
38
+ )
25
39
  clearSubscriptions()
26
40
  socket.emit(`serve:${token.key}`, getFromStore(store, token))
27
41
  subscriptions.add(
@@ -36,6 +50,12 @@ export function realtimeStateProvider({
36
50
  )
37
51
  subscriptions.add(
38
52
  employSocket(socket, `unsub:${token.key}`, () => {
53
+ store.logger.info(
54
+ `🙈`,
55
+ `user`,
56
+ userKey,
57
+ `unsubscribes from state "${token.key}"`,
58
+ )
39
59
  clearSubscriptions()
40
60
  start()
41
61
  }),
@@ -1,7 +1,8 @@
1
1
  import type { RootStore } from "atom.io/internal"
2
- import type { Socket } from "atom.io/realtime"
2
+ import type { Socket, UserKey } from "atom.io/realtime"
3
3
 
4
4
  export type ServerConfig = {
5
5
  socket: Socket
6
+ userKey: UserKey
6
7
  store?: RootStore
7
8
  }
@@ -54,15 +54,9 @@ function prefixLogger(store: Store, prefix: string) {
54
54
  return params
55
55
  },
56
56
  {
57
- info: (...params) => {
58
- console.info(prefix, ...params)
59
- },
60
- warn: (...params) => {
61
- console.warn(prefix, ...params)
62
- },
63
- error: (...params) => {
64
- console.error(prefix, ...params)
65
- },
57
+ info: AtomIO.simpleLog(`info`, prefix),
58
+ warn: AtomIO.simpleLog(`warn`, prefix),
59
+ error: AtomIO.simpleLog(`error`, prefix),
66
60
  },
67
61
  )
68
62
  }