atom.io 0.40.6 → 0.40.8

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 (186) hide show
  1. package/README.md +1 -1
  2. package/dist/data/index.d.ts +1 -1
  3. package/dist/data/index.js +1 -2
  4. package/dist/data/index.js.map +1 -1
  5. package/dist/employ-socket-D6wgByWh.js +12 -0
  6. package/dist/employ-socket-D6wgByWh.js.map +1 -0
  7. package/dist/eslint-plugin/index.js.map +1 -1
  8. package/dist/has-role-CMlaUlaf.js +1133 -0
  9. package/dist/has-role-CMlaUlaf.js.map +1 -0
  10. package/dist/internal/index.d.ts +248 -248
  11. package/dist/internal/index.d.ts.map +1 -1
  12. package/dist/internal/index.js +590 -1803
  13. package/dist/internal/index.js.map +1 -1
  14. package/dist/introspection/index.d.ts +1 -1
  15. package/dist/introspection/index.d.ts.map +1 -1
  16. package/dist/introspection/index.js +13 -32
  17. package/dist/introspection/index.js.map +1 -1
  18. package/dist/is-fn-DY1wZ-md.js +10 -0
  19. package/dist/is-fn-DY1wZ-md.js.map +1 -0
  20. package/dist/json/index.d.ts.map +1 -1
  21. package/dist/json/index.js.map +1 -1
  22. package/dist/main/index.d.ts +33 -33
  23. package/dist/main/index.d.ts.map +1 -1
  24. package/dist/main/index.js +3 -4
  25. package/dist/main/index.js.map +1 -1
  26. package/dist/mutex-store-CSvxY9i3.js +11 -0
  27. package/dist/mutex-store-CSvxY9i3.js.map +1 -0
  28. package/dist/react/index.d.ts +5 -5
  29. package/dist/react/index.d.ts.map +1 -1
  30. package/dist/react/index.js.map +1 -1
  31. package/dist/react-devtools/index.d.ts.map +1 -1
  32. package/dist/react-devtools/index.js +9 -11
  33. package/dist/react-devtools/index.js.map +1 -1
  34. package/dist/realtime/index.d.ts +7 -15
  35. package/dist/realtime/index.d.ts.map +1 -1
  36. package/dist/realtime/index.js +4 -35
  37. package/dist/realtime/index.js.map +1 -1
  38. package/dist/realtime-client/index.d.ts +6 -9
  39. package/dist/realtime-client/index.d.ts.map +1 -1
  40. package/dist/realtime-client/index.js +96 -88
  41. package/dist/realtime-client/index.js.map +1 -1
  42. package/dist/realtime-react/index.d.ts +17 -13
  43. package/dist/realtime-react/index.d.ts.map +1 -1
  44. package/dist/realtime-react/index.js +39 -50
  45. package/dist/realtime-react/index.js.map +1 -1
  46. package/dist/realtime-server/index.d.ts +83 -84
  47. package/dist/realtime-server/index.d.ts.map +1 -1
  48. package/dist/realtime-server/index.js +604 -543
  49. package/dist/realtime-server/index.js.map +1 -1
  50. package/dist/realtime-testing/index.d.ts +5 -4
  51. package/dist/realtime-testing/index.d.ts.map +1 -1
  52. package/dist/realtime-testing/index.js +35 -22
  53. package/dist/realtime-testing/index.js.map +1 -1
  54. package/dist/shared-room-store-BfW3nWif.js +31 -0
  55. package/dist/shared-room-store-BfW3nWif.js.map +1 -0
  56. package/dist/shared-room-store-D2o4ZLjC.d.ts +15 -0
  57. package/dist/shared-room-store-D2o4ZLjC.d.ts.map +1 -0
  58. package/dist/transceivers/set-rtx/index.d.ts.map +1 -1
  59. package/dist/transceivers/set-rtx/index.js +4 -8
  60. package/dist/transceivers/set-rtx/index.js.map +1 -1
  61. package/dist/web/index.d.ts +3 -3
  62. package/dist/web/index.d.ts.map +1 -1
  63. package/dist/web/index.js +4 -3
  64. package/dist/web/index.js.map +1 -1
  65. package/package.json +13 -13
  66. package/src/internal/atom/create-regular-atom.ts +5 -4
  67. package/src/internal/atom/dispose-atom.ts +7 -2
  68. package/src/internal/atom/has-role.ts +3 -3
  69. package/src/internal/caching.ts +4 -2
  70. package/src/internal/families/create-readonly-held-selector-family.ts +2 -1
  71. package/src/internal/families/create-readonly-pure-selector-family.ts +5 -2
  72. package/src/internal/families/create-regular-atom-family.ts +2 -1
  73. package/src/internal/families/create-writable-held-selector-family.ts +2 -1
  74. package/src/internal/families/create-writable-pure-selector-family.ts +5 -2
  75. package/src/internal/families/dispose-from-store.ts +4 -4
  76. package/src/internal/families/find-in-store.ts +10 -10
  77. package/src/internal/families/get-family-of-token.ts +2 -2
  78. package/src/internal/families/index.ts +1 -0
  79. package/src/internal/families/mint-in-store.ts +54 -19
  80. package/src/internal/families/seek-in-store.ts +1 -1
  81. package/src/internal/get-state/get-fallback.ts +2 -2
  82. package/src/internal/get-state/get-from-store.ts +5 -5
  83. package/src/internal/get-state/read-or-compute-value.ts +1 -1
  84. package/src/internal/get-state/reduce-reference.ts +8 -6
  85. package/src/internal/index.ts +2 -220
  86. package/src/internal/molecule.ts +1 -2
  87. package/src/internal/mutable/create-mutable-atom-family.ts +3 -2
  88. package/src/internal/mutable/create-mutable-atom.ts +4 -2
  89. package/src/internal/mutable/get-json-family.ts +1 -1
  90. package/src/internal/mutable/get-update-family.ts +1 -1
  91. package/src/internal/mutable/tracker-family.ts +2 -1
  92. package/src/internal/mutable/tracker.ts +71 -59
  93. package/src/internal/safe-compute.ts +1 -1
  94. package/src/internal/selector/create-readonly-held-selector.ts +2 -1
  95. package/src/internal/selector/create-readonly-pure-selector.ts +2 -1
  96. package/src/internal/selector/create-writable-held-selector.ts +2 -1
  97. package/src/internal/selector/create-writable-pure-selector.ts +2 -1
  98. package/src/internal/selector/dispose-selector.ts +3 -2
  99. package/src/internal/selector/register-selector.ts +8 -5
  100. package/src/internal/selector/trace-selector-atoms.ts +2 -1
  101. package/src/internal/set-state/dispatch-state-update.ts +3 -2
  102. package/src/internal/set-state/evict-downstream.ts +1 -1
  103. package/src/internal/set-state/operate-on-store.ts +16 -22
  104. package/src/internal/set-state/reset-atom-or-selector.ts +5 -3
  105. package/src/internal/set-state/reset-in-store.ts +5 -5
  106. package/src/internal/set-state/set-atom-or-selector.ts +2 -2
  107. package/src/internal/set-state/set-atom.ts +4 -2
  108. package/src/internal/set-state/set-into-store.ts +21 -39
  109. package/src/internal/set-state/set-selector.ts +3 -2
  110. package/src/internal/state-types.ts +228 -0
  111. package/src/internal/store/deposit.ts +4 -4
  112. package/src/internal/store/index.ts +0 -1
  113. package/src/internal/store/store.ts +9 -9
  114. package/src/internal/store/withdraw.ts +4 -4
  115. package/src/internal/subscribe/recall-state.ts +1 -1
  116. package/src/internal/subscribe/subscribe-to-root-atoms.ts +1 -12
  117. package/src/internal/subscribe/subscribe-to-state.ts +9 -0
  118. package/src/internal/subscribe/subscribe-to-transaction.ts +3 -2
  119. package/src/internal/transaction/build-transaction.ts +3 -2
  120. package/src/internal/transaction/index.ts +1 -23
  121. package/src/internal/transaction/is-root-store.ts +4 -1
  122. package/src/internal/transaction/transaction-meta-progress.ts +22 -0
  123. package/src/main/atom.ts +1 -2
  124. package/src/main/find-state.ts +5 -5
  125. package/src/main/get-state.ts +4 -4
  126. package/src/main/realm.ts +2 -2
  127. package/src/main/set-state.ts +10 -10
  128. package/src/react/parse-state-overloads.ts +3 -3
  129. package/src/react/use-i.ts +6 -4
  130. package/src/react/use-loadable.ts +4 -10
  131. package/src/react/use-o.ts +6 -4
  132. package/src/react-devtools/store.ts +6 -6
  133. package/src/realtime/index.ts +1 -0
  134. package/src/realtime/mutex-store.ts +11 -0
  135. package/src/realtime/realtime-continuity.ts +1 -5
  136. package/src/realtime-client/index.ts +0 -1
  137. package/src/realtime-client/pull-atom-family-member.ts +14 -17
  138. package/src/realtime-client/pull-atom.ts +1 -1
  139. package/src/realtime-client/pull-mutable-atom-family-member.ts +16 -12
  140. package/src/realtime-client/pull-selector-family-member.ts +8 -35
  141. package/src/realtime-client/pull-selector-roots.ts +90 -0
  142. package/src/realtime-client/pull-selector.ts +2 -27
  143. package/src/realtime-client/push-state.ts +33 -5
  144. package/src/realtime-client/realtime-client-stores/client-main-store.ts +2 -5
  145. package/src/realtime-react/index.ts +2 -2
  146. package/src/realtime-react/realtime-context.tsx +9 -5
  147. package/src/realtime-react/use-pull-atom-family-member.ts +2 -3
  148. package/src/realtime-react/use-pull-mutable-family-member.ts +2 -3
  149. package/src/realtime-react/use-pull-selector-family-member.ts +5 -6
  150. package/src/realtime-react/use-push.ts +7 -3
  151. package/src/realtime-react/use-realtime-service.ts +11 -11
  152. package/src/realtime-react/use-single-effect.ts +11 -14
  153. package/src/realtime-server/{realtime-server-stores/server-sync-store.ts → continuity/continuity-store.ts} +2 -27
  154. package/src/realtime-server/continuity/provide-continuity.ts +50 -0
  155. package/src/realtime-server/continuity/{subscribe-to-continuity-actions.ts → provide-outcomes.ts} +15 -13
  156. package/src/realtime-server/continuity/{subscribe-to-continuity-perpectives.ts → provide-perspectives.ts} +10 -8
  157. package/src/realtime-server/continuity/{prepare-to-send-initial-payload.ts → provide-startup-payloads.ts} +6 -4
  158. package/src/realtime-server/continuity/receive-action-requests.ts +68 -0
  159. package/src/realtime-server/continuity/track-acknowledgements.ts +46 -0
  160. package/src/realtime-server/employ-socket.ts +14 -0
  161. package/src/realtime-server/index.ts +3 -22
  162. package/src/realtime-server/ipc-sockets/child-socket.ts +125 -66
  163. package/src/realtime-server/ipc-sockets/custom-socket.ts +16 -14
  164. package/src/realtime-server/ipc-sockets/parent-socket.ts +98 -69
  165. package/src/realtime-server/realtime-family-provider.ts +78 -29
  166. package/src/realtime-server/realtime-mutable-family-provider.ts +80 -31
  167. package/src/realtime-server/realtime-mutable-provider.ts +30 -22
  168. package/src/realtime-server/realtime-server-stores/index.ts +0 -2
  169. package/src/realtime-server/realtime-server-stores/server-room-external-store.ts +77 -36
  170. package/src/realtime-server/realtime-server-stores/server-user-store.ts +12 -1
  171. package/src/realtime-server/realtime-state-provider.ts +30 -29
  172. package/src/realtime-server/realtime-state-receiver.ts +62 -16
  173. package/src/realtime-server/server-config.ts +8 -0
  174. package/src/realtime-server/socket-interface.ts +14 -0
  175. package/src/realtime-testing/setup-realtime-test.tsx +70 -31
  176. package/src/web/index.ts +1 -1
  177. package/src/web/{persist-sync.ts → storage-sync.ts} +5 -2
  178. package/src/internal/store/mint-or-counterfeit.ts +0 -108
  179. package/src/realtime-client/server-action.ts +0 -23
  180. package/src/realtime-react/on-mount.ts +0 -5
  181. package/src/realtime-react/use-server-action.ts +0 -19
  182. package/src/realtime-server/continuity/prepare-to-serve-transaction-request.ts +0 -59
  183. package/src/realtime-server/continuity/prepare-to-sync-realtime-continuity.ts +0 -145
  184. package/src/realtime-server/continuity/prepare-to-track-client-acknowledgement.ts +0 -41
  185. package/src/realtime-server/realtime-action-receiver.ts +0 -40
  186. package/src/realtime-server/realtime-server-stores/server-room-external-actions.ts +0 -79
