@reventlessdev/rescript-node 2.0.0-alpha.14 → 2.0.0-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 2.0.0-alpha.16 (2026-09-27)
7
+
8
+ ### Features
9
+
10
+ * **node:** bind node:test and node:assert, lstatSync, execPath and base64 decoding ([c067e39](https://github.com/ReventlessDev/reventless-core/commit/c067e39ce3a5979f3a18c4761e4673baa6c11ffd))
11
+
12
+
13
+ # 2.0.0-alpha.15 (2026-09-23)
14
+
15
+ * feat(node)!: every command-line tool reads its arguments through parseArgs ([2e41979](https://github.com/ReventlessDev/reventless-core/commit/2e41979b73646c46356e197e17eb4a3da0154c73))
16
+
17
+ ### BREAKING CHANGES
18
+
19
+ * NodeProcess.onSignal takes the new NodeProcess.signal
20
+ variant (SIGINT | SIGTERM | SIGHUP) instead of a polymorphic variant:
21
+ write onSignal(SIGINT, …) for onSignal(#SIGINT, …). Node receives the
22
+ same string.
23
+
24
+
25
+
6
26
  # 2.0.0-alpha.14 (2026-09-23)
7
27
 
8
28
  ### Features
package/README.md CHANGED
@@ -45,6 +45,7 @@ Add it to your `rescript.json` dependencies:
45
45
  | `NodeProcess` | the `process` global |
46
46
  | `NodeStreams` | `node:stream`, plus the stream-shaped parts of `node:fs` and `node:readline` |
47
47
  | `NodeUrl` | `node:url` |
48
+ | `NodeUtil` | `parseArgs` from `node:util` |
48
49
  | `NodeZlib` | `node:zlib` |
49
50
 
50
51
  Every module specifier is `node:`-prefixed. Bare `"fs"` is what bundlers alias to a browser polyfill
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/rescript-node",
3
- "version": "2.0.0-alpha.14",
3
+ "version": "2.0.0-alpha.16",
4
4
  "description": "ReScript bindings for the Node.js standard library",
5
5
  "license": "Apache-2.0",
6
6
  "devDependencies": {
package/rescript.json CHANGED
@@ -15,6 +15,7 @@
15
15
  "dir": "src",
16
16
  "subdirs": true,
17
17
  "public": [
18
+ "NodeAssert",
18
19
  "NodeBuffer",
19
20
  "NodeChildProcess",
20
21
  "NodeCrypto",
@@ -25,7 +26,9 @@
25
26
  "NodePath",
26
27
  "NodeProcess",
27
28
  "NodeStreams",
29
+ "NodeTest",
28
30
  "NodeUrl",
31
+ "NodeUtil",
29
32
  "NodeZlib"
30
33
  ]
31
34
  }
@@ -0,0 +1,35 @@
1
+ /** Bindings for [`node:assert/strict`](https://nodejs.org/api/assert.html#strict-assertion-mode).
2
+
3
+ The strict module only: `equal` is `===` and `deepEqual` is `deepStrictEqual`,
4
+ so a test cannot pass on a coercion. Each assertion that takes a message has a
5
+ `…Msg` form; the message replaces Node's generated one when the assertion
6
+ fails, so it should say what went wrong rather than restate the values. */
7
+ @module("node:assert/strict")
8
+ external equal: ('a, 'a) => unit = "equal"
9
+
10
+ @module("node:assert/strict")
11
+ external equalMsg: ('a, 'a, string) => unit = "equal"
12
+
13
+ @module("node:assert/strict")
14
+ external deepEqual: ('a, 'a) => unit = "deepEqual"
15
+
16
+ @module("node:assert/strict")
17
+ external deepEqualMsg: ('a, 'a, string) => unit = "deepEqual"
18
+
19
+ @module("node:assert/strict")
20
+ external ok: bool => unit = "ok"
21
+
22
+ @module("node:assert/strict")
23
+ external okMsg: (bool, string) => unit = "ok"
24
+
25
+ /** `assert.match`, renamed because `match` is not an identifier in ReScript. */
26
+ @module("node:assert/strict")
27
+ external matches: (string, RegExp.t) => unit = "match"
28
+
29
+ @module("node:assert/strict")
30
+ external doesNotMatch: (string, RegExp.t) => unit = "doesNotMatch"
31
+
32
+ /** Always throws, so it types as any value — usable as the arm of a `switch` that
33
+ has nothing to return. */
34
+ @module("node:assert/strict")
35
+ external fail: string => 'a = "fail"
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -25,6 +25,10 @@ external fromStringBase64Url: (string, @as("base64url") _) => t = "from"
25
25
 
26
26
  /** A `Buffer` over a copy of the bytes. A plain `Uint8Array` — what the AWS SDK
27
27
  hands back — has only the array's own `toString`, which joins the numbers. */
28
+ /** Standard base64, the alphabet of a `data:…;base64,` URI. */
29
+ @val @scope("Buffer")
30
+ external fromStringBase64: (string, @as("base64") _) => t = "from"
31
+
28
32
  @val @scope("Buffer")
29
33
  external fromBytes: Uint8Array.t => t = "from"
30
34
 
package/src/NodeFs.res CHANGED
@@ -16,6 +16,15 @@ existsSync: string => bool = "existsSync"
16
16
  @module("node:fs")
17
17
  external realpathSync: string => string = "realpathSync"
18
18
 
19
+ type stats
20
+
21
+ /** Stats the path itself rather than what it points to, which is the only way to
22
+ tell a symbolic link from its target. */
23
+ @module("node:fs")
24
+ external lstatSync: string => stats = "lstatSync"
25
+
26
+ @send external isSymbolicLink: stats => bool = "isSymbolicLink"
27
+
19
28
  /** Set a file's access and modification times, in seconds since the epoch.
20
29
 
21
30
  The reason this exists here rather than as a shell-out to `touch`: a build
@@ -23,6 +23,12 @@ external exit: int => unit = "exit"
23
23
  @val @scope("process")
24
24
  external pid: int = "pid"
25
25
 
26
+ /** The absolute path of the running `node` binary — what a test spawns a script
27
+ with, so the child runs on the same Node as the parent rather than whichever
28
+ `node` is first on `PATH`. */
29
+ @val @scope("process")
30
+ external execPath: string = "execPath"
31
+
26
32
  /** `versions["node"]` is the running Node's version, without the leading `v`. */
27
33
  @val @scope("process")
28
34
  external versions: dict<string> = "versions"
@@ -40,13 +46,20 @@ external kill: (int, int) => unit = "kill"
40
46
  synchronous work, while a signal handler receives the signal name and fires
41
47
  *before* the process is committed to leaving — code that registers one and
42
48
  expects the other's timing gets a cleanup that never runs. Signals are a
43
- polyvariant so a typo is a compile error rather than a handler that is never
44
- called. */
49
+ closed variant so a typo is a compile error rather than a handler that is
50
+ never called. */
45
51
  @val @scope("process")
46
52
  external onExit: (@as("exit") _, int => unit) => unit = "on"
47
53
 
54
+ /** The signals a CLI cleans up on. Each constructor compiles to the name Node
55
+ reads. */
56
+ type signal =
57
+ | @as("SIGINT") SIGINT
58
+ | @as("SIGTERM") SIGTERM
59
+ | @as("SIGHUP") SIGHUP
60
+
48
61
  @val @scope("process")
49
- external onSignal: ([#SIGINT | #SIGTERM | #SIGHUP], unit => unit) => unit = "on"
62
+ external onSignal: (signal, unit => unit) => unit = "on"
50
63
 
51
64
  /** The standard streams. `write`, `isTTY`, `pause` and `unref` are what the
52
65
  interactive prompts in this repository reach for; the type is abstract so it
@@ -0,0 +1,23 @@
1
+ /** Bindings for [`node:test`](https://nodejs.org/api/test.html), the runner behind
2
+ `node --test`.
3
+
4
+ Only the forms a test file declares itself with. A test body is synchronous
5
+ unless it is bound through {!testAsync}; a promise returned from {!test}'s body
6
+ would not be awaited by the type, so the two are kept apart. */
7
+ @module("node:test")
8
+ external test: (string, unit => unit) => unit = "test"
9
+
10
+ @module("node:test")
11
+ external testAsync: (string, unit => promise<unit>) => unit = "test"
12
+
13
+ /** Whether a test runs, or why it is skipped. Node takes `false` or a reason
14
+ string, and prints the reason beside the skipped test. */
15
+ @unboxed
16
+ type skip = | @as(false) Run | Skip(string)
17
+
18
+ type options = {skip?: skip}
19
+
20
+ /** A test that decides at load time whether it can run — one that needs a sibling
21
+ checkout, say, and skips with a reason where there is none. */
22
+ @module("node:test")
23
+ external testWith: (string, options, unit => unit) => unit = "test"
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
@@ -0,0 +1,52 @@
1
+ /** Bindings for `node:util`. `parseArgs` is stable from Node 20.
2
+
3
+ Node's string enums are regular variants whose constructors compile to the
4
+ exact strings Node reads and writes. `default` and `allowNegative` are left
5
+ out: the first is a string, a boolean or an array depending on the option,
6
+ and the second needs Node 22.4. */
7
+ /** An option's `type`. */
8
+ type optionType =
9
+ | @as("string") String
10
+ | @as("boolean") Boolean
11
+
12
+ type optionConfig = {
13
+ @as("type") type_: optionType,
14
+ short?: string,
15
+ multiple?: bool,
16
+ }
17
+
18
+ type config = {
19
+ args?: array<string>,
20
+ options: dict<optionConfig>,
21
+ strict?: bool,
22
+ allowPositionals?: bool,
23
+ tokens?: bool,
24
+ }
25
+
26
+ /** A token's `kind`. The constructor names avoid `Option`, which would read as
27
+ the standard library module at every use site. */
28
+ type tokenKind =
29
+ | @as("option") Flag
30
+ | @as("positional") Positional
31
+ | @as("option-terminator") Terminator
32
+
33
+ type token = {
34
+ kind: tokenKind,
35
+ index: int,
36
+ name?: string,
37
+ rawName?: string,
38
+ value?: string,
39
+ inlineValue?: bool,
40
+ }
41
+
42
+ /** `values` mixes strings, booleans and arrays under one object, so it is
43
+ abstract and read through the typed accessors below. */
44
+ type values
45
+
46
+ type parsed = {values: values, positionals: array<string>, tokens?: array<token>}
47
+
48
+ @module("node:util") external parseArgs: config => parsed = "parseArgs"
49
+
50
+ @get_index external string: (values, string) => option<string> = ""
51
+ @get_index external bool: (values, string) => option<bool> = ""
52
+ @get_index external strings: (values, string) => option<array<string>> = ""
@@ -0,0 +1,2 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+ /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */