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/README.md +90 -111
- package/bin.js +142 -53
- package/index.d.ts +301 -81
- package/index.js +132 -204
- package/lib/assets.js +54 -0
- package/lib/fs.js +2 -4
- package/lib/graph.js +96 -0
- package/lib/language/javascript.js +74 -0
- package/lib/language/kotlin.js +109 -0
- package/lib/language/python.js +65 -0
- package/lib/language/swift.js +111 -0
- package/lib/language.js +18 -0
- package/lib/link.js +141 -0
- package/lib/provider.js +33 -0
- package/lib/rpc/bare-rpc.js +220 -15
- package/lib/rpc.js +6 -18
- package/lib/shim.js +24 -31
- package/lib/target/bare-kit.js +144 -0
- package/lib/target/bare-sidecar.js +86 -53
- package/lib/target/bare-worker.js +18 -72
- package/lib/target/javascript.js +63 -0
- package/lib/target/swift.js +57 -0
- package/lib/target.js +43 -12
- package/package.json +5 -21
- package/lib/host.d.ts +0 -64
- package/lib/host.js +0 -114
- package/lib/protocol.d.ts +0 -46
- package/lib/protocol.js +0 -139
- package/lib/runtime.d.ts +0 -29
- package/lib/runtime.js +0 -92
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
const harness = require('./javascript')
|
|
2
|
+
|
|
1
3
|
exports.name = 'bare-worker'
|
|
4
|
+
exports.isolation = 'thread'
|
|
2
5
|
exports.linked = false
|
|
3
6
|
exports.offload = true
|
|
4
7
|
exports.format = 'bundle'
|
|
@@ -13,80 +16,23 @@ exports.hosts = [
|
|
|
13
16
|
'win32-x64'
|
|
14
17
|
]
|
|
15
18
|
|
|
16
|
-
exports.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
: `{ ${ipc}: import('bare-stow/host').IPC }`
|
|
26
|
-
|
|
27
|
-
const source = esm
|
|
28
|
-
? `\
|
|
29
|
-
import Worker from 'bare-worker'
|
|
30
|
-
import stow from 'bare-stow/host'
|
|
31
|
-
|
|
32
|
-
const bundle = import.meta.resolve(${JSON.stringify(bundleSpecifier)})
|
|
19
|
+
exports.languages = {
|
|
20
|
+
javascript: {
|
|
21
|
+
generate(context) {
|
|
22
|
+
return harness(context, {
|
|
23
|
+
name: 'bare-worker',
|
|
24
|
+
version: '^4.3.0',
|
|
25
|
+
binding: 'Worker',
|
|
26
|
+
setup: `\
|
|
27
|
+
const worker = new Worker(bundle, opts)
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
const worker = new Worker(bundle, opts)
|
|
36
|
-
|
|
37
|
-
const ${ipc} = stow.wrap(worker.IPC, { kill: () => worker.terminate(), timeout, grace })
|
|
38
|
-
|
|
39
|
-
// The IPC stream of a worker ends, but never closes, when its thread exits.
|
|
40
|
-
worker.IPC.on('end', () => worker.IPC.destroy())
|
|
41
|
-
|
|
42
|
-
worker.on('exit', (code) => ${ipc}.exited(code))
|
|
43
|
-
${client ? '\n' + indent(client.source, 2) : ''}
|
|
44
|
-
await ${ipc}.ready
|
|
45
|
-
|
|
46
|
-
return ${returned}
|
|
47
|
-
}
|
|
48
|
-
`
|
|
49
|
-
: `\
|
|
50
|
-
const Worker = require('bare-worker')
|
|
51
|
-
const stow = require('bare-stow/host')
|
|
29
|
+
const ipc = stow.wrap(worker.IPC, { kill: () => worker.terminate(), timeout, grace })
|
|
52
30
|
|
|
53
|
-
|
|
31
|
+
worker.IPC.on('end', () => worker.IPC.destroy())
|
|
54
32
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const ${ipc} = stow.wrap(worker.IPC, { kill: () => worker.terminate(), timeout, grace })
|
|
60
|
-
|
|
61
|
-
// The IPC stream of a worker ends, but never closes, when its thread exits.
|
|
62
|
-
worker.IPC.on('end', () => worker.IPC.destroy())
|
|
63
|
-
|
|
64
|
-
worker.on('exit', (code) => ${ipc}.exited(code))
|
|
65
|
-
${client ? '\n' + indent(client.source, 4) : ''}
|
|
66
|
-
await ${ipc}.ready
|
|
67
|
-
|
|
68
|
-
return ${returned}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
`
|
|
72
|
-
|
|
73
|
-
return [
|
|
74
|
-
{ source },
|
|
75
|
-
{
|
|
76
|
-
extension: '.d.ts',
|
|
77
|
-
source: `\
|
|
78
|
-
export function start(
|
|
79
|
-
opts?: import('bare-worker').WorkerOptions & Omit<import('bare-stow/host').IPCOptions, 'kill'>
|
|
80
|
-
): Promise<${handle}>
|
|
81
|
-
`
|
|
33
|
+
worker.on('exit', (code) => ipc.exited(code))`,
|
|
34
|
+
types: "import('bare-worker').WorkerOptions"
|
|
35
|
+
})
|
|
82
36
|
}
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function indent(source, spaces) {
|
|
87
|
-
const pad = ' '.repeat(spaces)
|
|
88
|
-
return source
|
|
89
|
-
.split('\n')
|
|
90
|
-
.map((line) => (line.length === 0 ? line : pad + line))
|
|
91
|
-
.join('\n')
|
|
37
|
+
}
|
|
92
38
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module.exports = function harness(context, target) {
|
|
2
|
+
const { bundle, client, options } = context
|
|
3
|
+
const { name, version, binding, url = false, setup, types } = target
|
|
4
|
+
|
|
5
|
+
const esm = options.module === 'esm'
|
|
6
|
+
|
|
7
|
+
const body = `\
|
|
8
|
+
${setup}
|
|
9
|
+
${client ? '\nconst rpc = client.attach(ipc, handlers)\n' : ''}
|
|
10
|
+
await ipc.ready
|
|
11
|
+
|
|
12
|
+
return ${client ? '{ ipc, rpc }' : '{ ipc }'}`
|
|
13
|
+
|
|
14
|
+
const source = esm
|
|
15
|
+
? `\
|
|
16
|
+
import ${binding} from '${name}'
|
|
17
|
+
import stow from 'bare-stow-host'
|
|
18
|
+
${client ? `import * as client from ${JSON.stringify(client)}\n` : ''}
|
|
19
|
+
const bundle = ${url ? `new URL(import.meta.resolve(${JSON.stringify(bundle)}))` : `import.meta.resolve(${JSON.stringify(bundle)})`}
|
|
20
|
+
|
|
21
|
+
export async function start({ timeout, grace, ${client ? 'handlers = () => {}, ' : ''}...opts } = {}) {
|
|
22
|
+
${indent(body, 2)}
|
|
23
|
+
}
|
|
24
|
+
`
|
|
25
|
+
: `\
|
|
26
|
+
const ${binding} = require('${name}')
|
|
27
|
+
const stow = require('bare-stow-host')
|
|
28
|
+
${client ? `const client = require(${JSON.stringify(client)})\n` : ''}
|
|
29
|
+
const bundle = require.resolve(${JSON.stringify(bundle)})
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
async start({ timeout, grace, ${client ? 'handlers = () => {}, ' : ''}...opts } = {}) {
|
|
33
|
+
${indent(body, 4)}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`
|
|
37
|
+
|
|
38
|
+
const handle = client
|
|
39
|
+
? `{ ipc: import('bare-stow-host').IPC; rpc: ReturnType<typeof import(${JSON.stringify(client)}).attach> }`
|
|
40
|
+
: `{ ipc: import('bare-stow-host').IPC }`
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
source,
|
|
44
|
+
dependencies: {
|
|
45
|
+
[name]: version,
|
|
46
|
+
'bare-stow-host': '^0.1.0'
|
|
47
|
+
},
|
|
48
|
+
types: `\
|
|
49
|
+
export function start(
|
|
50
|
+
opts?: ${types} & Omit<import('bare-stow-host').IPCOptions, 'kill'>${client ? ` & { handlers?: import(${JSON.stringify(client)}).Handlers }` : ''}
|
|
51
|
+
): Promise<${handle}>
|
|
52
|
+
`
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function indent(source, spaces) {
|
|
57
|
+
const pad = ' '.repeat(spaces)
|
|
58
|
+
|
|
59
|
+
return source
|
|
60
|
+
.split('\n')
|
|
61
|
+
.map((line) => (line.length === 0 ? line : pad + line))
|
|
62
|
+
.join('\n')
|
|
63
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// The harness qualifies `BareStowHost.IPC` as runtimes such as Bare Kit declare
|
|
2
|
+
// an `IPC` of their own.
|
|
3
|
+
module.exports = function harness(context, target) {
|
|
4
|
+
const { bundle, client } = context
|
|
5
|
+
const { module, conformance, fields = {}, params = [], setup, dependencies } = target
|
|
6
|
+
|
|
7
|
+
const started = { ...fields, ipc: 'BareStowHost.IPC' }
|
|
8
|
+
|
|
9
|
+
if (client) started.rpc = 'Client'
|
|
10
|
+
|
|
11
|
+
const source = `\
|
|
12
|
+
import ${module}
|
|
13
|
+
import BareStowHost
|
|
14
|
+
import Foundation
|
|
15
|
+
|
|
16
|
+
${conformance}
|
|
17
|
+
|
|
18
|
+
public struct Started: Sendable {
|
|
19
|
+
${Object.entries(started)
|
|
20
|
+
.map(([name, type]) => ` public let ${name}: ${type}`)
|
|
21
|
+
.join('\n')}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public func start(
|
|
25
|
+
${[
|
|
26
|
+
...params,
|
|
27
|
+
'timeout: TimeInterval? = nil',
|
|
28
|
+
'grace: TimeInterval = BareStowHost.IPC.defaultGrace',
|
|
29
|
+
...(client ? ['handlers: Handlers? = nil'] : [])
|
|
30
|
+
]
|
|
31
|
+
.map((param) => ' ' + param)
|
|
32
|
+
.join(',\n')}
|
|
33
|
+
) async throws -> Started {
|
|
34
|
+
let bundle = Bundle.module.url(forResource: ${JSON.stringify(bundle)}, withExtension: nil)!
|
|
35
|
+
|
|
36
|
+
${setup.replace(/^(?=.)/gm, ' ')}
|
|
37
|
+
${client ? '\n let rpc = attach(ipc, handlers)\n' : ''}
|
|
38
|
+
try await ipc.ready()
|
|
39
|
+
|
|
40
|
+
return Started(${Object.keys(started)
|
|
41
|
+
.map((name) => `${name}: ${name}`)
|
|
42
|
+
.join(', ')})
|
|
43
|
+
}
|
|
44
|
+
`
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
source,
|
|
48
|
+
dependencies: {
|
|
49
|
+
...dependencies,
|
|
50
|
+
'bare-stow-host-swift': {
|
|
51
|
+
url: 'https://github.com/holepunchto/bare-stow-host-swift',
|
|
52
|
+
from: '0.1.0',
|
|
53
|
+
products: ['BareStowHost']
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
package/lib/target.js
CHANGED
|
@@ -1,28 +1,59 @@
|
|
|
1
|
-
const registry =
|
|
1
|
+
const { registry, validateLanguages } = require('./provider')
|
|
2
|
+
|
|
3
|
+
const providers = {
|
|
4
|
+
'bare-kit': () => require('./target/bare-kit'),
|
|
2
5
|
'bare-sidecar': () => require('./target/bare-sidecar'),
|
|
3
6
|
'bare-worker': () => require('./target/bare-worker')
|
|
4
7
|
}
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
const properties = [
|
|
10
|
+
'isolation',
|
|
11
|
+
'linked',
|
|
12
|
+
'linking',
|
|
13
|
+
'offload',
|
|
14
|
+
'format',
|
|
15
|
+
'encoding',
|
|
16
|
+
'extension',
|
|
17
|
+
'hosts'
|
|
18
|
+
]
|
|
8
19
|
|
|
9
|
-
|
|
20
|
+
module.exports = registry('target', providers, function validate(target) {
|
|
21
|
+
validateLanguages('Target', target?.languages)
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
return target
|
|
24
|
+
})
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
module.exports.options = function options(target, given = {}) {
|
|
27
|
+
if (typeof target.options === 'function') return target.options(given)
|
|
14
28
|
|
|
15
|
-
|
|
29
|
+
for (const option of Object.keys(given)) {
|
|
30
|
+
throw new Error(`Unknown option '${option}' for target '${target.name}'`)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {}
|
|
16
34
|
}
|
|
17
35
|
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
36
|
+
// A property may instead be a function of the language of the harness, the
|
|
37
|
+
// options it resolved, and the options of the target, such as hosts that differ
|
|
38
|
+
// between languages.
|
|
39
|
+
module.exports.resolve = function resolve(target, context) {
|
|
40
|
+
const resolved = { linking: 'package', ...target }
|
|
41
|
+
|
|
42
|
+
for (const property of properties) {
|
|
43
|
+
if (typeof target[property] === 'function') resolved[property] = target[property](context)
|
|
21
44
|
}
|
|
22
45
|
|
|
23
|
-
if (
|
|
46
|
+
if (resolved.isolation !== 'process' && resolved.isolation !== 'thread') {
|
|
47
|
+
throw new Error("Target must provide an isolation of 'process' or 'thread'")
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (resolved.linking !== 'package' && resolved.linking !== 'app') {
|
|
51
|
+
throw new Error("Target must provide a linking of 'package' or 'app'")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!Array.isArray(resolved.hosts)) {
|
|
24
55
|
throw new Error('Target must provide a hosts array')
|
|
25
56
|
}
|
|
26
57
|
|
|
27
|
-
return
|
|
58
|
+
return resolved
|
|
28
59
|
}
|
package/package.json
CHANGED
|
@@ -1,24 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bare-stow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Module bundling and harness generation for Bare",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./package": "./package.json",
|
|
7
7
|
".": {
|
|
8
8
|
"types": "./index.d.ts",
|
|
9
9
|
"default": "./index.js"
|
|
10
|
-
},
|
|
11
|
-
"./protocol": {
|
|
12
|
-
"types": "./lib/protocol.d.ts",
|
|
13
|
-
"default": "./lib/protocol.js"
|
|
14
|
-
},
|
|
15
|
-
"./host": {
|
|
16
|
-
"types": "./lib/host.d.ts",
|
|
17
|
-
"default": "./lib/host.js"
|
|
18
|
-
},
|
|
19
|
-
"./runtime": {
|
|
20
|
-
"types": "./lib/runtime.d.ts",
|
|
21
|
-
"default": "./lib/runtime.js"
|
|
22
10
|
}
|
|
23
11
|
},
|
|
24
12
|
"imports": {
|
|
@@ -66,23 +54,23 @@
|
|
|
66
54
|
},
|
|
67
55
|
"homepage": "https://github.com/holepunchto/bare-stow#readme",
|
|
68
56
|
"dependencies": {
|
|
69
|
-
"b4a": "^1.6.0",
|
|
70
57
|
"bare-bundle": "^1.8.3",
|
|
71
58
|
"bare-bundle-id": "^1.0.0",
|
|
72
59
|
"bare-fs": "^4.2.1",
|
|
73
|
-
"bare-
|
|
60
|
+
"bare-link": "^4.1.0",
|
|
74
61
|
"bare-module-traverse": "^2.2.0",
|
|
75
62
|
"bare-pack": "^3.0.0",
|
|
76
63
|
"bare-path": "^3.0.0",
|
|
77
|
-
"bare-signals": "^5.0.0",
|
|
78
|
-
"bare-stream": "^2.13.1",
|
|
79
64
|
"bare-type-stripper": "^0.1.2",
|
|
65
|
+
"bare-unpack": "^1.1.3",
|
|
80
66
|
"paparam": "^1.5.0"
|
|
81
67
|
},
|
|
82
68
|
"devDependencies": {
|
|
83
69
|
"bare-os": "^3.0.0",
|
|
84
70
|
"bare-rpc": "^1.3.2",
|
|
85
71
|
"bare-sidecar": "^0.5.11",
|
|
72
|
+
"bare-stow-host": "^0.1.0",
|
|
73
|
+
"bare-stow-runtime": "^0.1.0",
|
|
86
74
|
"bare-worker": "^4.3.0",
|
|
87
75
|
"brittle": "^4.0.2",
|
|
88
76
|
"lunte": "^1.7.0",
|
|
@@ -91,13 +79,9 @@
|
|
|
91
79
|
"which-runtime": "^1.4.0"
|
|
92
80
|
},
|
|
93
81
|
"peerDependencies": {
|
|
94
|
-
"bare-buffer": "^3.6.0",
|
|
95
82
|
"bare-url": "^2.4.0"
|
|
96
83
|
},
|
|
97
84
|
"peerDependenciesMeta": {
|
|
98
|
-
"bare-buffer": {
|
|
99
|
-
"optional": true
|
|
100
|
-
},
|
|
101
85
|
"bare-url": {
|
|
102
86
|
"optional": true
|
|
103
87
|
}
|
package/lib/host.d.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Duplex } from 'bare-stream'
|
|
2
|
-
import { Protocol } from './protocol'
|
|
3
|
-
|
|
4
|
-
/** Options for `wrap()`. */
|
|
5
|
-
interface IPCOptions {
|
|
6
|
-
/**
|
|
7
|
-
* Stop the worker once it has ignored a `terminate` control frame for `grace` milliseconds.
|
|
8
|
-
* Defaults to destroying `stream`.
|
|
9
|
-
*/
|
|
10
|
-
kill?: () => unknown
|
|
11
|
-
/**
|
|
12
|
-
* The number of milliseconds to wait for the worker to signal ready before rejecting `ready` and
|
|
13
|
-
* terminating the worker, or `null` to wait indefinitely. Defaults to `null`.
|
|
14
|
-
*/
|
|
15
|
-
timeout?: number | null
|
|
16
|
-
/**
|
|
17
|
-
* The number of milliseconds to wait for the worker to exit after a `terminate` control frame
|
|
18
|
-
* before calling `kill`. Defaults to `5000`.
|
|
19
|
-
*/
|
|
20
|
-
grace?: number
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface IPC extends Protocol {
|
|
24
|
-
/**
|
|
25
|
-
* A promise that resolves once the worker has signaled ready, and rejects if the worker errors,
|
|
26
|
-
* exits, or times out before then. The worker is terminated when it rejects.
|
|
27
|
-
*/
|
|
28
|
-
readonly ready: Promise<void>
|
|
29
|
-
/**
|
|
30
|
-
* Send a `terminate` control frame to the worker and resolve once it exits, killing it if it has
|
|
31
|
-
* not exited within the grace period.
|
|
32
|
-
* @returns The worker's exit `code`, or `undefined` if it closed without signaling one.
|
|
33
|
-
*/
|
|
34
|
-
terminate(): Promise<number | undefined>
|
|
35
|
-
/**
|
|
36
|
-
* Report that the worker has exited, as observed by the transport. If the worker exited without
|
|
37
|
-
* saying why and was not asked to, the handle is destroyed with an error carrying the reason as
|
|
38
|
-
* `exitCode` and `signalCode`.
|
|
39
|
-
* @param code - The exit code of the worker, or `null` if it was killed by a signal.
|
|
40
|
-
* @param signal - The signal that killed the worker, or `null` (default `null`).
|
|
41
|
-
*/
|
|
42
|
-
exited(code: number | null, signal?: string | null): void
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
declare class IPC {
|
|
46
|
-
/**
|
|
47
|
-
* Wrap the host side of a stowed bundle's transport `stream`.
|
|
48
|
-
* @param stream - The host side of a stowed bundle's transport (any duplex byte stream).
|
|
49
|
-
* @param opts - Options; see [`IPCOptions`](#ipcoptions).
|
|
50
|
-
*/
|
|
51
|
-
constructor(stream: Duplex, opts?: IPCOptions)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Wrap the host side of a stowed bundle's transport `stream`, returning an `IPC` handle with
|
|
56
|
-
* lifecycle helpers layered on top of the `Protocol`.
|
|
57
|
-
* @param stream - The host side of a stowed bundle's transport (any duplex byte stream).
|
|
58
|
-
* @param opts - Options; see [`IPCOptions`](#ipcoptions).
|
|
59
|
-
* @returns An `IPC` handle wrapping `stream`, with the `ready` promise and `terminate()` layered on
|
|
60
|
-
* top of `Protocol`.
|
|
61
|
-
*/
|
|
62
|
-
declare function wrap(stream: Duplex, opts?: IPCOptions): IPC
|
|
63
|
-
|
|
64
|
-
export { IPC, type IPCOptions, wrap }
|
package/lib/host.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
const { Protocol, DEFAULT_GRACE } = require('./protocol')
|
|
2
|
-
|
|
3
|
-
class IPC extends Protocol {
|
|
4
|
-
constructor(stream, opts = {}) {
|
|
5
|
-
super(stream)
|
|
6
|
-
|
|
7
|
-
const { kill = () => stream.destroy(), timeout = null, grace = DEFAULT_GRACE } = opts
|
|
8
|
-
|
|
9
|
-
this._kill = kill
|
|
10
|
-
this._grace = grace
|
|
11
|
-
this._terminating = null
|
|
12
|
-
this._exitReported = false
|
|
13
|
-
|
|
14
|
-
this.once('exit', () => {
|
|
15
|
-
this._exitReported = true
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
this.send('configure', { grace })
|
|
19
|
-
|
|
20
|
-
this._ready = new Promise((resolve, reject) => {
|
|
21
|
-
const timer =
|
|
22
|
-
timeout === null
|
|
23
|
-
? null
|
|
24
|
-
: setTimeout(() => onerror(new Error('Worker timed out before ready')), timeout)
|
|
25
|
-
|
|
26
|
-
const cleanup = () => {
|
|
27
|
-
clearTimeout(timer)
|
|
28
|
-
this.off('ready', onready).off('error', onerror).off('exit', onexit).off('close', onclose)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const onready = () => {
|
|
32
|
-
cleanup()
|
|
33
|
-
resolve()
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const onerror = (err) => {
|
|
37
|
-
cleanup()
|
|
38
|
-
reject(err)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const onexit = (code) => {
|
|
42
|
-
// An error frame precedes the exit frame and is emitted on destroy
|
|
43
|
-
if (this.destroying) return
|
|
44
|
-
onerror(new Error(`Worker exited with code ${code} before ready`))
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const onclose = () => onerror(new Error('Worker closed before ready'))
|
|
48
|
-
|
|
49
|
-
this.on('ready', onready).on('error', onerror).on('exit', onexit).on('close', onclose)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
this._ready.catch(() => this.destroy())
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
get ready() {
|
|
56
|
-
return this._ready
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
terminate() {
|
|
60
|
-
if (this._stream.destroyed) return Promise.resolve(undefined)
|
|
61
|
-
|
|
62
|
-
return new Promise((resolve) => {
|
|
63
|
-
this.once('exit', resolve)
|
|
64
|
-
|
|
65
|
-
this._terminate().then(() => {
|
|
66
|
-
this.off('exit', resolve)
|
|
67
|
-
resolve(undefined)
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
exited(code, signal = null) {
|
|
73
|
-
// The worker either said why it exited or was asked to.
|
|
74
|
-
if (this._exitReported || this._terminating !== null || this.destroying) return
|
|
75
|
-
|
|
76
|
-
const err = new Error(
|
|
77
|
-
signal === null ? `Worker exited with code ${code}` : `Worker was killed by ${signal}`
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
err.exitCode = code
|
|
81
|
-
err.signalCode = signal
|
|
82
|
-
|
|
83
|
-
this.destroy(err)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
_destroy(err, cb) {
|
|
87
|
-
if (this._stream.destroyed) return cb(null)
|
|
88
|
-
|
|
89
|
-
this._terminate().then(() => cb(null))
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
_terminate() {
|
|
93
|
-
if (this._terminating !== null) return this._terminating
|
|
94
|
-
|
|
95
|
-
const timer = setTimeout(() => this._kill(), this._grace)
|
|
96
|
-
|
|
97
|
-
this.send('terminate')
|
|
98
|
-
|
|
99
|
-
this._terminating = new Promise((resolve) => {
|
|
100
|
-
this._stream.once('close', () => {
|
|
101
|
-
clearTimeout(timer)
|
|
102
|
-
resolve()
|
|
103
|
-
})
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
return this._terminating
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
exports.IPC = IPC
|
|
111
|
-
|
|
112
|
-
exports.wrap = function wrap(stream, opts) {
|
|
113
|
-
return new IPC(stream, opts)
|
|
114
|
-
}
|
package/lib/protocol.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Duplex, DuplexEvents } from 'bare-stream'
|
|
2
|
-
|
|
3
|
-
/** The frame type marker identifying a control-channel frame. */
|
|
4
|
-
declare const CONTROL: number
|
|
5
|
-
/** The frame type marker identifying a user-data-channel frame. */
|
|
6
|
-
declare const USER: number
|
|
7
|
-
/** The default number of milliseconds a terminating worker gets to stop and exit. */
|
|
8
|
-
declare const DEFAULT_GRACE: number
|
|
9
|
-
|
|
10
|
-
/** The events emitted by a `Protocol`, in addition to the standard duplex stream events. */
|
|
11
|
-
interface ProtocolEvents extends DuplexEvents {
|
|
12
|
-
/** Emitted when the worker signals it is ready. */
|
|
13
|
-
ready: []
|
|
14
|
-
/** Emitted when a `terminate` control frame is received. */
|
|
15
|
-
terminate: []
|
|
16
|
-
/** Emitted when the worker signals exit, carrying its exit `code`. */
|
|
17
|
-
exit: [code: number]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface Protocol<E extends ProtocolEvents = ProtocolEvents> extends Duplex<E> {
|
|
21
|
-
/**
|
|
22
|
-
* Send a control frame of `type` with an optional JSON-serializable `payload`.
|
|
23
|
-
* @param type - The control frame type, for example `'ready'`, `'exit'`, `'error'`, or
|
|
24
|
-
* `'terminate'`.
|
|
25
|
-
* @param payload - An optional JSON-serializable payload carried with the frame.
|
|
26
|
-
*/
|
|
27
|
-
send(type: string, payload?: object): Promise<void>
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
declare class Protocol {
|
|
31
|
-
/**
|
|
32
|
-
* Attach a `Protocol` to the given underlying duplex byte `stream`.
|
|
33
|
-
* @param stream - The underlying duplex byte stream to multiplex the control and user-data
|
|
34
|
-
* channels over.
|
|
35
|
-
*/
|
|
36
|
-
constructor(stream: Duplex)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Attach a `Protocol` to `stream`, an underlying duplex byte stream.
|
|
41
|
-
* @param stream - Any duplex byte stream to attach the protocol to.
|
|
42
|
-
* @returns A `Protocol` multiplexing control and user-data frames over `stream`.
|
|
43
|
-
*/
|
|
44
|
-
declare function attach(stream: Duplex): Protocol
|
|
45
|
-
|
|
46
|
-
export { type Protocol, ProtocolEvents, attach, CONTROL, USER, DEFAULT_GRACE }
|