@@ -0,0 +1,68 @@
1
+ import type { TransactionOutcomeEvent, TransactionToken } from "atom.io"
2
+ import type { Store } from "atom.io/internal"
3
+ import { actUponStore } from "atom.io/internal"
4
+ import type { Json, JsonIO } from "atom.io/json"
5
+ import type { ContinuityToken } from "atom.io/realtime"
6
+
7
+ import { employSocket } from "../employ-socket"
8
+ import type { Socket } from "../socket-interface"
9
+
10
+ export function receiveActionRequests(
11
+ store: Store,
12
+ socket: Socket,
13
+ continuity: ContinuityToken,
14
+ userKey: string,
15
+ ): () => void {
16
+ const continuityKey = continuity.key
17
+
18
+ return employSocket(
19
+ socket,
20
+ `tx-run:${continuityKey}`,
21
+ function serveTransactionRequest(
22
+ txOutcome: Json.Serializable &
23
+ Pick<
24
+ TransactionOutcomeEvent<TransactionToken<JsonIO>>,
25
+ `id` | `params` | `token`
26
+ >,
27
+ ) {
28
+ store.logger.info(`🛎️`, `continuity`, continuityKey, `received`, txOutcome)
29
+ const transactionKey = txOutcome.token.key
30
+ const updateId = txOutcome.id
31
+ const performanceKey = `tx-run:${transactionKey}:${updateId}`
32
+ const performanceKeyStart = `${performanceKey}:start`
33
+ const performanceKeyEnd = `${performanceKey}:end`
34
+ performance.mark(performanceKeyStart)
35
+ try {
36
+ actUponStore(
37
+ store,
38
+ { type: `transaction`, key: transactionKey },
39
+ updateId,
40
+ )(...txOutcome.params)
41
+ } catch (thrown) {
42
+ if (thrown instanceof Error) {
43
+ store.logger.error(
44
+ `❌`,
45
+ `continuity`,
46
+ continuityKey,
47
+ `failed to run transaction ${transactionKey} from ${userKey} with update ${updateId}`,
48
+ thrown.message,
49
+ )
50
+ }
51
+ }
52
+ performance.mark(performanceKeyEnd)
53
+ const metric = performance.measure(
54
+ performanceKey,
55
+ performanceKeyStart,
56
+ performanceKeyEnd,
57
+ )
58
+ store.logger.info(
59
+ `🚀`,
60
+ `transaction`,
61
+ transactionKey,
62
+ updateId,
63
+ userKey,
64
+ metric.duration,
65
+ )
66
+ },
67
+ )
68
+ }
@@ -0,0 +1,46 @@
1
+ import type { Store } from "atom.io/internal"
2
+ import { getFromStore, setIntoStore } from "atom.io/internal"
3
+ import type { ContinuityToken } from "atom.io/realtime"
4
+
5
+ import { employSocket } from "../employ-socket"
6
+ import type { UserKey } from "../realtime-server-stores"
7
+ import type { Socket } from "../socket-interface"
8
+ import { unacknowledgedUpdatesAtoms } from "./continuity-store"
9
+
10
+ export function trackAcknowledgements(
11
+ store: Store,
12
+ socket: Socket,
13
+ continuity: ContinuityToken,
14
+ userKey: UserKey,
15
+ ): () => void {
16
+ const continuityKey = continuity.key
17
+ const userUnacknowledgedUpdates = getFromStore(
18
+ store,
19
+ unacknowledgedUpdatesAtoms,
20
+ userKey,
21
+ )
22
+ function trackClientAcknowledgement(epoch: number): void {
23
+ store.logger.info(
24
+ `👍`,
25
+ `continuity`,
26
+ continuityKey,
27
+ `${userKey} acknowledged epoch ${epoch}`,
28
+ )
29
+ const isUnacknowledged = userUnacknowledgedUpdates[0]?.epoch === epoch
30
+ if (isUnacknowledged) {
31
+ setIntoStore(store, unacknowledgedUpdatesAtoms, userKey, (updates) => {
32
+ updates.shift()
33
+ store.logger.info(
34
+ `👍`,
35
+ `continuity`,
36
+ continuityKey,
37
+ `${userKey} unacknowledged update queue now has`,
38
+ updates.length,
39
+ `items`,
40
+ )
41
+ return updates
42
+ })
43
+ }
44
+ }
45
+ return employSocket(socket, `ack:${continuityKey}`, trackClientAcknowledgement)
46
+ }
@@ -0,0 +1,14 @@
1
+ import type { Events } from "./ipc-sockets"
2
+ import type { Socket } from "./socket-interface"
3
+
4
+ export function employSocket<I extends Events, K extends string & keyof I>(
5
+ socket: Socket,
6
+ event: K,
7
+ handleEvent: (...data: I[K]) => void,
8
+ ): () => void {
9
+ socket.on(event, handleEvent)
10
+ const retireSocket = () => {
11
+ socket.off(event, handleEvent)
12
+ }
13
+ return retireSocket
14
+ }
@@ -1,29 +1,10 @@
1
- import type { RootStore } from "atom.io/internal"
2
- import type { Json } from "atom.io/json"
3
-
4
- export * from "./continuity/prepare-to-sync-realtime-continuity"
1
+ export * from "./continuity/provide-continuity"
5
2
  export * from "./ipc-sockets"
