penpal 7.0.3 → 7.0.4
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/dist/penpal.cjs +953 -0
- package/dist/penpal.cjs.map +1 -0
- package/dist/penpal.d.cts +234 -0
- package/dist/penpal.d.ts +234 -0
- package/dist/penpal.js +890 -1033
- package/dist/penpal.js.map +1 -0
- package/dist/penpal.min.js +1 -1
- package/dist/penpal.min.js.map +1 -1
- package/dist/penpal.mjs +943 -0
- package/dist/penpal.mjs.map +1 -0
- package/package.json +13 -21
- package/cjs/CallOptions.d.ts +0 -10
- package/cjs/CallOptions.js +0 -16
- package/cjs/ErrorCodeObj.d.ts +0 -9
- package/cjs/ErrorCodeObj.js +0 -14
- package/cjs/PenpalBugError.d.ts +0 -8
- package/cjs/PenpalBugError.js +0 -12
- package/cjs/PenpalError.d.ts +0 -6
- package/cjs/PenpalError.js +0 -11
- package/cjs/Reply.d.ts +0 -9
- package/cjs/Reply.js +0 -16
- package/cjs/backwardCompatibility.d.ts +0 -56
- package/cjs/backwardCompatibility.js +0 -134
- package/cjs/connect.d.ts +0 -33
- package/cjs/connect.js +0 -78
- package/cjs/connectCallHandler.d.ts +0 -8
- package/cjs/connectCallHandler.js +0 -90
- package/cjs/connectRemoteProxy.d.ts +0 -12
- package/cjs/connectRemoteProxy.js +0 -139
- package/cjs/debug.d.ts +0 -3
- package/cjs/debug.js +0 -8
- package/cjs/errorSerialization.d.ts +0 -9
- package/cjs/errorSerialization.js +0 -26
- package/cjs/generateId.d.ts +0 -8
- package/cjs/generateId.js +0 -11
- package/cjs/getPromiseWithResolvers.d.ts +0 -6
- package/cjs/getPromiseWithResolvers.js +0 -19
- package/cjs/guards.d.ts +0 -10
- package/cjs/guards.js +0 -40
- package/cjs/index.d.ts +0 -12
- package/cjs/index.js +0 -21
- package/cjs/indexForBundle.d.ts +0 -31
- package/cjs/indexForBundle.js +0 -22
- package/cjs/messengers/Messenger.d.ts +0 -14
- package/cjs/messengers/Messenger.js +0 -2
- package/cjs/messengers/PortMessenger.d.ts +0 -21
- package/cjs/messengers/PortMessenger.js +0 -47
- package/cjs/messengers/WindowMessenger.d.ts +0 -29
- package/cjs/messengers/WindowMessenger.js +0 -178
- package/cjs/messengers/WorkerMessenger.d.ts +0 -23
- package/cjs/messengers/WorkerMessenger.js +0 -86
- package/cjs/methodSerialization.d.ts +0 -22
- package/cjs/methodSerialization.js +0 -48
- package/cjs/namespace.d.ts +0 -2
- package/cjs/namespace.js +0 -3
- package/cjs/once.d.ts +0 -2
- package/cjs/once.js +0 -15
- package/cjs/shakeHands.d.ts +0 -76
- package/cjs/shakeHands.js +0 -190
- package/cjs/types.d.ts +0 -89
- package/cjs/types.js +0 -2
- package/lib/CallOptions.d.ts +0 -10
- package/lib/CallOptions.js +0 -14
- package/lib/ErrorCodeObj.d.ts +0 -9
- package/lib/ErrorCodeObj.js +0 -12
- package/lib/PenpalBugError.d.ts +0 -8
- package/lib/PenpalBugError.js +0 -10
- package/lib/PenpalError.d.ts +0 -6
- package/lib/PenpalError.js +0 -9
- package/lib/Reply.d.ts +0 -9
- package/lib/Reply.js +0 -14
- package/lib/backwardCompatibility.d.ts +0 -56
- package/lib/backwardCompatibility.js +0 -128
- package/lib/connect.d.ts +0 -33
- package/lib/connect.js +0 -76
- package/lib/connectCallHandler.d.ts +0 -8
- package/lib/connectCallHandler.js +0 -88
- package/lib/connectRemoteProxy.d.ts +0 -12
- package/lib/connectRemoteProxy.js +0 -137
- package/lib/debug.d.ts +0 -3
- package/lib/debug.js +0 -6
- package/lib/errorSerialization.d.ts +0 -9
- package/lib/errorSerialization.js +0 -21
- package/lib/generateId.d.ts +0 -8
- package/lib/generateId.js +0 -9
- package/lib/getPromiseWithResolvers.d.ts +0 -6
- package/lib/getPromiseWithResolvers.js +0 -17
- package/lib/guards.d.ts +0 -10
- package/lib/guards.js +0 -28
- package/lib/index.d.ts +0 -12
- package/lib/index.js +0 -9
- package/lib/indexForBundle.d.ts +0 -31
- package/lib/indexForBundle.js +0 -20
- package/lib/messengers/Messenger.d.ts +0 -14
- package/lib/messengers/Messenger.js +0 -1
- package/lib/messengers/PortMessenger.d.ts +0 -21
- package/lib/messengers/PortMessenger.js +0 -45
- package/lib/messengers/WindowMessenger.d.ts +0 -29
- package/lib/messengers/WindowMessenger.js +0 -176
- package/lib/messengers/WorkerMessenger.d.ts +0 -23
- package/lib/messengers/WorkerMessenger.js +0 -84
- package/lib/methodSerialization.d.ts +0 -22
- package/lib/methodSerialization.js +0 -42
- package/lib/namespace.d.ts +0 -2
- package/lib/namespace.js +0 -1
- package/lib/once.d.ts +0 -2
- package/lib/once.js +0 -13
- package/lib/shakeHands.d.ts +0 -76
- package/lib/shakeHands.js +0 -188
- package/lib/types.d.ts +0 -89
- package/lib/types.js +0 -1
package/lib/connect.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import PenpalError from './PenpalError.js';
|
|
2
|
-
import shakeHands from './shakeHands.js';
|
|
3
|
-
import { isDestroyMessage, isMessage } from './guards.js';
|
|
4
|
-
import once from './once.js';
|
|
5
|
-
import namespace from './namespace.js';
|
|
6
|
-
const usedMessengers = new WeakSet();
|
|
7
|
-
/**
|
|
8
|
-
* Attempts to establish communication with the remote.
|
|
9
|
-
*/
|
|
10
|
-
const connect = ({ messenger, methods = {}, timeout, channel, log, }) => {
|
|
11
|
-
if (!messenger) {
|
|
12
|
-
throw new PenpalError('INVALID_ARGUMENT', 'messenger must be defined');
|
|
13
|
-
}
|
|
14
|
-
if (usedMessengers.has(messenger)) {
|
|
15
|
-
throw new PenpalError('INVALID_ARGUMENT', 'A messenger can only be used for a single connection');
|
|
16
|
-
}
|
|
17
|
-
usedMessengers.add(messenger);
|
|
18
|
-
const connectionDestroyedHandlers = [messenger.destroy];
|
|
19
|
-
const destroyConnection = once((notifyOtherParticipant) => {
|
|
20
|
-
if (notifyOtherParticipant) {
|
|
21
|
-
const destroyMessage = {
|
|
22
|
-
namespace,
|
|
23
|
-
channel,
|
|
24
|
-
type: 'DESTROY',
|
|
25
|
-
};
|
|
26
|
-
try {
|
|
27
|
-
messenger.sendMessage(destroyMessage);
|
|
28
|
-
}
|
|
29
|
-
catch (_) {
|
|
30
|
-
// We do our best to notify the other participant of the connection, but
|
|
31
|
-
// if there's an error in doing so (e.g., maybe the handshake hasn't
|
|
32
|
-
// completed and a messenger can't send the message), it's probably not
|
|
33
|
-
// worth bothering the consumer with an error.
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
for (const connectionDestroyedHandler of connectionDestroyedHandlers) {
|
|
37
|
-
connectionDestroyedHandler();
|
|
38
|
-
}
|
|
39
|
-
log?.('Connection destroyed');
|
|
40
|
-
});
|
|
41
|
-
const validateReceivedMessage = (data) => {
|
|
42
|
-
return isMessage(data) && data.channel === channel;
|
|
43
|
-
};
|
|
44
|
-
const promise = (async () => {
|
|
45
|
-
try {
|
|
46
|
-
messenger.initialize({ log, validateReceivedMessage });
|
|
47
|
-
messenger.addMessageHandler((message) => {
|
|
48
|
-
if (isDestroyMessage(message)) {
|
|
49
|
-
destroyConnection(false);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
const { remoteProxy, destroy } = await shakeHands({
|
|
53
|
-
messenger,
|
|
54
|
-
methods,
|
|
55
|
-
timeout,
|
|
56
|
-
channel,
|
|
57
|
-
log,
|
|
58
|
-
});
|
|
59
|
-
connectionDestroyedHandlers.push(destroy);
|
|
60
|
-
return remoteProxy;
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
destroyConnection(true);
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
})();
|
|
67
|
-
return {
|
|
68
|
-
promise,
|
|
69
|
-
// Why we don't reject the connection promise when consumer calls destroy():
|
|
70
|
-
// https://github.com/Aaronius/penpal/issues/51
|
|
71
|
-
destroy: () => {
|
|
72
|
-
destroyConnection(true);
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
export default connect;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Methods, Log } from './types.js';
|
|
2
|
-
import Messenger from './messengers/Messenger.js';
|
|
3
|
-
/**
|
|
4
|
-
* Listens for "call" messages from the remote, executes the corresponding method,
|
|
5
|
-
* and responds with the return value or error.
|
|
6
|
-
*/
|
|
7
|
-
declare const connectCallHandler: (messenger: Messenger, methods: Methods, channel: string | undefined, log: Log | undefined) => () => void;
|
|
8
|
-
export default connectCallHandler;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { serializeError } from './errorSerialization.js';
|
|
2
|
-
import Reply from './Reply.js';
|
|
3
|
-
import PenpalError from './PenpalError.js';
|
|
4
|
-
import { formatMethodPath, getMethodAtMethodPath, } from './methodSerialization.js';
|
|
5
|
-
import { isCallMessage } from './guards.js';
|
|
6
|
-
import namespace from './namespace.js';
|
|
7
|
-
const createErrorReplyMessage = (channel, callId, error) => ({
|
|
8
|
-
namespace,
|
|
9
|
-
channel,
|
|
10
|
-
type: 'REPLY',
|
|
11
|
-
callId,
|
|
12
|
-
isError: true,
|
|
13
|
-
...(error instanceof Error
|
|
14
|
-
? { value: serializeError(error), isSerializedErrorInstance: true }
|
|
15
|
-
: { value: error }),
|
|
16
|
-
});
|
|
17
|
-
/**
|
|
18
|
-
* Listens for "call" messages from the remote, executes the corresponding method,
|
|
19
|
-
* and responds with the return value or error.
|
|
20
|
-
*/
|
|
21
|
-
const connectCallHandler = (messenger, methods, channel, log) => {
|
|
22
|
-
let isDestroyed = false;
|
|
23
|
-
const handleMessage = async (message) => {
|
|
24
|
-
if (isDestroyed) {
|
|
25
|
-
// It's possible to throw an error here, but it would only be catchable
|
|
26
|
-
// using window.onerror since we're in an asynchronously-called function.
|
|
27
|
-
// There is no method call the consumer is making that they could wrap in
|
|
28
|
-
// a try-catch. Even if the consumer were to catch the error somehow,
|
|
29
|
-
// the value of doing so is questionable.
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (!isCallMessage(message)) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
log?.(`Received ${formatMethodPath(message.methodPath)}() call`, message);
|
|
36
|
-
const { methodPath, args, id: callId } = message;
|
|
37
|
-
let replyMessage;
|
|
38
|
-
let transferables;
|
|
39
|
-
try {
|
|
40
|
-
const method = getMethodAtMethodPath(methodPath, methods);
|
|
41
|
-
if (!method) {
|
|
42
|
-
throw new PenpalError('METHOD_NOT_FOUND', `Method \`${formatMethodPath(methodPath)}\` is not found.`);
|
|
43
|
-
}
|
|
44
|
-
let value = await method(...args);
|
|
45
|
-
if (value instanceof Reply) {
|
|
46
|
-
transferables = value.transferables;
|
|
47
|
-
value = await value.value;
|
|
48
|
-
}
|
|
49
|
-
replyMessage = {
|
|
50
|
-
namespace,
|
|
51
|
-
channel,
|
|
52
|
-
type: 'REPLY',
|
|
53
|
-
callId,
|
|
54
|
-
value,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
replyMessage = createErrorReplyMessage(channel, callId, error);
|
|
59
|
-
}
|
|
60
|
-
// Although we checked this at the beginning of the function, we need to
|
|
61
|
-
// check it again because we've made async calls, and the connection may
|
|
62
|
-
// have been destroyed in the meantime.
|
|
63
|
-
if (isDestroyed) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
try {
|
|
67
|
-
log?.(`Sending ${formatMethodPath(methodPath)}() reply`, replyMessage);
|
|
68
|
-
messenger.sendMessage(replyMessage, transferables);
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
// If a consumer attempts to send an object that's not
|
|
72
|
-
// cloneable (e.g., window), we want to ensure the receiver's promise
|
|
73
|
-
// gets rejected.
|
|
74
|
-
if (error.name === 'DataCloneError') {
|
|
75
|
-
replyMessage = createErrorReplyMessage(channel, callId, error);
|
|
76
|
-
log?.(`Sending ${formatMethodPath(methodPath)}() reply`, replyMessage);
|
|
77
|
-
messenger.sendMessage(replyMessage);
|
|
78
|
-
}
|
|
79
|
-
throw error;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
messenger.addMessageHandler(handleMessage);
|
|
83
|
-
return () => {
|
|
84
|
-
isDestroyed = true;
|
|
85
|
-
messenger.removeMessageHandler(handleMessage);
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
export default connectCallHandler;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { RemoteProxy, Methods, Log } from './types.js';
|
|
2
|
-
import Messenger from './messengers/Messenger.js';
|
|
3
|
-
/**
|
|
4
|
-
* Creates a proxy. When methods are called on the proxy, a "call" message will
|
|
5
|
-
* be sent to the remote, the remote's corresponding method will be
|
|
6
|
-
* executed, and the method's return value will be returned via a message.
|
|
7
|
-
*/
|
|
8
|
-
declare const connectRemoteProxy: <TMethods extends Methods>(messenger: Messenger, channel: string | undefined, log: Log | undefined) => {
|
|
9
|
-
remoteProxy: RemoteProxy<TMethods>;
|
|
10
|
-
destroy: () => void;
|
|
11
|
-
};
|
|
12
|
-
export default connectRemoteProxy;
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import generateId from './generateId.js';
|
|
2
|
-
import { deserializeError } from './errorSerialization.js';
|
|
3
|
-
import { formatMethodPath } from './methodSerialization.js';
|
|
4
|
-
import CallOptions from './CallOptions.js';
|
|
5
|
-
import PenpalError from './PenpalError.js';
|
|
6
|
-
import { isReplyMessage } from './guards.js';
|
|
7
|
-
import namespace from './namespace.js';
|
|
8
|
-
const methodsToTreatAsNative = new Set(['apply', 'call', 'bind']);
|
|
9
|
-
const createRemoteProxy = (callback, log, path = []) => {
|
|
10
|
-
return new Proxy(path.length
|
|
11
|
-
? () => {
|
|
12
|
-
// Intentionally empty
|
|
13
|
-
}
|
|
14
|
-
: Object.create(null), {
|
|
15
|
-
get(target, prop) {
|
|
16
|
-
// If a promise is resolved with this proxy object, the JavaScript
|
|
17
|
-
// runtime will look for a `then` property on this object to determine
|
|
18
|
-
// if it should be treated as a promise (to support promise chaining).
|
|
19
|
-
// If we don't return undefined here, the JavaScript runtime will treat
|
|
20
|
-
// this object as a promise and attempt to call `then`, which will
|
|
21
|
-
// then send a call message to the remote. This is not what we want.
|
|
22
|
-
if (prop === 'then') {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
// Because we're using a proxy and because Penpal supports developers
|
|
26
|
-
// exposing nested methods, we have a predicament. If a developer
|
|
27
|
-
// calls, for example, remote.auth.apply(), are they
|
|
28
|
-
// attempting to call a nested apply() method that a developer has
|
|
29
|
-
// explicitly exposed from the remote? Could they instead be attempting
|
|
30
|
-
// to call Function.prototype.apply() on the remote.auth() method?
|
|
31
|
-
// Without the remote telling the local Penpal which methods the
|
|
32
|
-
// developer has exposed, it has no way of knowing (and the main reason
|
|
33
|
-
// we use a proxy is so that Penpal doesn't have to communicate which
|
|
34
|
-
// methods are exposed). So, we treat certain methods as native methods
|
|
35
|
-
// and return the native method rather than a proxy. The downside of
|
|
36
|
-
// this is that if a developer has explicitly exposed a nested method
|
|
37
|
-
// with the same name as one of these native method names, the developer
|
|
38
|
-
// will be unable to call the exposed remote method because they will
|
|
39
|
-
// be calling the method on the Function prototype instead.
|
|
40
|
-
if (path.length && methodsToTreatAsNative.has(prop)) {
|
|
41
|
-
return Reflect.get(target, prop);
|
|
42
|
-
}
|
|
43
|
-
return createRemoteProxy(callback, log, [...path, prop]);
|
|
44
|
-
},
|
|
45
|
-
apply(target, _thisArg, args) {
|
|
46
|
-
return callback(path, args);
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
const getDestroyedConnectionMethodCallError = (methodPath) => {
|
|
51
|
-
return new PenpalError('CONNECTION_DESTROYED', `Method call ${formatMethodPath(methodPath)}() failed due to destroyed connection`);
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* Creates a proxy. When methods are called on the proxy, a "call" message will
|
|
55
|
-
* be sent to the remote, the remote's corresponding method will be
|
|
56
|
-
* executed, and the method's return value will be returned via a message.
|
|
57
|
-
*/
|
|
58
|
-
const connectRemoteProxy = (messenger, channel, log) => {
|
|
59
|
-
let isDestroyed = false;
|
|
60
|
-
const replyHandlers = new Map();
|
|
61
|
-
const handleMessage = (message) => {
|
|
62
|
-
if (!isReplyMessage(message)) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
const { callId, value, isError, isSerializedErrorInstance } = message;
|
|
66
|
-
const replyHandler = replyHandlers.get(callId);
|
|
67
|
-
if (!replyHandler) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
replyHandlers.delete(callId);
|
|
71
|
-
log?.(`Received ${formatMethodPath(replyHandler.methodPath)}() call`, message);
|
|
72
|
-
if (isError) {
|
|
73
|
-
replyHandler.reject(isSerializedErrorInstance ? deserializeError(value) : value);
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
replyHandler.resolve(value);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
messenger.addMessageHandler(handleMessage);
|
|
80
|
-
const remoteProxy = createRemoteProxy((methodPath, args) => {
|
|
81
|
-
if (isDestroyed) {
|
|
82
|
-
throw getDestroyedConnectionMethodCallError(methodPath);
|
|
83
|
-
}
|
|
84
|
-
const callId = generateId();
|
|
85
|
-
const lastArg = args[args.length - 1];
|
|
86
|
-
const lastArgIsOptions = lastArg instanceof CallOptions;
|
|
87
|
-
const { timeout, transferables } = lastArgIsOptions ? lastArg : {};
|
|
88
|
-
const argsWithoutOptions = lastArgIsOptions ? args.slice(0, -1) : args;
|
|
89
|
-
return new Promise((resolve, reject) => {
|
|
90
|
-
// We reference `window.setTimeout` instead of just `setTimeout`
|
|
91
|
-
// so that the TypeScript engine doesn't
|
|
92
|
-
// get confused when running tests. Something within
|
|
93
|
-
// Karma + @rollup/plugin-typescript leaks node types into source
|
|
94
|
-
// files when running tests. Node's setTimeout has a return type of
|
|
95
|
-
// Timeout rather than number, resulting in a build error when
|
|
96
|
-
// running tests if we don't disambiguate the browser setTimeout
|
|
97
|
-
// from node's setTimeout. There may be a better way to configure
|
|
98
|
-
// Karma + Rollup + Typescript to avoid node type leakage.
|
|
99
|
-
const timeoutId = timeout !== undefined
|
|
100
|
-
? window.setTimeout(() => {
|
|
101
|
-
replyHandlers.delete(callId);
|
|
102
|
-
reject(new PenpalError('METHOD_CALL_TIMEOUT', `Method call ${formatMethodPath(methodPath)}() timed out after ${timeout}ms`));
|
|
103
|
-
}, timeout)
|
|
104
|
-
: undefined;
|
|
105
|
-
replyHandlers.set(callId, { methodPath, resolve, reject, timeoutId });
|
|
106
|
-
try {
|
|
107
|
-
const callMessage = {
|
|
108
|
-
namespace,
|
|
109
|
-
channel,
|
|
110
|
-
type: 'CALL',
|
|
111
|
-
id: callId,
|
|
112
|
-
methodPath,
|
|
113
|
-
args: argsWithoutOptions,
|
|
114
|
-
};
|
|
115
|
-
log?.(`Sending ${formatMethodPath(methodPath)}() call`, callMessage);
|
|
116
|
-
messenger.sendMessage(callMessage, transferables);
|
|
117
|
-
}
|
|
118
|
-
catch (error) {
|
|
119
|
-
reject(new PenpalError('TRANSMISSION_FAILED', error.message));
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
}, log);
|
|
123
|
-
const destroy = () => {
|
|
124
|
-
isDestroyed = true;
|
|
125
|
-
messenger.removeMessageHandler(handleMessage);
|
|
126
|
-
for (const { methodPath, reject, timeoutId } of replyHandlers.values()) {
|
|
127
|
-
clearTimeout(timeoutId);
|
|
128
|
-
reject(getDestroyedConnectionMethodCallError(methodPath));
|
|
129
|
-
}
|
|
130
|
-
replyHandlers.clear();
|
|
131
|
-
};
|
|
132
|
-
return {
|
|
133
|
-
remoteProxy,
|
|
134
|
-
destroy,
|
|
135
|
-
};
|
|
136
|
-
};
|
|
137
|
-
export default connectRemoteProxy;
|
package/lib/debug.d.ts
DELETED
package/lib/debug.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { SerializedError } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Converts an error object into a plain object.
|
|
4
|
-
*/
|
|
5
|
-
export declare const serializeError: (error: Error) => SerializedError;
|
|
6
|
-
/**
|
|
7
|
-
* Converts a plain object into an error object.
|
|
8
|
-
*/
|
|
9
|
-
export declare const deserializeError: ({ name, message, stack, penpalCode, }: SerializedError) => Error;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import PenpalError from './PenpalError.js';
|
|
2
|
-
/**
|
|
3
|
-
* Converts an error object into a plain object.
|
|
4
|
-
*/
|
|
5
|
-
export const serializeError = (error) => ({
|
|
6
|
-
name: error.name,
|
|
7
|
-
message: error.message,
|
|
8
|
-
stack: error.stack,
|
|
9
|
-
penpalCode: error instanceof PenpalError ? error.code : undefined,
|
|
10
|
-
});
|
|
11
|
-
/**
|
|
12
|
-
* Converts a plain object into an error object.
|
|
13
|
-
*/
|
|
14
|
-
export const deserializeError = ({ name, message, stack, penpalCode, }) => {
|
|
15
|
-
const deserializedError = penpalCode
|
|
16
|
-
? new PenpalError(penpalCode, message)
|
|
17
|
-
: new Error(message);
|
|
18
|
-
deserializedError.name = name;
|
|
19
|
-
deserializedError.stack = stack;
|
|
20
|
-
return deserializedError;
|
|
21
|
-
};
|
package/lib/generateId.d.ts
DELETED
package/lib/generateId.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @return A unique ID
|
|
3
|
-
*/
|
|
4
|
-
// crypto.randomUUID is not available in insecure contexts.
|
|
5
|
-
export default crypto.randomUUID?.bind(crypto) ??
|
|
6
|
-
(() => new Array(4)
|
|
7
|
-
.fill(0)
|
|
8
|
-
.map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
|
|
9
|
-
.join('-'));
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Just use the native Promise.withResolvers() once it gains a bit more
|
|
2
|
-
// adoption. Safari was the last major browser to support it, which happened
|
|
3
|
-
// on March 5, 2024 in Safari 17.4.
|
|
4
|
-
const getPromiseWithResolvers = () => {
|
|
5
|
-
let resolve;
|
|
6
|
-
let reject;
|
|
7
|
-
const promise = new Promise((res, rej) => {
|
|
8
|
-
resolve = res;
|
|
9
|
-
reject = rej;
|
|
10
|
-
});
|
|
11
|
-
return {
|
|
12
|
-
promise,
|
|
13
|
-
resolve: resolve,
|
|
14
|
-
reject: reject,
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
export default getPromiseWithResolvers;
|
package/lib/guards.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Ack2Message, CallMessage, Message, ReplyMessage, Ack1Message, SynMessage, DestroyMessage } from './types.js';
|
|
2
|
-
export declare const isObject: (value: unknown) => value is Record<string | number | symbol, unknown>;
|
|
3
|
-
export declare const isFunction: (value: unknown) => value is Function;
|
|
4
|
-
export declare const isMessage: (data: unknown) => data is Message;
|
|
5
|
-
export declare const isSynMessage: (message: Message) => message is SynMessage;
|
|
6
|
-
export declare const isAck1Message: (message: Message) => message is Ack1Message;
|
|
7
|
-
export declare const isAck2Message: (message: Message) => message is Ack2Message;
|
|
8
|
-
export declare const isCallMessage: (message: Message) => message is CallMessage;
|
|
9
|
-
export declare const isReplyMessage: (message: Message) => message is ReplyMessage;
|
|
10
|
-
export declare const isDestroyMessage: (message: Message) => message is DestroyMessage;
|
package/lib/guards.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import namespace from './namespace.js';
|
|
2
|
-
export const isObject = (value) => {
|
|
3
|
-
return typeof value === 'object' && value !== null;
|
|
4
|
-
};
|
|
5
|
-
export const isFunction = (value) => {
|
|
6
|
-
return typeof value === 'function';
|
|
7
|
-
};
|
|
8
|
-
export const isMessage = (data) => {
|
|
9
|
-
return isObject(data) && data.namespace === namespace;
|
|
10
|
-
};
|
|
11
|
-
export const isSynMessage = (message) => {
|
|
12
|
-
return message.type === 'SYN';
|
|
13
|
-
};
|
|
14
|
-
export const isAck1Message = (message) => {
|
|
15
|
-
return message.type === 'ACK1';
|
|
16
|
-
};
|
|
17
|
-
export const isAck2Message = (message) => {
|
|
18
|
-
return message.type === 'ACK2';
|
|
19
|
-
};
|
|
20
|
-
export const isCallMessage = (message) => {
|
|
21
|
-
return message.type === 'CALL';
|
|
22
|
-
};
|
|
23
|
-
export const isReplyMessage = (message) => {
|
|
24
|
-
return message.type === 'REPLY';
|
|
25
|
-
};
|
|
26
|
-
export const isDestroyMessage = (message) => {
|
|
27
|
-
return message.type === 'DESTROY';
|
|
28
|
-
};
|
package/lib/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export { default as connect } from './connect.js';
|
|
2
|
-
export { default as WindowMessenger } from './messengers/WindowMessenger.js';
|
|
3
|
-
export { default as WorkerMessenger } from './messengers/WorkerMessenger.js';
|
|
4
|
-
export { default as PortMessenger } from './messengers/PortMessenger.js';
|
|
5
|
-
export { default as CallOptions } from './CallOptions.js';
|
|
6
|
-
export { default as Reply } from './Reply.js';
|
|
7
|
-
export { default as PenpalError } from './PenpalError.js';
|
|
8
|
-
export { default as ErrorCode } from './ErrorCodeObj.js';
|
|
9
|
-
export { default as debug } from './debug.js';
|
|
10
|
-
export { Connection, RemoteProxy, Methods } from './types.js';
|
|
11
|
-
export { default as Messenger, InitializeMessengerOptions, MessageHandler, } from './messengers/Messenger.js';
|
|
12
|
-
export { Log, Message, SynMessage, Ack1Message, Ack2Message, CallMessage, ReplyMessage, DestroyMessage, } from './types.js';
|
package/lib/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { default as connect } from './connect.js';
|
|
2
|
-
export { default as WindowMessenger } from './messengers/WindowMessenger.js';
|
|
3
|
-
export { default as WorkerMessenger } from './messengers/WorkerMessenger.js';
|
|
4
|
-
export { default as PortMessenger } from './messengers/PortMessenger.js';
|
|
5
|
-
export { default as CallOptions } from './CallOptions.js';
|
|
6
|
-
export { default as Reply } from './Reply.js';
|
|
7
|
-
export { default as PenpalError } from './PenpalError.js';
|
|
8
|
-
export { default as ErrorCode } from './ErrorCodeObj.js';
|
|
9
|
-
export { default as debug } from './debug.js';
|
package/lib/indexForBundle.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import WindowMessenger from './messengers/WindowMessenger.js';
|
|
2
|
-
import WorkerMessenger from './messengers/WorkerMessenger.js';
|
|
3
|
-
import PortMessenger from './messengers/PortMessenger.js';
|
|
4
|
-
import CallOptions from './CallOptions.js';
|
|
5
|
-
import Reply from './Reply.js';
|
|
6
|
-
import PenpalError from './PenpalError.js';
|
|
7
|
-
declare const _default: {
|
|
8
|
-
connect: <TMethods extends import("./types.js").Methods>({ messenger, methods, timeout, channel, log, }: {
|
|
9
|
-
messenger: import("./index.js").Messenger;
|
|
10
|
-
methods?: import("./types.js").Methods;
|
|
11
|
-
timeout?: number;
|
|
12
|
-
channel?: string;
|
|
13
|
-
log?: import("./types.js").Log;
|
|
14
|
-
}) => import("./types.js").Connection<TMethods>;
|
|
15
|
-
WindowMessenger: typeof WindowMessenger;
|
|
16
|
-
WorkerMessenger: typeof WorkerMessenger;
|
|
17
|
-
PortMessenger: typeof PortMessenger;
|
|
18
|
-
CallOptions: typeof CallOptions;
|
|
19
|
-
Reply: typeof Reply;
|
|
20
|
-
PenpalError: typeof PenpalError;
|
|
21
|
-
debug: (prefix?: string) => import("./types.js").Log;
|
|
22
|
-
ErrorCode: {
|
|
23
|
-
readonly ConnectionDestroyed: "CONNECTION_DESTROYED";
|
|
24
|
-
readonly ConnectionTimeout: "CONNECTION_TIMEOUT";
|
|
25
|
-
readonly InvalidArgument: "INVALID_ARGUMENT";
|
|
26
|
-
readonly MethodCallTimeout: "METHOD_CALL_TIMEOUT";
|
|
27
|
-
readonly MethodNotFound: "METHOD_NOT_FOUND";
|
|
28
|
-
readonly TransmissionFailed: "TRANSMISSION_FAILED";
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
export default _default;
|
package/lib/indexForBundle.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import connect from './connect.js';
|
|
2
|
-
import WindowMessenger from './messengers/WindowMessenger.js';
|
|
3
|
-
import WorkerMessenger from './messengers/WorkerMessenger.js';
|
|
4
|
-
import PortMessenger from './messengers/PortMessenger.js';
|
|
5
|
-
import CallOptions from './CallOptions.js';
|
|
6
|
-
import Reply from './Reply.js';
|
|
7
|
-
import PenpalError from './PenpalError.js';
|
|
8
|
-
import ErrorCode from './ErrorCodeObj.js';
|
|
9
|
-
import debug from './debug.js';
|
|
10
|
-
export default {
|
|
11
|
-
connect,
|
|
12
|
-
WindowMessenger,
|
|
13
|
-
WorkerMessenger,
|
|
14
|
-
PortMessenger,
|
|
15
|
-
CallOptions,
|
|
16
|
-
Reply,
|
|
17
|
-
PenpalError,
|
|
18
|
-
debug,
|
|
19
|
-
ErrorCode,
|
|
20
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Message, Log } from '../types.js';
|
|
2
|
-
export type MessageHandler = (message: Message) => void;
|
|
3
|
-
export type InitializeMessengerOptions = {
|
|
4
|
-
log?: Log;
|
|
5
|
-
validateReceivedMessage: (data: unknown) => data is Message;
|
|
6
|
-
};
|
|
7
|
-
interface Messenger {
|
|
8
|
-
sendMessage: (message: Message, transferables?: Transferable[]) => void;
|
|
9
|
-
addMessageHandler: (callback: MessageHandler) => void;
|
|
10
|
-
removeMessageHandler: (callback: MessageHandler) => void;
|
|
11
|
-
initialize: (options: InitializeMessengerOptions) => void;
|
|
12
|
-
destroy: () => void;
|
|
13
|
-
}
|
|
14
|
-
export default Messenger;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Message } from '../types.js';
|
|
2
|
-
import Messenger, { InitializeMessengerOptions, MessageHandler } from './Messenger.js';
|
|
3
|
-
type Options = {
|
|
4
|
-
/**
|
|
5
|
-
* The port used to communicate to the other port of the port pair.
|
|
6
|
-
*/
|
|
7
|
-
port: MessagePort;
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Handles the details of communicating on a MessagePort.
|
|
11
|
-
*/
|
|
12
|
-
declare class PortMessenger implements Messenger {
|
|
13
|
-
#private;
|
|
14
|
-
constructor({ port }: Options);
|
|
15
|
-
initialize: ({ validateReceivedMessage }: InitializeMessengerOptions) => void;
|
|
16
|
-
sendMessage: (message: Message, transferables?: Transferable[]) => void;
|
|
17
|
-
addMessageHandler: (callback: MessageHandler) => void;
|
|
18
|
-
removeMessageHandler: (callback: MessageHandler) => void;
|
|
19
|
-
destroy: () => void;
|
|
20
|
-
}
|
|
21
|
-
export default PortMessenger;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import PenpalError from '../PenpalError.js';
|
|
2
|
-
/**
|
|
3
|
-
* Handles the details of communicating on a MessagePort.
|
|
4
|
-
*/
|
|
5
|
-
class PortMessenger {
|
|
6
|
-
#port;
|
|
7
|
-
#validateReceivedMessage;
|
|
8
|
-
#messageCallbacks = new Set();
|
|
9
|
-
constructor({ port }) {
|
|
10
|
-
if (!port) {
|
|
11
|
-
throw new PenpalError('INVALID_ARGUMENT', 'port must be defined');
|
|
12
|
-
}
|
|
13
|
-
this.#port = port;
|
|
14
|
-
}
|
|
15
|
-
initialize = ({ validateReceivedMessage }) => {
|
|
16
|
-
this.#validateReceivedMessage = validateReceivedMessage;
|
|
17
|
-
this.#port.addEventListener('message', this.#handleMessage);
|
|
18
|
-
this.#port.start();
|
|
19
|
-
};
|
|
20
|
-
sendMessage = (message, transferables) => {
|
|
21
|
-
this.#port?.postMessage(message, {
|
|
22
|
-
transfer: transferables,
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
addMessageHandler = (callback) => {
|
|
26
|
-
this.#messageCallbacks.add(callback);
|
|
27
|
-
};
|
|
28
|
-
removeMessageHandler = (callback) => {
|
|
29
|
-
this.#messageCallbacks.delete(callback);
|
|
30
|
-
};
|
|
31
|
-
destroy = () => {
|
|
32
|
-
this.#port.removeEventListener('message', this.#handleMessage);
|
|
33
|
-
this.#port.close();
|
|
34
|
-
this.#messageCallbacks.clear();
|
|
35
|
-
};
|
|
36
|
-
#handleMessage = ({ data }) => {
|
|
37
|
-
if (!this.#validateReceivedMessage?.(data)) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
for (const callback of this.#messageCallbacks) {
|
|
41
|
-
callback(data);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
export default PortMessenger;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Message } from '../types.js';
|
|
2
|
-
import Messenger, { InitializeMessengerOptions, MessageHandler } from './Messenger.js';
|
|
3
|
-
type Options = {
|
|
4
|
-
/**
|
|
5
|
-
* The window with which the current window will communicate.
|
|
6
|
-
*/
|
|
7
|
-
remoteWindow: Window;
|
|
8
|
-
/**
|
|
9
|
-
* An array of strings or regular expressions defining to which origins
|
|
10
|
-
* communication will be allowed. If not provided, communication will be
|
|
11
|
-
* restricted to the origin of the current page. You may specify an allowed
|
|
12
|
-
* origin of `*` to not restrict communication, but beware the risks of
|
|
13
|
-
* doing so.
|
|
14
|
-
*/
|
|
15
|
-
allowedOrigins?: (string | RegExp)[];
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Handles the details of communicating with a child window.
|
|
19
|
-
*/
|
|
20
|
-
declare class WindowMessenger implements Messenger {
|
|
21
|
-
#private;
|
|
22
|
-
constructor({ remoteWindow, allowedOrigins }: Options);
|
|
23
|
-
initialize: ({ log, validateReceivedMessage, }: InitializeMessengerOptions) => void;
|
|
24
|
-
sendMessage: (message: Message, transferables?: Transferable[]) => void;
|
|
25
|
-
addMessageHandler: (callback: MessageHandler) => void;
|
|
26
|
-
removeMessageHandler: (callback: MessageHandler) => void;
|
|
27
|
-
destroy: () => void;
|
|
28
|
-
}
|
|
29
|
-
export default WindowMessenger;
|