bare-stow 0.1.9 → 0.2.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.
package/lib/protocol.js DELETED
@@ -1,139 +0,0 @@
1
- const { Duplex, Writable } = require('bare-stream')
2
- const b4a = require('b4a')
3
-
4
- const CONTROL = 0x00
5
- const USER = 0x01
6
-
7
- exports.CONTROL = CONTROL
8
- exports.USER = USER
9
-
10
- exports.DEFAULT_GRACE = 5000
11
-
12
- const HEADER_LENGTH = 5
13
-
14
- class Protocol extends Duplex {
15
- constructor(stream) {
16
- super()
17
-
18
- this._stream = stream
19
- this._buffer = []
20
- this._buffered = 0
21
- this._frame = -1
22
-
23
- stream
24
- .on('data', (chunk) => this._ondata(chunk))
25
- .on('end', () => this.push(null))
26
- .on('close', () => this.destroy())
27
- .on('error', (err) => this._onerror(err))
28
- }
29
-
30
- send(type, payload) {
31
- const frame = encodeFrame(CONTROL, b4a.from(JSON.stringify({ type, ...payload })))
32
-
33
- this._stream.write(frame)
34
-
35
- return Writable.drained(this._stream)
36
- }
37
-
38
- _write(data, encoding, cb) {
39
- const frame = encodeFrame(USER, data)
40
-
41
- const ok = this._stream.write(frame)
42
-
43
- if (ok) return cb(null)
44
-
45
- this._stream.once('drain', () => cb(null))
46
- }
47
-
48
- _destroy(err, cb) {
49
- this._stream.destroy()
50
- cb(null)
51
- }
52
-
53
- _onerror(err) {
54
- // On Linux, a peer that goes away with data still unread resets the
55
- // connection rather than ending it, which is no different from it closing.
56
- if (err.code === 'ECONNRESET') this.destroy()
57
- else this.destroy(err)
58
- }
59
-
60
- _ondata(chunk) {
61
- this._buffer.push(chunk)
62
- this._buffered += chunk.byteLength
63
-
64
- if (this._frame === -1) this._onbeforeframe()
65
- else this._onafterframe()
66
- }
67
-
68
- _onbeforeframe() {
69
- if (this._buffered < 4) return
70
-
71
- const buffer = this._buffer.length === 1 ? this._buffer[0] : b4a.concat(this._buffer)
72
-
73
- this._buffer = [buffer]
74
- this._frame = 4 + b4a.readUInt32LE(buffer, 0)
75
-
76
- this._onafterframe()
77
- }
78
-
79
- _onafterframe() {
80
- if (this._buffered < this._frame) return
81
-
82
- const buffer = this._buffer.length === 1 ? this._buffer[0] : b4a.concat(this._buffer)
83
- const frame = this._frame
84
-
85
- this._buffered -= frame
86
- this._buffer = this._buffered > 0 ? [buffer.subarray(frame)] : []
87
- this._frame = -1
88
-
89
- this._onframe(buffer.subarray(0, frame))
90
- this._onbeforeframe()
91
- }
92
-
93
- _onframe(frame) {
94
- const tag = frame[4]
95
- const payload = frame.subarray(HEADER_LENGTH)
96
-
97
- if (tag === USER) {
98
- this.push(b4a.from(payload))
99
- } else if (tag === CONTROL) {
100
- let message
101
-
102
- try {
103
- message = JSON.parse(b4a.toString(payload))
104
- } catch {
105
- return
106
- }
107
-
108
- if (message.type === 'error') {
109
- const err = new Error(message.message)
110
-
111
- if (message.stack) err.stack = message.stack
112
-
113
- this.destroy(err)
114
- } else if (message.type === 'exit') {
115
- this.emit('exit', message.code)
116
- } else {
117
- this.emit(message.type, message)
118
- }
119
- }
120
- }
121
- }
122
-
123
- exports.Protocol = Protocol
124
-
125
- exports.attach = function attach(stream) {
126
- return new Protocol(stream)
127
- }
128
-
129
- function encodeFrame(tag, data) {
130
- const length = data.length + 1
131
- const frame = b4a.alloc(HEADER_LENGTH + data.length)
132
-
133
- b4a.writeUInt32LE(frame, length, 0)
134
- frame[4] = tag
135
-
136
- b4a.copy(data, frame, HEADER_LENGTH)
137
-
138
- return frame
139
- }
package/lib/runtime.d.ts DELETED
@@ -1,29 +0,0 @@
1
- import { Duplex } from 'bare-stream'
2
- import { Protocol } from './protocol'
3
-
4
- interface Runtime extends Protocol {
5
- /**
6
- * Load the bundle entry and start it with `arg`, signaling ready once its `start()` resolves.
7
- * @param load - A function importing the bundle entry module.
8
- * @param arg - The value passed to the entry's `start()`.
9
- */
10
- run(load: () => Promise<{ default: Function }>, arg: unknown): Promise<void>
11
- }
12
-
13
- declare class Runtime {
14
- /**
15
- * Attach the worker side of a stowed bundle's lifecycle to `stream`.
16
- * @param stream - The worker side of a stowed bundle's transport, typically `Bare.IPC`.
17
- */
18
- constructor(stream: Duplex)
19
- }
20
-
21
- /**
22
- * Attach the worker side of a stowed bundle's lifecycle to `stream`, shutting the worker down on
23
- * `terminate`, `SIGTERM`, runtime exit, uncaught errors, or loss of the host.
24
- * @param stream - The worker side of a stowed bundle's transport, typically `Bare.IPC`.
25
- * @returns A `Runtime` multiplexing control and user-data frames over `stream`.
26
- */
27
- declare function attach(stream: Duplex): Runtime
28
-
29
- export { Runtime, attach }
package/lib/runtime.js DELETED
@@ -1,92 +0,0 @@
1
- const { Protocol, DEFAULT_GRACE } = require('./protocol')
2
-
3
- class Runtime extends Protocol {
4
- constructor(stream) {
5
- super(stream)
6
-
7
- this._stop = null
8
- this._grace = DEFAULT_GRACE
9
- this._readied = false
10
- this._exitCode = null
11
- this._connected = true
12
-
13
- const ondisconnect = () => this._ondisconnect()
14
-
15
- this.on('configure', ({ grace }) => {
16
- this._grace = grace
17
- }).on('terminate', () => this._shutdown(0))
18
-
19
- stream.on('end', ondisconnect).on('close', ondisconnect)
20
-
21
- Bare.on('beforeExit', (code) => this._shutdown(code))
22
- .on('uncaughtException', (err) => this._shutdown(1, err))
23
- .on('unhandledRejection', (err) => this._shutdown(1, err))
24
-
25
- // Signals are delivered to the whole process, so a worker thread must leave
26
- // them to the host.
27
- if (Bare.Thread.isMainThread) {
28
- const Signal = require('bare-signals')
29
-
30
- new Signal('SIGTERM')
31
- .on('signal', () => this._onsigterm())
32
- .start()
33
- .unref()
34
- }
35
- }
36
-
37
- async run(load, arg) {
38
- try {
39
- const entry = await load()
40
-
41
- this._stop = await entry.default(arg, () => this._ready())
42
-
43
- this._ready()
44
- } catch (err) {
45
- this._shutdown(1, err)
46
- }
47
- }
48
-
49
- _ready() {
50
- if (this._readied) return
51
- this._readied = true
52
-
53
- this.send('ready')
54
- }
55
-
56
- async _shutdown(code, err = null) {
57
- if (this._exitCode !== null) return
58
- this._exitCode = code
59
-
60
- setTimeout(() => Bare.exit(code), this._grace).unref()
61
-
62
- try {
63
- if (this._stop) await this._stop()
64
- } catch (e) {
65
- err = err || e
66
- }
67
-
68
- if (this._connected) {
69
- if (err) this.send('error', { message: err.message, stack: err.stack })
70
-
71
- await this.send('exit', { code })
72
- }
73
-
74
- Bare.exit(code)
75
- }
76
-
77
- _ondisconnect() {
78
- this._connected = false
79
- this._shutdown(0)
80
- }
81
-
82
- _onsigterm() {
83
- if (this._exitCode !== null) Bare.exit(this._exitCode)
84
- else this._shutdown(0)
85
- }
86
- }
87
-
88
- exports.Runtime = Runtime
89
-
90
- exports.attach = function attach(stream) {
91
- return new Runtime(stream)
92
- }