├── .gitignore ├── LICENSE ├── README.md ├── bsconfig.json ├── docs ├── faq.md └── todo.md ├── examples └── StreamTextToFile.re ├── package.json ├── src ├── Assert.re ├── BigInt.re ├── BinaryLike.re ├── Buffer.re ├── ChildProcess.re ├── Cluster.re ├── Console.re ├── Crypto.re ├── Dns.re ├── Errors.re ├── Event.re ├── EventEmitter.re ├── Fs.re ├── Global.re ├── Http.re ├── Http2.re ├── Https.re ├── Module.re ├── Net.re ├── Os.re ├── Path.re ├── PerfHooks.re ├── Process.re ├── QueryString.re ├── Readline.re ├── Stream.re ├── StringBuffer.re ├── StringDecoder.re ├── StringEncoding.re ├── Timers.re ├── Tls.re ├── Tty.re ├── Url.re ├── Util.re ├── V8.re ├── VM.re ├── WorkerThreads.re └── internal │ └── Internal__JsTypeReflection.re ├── test ├── __tests__ │ ├── BigInt_test.re │ ├── BinaryLike_test.re │ ├── Console_test.re │ ├── EventEmitter_test.re │ ├── Fs_test.re │ ├── Global_test.re │ ├── Path_test.re │ ├── Stream_test.re │ └── Util_test.re └── test_lib │ ├── EventEmitterTestLib.re │ └── StreamTestLib.re └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .merlin 3 | .bsb.lock 4 | npm-debug.log 5 | /lib/bs/ 6 | /node_modules/ 7 | bsb 8 | *.bs.js 9 | package-lock.json 10 | 11 | src/ScratchRe.re 12 | src/ScratchMl.ml 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Sikan He and Austin Davis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # reason-nodejs 2 | 3 | ## Project Status 4 | 5 | **Update (5/5/2020):** 6 | Announcing the beta release of `reason-node`! You can find it on NPM [here](https://www.npmjs.com/package/reason-nodejs), and install it from your terminal using the installation instructions below. 7 | 8 | We invite everyone to try it out in your own projects, and to provide any feedback you want. GitHub issues are a great way to provide such feedback, since those are easy for us to track and manage. However, if you need any help or have specific questions, don't hesitate to contact us on [Discord](https://discord.gg/7MgaPKW)! 9 | 10 | Happy hacking! 11 | 12 | ---- 13 | 14 | **Update (3/19/2020):** 15 | `reason-node` is nearly ready for its first public release. Most of the important design decisions have been made & implemented, and most of the API surface is becoming relatively stable. There are still a few gaps here and there, and we intend to refine the API over time as new ideas emerge. Therefore, we will likely push an alpha release first, to give us some space to make breaking changes if needed, based on community feedback. We will post updates here and in the ReasonML Discord server. 16 | 17 | ---- 18 | 19 | **Update (2/13/2020):** 20 | This library is still under construction. Some of the core design details are still being ironed out. Therefore we cannot guarantee API stability at this time. We intend to achieve API stability very soon. We will make an announcement on the ReasonML [Discord server](https://discord.gg/7MgaPKW) when we reach that goal. 21 | 22 | ---- 23 | 24 | ## Installation 25 | 26 | Using the [yarn](https://yarnpkg.com/) package manager: 27 | 28 | ```shell 29 | yarn add reason-nodejs 30 | ``` 31 | 32 | Using the [npm](https://www.npmjs.com/) package manager: 33 | 34 | ```shell 35 | npm i reason-nodejs 36 | ``` 37 | 38 | ## Goal of this library 39 | 40 | Help all Reason Node.js apps and libraries to be built faster by reducing the time spent on hand written bindings. 41 | 42 | ## Non-Goals 43 | 44 | - Have 100% coverage of Node.js api surface - Due to lack of man power for testing and maintaining, we should only have enough surface to cover all common use cases. But we should have enough coverage that developers only rarely have to write a custom binding. 45 | - Ensure all APIs are idiomatic Reason and 100% typesafe - This library should be as low-level as possible to allow for minimal context switching between offical Node.js documentation and the Reason equilvalent. And due to the dynamic nature of the JS API, bending it to be idiomatic Reason will lead to a ton of bikeshedding in design as well as sacrificing maintainability. 46 | 47 | ## Principles 48 | 49 | - When available, we prefer to bind to the promise version of the library instead of the callback version to reduce binding surface. 50 | - Use subtyping only where the benefit is huge. We use subtyping for various APIs that implement Node Streams, such as HTTP Request and Response, FileSystem streams, Crypto streams, and etc. This allows us to use a single set of functions to manipulate and combine streams across different modules. For example: 51 | 52 | ### Stream a file into stdout: 53 | 54 | ```reason 55 | Fs.createReadStream("/path") 56 | ->Stream.pipe(Process.(stdout(process))) 57 | ->Stream.onError(_ => Js.log("handleError")) 58 | ``` 59 | 60 | ### Echo server: 61 | 62 | ```reason 63 | Http.createServer((request, response) => { 64 | request->Stream.onData(data => Js.log(data)) 65 | request->Stream.pipe(response)->ignore 66 | }); 67 | ``` 68 | 69 | ## Contributing 70 | 71 | We welcome and encourage anyone to contribute! In order to minimize confusion and avoid any wasted effort, here are some recommendations: 72 | 73 | - If you notice a bug or a typo, feel free to create an issue or submit a PR to fix it. 74 | - If you want to request a feature/improvement, it's best to create an issue first, so we can discuss the details. The last thing we want is for you to spend a lot of valuable time and energy creating a pull request when it doesn't fit in with the project goals. That doesn't mean we won't merge your PR, but we cannot guarantee it. We prioritize code review and open discussion. 75 | - If you notice gaps in the documentation and want to help us fill in those gaps, you can help us out by submitting a PR, or by creating an issue and providing a draft of the docs you want to add. 76 | - If you have concerns about our implementations or design decisions (e.g. type soundness, complexity, ergonomics, edge cases, etc.), you should submit an issue voicing your concerns. We gladly welcome critique from the community. We want this library to be as useful as possible, so we want to hear from you! 77 | -------------------------------------------------------------------------------- /bsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/BuckleScript/bucklescript/master/docs/docson/build-schema.json", 3 | "name": "reason-nodejs", 4 | "sources": [ 5 | { 6 | "dir": "src", 7 | "subdirs": true 8 | }, 9 | { 10 | "dir": "test", 11 | "subdirs": true, 12 | "type": "dev" 13 | }, 14 | { 15 | "dir": "examples", 16 | "subdirs": true, 17 | "type": "dev" 18 | } 19 | ], 20 | "package-specs": [ 21 | { 22 | "module": "commonjs", 23 | "in-source": false 24 | } 25 | ], 26 | "suffix": ".bs.js", 27 | "namespace": "node-js", 28 | "bs-dependencies": [], 29 | "bs-dev-dependencies": [ 30 | "@glennsl/bs-jest" 31 | ], 32 | "ppx-flags": [], 33 | "refmt": 3, 34 | "bsc-flags": [] 35 | } -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sikanhe/reason-nodejs/b7b41349f85665d6cd7fc76a170229428e7ec94c/docs/faq.md -------------------------------------------------------------------------------- /docs/todo.md: -------------------------------------------------------------------------------- 1 | 2 | # Reason-Node Todo List 3 | 4 | Below are some concrete tasks that we want to complete. Some of them may already be in progress, so contributors should file an issue and get more information before starting work on these items. 5 | 6 | ## Implementations 7 | 8 | - `Https` module 9 | - `Tls` module 10 | - `V8` module 11 | - `Zlib` module 12 | - `Domain` module 13 | - `Tty` module 14 | 15 | ## Possible improvements 16 | 17 | - Implement `promisify` properly, and/or implement the "promisified" versions of the API. 18 | - This may end up living in a separate project, to keep this library as low-level as possible. 19 | 20 | ## Documentation 21 | 22 | Ordered by descending priority: 23 | 24 | - Core module docs 25 | - `Buffer` module 26 | - `Stream` module 27 | - `Path` module 28 | - `Fs` module 29 | - `Http` module 30 | - `Http2` module 31 | - `Https` module 32 | - `Process` module 33 | - `Child` module 34 | 35 | -------------------------------------------------------------------------------- /examples/StreamTextToFile.re: -------------------------------------------------------------------------------- 1 | let data = "Sample text to write to a file!"->Buffer.fromString; 2 | let process = Process.process; 3 | 4 | let outputPath = 5 | Path.relative(~from=Process.cwd(process), ~to_="example__output.txt"); 6 | 7 | let writeStream = Fs.createWriteStream(outputPath); 8 | 9 | let logErrorIfExists = maybeError => { 10 | switch (Js.Nullable.toOption(maybeError)) { 11 | | Some(err) => Js.log2("An error occurred", err) 12 | | None => () 13 | }; 14 | }; 15 | 16 | let () = 17 | writeStream 18 | ->Stream.writeWith( 19 | data, 20 | ~callback= 21 | maybeError => { 22 | logErrorIfExists(maybeError); 23 | Js.log("Finished"); 24 | }, 25 | (), 26 | ) 27 | ->ignore; 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reason-nodejs", 3 | "version": "13.0.0-beta.2", 4 | "scripts": { 5 | "build": "bsb -make-world", 6 | "clean-build": "bsb -clean-world && bsb -make-world", 7 | "start": "bsb -make-world -w", 8 | "clean-start": "bsb -clean-world && bsb -make-world -w", 9 | "test": "jest", 10 | "clean-test": "bsb -clean-world && bsb -make-world && jest", 11 | "clean": "bsb -clean-world" 12 | }, 13 | "keywords": [ 14 | "BuckleScript" 15 | ], 16 | "author": "Sikan He & Austin Davis", 17 | "homepage": "https://github.com/sikanhe/reason-node", 18 | "license": "MIT", 19 | "dependencies": {}, 20 | "devDependencies": { 21 | "@glennsl/bs-jest": "^0.4.10", 22 | "bs-platform": "^8.3.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Assert.re: -------------------------------------------------------------------------------- 1 | [@bs.module "assert"] external ok: 'a => unit = "ok"; 2 | [@bs.module "assert"] external equal: ('a, 'a) => unit = "equal"; 3 | [@bs.module "assert"] external notEqual: ('a, 'a) => unit = "notEqual"; 4 | [@bs.module "assert"] external deepEqual: ('a, 'a) => unit = "deepEqual"; 5 | [@bs.module "assert"] external notDeepEqual: ('a, 'a) => unit = "notDeepEqual"; 6 | [@bs.module "assert"] external strictEqual: ('a, 'a) => unit = "strictEqual"; 7 | [@bs.module "assert"] 8 | external notStrictEqual: ('a, 'a) => unit = "notStrictEqual"; 9 | [@bs.module "assert"] 10 | external deepStrictEqual: ('a, 'a) => unit = "deepStrictEqual"; 11 | [@bs.module "assert"] 12 | external notDeepStrictEqual: ('a, 'a) => unit = "notDeepStrictEqual"; 13 | [@bs.module "assert"] 14 | external throws: ([@bs.uncurry] (unit => 'a)) => unit = "throws"; 15 | [@bs.module "assert"] 16 | external throwsError: ([@bs.uncurry] (unit => 'a), 'e) => unit = "throws"; 17 | [@bs.module "assert"] 18 | external doesNotThrow: ([@bs.uncurry] (unit => 'a)) => unit = "doesNotThrow"; 19 | [@bs.module "assert"] 20 | external doesNotThrowError: ([@bs.uncurry] (unit => 'a), 'e) => unit = 21 | "doesNotThrow"; 22 | [@bs.module "assert"] external ifError: 'a => unit = "ifError"; 23 | [@bs.module "assert"] 24 | external rejects: ([@bs.uncurry] (unit => Js.Promise.t('a))) => unit = 25 | "rejects"; 26 | [@bs.module "assert"] 27 | external rejectsError: ([@bs.uncurry] (unit => Js.Promise.t('a)), 'e) => unit = 28 | "rejects"; 29 | [@bs.module "assert"] 30 | external doesNotReject: ([@bs.uncurry] (unit => Js.Promise.t('a))) => unit = 31 | "doesNotReject"; 32 | [@bs.module "assert"] 33 | external doesNotRejectError: 34 | ([@bs.uncurry] (unit => Js.Promise.t('a)), 'e) => unit = 35 | "doesNotReject"; 36 | 37 | module AssertionError = Errors.AssertionError; 38 | -------------------------------------------------------------------------------- /src/BigInt.re: -------------------------------------------------------------------------------- 1 | type t; 2 | 3 | [@bs.val] external fromInt: int => t = "BigInt"; 4 | [@bs.val] external toInt: t => int = "Number"; 5 | 6 | let%private _NEGATIVE_ONE = fromInt(-1); 7 | 8 | external (~-): t => t = "%negfloat"; 9 | external (+): (t, t) => t = "%addfloat"; 10 | external (-): (t, t) => t = "%subfloat"; 11 | external ( * ): (t, t) => t = "%mulfloat"; 12 | external (/): (t, t) => t = "%divfloat"; 13 | let (mod): (t, t) => t = Obj.magic(mod_float); 14 | let ( ** ): (t, t) => t = [%raw {|function (a, b) { return (a ** b); }|}]; 15 | external (land): (t, t) => t = "%andint"; 16 | external (lor): (t, t) => t = "%orint"; 17 | external (lxor): (t, t) => t = "%xorint"; 18 | let lnot: t => t = x => x lxor _NEGATIVE_ONE; 19 | external (lsl): (t, t) => t = "%lslint"; 20 | external (asr): (t, t) => t = "%asrint"; 21 | 22 | external negate: t => t = "%negfloat"; 23 | external add: (t, t) => t = "%addfloat"; 24 | external subtract: (t, t) => t = "%subfloat"; 25 | external multiply: (t, t) => t = "%mulfloat"; 26 | external divide: (t, t) => t = "%divfloat"; 27 | let modulo: (t, t) => t = Obj.magic(mod_float); 28 | let power: (t, t) => t = ( ** ); 29 | external logicalAnd: (t, t) => t = "%andint"; 30 | external logicalOr: (t, t) => t = "%orint"; 31 | external logicalXor: (t, t) => t = "%xorint"; 32 | let logicalNot: t => t = x => x lxor _NEGATIVE_ONE; 33 | external logicalShiftLeft: (t, t) => t = "%lslint"; 34 | external arithmeticShiftRight: (t, t) => t = "%asrint"; 35 | -------------------------------------------------------------------------------- /src/BinaryLike.re: -------------------------------------------------------------------------------- 1 | module Impl: { 2 | open Js.TypedArray2; 3 | 4 | type t; 5 | 6 | type case = 7 | | String(string) 8 | | Buffer(Buffer.t) 9 | | Uint8Array(Uint8Array.t) 10 | | Int8Array(Int8Array.t) 11 | | Uint8ClampedArray(Uint8ClampedArray.t) 12 | | Uint16Array(Uint16Array.t) 13 | | Int16Array(Int16Array.t) 14 | | Uint32Array(Uint32Array.t) 15 | | Int32Array(Uint32Array.t) 16 | | Float32Array(Float32Array.t) 17 | | Float64Array(Float64Array.t) 18 | | DataView(DataView.t) 19 | | Unknown(t); 20 | 21 | let string: string => t; 22 | let buffer: Buffer.t => t; 23 | let int8Array: Int8Array.t => t; 24 | let uInt8Array: Uint8Array.t => t; 25 | let uInt8ClampedArray: Uint8ClampedArray.t => t; 26 | let uInt16Array: Uint16Array.t => t; 27 | let int16Array: Int16Array.t => t; 28 | let uInt32Array: Uint32Array.t => t; 29 | let int32Array: Int32Array.t => t; 30 | let float32Array: Float32Array.t => t; 31 | let float64Array: Float64Array.t => t; 32 | let dataView: DataView.t => t; 33 | let classify: t => case; 34 | } = { 35 | open Js.TypedArray2; 36 | 37 | [@unboxed] 38 | type t = 39 | | BinaryLike('a): t; 40 | 41 | type case = 42 | | String(string) 43 | | Buffer(Buffer.t) 44 | | Uint8Array(Uint8Array.t) 45 | | Int8Array(Int8Array.t) 46 | | Uint8ClampedArray(Uint8ClampedArray.t) 47 | | Uint16Array(Uint16Array.t) 48 | | Int16Array(Int16Array.t) 49 | | Uint32Array(Uint32Array.t) 50 | | Int32Array(Uint32Array.t) 51 | | Float32Array(Float32Array.t) 52 | | Float64Array(Float64Array.t) 53 | | DataView(DataView.t) 54 | | Unknown(t); 55 | 56 | let string: string => t = x => BinaryLike(x); 57 | let buffer: Buffer.t => t = x => BinaryLike(x); 58 | let int8Array: Int8Array.t => t = x => BinaryLike(x); 59 | let uInt8Array: Uint8Array.t => t = x => BinaryLike(x); 60 | let uInt8ClampedArray: Uint8ClampedArray.t => t = x => BinaryLike(x); 61 | let uInt16Array: Uint16Array.t => t = x => BinaryLike(x); 62 | let int16Array: Int16Array.t => t = x => BinaryLike(x); 63 | let uInt32Array: Uint32Array.t => t = x => BinaryLike(x); 64 | let int32Array: Int32Array.t => t = x => BinaryLike(x); 65 | let float32Array: Float32Array.t => t = x => BinaryLike(x); 66 | let float64Array: Float64Array.t => t = x => BinaryLike(x); 67 | let dataView: DataView.t => t = x => BinaryLike(x); 68 | 69 | let classify: t => case = 70 | fun 71 | | BinaryLike(binaryLike) => 72 | if (Js.typeof(binaryLike) === "string") { 73 | String(Obj.magic(binaryLike)); 74 | } else if (Buffer.isBuffer(binaryLike)) { 75 | Buffer(Obj.magic(binaryLike)); 76 | } else if (Util.Types.isInt8Array(binaryLike)) { 77 | Int8Array(Obj.magic(binaryLike)); 78 | } else if (Util.Types.isUint8Array(binaryLike)) { 79 | Uint8Array(Obj.magic(binaryLike)); 80 | } else if (Util.Types.isUint8ClampedArray(binaryLike)) { 81 | Uint8ClampedArray(Obj.magic(binaryLike)); 82 | } else if (Util.Types.isInt16Array(binaryLike)) { 83 | Int16Array(Obj.magic(binaryLike)); 84 | } else if (Util.Types.isUint16Array(binaryLike)) { 85 | Uint16Array(Obj.magic(binaryLike)); 86 | } else if (Util.Types.isInt32Array(binaryLike)) { 87 | Int32Array(Obj.magic(binaryLike)); 88 | } else if (Util.Types.isUint32Array(binaryLike)) { 89 | Uint32Array(Obj.magic(binaryLike)); 90 | } else if (Util.Types.isFloat32Array(binaryLike)) { 91 | Float32Array(Obj.magic(binaryLike)); 92 | } else if (Util.Types.isFloat64Array(binaryLike)) { 93 | Float64Array(Obj.magic(binaryLike)); 94 | } else if (Util.Types.isDataView(binaryLike)) { 95 | DataView(Obj.magic(binaryLike)); 96 | } else if (Util.Types.isStringObject(binaryLike)) { 97 | String(Obj.magic(binaryLike)); 98 | } else { 99 | Unknown(Obj.magic(binaryLike)); 100 | }; 101 | }; 102 | 103 | include Impl; 104 | -------------------------------------------------------------------------------- /src/Buffer.re: -------------------------------------------------------------------------------- 1 | type t = Node.buffer; 2 | open Js.TypedArray2; 3 | 4 | module Constants = { 5 | [@bs.module "buffer"] [@bs.scope "constants"] [@bs.val] 6 | external _MAX_LENGTH: int = "MAX_LENGTH"; 7 | [@bs.module "buffer"] [@bs.scope "constants"] [@bs.val] 8 | external _MAX_STRING_LENGTH: int = "MAX_STRING_LENGTH"; 9 | }; 10 | 11 | [@bs.val] external isBuffer: 'a => bool = "Buffer.isBuffer"; 12 | [@bs.val] external fromString: string => t = "Buffer.from"; 13 | [@bs.val] 14 | external fromStringWithEncoding: (string, StringEncoding.t) => t = 15 | "Buffer.from"; 16 | 17 | /** 18 | * `fromArray(array)` 19 | * 20 | * Constructs a new `Buffer` object from an array of integers. 21 | */ 22 | [@bs.val] 23 | external fromArray: array(int) => t = "Buffer.from"; 24 | 25 | /** 26 | * `fromArrayBuffer(arrayBuffer)` 27 | * 28 | * Constructs a new `Buffer` object from an `ArrayBuffer` object. 29 | * 30 | * **Note:** This does not copy the data from the `ArrayBuffer` instance, but instead creates 31 | * a "view" over the existing data in memory. Mutations of the underlying `ArrayBuffer` 32 | * will be reflected in the `Buffer` view, and vice versa. 33 | */ 34 | [@bs.val] 35 | external fromArrayBuffer: ArrayBuffer.t => t = "Buffer.from"; 36 | 37 | /** 38 | * `fromArrayBufferOffset(arrayBuffer, ~offset)` 39 | * 40 | * Constructs a new `Buffer` object from an `ArrayBuffer` object, starting at index 41 | * `offset`. 42 | * 43 | * **Note:** This does not copy the data from the `ArrayBuffer` instance, but instead creates 44 | * a "view" over the existing data in memory. Mutations of the underlying `ArrayBuffer` 45 | * will be reflected in the `Buffer` view, and vice versa. 46 | */ 47 | [@bs.val] 48 | external fromArrayBufferOffset: (ArrayBuffer.t, ~offset: int) => t = 49 | "Buffer.from"; 50 | 51 | /** 52 | * `fromArrayBufferRange(arrayBuffer, ~offset, ~length)` 53 | * 54 | * Constructs a new `Buffer` object from an `ArrayBuffer` object, starting at index 55 | * `~offset`, and ending at index `~length`. 56 | * 57 | * **Note:** This does not copy the data from the `ArrayBuffer` instance, but instead creates 58 | * a "view" over the existing data in memory. Mutations of the underlying `ArrayBuffer` 59 | * will be reflected in the `Buffer` view, and vice versa. 60 | */ 61 | [@bs.val] 62 | external fromArrayBufferRange: (ArrayBuffer.t, ~offset: int, ~length: int) => t = 63 | "Buffer.from"; 64 | 65 | /** 66 | * `fromBuffer(buffer)` 67 | * 68 | * Constructs a new `Buffer` object from an existing `Buffer` object, creating a **copy** of 69 | * its internal data. 70 | */ 71 | [@bs.val] 72 | external fromBuffer: t => t = "Buffer.from"; 73 | 74 | /** 75 | * `alloc(size)` 76 | * 77 | * Allocates a new `Buffer` object with a length specified by `size`, setting each element 78 | * to zero. 79 | */ 80 | [@bs.val] 81 | external alloc: int => t = "Buffer.alloc"; 82 | 83 | /** 84 | * `allocFillInt(size, ~fill)` 85 | * 86 | * Allocates a new `Buffer` object with a length specified by `size`, and fills each element 87 | * with the value of `~fill`. 88 | */ 89 | [@bs.val] 90 | external allocFillInt: (int, ~fill: int) => t = "Buffer.alloc"; 91 | 92 | /** 93 | * `allocFillString(size, ~fill)` 94 | * 95 | * Allocates a new `Buffer` object with a length specified by `size`, and fills each element 96 | * with the value of `~fill`. 97 | */ 98 | [@bs.val] 99 | external allocFillString: (int, ~fill: string) => t = "Buffer.alloc"; 100 | 101 | /** 102 | * `allocFillStringWithEncoding(size, ~fill, encoding)` 103 | * 104 | * Allocates a new `Buffer` object with a length specified by `size`, fills each element 105 | * with the value of `~fill`, and sets the string encoding to `encoding`. 106 | */ 107 | [@bs.val] 108 | external allocFillStringWithEncoding: 109 | (int, ~fill: string, StringEncoding.t) => t = 110 | "Buffer.alloc"; 111 | 112 | /** 113 | * `allocFillBuffer(size, ~fill) 114 | * 115 | * Allocates a new `Buffer` object with a length specified by `size`, copying the data 116 | * from the `Buffer` object passed to the `~fill` parameter. 117 | */ 118 | [@bs.val] 119 | external allocFillBuffer: (int, ~fill: t) => t = "Buffer.alloc"; 120 | [@bs.val] external allocUnsafe: int => t = "Buffer.allocUnsafe"; 121 | [@bs.val] external allocUnsafeSlow: int => t = "Buffer.allocUnsafeSlow"; 122 | 123 | [@bs.get_index] external unsafeGet: (t, int) => int; 124 | [@bs.set_index] external unsafeSet: (t, int, int) => unit; 125 | 126 | [@bs.val] external byteLengthString: string => int = "Buffer.byteLength"; 127 | [@bs.val] 128 | external byteLengthStringWithEncoding: (string, StringEncoding.t) => int = 129 | "Buffer.byteLength"; 130 | [@bs.val] external byteLengthBuffer: t => int = "Buffer.byteLength"; 131 | [@bs.val] 132 | external byteLengthInt8Array: Int8Array.t => int = "Buffer.byteLength"; 133 | [@bs.val] 134 | external byteLengthUint8Array: Uint8Array.t => int = "Buffer.byteLength"; 135 | [@bs.val] 136 | external byteLengthInt16Array: Int16Array.t => int = "Buffer.byteLength"; 137 | [@bs.val] 138 | external byteLengthUint16Array: Uint16Array.t => int = "Buffer.byteLength"; 139 | [@bs.val] 140 | external byteLengthInt32Array: Int32Array.t => int = "Buffer.byteLength"; 141 | [@bs.val] 142 | external byteLengthUint32Array: Uint32Array.t => int = "Buffer.byteLength"; 143 | [@bs.val] 144 | external byteLengthFloat32Array: Float32Array.t => int = "Buffer.byteLength"; 145 | [@bs.val] 146 | external byteLengthFloat64Array: Float64Array.t => int = "Buffer.byteLength"; 147 | [@bs.val] external byteLengthDataView: DataView.t => int = "Buffer.byteLength"; 148 | [@bs.val] 149 | external byteLengthArrayBuffer: ArrayBuffer.t => int = "Buffer.byteLength"; 150 | 151 | [@bs.val] external compare: (t, t) => int = "Buffer.compare"; 152 | 153 | [@bs.val] external concat: array(t) => t = "Buffer.concat"; 154 | [@bs.val] 155 | external concatLength: (array(t), ~length: int) => t = "Buffer.concat"; 156 | 157 | [@bs.val] external isEncoding: string => bool = "Buffer.isEncoding"; 158 | 159 | type bufferClass; 160 | 161 | [@bs.val] external bufferClass: bufferClass = "Buffer"; 162 | [@bs.val] external poolSize: int = "Buffer.poolSize"; 163 | [@bs.set] external setPoolSize: (bufferClass, int) => int = "poolSize"; 164 | 165 | [@bs.send] external copy: (t, t) => int = "copy"; 166 | [@bs.send] external copyOffset: (t, t, ~offset: int) => int = "copy"; 167 | [@bs.send] 168 | external copyOffsetFromOffset: 169 | (t, t, ~targetStart: int, ~sourceStart: int) => int = 170 | "copy"; 171 | [@bs.send] 172 | external copyOffsetFromRange: 173 | (t, t, ~targetStart: int, ~sourceStart: int, ~sourceEnd: int) => int = 174 | "copy"; 175 | [@bs.send] external copyToUint8Array: (t, Uint8Array.t) => int = "copy"; 176 | [@bs.send] 177 | external copyToUint8ArrayOffset: (t, Uint8Array.t, ~targetStart: int) => int = 178 | "copy"; 179 | [@bs.send] 180 | external copyToUint8ArrayFrom: 181 | (t, Uint8Array.t, ~targetStart: int, ~sourceStart: int) => int = 182 | "copy"; 183 | [@bs.send] 184 | external copyToUint8ArrayFromRange: 185 | (t, Uint8Array.t, ~targetStart: int, ~sourceStart: int, ~sourceEnd: int) => 186 | int = 187 | "copy"; 188 | 189 | /* FIXME after iterators support */ 190 | /* external entries : t -> Iterator = "" [@@bs.get] */ 191 | 192 | [@bs.send] external equals: (t, t) => bool = "equals"; 193 | 194 | [@bs.send] external fillString: (t, string) => t = "fill"; 195 | [@bs.send] external fillStringOffset: (t, string, ~offset: int) => t = "fill"; 196 | [@bs.send] 197 | external fillStringRange: (t, string, ~offset: int, ~end_: int) => t = "fill"; 198 | [@bs.send] 199 | external fillStringRangeWithEncoding: 200 | (t, string, ~offset: int, ~end_: int, StringEncoding.t) => t = 201 | "fill"; 202 | [@bs.send] external fillBuffer: (t, t) => t = "fill"; 203 | [@bs.send] external fillBufferOffset: (t, t, ~offset: int) => t = "fill"; 204 | [@bs.send] 205 | external fillBufferRange: (t, t, ~offset: int, ~end_: int) => t = "fill"; 206 | [@bs.send] external fillInt: (t, int) => t = "fill"; 207 | [@bs.send] external fillIntOffset: (t, int, ~offset: int) => t = "fill"; 208 | [@bs.send] 209 | external fillIntRange: (t, int, ~offset: int, ~end_: int) => t = "fill"; 210 | 211 | [@bs.send] external includesString: (t, string) => bool = "includes"; 212 | [@bs.send] 213 | external includesStringFrom: (t, string, ~offset: int) => bool = "includes"; 214 | [@bs.send] 215 | external includesStringWithEncodingFrom: 216 | (t, string, ~offset: int, StringEncoding.t) => bool = 217 | "includes"; 218 | [@bs.send] external includesBuffer: (t, t) => bool = "includes"; 219 | [@bs.send] 220 | external includesBufferFrom: (t, t, ~offset: int) => bool = "includes"; 221 | [@bs.send] external includesInt: (t, int) => bool = "includes"; 222 | [@bs.send] 223 | external includesIntFrom: (t, int, ~offset: int) => bool = "includes"; 224 | 225 | [@bs.send] external indexOfString: (t, string) => int = "indexOf"; 226 | [@bs.send] 227 | external indexOfStringFrom: (t, string, ~offset: int) => int = "indexOf"; 228 | [@bs.send] 229 | external indexOfStringWithEncodingFrom: 230 | (t, string, ~offset: int, StringEncoding.t) => int = 231 | "indexOf"; 232 | [@bs.send] external indexOfBuffer: (t, t) => int = "indexOf"; 233 | [@bs.send] external indexOfBufferFrom: (t, t, ~offset: int) => int = "indexOf"; 234 | [@bs.send] external indexOfInt: (t, int) => int = "indexOf"; 235 | [@bs.send] external indexOfIntFrom: (t, int, ~offset: int) => int = "indexOf"; 236 | 237 | /* FIXME after iterators support */ 238 | /* external keys : t -> Iterator = "" [@@bs.send] */ 239 | 240 | [@bs.send] external lastIndexOfString: (t, string) => int = "lastIndexOf"; 241 | [@bs.send] 242 | external lastIndexOfStringFrom: (t, string, ~offset: int) => int = 243 | "lastIndexOf"; 244 | [@bs.send] 245 | external lastIndexOfStringWithEncodingFrom: 246 | (t, string, ~offset: int, StringEncoding.t) => int = 247 | "lastIndexOf"; 248 | [@bs.send] external lastIndexOfBuffer: (t, t) => int = "lastIndexOf"; 249 | [@bs.send] 250 | external lastIndexOfBufferFrom: (t, t, ~offset: int) => int = "lastIndexOf"; 251 | [@bs.send] external lastIndexOfInt: (t, int) => int = "lastIndexOf"; 252 | [@bs.send] 253 | external lastIndexOfIntFrom: (t, int, ~offset: int) => int = "lastIndexOf"; 254 | 255 | [@bs.get] external length: t => int = "length"; 256 | 257 | [@bs.send] external readDoubleBE: (t, ~offset: int) => float = "readDoubleBE"; 258 | [@bs.send] external readDoubleLE: (t, ~offset: int) => float = "readDoubleLE"; 259 | 260 | [@bs.send] external readFloatBE: (t, ~offset: int) => float = "readFloatBE"; 261 | [@bs.send] external readFloatLE: (t, ~offset: int) => float = "readFloatLE"; 262 | 263 | [@bs.send] external readInt8: (t, ~offset: int) => float = "readInt8"; 264 | 265 | [@bs.send] external readInt16BE: (t, ~offset: int) => float = "readInt16BE"; 266 | [@bs.send] external readInt16LE: (t, ~offset: int) => float = "readInt16LE"; 267 | 268 | [@bs.send] external readInt32BE: (t, ~offset: int) => float = "readInt32BE"; 269 | [@bs.send] external readInt32LE: (t, ~offset: int) => float = "readInt32LE"; 270 | 271 | [@bs.send] external readIntBE: (t, ~offset: int) => float = "readIntBE"; 272 | [@bs.send] 273 | external readIntLE: (t, ~offset: int, ~length: int) => float = "readIntLE"; 274 | 275 | [@bs.send] external readUint8: (t, ~offset: int) => float = "readUint8"; 276 | 277 | [@bs.send] external readUint16BE: (t, ~offset: int) => float = "readUint16BE"; 278 | [@bs.send] external readUint16LE: (t, ~offset: int) => float = "readUint16LE"; 279 | 280 | [@bs.send] external readUint32BE: (t, ~offset: int) => float = "readUint32BE"; 281 | [@bs.send] external readUint32LE: (t, ~offset: int) => float = "readUint32LE"; 282 | 283 | [@bs.send] 284 | external readUintBE: (t, ~offset: int, ~length: int) => float = "readUintBE"; 285 | [@bs.send] 286 | external readUintLE: (t, ~offset: int, ~length: int) => float = "readUintLE"; 287 | 288 | [@bs.send] external slice: (t, ~start: int, ~end_: int) => t = "slice"; 289 | [@bs.send] external sliceToEnd: (t, ~start: int) => t = "slice"; 290 | 291 | [@bs.send] external swap16: t => t = "swap16"; 292 | [@bs.send] external swap32: t => t = "swap32"; 293 | [@bs.send] external swap64: t => t = "swap64"; 294 | 295 | [@bs.send] external toJSON: t => Js.Json.t = "toJSON"; 296 | 297 | [@bs.send] external toString: t => string = "toString"; 298 | [@bs.send] 299 | external toStringWithEncoding: (t, StringEncoding.t) => string = "toString"; 300 | [@bs.send] 301 | external toStringWithEncodingOffset: 302 | (t, StringEncoding.t, ~start: int) => string = 303 | "toString"; 304 | [@bs.send] 305 | external toStringWithEncodingRange: 306 | (t, StringEncoding.t, ~start: int, ~end_: int) => string = 307 | "toString"; 308 | 309 | [@bs.send] external write: (t, string) => int = "write"; 310 | [@bs.send] 311 | external writeWithEncoding: (t, string, StringEncoding.t) => int = "write"; 312 | [@bs.send] external writeOffset: (t, string, ~offset: int) => int = "write"; 313 | [@bs.send] 314 | external writeRange: (t, string, ~offset: int, ~length: int) => int = "write"; 315 | [@bs.send] 316 | external writeRangeWithEncoding: 317 | (t, string, ~offset: int, ~length: int, StringEncoding.t) => int = 318 | "write"; 319 | 320 | [@bs.send] 321 | external writeDoubleBE: (t, float, ~offset: int) => float = "writeDoubleBE"; 322 | [@bs.send] 323 | external writeDoubleLE: (t, float, ~offset: int) => float = "writeDoubleLE"; 324 | [@bs.send] 325 | external writeFloatBE: (t, float, ~offset: int) => float = "writeFloatBE"; 326 | [@bs.send] 327 | external writeFloatLE: (t, float, ~offset: int) => float = "writeFloatLE"; 328 | [@bs.send] external writeInt8: (t, int, ~offset: int) => float = "writeInt8"; 329 | [@bs.send] 330 | external writeInt16BE: (t, int, ~offset: int) => float = "writeInt16BE"; 331 | [@bs.send] 332 | external writeInt16LE: (t, int, ~offset: int) => float = "writeInt16LE"; 333 | [@bs.send] 334 | external writeInt32BE: (t, int, ~offset: int) => float = "writeInt32BE"; 335 | [@bs.send] 336 | external writeInt32LE: (t, int, ~offset: int) => float = "writeInt32LE"; 337 | [@bs.send] 338 | external writeIntBE: (t, int, ~offset: int, ~length: int) => float = 339 | "writeIntBE"; 340 | [@bs.send] 341 | external writeIntLE: (t, int, ~offset: int, ~length: int) => float = 342 | "writeIntLE"; 343 | [@bs.send] external writeUint8: (t, int, ~offset: int) => float = "writeUint8"; 344 | [@bs.send] 345 | external writeUint16BE: (t, int, ~offset: int) => float = "writeUint16BE"; 346 | [@bs.send] 347 | external writeUint16LE: (t, int, ~offset: int) => float = "writeUint16LE"; 348 | [@bs.send] 349 | external writeUint32BE: (t, int, ~offset: int) => float = "writeUint32BE"; 350 | [@bs.send] 351 | external writeUint32LE: (t, int, ~offset: int) => float = "writeUint32LE"; 352 | [@bs.send] 353 | external writeUintBE: (t, int, ~offset: int, ~length: int) => float = 354 | "writeUintBE"; 355 | [@bs.send] 356 | external writeUintLE: (t, int, ~offset: int, ~length: int) => float = 357 | "writeUintLE"; 358 | 359 | [@bs.get] external _INSPECT_MAX_BYTES: t => int = "INSPECT_MAX_BYTES"; 360 | [@bs.get] external kMaxLength: t => int = "kMaxLength"; 361 | 362 | [@bs.send] 363 | external transcode: 364 | (t, ~source: t, ~from: StringEncoding.t, ~to_: StringEncoding.t) => t = 365 | "transcode"; 366 | -------------------------------------------------------------------------------- /src/ChildProcess.re: -------------------------------------------------------------------------------- 1 | type t; 2 | 3 | module Events = { 4 | [@bs.send] 5 | external onData: 6 | (t, [@bs.as "data"] _, [@bs.uncurry] (Buffer.t => unit)) => t = 7 | "on"; 8 | [@bs.send] 9 | external onDisconnect: 10 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 11 | "on"; 12 | [@bs.send] 13 | external onError: 14 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 15 | "on"; 16 | [@bs.send] 17 | external onExit: (t, [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => t = 18 | "on"; 19 | [@bs.send] 20 | external onClose: (t, [@bs.as "close"] _, [@bs.uncurry] (int => unit)) => t = 21 | "on"; 22 | 23 | [@bs.send] 24 | external offData: 25 | (t, [@bs.as "data"] _, [@bs.uncurry] (Buffer.t => unit)) => t = 26 | "off"; 27 | [@bs.send] 28 | external offDisconnect: 29 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 30 | "off"; 31 | [@bs.send] 32 | external offError: 33 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 34 | "off"; 35 | [@bs.send] 36 | external offExit: (t, [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => t = 37 | "off"; 38 | [@bs.send] 39 | external offClose: (t, [@bs.as "close"] _, [@bs.uncurry] (int => unit)) => t = 40 | "off"; 41 | 42 | [@bs.send] 43 | external onDataOnce: 44 | (t, [@bs.as "data"] _, [@bs.uncurry] (Buffer.t => unit)) => t = 45 | "once"; 46 | [@bs.send] 47 | external onDisconnectOnce: 48 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 49 | "once"; 50 | [@bs.send] 51 | external onErrorOnce: 52 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 53 | "once"; 54 | [@bs.send] 55 | external onExitOnce: (t, [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => t = 56 | "once"; 57 | [@bs.send] 58 | external onCloseOnce: 59 | (t, [@bs.as "close"] _, [@bs.uncurry] (int => unit)) => t = 60 | "once"; 61 | 62 | [@bs.send] 63 | external emitData: (t, [@bs.as "data"] _, Buffer.t) => bool = "emit"; 64 | [@bs.send] 65 | external emitDisconnect: (t, [@bs.as "disconnect"] _) => bool = "emit"; 66 | [@bs.send] 67 | external emitError: (t, [@bs.as "error"] _, Js.Exn.t) => bool = "emit"; 68 | [@bs.send] external emitExit: (t, [@bs.as "exit"] _, int) => bool = "emit"; 69 | [@bs.send] external emitClose: (t, [@bs.as "close"] _, int) => bool = "emit"; 70 | 71 | [@bs.send] external removeAllListeners: t => t = "removeAllListeners"; 72 | }; 73 | include Events; 74 | 75 | [@bs.get] external connected: t => bool = "connected"; 76 | [@bs.send] external disconnect: t => bool = "disconnect"; 77 | [@bs.send] external kill: (t, string) => unit = "kill"; 78 | [@bs.get] external killed: t => bool = "killed"; 79 | [@bs.get] external pid: t => int = "pid"; 80 | [@bs.get] external ref: t => unit = "ref"; 81 | [@bs.get] [@bs.return nullable] 82 | external stderr: t => option(Stream.Writable.t(Buffer.t)) = "stderr"; 83 | [@bs.get] [@bs.return nullable] 84 | external stdin: t => option(Stream.Readable.t(Buffer.t)) = "stdin"; 85 | [@bs.get] [@bs.return nullable] 86 | external stdout: t => option(Stream.Writable.t(Buffer.t)) = "stdout"; 87 | [@bs.get] external unref: t => unit = "unref"; 88 | 89 | type execOptions; 90 | 91 | [@bs.obj] 92 | external execOptions: 93 | ( 94 | ~cwd: string=?, 95 | ~env: Js.Dict.t(string)=?, 96 | ~shell: string=?, 97 | ~timeout: int=?, 98 | ~maxBuffer: int=?, 99 | ~killSignal: string=?, 100 | ~uid: int=?, 101 | ~gid: int=?, 102 | ~windowsHide: bool=?, 103 | unit 104 | ) => 105 | execOptions; 106 | 107 | [@bs.module "child_process"] [@bs.val] 108 | external exec: (string, (Js.nullable(Js.Exn.t), Buffer.t, Buffer.t) => unit) => t = 109 | "exec"; 110 | 111 | [@bs.module "child_process"] [@bs.val] 112 | external execWith: 113 | (string, execOptions, (Js.nullable(Js.Exn.t), Buffer.t, Buffer.t) => unit) => t = 114 | "exec"; 115 | 116 | type execFileOptions; 117 | 118 | [@bs.obj] 119 | external execFileOption: 120 | ( 121 | ~cwd: string=?, 122 | ~env: Js.Dict.t(string)=?, 123 | ~timeout: int=?, 124 | ~maxBuffer: int=?, 125 | ~killSignal: string=?, 126 | ~uid: int=?, 127 | ~gid: int=?, 128 | ~windowsHide: bool=?, 129 | ~shell: string=?, 130 | unit 131 | ) => 132 | execFileOptions; 133 | 134 | [@bs.module "child_process"] [@bs.val] 135 | external execFile: 136 | (string, array(string), (Js.nullable(Js.Exn.t), Buffer.t, Buffer.t) => unit) => t = 137 | "execFile"; 138 | 139 | [@bs.module "child_process"] [@bs.val] 140 | external execFileWith: 141 | ( 142 | string, 143 | array(string), 144 | execFileOptions, 145 | (Js.nullable(Js.Exn.t), Buffer.t, Buffer.t) => unit 146 | ) => 147 | t = 148 | "execFile"; 149 | 150 | type forkOptions; 151 | 152 | [@bs.obj] 153 | external forkOptions: 154 | ( 155 | ~cwd: string=?, 156 | ~detached: bool=?, 157 | ~env: Js.Dict.t(string)=?, 158 | ~execPath: string=?, 159 | ~execArgv: array(string)=?, 160 | ~silent: bool=?, 161 | ~stdio: string=?, 162 | ~uid: int=?, 163 | ~gid: int=?, 164 | ~windowsVerbatimArguments: bool=?, 165 | unit 166 | ) => 167 | forkOptions; 168 | 169 | [@bs.module "child_process"] [@bs.val] 170 | external fork: (string, array(string)) => t = "fork"; 171 | 172 | [@bs.module "child_process"] [@bs.val] 173 | external forkWith: (string, array(string), forkOptions) => t = "fork"; 174 | 175 | type spawnOptions; 176 | 177 | [@bs.obj] 178 | external spawnOptions: 179 | ( 180 | ~cwd: string=?, 181 | ~env: Js.Dict.t(string)=?, 182 | ~argv0: string=?, 183 | ~stdio: string=?, 184 | ~detached: bool=?, 185 | ~uid: int=?, 186 | ~gid: int=?, 187 | ~shell: string=?, 188 | ~windowsVerbatimArguments: bool=?, 189 | ~windowsHide: bool=?, 190 | unit 191 | ) => 192 | spawnOptions; 193 | 194 | [@bs.module "child_process"] [@bs.val] 195 | external spawn: (string, array(string)) => t = "spawn"; 196 | 197 | [@bs.module "child_process"] [@bs.val] 198 | external spawnWith: (string, array(string), spawnOptions) => t = "spawn"; 199 | 200 | type spawnSyncResult('a) = { 201 | pid: int, 202 | output: array('a), 203 | stdout: Buffer.t, 204 | stderr: Buffer.t, 205 | status: int, 206 | signal: Js.nullable(string), 207 | error: Js.nullable(Js.Exn.t), 208 | }; 209 | 210 | type spawnSyncOptions; 211 | 212 | [@bs.obj] 213 | external spawnSyncOptions: 214 | ( 215 | ~cwd: string=?, 216 | ~env: Js.Dict.t(string)=?, 217 | ~input: Buffer.t=?, 218 | ~argv0: string=?, 219 | ~stdio: string=?, 220 | ~detached: bool=?, 221 | ~uid: int=?, 222 | ~gid: int=?, 223 | ~shell: string=?, 224 | ~windowsVerbatimArguments: bool=?, 225 | ~windowsHide: bool=?, 226 | unit 227 | ) => 228 | spawnSyncOptions; 229 | 230 | [@bs.module "child_process"] [@bs.val] 231 | external spawnSync: 232 | (string, array(string), spawnSyncOptions) => spawnSyncResult('a) = 233 | "spawnSync"; 234 | 235 | [@bs.module "child_process"] [@bs.val] 236 | external spawnSyncWith: 237 | (string, array(string), spawnSyncOptions) => spawnSyncResult('a) = 238 | "spawnSync"; 239 | 240 | type execSyncOptions; 241 | 242 | [@bs.obj] 243 | external execSyncOptions: 244 | ( 245 | ~cwd: string=?, 246 | ~env: Js.Dict.t(string)=?, 247 | ~input: Buffer.t=?, 248 | ~shell: string=?, 249 | ~timeout: int=?, 250 | ~maxBuffer: int=?, 251 | ~killSignal: string=?, 252 | ~uid: int=?, 253 | ~gid: int=?, 254 | ~windowsHide: bool=?, 255 | unit 256 | ) => 257 | execSyncOptions; 258 | 259 | [@bs.module "child_process"] [@bs.val] 260 | external execSync: string => Buffer.t = "execSync"; 261 | 262 | [@bs.module "child_process"] [@bs.val] 263 | external execSyncWith: (string, execSyncOptions) => Buffer.t = "execSync"; 264 | 265 | type execFileSyncOptions; 266 | 267 | [@bs.obj] 268 | external execFileSyncOptions: 269 | ( 270 | ~cwd: string=?, 271 | ~env: Js.Dict.t(string)=?, 272 | ~input: Buffer.t=?, 273 | ~shell: string=?, 274 | ~timeout: int=?, 275 | ~maxBuffer: int=?, 276 | ~killSignal: string=?, 277 | ~uid: int=?, 278 | ~gid: int=?, 279 | ~windowsHide: bool=?, 280 | unit 281 | ) => 282 | execFileSyncOptions; 283 | 284 | [@bs.module "child_process"] [@bs.val] 285 | external execFileSync: (string, array(string)) => Buffer.t = "execFileSync"; 286 | 287 | [@bs.module "child_process"] [@bs.val] 288 | external execFileSyncWith: 289 | (string, array(string), execFileSyncOptions) => Buffer.t = 290 | "execFileSync"; 291 | -------------------------------------------------------------------------------- /src/Cluster.re: -------------------------------------------------------------------------------- 1 | module Address = { 2 | type t = 3 | pri { 4 | [@bs.as "address"] 5 | address: string, 6 | [@bs.as "port"] 7 | port: string, 8 | }; 9 | type internalView('a) = 10 | pri { 11 | [@bs.as "address"] 12 | address: string, 13 | [@bs.as "port"] 14 | port: string, 15 | [@bs.as "addressType"] 16 | addressType: 'a, 17 | }; 18 | type case = 19 | | TcpV4(t) 20 | | TcpV6(t) 21 | | UnixDomainSocket(t) 22 | | Udp4(t) 23 | | Udp6(t) 24 | | Unknown(t); 25 | 26 | let classify: t => case = 27 | fun 28 | | address => { 29 | let internalReturn: internalView('a) = Obj.magic(address); 30 | let addressType = internalReturn.addressType; 31 | let intOrString = Js.typeof(addressType); 32 | switch (intOrString) { 33 | | "number" => 34 | switch ((Obj.magic(addressType): int)) { 35 | | 4 => TcpV4(address) 36 | | 6 => TcpV6(address) 37 | | (-1) => UnixDomainSocket(address) 38 | | _ => Unknown(address) 39 | } 40 | | "string" => 41 | switch ((Obj.magic(addressType): string)) { 42 | | "udp4" => Udp4(address) 43 | | "udp6" => Udp6(address) 44 | | _ => Unknown(address) 45 | } 46 | | _ => Unknown(address) 47 | }; 48 | }; 49 | }; 50 | 51 | module Message = { 52 | type t('a) = Js.t('a); 53 | }; 54 | 55 | module Worker = { 56 | type t; 57 | module Events = { 58 | [@bs.send] 59 | external onDisconnect: 60 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 61 | "on"; 62 | [@bs.send] 63 | external onError: 64 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 65 | "on"; 66 | [@bs.send] 67 | external onExit: 68 | ( 69 | t, 70 | [@bs.as "exit"] _, 71 | [@bs.uncurry] ((Js.nullable(int), Js.nullable(string)) => unit) 72 | ) => 73 | t = 74 | "on"; 75 | [@bs.send] 76 | external onListening: 77 | (t, [@bs.as "listening"] _, [@bs.uncurry] (Address.t => unit)) => t = 78 | "on"; 79 | [@bs.send] 80 | external onMessage: 81 | ( 82 | t, 83 | [@bs.as "message"] _, 84 | [@bs.uncurry] ((Message.t('a), Js.nullable(Js.t('a))) => unit) 85 | ) => 86 | t = 87 | "on"; 88 | [@bs.send] 89 | external onOnline: 90 | (t, [@bs.as "online"] _, [@bs.uncurry] (unit => unit)) => t = 91 | "on"; 92 | 93 | [@bs.send] 94 | external offDisconnect: 95 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 96 | "off"; 97 | [@bs.send] 98 | external offError: 99 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 100 | "off"; 101 | [@bs.send] 102 | external offExit: 103 | ( 104 | t, 105 | [@bs.as "exit"] _, 106 | [@bs.uncurry] ((Js.nullable(int), Js.nullable(string)) => unit) 107 | ) => 108 | t = 109 | "off"; 110 | [@bs.send] 111 | external offListening: 112 | (t, [@bs.as "listening"] _, [@bs.uncurry] (Address.t => unit)) => t = 113 | "off"; 114 | [@bs.send] 115 | external offMessage: 116 | ( 117 | t, 118 | [@bs.as "message"] _, 119 | [@bs.uncurry] ((Message.t('a), Js.nullable(Js.t('a))) => unit) 120 | ) => 121 | t = 122 | "off"; 123 | [@bs.send] 124 | external offOnline: 125 | (t, [@bs.as "online"] _, [@bs.uncurry] (unit => unit)) => t = 126 | "off"; 127 | 128 | [@bs.send] 129 | external onDisconnectOnce: 130 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 131 | "once"; 132 | [@bs.send] 133 | external onErrorOnce: 134 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 135 | "once"; 136 | [@bs.send] 137 | external onExitOnce: 138 | ( 139 | t, 140 | [@bs.as "exit"] _, 141 | [@bs.uncurry] ((Js.nullable(int), Js.nullable(string)) => unit) 142 | ) => 143 | t = 144 | "once"; 145 | [@bs.send] 146 | external onListeningOnce: 147 | (t, [@bs.as "listening"] _, [@bs.uncurry] (Address.t => unit)) => t = 148 | "once"; 149 | [@bs.send] 150 | external onMessageOnce: 151 | ( 152 | t, 153 | [@bs.as "message"] _, 154 | [@bs.uncurry] ((Message.t('a), Js.nullable(Js.t('a))) => unit) 155 | ) => 156 | t = 157 | "once"; 158 | [@bs.send] 159 | external onOnlineOnce: 160 | (t, [@bs.as "online"] _, [@bs.uncurry] (unit => unit)) => t = 161 | "once"; 162 | 163 | [@bs.send] external removeAllListeners: t => unit = "removeAllListeners"; 164 | }; 165 | [@bs.send] external disconnect: t => unit = "disconnect"; 166 | [@bs.send] 167 | external exitedAfterDisconnect: t => bool = "exitedAfterDisconnect"; 168 | [@bs.send] external id: t => int = "id"; 169 | [@bs.send] external isConnected: t => bool = "isConnected"; 170 | [@bs.send] external isDead: t => bool = "isConnected"; 171 | [@bs.send] external kill: t => unit = "kill"; 172 | [@bs.send] external killWith: (t, ~signal: string) => unit = "kill"; 173 | [@bs.send] external process: t => ChildProcess.t = "process"; 174 | [@bs.send] external send: string => unit = "send"; 175 | 176 | [@bs.send] 177 | external sendHttpServerHandle: 178 | (string, Http.Server.t, Js.nullable(Js.t({..}))) => unit = 179 | "send"; 180 | let sendHttpServerHandle = (~options=?, msg, handle) => 181 | sendHttpServerHandle(msg, handle, Js.Nullable.fromOption(options)); 182 | [@bs.send] 183 | external sendSocketHandle: 184 | (string, Net.Socket.subtype('w, 'r, 'a), Js.nullable(Js.t({..}))) => 185 | unit = 186 | "send"; 187 | let sendSocketHandle = (~options=?, msg, handle) => 188 | sendSocketHandle(msg, handle, Js.Nullable.fromOption(options)); 189 | }; 190 | 191 | type clusterSettings = 192 | pri { 193 | execArgv: Js.nullable(array(string)), 194 | exec: Js.nullable(string), 195 | args: Js.nullable(array(string)), 196 | cwd: Js.nullable(string), 197 | serialization: Js.nullable(string), 198 | silent: Js.nullable(bool), 199 | stdio: Js.nullable(array(string)), 200 | uid: Js.nullable(int), 201 | gid: Js.nullable(int), 202 | inspectPort: Js.nullable(int), 203 | windowsHide: Js.nullable(bool), 204 | }; 205 | 206 | [@bs.obj] 207 | external clusterSettings: 208 | ( 209 | ~execArgv: array(string)=?, 210 | ~exec: string=?, 211 | ~args: array(string)=?, 212 | ~cwd: string=?, 213 | ~serialization: string=?, 214 | ~silent: bool=?, 215 | ~stdio: array(string)=?, 216 | ~uid: int=?, 217 | ~gid: int=?, 218 | ~inspectPort: int=?, 219 | ~windowsHide: bool=?, 220 | unit 221 | ) => 222 | clusterSettings; 223 | 224 | [@bs.module] 225 | external disconnect: Js.Nullable.t(unit => unit) => unit = "disconnect"; 226 | let disconnect = (~callback=?, ()) => 227 | disconnect(Js.Nullable.fromOption(callback)); 228 | [@bs.module "cluster"] 229 | external fork: option(Js.Dict.t(string)) => Worker.t = "fork"; 230 | let fork = (~env=?, ()) => fork(env); 231 | [@bs.module "cluster"] external isMaster: bool = "isMaster"; 232 | [@bs.module "cluster"] external isWorker: bool = "isWorker"; 233 | [@bs.module "cluster"] external settings: clusterSettings = "settings"; 234 | [@bs.module "cluster"] 235 | external setupMaster: clusterSettings => unit = "setupMaster"; 236 | [@bs.module "cluster"] external _SCHED_NONE: int = "SCHED_NONE"; 237 | [@bs.module "cluster"] external _SCHED_RR: int = "SCHED_RR"; 238 | [@bs.module "cluster"] external schedulingPolicy: int = "schedulingPolicy"; 239 | type schedulingPolicy = 240 | | SCHED_NONE 241 | | SCHED_RR; 242 | let decodeSchedulingPolicy = 243 | if (schedulingPolicy === _SCHED_RR) { 244 | SCHED_RR; 245 | } else { 246 | SCHED_NONE; 247 | }; 248 | [@bs.module "cluster"] external worker: Worker.t = "worker"; 249 | [@bs.module "cluster"] external workers: Js.Dict.t(Worker.t) = "workers"; 250 | let getWorker: (Js.Dict.t(Worker.t), int) => option(Worker.t) = 251 | (_workers, id) => Js.Dict.get(_workers, Js.Int.toString(id)); 252 | -------------------------------------------------------------------------------- /src/Console.re: -------------------------------------------------------------------------------- 1 | // We'll only bind to the instance version of console.Console for now: https://nodejs.org/api/console.html 2 | // For global console.log and others, use the existing Js.Console.* provided by BuckleScript out of the box 3 | 4 | type t; 5 | [@bs.val] external console: t = "console"; 6 | 7 | type consoleOptions; 8 | [@bs.obj] 9 | external consoleOptions: 10 | ( 11 | ~stdout: Stream.Writable.subtype('w, 'a), 12 | ~stderr: Stream.Writable.subtype('w, 'a)=?, 13 | ~ignoreErrors: bool=?, 14 | ~colorMode: bool=?, 15 | ~inspectOptions: Util.inspectOptions=?, 16 | unit 17 | ) => 18 | consoleOptions; 19 | 20 | [@bs.new] [@bs.module "console"] 21 | external make: consoleOptions => t = "Console"; 22 | [@bs.new] [@bs.module "console"] 23 | external make2: {.. "stdout": Stream.Writable.subtype('w, 'a)} => t = 24 | "Console"; 25 | 26 | [@bs.send] external assert_: (t, bool) => unit = "assert"; 27 | // TODO: reconsider naming 28 | [@bs.send] external assertWithMessage: (t, bool, string) => unit = "assert"; 29 | [@bs.send] external clear: (t) => unit = "clear"; 30 | [@bs.send] external count: (t, string) => unit = "count"; 31 | [@bs.send] external countReset: (t, string) => unit = "countReset"; 32 | 33 | [@bs.send] external debug: (t, string) => unit = "debug"; 34 | [@bs.send] [@bs.variadic] 35 | external debugMany: (t, array('a)) => unit = "debug"; 36 | 37 | [@bs.send] external dir: (t, 'a) => unit = "dir"; 38 | [@bs.send] [@bs.variadic] external dirMany: (t, array('a)) => unit = "dir"; 39 | 40 | [@bs.send] external dirxml: (t, string) => unit = "dirxml"; 41 | [@bs.send] [@bs.variadic] 42 | external dirxmlMany: (t, array('a)) => unit = "dirxml"; 43 | 44 | [@bs.send] external error: (t, string) => unit = "error"; 45 | [@bs.send] [@bs.variadic] 46 | external errorMany: (t, array('a)) => unit = "error"; 47 | 48 | [@bs.send] external group: (t, string) => unit = "group"; 49 | [@bs.send] [@bs.variadic] 50 | external groupMany: (t, array('a)) => unit = "group"; 51 | 52 | [@bs.send] external groupEnd: (t, unit) => unit = "groupEnd"; 53 | 54 | [@bs.send] external info: (t, string) => unit = "info"; 55 | [@bs.send] [@bs.variadic] external infoMany: (t, array('a)) => unit = "info"; 56 | 57 | [@bs.send] external log: (t, string) => unit = "log"; 58 | [@bs.send] [@bs.variadic] external logMany: (t, array('a)) => unit = "log"; 59 | 60 | [@bs.send] external table: (t, array('a)) => unit = "table"; 61 | 62 | [@bs.send] external time: (t, string) => unit = "time"; 63 | 64 | //TODO: research more into this function. Not sure how it works. 65 | [@bs.send] [@bs.variadic] 66 | external timeLog: (t, string, array('a)) => unit = "timeLog"; 67 | 68 | [@bs.send] external trace: (t, string) => unit = "trace"; 69 | [@bs.send] [@bs.variadic] 70 | external traceMany: (t, array('a)) => unit = "trace"; 71 | 72 | [@bs.send] external warn: (t, string) => unit = "warn"; 73 | [@bs.send] [@bs.variadic] external warnMany: (t, array('a)) => unit = "warn"; 74 | -------------------------------------------------------------------------------- /src/Crypto.re: -------------------------------------------------------------------------------- 1 | /** 2 | * UNDER CONSTRUCTION - API UNSTABLE 3 | */ 4 | // TODO: Consider alternative implementation of KeyObject subtype. 5 | module KeyObject = { 6 | type t('a, 'b); 7 | type symmetric = [ | `Symmetric]; 8 | type asymmetric = [ | `Asymmetric]; 9 | type publicKey = [ | `PublicKey]; 10 | type privateKey = [ | `PrivateKey]; 11 | type secretKey = [ | `SecretKey]; 12 | [@bs.send] 13 | external symmetricExport: 14 | t(symmetric, [< publicKey | privateKey]) => Buffer.t = 15 | "export"; 16 | [@bs.send] 17 | external asymmetricExport: 18 | t(asymmetric, [< publicKey | privateKey | secretKey]) => Buffer.t = 19 | "export"; 20 | module Symmetric = { 21 | type kind = [ symmetric]; 22 | type nonrec t('a) = t([ kind], 'a); 23 | module Impl = {}; 24 | }; 25 | module Asymmetric = { 26 | type kind = [ asymmetric]; 27 | type nonrec t('a) = t([ kind], 'a); 28 | module Impl = {}; 29 | }; 30 | module Impl = { 31 | include Symmetric.Impl; 32 | include Asymmetric.Impl; 33 | }; 34 | include Impl; 35 | }; 36 | 37 | module PivateKey = { 38 | include KeyObject.Impl; 39 | type kind = [ KeyObject.privateKey]; 40 | type t('a) = KeyObject.t('a, [ kind]); 41 | [@bs.module "crypto"] external make: Buffer.t => t('a) = "createPrivateKey"; 42 | [@bs.module "crypto"] 43 | external makeWithPassphrase: 44 | { 45 | .. 46 | "key": Buffer.t, 47 | "passphrase": Buffer.t, 48 | } => 49 | t('a) = 50 | "createPrivateKey"; 51 | }; 52 | 53 | module PublicKey = { 54 | include KeyObject.Impl; 55 | type kind = [ KeyObject.publicKey]; 56 | type t('a) = KeyObject.t('a, [ kind]); 57 | [@bs.module "crypto"] external make: Buffer.t => t('a) = "createPublicKey"; 58 | [@bs.module "crypto"] 59 | external fromPrivateKey: KeyObject.t('a, [> KeyObject.privateKey]) => t('a) = 60 | "createPublicKey"; 61 | }; 62 | 63 | module Hash = { 64 | type kind('w, 'r) = [ Stream.transform('w, 'r) | `Hash]; 65 | type subtype('w, 'r, 'a) = Stream.subtype([> kind('w, 'r)] as 'a); 66 | type supertype('w, 'r, 'a) = Stream.subtype([< kind('w, 'r)] as 'a); 67 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 68 | module Impl = { 69 | include Stream.Transform.Impl; 70 | [@bs.send] external copy: t => t = "copy"; 71 | [@bs.send] external digest: t => Buffer.t = "digest"; 72 | [@bs.send] external update: (t, Buffer.t) => unit = "update"; 73 | }; 74 | include Impl; 75 | }; 76 | 77 | [@bs.module "crypto"] external createHash: string => Hash.t = "createHash"; 78 | 79 | module Hmac = { 80 | type kind('w, 'r) = [ Stream.transform('w, 'r) | `Hmac]; 81 | type subtype('w, 'r, 'a) = Stream.subtype([> kind('w, 'r)] as 'a); 82 | type supertype('w, 'r, 'a) = Stream.subtype([< kind('w, 'r)] as 'a); 83 | type t = subtype(Buffer.t, Buffer.t, kind('w, 'r)); 84 | module Impl = { 85 | include Stream.Transform.Impl; 86 | [@bs.send] external digest: t => Buffer.t = "digest"; 87 | [@bs.send] external update: (t, Buffer.t) => unit = "update"; 88 | }; 89 | include Impl; 90 | }; 91 | 92 | [@bs.module "crypto"] 93 | external createHmac: (string, ~key: string) => Hmac.t = "createHmac"; 94 | 95 | module Certificate = { 96 | type t; 97 | [@bs.send] 98 | external exportChallenge: (t, Buffer.t) => Buffer.t = "exportChallenge"; 99 | [@bs.send] 100 | external exportPublicKey: (t, Buffer.t) => Buffer.t = "exportPublicKey"; 101 | [@bs.send] 102 | external verifyCertificate: (t, Buffer.t) => bool = "verifyCertificate"; 103 | }; 104 | 105 | module Cipher = { 106 | type kind('w, 'r) = [ Stream.transform('w, 'r) | `Cipher]; 107 | type subtype('w, 'r, 'a) = Stream.subtype([> kind('w, 'r)] as 'a); 108 | type supertype('w, 'r, 'a) = Stream.subtype([< kind('w, 'r)] as 'a); 109 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 110 | module Impl = { 111 | include Stream.Transform.Impl; 112 | [@bs.send] external final: (t, string) => Buffer.t = "final"; 113 | [@bs.send] external setAAD: (t, Buffer.t) => t = "setAAD"; 114 | [@bs.send] 115 | external setAADWith: 116 | ( 117 | t, 118 | Buffer.t, 119 | ~options: Stream.Transform.makeOptions(Buffer.t, Buffer.t) 120 | ) => 121 | t = 122 | "setAAD"; 123 | [@bs.send] external getAuthTag: t => Buffer.t = "getAuthTag"; 124 | [@bs.send] external setAutoPadding: (t, bool) => t = "setAutoPadding"; 125 | [@bs.send] external update: (t, Buffer.t) => Buffer.t = "update"; 126 | }; 127 | include Impl; 128 | [@bs.module "crypto"] 129 | external make: 130 | ( 131 | ~algorithm: string, 132 | ~key: KeyObject.t('a, [> KeyObject.secretKey]), 133 | ~iv: Js.Null.t(Buffer.t) 134 | ) => 135 | t = 136 | "createCipheriv"; 137 | [@bs.module "crypto"] 138 | external makeWith: 139 | ( 140 | ~algorithm: string, 141 | ~key: KeyObject.t('a, [> KeyObject.secretKey]), 142 | ~iv: Js.Null.t(Buffer.t), 143 | ~options: Stream.Transform.makeOptions(Buffer.t, Buffer.t)=? 144 | ) => 145 | t = 146 | "createCipheriv"; 147 | }; 148 | 149 | module Decipher = { 150 | type kind('w, 'r) = [ Stream.transform('w, 'r) | `Decipher]; 151 | type subtype('w, 'r, 'a) = Stream.subtype([> kind('w, 'r)] as 'a); 152 | type supertype('w, 'r, 'a) = Stream.subtype([< kind('w, 'r)] as 'a); 153 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 154 | module Impl = { 155 | [@bs.send] 156 | external final: (subtype('w, 'r, 'a), string) => Buffer.t = "final"; 157 | [@bs.send] 158 | external setAAD: (subtype('w, 'r, 'a), Buffer.t) => t = "setAAD"; 159 | [@bs.send] 160 | external setAADWith: 161 | ( 162 | subtype('w, 'r, 'a), 163 | Buffer.t, 164 | ~options: Stream.Transform.makeOptions(Buffer.t, Buffer.t) 165 | ) => 166 | t = 167 | "setAAD"; 168 | [@bs.send] 169 | external setAuthTag: (subtype('w, 'r, 'a), Buffer.t) => t = "setAuthTag"; 170 | [@bs.send] 171 | external setAutoPatting: (subtype('w, 'r, 'a), bool) => t = 172 | "setAutoPadding"; 173 | [@bs.send] 174 | external update: (subtype('w, 'r, 'a), Buffer.t) => Buffer.t = "update"; 175 | }; 176 | include Impl; 177 | [@bs.module "crypto"] 178 | external make: 179 | ( 180 | ~algorithm: string, 181 | ~key: KeyObject.t('a, [> KeyObject.secretKey]), 182 | ~iv: Js.Null.t(Buffer.t) 183 | ) => 184 | t = 185 | "createDecipheriv"; 186 | [@bs.module "crypto"] 187 | external makeWith: 188 | ( 189 | ~algorithm: string, 190 | ~key: KeyObject.t('a, [> KeyObject.secretKey]), 191 | ~iv: Js.Null.t(Buffer.t), 192 | ~options: Stream.Transform.makeOptions(Buffer.t, Buffer.t)=? 193 | ) => 194 | t = 195 | "createDecipheriv"; 196 | } /* }*/ /* }*/ /* module Verify = */; 197 | 198 | // module DiffieHellman = { 199 | 200 | // }; 201 | 202 | // module DiffieHellmanGroup = { 203 | 204 | // }; 205 | 206 | // module Sign = { -------------------------------------------------------------------------------- /src/Dns.re: -------------------------------------------------------------------------------- 1 | type lookupOptions; 2 | [@bs.obj] 3 | external lookupOptions: 4 | (~family: int=?, ~hints: int=?, ~all: bool=?, ~verbatim: bool=?) => 5 | lookupOptions; 6 | [@bs.module "dns"] [@bs.scope "promise"] 7 | external lookup: 8 | string => 9 | Js.Promise.t( 10 | array({ 11 | . 12 | "address": string, 13 | "family": int, 14 | }), 15 | ) = 16 | "lookup"; 17 | [@bs.module "dns"] [@bs.scope "promise"] 18 | external lookupWithOptions: 19 | (string, lookupOptions) => 20 | Js.Promise.t( 21 | array({ 22 | . 23 | "address": string, 24 | "family": int, 25 | }), 26 | ) = 27 | "lookup"; 28 | [@bs.module "dns"] [@bs.scope "promise"] 29 | external lookupService: 30 | (string, int) => 31 | Js.Promise.t({ 32 | . 33 | "hostname": string, 34 | "service": string, 35 | }) = 36 | "lookupService"; 37 | [@bs.module "dns"] [@bs.scope "promise"] 38 | external resolve4: string => Js.Promise.t(array(string)) = "resolve4"; 39 | [@bs.module "dns"] [@bs.scope "promise"] 40 | external resolve4TTL: 41 | (string, [@bs.as {json| {"ttl": true} |json}] _) => 42 | Js.Promise.t(array(string)) = 43 | "resolve4"; 44 | [@bs.module "dns"] [@bs.scope "promise"] 45 | external resolve6: string => Js.Promise.t(array(string)) = "resolve6"; 46 | [@bs.module "dns"] [@bs.scope "promise"] 47 | external resolve6TTL: 48 | (string, [@bs.as {json| {"ttl": true} |json}] _) => 49 | Js.Promise.t(array(string)) = 50 | "resolve6"; 51 | [@bs.module "dns"] [@bs.scope "promise"] 52 | external resolveAny: string => Js.Promise.t(array(Js.t({..}))) = 53 | "resolveAny"; 54 | [@bs.module "dns"] [@bs.scope "promise"] 55 | external resolveCname: string => Js.Promise.t(array(string)) = 56 | "resolveCname"; 57 | [@bs.module "dns"] [@bs.scope "promise"] 58 | external resolveMx: 59 | string => 60 | Js.Promise.t( 61 | array({ 62 | . 63 | "priority": int, 64 | "exchange": string, 65 | }), 66 | ) = 67 | "resolveMx"; 68 | [@bs.module "dns"] [@bs.scope "promise"] 69 | external resolveNaptr: 70 | string => 71 | Js.Promise.t( 72 | array({ 73 | . 74 | "flags": string, 75 | "service": string, 76 | "regexp": string, 77 | "replacement": string, 78 | "order": int, 79 | "preference": int, 80 | }), 81 | ) = 82 | "resolveNaptr"; 83 | [@bs.module "dns"] [@bs.scope "promise"] 84 | external resolveNs: string => Js.Promise.t(array(string)) = "resolveNs"; 85 | [@bs.module "dns"] [@bs.scope "promise"] 86 | external resolvePtr: string => Js.Promise.t(array(string)) = "resolvePtr"; 87 | [@bs.module "dns"] [@bs.scope "promise"] 88 | external resolveSoa: 89 | string => 90 | Js.Promise.t( 91 | array({ 92 | . 93 | "nsname": string, 94 | "hostmaster": string, 95 | "serial": float, 96 | "refresh": int, 97 | "retry": int, 98 | "expire": int, 99 | "minttl": int, 100 | }), 101 | ) = 102 | "resolveSoa"; 103 | 104 | [@bs.module "dns"] [@bs.scope "promise"] 105 | external resolveSrv: 106 | string => 107 | Js.Promise.t( 108 | array({ 109 | . 110 | "priority": int, 111 | "weight": int, 112 | "port": int, 113 | "name": string, 114 | }), 115 | ) = 116 | "resolveSrv"; 117 | [@bs.module "dns"] [@bs.scope "promise"] 118 | external resolveTxt: string => Js.Promise.t(array(array(string))) = 119 | "resolveTxt"; 120 | [@bs.module "dns"] [@bs.scope "promise"] 121 | external reverse: string => Js.Promise.t(array(string)) = "reverse"; 122 | [@bs.module "dns"] [@bs.scope "promise"] 123 | external setServers: array(string) => Js.Promise.t(unit) = "setServers"; 124 | 125 | module CallbackAPI = { 126 | [@bs.module "dns"] 127 | external lookup: (string, (Js.Exn.t, string, int) => unit) => string = 128 | "lookup"; 129 | [@bs.module "dns"] 130 | external lookupWithOptions: 131 | (string, lookupOptions, (Js.Exn.t, string, int) => unit) => string = 132 | "lookup"; 133 | [@bs.module "dns"] 134 | external getServers: unit => array(string) = "getServers"; 135 | [@bs.module "dns"] 136 | external resolveAny: 137 | (string, (Js.Exn.t, array(Js.t({..}))) => unit) => unit = 138 | "resolveAny"; 139 | [@bs.module "dns"] 140 | external resolve4: (string, (Js.Exn.t, array(string)) => unit) => unit = 141 | "resolve4"; 142 | [@bs.module "dns"] 143 | external resolve4TTL: 144 | ( 145 | string, 146 | [@bs.as {json| {"ttl": true} |json}] _, 147 | ( 148 | Js.Exn.t, 149 | array({ 150 | . 151 | "address": string, 152 | "ttl": int, 153 | }) 154 | ) => 155 | unit 156 | ) => 157 | unit = 158 | "resolve4"; 159 | [@bs.module "dns"] 160 | external resolve6: (string, (Js.Exn.t, array(string)) => unit) => unit = 161 | "resolve6"; 162 | [@bs.module "dns"] 163 | external resolve6TTL: 164 | ( 165 | string, 166 | [@bs.as {json| {"ttl": true} |json}] _, 167 | ( 168 | Js.Exn.t, 169 | array({ 170 | . 171 | "address": string, 172 | "ttl": int, 173 | }) 174 | ) => 175 | unit 176 | ) => 177 | unit = 178 | "resolve6"; 179 | [@bs.module "dns"] 180 | external resolveCname: (string, (Js.Exn.t, array(string)) => unit) => unit = 181 | "resolveCname"; 182 | [@bs.module "dns"] 183 | external resolveMx: 184 | ( 185 | string, 186 | ( 187 | Js.Exn.t, 188 | array({ 189 | . 190 | "exchange": string, 191 | "priority": int, 192 | }), 193 | ) 194 | ) => 195 | unit = 196 | "resolveMx"; 197 | [@bs.module "dns"] 198 | external resolveNaptr: 199 | ( 200 | string, 201 | ( 202 | Js.Exn.t, 203 | array({ 204 | . 205 | "flags": string, 206 | "service": string, 207 | "regexp": string, 208 | "replacement": string, 209 | "order": int, 210 | "preference": int, 211 | }) 212 | ) => 213 | unit 214 | ) => 215 | unit = 216 | "resolveNaptr"; 217 | [@bs.module "dns"] 218 | external resolveNs: (string, (Js.Exn.t, array(string))) => unit = 219 | "resolveNs"; 220 | [@bs.module "dns"] 221 | external resolvePtr: (string, (Js.Exn.t, array(string))) => unit = 222 | "resolvePtr"; 223 | [@bs.module "dns"] 224 | external resolveSoa: 225 | ( 226 | string, 227 | ( 228 | Js.Exn.t, 229 | { 230 | . 231 | "nsname": string, 232 | "hostmaster": string, 233 | "serial": float, 234 | "refresh": int, 235 | "retry": int, 236 | "expire": int, 237 | "minttl": int, 238 | } 239 | ) => 240 | unit 241 | ) => 242 | unit = 243 | "resolveSoa"; 244 | [@bs.module "dns"] 245 | external resolveSrv: 246 | ( 247 | string, 248 | ( 249 | Js.Exn.t, 250 | array({ 251 | . 252 | "priority": int, 253 | "weight": int, 254 | "port": int, 255 | "name": string, 256 | }) 257 | ) => 258 | unit 259 | ) => 260 | unit = 261 | "resolveSrv"; 262 | [@bs.module "dns"] 263 | external resolveTxt: (string, (Js.Exn.t, array(array(string)))) => unit = 264 | "resolveTxt"; 265 | [@bs.module "dns"] 266 | external reverse: (string, (Js.Exn.t, array(string)) => unit) => unit = 267 | "reverse"; 268 | [@bs.module "dns"] 269 | external setServers: array(string) => unit = "setServers"; 270 | }; 271 | -------------------------------------------------------------------------------- /src/Errors.re: -------------------------------------------------------------------------------- 1 | [@bs.val] [@bs.scope "Error"] 2 | external captureStackTrace: Js.t({..}) => unit = "captureStackTrace"; 3 | [@bs.val] [@bs.scope "Error"] 4 | external stackTraceLimit: int = "captureStackTrace"; 5 | %bs.raw 6 | {| 7 | function setStackTraceLimit(n) { 8 | Error.stackTraceLimit = n; 9 | return undefined; 10 | } 11 | |}; 12 | [@bs.val] 13 | external setStackTraceLimit: int => Js.Undefined.t('a) = "setStackTraceLimit"; 14 | let setStackTraceLimit: int => unit = n => setStackTraceLimit(n)->ignore; 15 | 16 | module Error = { 17 | type t = exn; 18 | type constructor; 19 | [@bs.val] external constructor: constructor = "Error"; 20 | [@bs.new] external make: string => t = "Error"; 21 | [@bs.get] external name: t => string = "name"; 22 | [@bs.get] external code: t => string = "code"; 23 | [@bs.get] external message: t => string = "message"; 24 | [@bs.get] external stack: t => string = "stack"; 25 | let instanceOf = x => 26 | Internal__JsTypeReflection.instanceOfClass( 27 | ~instance=x, 28 | ~class_=constructor, 29 | ); 30 | let isError: Js.Exn.t => bool = 31 | x => 32 | Internal__JsTypeReflection.constructorName(x) == "Error" 33 | && Internal__JsTypeReflection.instanceOfClass( 34 | ~instance=x, 35 | ~class_=constructor, 36 | ); 37 | external toJsExn: t => Js.Exn.t = "%identity"; 38 | external fromJsExn: Js.Exn.t => t = "%identity"; 39 | let fromJsExn: Js.Exn.t => option(t) = 40 | exn => isError(exn) ? Some(fromJsExn(exn)) : None; 41 | }; 42 | 43 | module AssertionError = { 44 | type t = exn; 45 | type constructor; 46 | type makeOptions; 47 | [@bs.obj] 48 | external makeOptions: 49 | ( 50 | ~message: string=?, 51 | ~actual: 'actual=?, 52 | ~expected: 'expected=?, 53 | ~operator: string=?, 54 | ~stackStartFn: 'a => 'b=?, 55 | unit 56 | ) => 57 | makeOptions; 58 | [@bs.module "assert"] external constructor: constructor = "AssertionError"; 59 | [@bs.module "assert"] [@bs.new] 60 | external make: makeOptions => t = "AssertionError"; 61 | [@bs.get] external actual: t => 'a = "actual"; 62 | [@bs.get] external expected: t => 'a = "expected"; 63 | [@bs.get] external generatedMessage: t => bool = "generatedMessage"; 64 | [@bs.get] external code: t => string = "code"; 65 | [@bs.get] external name: t => string = "name"; 66 | [@bs.get] external message: t => string = "message"; 67 | [@bs.get] external operator: t => string = "operator"; 68 | [@bs.get] external stack: t => string = "stack"; 69 | let instanceOf = x => 70 | Internal__JsTypeReflection.instanceOfClass( 71 | ~instance=x, 72 | ~class_=constructor, 73 | ); 74 | let isAssertionError: Js.Exn.t => bool = 75 | x => 76 | Internal__JsTypeReflection.constructorName(x) == "AssertionError" 77 | && Internal__JsTypeReflection.instanceOfClass( 78 | ~instance=x, 79 | ~class_=constructor, 80 | ); 81 | external toJsExn: t => Js.Exn.t = "%identity"; 82 | external fromJsExn: Js.Exn.t => t = "%identity"; 83 | let fromJsExn: Js.Exn.t => option(t) = 84 | exn => isAssertionError(exn) ? Some(fromJsExn(exn)) : None; 85 | }; 86 | 87 | module EvalError = { 88 | type t = exn; 89 | type constructor; 90 | [@bs.val] external constructor: constructor = "EvalError"; 91 | [@bs.new] external make: string => t = "EvalError"; 92 | [@bs.get] external message: t => string = "message"; 93 | [@bs.get] external name: t => string = "name"; 94 | [@bs.get] external stack: t => string = "stack"; 95 | let instanceOf = x => 96 | Internal__JsTypeReflection.instanceOfClass( 97 | ~instance=x, 98 | ~class_=constructor, 99 | ); 100 | let isEvalError: Js.Exn.t => bool = 101 | x => 102 | Internal__JsTypeReflection.constructorName(x) == "EvalError" 103 | && Internal__JsTypeReflection.instanceOfClass( 104 | ~instance=x, 105 | ~class_=constructor, 106 | ); 107 | external toJsExn: t => Js.Exn.t = "%identity"; 108 | external fromJsExn: Js.Exn.t => t = "%identity"; 109 | let fromJsExn: Js.Exn.t => option(t) = 110 | exn => isEvalError(exn) ? Some(fromJsExn(exn)) : None; 111 | }; 112 | 113 | module RangeError = { 114 | type t = exn; 115 | type constructor; 116 | [@bs.val] external constructor: constructor = "RangeError"; 117 | [@bs.new] external make: string => t = "RangeError"; 118 | [@bs.get] external name: t => string = "name"; 119 | [@bs.get] external code: t => string = "code"; 120 | [@bs.get] external message: t => string = "message"; 121 | [@bs.get] external stack: t => string = "stack"; 122 | let instanceOf = x => 123 | Internal__JsTypeReflection.instanceOfClass( 124 | ~instance=x, 125 | ~class_=constructor, 126 | ); 127 | let isRangeError: Js.Exn.t => bool = 128 | x => 129 | Internal__JsTypeReflection.constructorName(x) == "RangeError" 130 | && Internal__JsTypeReflection.instanceOfClass( 131 | ~instance=x, 132 | ~class_=constructor, 133 | ); 134 | external toJsExn: t => Js.Exn.t = "%identity"; 135 | external fromJsExn: Js.Exn.t => t = "%identity"; 136 | let fromJsExn: Js.Exn.t => option(t) = 137 | exn => isRangeError(exn) ? Some(fromJsExn(exn)) : None; 138 | }; 139 | 140 | module ReferenceError = { 141 | type t = exn; 142 | type constructor; 143 | [@bs.val] external constructor: constructor = "ReferenceError"; 144 | [@bs.new] external make: string => t = "ReferenceError"; 145 | [@bs.get] external name: t => string = "name"; 146 | [@bs.get] external code: t => string = "code"; 147 | [@bs.get] external message: t => string = "message"; 148 | [@bs.get] external stack: t => string = "stack"; 149 | let instanceOf = x => 150 | Internal__JsTypeReflection.instanceOfClass( 151 | ~instance=x, 152 | ~class_=constructor, 153 | ); 154 | let isReferenceError: Js.Exn.t => bool = 155 | x => 156 | Internal__JsTypeReflection.constructorName(x) == "ReferenceError" 157 | && Internal__JsTypeReflection.instanceOfClass( 158 | ~instance=x, 159 | ~class_=constructor, 160 | ); 161 | external toJsExn: t => Js.Exn.t = "%identity"; 162 | external fromJsExn: Js.Exn.t => t = "%identity"; 163 | let fromJsExn: Js.Exn.t => option(t) = 164 | exn => isReferenceError(exn) ? Some(fromJsExn(exn)) : None; 165 | }; 166 | 167 | module SyntaxError = { 168 | type t = exn; 169 | type constructor; 170 | [@bs.val] external constructor: constructor = "SyntaxError"; 171 | [@bs.new] external make: string => t = "SyntaxError"; 172 | [@bs.get] external name: t => string = "name"; 173 | [@bs.get] external code: t => string = "code"; 174 | [@bs.get] external message: t => string = "message"; 175 | [@bs.get] external stack: t => string = "stack"; 176 | let instanceOf = x => 177 | Internal__JsTypeReflection.instanceOfClass( 178 | ~instance=x, 179 | ~class_=constructor, 180 | ); 181 | let isSyntaxError: Js.Exn.t => bool = 182 | x => 183 | Internal__JsTypeReflection.constructorName(x) == "SyntaxError" 184 | && Internal__JsTypeReflection.instanceOfClass( 185 | ~instance=x, 186 | ~class_=constructor, 187 | ); 188 | external toJsExn: t => Js.Exn.t = "%identity"; 189 | external fromJsExn: Js.Exn.t => t = "%identity"; 190 | let fromJsExn: Js.Exn.t => option(t) = 191 | exn => isSyntaxError(exn) ? Some(fromJsExn(exn)) : None; 192 | }; 193 | 194 | // It's not clear that SystemError works as expressed in the Node API. 195 | // `SystemError` is an undefined identifier at runtime. 196 | 197 | module SystemError = { 198 | type t = exn; 199 | [@bs.get] external name: t => string = "name"; 200 | [@bs.get] [@bs.return nullable] 201 | external address: t => option(string) = "address"; 202 | [@bs.get] external code: t => string = "code"; 203 | [@bs.get] [@bs.return nullable] external dest: t => option(string) = "dest"; 204 | [@bs.get] external errno: t => int = "errno"; 205 | [@bs.get] [@bs.return nullable] 206 | external info: t => option(Js.t({..})) = "info"; 207 | [@bs.get] external message: t => string = "message"; 208 | [@bs.get] [@bs.return nullable] external path: t => option(string) = "path"; 209 | [@bs.get] [@bs.return nullable] external port: t => option(int) = "port"; 210 | [@bs.get] [@bs.return nullable] 211 | external stack: t => option(string) = "stack"; 212 | [@bs.get] external syscall: t => string = "syscall"; 213 | }; 214 | 215 | module TypeError = { 216 | type t = exn; 217 | type constructor; 218 | [@bs.val] external constructor: constructor = "TypeError"; 219 | [@bs.new] external make: string => t = "TypeError"; 220 | [@bs.get] external name: t => string = "name"; 221 | [@bs.get] external code: t => string = "code"; 222 | [@bs.get] external message: t => string = "message"; 223 | [@bs.get] external stack: t => string = "stack"; 224 | external toJsExn: t => Js.Exn.t = "%identity"; 225 | let instanceOf = x => 226 | Internal__JsTypeReflection.instanceOfClass( 227 | ~instance=x, 228 | ~class_=constructor, 229 | ); 230 | let isTypeError: Js.Exn.t => bool = 231 | x => 232 | Internal__JsTypeReflection.constructorName(x) == "TypeError" 233 | && Internal__JsTypeReflection.instanceOfClass( 234 | ~instance=x, 235 | ~class_=constructor, 236 | ); 237 | external fromJsExn: Js.Exn.t => t = "%identity"; 238 | let fromJsExn: Js.Exn.t => option(t) = 239 | exn => isTypeError(exn) ? Some(fromJsExn(exn)) : None; 240 | }; 241 | 242 | module URIError = { 243 | type t = exn; 244 | type constructor; 245 | [@bs.val] external constructor: constructor = "URIError"; 246 | [@bs.new] external make: string => t = "URIError"; 247 | [@bs.get] external message: t => string = "message"; 248 | [@bs.get] external name: t => string = "name"; 249 | [@bs.get] external stack: t => string = "stack"; 250 | let instanceOf = x => 251 | Internal__JsTypeReflection.instanceOfClass( 252 | ~instance=x, 253 | ~class_=constructor, 254 | ); 255 | let isURIError: Js.Exn.t => bool = 256 | x => 257 | Internal__JsTypeReflection.constructorName(x) == "URIError" 258 | && Internal__JsTypeReflection.instanceOfClass( 259 | ~instance=x, 260 | ~class_=constructor, 261 | ); 262 | external toJsExn: t => Js.Exn.t = "%identity"; 263 | external fromJsExn: Js.Exn.t => t = "%identity"; 264 | let fromJsExn: Js.Exn.t => option(t) = 265 | exn => isURIError(exn) ? Some(fromJsExn(exn)) : None; 266 | }; 267 | 268 | type case = 269 | | Error(Error.t) 270 | | AssertionError(AssertionError.t) 271 | | EvalError(EvalError.t) 272 | | RangeError(RangeError.t) 273 | | ReferenceError(ReferenceError.t) 274 | | SyntaxError(SyntaxError.t) 275 | | TypeError(TypeError.t) 276 | | URIError(URIError.t); 277 | 278 | let classifyOpt: Js.Exn.t => option(case) = 279 | value => 280 | if (AssertionError.isAssertionError(value)) { 281 | Some(AssertionError(Obj.magic(value))); 282 | } else if (EvalError.isEvalError(value)) { 283 | Some(EvalError(Obj.magic(value))); 284 | } else if (RangeError.isRangeError(value)) { 285 | Some(RangeError(Obj.magic(value))); 286 | } else if (ReferenceError.isReferenceError(value)) { 287 | Some(ReferenceError(Obj.magic(value))); 288 | } else if (SyntaxError.isSyntaxError(value)) { 289 | Some(SyntaxError(Obj.magic(value))); 290 | } else if (TypeError.isTypeError(value)) { 291 | Some(TypeError(Obj.magic(value))); 292 | } else if (URIError.isURIError(value)) { 293 | Some(URIError(Obj.magic(value))); 294 | } else if (Error.isError(value)) { 295 | Some(Error(Obj.magic(value))); 296 | } else { 297 | None; 298 | }; 299 | 300 | let classifyExn: Js.Exn.t => case = 301 | value => 302 | switch (classifyOpt(value)) { 303 | | None => failwith("Unknown data type") 304 | | Some(err) => err 305 | }; 306 | 307 | let classify: Js.Exn.t => Belt.Result.t(case, 'a) = 308 | value => 309 | switch (classifyOpt(value)) { 310 | | None => Error(value) 311 | | Some(err) => Ok(err) 312 | }; 313 | 314 | module ErrorCodes = {}; 315 | -------------------------------------------------------------------------------- /src/Event.re: -------------------------------------------------------------------------------- 1 | /** 2 | * The `Event` type represents the strings/symbols used in Node to 3 | * identify event types for `EventEmitter` and its subclasses, including 4 | * streams, sockets, and servers. 5 | * 6 | * Given a type signature `Event.t('a => 'b, 'ty)`, the first type 7 | * variable, `'a => 'b`, denotes the type signature of the event listener 8 | * function, and `'ty` denotes the type of the associated `EventEmitter`. 9 | * 10 | * These abstract `Event.t` types must be passed to `EventEmitter` 11 | * functions to register event listeners or emit events. By encoding the 12 | * listener function type in a type variable, we can ensure that each 13 | * listener has the correct type. The type parameter for the emitter 14 | * prevents two different emitters from using each other's events. 15 | * 16 | * While this gives us some degree of type safety, it is still possible 17 | * to introduce runtime errors with this API. In particular, two or more 18 | * `Event.t` types can be defined from the same string/symbol, but with 19 | * different listener types. Therefore, we strongly recommend using 20 | * 100% unique strings/symbols to define events. 21 | * 22 | */ 23 | type t('listener, 'ty); 24 | external fromString: string => t('a => 'b, 'ty) = "%identity"; 25 | external fromSymbol: Js.Types.symbol => t('a => 'b, 'ty) = "%identity"; 26 | external unsafeToString: t('a => 'b, 'ty) => string = "%identity"; 27 | external unsafeToSymbol: t('a => 'b, 'ty) => Js.Types.symbol = "%identity"; 28 | type case = 29 | | String(string) 30 | | Symbol(Js.Types.symbol) 31 | | Unknown; 32 | let classify = evt => { 33 | switch (Js.typeof(evt)) { 34 | | "string" => String(unsafeToString(evt)) 35 | | "symbol" => Symbol(unsafeToSymbol(evt)) 36 | | _ => Unknown 37 | }; 38 | }; 39 | let eq = (event1, event2) => { 40 | switch (Js.typeof(event1), Js.typeof(event2)) { 41 | | ("string", "string") => Obj.magic(event1) === Obj.magic(event2) 42 | | ("symbol", "symbol") => Obj.magic(event1) === Obj.magic(event2) 43 | | _ => false 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /src/EventEmitter.re: -------------------------------------------------------------------------------- 1 | /** 2 | * `Impl` is a functor which generates FFI bindings to Node's `EventEmitter` 3 | * class for any type `t`. This is not inherently type-safe. Type-safety can 4 | * be achieved by implementing the known `Event.t('a => 'b, t)` types 5 | */ 6 | module Impl = (T: {type t;}) => { 7 | /** 8 | * `addListener(emitter, event, listener)` 9 | * 10 | * Adds a new event listener function to the event emitter. 11 | */ 12 | [@bs.send] 13 | external addListener: (T.t, Event.t('a => 'b, T.t), 'a => 'b) => T.t = 14 | "addListener"; 15 | 16 | [@bs.send] 17 | external emit: (T.t, Event.t('a => 'b, T.t), 'a) => bool = "emit"; 18 | 19 | [@bs.get] external errorMonitor: T.t => Js.Types.symbol = "errorMonitor"; 20 | 21 | [@bs.send] 22 | external eventNames: 23 | (T.t, Event.t('a => 'b, T.t)) => array(Event.t('a => 'b, T.t)) = 24 | "eventNames"; 25 | 26 | [@bs.send] external getMaxListeners: T.t => int = "getMaxListeners"; 27 | 28 | [@bs.send] 29 | external listenerCount: (T.t, Event.t('a => 'b, T.t)) => int = 30 | "listenerCount"; 31 | [@bs.send] 32 | external listeners: (T.t, Event.t('a => 'b, T.t)) => array('a => 'b) = 33 | "listeners"; 34 | 35 | /** 36 | * `on(emitter, event, listener)` 37 | * 38 | * Adds a new event listener function to the event emitter. 39 | * Alias for `addListener`. 40 | */ 41 | [@bs.send] 42 | external on: (T.t, Event.t('a => 'b, T.t), 'a => 'b) => T.t = "on"; 43 | 44 | /** 45 | * `once(emitter, event, listener)` 46 | * 47 | * Adds a new **single-use** event listener function to the event 48 | * emitter. Then next time the given event is emitted, this listener 49 | * will fire exactly once, and then be removed from the emitter's 50 | * internal listener array. 51 | */ 52 | [@bs.send] 53 | external once: (T.t, Event.t('a => 'b, T.t), 'a => 'b) => T.t = "once"; 54 | 55 | /** 56 | * `off(emitter, event, listener)` 57 | * 58 | * Removes the listener function from the event emitter. 59 | * 60 | * The specified listener function is compared by **referential 61 | * equality** to each function in the emitter's internal listener 62 | * array. 63 | * 64 | * This means that, when the target listener is initially added, that 65 | * exact function reference must be maintained and provided here 66 | * in order to ensure removal. 67 | * 68 | * Alias for `removeListener`. 69 | */ 70 | [@bs.send] 71 | external off: (T.t, Event.t('a => 'b, T.t), 'a => 'b) => T.t = "off"; 72 | 73 | /** 74 | * `prependListener(emitter, event, listener)` 75 | * 76 | * Adds a new event listener function to the event emitter. 77 | * 78 | * Unlike `on` and `addListener`, `prependListener` adds the listener 79 | * function to the front of the internal listener array, ensuring 80 | * that this function is called before the rest of the listeners for 81 | * the given event. 82 | */ 83 | [@bs.send] 84 | external prependListener: (T.t, Event.t('a => 'b, T.t), 'a => 'b) => T.t = 85 | "prependListener"; 86 | 87 | /** 88 | * `prependListenerOnce(emitter, event, listener)` 89 | * 90 | * Adds a new **single-use** event listener function to the event 91 | * emitter. Then next time the given event is emitted, this listener 92 | * will fire exactly once, and then be removed from the emitter's 93 | * internal listener array. 94 | * 95 | * Unlike `once`, `prependListenerOnce` adds the listener function 96 | * to the front of the internal listener array, ensuring that this 97 | * function is called before the rest of the listeners for the 98 | * given event. 99 | */ 100 | [@bs.send] 101 | external prependOnceListener: (T.t, Event.t('a => 'b, T.t), 'a => 'b) => T.t = 102 | "prependOnceListener"; 103 | 104 | [@bs.send] external removeAllListeners: T.t => T.t = "removeAllListeners"; 105 | 106 | /** 107 | * `removeListener(emitter, event, listener)` 108 | * 109 | * Removes the listener function from the event emitter. 110 | * 111 | * The specified listener function is compared by **referential 112 | * equality** to each function in the emitter's internal listener 113 | * array. 114 | * 115 | * This means that, when the target listener is initially added, that 116 | * exact function reference must be maintained and provided here 117 | * in order to ensure removal. 118 | */ 119 | [@bs.send] 120 | external removeListener: (T.t, Event.t('a => 'b, T.t), 'a => 'b) => T.t = 121 | "removeListener"; 122 | 123 | /** 124 | * `setMaxListeners(emitter, numberOfListeners)` 125 | * 126 | * Sets the maximum number of event listeners that may be added to 127 | * an event emitter before Node begins emitting warnings. 128 | * 129 | * By default, each event emitter has this value set to 10. This is 130 | * intended to warn the user about possible memory leaks. 131 | * `setMaxListeners` will increase this threshold. 132 | */ 133 | [@bs.send] 134 | external setMaxListeners: (T.t, int) => T.t = "setMaxListeners"; 135 | }; 136 | 137 | /** 138 | * A generative functor that creates a unique type `t` with the `EventEmitter` 139 | * interface bindings. 140 | */ 141 | module Make = (()) => { 142 | type t; 143 | include Impl({ 144 | type nonrec t = t; 145 | }); 146 | [@bs.module "events"] [@bs.new] external make: unit => t = "EventEmitter"; 147 | }; -------------------------------------------------------------------------------- /src/Fs.re: -------------------------------------------------------------------------------- 1 | module Dirent = { 2 | type t; 3 | [@bs.send] external isBlockDevice: t => bool = "isBlockDevice"; 4 | [@bs.send] external isCharacterDevice: t => bool = "isCharacterDevice"; 5 | [@bs.send] external isDirectory: t => bool = "isDirectory"; 6 | [@bs.send] external isFIFO: t => bool = "isFIFO"; 7 | [@bs.send] external isFile: t => bool = "isFile"; 8 | [@bs.send] external isSocket: t => bool = "isSocket"; 9 | [@bs.send] external isSymbolicLink: t => bool = "isSymbolicLink"; 10 | [@bs.get] external name: t => string = "name"; 11 | }; 12 | 13 | module Dir = { 14 | type t; 15 | [@bs.send] external close: t => Js.Promise.t(unit) = "close"; 16 | [@bs.send] 17 | external closeWithCallback: (t, Js.nullable(Js.Exn.t) => unit) => unit = 18 | "close"; 19 | [@bs.send] external closeSync: t => unit = "closeSync"; 20 | [@bs.get] external path: t => string = "path"; 21 | [@bs.send] 22 | external read: t => Js.Promise.t(Js.nullable(Dirent.t)) = "read"; 23 | [@bs.send] 24 | external readWithCallback: 25 | (t, (Js.Exn.t, Js.nullable(Dirent.t)) => unit) => unit = 26 | "read"; 27 | [@bs.send] external readSync: t => Js.nullable(Dirent.t) = "readSync"; 28 | }; 29 | 30 | module Stats = { 31 | type t = { 32 | dev: int, 33 | ino: int, 34 | mode: int, 35 | nlink: int, 36 | uid: int, 37 | gid: int, 38 | rdev: int, 39 | size: int, 40 | blksize: int, 41 | blocks: int, 42 | atimeMs: float, 43 | mtimeMs: float, 44 | ctimeMs: float, 45 | birthtimeMs: float, 46 | atime: string, 47 | mtime: string, 48 | ctime: string, 49 | birthtime: string, 50 | }; 51 | 52 | /** `isFile(stats)` Returns true if the `stats` object describes a file. */ 53 | [@bs.send] 54 | external isFile: t => bool = "isFile"; 55 | /** `isDirectory(stats)` Returns true if the `stats` object describes a directory. */ 56 | [@bs.send] 57 | external isDirectory: t => bool = "isDirectory"; 58 | /** `isBlockDevice(stats)` Returns true if the `stats` object describes a block device. */ 59 | [@bs.send] 60 | external isBlockDevice: t => bool = "isBlockDevice"; 61 | /** `isBlockDevice(stats)` Returns true if the `stats` object describes a character device. */ 62 | [@bs.send] 63 | external isCharacterDevice: t => bool = "isCharacterDevice"; 64 | /** `isBlockDevice(stats)` Returns true if the `stats` object describes a symbolic link. */ 65 | [@bs.send] 66 | external isSymbolicLink: t => bool = "isSymbolicLink"; 67 | /** `isBlockDevice(stats)` Returns true if the `stats` object describes a first-in-first-out (FIFO) pipe. */ 68 | [@bs.send] 69 | external isFIFO: t => bool = "isFIFO"; 70 | /** `isBlockDevice(stats)` Returns true if the `stats` object describes a socket. */ 71 | [@bs.send] 72 | external isSocket: t => bool = "isSocket"; 73 | }; 74 | 75 | module Constants = { 76 | type t = pri int; 77 | 78 | /** Bitwise 'or' i.e. JavaScript [x | y] */ 79 | external (lor): (t, t) => t = "%orint"; 80 | 81 | [@text "{1 File Access Constants}"]; 82 | 83 | [@bs.module "fs"] [@bs.scope "constants"] external f_ok: t = "F_OK"; 84 | [@bs.module "fs"] [@bs.scope "constants"] external w_ok: t = "W_OK"; 85 | [@bs.module "fs"] [@bs.scope "constants"] external r_ok: t = "R_OK"; 86 | [@bs.module "fs"] [@bs.scope "constants"] external x_ok: t = "X_OK"; 87 | 88 | [@text "{1 File Copy Constants}"]; 89 | 90 | [@bs.module "fs"] [@bs.scope "constants"] external copyfile_excl: t = "COPYFILE_EXCL"; 91 | [@bs.module "fs"] [@bs.scope "constants"] external copyfile_ficlone: t = "COPYFILE_FICLONE"; 92 | [@bs.module "fs"] [@bs.scope "constants"] external copyfile_ficlone_force: t = "COPYFILE_FICLONE_FORCE"; 93 | 94 | [@text "{1 File Open Constants}"]; 95 | 96 | [@bs.module "fs"] [@bs.scope "constants"] external o_rdonly: t = "O_RDONLY"; 97 | [@bs.module "fs"] [@bs.scope "constants"] external o_wronly: t = "O_WRONLY"; 98 | [@bs.module "fs"] [@bs.scope "constants"] external o_rdwr: t = "O_RDWR"; 99 | [@bs.module "fs"] [@bs.scope "constants"] external o_creat: t = "O_CREAT"; 100 | [@bs.module "fs"] [@bs.scope "constants"] external o_excl: t = "O_EXCL"; 101 | [@bs.module "fs"] [@bs.scope "constants"] external o_noctty: t = "O_NOCTTY"; 102 | [@bs.module "fs"] [@bs.scope "constants"] external o_trunc: t = "O_TRUNC"; 103 | [@bs.module "fs"] [@bs.scope "constants"] external o_append: t = "O_APPEND"; 104 | [@bs.module "fs"] [@bs.scope "constants"] external o_directory: t = "O_DIRECTORY"; 105 | [@bs.module "fs"] [@bs.scope "constants"] external o_noatime: t = "O_NOATIME"; 106 | [@bs.module "fs"] [@bs.scope "constants"] external o_nofollow: t = "O_NOFOLLOW"; 107 | [@bs.module "fs"] [@bs.scope "constants"] external o_sync: t = "O_SYNC"; 108 | [@bs.module "fs"] [@bs.scope "constants"] external o_dsync: t = "O_DSYNC"; 109 | [@bs.module "fs"] [@bs.scope "constants"] external o_symlink: t = "O_SYMLINK"; 110 | [@bs.module "fs"] [@bs.scope "constants"] external o_direct: t = "O_DIRECT"; 111 | [@bs.module "fs"] [@bs.scope "constants"] external o_nonblock: t = "O_NONBLOCK"; 112 | 113 | [@text "{1 File Type Constants}"]; 114 | 115 | [@bs.module "fs"] [@bs.scope "constants"] external s_ifmt: t = "S_IFMT"; 116 | [@bs.module "fs"] [@bs.scope "constants"] external s_ifreg: t = "S_IFREG"; 117 | [@bs.module "fs"] [@bs.scope "constants"] external s_ifdir: t = "S_IFDIR"; 118 | [@bs.module "fs"] [@bs.scope "constants"] external s_ifchr: t = "S_IFCHR"; 119 | [@bs.module "fs"] [@bs.scope "constants"] external s_ifblk: t = "S_IFBLK"; 120 | [@bs.module "fs"] [@bs.scope "constants"] external s_ififo: t = "S_IFIFO"; 121 | [@bs.module "fs"] [@bs.scope "constants"] external s_iflnk: t = "S_IFLNK"; 122 | [@bs.module "fs"] [@bs.scope "constants"] external s_ifsock: t = "S_IFSOCK"; 123 | 124 | [@text "{1 File Mode Constants}"]; 125 | 126 | [@bs.module "fs"] [@bs.scope "constants"] external s_irwxu: t = "S_IRWXU"; 127 | [@bs.module "fs"] [@bs.scope "constants"] external s_irusr: t = "S_IRUSR"; 128 | [@bs.module "fs"] [@bs.scope "constants"] external s_iwusr: t = "S_IWUSR"; 129 | [@bs.module "fs"] [@bs.scope "constants"] external s_ixusr: t = "S_IXUSR"; 130 | [@bs.module "fs"] [@bs.scope "constants"] external s_irwxg: t = "S_IRWXG"; 131 | [@bs.module "fs"] [@bs.scope "constants"] external s_irgrp: t = "S_IRGRP"; 132 | [@bs.module "fs"] [@bs.scope "constants"] external s_iwgrp: t = "S_IWGRP"; 133 | [@bs.module "fs"] [@bs.scope "constants"] external s_ixgrp: t = "S_IXGRP"; 134 | [@bs.module "fs"] [@bs.scope "constants"] external s_irwxo: t = "S_IRWXO"; 135 | [@bs.module "fs"] [@bs.scope "constants"] external s_iroth: t = "S_IROTH"; 136 | [@bs.module "fs"] [@bs.scope "constants"] external s_iwoth: t = "S_IWOTH"; 137 | [@bs.module "fs"] [@bs.scope "constants"] external s_ixoth: t = "S_IXOTH"; 138 | }; 139 | 140 | module Flag: { 141 | type t = pri string; 142 | 143 | [@bs.inline "r"] 144 | let read: t; 145 | [@bs.inline "r+"] 146 | let readWrite: t; 147 | [@bs.inline "rs+"] 148 | let readWriteSync: t; 149 | [@bs.inline "w"] 150 | let write: t; 151 | [@bs.inline "wx"] 152 | let writeFailIfExists: t; 153 | [@bs.inline "w+"] 154 | let writeRead: t; 155 | [@bs.inline "wx+"] 156 | let writeReadFailIfExists: t; 157 | [@bs.inline "a"] 158 | let append: t; 159 | [@bs.inline "ax"] 160 | let appendFailIfExists: t; 161 | [@bs.inline "a+"] 162 | let appendRead: t; 163 | [@bs.inline "ax+"] 164 | let appendReadFailIfExists: t; 165 | } = { 166 | type t = string; 167 | [@bs.inline "r"] 168 | let read = "r"; 169 | [@bs.inline "r+"] 170 | let readWrite = "r+"; 171 | [@bs.inline "rs+"] 172 | let readWriteSync = "rs+"; 173 | [@bs.inline "w"] 174 | let write = "w"; 175 | [@bs.inline "wx"] 176 | let writeFailIfExists = "wx"; 177 | [@bs.inline "w+"] 178 | let writeRead = "w+"; 179 | [@bs.inline "wx+"] 180 | let writeReadFailIfExists = "wx+"; 181 | [@bs.inline "a"] 182 | let append = "a"; 183 | [@bs.inline "ax"] 184 | let appendFailIfExists = "ax"; 185 | [@bs.inline "a+"] 186 | let appendRead = "a+"; 187 | [@bs.inline "ax+"] 188 | let appendReadFailIfExists = "ax+"; 189 | }; 190 | 191 | type fd = pri int; 192 | 193 | type writeFileOptions; 194 | [@bs.obj] 195 | external writeFileOptions: 196 | (~mode: int=?, ~flag: string=?, unit) => writeFileOptions; 197 | 198 | type appendFileOptions; 199 | [@bs.obj] 200 | external appendFileOptions: 201 | (~mode: int=?, ~flag: Flag.t=?, unit) => appendFileOptions; 202 | 203 | type readFileOptions; 204 | [@bs.obj] external readFileOptions: (~flag: Flag.t=?, unit) => readFileOptions; 205 | 206 | /** 207 | * `readdirSync(path)` 208 | * Reads the contents of a directory, returning an array of strings representing 209 | * the paths of files and sub-directories. **Execution is synchronous and blocking**. 210 | */ 211 | [@bs.module "fs"] 212 | external readdirSync: string => array(string) = "readdirSync"; 213 | 214 | /** 215 | * `renameSync(~oldPath, ~newPath) 216 | * Renames/moves the file located at `~oldPath` to `~newPath`. **Execution is 217 | * synchronous and blocking**. 218 | */ 219 | [@bs.module "fs"] 220 | external renameSync: (~from: string, ~to_: string) => unit = "renameSync"; 221 | [@bs.module "fs"] external ftruncateSync: (fd, int) => unit = "ftruncateSync"; 222 | [@bs.module "fs"] 223 | external truncateSync: (string, int) => unit = "truncateSync"; 224 | [@bs.module "fs"] 225 | external chownSync: (string, ~uid: int, ~gid: int) => unit = "chownSync"; 226 | [@bs.module "fs"] 227 | external fchownSync: (fd, ~uid: int, ~gid: int) => unit = "fchownSync"; 228 | [@bs.module "fs"] external readlinkSync: string => string = "readlinkSync"; 229 | [@bs.module "fs"] external unlinkSync: string => unit = "unlinkSync"; 230 | 231 | /** 232 | * `rmdirSync(dirPath) 233 | * **Note: (recursive removal is experimental).** 234 | * Removes the directory at `dirPath`. **Execution is synchronous and blocking**. 235 | */ 236 | [@bs.module "fs"] 237 | external rmdirSync: string => unit = "rmdirSync"; 238 | 239 | [@bs.module "fs"] external openSync: string => fd = "openSync"; 240 | [@bs.module "fs"] 241 | external openSyncWith: (string, ~flag: Flag.t=?, ~mode: int=?) => fd = 242 | "openSync"; 243 | 244 | [@bs.module "fs"] 245 | external readFileSync: (string, ~options: readFileOptions=?, unit) => Buffer.t = 246 | "readFileSync"; 247 | [@bs.module "fs"] external existsSync: string => bool = "existsSync"; 248 | 249 | type writeFileSyncOptions; 250 | [@bs.obj] 251 | external writeFileSyncOptions: 252 | (~mode: int=?, ~flag: Flag.t=?, unit) => writeFileSyncOptions; 253 | 254 | [@bs.val] [@bs.module "fs"] 255 | external writeFileSync: (string, Buffer.t) => unit = "writeFileSync"; 256 | [@bs.val] [@bs.module "fs"] 257 | external writeFileSyncWith: (string, Buffer.t, writeFileSyncOptions) => unit = 258 | "writeFileSync"; 259 | 260 | module FileHandle = { 261 | type t; 262 | 263 | [@bs.send] 264 | external appendFile: (t, Buffer.t, appendFileOptions) => Js.Promise.t(unit) = 265 | "appendFile"; 266 | [@bs.send] 267 | external appendFileWith: (t, Buffer.t) => Js.Promise.t(unit) = "appendFile"; 268 | [@bs.send] external chmod: (t, int) => Js.Promise.t(unit) = "chmod"; 269 | [@bs.send] external chown: (t, int, int) => Js.Promise.t(unit) = "chown"; 270 | [@bs.send] external close: t => Js.Promise.t(unit) = "close"; 271 | [@bs.send] external datasync: t => Js.Promise.t(unit) = "datasync"; 272 | [@bs.get] external fd: t => fd = "fd"; 273 | 274 | type readInfo = { 275 | bytesRead: int, 276 | buffer: Buffer.t, 277 | }; 278 | 279 | [@bs.send] 280 | external read: 281 | (t, Buffer.t, ~offset: int, ~length: int, ~position: int) => 282 | Js.Promise.t(readInfo) = 283 | "read"; 284 | [@bs.send] external readFile: t => Js.Promise.t(Buffer.t) = "readFile"; 285 | [@bs.send] 286 | external readFileWith: (t, ~encoding: string) => Js.Promise.t(string) = 287 | "readFile"; 288 | 289 | [@bs.send] external stat: t => Js.Promise.t(Stats.t) = "stat"; 290 | [@bs.send] external sync: t => Js.Promise.t(unit) = "sync"; 291 | [@bs.send] 292 | external truncate: (t, ~length: int=?, unit) => Js.Promise.t(unit) = 293 | "truncate"; 294 | 295 | type writeInfo = {bytesWritten: int}; 296 | 297 | [@bs.send] 298 | external write: (t, Buffer.t) => Js.Promise.t(writeInfo) = "write"; 299 | [@bs.send] 300 | external writeOffset: (t, Buffer.t, ~offset: int) => Js.Promise.t(writeInfo) = 301 | "write"; 302 | [@bs.send] 303 | external writeRange: 304 | (t, Buffer.t, ~offset: int, ~length: int, ~position: int) => 305 | Js.Promise.t(writeInfo) = 306 | "write"; 307 | 308 | type writeFileOptions; 309 | [@bs.obj] 310 | external writeFileOptions: 311 | (~mode: int=?, ~flag: Flag.t=?, unit) => writeFileOptions; 312 | 313 | [@bs.send] 314 | external writeFile: (t, Buffer.t) => Js.Promise.t(unit) = "writeFile"; 315 | [@bs.send] 316 | external writeFileWith: 317 | (t, Buffer.t, writeFileOptions) => Js.Promise.t(unit) = 318 | "writeFile"; 319 | }; 320 | 321 | [@bs.module "fs"] [@bs.scope "promises"] 322 | external access: string => Js.Promise.t(unit) = "access"; 323 | [@bs.module "fs"] [@bs.scope "promises"] 324 | external accessWithMode: (string, ~mode: int) => Js.Promise.t(unit) = 325 | "access"; 326 | 327 | [@bs.module "fs"] [@bs.scope "promises"] 328 | external appendFile: (string, string, appendFileOptions) => Js.Promise.t(unit) = 329 | "appendFile"; 330 | 331 | [@bs.module "fs"] [@bs.scope "promises"] 332 | external appendFileWith: 333 | (string, string, appendFileOptions) => Js.Promise.t(unit) = 334 | "appendFile"; 335 | 336 | type appendFileBufferOptions; 337 | [@bs.obj] 338 | external appendFileBufferOptions: 339 | (~mode: int=?, ~flag: Flag.t=?, unit) => appendFileBufferOptions; 340 | 341 | [@bs.module "fs"] [@bs.scope "promises"] 342 | external appendFileBuffer: (string, Buffer.t) => Js.Promise.t(unit) = 343 | "appendFile"; 344 | 345 | [@bs.module "fs"] [@bs.scope "promises"] 346 | external appendFileBufferWith: 347 | (string, Buffer.t, appendFileBufferOptions) => Js.Promise.t(unit) = 348 | "appendFile"; 349 | 350 | [@bs.module "fs"] [@bs.scope "promises"] 351 | external chmod: (string, ~mode: int) => Js.Promise.t(unit) = "chmod"; 352 | 353 | [@bs.module "fs"] [@bs.scope "promises"] 354 | external chown: (string, ~uid: int, ~gid: int) => Js.Promise.t(unit) = 355 | "chown"; 356 | 357 | [@bs.module "fs"] [@bs.scope "promises"] 358 | external copyFile: (string, ~dest: string) => Js.Promise.t(unit) = "copyFile"; 359 | 360 | [@bs.module "fs"] [@bs.scope "promises"] 361 | external copyFileFlag: 362 | (string, ~dest: string, ~flags: Constants.t) => Js.Promise.t(unit) = 363 | "copyFile"; 364 | 365 | [@bs.module "fs"] [@bs.scope "promises"] 366 | external lchmod: (string, ~mode: int) => Js.Promise.t(unit) = "lchmod"; 367 | 368 | [@bs.module "fs"] [@bs.scope "promises"] 369 | external link: (~existingPath: string, ~newPath: string) => Js.Promise.t(unit) = 370 | "link"; 371 | 372 | [@bs.module "fs"] [@bs.scope "promises"] 373 | external lstat: string => Js.Promise.t(Stats.t) = "lstat"; 374 | 375 | [@bs.module "fs"] [@bs.scope "promises"] 376 | external lstatBigInt: (string, bool) => Js.Promise.t(Stats.t) = "lstat"; 377 | 378 | type mkdirOptions; 379 | [@bs.obj] 380 | external mkdirOptions: 381 | (~recursive: bool=?, ~mode: int=?, unit) => mkdirOptions; 382 | 383 | [@bs.module "fs"] [@bs.scope "promises"] 384 | external mkdir: (string, mkdirOptions) => Js.Promise.t(unit) = "mkdir"; 385 | 386 | [@bs.module "fs"] [@bs.scope "promises"] 387 | external mkdirWith: (string, mkdirOptions) => Js.Promise.t(unit) = "mkdir"; 388 | 389 | type mkdtempOptions; 390 | [@bs.obj] external mdktempOptions: unit => mkdtempOptions; 391 | 392 | [@bs.module "fs"] [@bs.scope "promises"] 393 | external mkdtemp: (string, mkdtempOptions) => Js.Promise.t(string) = 394 | "mkddtemp"; 395 | 396 | [@bs.module "fs"] [@bs.scope "promises"] 397 | external mkdtempWith: (string, mkdtempOptions) => Js.Promise.t(string) = 398 | "mkddtemp"; 399 | 400 | [@bs.module "fs"] [@bs.scope "promises"] 401 | external open_: (string, Flag.t) => Js.Promise.t(FileHandle.t) = "open"; 402 | 403 | [@bs.module "fs"] [@bs.scope "promises"] 404 | external openWithMode: 405 | (string, Flag.t, ~mode: int) => Js.Promise.t(FileHandle.t) = 406 | "open"; 407 | 408 | module WriteStream = { 409 | type kind('w) = [ Stream.writable('w) | `FileSystem]; 410 | type subtype('w, 'ty) = Stream.subtype([> kind('w)] as 'ty); 411 | type supertype('w, 'ty) = Stream.subtype([< kind('w)] as 'ty); 412 | type t = subtype(Buffer.t, [ kind(Buffer.t)]); 413 | module Impl = { 414 | include Stream.Writable.Impl; 415 | [@bs.send] 416 | external bytesWritten: subtype('w, [> kind('w)]) => int = "bytesWritten"; 417 | [@bs.send] external path: subtype('w, [> kind('w)]) => string = "path"; 418 | [@bs.send] 419 | external pending: subtype('w, [> kind('w)]) => bool = "pending"; 420 | [@bs.send] 421 | external onOpen: 422 | ( 423 | subtype('w, [> kind('w)]) as 'stream', 424 | [@bs.as "open"] _, 425 | [@bs.uncurry] (fd => unit) 426 | ) => 427 | 'stream = 428 | "on"; 429 | [@bs.send] 430 | external onReady: 431 | ( 432 | subtype('w, [> kind('w)]) as 'stream, 433 | [@bs.as "ready"] _, 434 | [@bs.uncurry] (unit => unit) 435 | ) => 436 | 'stream = 437 | "on"; 438 | }; 439 | include Impl; 440 | }; 441 | 442 | module ReadStream = { 443 | type kind('r) = [ Stream.readable('r) | `FileSystem]; 444 | type subtype('r, 'ty) = Stream.subtype([> kind('r)] as 'ty); 445 | type supertype('r, 'ty) = Stream.subtype([< kind('r)] as 'ty); 446 | type t = subtype(Buffer.t, [ kind(Buffer.t)]); 447 | module Impl = { 448 | include Stream.Readable.Impl; 449 | [@bs.send] 450 | external bytesRead: subtype('r, [> kind('r)]) => int = "bytesWritten"; 451 | [@bs.send] external path: subtype('r, [> kind('r)]) => string = "path"; 452 | [@bs.send] 453 | external pending: subtype('r, [> kind('r)]) => bool = "pending"; 454 | [@bs.send] 455 | external onOpen: 456 | ( 457 | subtype('r, [> kind('r)]) as 'stream, 458 | [@bs.as "open"] _, 459 | [@bs.uncurry] (fd => unit) 460 | ) => 461 | 'stream = 462 | "on"; 463 | [@bs.send] 464 | external onReady: 465 | ( 466 | subtype('r, [> kind('r)]) as 'stream, 467 | [@bs.as "ready"] _, 468 | [@bs.uncurry] (unit => unit) 469 | ) => 470 | 'stream = 471 | "on"; 472 | }; 473 | include Impl; 474 | }; 475 | 476 | type createReadStreamOptions; 477 | [@bs.obj] 478 | external createReadStreamOptions: 479 | ( 480 | ~flags: string=?, 481 | ~fd: fd=?, 482 | ~mode: int=?, 483 | ~autoClose: bool=?, 484 | ~emitClose: bool=?, 485 | ~start: int=?, 486 | ~_end: int=?, 487 | ~highWaterMark: int=?, 488 | unit 489 | ) => 490 | createReadStreamOptions; 491 | 492 | [@bs.module "fs"] 493 | external createReadStream: string => ReadStream.t = "createReadStream"; 494 | [@bs.module "fs"] 495 | external createReadStreamWith: 496 | (string, createReadStreamOptions) => ReadStream.t = 497 | "createReadStream"; 498 | 499 | type createWriteStreamOptions; 500 | [@bs.obj] 501 | external createWriteStreamOptions: 502 | ( 503 | ~flags: string=?, 504 | ~fd: fd=?, 505 | ~mode: int=?, 506 | ~autoClose: bool=?, 507 | ~emitClose: bool=?, 508 | ~start: int=?, 509 | ~fs: Js.t({..})=?, 510 | unit 511 | ) => 512 | createReadStreamOptions; 513 | [@bs.module "fs"] 514 | external createWriteStream: string => WriteStream.t = "createWriteStream"; 515 | 516 | [@bs.module "fs"] 517 | external createWriteStreamWith: 518 | (string, createWriteStreamOptions) => WriteStream.t = 519 | "createWriteStream"; 520 | -------------------------------------------------------------------------------- /src/Global.re: -------------------------------------------------------------------------------- 1 | [@bs.val] external dirname: string = "__dirname"; 2 | [@bs.val] external filename: string = "__filename"; 3 | [@bs.val] external global: Js.t({..}) = "global"; 4 | [@bs.val] external require: string => Js.t({..}) = "require"; 5 | -------------------------------------------------------------------------------- /src/Http2.re: -------------------------------------------------------------------------------- 1 | type settingsObject; 2 | 3 | external settingsObject: 4 | ( 5 | ~headerTableSize: int=?, 6 | ~enablePush: bool=?, 7 | ~initialWindowSize: int=?, 8 | ~maxFrameSize: int=?, 9 | ~maxConcurrentStreams: int=?, 10 | ~maxHeaderListSize: int=?, 11 | ~enableConnectProtocol: bool=? 12 | ) => 13 | settingsObject; 14 | 15 | module Http2Stream = { 16 | type kind('w, 'r) = [ Stream.duplex('w, 'r) | `Http2Stream]; 17 | type subtype('w, 'r, 'ty) = Stream.subtype([> kind('w, 'r)] as 'ty); 18 | type supertype('w, 'r, 'ty) = Stream.subtype([< kind('w, 'r)] as 'ty); 19 | type t('w, 'r) = Stream.subtype(kind('w, 'r)); 20 | module Events = { 21 | include Stream.Duplex.Events; 22 | }; 23 | module Impl = { 24 | include Stream.Duplex.Impl; 25 | [@bs.get] external aborted: subtype('w, 'r, 'ty) => bool = "aborted"; 26 | [@bs.get] external bufferSize: subtype('w, 'r, 'ty) => int = "bufferSize"; 27 | [@bs.get] external closed: subtype('w, 'r, 'ty) => bool = "closed"; 28 | [@bs.get] external destroyed: subtype('w, 'r, 'ty) => bool = "destroyed"; 29 | [@bs.get] 30 | external endAfterHeaders: subtype('w, 'r, 'ty) => bool = 31 | "endAfterHeaders"; 32 | [@bs.get] [@bs.return nullable] 33 | external id: subtype('w, 'r, 'ty) => option(int) = "id"; 34 | [@bs.get] external pending: subtype('w, 'r, 'ty) => bool = "pending"; 35 | [@bs.get] external rstCode: subtype('w, 'r, 'ty) => int = "rstCode"; 36 | [@bs.get] 37 | external sentHeaders: subtype('w, 'r, 'ty) => bool = "sentHeaders"; 38 | }; 39 | include Impl; 40 | }; 41 | 42 | module ClientHttp2Stream = { 43 | type kind('w, 'r) = [ Http2Stream.kind('w, 'r) | `ClientHttp2Stream]; 44 | type subtype('w, 'r, 'ty) = Stream.subtype([> kind('w, 'r)] as 'ty); 45 | type supertype('w, 'r, 'ty) = Stream.subtype([< kind('w, 'r)] as 'ty); 46 | type t('w, 'r) = Stream.subtype(kind('w, 'r)); 47 | module Events = { 48 | include Http2Stream.Events; 49 | }; 50 | module Impl = { 51 | include Http2Stream.Impl; 52 | }; 53 | include Impl; 54 | }; 55 | 56 | module ServerHttp2Stream = { 57 | type kind('w, 'r) = [ Http2Stream.kind('w, 'r) | `ServerHttp2Stream]; 58 | type subtype('w, 'r, 'ty) = Stream.subtype([> kind('w, 'r)] as 'ty); 59 | type supertype('w, 'r, 'ty) = Stream.subtype([< kind('w, 'r)] as 'ty); 60 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 61 | module Events = { 62 | include Http2Stream.Events; 63 | }; 64 | module Impl = { 65 | include Http2Stream.Impl; 66 | }; 67 | include Impl; 68 | }; 69 | 70 | module Http2Session = { 71 | type t; 72 | [@bs.send] 73 | external onClose: (t, [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => t = 74 | "on"; 75 | [@bs.send] 76 | external onConnect: 77 | (t, [@bs.as "connect"] _, [@bs.uncurry] ((t, Net.Socket.t) => unit)) => t = 78 | "on"; 79 | [@bs.send] 80 | external onError: 81 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 82 | "on"; 83 | [@bs.send] 84 | external onFrameError: 85 | ( 86 | t, 87 | [@bs.as "frameError"] _, 88 | [@bs.uncurry] ((~type_: int, ~errorCode: int, ~streamId: int) => unit) 89 | ) => 90 | t = 91 | "on"; 92 | [@bs.send] 93 | external onGoAway: 94 | ( 95 | t, 96 | [@bs.as "goAway"] _, 97 | [@bs.uncurry] ((~errorCode: int, ~lastStreamId: int, Buffer.t) => unit) 98 | ) => 99 | t = 100 | "on"; 101 | [@bs.send] 102 | external onLocalSettings: 103 | (t, [@bs.as "localSettings"] _, [@bs.uncurry] (settingsObject => unit)) => 104 | t = 105 | "on"; 106 | [@bs.send] 107 | external onPing: 108 | (t, [@bs.as "ping"] _, [@bs.uncurry] (Buffer.t => unit)) => t = 109 | "on"; 110 | [@bs.send] 111 | external onRemoteSettings: 112 | (t, [@bs.as "remoteSettings"] _, [@bs.uncurry] (settingsObject => unit)) => 113 | t = 114 | "on"; 115 | [@bs.send] 116 | external onStream: 117 | ( 118 | t, 119 | [@bs.as "stream"] _, 120 | [@bs.uncurry] ( 121 | ( 122 | t, 123 | Js.t({ 124 | .. 125 | "status": string, 126 | "content-type": string, 127 | }), 128 | int, 129 | array(Js.t({..})) 130 | ) => 131 | unit 132 | ) 133 | ) => 134 | t = 135 | "on"; 136 | [@bs.send] 137 | external onTimeout: 138 | (t, [@bs.as "timeout"] _, [@bs.uncurry] (unit => unit)) => t = 139 | "on"; 140 | [@bs.get] [@bs.return nullable] 141 | external alpnProtocol: t => option(string) = "alpnProtocol"; 142 | [@bs.send] external close: t => unit = "close"; 143 | [@bs.get] external closed: t => bool = "closed"; 144 | [@bs.send] external destroy: t => unit = "destroy"; 145 | [@bs.send] external destroyWithError: (t, Js.Exn.t) => unit = "destroy"; 146 | [@bs.send] external destroyWithCode: (t, int) => unit = "destroy"; 147 | [@bs.get] external destroyed: t => bool = "destroyed"; 148 | [@bs.get] [@bs.return nullable] 149 | external encrypted: t => option(bool) = "encrypted"; 150 | [@bs.send] external goaway: t => unit = "goaway"; 151 | [@bs.send] 152 | external goawayWith: 153 | (t, ~code: int=?, ~lastStreamId: int=?, ~data: Buffer.t=?, unit) => unit = 154 | "goaway"; 155 | [@bs.get] 156 | external localSettings: 157 | t => 158 | { 159 | . 160 | "headerTableSize": int, 161 | "enablePush": bool, 162 | "initialWindowSize": int, 163 | "maxFrameSize": int, 164 | "maxConcurrentStreams": int, 165 | "maxHeaderListSize": int, 166 | "enableConnectProtocol": bool, 167 | } = 168 | "on"; 169 | [@bs.get] [@bs.return nullable] 170 | external originSet: t => option(array(string)) = "originSet"; 171 | [@bs.get] external pendingSettingsAck: t => bool = "pendingSettingsAck"; 172 | [@bs.send] 173 | external ping: (t, (Js.Nullable.t(Js.Exn.t), int, Buffer.t) => unit) => bool = 174 | "ping"; 175 | [@bs.send] 176 | external pingWith: 177 | ( 178 | t, 179 | ~payload: Buffer.t, 180 | (Js.Nullable.t(Js.Exn.t), int, Buffer.t) => unit 181 | ) => 182 | bool = 183 | "ping"; 184 | [@bs.send] external ref: t => unit = "ref"; 185 | [@bs.get] 186 | external remoteSettings: 187 | t => 188 | { 189 | . 190 | "headerTableSize": int, 191 | "enablePush": bool, 192 | "initialWindowSize": int, 193 | "maxFrameSize": int, 194 | "maxConcurrentStreams": int, 195 | "maxHeaderListSize": int, 196 | "enableConnectProtocol": bool, 197 | } = 198 | "remoteSettings"; 199 | [@bs.send] 200 | external setTimeout: (t, int, unit => unit) => unit = "setTimeout"; 201 | [@bs.get] external socket: t => Net.TcpSocket.t = "socket"; 202 | [@bs.get] 203 | external state: 204 | t => 205 | { 206 | . 207 | "effectiveLocalWindowSize": int, 208 | "effectiveRecvDataLength": int, 209 | "nextStreamID": int, 210 | "localWindowSize": int, 211 | "lastProcStreamID": int, 212 | "remoteWindowSize": int, 213 | "deflateDynamicTableSize": int, 214 | "inflateDynamicTableSize": int, 215 | } = 216 | "state"; 217 | [@bs.send] 218 | external settings: 219 | ( 220 | t, 221 | settingsObject, 222 | ~callback: (Js.Null.t(Js.Exn.t), settingsObject, int) => unit=? 223 | ) => 224 | unit = 225 | "settings"; 226 | [@bs.get] external type_: t => int = "type"; 227 | }; 228 | 229 | module ServerHttp2Session = { 230 | include Http2Session; 231 | 232 | module Origin = { 233 | type t('a); 234 | type urlString = [ | `UrlString]; 235 | type url = [ | `Url]; 236 | type object_ = [ | `Object]; 237 | type streamId = [ | `StreamId]; 238 | external urlString: string => t(urlString) = "%identity"; 239 | external url: Url.t => t(url) = "%identity"; 240 | external object_: {. "origin": string} => t(object_) = "%identity"; 241 | external streamId: int => t(streamId) = "%identity"; 242 | }; 243 | 244 | [@bs.send] 245 | external altsvc: 246 | ( 247 | t, 248 | string, 249 | Origin.t( 250 | [ Origin.urlString | Origin.url | Origin.object_ | Origin.streamId], 251 | ) 252 | ) => 253 | unit = 254 | "altsvc"; 255 | 256 | [@bs.send] [@bs.variadic] 257 | external origin: 258 | array(Origin.t([ Origin.urlString | Origin.url | Origin.object_])) => 259 | unit = 260 | "origin"; 261 | }; 262 | 263 | module Http2ServerRequest = { 264 | type kind('r) = [ Stream.readable('r) | `Http2ServerRequest]; 265 | type subtype('r, 'ty) = Stream.subtype([> kind('r)] as 'ty); 266 | type supertype('r, 'ty) = Stream.subtype([< kind('r)] as 'ty); 267 | type t = Stream.subtype(kind(Buffer.t)); 268 | module Impl = { 269 | include Stream.Readable.Impl; 270 | [@bs.send] 271 | external onAborted: 272 | ( 273 | subtype('r, 'ty), 274 | [@bs.as "aborted"] _, 275 | [@bs.uncurry] (unit => unit) 276 | ) => 277 | subtype('r, 'ty) = 278 | "on"; 279 | [@bs.send] 280 | external onClose: 281 | (subtype('r, 'ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 282 | subtype('r, 'ty) = 283 | "on"; 284 | [@bs.get] external aborted: subtype('r, 'ty) => bool = "aborted"; 285 | [@bs.get] external authority: subtype('r, 'ty) => string = "authority"; 286 | [@bs.get] external complete: subtype('r, 'ty) => bool = "complete"; 287 | [@bs.send] external destroy: subtype('r, 'ty) => unit = "destroy"; 288 | [@bs.send] 289 | external destroyWithError: (subtype('r, 'ty), Js.Exn.t) => unit = 290 | "destroy"; 291 | [@bs.get] external headers: subtype('r, 'ty) => Js.t({..}) = "headers"; 292 | [@bs.get] 293 | external httpVersion: subtype('r, 'ty) => string = "httpVersion"; 294 | [@bs.get] external method_: subtype('r, 'ty) => string = "method"; 295 | [@bs.get] 296 | external rawHeaders: subtype('r, 'ty) => array(string) = "rawHeaders"; 297 | [@bs.get] 298 | external rawTrailers: subtype('r, 'ty) => array(string) = "rawTrailers"; 299 | [@bs.get] external scheme: subtype('r, 'ty) => string = "scheme"; 300 | [@bs.send] 301 | external setTimeout: 302 | (subtype('r, 'ty), int, unit => unit) => subtype('r, 'ty) = 303 | "setTimeout"; 304 | [@bs.get] 305 | external socket: 306 | t => 307 | Stream.subtype( 308 | [< Net.Socket.kind('w, 'r) | Tls.TlsSocket.kind('w, 'r)], 309 | ) = 310 | "socket"; 311 | [@bs.get] external stream: t => Stream.t = "stream"; 312 | [@bs.get] external trailers: t => Js.t({..}) = "trailers"; 313 | [@bs.get] external url: t => string = "url"; 314 | }; 315 | include Impl; 316 | }; 317 | 318 | module Http2ServerResponse = { 319 | type kind = [ Stream.stream | `Http2ServerResponse]; 320 | type subtype('ty) = Stream.subtype([> kind] as 'ty); 321 | type supertype('ty) = Stream.subtype([< kind] as 'ty); 322 | type t = Stream.subtype(kind); 323 | module Impl = { 324 | include Stream.Duplex.Impl; 325 | [@bs.send] 326 | external onClose: 327 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 328 | subtype('ty) = 329 | "on"; 330 | [@bs.send] 331 | external onFinish: 332 | (subtype('ty), [@bs.as "finish"] _, [@bs.uncurry] (unit => unit)) => 333 | subtype('ty) = 334 | "on"; 335 | [@bs.send] 336 | external setTrailers: (subtype('ty), Js.t({..})) => unit = "setTrailers"; 337 | [@bs.send] external end_: subtype('ty) => unit = "end"; 338 | [@bs.send] 339 | external endWith: 340 | (subtype('ty), ~data: Buffer.t=?, ~callback: unit => unit=?) => 341 | subtype('ty) = 342 | "end"; 343 | [@bs.send] 344 | external getHeader: (subtype('ty), string) => string = "getHeader"; 345 | [@bs.send] 346 | external getHeaderNames: subtype('ty) => array(string) = 347 | "getHeaderNames"; 348 | [@bs.send] 349 | external getHeaders: subtype('ty) => Js.t({..}) = "getHeaders"; 350 | [@bs.send] 351 | external hasHeader: (subtype('ty), string) => bool = "hasHeader"; 352 | [@bs.send] external headersSent: subtype('ty) => bool = "headersSent"; 353 | [@bs.send] 354 | external removeHeader: (subtype('ty), string) => unit = "removeHeader"; 355 | [@bs.send] 356 | external setHeader: (subtype('ty), string) => unit = "setHeader"; 357 | [@bs.send] 358 | external setHeaderArray: (subtype('ty), array(string)) => unit = 359 | "setHeader"; 360 | [@bs.send] 361 | external setTimeout: 362 | (subtype('ty), int, unit => unit) => Http2Stream.t('w, 'r) = 363 | "setTimeout"; 364 | [@bs.get] external socket: subtype('ty) => Net.TcpSocket.t = "socket"; 365 | [@bs.get] external statusCode: subtype('ty) => int = "statusCode"; 366 | [@bs.get] 367 | external statusMessage: subtype('ty) => string = "statusMessage"; 368 | [@bs.get] 369 | external stream: subtype('ty) => Http2Stream.t('w, 'r) = "stream"; 370 | [@bs.get] external writableEnded: subtype('ty) => bool = "writableEnded"; 371 | [@bs.send] external write: (subtype('ty), Buffer.t) => bool = "write"; 372 | [@bs.send] 373 | external writeWith: 374 | (subtype('ty), Buffer.t, ~callback: unit => unit=?) => bool = 375 | "write"; 376 | [@bs.send] external writeContinue: subtype('ty) => unit = "writeContinue"; 377 | [@bs.send] 378 | external writeHead: (subtype('ty), int) => subtype('ty) = "writeHead"; 379 | [@bs.send] 380 | external writeHeadWith: 381 | (subtype('ty), int, ~message: string=?, ~headers: Js.t({..})=?) => 382 | subtype('ty) = 383 | "writeHead"; 384 | [@bs.send] 385 | external createPushResponse: 386 | ( 387 | subtype('ty), 388 | Js.t({..}), 389 | [@bs.uncurry] ((Js.Exn.t, ServerHttp2Stream.t) => unit) 390 | ) => 391 | unit = 392 | "writeHead"; 393 | }; 394 | include Impl; 395 | }; -------------------------------------------------------------------------------- /src/Https.re: -------------------------------------------------------------------------------- 1 | type https = [ | `Https]; 2 | 3 | module HttpsServer = { 4 | type kind = [ Tls.TlsServer.kind | https]; 5 | type subtype('a) = Net.Server.subtype([> kind] as 'a); 6 | type supertype('a) = Net.Server.subtype([< kind] as 'a); 7 | type t = subtype(kind); 8 | module Events = { 9 | include Tls.TlsServer.Events; 10 | }; 11 | module Impl = { 12 | include Tls.TlsServer.Impl; 13 | include Events; 14 | }; 15 | include Impl; 16 | }; 17 | 18 | module Agent = { 19 | type t; 20 | module Events = { 21 | [@bs.send] 22 | external onKeylog: 23 | ( 24 | t, 25 | [@bs.as "keylog"] _, 26 | [@bs.uncurry] ((Buffer.t, Tls.TlsSocket.t) => unit) 27 | ) => 28 | t = 29 | "on"; 30 | [@bs.send] 31 | external onKeylogOnce: 32 | ( 33 | t, 34 | [@bs.as "keylog"] _, 35 | [@bs.uncurry] ((Buffer.t, Tls.TlsSocket.t) => unit) 36 | ) => 37 | t = 38 | "once"; 39 | [@bs.send] 40 | external offKeylog: 41 | ( 42 | t, 43 | [@bs.as "keylog"] _, 44 | [@bs.uncurry] ((Buffer.t, Tls.TlsSocket.t) => unit) 45 | ) => 46 | t = 47 | "off"; 48 | }; 49 | include Events; 50 | }; 51 | -------------------------------------------------------------------------------- /src/Module.re: -------------------------------------------------------------------------------- 1 | include Node_module -------------------------------------------------------------------------------- /src/Net.re: -------------------------------------------------------------------------------- 1 | type tcp = [ | `Tcp]; 2 | type icp = [ | `Icp]; 3 | 4 | type address = { 5 | [@bs.as "port"] 6 | port: int, 7 | [@bs.as "family"] 8 | family: string, 9 | [@bs.as "address"] 10 | address: string, 11 | }; 12 | 13 | module Socket = { 14 | type kind('w, 'r) = [ Stream.socket('w, 'r)]; 15 | type subtype('w, 'r, 'ty) = Stream.subtype([> kind('w, 'r)] as 'ty); 16 | type supertype('w, 'r, 'ty) = Stream.subtype([< kind('w, 'r)] as 'ty); 17 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 18 | 19 | module Events = { 20 | [@bs.send] 21 | external onClose: 22 | ( 23 | subtype('w, 'r, 'ty), 24 | [@bs.as "close"] _, 25 | [@bs.uncurry] (bool => unit) 26 | ) => 27 | subtype('w, 'r, 'ty) = 28 | "on"; 29 | [@bs.send] 30 | external onConnect: 31 | ( 32 | subtype('w, 'r, 'ty), 33 | [@bs.as "connect"] _, 34 | [@bs.uncurry] (unit => unit) 35 | ) => 36 | subtype('w, 'r, 'ty) = 37 | "on"; 38 | [@bs.send] 39 | external onData: 40 | (subtype('w, 'r, 'ty), [@bs.as "data"] _, [@bs.uncurry] ('r => unit)) => 41 | subtype('w, 'r, 'ty) = 42 | "on"; 43 | [@bs.send] 44 | external onDrain: 45 | ( 46 | subtype('w, 'r, 'ty), 47 | [@bs.as "drain"] _, 48 | [@bs.uncurry] (unit => unit) 49 | ) => 50 | subtype('w, 'r, 'ty) = 51 | "on"; 52 | [@bs.send] 53 | external onEnd: 54 | ( 55 | subtype('w, 'r, 'ty), 56 | [@bs.as "end"] _, 57 | [@bs.uncurry] (unit => unit) 58 | ) => 59 | subtype('w, 'r, 'ty) = 60 | "on"; 61 | [@bs.send] 62 | external onError: 63 | ( 64 | subtype('w, 'r, 'ty), 65 | [@bs.as "error"] _, 66 | [@bs.uncurry] (Js.Exn.t => unit) 67 | ) => 68 | subtype('w, 'r, 'ty) = 69 | "on"; 70 | [@bs.send] 71 | external onLookup: 72 | ( 73 | subtype('w, 'r, 'ty), 74 | [@bs.as "lookup"] _, 75 | [@bs.uncurry] (unit => unit) 76 | ) => 77 | subtype('w, 'r, 'ty) = 78 | "on"; 79 | [@bs.send] 80 | external onReady: 81 | ( 82 | subtype('w, 'r, 'ty), 83 | [@bs.as "ready"] _, 84 | [@bs.uncurry] (unit => unit) 85 | ) => 86 | subtype('w, 'r, 'ty) = 87 | "on"; 88 | [@bs.send] 89 | external onTimeout: 90 | (subtype('w, 'r, 'ty), [@bs.as "timeout"] _, unit => unit) => 91 | subtype('w, 'r, 'ty) = 92 | "on"; 93 | 94 | [@bs.send] 95 | external offClose: 96 | ( 97 | subtype('w, 'r, 'ty), 98 | [@bs.as "close"] _, 99 | [@bs.uncurry] (bool => unit) 100 | ) => 101 | subtype('w, 'r, 'ty) = 102 | "off"; 103 | [@bs.send] 104 | external offConnect: 105 | ( 106 | subtype('w, 'r, 'ty), 107 | [@bs.as "connect"] _, 108 | [@bs.uncurry] (unit => unit) 109 | ) => 110 | subtype('w, 'r, 'ty) = 111 | "off"; 112 | [@bs.send] 113 | external offData: 114 | (subtype('w, 'r, 'ty), [@bs.as "data"] _, [@bs.uncurry] ('r => unit)) => 115 | subtype('w, 'r, 'ty) = 116 | "off"; 117 | [@bs.send] 118 | external offDrain: 119 | ( 120 | subtype('w, 'r, 'ty), 121 | [@bs.as "drain"] _, 122 | [@bs.uncurry] (unit => unit) 123 | ) => 124 | subtype('w, 'r, 'ty) = 125 | "off"; 126 | [@bs.send] 127 | external offEnd: 128 | ( 129 | subtype('w, 'r, 'ty), 130 | [@bs.as "end"] _, 131 | [@bs.uncurry] (unit => unit) 132 | ) => 133 | subtype('w, 'r, 'ty) = 134 | "off"; 135 | [@bs.send] 136 | external offError: 137 | ( 138 | subtype('w, 'r, 'ty), 139 | [@bs.as "error"] _, 140 | [@bs.uncurry] (Js.Exn.t => unit) 141 | ) => 142 | subtype('w, 'r, 'ty) = 143 | "off"; 144 | [@bs.send] 145 | external offLookup: 146 | ( 147 | subtype('w, 'r, 'ty), 148 | [@bs.as "lookup"] _, 149 | [@bs.uncurry] (unit => unit) 150 | ) => 151 | subtype('w, 'r, 'ty) = 152 | "off"; 153 | [@bs.send] 154 | external offReady: 155 | ( 156 | subtype('w, 'r, 'ty), 157 | [@bs.as "ready"] _, 158 | [@bs.uncurry] (unit => unit) 159 | ) => 160 | subtype('w, 'r, 'ty) = 161 | "off"; 162 | [@bs.send] 163 | external offTimeout: 164 | ( 165 | subtype('w, 'r, 'ty), 166 | [@bs.as "timeout"] _, 167 | [@bs.uncurry] (unit => unit) 168 | ) => 169 | subtype('w, 'r, 'ty) = 170 | "off"; 171 | 172 | [@bs.send] 173 | external onCloseOnce: 174 | ( 175 | subtype('w, 'r, 'ty), 176 | [@bs.as "close"] _, 177 | [@bs.uncurry] (bool => unit) 178 | ) => 179 | subtype('w, 'r, 'ty) = 180 | "once"; 181 | [@bs.send] 182 | external onConnectOnce: 183 | ( 184 | subtype('w, 'r, 'ty), 185 | [@bs.as "connect"] _, 186 | [@bs.uncurry] (unit => unit) 187 | ) => 188 | subtype('w, 'r, 'ty) = 189 | "once"; 190 | [@bs.send] 191 | external onDataOnce: 192 | (subtype('w, 'r, 'ty), [@bs.as "data"] _, [@bs.uncurry] ('r => unit)) => 193 | subtype('w, 'r, 'ty) = 194 | "once"; 195 | [@bs.send] 196 | external onDrainOnce: 197 | ( 198 | subtype('w, 'r, 'ty), 199 | [@bs.as "drain"] _, 200 | [@bs.uncurry] (unit => unit) 201 | ) => 202 | subtype('w, 'r, 'ty) = 203 | "once"; 204 | [@bs.send] 205 | external onEndOnce: 206 | ( 207 | subtype('w, 'r, 'ty), 208 | [@bs.as "end"] _, 209 | [@bs.uncurry] (unit => unit) 210 | ) => 211 | subtype('w, 'r, 'ty) = 212 | "once"; 213 | [@bs.send] 214 | external onErrorOnce: 215 | ( 216 | subtype('w, 'r, 'ty), 217 | [@bs.as "error"] _, 218 | [@bs.uncurry] (Js.Exn.t => unit) 219 | ) => 220 | subtype('w, 'r, 'ty) = 221 | "once"; 222 | [@bs.send] 223 | external onLookupOnce: 224 | ( 225 | subtype('w, 'r, 'ty), 226 | [@bs.as "lookup"] _, 227 | [@bs.uncurry] (unit => unit) 228 | ) => 229 | subtype('w, 'r, 'ty) = 230 | "once"; 231 | [@bs.send] 232 | external onReadyOnce: 233 | ( 234 | subtype('w, 'r, 'ty), 235 | [@bs.as "ready"] _, 236 | [@bs.uncurry] (unit => unit) 237 | ) => 238 | subtype('w, 'r, 'ty) = 239 | "once"; 240 | [@bs.send] 241 | external onTimeoutOnce: 242 | ( 243 | subtype('w, 'r, 'ty), 244 | [@bs.as "timeout"] _, 245 | [@bs.uncurry] (unit => unit) 246 | ) => 247 | subtype('w, 'r, 'ty) = 248 | "once"; 249 | }; 250 | 251 | module Impl = { 252 | include Stream.Duplex.Impl; 253 | include Events; 254 | [@bs.send] external address: subtype('w, 'r, 'ty) => address = "address"; 255 | [@bs.get] external bufferSize: subtype('w, 'r, 'ty) => int = "bufferSize"; 256 | [@bs.get] external bytesRead: subtype('w, 'r, 'ty) => int = "bytesRead"; 257 | [@bs.get] 258 | external bytesWritten: subtype('w, 'r, 'ty) => int = "bytesWritten"; 259 | [@bs.get] 260 | external connecting: subtype('w, 'r, 'ty) => bool = "connecting"; 261 | [@bs.get] external destroyed: subtype('w, 'r, 'ty) => bool = "destroyed"; 262 | [@bs.send] 263 | external destroy: 264 | (subtype('w, 'r, 'ty), ~error: option(Js.Exn.t)) => 265 | subtype('w, 'r, 'ty) = 266 | "destroy"; 267 | [@bs.get] 268 | external localAddress: subtype('w, 'r, 'ty) => string = "localAddress"; 269 | [@bs.get] external localPort: subtype('w, 'r, 'ty) => int = "localPort"; 270 | [@bs.send] 271 | external pause: subtype('w, 'r, 'ty) => subtype('w, 'r, 'ty) = "pause"; 272 | [@bs.get] external pending: subtype('w, 'r, 'ty) => bool = "pending"; 273 | [@bs.send] 274 | external ref: subtype('w, 'r, 'ty) => subtype('w, 'r, 'ty) = "ref"; 275 | [@bs.get] 276 | external remoteAddress: subtype('w, 'r, 'ty) => string = "remoteAddress"; 277 | [@bs.get] 278 | external remoteFamily: subtype('w, 'r, 'ty) => string = "remoteFamily"; 279 | [@bs.get] external remotePort: subtype('w, 'r, 'ty) => int = "remotePort"; 280 | [@bs.send] 281 | external resume: subtype('w, 'r, 'ty) => subtype('w, 'r, 'ty) = "resume"; 282 | [@bs.send] 283 | external setKeepAlive: 284 | (subtype('w, 'r, 'ty), ~enable: bool, ~delay: int) => 285 | subtype('w, 'r, 'ty) = 286 | "setKeepAlive"; 287 | [@bs.send] 288 | external setNoDelay: 289 | (subtype('w, 'r, 'ty), ~noDelay: bool) => subtype('w, 'r, 'ty) = 290 | "noDelay"; 291 | [@bs.send] 292 | external setTimeout: 293 | ( 294 | subtype('w, 'r, 'ty), 295 | int, 296 | ~callback: [@bs.this] (subtype('w, 'r, 'ty) => unit) 297 | ) => 298 | subtype('w, 'r, 'ty) = 299 | "setTimeout"; 300 | [@bs.send] 301 | external unref: subtype('w, 'r, 'ty) => subtype('w, 'r, 'ty) = "unref"; 302 | [@bs.send] 303 | external connectIcp: 304 | ( 305 | subtype('w, 'r, [> kind('w, 'r) | icp]) as 'icpSocket, 306 | ~path: string, 307 | [@bs.uncurry] (unit => unit) 308 | ) => 309 | 'icpSocket = 310 | "connect"; 311 | [@bs.send] 312 | external connectTcp: 313 | ( 314 | subtype('w, 'r, [> kind('w, 'r) | tcp]) as 'tcpSocket, 315 | ~port: int, 316 | ~host: string, 317 | [@bs.uncurry] (unit => unit) 318 | ) => 319 | 'tcpSocket = 320 | "connect"; 321 | }; 322 | include Impl; 323 | 324 | type makeOptions; 325 | 326 | [@bs.obj] 327 | external makeOptions: 328 | (~fd: int=?, ~readable: bool=?, ~writable: bool=?, unit) => makeOptions; 329 | 330 | [@bs.module "net"] [@bs.new] 331 | external make: (~options: makeOptions=?, unit) => t = "Socket"; 332 | }; 333 | 334 | module TcpSocket = { 335 | type nonrec kind('w, 'r) = [ Socket.kind('w, 'r) | tcp]; 336 | type subtype('w, 'r, 'ty) = Stream.subtype([> kind('w, 'r)] as 'ty); 337 | type supertype('w, 'r, 'ty) = Stream.subtype([< kind('w, 'r)] as 'ty); 338 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 339 | module Events = { 340 | include Socket.Events; 341 | }; 342 | module Impl = { 343 | include Socket.Impl; 344 | include Events; 345 | [@bs.send] 346 | external connect: 347 | ( 348 | subtype('w, 'r, 'ty), 349 | ~port: int, 350 | ~host: string, 351 | [@bs.uncurry] (unit => unit) 352 | ) => 353 | subtype('w, 'r, 'ty) = 354 | "connect"; 355 | }; 356 | include Impl; 357 | [@bs.module "net"] [@bs.new] external make: unit => t = "Socket"; 358 | }; 359 | 360 | module IcpSocket = { 361 | type kind('w, 'r) = [ Socket.kind('w, 'r) | icp]; 362 | type subtype('w, 'r, 'ty) = Stream.subtype([> kind('w, 'r)] as 'ty); 363 | type supertype('w, 'r, 'ty) = Stream.subtype([< kind('w, 'r)] as 'ty); 364 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 365 | module Events = { 366 | include Socket.Events; 367 | }; 368 | module Impl = { 369 | include Socket.Impl; 370 | [@bs.send] 371 | external connect: 372 | (subtype('w, 'r, 'ty), ~path: string, [@bs.uncurry] (unit => unit)) => 373 | subtype('w, 'r, 'ty) = 374 | "connect"; 375 | }; 376 | include Impl; 377 | [@bs.module "net"] [@bs.new] external make: unit => t = "Socket"; 378 | }; 379 | 380 | module Server = { 381 | type kind = [ | `Server]; 382 | type subtype('ty) constraint 'ty = [> kind]; 383 | type supertype('ty) constraint 'ty = [< kind]; 384 | type t('ty) = subtype('ty); 385 | module Events = { 386 | [@bs.send] 387 | external onClose: 388 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 389 | subtype('ty) = 390 | "on"; 391 | [@bs.send] 392 | external onError: 393 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 394 | subtype('ty) = 395 | "on"; 396 | [@bs.send] 397 | external onConnection: 398 | ( 399 | subtype('ty), 400 | [@bs.as "connection"] _, 401 | [@bs.uncurry] (Socket.t => unit) 402 | ) => 403 | subtype('ty) = 404 | "on"; 405 | [@bs.send] 406 | external onListening: 407 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 408 | subtype('ty) = 409 | "on"; 410 | [@bs.send] 411 | external offClose: 412 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 413 | subtype('ty) = 414 | "off"; 415 | [@bs.send] 416 | external offError: 417 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 418 | subtype('ty) = 419 | "off"; 420 | [@bs.send] 421 | external offConnection: 422 | ( 423 | subtype('ty), 424 | [@bs.as "connection"] _, 425 | [@bs.uncurry] (Socket.t => unit) 426 | ) => 427 | subtype('ty) = 428 | "off"; 429 | [@bs.send] 430 | external offListening: 431 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 432 | subtype('ty) = 433 | "off"; 434 | [@bs.send] 435 | external onCloseOnce: 436 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 437 | subtype('ty) = 438 | "once"; 439 | [@bs.send] 440 | external onErrorOnce: 441 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 442 | subtype('ty) = 443 | "once"; 444 | [@bs.send] 445 | external onConnectionOnce: 446 | ( 447 | subtype('ty), 448 | [@bs.as "connection"] _, 449 | [@bs.uncurry] (Socket.t => unit) 450 | ) => 451 | subtype('ty) = 452 | "once"; 453 | [@bs.send] 454 | external onListeningOnce: 455 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 456 | subtype('ty) = 457 | "once"; 458 | }; 459 | module Impl = { 460 | include Events; 461 | [@bs.send] 462 | external close: 463 | (subtype('ty), ~callback: Js.nullable(Js.Exn.t) => unit=?, unit) => 464 | subtype('ty) = 465 | "close"; 466 | [@bs.send] 467 | external getConnections: 468 | (subtype('ty), (Js.nullable(Js.Exn.t), int) => unit) => subtype('ty) = 469 | "getConnections"; 470 | [@bs.set] 471 | external setMaxConnections: (subtype('ty), int) => unit = 472 | "maxConnections"; 473 | [@bs.get] external maxConnections: subtype('ty) => int = "maxConnections"; 474 | [@bs.send] external ref: subtype('ty) => subtype('ty) = "ref"; 475 | [@bs.send] external unref: subtype('ty) => subtype('ty) = "unref"; 476 | [@bs.get] external listening: subtype('ty) => bool = "listening"; 477 | }; 478 | 479 | include Impl; 480 | }; 481 | 482 | module TcpServer = { 483 | type kind = [ Server.kind | tcp]; 484 | type t = Server.subtype(kind); 485 | type subtype('ty) = Server.subtype([> kind] as 'ty); 486 | type supertype('ty) = Server.subtype([< kind] as 'ty); 487 | module Events = { 488 | [@bs.send] 489 | external onClose: 490 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 491 | subtype('ty) = 492 | "on"; 493 | [@bs.send] 494 | external onError: 495 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 496 | subtype('ty) = 497 | "on"; 498 | [@bs.send] 499 | external onConnection: 500 | ( 501 | subtype('ty), 502 | [@bs.as "connection"] _, 503 | [@bs.uncurry] (TcpSocket.t => unit) 504 | ) => 505 | subtype('ty) = 506 | "on"; 507 | [@bs.send] 508 | external onListening: 509 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 510 | subtype('ty) = 511 | "on"; 512 | [@bs.send] 513 | external offClose: 514 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 515 | subtype('ty) = 516 | "off"; 517 | [@bs.send] 518 | external offError: 519 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 520 | subtype('ty) = 521 | "off"; 522 | [@bs.send] 523 | external offConnection: 524 | ( 525 | subtype('ty), 526 | [@bs.as "connection"] _, 527 | [@bs.uncurry] (TcpSocket.t => unit) 528 | ) => 529 | subtype('ty) = 530 | "off"; 531 | [@bs.send] 532 | external offListening: 533 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 534 | subtype('ty) = 535 | "off"; 536 | [@bs.send] 537 | external onCloseOnce: 538 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 539 | subtype('ty) = 540 | "once"; 541 | [@bs.send] 542 | external onErrorOnce: 543 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 544 | subtype('ty) = 545 | "once"; 546 | [@bs.send] 547 | external onConnectionOnce: 548 | ( 549 | subtype('ty), 550 | [@bs.as "connection"] _, 551 | [@bs.uncurry] (TcpSocket.t => unit) 552 | ) => 553 | subtype('ty) = 554 | "once"; 555 | [@bs.send] 556 | external onListeningOnce: 557 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 558 | subtype('ty) = 559 | "once"; 560 | }; 561 | module Impl = { 562 | include Events; 563 | [@bs.send] 564 | external close: 565 | (subtype('ty), ~callback: Js.nullable(Js.Exn.t) => unit) => 566 | subtype('ty) = 567 | "close"; 568 | [@bs.send] 569 | external getConnections: 570 | (subtype('ty), (Js.nullable(Js.Exn.t), int) => unit) => subtype('ty) = 571 | "getConnections"; 572 | [@bs.set] 573 | external setMaxConnections: (subtype('ty), int) => unit = 574 | "maxConnections"; 575 | [@bs.get] external maxConnections: subtype('ty) => int = "maxConnections"; 576 | [@bs.send] external ref: subtype('ty) => subtype('ty) = "ref"; 577 | [@bs.send] external unref: subtype('ty) => subtype('ty) = "unref"; 578 | [@bs.get] external listening: subtype('ty) => bool = "listening"; 579 | }; 580 | include Impl; 581 | type listenOptions; 582 | [@bs.obj] 583 | external listenOptions: 584 | ( 585 | ~port: int=?, 586 | ~host: string=?, 587 | ~backlog: int=?, 588 | ~exclusive: bool=?, 589 | ~ipv6Only: bool=?, 590 | unit 591 | ) => 592 | listenOptions; 593 | [@bs.module "net"] [@bs.new] external make: unit => t = "Server"; 594 | [@bs.send] 595 | external listen: (t, ~port: int, ~host: string, ~callback: unit => unit) => t = 596 | "listen"; 597 | [@bs.send] 598 | external listenWithOptions: (t, listenOptions, ~callback: unit => unit) => t = 599 | "listen"; 600 | }; 601 | 602 | module IcpServer = { 603 | type kind = [ Server.kind | icp]; 604 | type t = Server.subtype(kind); 605 | type subtype('ty) = Server.subtype([> kind] as 'ty); 606 | type supertype('ty) = Server.subtype([< kind] as 'ty); 607 | module Events = { 608 | [@bs.send] 609 | external onClose: 610 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 611 | subtype('ty) = 612 | "on"; 613 | [@bs.send] 614 | external onError: 615 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 616 | subtype('ty) = 617 | "on"; 618 | [@bs.send] 619 | external onConnection: 620 | ( 621 | subtype('ty), 622 | [@bs.as "connection"] _, 623 | [@bs.uncurry] (IcpSocket.t => unit) 624 | ) => 625 | subtype('ty) = 626 | "on"; 627 | [@bs.send] 628 | external onListening: 629 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 630 | subtype('ty) = 631 | "on"; 632 | [@bs.send] 633 | external offClose: 634 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 635 | subtype('ty) = 636 | "off"; 637 | [@bs.send] 638 | external offError: 639 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 640 | subtype('ty) = 641 | "off"; 642 | [@bs.send] 643 | external offConnection: 644 | ( 645 | subtype('ty), 646 | [@bs.as "connection"] _, 647 | [@bs.uncurry] (IcpSocket.t => unit) 648 | ) => 649 | subtype('ty) = 650 | "off"; 651 | [@bs.send] 652 | external offListening: 653 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 654 | subtype('ty) = 655 | "off"; 656 | [@bs.send] 657 | external onCloseOnce: 658 | (subtype('ty), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => 659 | subtype('ty) = 660 | "once"; 661 | [@bs.send] 662 | external onErrorOnce: 663 | (subtype('ty), [@bs.as "error"] _, [@bs.uncurry] (unit => unit)) => 664 | subtype('ty) = 665 | "once"; 666 | [@bs.send] 667 | external onConnectionOnce: 668 | ( 669 | subtype('ty), 670 | [@bs.as "connection"] _, 671 | [@bs.uncurry] (IcpSocket.t => unit) 672 | ) => 673 | subtype('ty) = 674 | "once"; 675 | [@bs.send] 676 | external onListeningOnce: 677 | (subtype('ty), [@bs.as "listening"] _, [@bs.uncurry] (unit => unit)) => 678 | subtype('ty) = 679 | "once"; 680 | }; 681 | module Impl = { 682 | include Events; 683 | [@bs.send] 684 | external close: 685 | (subtype('ty), ~callback: Js.nullable(Js.Exn.t) => unit) => 686 | subtype('ty) = 687 | "close"; 688 | [@bs.send] 689 | external getConnections: 690 | (subtype('ty), (Js.nullable(Js.Exn.t), int) => unit) => subtype('ty) = 691 | "getConnections"; 692 | [@bs.set] 693 | external setMaxConnections: (subtype('ty), int) => unit = 694 | "maxConnections"; 695 | [@bs.get] external maxConnections: subtype('ty) => int = "maxConnections"; 696 | [@bs.send] external ref: subtype('ty) => subtype('ty) = "ref"; 697 | [@bs.send] external unref: subtype('ty) => subtype('ty) = "unref"; 698 | [@bs.get] external listening: subtype('ty) => bool = "listening"; 699 | }; 700 | include Impl; 701 | type listenOptions; 702 | [@bs.obj] 703 | external listenOptions: 704 | ( 705 | ~path: string=?, 706 | ~host: string=?, 707 | ~backlog: int=?, 708 | ~exclusive: bool=?, 709 | ~readableAll: bool=?, 710 | ~writableAll: bool=?, 711 | unit 712 | ) => 713 | listenOptions; 714 | [@bs.send] 715 | external listen: (t, ~path: string, ~callback: unit => unit) => t = "listen"; 716 | [@bs.send] 717 | external listenWithOptions: 718 | (t, ~options: listenOptions, ~callback: unit => unit) => t = 719 | "listen"; 720 | }; 721 | 722 | [@bs.module "net"] [@bs.val] external isIP: string => bool = "isIP"; 723 | [@bs.module "net"] [@bs.val] external isIPv4: string => bool = "isIPv4"; 724 | [@bs.module "net"] [@bs.val] external isIPv6: string => bool = "isIPv6"; 725 | -------------------------------------------------------------------------------- /src/Os.re: -------------------------------------------------------------------------------- 1 | type cpuTimes = 2 | pri { 3 | user: int, 4 | nice: int, 5 | sys: int, 6 | idle: int, 7 | irq: int, 8 | }; 9 | type cpu = 10 | pri { 11 | model: string, 12 | speed: string, 13 | times: cpuTimes, 14 | }; 15 | [@bs.module "os"] [@bs.val] external eol: string = "EOL"; 16 | [@bs.module "os"] [@bs.val] external arch: string = "arch"; 17 | [@bs.module "os"] [@bs.val] external cpus: unit => array(cpu) = "cpus"; 18 | [@bs.module "os"] [@bs.val] external endianness: unit => string = "endianness"; 19 | [@bs.module "os"] [@bs.val] external freemem: unit => int = "freemem"; 20 | [@bs.module "os"] [@bs.val] external getPriority: int => int = "getPriority"; 21 | [@bs.module "os"] [@bs.val] external homedir: unit => string = "homedir"; 22 | [@bs.module "os"] [@bs.val] external hostname: unit => string = "hostname"; 23 | [@bs.module "os"] [@bs.val] 24 | external loadavg: unit => array(float) = "loadavg"; 25 | [@bs.module "os"] [@bs.val] external platform: unit => string = "platform"; 26 | [@bs.module "os"] [@bs.val] external release: unit => string = "release"; 27 | [@bs.module "os"] [@bs.val] 28 | external setPriority: (int, int) => unit = "setPriority"; 29 | [@bs.module "os"] [@bs.val] external tmpdir: unit => string = "tmpdir"; 30 | [@bs.module "os"] [@bs.val] external totalmem: unit => int = "totalmem"; 31 | [@bs.module "os"] [@bs.val] external type_: unit => string = "type"; 32 | [@bs.module "os"] [@bs.val] external uptime: unit => int = "uptime"; 33 | -------------------------------------------------------------------------------- /src/Path.re: -------------------------------------------------------------------------------- 1 | type t = { 2 | dir: string, 3 | root: string, 4 | base: string, 5 | name: string, 6 | ext: string, 7 | }; 8 | 9 | [@bs.module "path"] external basename: string => string = "basename"; 10 | 11 | [@bs.module "path"] 12 | external basenameExt: (string, string) => string = "basename"; 13 | 14 | [@bs.module "path"] external delimiter: string = "delimiter"; 15 | 16 | [@bs.module "path"] external dirname: string => string = "dirname"; 17 | 18 | [@bs.module "path"] external extname: string => string = "extname"; 19 | 20 | [@bs.module "path"] external format: t => string = "format"; 21 | 22 | [@bs.module "path"] external isAbsolute: string => bool = "isAbsolute"; 23 | 24 | [@bs.module "path"] [@bs.splice] 25 | external join: array(string) => string = "join"; 26 | 27 | [@bs.module "path"] external join2: (string, string) => string = "join"; 28 | 29 | [@bs.module "path"] external normalize: string => string = "normalize"; 30 | 31 | [@bs.module "path"] external parse: string => t = "parse"; 32 | 33 | [@bs.module "path"] 34 | external relative: (~from: string, ~to_: string) => string = "relative"; 35 | 36 | [@bs.module "path"] [@bs.splice] 37 | external resolve: array(string) => string = "resolve"; 38 | 39 | [@bs.module "path"] external sep: string = "sep"; 40 | 41 | [@bs.module "path"] 42 | external toNamespacedPath: string => string = "toNamespacedPath"; 43 | 44 | module Posix = { 45 | [@bs.module "path"] [@bs.scope "posix"] 46 | external basename: string => string = "basename"; 47 | 48 | [@bs.module "path"] [@bs.scope "posix"] 49 | external basenameExt: (string, string) => string = "basename"; 50 | 51 | [@bs.module "path"] [@bs.scope "posix"] 52 | external delimiter: string = "delimiter"; 53 | 54 | [@bs.module "path"] [@bs.scope "posix"] 55 | external dirname: string => string = "dirname"; 56 | 57 | [@bs.module "path"] [@bs.scope "posix"] 58 | external extname: string => string = "extname"; 59 | 60 | [@bs.module "path"] [@bs.scope "posix"] 61 | external format: t => string = "format"; 62 | 63 | [@bs.module "path"] [@bs.scope "posix"] 64 | external isAbsolute: string => bool = "isAbsolute"; 65 | 66 | [@bs.module "path"] [@bs.scope "posix"] [@bs.splice] 67 | external join: array(string) => string = "join"; 68 | 69 | [@bs.module "path"] [@bs.scope "posix"] 70 | external join2: (string, string) => string = "join"; 71 | 72 | [@bs.module "path"] [@bs.scope "posix"] 73 | external normalize: string => string = "normalize"; 74 | 75 | [@bs.module "path"] [@bs.scope "posix"] 76 | external parse: string => t = "parse"; 77 | 78 | [@bs.module "path"] [@bs.scope "posix"] 79 | external relative: (~from: string, ~to_: string) => string = "relative"; 80 | 81 | [@bs.module "path"] [@bs.scope "posix"] [@bs.splice] 82 | external resolve: array(string) => string = "resolve"; 83 | 84 | [@bs.module "path"] [@bs.scope "posix"] external sep: string = "sep"; 85 | 86 | [@bs.module "path"] [@bs.scope "posix"] 87 | external toNamespacedPath: string => string = "toNamespacedPath"; 88 | }; 89 | 90 | module Win32 = { 91 | [@bs.module "path"] [@bs.scope "win32"] 92 | external basename: string => string = "basename"; 93 | 94 | [@bs.module "path"] [@bs.scope "win32"] 95 | external basenameExt: (string, string) => string = "basename"; 96 | 97 | [@bs.module "path"] [@bs.scope "win32"] 98 | external delimiter: string = "delimiter"; 99 | 100 | [@bs.module "path"] [@bs.scope "win32"] 101 | external dirname: string => string = "dirname"; 102 | 103 | [@bs.module "path"] [@bs.scope "win32"] 104 | external extname: string => string = "extname"; 105 | 106 | [@bs.module "path"] [@bs.scope "win32"] 107 | external format: t => string = "format"; 108 | 109 | [@bs.module "path"] [@bs.scope "win32"] 110 | external isAbsolute: string => bool = "isAbsolute"; 111 | 112 | [@bs.module "path"] [@bs.scope "win32"] [@bs.splice] 113 | external join: array(string) => string = "join"; 114 | 115 | [@bs.module "path"] [@bs.scope "win32"] 116 | external join2: (string, string) => string = "join"; 117 | 118 | [@bs.module "path"] [@bs.scope "win32"] 119 | external normalize: string => string = "normalize"; 120 | 121 | [@bs.module "path"] [@bs.scope "win32"] 122 | external parse: string => t = "parse"; 123 | 124 | [@bs.module "path"] [@bs.scope "win32"] 125 | external relative: (~from: string, ~to_: string) => string = "relative"; 126 | 127 | [@bs.module "path"] [@bs.scope "win32"] [@bs.splice] 128 | external resolve: array(string) => string = "resolve"; 129 | 130 | [@bs.module "path"] [@bs.scope "win32"] external sep: string = "sep"; 131 | 132 | [@bs.module "path"] [@bs.scope "win32"] 133 | external toNamespacedPath: string => string = "toNamespacedPath"; 134 | }; 135 | -------------------------------------------------------------------------------- /src/PerfHooks.re: -------------------------------------------------------------------------------- 1 | module PerformanceEntry = { 2 | type t; 3 | [@bs.get] external duration: t => float = "duration"; 4 | [@bs.get] external name: t => string = "name"; 5 | [@bs.get] external startTime: t => float = "startTime"; 6 | [@bs.get] external entryType: t => string = "entryType"; 7 | [@bs.get] external kind: t => int = "kind"; 8 | }; 9 | 10 | module PerformanceNodeTiming = { 11 | type t; 12 | // Extends PerformanceEntry: 13 | [@bs.get] external duration: t => float = "duration"; 14 | [@bs.get] external name: t => string = "name"; 15 | [@bs.get] external startTime: t => float = "startTime"; 16 | [@bs.get] external entryType: t => string = "entryType"; 17 | [@bs.get] external kind: t => int = "kind"; 18 | // Specific to this class: 19 | [@bs.get] external bootstrapComplete: t => float = "bootstrapComplete"; 20 | [@bs.get] external clusterSetupStart: t => float = "clusterSetupStart"; 21 | [@bs.get] external clusterSetupEnd: t => float = "clusterSetupEnd"; 22 | [@bs.get] external environment: t => float = "environment"; 23 | [@bs.get] external loopStart: t => float = "loopStart"; 24 | [@bs.get] external loopExit: t => float = "loopExit"; 25 | [@bs.get] external moduleLoadStart: t => float = "moduleLoadStart"; 26 | [@bs.get] external moduleLoadEnd: t => float = "moduleLoadEnd"; 27 | [@bs.get] external nodeStart: t => float = "nodeStart"; 28 | [@bs.get] 29 | external preloadModuleLoadStart: t => float = "preloadModuleLoadStart"; 30 | [@bs.get] external preloadModuleLoadEnd: t => float = "preloadModuleLoadEnd"; 31 | [@bs.get] external thirdPartyMainStart: t => float = "thirdPartyMainStart"; 32 | [@bs.get] external thirdPartyMainEnd: t => float = "thirdPartyMainEnd"; 33 | [@bs.get] external v8Start: t => float = "v8Start"; 34 | }; 35 | 36 | module Performance = { 37 | type t; 38 | [@bs.module "perf_hooks"] external performance: t = "performance"; 39 | [@bs.send] external clearMarks: (t, unit) => unit = "clearMarks"; 40 | [@bs.send] external clearMarksByName: (t, string) => unit = "clearMarks"; 41 | [@bs.send] external mark: (t, unit) => unit = "mark"; 42 | [@bs.send] external markWithName: (t, string) => unit = "mark"; 43 | [@bs.send] 44 | external measure: (t, string, ~startMark: string, ~endMark: string) => unit = 45 | "measure"; 46 | [@bs.get] external nodeTiming: t => PerformanceNodeTiming.t = "nodeTiming"; 47 | [@bs.send] external now: t => float = "now"; 48 | [@bs.send] external timerify: (unit => unit, unit) => unit = "timerify"; 49 | [@bs.send] 50 | external timerifyU: ([@bs.uncurry] (unit => unit), unit) => unit = 51 | "timerify"; 52 | }; 53 | 54 | module Histogram = { 55 | type t; 56 | [@bs.send] external disable: (t, unit) => bool = "disable"; 57 | [@bs.send] external enable: (t, unit) => bool = "enable"; 58 | [@bs.get] external exceeds: t => float = "exceeds"; 59 | [@bs.get] external max: t => float = "max"; 60 | [@bs.get] external mean: t => float = "mean"; 61 | [@bs.get] external min: t => float = "min"; 62 | [@bs.send] external percentile: (t, int) => float = "percentile"; 63 | [@bs.send] external reset: t => unit = "reset"; 64 | [@bs.send] external stddev: t => float = "stddev"; 65 | // ES6 Map type not defined by BuckleScript as far as I can tell 66 | // [@bs.get] external percentiles: t => ES6Map.t(int, float) = "percentiles"; 67 | }; 68 | 69 | module PerformanceObserverEntryList = { 70 | type t; 71 | [@bs.send] 72 | external getEntries: t => array(PerformanceEntry.t) = "getEntries"; 73 | [@bs.send] 74 | external getEntriesByName: 75 | (t, string, Js.Nullable.t(string)) => array(PerformanceEntry.t) = 76 | "getEntriesByName"; 77 | let getEntriesByName = (entryList, ~type_=?, name) => 78 | getEntriesByName(entryList, name, Js.Nullable.fromOption(type_)); 79 | [@bs.send] 80 | external getEntriesByType: (t, string) => array(PerformanceEntry.t) = 81 | "getEntriesByType"; 82 | }; 83 | 84 | module PerformanceObserver = { 85 | type t; 86 | [@bs.module "perf_hooks"] [@bs.new] 87 | external make: ((PerformanceObserverEntryList.t, t) => unit) => t = 88 | "PerformanceObserver"; 89 | }; 90 | 91 | [@bs.module "perf_hooks"] 92 | external monitorEventLoopDelay: 93 | Js.Nullable.t({. "resolution": float}) => Histogram.t = 94 | "eventLoopDelay"; 95 | let monitorEventLoopDelay = (~resolution=?, ()) => 96 | monitorEventLoopDelay(Js.Nullable.fromOption(resolution)); 97 | -------------------------------------------------------------------------------- /src/Process.re: -------------------------------------------------------------------------------- 1 | type t; 2 | [@bs.module] external process: t = "process"; 3 | 4 | type warning = { 5 | name: string, 6 | message: string, 7 | stack: string, 8 | }; 9 | 10 | module Events = { 11 | [@bs.send] 12 | external onBeforeExit: 13 | (t, [@bs.as "beforeExit"] _, [@bs.uncurry] (int => unit)) => t = 14 | "on"; 15 | [@bs.send] 16 | external onDisconnect: 17 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 18 | "on"; 19 | [@bs.send] 20 | external onExit: (t, [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => t = 21 | "on"; 22 | [@bs.send] 23 | external onMultipleResolves: 24 | ( 25 | t, 26 | [@bs.as "multipleResolves"] _, 27 | [@bs.uncurry] ((string, Js.Promise.t('a), 'a) => unit) 28 | ) => 29 | t = 30 | "on"; 31 | [@bs.send] 32 | external onRejectionHandled: 33 | ( 34 | t, 35 | [@bs.as "rejectionHandled"] _, 36 | [@bs.uncurry] (Js.Promise.t('a) => unit) 37 | ) => 38 | t = 39 | "on"; 40 | [@bs.send] 41 | external onUncaughtException: 42 | ( 43 | t, 44 | [@bs.as "uncaughtException"] _, 45 | [@bs.uncurry] ((Js.Exn.t, string) => unit) 46 | ) => 47 | t = 48 | "on"; 49 | [@bs.send] 50 | external onUnhandledRejection: 51 | ( 52 | t, 53 | [@bs.as "unhandledRejection"] _, 54 | [@bs.uncurry] ((Js.Exn.t, Js.Promise.t('a)) => unit) 55 | ) => 56 | t = 57 | "on"; 58 | [@bs.send] 59 | external onWarning: 60 | (t, [@bs.as "warning"] _, [@bs.uncurry] (warning => unit)) => t = 61 | "on"; 62 | 63 | [@bs.send] 64 | external offBeforeExit: 65 | (t, [@bs.as "beforeExit"] _, [@bs.uncurry] (int => unit)) => t = 66 | "off"; 67 | [@bs.send] 68 | external offDisconnect: 69 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 70 | "off"; 71 | [@bs.send] 72 | external offExit: (t, [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => t = 73 | "off"; 74 | [@bs.send] 75 | external offMultipleResolves: 76 | ( 77 | t, 78 | [@bs.as "multipleResolves"] _, 79 | [@bs.uncurry] ((string, Js.Promise.t('a), 'a) => unit) 80 | ) => 81 | t = 82 | "off"; 83 | [@bs.send] 84 | external offRejectionHandled: 85 | ( 86 | t, 87 | [@bs.as "rejectionHandled"] _, 88 | [@bs.uncurry] (Js.Promise.t('a) => unit) 89 | ) => 90 | t = 91 | "off"; 92 | [@bs.send] 93 | external offUncaughtException: 94 | ( 95 | t, 96 | [@bs.as "uncaughtException"] _, 97 | [@bs.uncurry] ((Js.Exn.t, string) => unit) 98 | ) => 99 | t = 100 | "off"; 101 | [@bs.send] 102 | external offUnhandledRejection: 103 | ( 104 | t, 105 | [@bs.as "unhandledRejection"] _, 106 | [@bs.uncurry] ((Js.Exn.t, Js.Promise.t('a)) => unit) 107 | ) => 108 | t = 109 | "off"; 110 | [@bs.send] 111 | external offWarning: 112 | (t, [@bs.as "warning"] _, [@bs.uncurry] (warning => unit)) => t = 113 | "off"; 114 | 115 | [@bs.send] 116 | external onBeforeExitOnce: 117 | (t, [@bs.as "beforeExit"] _, [@bs.uncurry] (int => unit)) => t = 118 | "once"; 119 | [@bs.send] 120 | external onDisconnectOnce: 121 | (t, [@bs.as "disconnect"] _, [@bs.uncurry] (unit => unit)) => t = 122 | "once"; 123 | [@bs.send] 124 | external onExitOnce: 125 | (t, [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => unit = 126 | "once"; 127 | [@bs.send] 128 | external onMultipleResolvesOnce: 129 | ( 130 | t, 131 | [@bs.as "multipleResolves"] _, 132 | [@bs.uncurry] ((string, Js.Promise.t('a), 'a) => unit) 133 | ) => 134 | t = 135 | "once"; 136 | [@bs.send] 137 | external onRejectionHandledOnce: 138 | ( 139 | t, 140 | [@bs.as "rejectionHandled"] _, 141 | [@bs.uncurry] (Js.Promise.t('a) => unit) 142 | ) => 143 | t = 144 | "once"; 145 | [@bs.send] 146 | external onUncaughtExceptionOnce: 147 | ( 148 | t, 149 | [@bs.as "uncaughtException"] _, 150 | [@bs.uncurry] ((Js.Exn.t, string) => unit) 151 | ) => 152 | t = 153 | "once"; 154 | [@bs.send] 155 | external onUnhandledRejectionOnce: 156 | ( 157 | t, 158 | [@bs.as "unhandledRejection"] _, 159 | [@bs.uncurry] ((Js.Exn.t, Js.Promise.t('a)) => unit) 160 | ) => 161 | t = 162 | "once"; 163 | [@bs.send] 164 | external onWarningOnce: 165 | (t, [@bs.as "warning"] _, [@bs.uncurry] (warning => unit)) => t = 166 | "once"; 167 | 168 | [@bs.send] external removeAllListeners: t => t = "removeAllListeners"; 169 | }; 170 | include Events; 171 | 172 | [@bs.send] external abort: t => unit = "abort"; 173 | [@bs.get] external argv: t => array(string) = "argv"; 174 | [@bs.get] external argv0: t => string = "argv0"; 175 | [@bs.send] external chdir: (t, string) => unit = "chdir"; 176 | [@bs.send] external cwd: t => string = "cwd"; 177 | [@bs.send] external disconnect: t => unit = "disconnect"; 178 | [@bs.get] external env: t => Js.Dict.t(string) = "env"; 179 | [@bs.get] external execArgv: t => array(string) = "execArgv"; 180 | [@bs.get] external execPath: t => string = "execPath"; 181 | [@bs.send] external exit: (t, unit) => unit = "exit"; 182 | [@bs.send] external exitWithCode: (t, int) => unit = "exit"; 183 | [@bs.get] external exitCode: t => int = "exitCode"; 184 | [@bs.send] 185 | external nextTick: (t, [@bs.uncurry] (unit => unit)) => unit = "nextTick"; 186 | [@bs.send] 187 | external nextTickApply1: (t, [@bs.uncurry] ('a => unit), 'a) => unit = 188 | "nextTick"; 189 | [@bs.send] 190 | external nextTickApply2: (t, [@bs.uncurry] (('a, 'b) => unit), 'a, 'b) => unit = 191 | "nextTick"; 192 | [@bs.send] 193 | external nextTickApply3: 194 | (t, [@bs.uncurry] (('a, 'b, 'c) => unit), 'a, 'b, 'c) => unit = 195 | "nextTick"; 196 | [@bs.send] 197 | external nextTickApply4: 198 | (t, [@bs.uncurry] (('a, 'b, 'c, 'd) => unit), 'a, 'b, 'c, 'd) => unit = 199 | "nextTick"; 200 | [@bs.send] 201 | external nextTickApply5: 202 | (t, [@bs.uncurry] (('a, 'b, 'c, 'd, 'e) => unit), 'a, 'b, 'c, 'd, 'e) => unit = 203 | "nextTick"; 204 | [@bs.send] external hrtime: t => (int, int) = "hrtime"; 205 | [@bs.send] [@bs.scope "hrtime"] 206 | external hrtimeBigInt: t => BigInt.t = "bigint"; 207 | [@bs.get] external stderr: t => Stream.Writable.t(Buffer.t) = "stderr"; 208 | [@bs.get] external stdin: t => Stream.Readable.t(Buffer.t) = "stdin"; 209 | [@bs.get] external stdout: t => Stream.Writable.t(Buffer.t) = "stdout"; 210 | [@bs.get] external pid: t => int = "pid"; 211 | [@bs.get] external platform: t => string = "platform"; 212 | [@bs.get] external ppid: t => int = "ppid"; 213 | [@bs.get] external uptime: t => float = "uptime"; 214 | [@bs.get] external title: t => string = "title"; 215 | [@bs.get] external version: t => string = "version"; 216 | [@bs.get] external versions: t => Js.Dict.t(string) = "versions"; 217 | type memoryUsageStats = { 218 | [@bs.as "rss"] 219 | rss: int, 220 | [@bs.as "heapTotal"] 221 | heapTotal: int, 222 | [@bs.as "heapUsed"] 223 | heapUsed: int, 224 | [@bs.as "external"] 225 | external_: int, 226 | [@bs.as "arrayBuffers"] 227 | arrayBuffers: int, 228 | }; 229 | [@bs.send] external memoryUsage: t => memoryUsageStats = "memoryUsage"; 230 | -------------------------------------------------------------------------------- /src/QueryString.re: -------------------------------------------------------------------------------- 1 | type t = string; 2 | 3 | [@bs.module "querystring"] 4 | external parse: string => Js.Dict.t(string) = "parse"; 5 | [@bs.module "querystring"] 6 | external decode: string => Js.Dict.t(string) = "decode"; 7 | [@bs.module "querystring"] 8 | external stringify: Js.Dict.t(string) => string = "stringify"; 9 | -------------------------------------------------------------------------------- /src/Readline.re: -------------------------------------------------------------------------------- 1 | module Interface = { 2 | type t; 3 | type interfaceOptions; 4 | [@bs.obj] 5 | external interfaceOptions: 6 | ( 7 | ~input: Stream.Readable.subtype(Buffer.t, 'rtype), 8 | ~output: Stream.Writable.subtype(Buffer.t, 'wtype)=?, 9 | ~completer: (string, (string, (array(string), string)) => unit) => unit 10 | =?, 11 | ~terminal: bool=?, 12 | ~historySize: int=?, 13 | ~prompt: string=?, 14 | ~crlfDelay: int=?, 15 | ~removeHistoryDuplicates: bool=?, 16 | ~escapeCodeTimeout: int=?, 17 | unit 18 | ) => 19 | interfaceOptions; 20 | [@bs.send] external make: (t, interfaceOptions) => t = "createInterface"; 21 | [@bs.send] external close: t => unit = "close"; 22 | [@bs.send] external pause: t => unit = "pause"; 23 | [@bs.send] external prompt: (t, Js.nullable(bool)) => unit = "prompt"; 24 | [@bs.send] 25 | external question: (t, string, string => unit) => unit = "question"; 26 | [@bs.send] external resume: t => unit = "resume"; 27 | [@bs.send] external setPrompt: (t, string) => unit = "setPrompt"; 28 | [@bs.send] external write: (t, string) => unit = "write"; 29 | type keyOptions; 30 | [@bs.obj] 31 | external keyOptions: 32 | (~ctrl: bool=?, ~meta: bool=?, ~shift: bool=?, ~name: string=?) => 33 | keyOptions; 34 | [@bs.send] 35 | external writeKey: (t, Js.Null.t(string), keyOptions) => unit = "write"; 36 | [@bs.send] 37 | external writeKey2: 38 | ( 39 | t, 40 | Js.Null.t(string), 41 | { 42 | . 43 | "ctrl": option(bool), 44 | "meta": option(bool), 45 | "shift": option(bool), 46 | "name": option(string), 47 | } 48 | ) => 49 | unit = 50 | "write"; 51 | [@bs.get] [@bs.return nullable] external line: t => option(string) = "line"; 52 | [@bs.get] [@bs.return nullable] 53 | external cursor: t => option(int) = "cursor"; 54 | [@bs.send] 55 | external clearLine: (t, Stream.Writable.subtype(Buffer.t, 'ty), int) => bool = 56 | "clearLine"; 57 | [@bs.send] 58 | external clearScreenDown: 59 | (t, Stream.Writable.subtype(Buffer.t, 'ty), unit => unit) => bool = 60 | "clearScreenDown"; 61 | [@bs.send] 62 | external cursorTo: 63 | ( 64 | t, 65 | Stream.Writable.subtype(Buffer.t, 'ty), 66 | int, 67 | Js.Undefined.t(int), 68 | Js.Undefined.t(unit => unit) 69 | ) => 70 | bool = 71 | "cursorTo"; 72 | [@bs.send] 73 | external moveCursor: 74 | ( 75 | t, 76 | Stream.Writable.subtype(Buffer.t, 'ty), 77 | int, 78 | int, 79 | Js.Undefined.t(unit => unit) 80 | ) => 81 | bool = 82 | "moveCursor"; 83 | }; -------------------------------------------------------------------------------- /src/StringBuffer.re: -------------------------------------------------------------------------------- 1 | type t; 2 | 3 | external string: string => t = "%identity"; 4 | external buffer: Buffer.t => t = "%identity"; 5 | 6 | type case = 7 | | String(string) 8 | | Buffer(Buffer.t); 9 | 10 | let classifyOpt = value => 11 | if (Js.typeof(value) === "string") { 12 | Some(String(Obj.magic(value))); 13 | } else if (Buffer.isBuffer(value)) { 14 | Some(Buffer(Obj.magic(value))); 15 | } else { 16 | None; 17 | }; 18 | 19 | let classifyExn = value => 20 | if (Js.typeof(value) === "string") { 21 | String(Obj.magic(value)); 22 | } else if (Buffer.isBuffer(value)) { 23 | Buffer(Obj.magic(value)); 24 | } else { 25 | failwith("Unknown data type"); 26 | }; 27 | 28 | let classify = value => 29 | if (Js.typeof(value) === "string") { 30 | Ok(String(Obj.magic(value))); 31 | } else if (Buffer.isBuffer(value)) { 32 | Ok(Buffer(Obj.magic(value))); 33 | } else { 34 | Error(value); 35 | }; 36 | -------------------------------------------------------------------------------- /src/StringDecoder.re: -------------------------------------------------------------------------------- 1 | type t; 2 | [@bs.new] [@bs.module "string_decoder"] 3 | external make: StringEncoding.t => t = "StringDecoder"; 4 | [@bs.send] external end_: t => string = "end"; 5 | [@bs.send] external writeEnd: (t, Buffer.t) => string = "end"; 6 | [@bs.send] external write: (t, Buffer.t) => string = "write"; 7 | -------------------------------------------------------------------------------- /src/StringEncoding.re: -------------------------------------------------------------------------------- 1 | module Impl: { 2 | type t = pri string; 3 | [@bs.inline "ascii"] 4 | let ascii: t; 5 | [@bs.inline "utf8"] 6 | let utf8: t; 7 | [@bs.inline "utf16le"] 8 | let utf16le: t; 9 | [@bs.inline "usc2"] 10 | let usc2: t; 11 | [@bs.inline "base64"] 12 | let base64: t; 13 | [@bs.inline "latin1"] 14 | let latin1: t; 15 | [@bs.inline "binary"] 16 | let binary: t; 17 | [@bs.inline "hex"] 18 | let hex: t; 19 | } = { 20 | type t = string; 21 | [@bs.inline "ascii"] 22 | let ascii = "ascii"; 23 | [@bs.inline "utf8"] 24 | let utf8 = "utf8"; 25 | [@bs.inline "utf16le"] 26 | let utf16le = "utf16le"; 27 | [@bs.inline "usc2"] 28 | let usc2 = "usc2"; 29 | [@bs.inline "base64"] 30 | let base64 = "base64"; 31 | [@bs.inline "latin1"] 32 | let latin1 = "latin1"; 33 | [@bs.inline "binary"] 34 | let binary = "binary"; 35 | [@bs.inline "hex"] 36 | let hex = "hex"; 37 | }; 38 | 39 | include Impl; 40 | -------------------------------------------------------------------------------- /src/Timers.re: -------------------------------------------------------------------------------- 1 | module Immediate = { 2 | type t; 3 | [@bs.send] external hasRef: t => bool = "hasRef"; 4 | [@bs.send] external ref: t => t = "ref"; 5 | [@bs.send] external unref: t => t = "unref"; 6 | }; 7 | 8 | module Timeout = { 9 | type t; 10 | [@bs.send] external hasRef: t => bool = "hasRef"; 11 | [@bs.send] external ref: t => t = "ref"; 12 | [@bs.send] external refresh: t => t = "refresh"; 13 | [@bs.send] external unref: t => t = "unref"; 14 | }; 15 | 16 | [@bs.val] 17 | external setImmediate: (unit => unit) => Immediate.t = "setImmediate"; 18 | [@bs.val] external setTimeout: (unit => unit, int) => Timeout.t = "setTimeout"; 19 | [@bs.val] 20 | external setInterval: (unit => unit, int) => Timeout.t = "setInterval"; 21 | [@bs.val] external clearImmediate: Immediate.t => unit = "clearImmediate"; 22 | [@bs.val] external clearTimeout: Timeout.t => unit = "clearTimeout"; 23 | [@bs.val] external clearInterval: Timeout.t => unit = "clearInterval"; 24 | -------------------------------------------------------------------------------- /src/Tls.re: -------------------------------------------------------------------------------- 1 | type tls = [ | `Tls]; 2 | 3 | module TlsSocket = { 4 | type kind('w, 'r) = [ Net.Socket.kind('w, 'r) | tls]; 5 | type subtype('w, 'r, 'ty) = Stream.subtype([> kind('w, 'r)] as 'ty); 6 | type supertype('w, 'r, 'ty) = Stream.subtype([< kind('w, 'r)] as 'ty); 7 | type t = Stream.subtype(kind(Buffer.t, Buffer.t)); 8 | module Events = { 9 | include Net.TcpSocket.Events; 10 | }; 11 | module Impl = { 12 | include Net.TcpSocket.Impl; 13 | include Events; 14 | }; 15 | include Impl; 16 | }; 17 | 18 | module TlsServer = { 19 | type kind = [ Net.Server.kind | tls]; 20 | type subtype('ty) = Net.Server.subtype([> kind] as 'ty); 21 | type supertype('ty) = Net.Server.subtype([< kind] as 'ty); 22 | type t = Net.Server.subtype(kind); 23 | module Events = { 24 | include Net.TcpServer.Events; 25 | }; 26 | module Impl = { 27 | include Net.TcpServer.Impl; 28 | include Events; 29 | }; 30 | include Impl; 31 | }; 32 | -------------------------------------------------------------------------------- /src/Tty.re: -------------------------------------------------------------------------------- 1 | type tty = [ | `Tty]; 2 | 3 | module ReadStream = { 4 | type kind('r) = [ Stream.readable('r) | tty]; 5 | type subtype('r, 'ty) = Stream.subtype([> kind('r)] as 'ty); 6 | type supertype('r, 'ty) = Stream.subtype([< kind('r)] as 'ty); 7 | type t = Stream.subtype(kind(Buffer.t)); 8 | module Events = { 9 | include Stream.Readable.Events; 10 | }; 11 | module Impl = { 12 | include Stream.Readable.Impl; 13 | [@bs.get] external isRaw: t => bool = "isRaw"; 14 | [@bs.get] external isTTY: t => bool = "isTTY"; 15 | [@bs.send] external setRawMode: (t, bool) => t = "setRawMode"; 16 | external unsafeCoerceToSocket: t => Net.Socket.t = "%identity"; 17 | external unsafeCoerceFromSocket: Net.Socket.t => t = "%identity"; 18 | external unsafeCoerceToReadable: t => Stream.Readable.t(Buffer.t) = 19 | "%identity"; 20 | external unsafeCoerceFromReadable: Stream.Readable.t(Buffer.t) => t = 21 | "%identity"; 22 | }; 23 | include Events; 24 | include Impl; 25 | }; 26 | 27 | module WriteStream = { 28 | type kind('w) = [ Stream.writable('w) | tty]; 29 | type subtype('w, 'ty) = Stream.subtype([> kind('w)] as 'ty); 30 | type supertype('w, 'ty) = Stream.subtype([< kind('w)] as 'ty); 31 | type t = Stream.subtype(kind(Buffer.t)); 32 | module Events = { 33 | include Stream.Writable.Events; 34 | [@bs.send] 35 | external onResize: 36 | (subtype('w, 'ty), [@bs.as "resize"] _, [@bs.uncurry] (unit => unit)) => 37 | unit = 38 | "on"; 39 | [@bs.send] 40 | external offResize: 41 | (subtype('w, 'ty), [@bs.as "resize"] _, [@bs.uncurry] (unit => unit)) => 42 | unit = 43 | "off"; 44 | [@bs.send] 45 | external onResizeOnce: 46 | (subtype('w, 'ty), [@bs.as "resize"] _, [@bs.uncurry] (unit => unit)) => 47 | unit = 48 | "once"; 49 | }; 50 | 51 | module Impl = { 52 | include Stream.Writable.Impl; 53 | [@bs.send] 54 | external clearLineLeft: 55 | (t, [@bs.as {json|-1|json}] _, [@bs.uncurry] (unit => unit), unit) => 56 | bool = 57 | "clearLine"; 58 | [@bs.send] 59 | external clearLineRight: 60 | (t, [@bs.as {json|1|json}] _, [@bs.uncurry] (unit => unit), unit) => bool = 61 | "clearLine"; 62 | [@bs.send] 63 | external clearLine: 64 | (t, [@bs.as {json|0|json}] _, [@bs.uncurry] (unit => unit), unit) => bool = 65 | "clearLine"; 66 | [@bs.send] 67 | external clearScreenDown: (t, [@bs.uncurry] (unit => unit), unit) => bool = 68 | "clearScreenDown"; 69 | [@bs.get] external columns: t => int = "columns"; 70 | [@bs.send] external getColorDepth: t => int = "getColorDepth"; 71 | [@bs.send] 72 | external getColorDepthFromEnv: (t, Js.Dict.t('ty)) => int = 73 | "getColorDepth"; 74 | [@bs.send] external getWindowSize: t => (int, int) = "getWindowSize"; 75 | [@bs.send] external hasColors: (t, int) => bool = "hasColors"; 76 | [@bs.send] 77 | external hasColorsFromEnv: (t, int, Js.Dict.t('ty)) => bool = "hasColors"; 78 | [@bs.send] external hasAtLeast16Colors: t => bool = "hasColors"; 79 | [@bs.send] 80 | external moveCursor: 81 | (t, int, int, [@bs.uncurry] (unit => unit)) => bool = 82 | "moveCursor"; 83 | [@bs.get] external rows: t => int = "rows"; 84 | [@bs.get] external isTTY: t => bool = "isTTY"; 85 | external unsafeCoerceToSocket: t => Net.Socket.t = "%identity"; 86 | external unsafeCoerceFromSocket: Net.Socket.t => t = "%identity"; 87 | external unsafeCoerceToWritable: t => Stream.Writable.t(Buffer.t) = 88 | "%identity"; 89 | external unsafeCoerceFromWritable: Stream.Writable.t(Buffer.t) => t = 90 | "%identity"; 91 | }; 92 | include Events; 93 | include Impl; 94 | }; 95 | 96 | [@bs.module "tty"] external isatty: Fs.fd => bool = "isatty"; 97 | 98 | -------------------------------------------------------------------------------- /src/Url.re: -------------------------------------------------------------------------------- 1 | module SearchParams = { 2 | type t = { 3 | [@bs.as "append"] 4 | append: (~name: string, ~value: string) => unit, 5 | [@bs.as "delete"] 6 | delete: string => unit, 7 | [@bs.as "forEach"] 8 | forEach: 9 | ((~value: string, ~name: string=?, ~searchParams: t=?) => unit) => unit, 10 | [@bs.as "get"] 11 | get: string => Js.Null.t(string), 12 | [@bs.as "getAll"] 13 | getAll: string => array(string), 14 | [@bs.as "has"] 15 | has: string => bool, 16 | [@bs.as "set"] 17 | set: (~name: string, ~value: string) => unit, 18 | [@bs.as "sort"] 19 | sort: unit => unit, 20 | [@bs.as "toString"] 21 | toString: unit => string, 22 | // [@bs.as "[Symbol.iterator]"] iteratorSymbol: unit => iterator, // no type definition for 'iterator' 23 | // [@bs.as "values"] values: unit => iterator, // no type definition for 'iterator' 24 | // [@bs.as "entries"] entries: unit => iterator, // no type definition for 'iterator' 25 | // [@bs.as "keys"] keys: unit => iterator, // no type definition for 'iterator' 26 | }; 27 | [@bs.new] external empty: unit => t = "URLSearchParams"; 28 | [@bs.new] external fromString: string => t = "URLSearchParams"; 29 | [@bs.new] external fromDict: Js.Dict.t(string) => t = "URLSearchParams"; 30 | // [@bs.new] external fromIterable: iterable => t = "URLSearchParams"; // no type definition for 'iterator' 31 | }; 32 | 33 | type t = { 34 | hash: string, 35 | host: string, 36 | hostname: string, 37 | href: string, 38 | origin: string, 39 | password: string, 40 | pathname: string, 41 | port: int, 42 | protocol: string, 43 | search: string, 44 | searchParams: SearchParams.t, 45 | username: string, 46 | toString: unit => string, 47 | toJson: unit => Js.Json.t, 48 | }; 49 | 50 | [@bs.module "url"] [@bs.new] external make: string => t = "URL"; 51 | [@bs.module "url"] [@bs.new] 52 | external fromBaseString: (~input: string, ~base: string) => t = "URL"; 53 | [@bs.module "url"] [@bs.new] 54 | external fromBaseUrl: (~input: string, ~base: t) => t = "URL"; 55 | 56 | [@bs.module "url"] external domainToASCII: string => string = "domainToASCII"; 57 | [@bs.module "url"] 58 | external domainToUnicode: string => string = "domainToUnicode"; 59 | [@bs.module "url"] external fileURLToPath: t => string = "fileURLToPath"; 60 | [@bs.module "url"] 61 | external fileStringToPath: string => string = "fileURLToPath"; 62 | 63 | type urlFormatOptions = { 64 | . 65 | "auth": bool, 66 | "fragment": bool, 67 | "search": bool, 68 | "unicode": bool, 69 | }; 70 | 71 | [@bs.module "url"] 72 | external format: 73 | ( 74 | t, 75 | { 76 | . 77 | "auth": Js.Nullable.t(bool), 78 | "fragment": Js.Nullable.t(bool), 79 | "search": Js.Nullable.t(bool), 80 | "unicode": Js.Nullable.t(bool), 81 | } 82 | ) => 83 | string = 84 | "format"; 85 | let format = (~auth=?, ~fragment=?, ~search=?, ~unicode=?, url) => 86 | format( 87 | url, 88 | { 89 | "auth": Js.Nullable.fromOption(auth), 90 | "fragment": Js.Nullable.fromOption(fragment), 91 | "search": Js.Nullable.fromOption(search), 92 | "unicode": Js.Nullable.fromOption(unicode), 93 | }, 94 | ); 95 | 96 | [@bs.module "url"] external pathToFileURL: string => t = "pathToFileURL"; 97 | -------------------------------------------------------------------------------- /src/Util.re: -------------------------------------------------------------------------------- 1 | [@bs.module "util"] 2 | external getSystemErrorName: int => string = "getSystemErrorName"; 3 | 4 | type inspectOptions; 5 | [@bs.obj] 6 | external inspectOptions: 7 | ( 8 | ~showHidden: bool=?, 9 | ~depth: int=?, 10 | ~colors: bool=?, 11 | ~customInspect: bool=?, 12 | ~showProxy: bool=?, 13 | ~maxArrayLength: int=?, 14 | ~breakLength: int=?, 15 | ~compact: bool=?, 16 | ~sorted: bool=?, 17 | ~getters: bool=?, 18 | unit 19 | ) => 20 | inspectOptions; 21 | 22 | module Types = { 23 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 24 | external isAnyArrayBuffer: 'a => bool = "isAnyArrayBuffer"; 25 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 26 | external isArgumentsObject: 'a => bool = "isArgumentsObject"; 27 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 28 | external isAsyncFunction: 'a => bool = "isAsyncFunction"; 29 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 30 | external isBigInt64Array: 'a => bool = "isBigInt64Array"; 31 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 32 | external isBigUint64Array: 'a => bool = "isBigUint64Array"; 33 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 34 | external isBooleanObject: 'a => bool = "isBooleanObject"; 35 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 36 | external isBoxedPrimitive: 'a => bool = "isBoxedPrimitive"; 37 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 38 | external isDataView: 'a => bool = "isDataView"; 39 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 40 | external isDate: 'a => bool = "isDate"; 41 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 42 | external isExternal: 'a => bool = "isExternal"; 43 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 44 | external isFloat32Array: 'a => bool = "isFloat32Array"; 45 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 46 | external isFloat64Array: 'a => bool = "isFloat64Array"; 47 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 48 | external isGeneratorObject: 'a => bool = "isGeneratorObject"; 49 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 50 | external isInt8Array: 'a => bool = "isInt8Array"; 51 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 52 | external isInt16Array: 'a => bool = "isInt16Array"; 53 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 54 | external isInt32Array: 'a => bool = "isInt32Array"; 55 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 56 | external isMap: 'a => bool = "isMap"; 57 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 58 | external isMapIterator: 'a => bool = "isMapIterator"; 59 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 60 | external isModuleNamespaceObject: 'a => bool = "isModuleNamespaceObject"; 61 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 62 | external isNumberObject: 'a => bool = "isNumberObject"; 63 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 64 | external isPromise: 'a => bool = "isPromise"; 65 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 66 | external isProxy: 'a => bool = "isProxy"; 67 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 68 | external isRegExp: 'a => bool = "isRegExp"; 69 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 70 | external isSet: 'a => bool = "isSet"; 71 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 72 | external isSetIterator: 'a => bool = "isSetIterator"; 73 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 74 | external isSharedArrayBuffer: 'a => bool = "isSharedArrayBuffer"; 75 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 76 | external isStringObject: 'a => bool = "isStringObject"; 77 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 78 | external isSymbolObject: 'a => bool = "isSymbolObject"; 79 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 80 | external isUint8Array: 'a => bool = "isUint8Array"; 81 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 82 | external isUint8ClampedArray: 'a => bool = "isUint8ClampedArray"; 83 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 84 | external isUint16Array: 'a => bool = "isUint16Array"; 85 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 86 | external isUint32Array: 'a => bool = "isUint32Array"; 87 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 88 | external isWeakMap: 'a => bool = "isWeakMap"; 89 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 90 | external isWeakSet: 'a => bool = "isWeakSet"; 91 | [@bs.val] [@bs.module "util"] [@bs.scope "types"] 92 | external isWebAssemblyCompiledModule: 'a => bool = 93 | "isWebAssemblyCompiledModule"; 94 | }; 95 | -------------------------------------------------------------------------------- /src/V8.re: -------------------------------------------------------------------------------- 1 | [@bs.module "v8"] 2 | external cachedDataVersionTag: unit => int = "cachedDataVersion"; 3 | 4 | type heapSpaceStats = { 5 | [@bs.as "space_name"] 6 | space_name: string, 7 | [@bs.as "space_size"] 8 | space_size: int, 9 | [@bs.as "space_used_size"] 10 | space_used_size: int, 11 | [@bs.as "space_available_size"] 12 | space_available_size: int, 13 | [@bs.as "space_physical_size"] 14 | space_physical_size: int, 15 | }; 16 | 17 | [@bs.module "v8"] 18 | external getHeapSpaceStatistics: unit => array(heapSpaceStats) = 19 | "getHeapSpaceStatistics"; 20 | 21 | [@bs.module "v8"] 22 | external getHeapSnapshot: unit => Stream.Readable.t(Buffer.t) = 23 | "getHeapSnapshot"; 24 | 25 | type heapStats = { 26 | [@bs.as "total_heap_size_executable"] 27 | total_heap_size_executable: int, 28 | [@bs.as "total_physical_size"] 29 | total_physical_size: int, 30 | [@bs.as "total_available_size"] 31 | total_available_size: int, 32 | [@bs.as "used_heap_space"] 33 | used_heap_space: int, 34 | [@bs.as "heap_size_limit"] 35 | heap_size_limit: int, 36 | [@bs.as "malloced_memory"] 37 | malloced_memory: int, 38 | [@bs.as "peak_malloced_memory"] 39 | peak_malloced_memory: int, 40 | [@bs.as "does_zap_garbage"] 41 | does_zap_garbage: int, 42 | [@bs.as "number_of_native_contexts"] 43 | number_of_native_contexts: int, 44 | [@bs.as "number_of_detached_contexts"] 45 | number_of_detached_contexts: int, 46 | }; 47 | 48 | [@bs.module "v8"] 49 | external getHeapStatistics: unit => heapStats = "getHeapStatistics"; 50 | 51 | type heapCodeStats = { 52 | [@bs.as "code_and_metadata_size"] 53 | code_and_metadata_size: int, 54 | [@bs.as "bytecode_and_metadata_size"] 55 | bytecode_and_metadata_size: int, 56 | [@bs.as "external_script_source_size"] 57 | external_script_source_size: int, 58 | }; 59 | 60 | [@bs.module "v8"] 61 | external getHeapCodeStatistics: unit => heapStats = "getHeapCodeStatistics"; 62 | 63 | [@bs.module "v8"] 64 | external writeHeapSnapshot: string => Js.Json.t = "writeHeapSnapshot"; 65 | 66 | [@bs.module "v8"] external serialize: 'a => Buffer.t = "serialize"; 67 | [@bs.module "v8"] external deserialize: Buffer.t => 'a = "deserialize"; 68 | -------------------------------------------------------------------------------- /src/VM.re: -------------------------------------------------------------------------------- 1 | type contextifiedObject('a); 2 | 3 | type createContextOptions; 4 | [@bs.obj] 5 | external createContextOptions: 6 | ( 7 | ~name: string=?, 8 | ~origin: string=?, 9 | ~codeGeneration: { 10 | . 11 | "strings": bool, 12 | "wasm": bool, 13 | } 14 | =? 15 | ) => 16 | createContextOptions; 17 | [@bs.val] [@bs.module "vm"] 18 | external createContext: Js.t({..} as 'a) => contextifiedObject('a) = 19 | "createContext"; 20 | [@bs.val] [@bs.module "vm"] 21 | external createContextWithOptions: 22 | (Js.t({..} as 'a), createContextOptions) => contextifiedObject('a) = 23 | "createContext"; 24 | 25 | module Script = { 26 | type t; 27 | type makeOptions; 28 | [@bs.obj] 29 | external makeOptions: 30 | ( 31 | ~filename: string=?, 32 | ~lineOffset: int=?, 33 | ~columnOffset: int=?, 34 | ~cachedData: Buffer.t=?, 35 | ~produceCachedData: bool=? 36 | ) => 37 | makeOptions; 38 | [@bs.new] [@bs.module "vm"] external make: string => t = "Script"; 39 | [@bs.new] [@bs.module "vm"] 40 | external makeWithOptions: (string, makeOptions) => t = "Script"; 41 | [@bs.send] external createCachedData: t => Buffer.t = "createCachedData"; 42 | [@bs.send] 43 | external runInContext: (t, string, contextifiedObject('a)) => 'b = 44 | "runInContext"; 45 | [@bs.send] 46 | external runInNewContext: (t, string, contextifiedObject('a)) => 'b = 47 | "runInNewContext"; 48 | [@bs.send] external runInThisContext: (t, string) => 'a = "runInThisContext"; 49 | }; 50 | -------------------------------------------------------------------------------- /src/WorkerThreads.re: -------------------------------------------------------------------------------- 1 | /** 2 | * TODO: 3 | * 4 | * Not sure if the functor approach is the best way to use this module. But it 5 | * does allow us to "lock in" the data types we want to use across contexts. 6 | * There may be some other issues with this implementaiton due to a naive 7 | * understanding of how data is passed/shared. 8 | * 9 | * We should revisit this with concrete tests to determine the best design. 10 | */ 11 | module MessagePort = { 12 | type t('a); 13 | [@bs.send] 14 | external onClose: 15 | (t('a), [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => t('a) = 16 | "on"; 17 | [@bs.send] 18 | external onMessage: 19 | (t('a), [@bs.as "message"] _, [@bs.uncurry] ('a => unit)) => t('a) = 20 | "on"; 21 | [@bs.send] external close: t('a) => unit = "close"; 22 | [@bs.send] external postMessage: (t('a), 'a) => unit = "postMessage"; 23 | [@bs.send] external ref: t('a) => unit = "ref"; 24 | [@bs.send] external start: t('a) => unit = "start"; 25 | [@bs.send] external unref: t('a) => unit = "unref"; 26 | 27 | module WithMessageType = (T: {type message;}) => { 28 | type nonrec t = t(T.message); 29 | [@bs.send] 30 | external onClose: 31 | (t, [@bs.as "close"] _, [@bs.uncurry] (unit => unit)) => t = 32 | "on"; 33 | [@bs.send] 34 | external onMessage: 35 | (t, [@bs.as "message"] _, [@bs.uncurry] (T.message => unit)) => t = 36 | "on"; 37 | [@bs.send] external close: t => unit = "close"; 38 | [@bs.send] external postMessage: (t, T.message) => unit = "postMessage"; 39 | [@bs.send] external ref: t => unit = "ref"; 40 | [@bs.send] external start: t => unit = "start"; 41 | [@bs.send] external unref: t => unit = "unref"; 42 | }; 43 | }; 44 | 45 | module MessageChannel = { 46 | type t('message1, 'message2); 47 | [@bs.module "worker_threads"] [@bs.new] 48 | external make: unit => t('message1, 'message2) = "MessageChannel"; 49 | [@bs.get] 50 | external port1: t('message1, 'message2) => MessagePort.t('message1) = 51 | "port1"; 52 | [@bs.get] 53 | external port2: t('message1, 'message2) => MessagePort.t('message2) = 54 | "port2"; 55 | 56 | module WithMessageTypes = (T: { 57 | type message1; 58 | type message2; 59 | }) => { 60 | type nonrec t = t(T.message1, T.message2); 61 | [@bs.module "worker_threads"] [@bs.new] 62 | external make: unit => t = "MessageChannel"; 63 | [@bs.get] external port1: t => MessagePort.t(T.message1) = "port1"; 64 | [@bs.get] external port2: t => MessagePort.t(T.message2) = "port2"; 65 | }; 66 | }; 67 | 68 | type workerResourceLimits = { 69 | [@bs.as "maxYoungGenerationSizeMb"] 70 | maxYoungGenerationSizeMb: int, 71 | [@bs.as "maxOldGenerationSizeMb"] 72 | maxOldGenerationSizeMb: int, 73 | [@bs.as "codeRangeSizeMb"] 74 | codeRangeSizeMb: int, 75 | }; 76 | 77 | module Worker = { 78 | type t('a); 79 | 80 | type makeOptions('a); 81 | [@bs.obj] 82 | external makeOptions: 83 | ( 84 | ~argv: array(string)=?, 85 | ~env: Js.t({..})=?, 86 | ~eval: bool=?, 87 | ~execArgv: array(string)=?, 88 | ~stdin: bool=?, 89 | ~stdout: bool=?, 90 | ~stderr: bool=?, 91 | ~workerData: 'a=?, 92 | ~resourceLimits: workerResourceLimits=?, 93 | unit 94 | ) => 95 | makeOptions('a); 96 | 97 | [@bs.module "worker_threads"] [@bs.new] 98 | external make: (~file: string, ~options: makeOptions('a)=?, unit) => t('a) = 99 | "Worker"; 100 | [@bs.send] 101 | external onError: 102 | (t('a), [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t('a) = 103 | "on"; 104 | [@bs.send] 105 | external onMessage: 106 | (t('a), [@bs.as "message"] _, [@bs.uncurry] ('a => unit)) => t('a) = 107 | "on"; 108 | [@bs.send] 109 | external onExit: 110 | (t('a), [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => t('a) = 111 | "on"; 112 | [@bs.send] 113 | external onOnline: 114 | (t('a), [@bs.as "online"] _, [@bs.uncurry] (unit => unit)) => t('a) = 115 | "on"; 116 | [@bs.send] external postMessage: (t('a), 'a) => unit = "postMessage"; 117 | [@bs.send] external ref: t('a) => unit = "ref"; 118 | [@bs.send] 119 | external resourceLimits: t('a) => workerResourceLimits = 120 | "workerResourceLimits"; 121 | [@bs.get] external stderr: t('a) => Stream.Readable.t('a) = "stderr"; 122 | [@bs.get] 123 | external stdin: t('a) => Js.nullable(Stream.Writable.t('a)) = "stdin"; 124 | [@bs.get] external stdout: t('a) => Stream.Readable.t('a) = "stdout"; 125 | [@bs.send] external terminate: t('a) => Js.Promise.t(int) = "terminate"; 126 | [@bs.get] external threadId: t('a) => int = "threadId"; 127 | [@bs.send] external unref: t('a) => unit = "unref"; 128 | 129 | module WithMessageType = (T: {type message;}) => { 130 | type nonrec t = t(T.message); 131 | 132 | type nonrec makeOptions = makeOptions(T.message); 133 | [@bs.obj] 134 | external makeOptions: 135 | ( 136 | ~argv: array(string)=?, 137 | ~env: Js.t({..})=?, 138 | ~eval: bool=?, 139 | ~execArgv: array(string)=?, 140 | ~stdin: bool=?, 141 | ~stdout: bool=?, 142 | ~stderr: bool=?, 143 | ~workerData: T.message=?, 144 | ~resourceLimits: workerResourceLimits=?, 145 | unit 146 | ) => 147 | makeOptions; 148 | 149 | [@bs.module "worker_threads"] [@bs.new] 150 | external make: (~file: string, ~options: makeOptions=?, unit) => t = 151 | "Worker"; 152 | [@bs.send] 153 | external onError: 154 | (t, [@bs.as "error"] _, [@bs.uncurry] (Js.Exn.t => unit)) => t = 155 | "on"; 156 | [@bs.send] 157 | external onMessage: 158 | (t, [@bs.as "message"] _, [@bs.uncurry] (T.message => unit)) => t = 159 | "on"; 160 | [@bs.send] 161 | external onExit: (t, [@bs.as "exit"] _, [@bs.uncurry] (int => unit)) => t = 162 | "on"; 163 | [@bs.send] 164 | external onOnline: 165 | (t, [@bs.as "online"] _, [@bs.uncurry] (unit => unit)) => t = 166 | "on"; 167 | [@bs.send] external postMessage: (t, T.message) => unit = "postMessage"; 168 | [@bs.send] external ref: t => unit = "ref"; 169 | [@bs.send] 170 | external resourceLimits: t => workerResourceLimits = 171 | "workerResourceLimits"; 172 | [@bs.get] external stderr: t => Stream.Readable.t('a) = "stderr"; 173 | [@bs.get] 174 | external stdin: t => Js.nullable(Stream.Writable.t('a)) = "stdin"; 175 | [@bs.get] external stdout: t => Stream.Readable.t('a) = "stdout"; 176 | [@bs.send] external terminate: t => Js.Promise.t(int) = "terminate"; 177 | [@bs.get] external threadId: t => int = "threadId"; 178 | [@bs.send] external unref: t => unit = "unref"; 179 | }; 180 | }; 181 | 182 | [@bs.val] [@bs.module "worker_threads"] 183 | external isMainThread: bool = "isMainThread"; 184 | [@bs.val] [@bs.module "worker_threads"] 185 | external moveMessagePortToContext: 186 | (MessagePort.t('a), VM.contextifiedObject('b)) => MessagePort.t('a) = 187 | "moveMessagePortToContext"; 188 | [@bs.val] [@bs.module "worker_threads"] [@bs.return nullable] 189 | external parentPort: option(MessagePort.t('a)) = "parentPort"; 190 | [@bs.val] [@bs.module "worker_threads"] [@bs.return nullable] 191 | external receiveMessageOnPort: MessagePort.t('a) => option(Js.t({..})) = 192 | "receiveMessageOnPort"; 193 | [@bs.val] [@bs.module "worker_threads"] 194 | external resourceLimits: workerResourceLimits = "resourceLimits"; 195 | [@bs.val] [@bs.module "worker_threads"] 196 | external _SHARE_ENV: Js.Types.symbol = "SHARE_ENV"; 197 | [@bs.val] [@bs.module "worker_threads"] external threadId: int = "threadId"; 198 | [@bs.val] [@bs.module "worker_threads"] external workerData: 'a = "workerData"; 199 | 200 | module WithMessageType = (T: {type message;}) => { 201 | module Worker = 202 | Worker.WithMessageType({ 203 | type nonrec message = T.message; 204 | }); 205 | [@bs.val] [@bs.module "worker_threads"] 206 | external isMainThread: bool = "isMainThread"; 207 | [@bs.val] [@bs.module "worker_threads"] 208 | external moveMessagePortToContext: 209 | (MessagePort.t(T.message), VM.contextifiedObject('b)) => 210 | MessagePort.t(T.message) = 211 | "moveMessagePortToContext"; 212 | [@bs.val] [@bs.module "worker_threads"] [@bs.return nullable] 213 | external parentPort: option(MessagePort.t(T.message)) = "parentPort"; 214 | [@bs.val] [@bs.module "worker_threads"] [@bs.return nullable] 215 | external receiveMessageOnPort: 216 | MessagePort.t(T.message) => option(Js.t({..})) = 217 | "receiveMessageOnPort"; 218 | [@bs.val] [@bs.module "worker_threads"] 219 | external resourceLimits: workerResourceLimits = "resourceLimits"; 220 | [@bs.val] [@bs.module "worker_threads"] 221 | external _SHARE_ENV: Js.Types.symbol = "SHARE_ENV"; 222 | [@bs.val] [@bs.module "worker_threads"] external threadId: int = "threadId"; 223 | [@bs.val] [@bs.module "worker_threads"] 224 | external workerData: T.message = "workerData"; 225 | }; 226 | -------------------------------------------------------------------------------- /src/internal/Internal__JsTypeReflection.re: -------------------------------------------------------------------------------- 1 | /** 2 | * Note that the *third* definition of this function is 3 | * strictly necessary because the second one assumes 4 | * the raw function is already in scope, even in other 5 | * modules where it is not defined. 6 | */ 7 | %bs.raw 8 | {| 9 | function instanceOfClass(instance, _class) { 10 | try { 11 | return (instance instanceof _class); 12 | } catch { 13 | return false; 14 | } 15 | } 16 | |}; 17 | 18 | [@bs.val] external instanceOfClass: ('a, 'b) => bool = "instanceOfClass"; 19 | 20 | /** 21 | * `intanceOfClass` wraps the `instanceof` operator in a function. 22 | * It returns `true` whe `~instance` is an instance of `~class_`. 23 | * 24 | * Normally the operator will throw a `TypeError` exception if the 25 | * class constructor operand is not actually a constructor function. 26 | * 27 | * This wrapper function will catch such errors and return false if 28 | * they occur. 29 | */ 30 | let instanceOfClass = (~instance, ~class_) => instanceOfClass(instance, class_); 31 | 32 | /** 33 | * `functionLength` returns the arity of a JS function. 34 | * 35 | * 'functionLength' Will not work properly on JS functions which 36 | * use "default arguments" or "rest parameters": 37 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length 38 | * 39 | * Therefore, this function must be used with caution. 40 | */ 41 | [@bs.get] 42 | external functionLength: ('a => 'b) => int = "length"; 43 | 44 | /** 45 | * `prototype` returns `Some` 'prototype' property of a JS 46 | * data type, if it is defined. If the prototype is not defined, 47 | * returns `None`. 48 | */ 49 | [@bs.get] 50 | external prototype: 'a => option(Js.t({..})) = "prototype"; 51 | 52 | /** 53 | * `constructor` gets the class constructor function of a given JS 54 | * object. This type is left polymorphic and abstract since the function 55 | * type signature and arity cannot be statically determined. 56 | */ 57 | [@bs.get] 58 | external constructor: 'a => option('b) = "constructor"; 59 | 60 | /** 61 | * `constructorName` returns the name of the constructor function 62 | * of a given JS object. The constructor is the equivalent of a "class" 63 | * in JS, so this will (usually) identify the specific class type. 64 | */ 65 | [@bs.get] [@bs.scope "constructor"] 66 | external constructorName: 'a => string = "name"; 67 | 68 | /** 69 | * `objectToString` returns the value of the internal `[@@toStringTag]` 70 | * property on a given JS object (or located somewhere on its prototype 71 | * chain). This is commonly used to identify the base class when a class 72 | * has been extended by a sub-class. 73 | * 74 | * Note, this will fail for `null` and `undefined` values, which will 75 | * raise a exception of type `ReferenceError`, since the `[@@toStringTag]` 76 | * property is normally unavailable for those types. 77 | */ 78 | [@bs.val] [@bs.scope ("Object", "prototype", "toString")] 79 | external objectToString: 'a => string = "call"; 80 | -------------------------------------------------------------------------------- /test/__tests__/BigInt_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | 3 | describe("BigInt", () => { 4 | Random.init(84611); 5 | 6 | let fourHundred = 400; 7 | let randomInt = _ => Random.int(fourHundred); 8 | 9 | test( 10 | "'BigInt.fromInt' and 'BigInt.toInt' are associative operations for all 32-bit integers", 11 | () => { 12 | let arrA = Belt.Array.makeByU(1000, (. _) => Random.int(1000000)); 13 | let arrB = Belt.Array.map(arrA, BigInt.fromInt); 14 | let arrC = Belt.Array.map(arrB, BigInt.toInt); 15 | Expect.(expect(arrA) |> toEqual(arrC)); 16 | }, 17 | ); 18 | 19 | test("BigInt.add", () => { 20 | let a = randomInt(); 21 | let b = randomInt(); 22 | let c = a + b; 23 | 24 | Expect.( 25 | [@ocaml.warning "-44"] expect(BigInt.(add(fromInt(a), fromInt(b)))) 26 | |> toEqual(BigInt.fromInt(c)) 27 | ); 28 | }); 29 | 30 | test("BigInt.(+)", () => { 31 | let a = randomInt(); 32 | let b = randomInt(); 33 | let c = a + b; 34 | 35 | Expect.( 36 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) + fromInt(b))) 37 | |> toEqual(BigInt.fromInt(c)) 38 | ); 39 | }); 40 | 41 | test("BigInt.subtract", () => { 42 | let a = randomInt(); 43 | let b = randomInt(); 44 | let c = a - b; 45 | 46 | Expect.( 47 | [@ocaml.warning "-44"] 48 | expect(BigInt.(subtract(fromInt(a), fromInt(b)))) 49 | |> toEqual(BigInt.fromInt(c)) 50 | ); 51 | }); 52 | 53 | test("BigInt.(-)", () => { 54 | let a = randomInt(); 55 | let b = randomInt(); 56 | let c = a - b; 57 | 58 | Expect.( 59 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) - fromInt(b))) 60 | |> toEqual(BigInt.fromInt(c)) 61 | ); 62 | }); 63 | 64 | test("BigInt.multiply", () => { 65 | let a = randomInt(); 66 | let b = randomInt(); 67 | let c = a * b; 68 | 69 | Expect.( 70 | [@ocaml.warning "-44"] 71 | expect(BigInt.(multiply(fromInt(a), fromInt(b)))) 72 | |> toEqual(BigInt.fromInt(c)) 73 | ); 74 | }); 75 | 76 | test("BigInt.(*)", () => { 77 | let a = randomInt(); 78 | let b = randomInt(); 79 | let c = a * b; 80 | 81 | Expect.( 82 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) * fromInt(b))) 83 | |> toEqual(BigInt.fromInt(c)) 84 | ); 85 | }); 86 | 87 | test("BigInt.divide", () => { 88 | let a = randomInt(); 89 | let b = randomInt(); 90 | let c = a / b; 91 | 92 | Expect.( 93 | [@ocaml.warning "-44"] 94 | expect(BigInt.(divide(fromInt(a), fromInt(b)))) 95 | |> toEqual(BigInt.fromInt(c)) 96 | ); 97 | }); 98 | 99 | test("BigInt.(/)", () => { 100 | let a = randomInt(); 101 | let b = randomInt(); 102 | let c = a / b; 103 | 104 | Expect.( 105 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) / fromInt(b))) 106 | |> toEqual(BigInt.fromInt(c)) 107 | ); 108 | }); 109 | 110 | test("BigInt.negate", () => { 111 | let a = randomInt(); 112 | let b = - a; 113 | 114 | Expect.( 115 | [@ocaml.warning "-44"] expect(BigInt.(negate(fromInt(a)))) 116 | |> toEqual(BigInt.fromInt(b)) 117 | ); 118 | }); 119 | 120 | test("BigInt.(~-)", () => { 121 | let a = randomInt(); 122 | let b = - a; 123 | 124 | Expect.( 125 | [@ocaml.warning "-44"] expect(BigInt.(- fromInt(a))) 126 | |> toEqual(BigInt.fromInt(b)) 127 | ); 128 | }); 129 | 130 | test("BigInt.modulo", () => { 131 | let a = randomInt(); 132 | let b = randomInt(); 133 | let c = a mod b; 134 | 135 | Expect.( 136 | [@ocaml.warning "-44"] 137 | expect(BigInt.(modulo(fromInt(a), fromInt(b)))) 138 | |> toEqual(BigInt.fromInt(c)) 139 | ); 140 | }); 141 | 142 | test("BigInt.(mod)", () => { 143 | let a = randomInt(); 144 | let b = randomInt(); 145 | let c = a mod b; 146 | 147 | Expect.( 148 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) mod fromInt(b))) 149 | |> toEqual(BigInt.fromInt(c)) 150 | ); 151 | }); 152 | 153 | test("BigInt.power", () => { 154 | let a = Random.int(6); 155 | let b = Random.int(8); 156 | 157 | [@ocaml.warning "-3"] 158 | let c = Js.Math.pow_int(~base=a, ~exp=b); 159 | 160 | Expect.( 161 | [@ocaml.warning "-44"] expect(BigInt.(power(fromInt(a), fromInt(b)))) 162 | |> toEqual(BigInt.fromInt(c)) 163 | ); 164 | }); 165 | 166 | test("BigInt.(**)", () => { 167 | let a = Random.int(6); 168 | let b = Random.int(8); 169 | 170 | [@ocaml.warning "-3"] 171 | let c = Js.Math.pow_int(~base=a, ~exp=b); 172 | 173 | Expect.( 174 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) ** fromInt(b))) 175 | |> toEqual(BigInt.fromInt(c)) 176 | ); 177 | }); 178 | 179 | test("BigInt.logicalAnd", () => { 180 | let a = Random.int(256); 181 | let b = Random.int(256); 182 | let c = a land b; 183 | 184 | Expect.( 185 | [@ocaml.warning "-44"] 186 | expect(BigInt.(logicalAnd(fromInt(a), fromInt(b)))) 187 | |> toEqual(BigInt.fromInt(c)) 188 | ); 189 | }); 190 | 191 | test("BigInt.(land)", () => { 192 | let a = Random.int(256); 193 | let b = Random.int(256); 194 | let c = a land b; 195 | 196 | Expect.( 197 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) land fromInt(b))) 198 | |> toEqual(BigInt.fromInt(c)) 199 | ); 200 | }); 201 | 202 | test("BigInt.logicalOr", () => { 203 | let a = randomInt(); 204 | let b = randomInt(); 205 | let c = a lor b; 206 | 207 | Expect.( 208 | [@ocaml.warning "-44"] 209 | expect(BigInt.(logicalOr(fromInt(a), fromInt(b)))) 210 | |> toEqual(BigInt.fromInt(c)) 211 | ); 212 | }); 213 | 214 | test("BigInt.(lor)", () => { 215 | let a = randomInt(); 216 | let b = randomInt(); 217 | let c = a lor b; 218 | 219 | Expect.( 220 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) lor fromInt(b))) 221 | |> toEqual(BigInt.fromInt(c)) 222 | ); 223 | }); 224 | 225 | test("BigInt.logicalXor", () => { 226 | let a = randomInt(); 227 | let b = randomInt(); 228 | let c = a lxor b; 229 | 230 | Expect.( 231 | [@ocaml.warning "-44"] 232 | expect(BigInt.(logicalXor(fromInt(a), fromInt(b)))) 233 | |> toEqual(BigInt.fromInt(c)) 234 | ); 235 | }); 236 | 237 | test("BigInt.(lxor)", () => { 238 | let a = randomInt(); 239 | let b = randomInt(); 240 | let c = a lxor b; 241 | 242 | Expect.( 243 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) lxor fromInt(b))) 244 | |> toEqual(BigInt.fromInt(c)) 245 | ); 246 | }); 247 | 248 | test("BigInt.logicalNot", () => { 249 | let a = randomInt(); 250 | let b = lnot(a); 251 | 252 | Expect.( 253 | [@ocaml.warning "-44"] expect(BigInt.(logicalNot(fromInt(a)))) 254 | |> toEqual(BigInt.fromInt(b)) 255 | ); 256 | }); 257 | 258 | test("BigInt.(lnot)", () => { 259 | let a = randomInt(); 260 | let b = lnot(a); 261 | 262 | Expect.( 263 | [@ocaml.warning "-44"] expect(BigInt.(lnot(fromInt(a)))) 264 | |> toEqual(BigInt.fromInt(b)) 265 | ); 266 | }); 267 | 268 | test("BigInt.logicalShiftLeft", () => { 269 | let a = 26; 270 | let b = 7; 271 | let c = a lsl b; 272 | 273 | Expect.( 274 | [@ocaml.warning "-44"] 275 | expect(BigInt.(logicalShiftLeft(fromInt(a), fromInt(b)))) 276 | |> toEqual(BigInt.fromInt(c)) 277 | ); 278 | }); 279 | 280 | test("BigInt.(lsl)", () => { 281 | let a = 26; 282 | let b = 7; 283 | let c = a lsl b; 284 | 285 | Expect.( 286 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) lsl fromInt(b))) 287 | |> toEqual(BigInt.fromInt(c)) 288 | ); 289 | }); 290 | 291 | test("BigInt.arithmeticShiftRight", () => { 292 | let a = 32; 293 | let b = 4; 294 | let c = a asr b; 295 | 296 | Expect.( 297 | [@ocaml.warning "-44"] 298 | expect(BigInt.(arithmeticShiftRight(fromInt(a), fromInt(b)))) 299 | |> toEqual(BigInt.fromInt(c)) 300 | ); 301 | }); 302 | 303 | test("BigInt.(asr)", () => { 304 | let a = 32; 305 | let b = 4; 306 | let c = a asr b; 307 | 308 | Expect.( 309 | [@ocaml.warning "-44"] expect(BigInt.(fromInt(a) asr fromInt(b))) 310 | |> toEqual(BigInt.fromInt(c)) 311 | ); 312 | }); 313 | }); 314 | -------------------------------------------------------------------------------- /test/__tests__/BinaryLike_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | describe("BinaryLike", () => { 3 | open Js.TypedArray2; 4 | 5 | let string_ = "test1234"; 6 | let binaryLikeString = string_->BinaryLike.string; 7 | 8 | let buffer_ = Buffer.fromArray([| 1, 2, 3, 4 |]); 9 | let binaryLikeBuffer = BinaryLike.buffer(buffer_) 10 | 11 | let uInt8Array = Uint8Array.make([|1, 2, 3, 4|]); 12 | let binaryLikeUint8Array = BinaryLike.uInt8Array(uInt8Array); 13 | 14 | let int8Array = Int8Array.make([|1, 2, 3, 4|]); 15 | let binaryLikeInt8Array = BinaryLike.int8Array(int8Array); 16 | 17 | let uInt8ClampedArray = Uint8ClampedArray.make([|1, 2, 3, 4|]); 18 | let binaryLikeUint8ClampedArray = BinaryLike.uInt8ClampedArray(uInt8ClampedArray); 19 | 20 | let uInt16Array = Uint16Array.make([|1, 2, 3, 4|]); 21 | let binaryLikeUint16Array = BinaryLike.uInt16Array(uInt16Array); 22 | 23 | let int16Array = Int16Array.make([|1, 2, 3, 4|]); 24 | let binaryLikeInt16Array = BinaryLike.int16Array(int16Array); 25 | 26 | 27 | test("BinaryLike.classify(string) should return a 'String' variant", () => { 28 | open ExpectJs; 29 | expect( 30 | switch(BinaryLike.classify(binaryLikeString)) { 31 | | String(_) => true 32 | | _ => false 33 | }) |> toBe(true) 34 | }); 35 | 36 | test("BinaryLike.classify(buffer) should return a 'Buffer' variant", () => { 37 | open ExpectJs; 38 | expect( 39 | switch(BinaryLike.classify(binaryLikeBuffer)) { 40 | | Buffer(_) => true 41 | | _ => false 42 | }) |> toBe(true) 43 | }); 44 | 45 | test("BinaryLike.classify(uInt8Array) should return a 'Uint8Array' variant", () => { 46 | open ExpectJs; 47 | expect( 48 | switch(BinaryLike.classify(binaryLikeUint8Array)) { 49 | | Uint8Array(_) => true 50 | | _ => false 51 | }) |> toBe(true) 52 | }); 53 | 54 | test("BinaryLike.classify(int8Array) should return a 'Int8Array' variant", () => { 55 | open ExpectJs; 56 | expect( 57 | switch(BinaryLike.classify(binaryLikeInt8Array)) { 58 | | Int8Array(_) => true 59 | | _ => false 60 | }) |> toBe(true) 61 | }); 62 | 63 | test("BinaryLike.classify(uInt8ClampedArray) should return a 'Uint8ClampedArray' variant", () => { 64 | open ExpectJs; 65 | expect( 66 | switch(BinaryLike.classify(binaryLikeUint8ClampedArray)) { 67 | | Uint8ClampedArray(_) => true 68 | | _ => false 69 | }) |> toBe(true) 70 | }); 71 | 72 | test("BinaryLike.classify(uInt16Array) should return a 'Uint16Array' variant", () => { 73 | open ExpectJs; 74 | expect( 75 | switch(BinaryLike.classify(binaryLikeUint16Array)) { 76 | | Uint16Array(_) => true 77 | | _ => false 78 | }) |> toBe(true) 79 | }); 80 | 81 | test("BinaryLike.classify(int16Array) should return a 'Int16Array' variant", () => { 82 | open ExpectJs; 83 | expect( 84 | switch(BinaryLike.classify(binaryLikeInt16Array)) { 85 | | Int16Array(_) => true 86 | | _ => false 87 | }) |> toBe(true) 88 | }); 89 | 90 | 91 | (); 92 | }); 93 | -------------------------------------------------------------------------------- /test/__tests__/Console_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | let process = Process.process; 3 | 4 | describe("Console", () => { 5 | let c1 = 6 | Console.( 7 | make( 8 | consoleOptions( 9 | ~stderr=Process.stderr(process), 10 | ~ignoreErrors=false, 11 | ~colorMode=true, 12 | ~inspectOptions=Util.inspectOptions(), 13 | ~stdout=Process.stdout(process), 14 | (), 15 | ), 16 | ) 17 | ); 18 | 19 | let c2 = 20 | Console.make2({ 21 | "stderr": Process.stderr(process), 22 | "ignoreErrors": false, 23 | "colorMode": true, 24 | "inspectOptions": Util.inspectOptions(), 25 | "stdout": Process.stdout(process), 26 | }); 27 | 28 | c1->Console.logMany([|"a", "b"|]); 29 | c2->Console.table([|"hi", "bye"|]); 30 | c2->Console.table([|Js.Dict.fromArray([|("a", 1), ("b", 2)|])|]); 31 | 32 | test("New console instance should be defined", () => { 33 | ExpectJs.(expect(Js.Undefined.return(c1)) |> toBeDefined) 34 | }); 35 | 36 | test("New console instance should be defined", () => { 37 | ExpectJs.(expect(Js.Undefined.return(c2)) |> toBeDefined) 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/__tests__/EventEmitter_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | 3 | describe("EventEmitter", () => { 4 | test( 5 | "'Emitter.make' should create a new emitter instance that is defined", () => { 6 | open! ExpectJs; 7 | open! EventEmitterTestLib; 8 | let emitter = Emitter1.make(); 9 | expect(emitter->Js.Undefined.return) |> toBeDefined; 10 | }); 11 | 12 | test("'Emitter.addListener' should add a new event listener", () => { 13 | open! ExpectJs; 14 | open! EventEmitterTestLib; 15 | let listeners = 16 | Emitter1.( 17 | { 18 | make()->addListener(Events.text, _ => ())->listeners(Events.text); 19 | } 20 | ); 21 | expect(Array.length(listeners)) |> toBe(1); 22 | }); 23 | 24 | test("'Emitter.on' should add a new event listener", () => { 25 | open! ExpectJs; 26 | open! EventEmitterTestLib; 27 | let listeners = 28 | Emitter1.( 29 | { 30 | make()->on(Events.text, _ => ())->listeners(Events.text); 31 | } 32 | ); 33 | expect(Array.length(listeners)) |> toBe(1); 34 | }); 35 | 36 | test("'Emitter.on' should add a new event listener", () => { 37 | open! ExpectJs; 38 | open! EventEmitterTestLib; 39 | let listeners = 40 | Emitter1.( 41 | { 42 | make()->on(Events.text, _ => ())->listeners(Events.text); 43 | } 44 | ); 45 | expect(Array.length(listeners)) |> toBe(1); 46 | }); 47 | 48 | test("'Emitter.removeListener' should remove the event listener", () => { 49 | open! ExpectJs; 50 | open! EventEmitterTestLib; 51 | let eventListener = (_) => (); 52 | let listeners = 53 | Emitter1.( 54 | { 55 | make() 56 | |> on(_, Events.text, eventListener) 57 | |> removeListener(_, Events.text, eventListener) 58 | |> listeners(_, Events.text); 59 | } 60 | ); 61 | expect(Array.length(listeners)) |> toBe(0); 62 | }); 63 | 64 | test("'Emitter.off' should remove the event listener", () => { 65 | open! ExpectJs; 66 | open! EventEmitterTestLib; 67 | let eventListener = (_) => (); 68 | let listeners = 69 | Emitter1.( 70 | { 71 | make() 72 | |> on(_, Events.text, eventListener) 73 | |> off(_, Events.text, eventListener) 74 | |> listeners(_, Events.text); 75 | } 76 | ); 77 | expect(Array.length(listeners)) |> toBe(0); 78 | }); 79 | 80 | test("'Emitter.emit' should execute each listener for the correct event", () => { 81 | open! ExpectJs; 82 | open! EventEmitterTestLib; 83 | let ref1 = ref(0); 84 | let ref2 = ref(0); 85 | let data1 = 1; 86 | let data2 = 2; 87 | let listener1 = (_) => { ref1 := data1; }; 88 | let listener2 = (_) => { ref2 := data2; }; 89 | Emitter1.({ 90 | let emitter = 91 | make() 92 | |> on(_, Events.integer, listener1) 93 | |> on(_, Events.integer, listener2); 94 | emit(emitter, Events.integer, data1)->ignore; 95 | emit(emitter, Events.integer, data2)->ignore; 96 | }); 97 | Assert.strictEqual(ref1^, 1); 98 | Assert.strictEqual(ref2^, 2); 99 | expect(ref1^ === 1 && ref2^ === 2) |> toBe(true); 100 | }); 101 | 102 | test("'Emitter.removeAllListeners' should remove all event listeners", () => { 103 | open! ExpectJs; 104 | open! EventEmitterTestLib; 105 | let eventListener = (_) => (); 106 | let emitter = 107 | Emitter1.( 108 | { 109 | make() 110 | |> on(_, Events.text, eventListener) 111 | |> on(_, Events.text, eventListener) 112 | |> on(_, Events.text, eventListener) 113 | } 114 | ); 115 | // Make sure 3 listeners were indeed added: 116 | Assert.strictEqual(Emitter1.(listeners(emitter, Events.text))->Array.length, 3); 117 | // Remove all the listeners: 118 | Emitter1.removeAllListeners(emitter)->ignore; 119 | expect(Emitter1.(listeners(emitter, Events.text))->Array.length) |> toBe(0); 120 | }); 121 | 122 | }); 123 | -------------------------------------------------------------------------------- /test/__tests__/Fs_test.re: -------------------------------------------------------------------------------- 1 | open Fs; 2 | open Jest; 3 | open Js.Promise; 4 | 5 | describe("Fs", () => { 6 | testPromise("readFile should read entire file", () => { 7 | open_(Global.filename, Flag.read) 8 | |> then_(fh => 9 | Fs.FileHandle.readFile(fh) 10 | |> then_(buffer => 11 | FileHandle.close(fh) |> then_(_ => resolve(buffer)) 12 | ) 13 | ) 14 | |> then_(buffer => { 15 | let needle = "Random string: Gh2e71pdHhPxU"; 16 | Expect.( 17 | expect(buffer->Buffer.indexOfString(needle)) 18 | |> toBeGreaterThan(0) 19 | |> resolve 20 | ); 21 | }) 22 | }); 23 | testPromise("readFileWith should read entire file as a string", () => { 24 | open_(Global.filename, Flag.read) 25 | |> then_(fh => 26 | Fs.FileHandle.readFileWith(fh, ~encoding="UTF-8") 27 | |> then_(buffer => 28 | FileHandle.close(fh) |> then_(_ => resolve(buffer)) 29 | ) 30 | ) 31 | |> then_(content => { 32 | let needle = "Random string: uCF6c5f3Arrq"; 33 | Expect.( 34 | expect(Js.String.indexOf(needle, content)) 35 | |> toBeGreaterThan(0) 36 | |> resolve 37 | ); 38 | }) 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/__tests__/Global_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | 3 | describe("Global", () => { 4 | 5 | test("dirname should be defined", () => { 6 | open ExpectJs; 7 | expect(Js.Undefined.return(Global.dirname)) |> toBeDefined; 8 | }); 9 | 10 | test("dirname should be of type 'string'", () => { 11 | open Expect; 12 | expect(Global.dirname->Js.typeof) |> toEqual("string"); 13 | }); 14 | 15 | test("filename should be defined", () => { 16 | open ExpectJs; 17 | expect(Js.Undefined.return(Global.filename)) |> toBeDefined; 18 | }); 19 | 20 | test("filename should be of type 'string'", () => { 21 | open Expect; 22 | expect(Global.filename->Js.typeof) |> toEqual("string"); 23 | }); 24 | 25 | test("'global' object should be defined", () => { 26 | open ExpectJs; 27 | expect(Js.Undefined.return(Global.global)) |> toBeDefined; 28 | }); 29 | 30 | test("'global' object should be of type 'object'", () => { 31 | open Expect; 32 | expect(Global.global->Js.typeof) |> toEqual("object"); 33 | }); 34 | 35 | test("'require' function should be defined", () => { 36 | open ExpectJs; 37 | expect(Global.require->Js.Undefined.return) |> toBeDefined; 38 | }); 39 | 40 | test("'require' function should be of type 'function'", () => { 41 | open Expect; 42 | expect(Global.require->Js.typeof) |> toEqual("function"); 43 | }); 44 | 45 | test("'require' fuction should return a defined value from a relative path", () => { 46 | open ExpectJs; 47 | expect(Global.require("path")->Js.Undefined.return) |> toBeDefined; 48 | }); 49 | 50 | test("'require' fuction should successfully import a module object from a relative path", () => { 51 | open Expect; 52 | expect(Global.require("path")->Js.typeof) |> toEqual("object"); 53 | }); 54 | 55 | 56 | }); -------------------------------------------------------------------------------- /test/__tests__/Path_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | 3 | describe("Path", () => { 4 | test("basename should isolate filename with extension", () => { 5 | open Expect; 6 | expect(Path.Posix.basename("/tmp/myfile.html")) |> toBe("myfile.html"); 7 | }); 8 | 9 | }); 10 | -------------------------------------------------------------------------------- /test/__tests__/Stream_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | 3 | describe("Stream.Readable", () => { 4 | testAsync("'Stream.Readable.make' should return a defined value", resolve => { 5 | open! ExpectJs; 6 | open StreamTestLib; 7 | let readable = makeReadableEmpty(); 8 | expect(readable->Js.Undefined.return) |> toBeDefined |> resolve; 9 | }); 10 | 11 | testAsync( 12 | "'Stream.Readable.make' should return an instance of 'Readable'", resolve => { 13 | open! ExpectJs; 14 | open StreamTestLib; 15 | let readable = makeReadableEmpty(); 16 | expect(readable->Internal__JsTypeReflection.constructorName) 17 | |> toBe("Readable") 18 | |> resolve; 19 | }); 20 | 21 | testAsync("'Stream.Readable.pipe' returns a writable stream", resolve => { 22 | open! ExpectJs; 23 | open StreamTestLib; 24 | let readable = makeReadableEmpty(); 25 | let writable = makeWritableEmpty(); 26 | expect(Stream.pipe(readable, writable)) |> toBe(writable) |> resolve; 27 | }); 28 | 29 | testAsync( 30 | "'Stream.Readable.destroyWithError' should emit 'error' event", resolve => { 31 | open! ExpectJs; 32 | open! Errors; 33 | let dummyError = Error.make("Destroyed")->Error.toJsExn; 34 | let () = 35 | StreamTestLib.makeReadableEmpty() 36 | ->Stream.onError(err => { 37 | Console.(console->dir(err)); 38 | expect(err) |> toEqual(dummyError) |> resolve; 39 | }) 40 | ->Stream.destroyWithError(dummyError) 41 | ->ignore; 42 | (); 43 | }); 44 | 45 | testAsync( 46 | "'Stream.Readable.destroy' should return the exact same instance of 'Readable'", 47 | resolve => { 48 | open! ExpectJs; 49 | let readable = StreamTestLib.makeReadableEmpty(); 50 | expect(readable->Stream.destroy) |> toBe(readable) |> resolve; 51 | }, 52 | ); 53 | }); 54 | 55 | describe("Stream.Writable", () => { 56 | testAsync("'Stream.Writable.make' should return a defined value", resolve => { 57 | open! ExpectJs; 58 | open StreamTestLib; 59 | let writable = makeWritableEmpty(); 60 | expect(writable->Js.Undefined.return) |> toBeDefined |> resolve; 61 | }); 62 | 63 | testAsync( 64 | "'Stream.Writable.make' should return an instance of 'Writable'", resolve => { 65 | open! ExpectJs; 66 | open StreamTestLib; 67 | let writable = makeWritableEmpty(); 68 | expect(writable->Internal__JsTypeReflection.constructorName) 69 | |> toBe("Writable") 70 | |> resolve; 71 | }); 72 | 73 | testAsync( 74 | "Stream.Writable.makeObjMode should have a 'write' function with the correct function signature", 75 | resolve => { 76 | open Stream; 77 | 78 | let args = ref(None); 79 | 80 | let options = 81 | Writable.makeOptionsObjMode( 82 | ~write= 83 | [@bs.this] (wstream, ~data, ~encoding, ~callback) => { 84 | args := Some((wstream, data, encoding, callback)); 85 | callback(~error=None); 86 | }, 87 | (), 88 | ); 89 | 90 | let writeStream = Writable.makeObjMode(options); 91 | 92 | ExpectJs.( 93 | Writable.writeWith( 94 | writeStream, 95 | 42, 96 | ~callback= 97 | _ => { 98 | expect( 99 | { 100 | switch (args^) { 101 | | None => None 102 | | Some((wstream, value, encoding, cb)) => 103 | Some(( 104 | Internal__JsTypeReflection.constructorName(wstream) 105 | === "Writable", 106 | Js.typeof(value) === "number", 107 | Js.typeof(encoding) === "string", 108 | Js.typeof(cb) === "function", 109 | )) 110 | }; 111 | }, 112 | ) 113 | |> toEqual(Some((true, true, true, true))) 114 | |> resolve 115 | }, 116 | (), 117 | ) 118 | ->ignore 119 | ); 120 | }, 121 | ); 122 | }); 123 | -------------------------------------------------------------------------------- /test/__tests__/Util_test.re: -------------------------------------------------------------------------------- 1 | open Jest; 2 | 3 | describe("Util.Types", () => { 4 | test("Util.Types.isAnyArrayBuffer(arrayBuffer) should return true", () => { 5 | open Expect; 6 | let arrayBuffer = Js.TypedArray2.ArrayBuffer.make(16); 7 | expect(arrayBuffer->Util.Types.isAnyArrayBuffer) |> toEqual(true); 8 | }); 9 | 10 | test("Util.Types.isAnyArrayBuffer(string) should return false", () => { 11 | open Expect; 12 | let str = "not array buffer"; 13 | expect(str->Util.Types.isAnyArrayBuffer) |> toEqual(false); 14 | }); 15 | 16 | }); 17 | -------------------------------------------------------------------------------- /test/test_lib/EventEmitterTestLib.re: -------------------------------------------------------------------------------- 1 | module Emitter1 = { 2 | include EventEmitter.Make(); 3 | 4 | let uniqueSymbol: Js.Types.symbol = [%raw {|Symbol("emitter1")|}]; 5 | 6 | module Events = { 7 | let symbol: Event.t(Js.Types.symbol => unit, t) = Event.fromSymbol(uniqueSymbol); 8 | let text: Event.t(string => unit, t) = Event.fromString("text"); 9 | let integer: Event.t(int => unit, t) = Event.fromString("integer"); 10 | let textAndInteger: Event.t((string, int) => unit, t) = Event.fromString("textAndInteger"); 11 | }; 12 | 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /test/test_lib/StreamTestLib.re: -------------------------------------------------------------------------------- 1 | /** Creates a readable stream with no functionality */ 2 | let makeReadableEmpty = () => { 3 | open Stream.Readable; 4 | let options = 5 | makeOptions( 6 | ~destroy= 7 | [@bs.this] (_, ~error, ~callback) => { 8 | callback(~error=Js.Nullable.toOption(error)) 9 | }, 10 | ~read=[@bs.this] (_, ~size as _) => (), 11 | ~autoDestroy=true, 12 | (), 13 | ); 14 | make(options); 15 | }; 16 | 17 | /** Creates a writable stream with no functionality */ 18 | let makeWritableEmpty = () => { 19 | open Stream.Writable; 20 | let options = 21 | makeOptions( 22 | ~destroy= 23 | [@bs.this] (_, ~error, ~callback) => { 24 | callback(~error=Js.Nullable.toOption(error)) 25 | }, 26 | ~write= 27 | [@bs.this] (_, ~data as _, ~encoding as _, ~callback) => 28 | callback(~error=None), 29 | ~autoDestroy=true, 30 | (), 31 | ); 32 | make(options); 33 | }; 34 | --------------------------------------------------------------------------------