6
- export * from "./realtime-action-receiver"
7
3
  export * from "./realtime-family-provider"
8
4
  export * from "./realtime-mutable-family-provider"
9
5
  export * from "./realtime-mutable-provider"
10
6
  export * from "./realtime-server-stores"
11
7
  export * from "./realtime-state-provider"
12
8
  export * from "./realtime-state-receiver"
13
-
14
- export type Socket = {
15
- id: string | undefined
16
- on: (event: string, listener: (...args: Json.Serializable[]) => void) => void
17
- onAny: (
18
- listener: (event: string, ...args: Json.Serializable[]) => void,
19
- ) => void
20
- off: (event: string, listener: (...args: Json.Serializable[]) => void) => void
21
- offAny: (
22
- listener: (event: string, ...args: Json.Serializable[]) => void,
23
- ) => void
24
- emit: (event: string, ...args: Json.Serializable[]) => void
25
- }
26
- export type ServerConfig = {
27
- socket: Socket
28
- store?: RootStore
29
- }
9
+ export type * from "./server-config"
10
+ export type * from "./socket-interface"
@@ -1,16 +1,26 @@
1
- import type { ChildProcessWithoutNullStreams } from "node:child_process"
1
+ import type { Readable, Writable } from "node:stream"
2
2
 
3
- import type { Json } from "atom.io/json"
3
+ import type { Json, stringified } from "atom.io/json"
4
4
  import { parseJson } from "atom.io/json"
5
5
 
6
- import type { EventBuffer, Events } from "./custom-socket"
6
+ import type { EventBuffer, EventPayload, Events } from "./custom-socket"
7
7
  import { CustomSocket } from "./custom-socket"
8
8
 
9
9
  /* eslint-disable no-console */
10
10
 
11
+ export type ChildProcess = {
12
+ pid?: number | undefined
13
+ stdin: Writable
14
+ stdout: Readable
15
+ stderr: Readable
16
+ }
17
+
18
+ export type StderrLog = [`e` | `i` | `w`, ...Json.Array]
19
+
11
20
  export class ChildSocket<
12
21
  I extends Events,
13
22
  O extends Events,
23
+ P extends ChildProcess = ChildProcess,
14
24
  > extends CustomSocket<I, O> {
15
25
  protected incompleteData = ``
16
26
  protected unprocessedEvents: string[] = []
@@ -19,13 +29,13 @@ export class ChildSocket<
19
29
 
20
30
  public id = `#####`
21
31
 
22
- public process: ChildProcessWithoutNullStreams
32
+ public proc: P
23
33
  public key: string
24
34
  public logger: Pick<Console, `error` | `info` | `warn`>
25
35
 
26
- protected handleLog(arg: Json.Serializable): void {
27
- if (Array.isArray(arg)) {
28
- const [level, ...rest] = arg
36
+ protected handleLog(log: StderrLog): void {
37
+ if (Array.isArray(log)) {
38
+ const [level, ...rest] = log
29
39
  switch (level) {
30
40
  case `i`:
31
41
  this.logger.info(...rest)
@@ -36,14 +46,12 @@ export class ChildSocket<
36
46
  case `e`:
37
47
  this.logger.error(...rest)
38
48
  break
39
- default:
40
- return
41
49
  }
42
50
  }
43
51
  }
44
52
 
45
53
  public constructor(
46
- process: ChildProcessWithoutNullStreams,
54
+ proc: P,
47
55
  key: string,
48
56
  logger?: Pick<Console, `error` | `info` | `warn`>,
49
57
  ) {
@@ -51,17 +59,17 @@ export class ChildSocket<
51
59
  const stringifiedEvent = JSON.stringify([event, ...args]) + `\x03`
52
60
  const errorHandler = (err: { code: string }) => {
53
61
  if (err.code === `EPIPE`) {
54
- console.error(`EPIPE error during write`, this.process.stdin)
62
+ console.error(`EPIPE error during write`, this.proc.stdin)
55
63
  }
56
- this.process.stdin.removeListener(`error`, errorHandler)
64
+ this.proc.stdin.removeListener(`error`, errorHandler)
57
65
  }
58
66
 
59
- this.process.stdin.once(`error`, errorHandler)
60
- this.process.stdin.write(stringifiedEvent)
67
+ this.proc.stdin.once(`error`, errorHandler)
68
+ this.proc.stdin.write(stringifiedEvent)
61
69
 
62
70
  return this
63
71
  })
64
- this.process = process
72
+ this.proc = proc
65
73
  this.key = key
66
74
  this.logger = logger ?? {
67
75
  info: (...args: unknown[]) => {
@@ -74,74 +82,125 @@ export class ChildSocket<
74
82
  console.error(this.id, this.key, ...args)
75
83
  },
76
84
  }
77
- this.process.stdout.on(
85
+ this.proc.stdout.on(
78
86
  `data`,
79
- <Event extends keyof I>(buffer: EventBuffer<string, I[Event]>) => {
87
+ <K extends string & keyof I>(buffer: EventBuffer<I, K>) => {
80
88
  const chunk = buffer.toString()
81
89
 
82
90
  if (chunk === `ALIVE`) {
83
- // console.log(chunk)
91
+ this.logger.info(chunk)
84
92
  return
85
93
  }
86
- this.unprocessedEvents.push(...chunk.split(`\x03`))
87
- // console.log(`🤓`, chunk.length)
88
- // console.log(`🤓`, this.unprocessedEvents.length)
89
- // console.log(`🤓`, ...this.unprocessedEvents.map((x) => x.length))
90
- const newInput = this.unprocessedEvents.shift()
91
- this.incompleteData += newInput ?? ``
92
- try {
93
- if (this.incompleteData.startsWith(`error`)) {
94
- console.log(`❗`, this.incompleteData)
94
+
95
+ const pieces = chunk.split(`\x03`)
96
+ const initialMaybeWellFormed = pieces[0]
97
+ pieces[0] = this.incompleteData + initialMaybeWellFormed
98
+ let idx = 0
99
+ for (const piece of pieces) {
100
+ if (piece === ``) {
101
+ continue
95
102
  }
96
- let parsedEvent = parseJson(this.incompleteData)
97
- this.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))
98
- while (this.unprocessedEvents.length > 0) {
99
- const event = this.unprocessedEvents.shift()
100
- if (event) {
101
- if (this.unprocessedEvents.length === 0) {
102
- this.incompleteData = event
103
+ try {
104
+ const jsonPiece = parseJson(piece as stringified<EventPayload<I, K>>)
105
+ this.handleEvent(...jsonPiece)
106
+ this.incompleteData = ``
107
+ } catch (thrown0) {
108
+ if (thrown0 instanceof Error) {
109
+ console.error(
110
+ [
111
+ `❌ Malformed data received from child process`,
112
+ ``,
113
+ piece,
114
+ ``,
115
+ thrown0.message,
116
+ ].join(`\n❌\t`),
117
+ )
118
+ }
119
+ try {
120
+ if (idx === 0) {
121
+ this.incompleteData = piece
122
+ const maybeActualJsonPiece = parseJson(
123
+ initialMaybeWellFormed as stringified<EventPayload<I, K>>,
124
+ )
125
+ this.handleEvent(...maybeActualJsonPiece)
126
+ this.incompleteData = ``
127
+ } else {
128
+ this.incompleteData += piece
129
+ }
130
+ } catch (thrown1) {
131
+ if (thrown1 instanceof Error) {
132
+ console.error(
133
+ [
134
+ `❌ Malformed data received from child process`,
135
+ ``,
136
+ initialMaybeWellFormed,
137
+ ``,
138
+ thrown1.message,
139
+ ].join(`\n❌\t`),
140
+ )
103
141
  }
104
- parsedEvent = parseJson(event)
105
- this.handleEvent(...(parsedEvent as [string, ...I[keyof I]]))
106
142
  }
107
143
  }
108
- this.incompleteData = ``
109
- } catch (error) {
110
- console.warn(`⚠️----------------⚠️`)
111
- console.warn(this.incompleteData)
112
- console.warn(`⚠️----------------⚠️`)
113
- console.error(error)
144
+ ++idx
114
145
  }
115
146
  },
116
147
  )
117
- this.process.stderr.on(`data`, (buf) => {
118
- const chunk = buf.toString()
119
- this.unprocessedLogs.push(...chunk.split(`\x03`))
120
- // console.log(`🤫`, chunk.length)
121
- // console.log(`🤫`, this.unprocessedLogs.length)
122
- // console.log(`🤫`, ...this.unprocessedLogs.map((x) => x.length))
123
- const newInput = this.unprocessedLogs.shift()
124
- this.incompleteLog += newInput ?? ``
125
- try {
126
- let parsedLog = parseJson(this.incompleteLog)
127
- // console.log(`🤫`, parsedLog)
128
- this.handleLog(parsedLog)
129
- while (this.unprocessedLogs.length > 0) {
130
- this.incompleteLog = this.unprocessedLogs.shift() ?? ``
131
- if (this.incompleteLog) {
132
- parsedLog = parseJson(this.incompleteLog)
133
- this.handleLog(parsedLog)
148
+ this.proc.stderr.on(`data`, (buffer: Buffer) => {
149
+ const chunk = buffer.toString()
150
+ const pieces = chunk.split(`\x03`)
151
+ const initialMaybeWellFormed = pieces[0]
152
+ pieces[0] = this.incompleteData + initialMaybeWellFormed
153
+ let idx = 0
154
+ for (const piece of pieces) {
155
+ if (piece === ``) {
156
+ continue
157
+ }
158
+ try {
159
+ const jsonPiece = parseJson(piece as stringified<StderrLog>)
160
+ this.handleLog(jsonPiece)
161
+ this.incompleteData = ``
162
+ } catch (thrown0) {
163
+ if (thrown0 instanceof Error) {
164
+ console.error(
165
+ [
166
+ `❌ Malformed log received from child process`,
167
+ ``,
168
+ piece,
169
+ ``,
170
+ thrown0.message,
171
+ ].join(`\n❌\t`),
172
+ )
173
+ }
174
+ try {
175
+ if (idx === 0) {
176
+ this.incompleteData = piece
177
+ const maybeActualJsonPiece = parseJson(
178
+ initialMaybeWellFormed as stringified<StderrLog>,
179
+ )
180
+ this.handleLog(maybeActualJsonPiece)
181
+ this.incompleteData = ``
182
+ } else {
183
+ this.incompleteData += piece
184
+ }
185
+ } catch (thrown1) {
186
+ if (thrown1 instanceof Error) {
187
+ console.error(
188
+ [
189
+ `❌ Malformed log received from child process...`,
190
+ ``,
191
+ initialMaybeWellFormed,
192
+ ``,
193
+ thrown1.message,
194
+ ].join(`\n❌\t`),
195
+ )
196
+ }
134
197
  }
135
198
  }
136
- } catch (error) {
137
- console.error(`❌❌❌`)
138
- console.error(this.incompleteLog)
139
- console.error(error)
140
- console.error(`❌❌❌️`)
199
+ ++idx
141
200
  }
142
201
  })
143
- if (process.pid) {
144
- this.id = process.pid.toString()
202
+ if (proc.pid) {
203
+ this.id = proc.pid.toString()
145
204
  }
146
205
  }
147
206
  }
@@ -1,35 +1,37 @@
1
1
  import type { Json, stringified } from "atom.io/json"
2
2
 
3
- import type { Socket } from ".."
3
+ import type { Socket } from "../socket-interface"
4
4
 
5
5
  export type Events = Json.Object<string, Json.Serializable[]>
6
6
 
7
- export type StringifiedEvent<
8
- Key extends string,
9
- Params extends Json.Serializable[],
10
- > = stringified<[Key, ...Params]>
7
+ export type EventPayload<
8
+ receiveRelay extends Events,
9
+ K extends string & keyof receiveRelay = string & keyof receiveRelay,
10
+ > = [string, ...receiveRelay[K]]
11
11
 
12
12
  export interface EventBuffer<
13
- Key extends string,
14
- Params extends Json.Serializable[],
13
+ E extends Events,
14
+ K extends string & keyof E = string & keyof E,
15
15
  > extends Buffer {
16
- toString(): StringifiedEvent<Key, Params>
16
+ toString(): stringified<EventPayload<E, K>>
17
17
  }
18
18
 
19
- export class CustomSocket<I extends Events, O extends Events> implements Socket {
19
+ export abstract class CustomSocket<I extends Events, O extends Events>
20
+ implements Socket
21
+ {
20
22
  protected listeners: Map<keyof O, Set<(...args: Json.Array) => void>>
21
23
  protected globalListeners: Set<(event: string, ...args: Json.Array) => void>
22
- protected handleEvent<Event extends keyof I>(
23
- event: string,
24
- ...args: I[Event]
24
+ protected handleEvent<K extends string & keyof I>(
25
+ ...args: EventPayload<I, K>
25
26
  ): void {
27
+ const [event, ...rest] = args
26
28
  for (const listener of this.globalListeners) {
27
- listener(event, ...args)
29
+ listener(event, ...rest)
28
30
  }
29
31
  const listeners = this.listeners.get(event)
30
32
  if (listeners) {
31
33
  for (const listener of listeners) {
32
- listener(...args)
34
+ listener(...rest)
33
35
  }
34
36
  }
35
37
  }