diff --git a/.gitignore b/.gitignore
index 26214e1..c70445e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
node_modules/
dist/
www/
+docs/
+temp/
coverage/
.rpt2_cache/
diff --git a/.prettierignore b/.prettierignore
index e75b87e..f6edd7c 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -3,4 +3,7 @@
/www
/coverage
/scripts
+/api
+/docs
+/temp
*.config.js
\ No newline at end of file
diff --git a/README.md b/README.md
index 7d35a12..ccfebb3 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,8 @@ In this [live demo](https://alesgenova.github.io/post-me-demo) the main window c
5. [Callbacks as parameters](#callbacks)
6. [Transfer vs Clone](#transfer)
7. [Debugging](#debugging)
-8. [References](#references)
+8. [API Documentation](#api)
+9. [References](#references)
@@ -386,6 +387,12 @@ ParentHandshake(messenger).then((connection) => {
Output:
![debug output](debug.png)
+
+
+## API Documentation
+
+The full [__API reference__](https://alesgenova.github.io/post-me/post-me.html) cab be found [here](https://alesgenova.github.io/post-me/post-me.html).
+
## References
diff --git a/api-extractor.json b/api-extractor.json
new file mode 100644
index 0000000..bbafbe1
--- /dev/null
+++ b/api-extractor.json
@@ -0,0 +1,339 @@
+/**
+ * Config file for API Extractor. For more info, please visit: https://api-extractor.com
+ */
+{
+ "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
+ /**
+ * Optionally specifies another JSON config file that this file extends from. This provides a way for
+ * standard settings to be shared across multiple projects.
+ *
+ * If the path starts with "./" or "../", the path is resolved relative to the folder of the file that contains
+ * the "extends" field. Otherwise, the first path segment is interpreted as an NPM package name, and will be
+ * resolved using NodeJS require().
+ *
+ * SUPPORTED TOKENS: none
+ * DEFAULT VALUE: ""
+ */
+ // "extends": "./shared/api-extractor-base.json"
+ // "extends": "my-package/include/api-extractor-base.json"
+ /**
+ * Determines the "" token that can be used with other config file settings. The project folder
+ * typically contains the tsconfig.json and package.json config files, but the path is user-defined.
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting.
+ *
+ * The default value for "projectFolder" is the token "", which means the folder is determined by traversing
+ * parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder
+ * that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error
+ * will be reported.
+ *
+ * SUPPORTED TOKENS:
+ * DEFAULT VALUE: ""
+ */
+ // "projectFolder": "..",
+ /**
+ * (REQUIRED) Specifies the .d.ts file to be used as the starting point for analysis. API Extractor
+ * analyzes the symbols exported by this module.
+ *
+ * The file extension must be ".d.ts" and not ".ts".
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * SUPPORTED TOKENS: , ,
+ */
+ "mainEntryPointFilePath": "/dist/index.d.ts",
+ /**
+ * A list of NPM package names whose exports should be treated as part of this package.
+ *
+ * For example, suppose that Webpack is used to generate a distributed bundle for the project "library1",
+ * and another NPM package "library2" is embedded in this bundle. Some types from library2 may become part
+ * of the exported API for library1, but by default API Extractor would generate a .d.ts rollup that explicitly
+ * imports library2. To avoid this, we can specify:
+ *
+ * "bundledPackages": [ "library2" ],
+ *
+ * This would direct API Extractor to embed those types directly in the .d.ts rollup, as if they had been
+ * local files for library1.
+ */
+ "bundledPackages": [],
+ /**
+ * Determines how the TypeScript compiler engine will be invoked by API Extractor.
+ */
+ "compiler": {
+ /**
+ * Specifies the path to the tsconfig.json file to be used by API Extractor when analyzing the project.
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * Note: This setting will be ignored if "overrideTsconfig" is used.
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: "/tsconfig.json"
+ */
+ // "tsconfigFilePath": "/tsconfig.json",
+ /**
+ * Provides a compiler configuration that will be used instead of reading the tsconfig.json file from disk.
+ * The object must conform to the TypeScript tsconfig schema:
+ *
+ * http://json.schemastore.org/tsconfig
+ *
+ * If omitted, then the tsconfig.json file will be read from the "projectFolder".
+ *
+ * DEFAULT VALUE: no overrideTsconfig section
+ */
+ // "overrideTsconfig": {
+ // . . .
+ // }
+ /**
+ * This option causes the compiler to be invoked with the --skipLibCheck option. This option is not recommended
+ * and may cause API Extractor to produce incomplete or incorrect declarations, but it may be required when
+ * dependencies contain declarations that are incompatible with the TypeScript engine that API Extractor uses
+ * for its analysis. Where possible, the underlying issue should be fixed rather than relying on skipLibCheck.
+ *
+ * DEFAULT VALUE: false
+ */
+ // "skipLibCheck": true,
+ },
+ /**
+ * Configures how the API report file (*.api.md) will be generated.
+ */
+ "apiReport": {
+ /**
+ * (REQUIRED) Whether to generate an API report.
+ */
+ "enabled": true,
+ /**
+ * The filename for the API report files. It will be combined with "reportFolder" or "reportTempFolder" to produce
+ * a full file path.
+ *
+ * The file extension should be ".api.md", and the string should not contain a path separator such as "\" or "/".
+ *
+ * SUPPORTED TOKENS: ,
+ * DEFAULT VALUE: ".api.md"
+ */
+ // "reportFileName": ".api.md",
+ /**
+ * Specifies the folder where the API report file is written. The file name portion is determined by
+ * the "reportFileName" setting.
+ *
+ * The API report file is normally tracked by Git. Changes to it can be used to trigger a branch policy,
+ * e.g. for an API review.
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: "/etc/"
+ */
+ "reportFolder": "/api/"
+ /**
+ * Specifies the folder where the temporary report file is written. The file name portion is determined by
+ * the "reportFileName" setting.
+ *
+ * After the temporary file is written to disk, it is compared with the file in the "reportFolder".
+ * If they are different, a production build will fail.
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: "/temp/"
+ */
+ // "reportTempFolder": "/temp/"
+ },
+ /**
+ * Configures how the doc model file (*.api.json) will be generated.
+ */
+ "docModel": {
+ /**
+ * (REQUIRED) Whether to generate a doc model file.
+ */
+ "enabled": true,
+ /**
+ * The output path for the doc model file. The file extension should be ".api.json".
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: "/temp/.api.json"
+ */
+ "apiJsonFilePath": "/docs/input/.api.json"
+ },
+ /**
+ * Configures how the .d.ts rollup file will be generated.
+ */
+ "dtsRollup": {
+ /**
+ * (REQUIRED) Whether to generate the .d.ts rollup file.
+ */
+ "enabled": false
+ /**
+ * Specifies the output path for a .d.ts rollup file to be generated without any trimming.
+ * This file will include all declarations that are exported by the main entry point.
+ *
+ * If the path is an empty string, then this file will not be written.
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: "/dist/.d.ts"
+ */
+ // "untrimmedFilePath": "/dist/.d.ts",
+ /**
+ * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "beta" release.
+ * This file will include only declarations that are marked as "@public" or "@beta".
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: ""
+ */
+ // "betaTrimmedFilePath": "/dist/-beta.d.ts",
+ /**
+ * Specifies the output path for a .d.ts rollup file to be generated with trimming for a "public" release.
+ * This file will include only declarations that are marked as "@public".
+ *
+ * If the path is an empty string, then this file will not be written.
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: ""
+ */
+ // "publicTrimmedFilePath": "/dist/-public.d.ts",
+ /**
+ * When a declaration is trimmed, by default it will be replaced by a code comment such as
+ * "Excluded from this release type: exampleMember". Set "omitTrimmingComments" to true to remove the
+ * declaration completely.
+ *
+ * DEFAULT VALUE: false
+ */
+ // "omitTrimmingComments": true
+ },
+ /**
+ * Configures how the tsdoc-metadata.json file will be generated.
+ */
+ "tsdocMetadata": {
+ /**
+ * Whether to generate the tsdoc-metadata.json file.
+ *
+ * DEFAULT VALUE: true
+ */
+ // "enabled": true,
+ /**
+ * Specifies where the TSDoc metadata file should be written.
+ *
+ * The path is resolved relative to the folder of the config file that contains the setting; to change this,
+ * prepend a folder token such as "".
+ *
+ * The default value is "", which causes the path to be automatically inferred from the "tsdocMetadata",
+ * "typings" or "main" fields of the project's package.json. If none of these fields are set, the lookup
+ * falls back to "tsdoc-metadata.json" in the package folder.
+ *
+ * SUPPORTED TOKENS: , ,
+ * DEFAULT VALUE: ""
+ */
+ // "tsdocMetadataFilePath": "/dist/tsdoc-metadata.json"
+ },
+ /**
+ * Specifies what type of newlines API Extractor should use when writing output files. By default, the output files
+ * will be written with Windows-style newlines. To use POSIX-style newlines, specify "lf" instead.
+ * To use the OS's default newline kind, specify "os".
+ *
+ * DEFAULT VALUE: "crlf"
+ */
+ // "newlineKind": "crlf",
+ /**
+ * Configures how API Extractor reports error and warning messages produced during analysis.
+ *
+ * There are three sources of messages: compiler messages, API Extractor messages, and TSDoc messages.
+ */
+ "messages": {
+ /**
+ * Configures handling of diagnostic messages reported by the TypeScript compiler engine while analyzing
+ * the input .d.ts files.
+ *
+ * TypeScript message identifiers start with "TS" followed by an integer. For example: "TS2551"
+ *
+ * DEFAULT VALUE: A single "default" entry with logLevel=warning.
+ */
+ "compilerMessageReporting": {
+ /**
+ * Configures the default routing for messages that don't match an explicit rule in this table.
+ */
+ "default": {
+ /**
+ * Specifies whether the message should be written to the the tool's output log. Note that
+ * the "addToApiReportFile" property may supersede this option.
+ *
+ * Possible values: "error", "warning", "none"
+ *
+ * Errors cause the build to fail and return a nonzero exit code. Warnings cause a production build fail
+ * and return a nonzero exit code. For a non-production build (e.g. when "api-extractor run" includes
+ * the "--local" option), the warning is displayed but the build will not fail.
+ *
+ * DEFAULT VALUE: "warning"
+ */
+ "logLevel": "warning"
+ /**
+ * When addToApiReportFile is true: If API Extractor is configured to write an API report file (.api.md),
+ * then the message will be written inside that file; otherwise, the message is instead logged according to
+ * the "logLevel" option.
+ *
+ * DEFAULT VALUE: false
+ */
+ // "addToApiReportFile": false
+ }
+ // "TS2551": {
+ // "logLevel": "warning",
+ // "addToApiReportFile": true
+ // },
+ //
+ // . . .
+ },
+ /**
+ * Configures handling of messages reported by API Extractor during its analysis.
+ *
+ * API Extractor message identifiers start with "ae-". For example: "ae-extra-release-tag"
+ *
+ * DEFAULT VALUE: See api-extractor-defaults.json for the complete table of extractorMessageReporting mappings
+ */
+ "extractorMessageReporting": {
+ "default": {
+ "logLevel": "warning"
+ // "addToApiReportFile": false
+ }
+ // "ae-extra-release-tag": {
+ // "logLevel": "warning",
+ // "addToApiReportFile": true
+ // },
+ //
+ // . . .
+ },
+ /**
+ * Configures handling of messages reported by the TSDoc parser when analyzing code comments.
+ *
+ * TSDoc message identifiers start with "tsdoc-". For example: "tsdoc-link-tag-unescaped-text"
+ *
+ * DEFAULT VALUE: A single "default" entry with logLevel=warning.
+ */
+ "tsdocMessageReporting": {
+ "default": {
+ "logLevel": "warning"
+ // "addToApiReportFile": false
+ }
+ // "tsdoc-link-tag-unescaped-text": {
+ // "logLevel": "warning",
+ // "addToApiReportFile": true
+ // },
+ //
+ // . . .
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/post-me.api.md b/api/post-me.api.md
new file mode 100644
index 0000000..86af29e
--- /dev/null
+++ b/api/post-me.api.md
@@ -0,0 +1,121 @@
+## API Report File for "post-me"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+
+// @public (undocumented)
+export class BareMessenger implements Messenger {
+ // Warning: (ae-forgotten-export) The symbol "Postable" needs to be exported by the entry point index.d.ts
+ constructor(postable: Postable);
+ // Warning: (ae-forgotten-export) The symbol "MessageListener" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "ListenerRemover" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
+ addMessageListener: (listener: MessageListener) => ListenerRemover;
+ // (undocumented)
+ postMessage: (message: any, transfer?: Transferable[]) => void;
+}
+
+// @public
+export type CallOptions = {
+ transfer?: Transferable[];
+};
+
+// Warning: (ae-forgotten-export) The symbol "MethodsType" needs to be exported by the entry point index.d.ts
+//
+// @public
+export function ChildHandshake(messenger: Messenger, localMethods?: M): Promise;
+
+// Warning: (ae-forgotten-export) The symbol "EventsType" needs to be exported by the entry point index.d.ts
+//
+// @public
+export class ConcreteEmitter implements Emitter {
+ constructor();
+ addEventListener(eventName: K, listener: (data: E[K]) => void): void;
+ // @internal (undocumented)
+ protected emit(eventName: K, data: E[K]): void;
+ once(eventName: K): Promise;
+ // @internal (undocumented)
+ protected removeAllListeners(): void;
+ removeEventListener(eventName: K, listener: (data: E[K]) => void): void;
+}
+
+// @public
+export interface Connection {
+ close(): void;
+ localHandle(): LocalHandle;
+ remoteHandle(): RemoteHandle;
+}
+
+// @public
+export function debug(namespace: string, log?: (...data: any[]) => void): (...data: any[]) => void;
+
+// @public
+export function DebugMessenger(messenger: Messenger, log?: (...data: any[]) => void): Messenger;
+
+// @public
+export type EmitOptions = {
+ transfer?: Transferable[];
+};
+
+// @public
+export interface Emitter {
+ addEventListener(eventName: K, listener: (data: E[K]) => void): void;
+ once(eventName: K): Promise;
+ removeEventListener(eventName: K, listener: (data: E[K]) => void): void;
+}
+
+// @public
+export interface LocalHandle {
+ emit(eventName: K, data: E[K], options?: EmitOptions): void;
+ setEmitTransfer(eventName: K, transfer: (payload: E[K]) => Transferable[]): void;
+ // Warning: (ae-forgotten-export) The symbol "InnerType" needs to be exported by the entry point index.d.ts
+ setReturnTransfer(methodName: K, transfer: (result: InnerType>) => Transferable[]): void;
+}
+
+// @public
+export interface Messenger {
+ addMessageListener(listener: MessageListener): ListenerRemover;
+ postMessage(message: any, transfer?: Transferable[]): void;
+}
+
+// @public
+export function ParentHandshake(messenger: Messenger, localMethods?: M0, maxAttempts?: number, attemptsInterval?: number): Promise;
+
+// @public
+export class PortMessenger extends BareMessenger implements Messenger {
+ constructor({ port }: {
+ port: MessagePort;
+ });
+}
+
+// @public
+export interface RemoteHandle extends Emitter {
+ call(methodName: K, ...args: Parameters): Promise>>;
+ customCall(methodName: K, args: Parameters, options?: CallOptions): Promise>>;
+ setCallTransfer(methodName: K, transfer: (...args: Parameters) => Transferable[]): void;
+}
+
+// @public
+export class WindowMessenger implements Messenger {
+ constructor({ localWindow, remoteWindow, remoteOrigin, }: {
+ localWindow?: Window;
+ remoteWindow: Window;
+ remoteOrigin: string;
+ });
+ // (undocumented)
+ addMessageListener: (listener: MessageListener) => ListenerRemover;
+ // (undocumented)
+ postMessage: (message: any, transfer?: Transferable[]) => void;
+}
+
+// @public
+export class WorkerMessenger extends BareMessenger implements Messenger {
+ constructor({ worker }: {
+ worker: Worker;
+ });
+}
+
+
+```
diff --git a/scripts/build-demo.js b/demo/build.js
similarity index 100%
rename from scripts/build-demo.js
rename to demo/build.js
diff --git a/package-lock.json b/package-lock.json
index e3996e8..424794b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1525,6 +1525,103 @@
}
}
},
+ "@microsoft/api-documenter": {
+ "version": "7.12.6",
+ "resolved": "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.12.6.tgz",
+ "integrity": "sha512-67VolY0ObxFyLqK5eVT73x1TLldZHWOyeW4R1FazGA+3LPheCU+TLW6ys7yrdtwuprw2jqtOXcvhVYVuvjkepw==",
+ "dev": true,
+ "requires": {
+ "@microsoft/api-extractor-model": "7.12.1",
+ "@microsoft/tsdoc": "0.12.24",
+ "@rushstack/node-core-library": "3.35.2",
+ "@rushstack/ts-command-line": "4.7.8",
+ "colors": "~1.2.1",
+ "js-yaml": "~3.13.1",
+ "resolve": "~1.17.0"
+ },
+ "dependencies": {
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ }
+ }
+ },
+ "@microsoft/api-extractor": {
+ "version": "7.13.0",
+ "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.13.0.tgz",
+ "integrity": "sha512-T+14VIhB91oJIett5AZ02VWYmz/01VHFWkcAOWiErIQ8AiFhJZoGqTjGxoi8ZpEEBuAj2EGVYojORwLc/+aiDQ==",
+ "dev": true,
+ "requires": {
+ "@microsoft/api-extractor-model": "7.12.1",
+ "@microsoft/tsdoc": "0.12.24",
+ "@rushstack/node-core-library": "3.35.2",
+ "@rushstack/rig-package": "0.2.9",
+ "@rushstack/ts-command-line": "4.7.8",
+ "colors": "~1.2.1",
+ "lodash": "~4.17.15",
+ "resolve": "~1.17.0",
+ "semver": "~7.3.0",
+ "source-map": "~0.6.1",
+ "typescript": "~4.1.3"
+ },
+ "dependencies": {
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "semver": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "@microsoft/api-extractor-model": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.12.1.tgz",
+ "integrity": "sha512-Hw+kYfUb1gt6xPWGFW8APtLVWeNEWz4JE6PbLkSHw/j+G1hAaStzgxhBx3GOAWM/G0SCDGVJOpd5YheVOyu/KQ==",
+ "dev": true,
+ "requires": {
+ "@microsoft/tsdoc": "0.12.24",
+ "@rushstack/node-core-library": "3.35.2"
+ }
+ },
+ "@microsoft/tsdoc": {
+ "version": "0.12.24",
+ "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.12.24.tgz",
+ "integrity": "sha512-Mfmij13RUTmHEMi9vRUhMXD7rnGR2VvxeNYtaGtaJ4redwwjT4UXYJ+nzmVJF7hhd4pn/Fx5sncDKxMVFJSWPg==",
+ "dev": true
+ },
"@rollup/plugin-babel": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz",
@@ -1556,6 +1653,100 @@
"picomatch": "^2.2.2"
}
},
+ "@rushstack/node-core-library": {
+ "version": "3.35.2",
+ "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.35.2.tgz",
+ "integrity": "sha512-SPd0uG7mwsf3E30np9afCUhtaM1SBpibrbxOXPz82KWV6SQiPUtXeQfhXq9mSnGxOb3WLWoSDe7AFxQNex3+kQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "10.17.13",
+ "colors": "~1.2.1",
+ "fs-extra": "~7.0.1",
+ "import-lazy": "~4.0.0",
+ "jju": "~1.4.0",
+ "resolve": "~1.17.0",
+ "semver": "~7.3.0",
+ "timsort": "~0.3.0",
+ "z-schema": "~3.18.3"
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "10.17.13",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz",
+ "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "semver": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ }
+ }
+ },
+ "@rushstack/rig-package": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.2.9.tgz",
+ "integrity": "sha512-4tqsZ/m+BjeNAGeAJYzPF53CT96TsAYeZ3Pq3T4tb1pGGM3d3TWfkmALZdKNhpRlAeShKUrb/o/f/0sAuK/1VQ==",
+ "dev": true,
+ "requires": {
+ "@types/node": "10.17.13",
+ "resolve": "~1.17.0",
+ "strip-json-comments": "~3.1.1"
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "10.17.13",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.13.tgz",
+ "integrity": "sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ }
+ }
+ },
+ "@rushstack/ts-command-line": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.7.8.tgz",
+ "integrity": "sha512-8ghIWhkph7NnLCMDJtthpsb7TMOsVGXVDvmxjE/CeklTqjbbUFBjGXizJfpbEkRQTELuZQ2+vGn7sGwIWKN2uA==",
+ "dev": true,
+ "requires": {
+ "@types/argparse": "1.0.38",
+ "argparse": "~1.0.9",
+ "colors": "~1.2.1",
+ "string-argv": "~0.3.1"
+ }
+ },
"@sinonjs/commons": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz",
@@ -1574,6 +1765,12 @@
"@sinonjs/commons": "^1.7.0"
}
},
+ "@types/argparse": {
+ "version": "1.0.38",
+ "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz",
+ "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==",
+ "dev": true
+ },
"@types/babel__core": {
"version": "7.1.12",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz",
@@ -2363,6 +2560,12 @@
"integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
"dev": true
},
+ "colors": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz",
+ "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==",
+ "dev": true
+ },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -3505,6 +3708,12 @@
"resolve-from": "^4.0.0"
}
},
+ "import-lazy": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
+ "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
+ "dev": true
+ },
"import-local": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz",
@@ -5074,6 +5283,12 @@
}
}
},
+ "jju": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
+ "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=",
+ "dev": true
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -5239,6 +5454,18 @@
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
+ "lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+ "dev": true
+ },
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
+ "dev": true
+ },
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -6929,6 +7156,12 @@
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
"dev": true
},
+ "string-argv": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
+ "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
+ "dev": true
+ },
"string-length": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz",
@@ -6977,6 +7210,12 @@
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"dev": true
},
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
"strip-outer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
@@ -7061,6 +7300,12 @@
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
"dev": true
},
+ "timsort": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
+ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
+ "dev": true
+ },
"tmpl": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
@@ -7385,6 +7630,12 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "validator": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz",
+ "integrity": "sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==",
+ "dev": true
+ },
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@@ -7607,6 +7858,18 @@
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true
+ },
+ "z-schema": {
+ "version": "3.18.4",
+ "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.18.4.tgz",
+ "integrity": "sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw==",
+ "dev": true,
+ "requires": {
+ "commander": "^2.7.1",
+ "lodash.get": "^4.0.0",
+ "lodash.isequal": "^4.0.0",
+ "validator": "^8.0.0"
+ }
}
}
}
diff --git a/package.json b/package.json
index d02f3f7..a67503e 100644
--- a/package.json
+++ b/package.json
@@ -30,9 +30,11 @@
"build:src": "rollup -c",
"build:types": "tsc --emitDeclarationOnly",
"build:min": "uglifyjs dist/index.js -o dist/index.min.js",
- "build:demo": "npm run build:src && node scripts/build-demo.js www",
+ "build:docs": "npm run build:types && api-extractor run --local --verbose && api-documenter markdown -i=docs/input -o=docs/output",
+ "build:demo": "npm run build:src && node demo/build.js www",
"prepublishOnly": "npm run build",
"demo": "npm run build:demo && npx serve www",
+ "deploy:docs": "npm run build:docs && gh-pages -d docs/output",
"deploy:demo": "npm run build:demo && gh-pages -d www",
"test": "jest --coverage tests",
"prettier:check-staged": "pretty-quick --staged --check --pattern '**/*.{js,jsx,ts,tsx,css,html}'",
@@ -46,6 +48,8 @@
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/preset-env": "^7.12.11",
+ "@microsoft/api-documenter": "^7.12.6",
+ "@microsoft/api-extractor": "^7.13.0",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-typescript": "^8.1.0",
"@types/jest": "^26.0.15",
diff --git a/src/common.ts b/src/common.ts
index 1d52da3..2e2cded 100644
--- a/src/common.ts
+++ b/src/common.ts
@@ -3,10 +3,22 @@ export const MARKER = '@post-me';
export type IdType = number;
export type KeyType = string;
+/**
+ * The options that can be passed when calling a method on the other context with RemoteHandle.customCall()
+ *
+ * @public
+ *
+ */
export type CallOptions = {
transfer?: Transferable[];
};
+/**
+ * The options that can be passed when emitting an event to the other context with LocalHandle.emit()
+ *
+ * @public
+ *
+ */
export type EmitOptions = {
transfer?: Transferable[];
};
diff --git a/src/connection.ts b/src/connection.ts
index bb4d7fa..9f0bc8e 100644
--- a/src/connection.ts
+++ b/src/connection.ts
@@ -7,15 +7,41 @@ import {
RemoteHandle,
} from './handles';
+/**
+ * An active connection between two contexts
+ *
+ * @typeParam M0 - The methods exposed by this context
+ * @typeParam E1 - The events exposed by this context
+ * @typeParam M1 - The methods exposed by the other context
+ * @typeParam E1 - The events exposed by the other context
+ *
+ * @public
+ *
+ */
export interface Connection<
M0 extends MethodsType = any,
E0 extends EventsType = any,
M1 extends MethodsType = any,
E1 extends EventsType = any
> {
- localHandle: () => LocalHandle;
- remoteHandle: () => RemoteHandle;
- close: () => void;
+ /**
+ * Get a handle to the local end of the connection
+ *
+ * @returns A {@link LocalHandle} to the local side of the Connection
+ */
+ localHandle(): LocalHandle;
+
+ /**
+ * Get a handle to the other end of the connection
+ *
+ * @returns A {@link RemoteHandle} to the other side of the Connection
+ */
+ remoteHandle(): RemoteHandle;
+
+ /**
+ * Stop listening to incoming message from the other side
+ */
+ close(): void;
}
export class ConcreteConnection implements Connection {
diff --git a/src/dispatcher.ts b/src/dispatcher.ts
index f2ef765..b47ef39 100644
--- a/src/dispatcher.ts
+++ b/src/dispatcher.ts
@@ -1,6 +1,6 @@
import { IdType, KeyType, createUniqueIdFn } from './common';
import { Messenger } from './messenger';
-import { Emitter } from './emitter';
+import { ConcreteEmitter } from './emitter';
import {
isMessage,
isCallMessage,
@@ -42,7 +42,7 @@ export type DispatcherEvents = {
[MessageType.Event]: EventMessage;
};
-export class Dispatcher extends Emitter {
+export class Dispatcher extends ConcreteEmitter {
private messenger: Messenger;
private sessionId: IdType;
private removeMessengerListener: () => void;
@@ -138,7 +138,7 @@ export type ParentHandshakeDispatcherEvents = {
[x: number]: HandshakeResponseMessage;
};
-export class ParentHandshakeDispatcher extends Emitter {
+export class ParentHandshakeDispatcher extends ConcreteEmitter {
private messenger: Messenger;
private sessionId: IdType;
private removeMessengerListener: () => void;
@@ -186,7 +186,7 @@ export type ChildHandshakeDispatcherEvents = {
[MessageType.HandshakeRequest]: HandshakeRequestMessage;
};
-export class ChildHandshakeDispatcher extends Emitter {
+export class ChildHandshakeDispatcher extends ConcreteEmitter {
private messenger: Messenger;
private removeMessengerListener: () => void;
diff --git a/src/emitter.ts b/src/emitter.ts
index 3565d43..1198184 100644
--- a/src/emitter.ts
+++ b/src/emitter.ts
@@ -1,24 +1,61 @@
import { EventsType } from './common';
-export interface IEmitter {
- addEventListener: (
+/**
+ * A simple event emitter interface used to implement the observer pattern throughout the codebase.
+ *
+ * @public
+ *
+ */
+export interface Emitter {
+ /**
+ * Add a listener to a specific event.
+ *
+ * @param eventName - The name of the event
+ * @param listener - A listener function that takes as parameter the payload of the event
+ */
+ addEventListener(
eventName: K,
listener: (data: E[K]) => void
- ) => void;
- removeEventListener: (
+ ): void;
+
+ /**
+ * Remove a listener from a specific event.
+ *
+ * @param eventName - The name of the event
+ * @param listener - A listener function that had been added previously
+ */
+ removeEventListener(
eventName: K,
listener: (data: E[K]) => void
- ) => void;
- once: (eventName: K) => Promise;
+ ): void;
+
+ /**
+ * Add a listener to a specific event, that will only be invoked once
+ *
+ * @remarks
+ *
+ * After the first occurrence of the specified event, the listener will be invoked and
+ * immediately removed.
+ *
+ * @param eventName - The name of the event
+ * @param listener - A listener function that had been added previously
+ */
+ once(eventName: K): Promise;
}
-export class Emitter implements IEmitter {
+/**
+ * A concrete implementation of the {@link Emitter} interface
+ *
+ * @public
+ */
+export class ConcreteEmitter implements Emitter {
private _listeners: Partial void>>>;
constructor() {
this._listeners = {};
}
+ /** {@inheritDoc Emitter.addEventListener} */
addEventListener(
eventName: K,
listener: (data: E[K]) => void
@@ -33,6 +70,7 @@ export class Emitter implements IEmitter {
listeners.add(listener);
}
+ /** {@inheritDoc Emitter.removeEventListener} */
removeEventListener(
eventName: K,
listener: (data: E[K]) => void
@@ -46,6 +84,7 @@ export class Emitter implements IEmitter {
listeners.delete(listener);
}
+ /** {@inheritDoc Emitter.once} */
once(eventName: K): Promise {
return new Promise((resolve) => {
const listener = (data: E[K]) => {
@@ -57,6 +96,7 @@ export class Emitter implements IEmitter {
});
}
+ /** @internal */
protected emit(eventName: K, data: E[K]) {
let listeners = this._listeners[eventName];
@@ -69,6 +109,7 @@ export class Emitter implements IEmitter {
});
}
+ /** @internal */
protected removeAllListeners() {
Object.values(this._listeners).forEach((listeners) => {
if (listeners) {
diff --git a/src/handles.ts b/src/handles.ts
index 08f5603..addf7bd 100644
--- a/src/handles.ts
+++ b/src/handles.ts
@@ -5,7 +5,7 @@ import {
EmitOptions,
CallOptions,
} from './common';
-import { Emitter, IEmitter } from './emitter';
+import { Emitter, ConcreteEmitter } from './emitter';
import { Dispatcher } from './dispatcher';
import {
MessageType,
@@ -16,49 +16,149 @@ import {
} from './messages';
import { createCallbackProxy, isCallbackProxy } from './proxy';
+/**
+ * A handle to the other end of the connection
+ *
+ * @remarks
+ *
+ * Use this handle to:
+ *
+ * - Call methods exposed by the other end
+ *
+ * - Add listeners to custom events emitted by the other end
+ *
+ * @typeParam M - The methods exposed by the other context
+ * @typeParam E - The events exposed by the other context
+ *
+ * @public
+ *
+ */
export interface RemoteHandle<
M extends MethodsType = any,
E extends EventsType = any
-> extends IEmitter {
- call: (
+> extends Emitter {
+ /**
+ * Call a method exposed by the other end.
+ *
+ * @param methodName - The name of the method
+ * @param args - The list of arguments passed to the method
+ * @returns A Promise of the value returned by the method
+ *
+ */
+ call(
methodName: K,
...args: Parameters
- ) => Promise>>;
- customCall: (
+ ): Promise>>;
+
+ /**
+ * Call a method exposed by the other end.
+ *
+ * @param methodName - The name of the method
+ * @param args - The list of arguments passed to the method
+ * @param options - The {@link CallOptions} to customize this method call
+ * @returns A Promise of the value returned by the method
+ *
+ */
+ customCall(
methodName: K,
args: Parameters,
options?: CallOptions
- ) => Promise>>;
- setCallTransfer: (
+ ): Promise>>;
+
+ /**
+ * Specify which parts of the arguments of a given method call should be transferred
+ * into the other context instead of cloned.
+ *
+ * @remarks
+ *
+ * You only need to call setCallTransfer once per method. After the transfer function is set,
+ * it will automatically be used by all subsequent calls to the specified method.
+ *
+ * @param methodName - The name of the method
+ * @param transfer - A function that takes as parameters the arguments of a method call, and returns a list of transferable objects.
+ *
+ */
+ setCallTransfer(
methodName: K,
transfer: (...args: Parameters) => Transferable[]
- ) => void;
+ ): void;
}
+/**
+ * A handle to the local end of the connection
+ *
+ * @remarks
+ *
+ * Use this handle to:
+ *
+ * - Emit custom events to the other end
+ *
+ * @typeParam M - The methods exposed by this context
+ * @typeParam E - The events exposed by this context
+ *
+ * @public
+ *
+ */
export interface LocalHandle<
M extends MethodsType = any,
E extends EventsType = any
> {
- emit: (
+ /**
+ * Emit a custom event with a payload. The event can be captured by the other context.
+ *
+ * @param eventName - The name of the event
+ * @param data - The payload associated with the event
+ * @param options - The {@link EmitOptions} to customize this emit call
+ *
+ */
+ emit(
eventName: K,
data: E[K],
options?: EmitOptions
- ) => void;
- setReturnTransfer: (
+ ): void;
+
+ /**
+ * Specify which parts of the return value of a given method call should be transferred
+ * into the other context instead of cloned.
+ *
+ * @remarks
+ *
+ * You only need to call setReturnTransfer once per method. After the transfer function is set,
+ * it will automatically be used every time a value is returned by the specified method.
+ *
+ * @param methodName - The name of the method
+ * @param transfer - A function that takes as parameter the return value of a method call, and returns a list of transferable objects.
+ *
+ */
+ setReturnTransfer(
methodName: K,
transfer: (result: InnerType>) => Transferable[]
- ) => void;
- setEmitTransfer: (
+ ): void;
+
+ /**
+ * Specify which parts of the payload of a given event should be transferred
+ * into the other context instead of cloned.
+ *
+ * @remarks
+ *
+ * You only need to call setEmitTransfer once per event type. After the transfer function is set,
+ * it will automatically be used every time a payload is attached to the specific event.
+ *
+ * @param eventName - The name of the method
+ * @param transfer - A function that takes as parameter the payload of an event, and returns a list of transferable objects.
+ *
+ */
+ setEmitTransfer(
eventName: K,
transfer: (payload: E[K]) => Transferable[]
- ) => void;
+ ): void;
}
export class ConcreteRemoteHandle<
M extends MethodsType = any,
E extends EventsType = any
>
- extends Emitter
+ extends ConcreteEmitter
implements RemoteHandle {
private _dispatcher: Dispatcher;
private _callTransfer: { [x: string]: (...args: any) => Transferable[] };
diff --git a/src/handshake.ts b/src/handshake.ts
index 9c9ea9d..92251b0 100644
--- a/src/handshake.ts
+++ b/src/handshake.ts
@@ -31,6 +31,17 @@ const runUntil = (
fn();
};
+/**
+ * Initiate the handshake from the Parent side
+ *
+ * @param messenger - The Messenger used to send and receive messages from the other end
+ * @param localMethods - The methods that will be exposed to the other end
+ * @param maxAttempts - The maximum number of handshake attempts
+ * @param attemptsInterval - The interval between handshake attempts
+ * @returns A Promise to an active {@link Connection} to the other end
+ *
+ * @public
+ */
export function ParentHandshake(
messenger: Messenger,
localMethods: M0 = {} as M0,
@@ -67,6 +78,15 @@ export function ParentHandshake(
});
}
+/**
+ * Initiate the handshake from the Child side
+ *
+ * @param messenger - The Messenger used to send and receive messages from the other end
+ * @param localMethods - The methods that will be exposed to the other end
+ * @returns A Promise to an active {@link Connection} to the other end
+ *
+ * @public
+ */
export function ChildHandshake(
messenger: Messenger,
localMethods: M = {} as M
diff --git a/src/index.ts b/src/index.ts
index 4d19c28..98e0959 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,10 @@
+/**
+ * @packageDocumentation Use web Workers and other Windows through a simple Promise API
+ */
+
import { ParentHandshake, ChildHandshake } from './handshake';
import { Connection } from './connection';
+import { Emitter, ConcreteEmitter } from './emitter';
import {
Messenger,
WindowMessenger,
@@ -10,18 +15,27 @@ import {
debug,
} from './messenger';
import { RemoteHandle, LocalHandle } from './handles';
+import { CallOptions, EmitOptions } from './common';
export {
- ParentHandshake,
- ChildHandshake,
+ // Interfaces
Connection,
+ Emitter,
RemoteHandle,
LocalHandle,
Messenger,
+ // Methods
+ ParentHandshake,
+ ChildHandshake,
+ DebugMessenger,
+ debug,
+ // Classes
+ ConcreteEmitter,
WindowMessenger,
WorkerMessenger,
PortMessenger,
BareMessenger,
- DebugMessenger,
- debug,
+ // Types
+ CallOptions,
+ EmitOptions,
};
diff --git a/src/messenger.ts b/src/messenger.ts
index 229b8ad..6a4f2a1 100644
--- a/src/messenger.ts
+++ b/src/messenger.ts
@@ -1,9 +1,35 @@
type MessageListener = (event: MessageEvent) => void;
type ListenerRemover = () => void;
+/**
+ * An interface used internally to exchange low level messages across contexts.
+ *
+ * @remarks
+ *
+ * Having a single interface lets post-me deal with Workers, Windows, and MessagePorts
+ * without having to worry about their differences.
+ *
+ * A few concrete implementations of the Messenger interface are provided.
+ *
+ * @public
+ *
+ */
export interface Messenger {
- postMessage: (message: any, transfer?: Transferable[]) => void;
- addMessageListener: (listener: MessageListener) => ListenerRemover;
+ /**
+ * Send a message to the other context
+ *
+ * @param message - The payload of the message
+ * @param transfer - A list of Transferable objects that should be transferred to the other context instead of cloned.
+ */
+ postMessage(message: any, transfer?: Transferable[]): void;
+
+ /**
+ * Add a listener to messages received by the other context
+ *
+ * @param listener - A listener that will receive the MessageEvent
+ * @returns A function that can be invoked to remove the listener
+ */
+ addMessageListener(listener: MessageListener): ListenerRemover;
}
const acceptableMessageEvent = (
@@ -24,6 +50,12 @@ const acceptableMessageEvent = (
return true;
};
+/**
+ * A concrete implementation of {@link Messenger} used to communicate with another Window.
+ *
+ * @public
+ *
+ */
export class WindowMessenger implements Messenger {
postMessage: (message: any, transfer?: Transferable[]) => void;
addMessageListener: (listener: MessageListener) => ListenerRemover;
@@ -67,6 +99,7 @@ interface Postable {
removeEventListener(eventName: 'message', listener: MessageListener): void;
}
+/** @public */
export class BareMessenger implements Messenger {
postMessage: (message: any, transfer?: Transferable[]) => void;
addMessageListener: (listener: MessageListener) => ListenerRemover;
@@ -92,25 +125,55 @@ export class BareMessenger implements Messenger {
}
}
+/**
+ * A concrete implementation of {@link Messenger} used to communicate with a Worker.
+ *
+ * @public
+ *
+ */
export class WorkerMessenger extends BareMessenger implements Messenger {
constructor({ worker }: { worker: Worker }) {
super(worker);
}
}
+/**
+ * A concrete implementation of {@link Messenger} used to communicate with a MessagePort.
+ *
+ * @public
+ *
+ */
export class PortMessenger extends BareMessenger implements Messenger {
constructor({ port }: { port: MessagePort }) {
super(port);
}
}
-export const debug = (namespace: string, log?: (...data: any[]) => void) => {
+/**
+ * Create a logger function with a specific namespace
+ *
+ * @param namespace - The namespace will be prepended to all the arguments passed to the logger function
+ * @param log - The underlying logger (`console.log` by default)
+ *
+ * @public
+ *
+ */
+export function debug(namespace: string, log?: (...data: any[]) => void) {
log = log || console.debug || console.log || (() => {});
return (...data: any[]) => {
log!(namespace, ...data);
};
-};
+}
+/**
+ * Decorate a {@link Messenger} so that it will log any message exchanged
+ * @param messenger - The Messenger that will be decorated
+ * @param log - The logger function that will receive each message
+ * @returns A decorated Messenger
+ *
+ * @public
+ *
+ */
export function DebugMessenger(
messenger: Messenger,
log?: (...data: any[]) => void
diff --git a/tests/index.spec.ts b/tests/index.spec.ts
index 1a0a5dd..aafe5eb 100644
--- a/tests/index.spec.ts
+++ b/tests/index.spec.ts
@@ -1,6 +1,6 @@
import { ParentHandshake, ChildHandshake } from '../src/handshake';
import { Connection } from '../src/connection';
-import { Emitter } from '../src/emitter';
+import { ConcreteEmitter } from '../src/emitter';
import {
Messenger,
WindowMessenger,
@@ -758,8 +758,8 @@ test('debug', () => {
});
function MockWorker(script: (self: any) => void) {
- const worker: any = new Emitter();
- const self: any = new Emitter();
+ const worker: any = new ConcreteEmitter();
+ const self: any = new ConcreteEmitter();
self.postMessage = (payload: any) => {
worker.emit('message', { data: payload });
diff --git a/tsconfig.json b/tsconfig.json
index dd33288..dcf4275 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,25 +1,25 @@
{
"compilerOptions": {
/* Basic Options */
- "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
- "module": "esnext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
+ "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
+ "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"lib": [
"esnext",
- "dom",
+ "dom"
// "webworker"
- ], /* Specify library files to be included in the compilation. */
- "strict": true, /* Enable all strict type-checking options. */
- "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
- "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
- "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
- "outDir": "./dist", /* Redirect output structure to the directory. */
- "declaration": true, /* Generates corresponding '.d.ts' file. */
+ ] /* Specify library files to be included in the compilation. */,
+ "strict": true /* Enable all strict type-checking options. */,
+ "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
+ "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
+ "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
+ "outDir": "./dist" /* Redirect output structure to the directory. */,
+ "declaration": true /* Generates corresponding '.d.ts' file. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
- // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
- // "sourceMap": true, /* Generates corresponding '.map' file. */
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
+ // "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "composite": true, /* Enable project compilation */
// "incremental": true, /* Enable incremental compilation */
@@ -58,13 +58,10 @@
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
},
- "include": [
- "src",
- "tests",
- ],
+ "include": ["src", "tests"],
"exclude": [
// "dist",
"node_modules",
"**/*.spec.ts"
]
-}
\ No newline at end of file
+}