{"id":13626136,"url":"https://github.com/aalykiot/dune","last_synced_at":"2025-05-16T09:05:25.364Z","repository":{"id":58808021,"uuid":"444909871","full_name":"aalykiot/dune","owner":"aalykiot","description":"A hobby runtime for JavaScript and TypeScript 🚀","archived":false,"fork":false,"pushed_at":"2025-05-06T22:11:51.000Z","size":2075,"stargazers_count":386,"open_issues_count":6,"forks_count":10,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-06T23:21:12.440Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://aalykiot.github.io/dune/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aalykiot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-01-05T18:27:58.000Z","updated_at":"2025-03-18T01:25:55.000Z","dependencies_parsed_at":"2023-10-27T16:27:47.088Z","dependency_job_id":"b1cf99d2-5ea4-4d5f-bcd1-b5abb7400d49","html_url":"https://github.com/aalykiot/dune","commit_stats":null,"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalykiot%2Fdune","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalykiot%2Fdune/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalykiot%2Fdune/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aalykiot%2Fdune/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aalykiot","download_url":"https://codeload.github.com/aalykiot/dune/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254501557,"owners_count":22081528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T21:02:10.887Z","updated_at":"2025-05-16T09:05:20.355Z","avatar_url":"https://github.com/aalykiot.png","language":"Rust","funding_links":[],"categories":["Rust","Runtimes"],"sub_categories":[],"readme":"# Dune\n\nDune is an open-source, cross-platform, shell around the **V8** engine, written in **Rust** and capable of running JavaScript (dah) and TypeScript code out of the box.\n\nDeveloped completely for fun and experimentation.\n\n![GitHub](https://img.shields.io/github/license/aalykiot/dune?style=flat-square)\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/aalykiot/dune/dune-ci.yml?branch=main\u0026style=flat-square)\n\n## Installation\n\n**Mac, Linux:**\n\n```sh\ncurl -fsSL https://raw.githubusercontent.com/aalykiot/dune/main/install.sh | sh\n```\n\n**Windows (PowerShell)**\n\n```powershell\nirm https://raw.githubusercontent.com/aalykiot/dune/main/install.ps1 | iex\n```\n\n\u003e Otherwise you have to manually download and unzip the \u003ca href=\"https://github.com/aalykiot/dune/releases/latest/download/dune-x86_64-pc-windows-msvc.zip\"\u003erelease\u003c/a\u003e build.\n\n**From Source:**\n\nClone the repo and build it using \u003ca href=\"https://rustup.rs/\"\u003eCargo\u003c/a\u003e.\n\n```bash\ngit clone https://github.com/aalykiot/dune.git \u0026\u0026 cd ./dune \u0026\u0026 cargo build --release\n```\n\n\u003e Make sure to create a `.dune` directory under your user.\n\n## Getting Started\n\nA simple example.\n\n```js\nimport shortid from 'https://cdn.skypack.dev/shortid';\n\nconsole.log(shortid()); //=\u003e \"lXN1aGba2\"\n```\n\nAnother example using the net module.\n\n```js\nimport net from 'net';\n\nconst server = net.createServer(async (socket) =\u003e {\n  console.log('Got new connection!');\n  await socket.write('Hello! 👋\\n');\n  await socket.destroy();\n});\n\nawait server.listen(3000, '127.0.0.1');\n\nconsole.log('Server is listening on port 3000...');\n```\n\nJSX/TSX files are also supported for server side rendering.\n\n```jsx\nimport { h, Component } from 'https://esm.sh/preact@10.11.3';\nimport { render } from 'https://esm.sh/preact-render-to-string@5.2.6';\n\n/** @jsx h */\n\n// Classical components work.\nclass Fox extends Component {\n  render({ name }) {\n    return \u003cspan class=\"fox\"\u003e{name}\u003c/span\u003e;\n  }\n}\n\n// ... and so do pure functional components:\nconst Box = ({ type, children }) =\u003e (\n  \u003cdiv class={`box box-${type}`}\u003e{children}\u003c/div\u003e\n);\n\nlet html = render(\n  \u003cBox type=\"open\"\u003e\n    \u003cFox name=\"Finn\" /\u003e\n  \u003c/Box\u003e\n);\n\nconsole.log(html);\n```\n\nFor more examples look at the \u003ca href=\"./examples\"\u003eexamples\u003c/a\u003e directory.\n\n## Available APIs\n\n### Globals\n\n- [x] `global`: Reference to the global object.\n- [x] `globalThis`: Same as `global`.\n- [x] `console`: A subset of the WHATWG console.\n- [x] `prompt`: Shows the given message and waits for the user's input.\n- [x] `TextEncoder` / `TextDecoder`: WHATWG encoding API.\n- [x] `setTimeout` / `setInterval` / `clearTimeout` / `clearInterval`: DOM style timers.\n- [x] `setImmediate` / `clearImmediate`: Node.js like immediate timers.\n- [x] `process`: An object that provides info about the current dune process.\n- [x] `structuredClone`: Creates a deep clone of a given value.\n- [x] `AbortController` / `AbortSignal`: Allows you to communicate with a request and abort it.\n- [x] `fetch`: A wrapper around `http.request` (not fully compatible with WHATWG fetch).\n- [x] `queueMicrotask`: Queues a microtask to invoke a callback.\n\n### Module Metadata\n\n- [x] `import.meta.url`: A string representation of the fully qualified module URL.\n- [x] `import.meta.main`: A flag that indicates if the current module is the main module.\n- [x] `import.meta.resolve(specifier)`: A function that returns resolved specifier.\n\n### Process\n\n- [x] `argv`: An array containing the command-line arguments passed when the dune process was launched.\n- [x] `cwd()`: Current working directory.\n- [x] `env`: An object containing the user environment.\n- [x] `exit(code?)`: Exits the program with the given code.\n- [ ] `getActiveResourcesInfo()`: An array of strings containing the types of the active resources that are currently keeping the event loop alive. 🚧\n- [x] `memoryUsage()`: An object describing the memory usage.\n- [x] `nextTick(cb, ...args?)`: Adds callback to the \"next tick queue\".\n- [x] `pid`: PID of the process.\n- [x] `platform`: A string identifying the operating system platform.\n- [x] `uptime()`: A number describing the amount of time (in seconds) the process is running.\n- [x] `version`: The dune version.\n- [x] `versions`: An object listing the version strings of dune and its dependencies.\n- [x] `binding(module)`: Exposes modules with bindings to Rust.\n- [x] `kill(pid, signal?)`: Sends the signal to the process identified by pid.\n- [x] `stdout`: Points to system's `stdout` stream.\n- [x] `stdin`: Points to system's `stdin` stream.\n- [x] `stderr`: Points to system's `stderr` stream.\n\n##### Events\n\n- [x] `uncaughtException`: Emitted when an uncaught exception bubbles up to Dune.\n- [x] `unhandledRejection`: Emitted when a Promise is rejected with no handler.\n\n\u003e Signal events will be emitted when the Dune process receives a signal. Please refer to [signal(7)](https://man7.org/linux/man-pages/man7/signal.7.html) for a listing of standard POSIX signal names.\n\n### File System\n\n\u003e This module also includes a `Sync` method for every async operation available.\n\n- [x] `copyFile(src, dest)`: Copies `src` to `dest`.\n- [x] `createReadStream(path, options?)`: Returns a new readable IO stream.\n- [x] `createWriteStream(path, options?)`: Returns a new writable IO stream.\n- [x] `open(path, mode?)`: Asynchronous file open.\n- [x] `mkdir(path, options?)`: Creates a directory.\n- [x] `readFile(path, options?)`: Reads the entire contents of a file.\n- [x] `rmdir(path, options?)`: Deletes a directory (must be empty).\n- [x] `readdir(path)`: Reads the contents of a directory.\n- [x] `rm(path, options?)`: Removes files and directories.\n- [x] `rename(from, to)`: Renames the file from oldPath to newPath.\n- [x] `stat(path)`: Retrieves statistics for the file.\n- [x] `watch(path, options?)`: Returns an async iterator that watches for changes over a path.\n- [x] `writeFile(path, data, options?)`: Writes data to the file, replacing the file if it already exists.\n\n\u003e Data (to be written) must be of type String|Uint8Array.\n\n### File\n\n- [x] `fd`: The numeric file descriptor.\n- [x] `close()`: Closes the file.\n- [x] `read(size?, offset?)`: Reads data from the file.\n- [x] `stat()`: Retrieves statistics for the file.\n- [x] `write(data, offset?)`: Writes data to the file.\n\n### Net\n\n- [x] `createServer(connectionHandler?)`: Creates a new TCP server.\n- [x] `createConnection(options)`: Creates unix socket connection to a remote host.\n- [x] `connect(options)`: An alias of `createConnection()`.\n- [x] `TimeoutError`: Custom error signalling a socket (read) timeout.\n\n#### `net.Server`\n\n\u003e net.Server is a class extending `EventEmitter` and implements `@@asyncIterator`.\n\n- [x] `listen(port, host?)`: Begin accepting connections on the specified port and host.\n- [x] `accept()`: Waits for a TCP client to connect and accepts the connection.\n- [x] `address()`: Returns the bound address.\n- [x] `close()`: Stops the server from accepting new connections and keeps existing connections.\n\n##### Events\n\n- [x] `listening`: Emitted when the server has been bound after calling `server.listen`.\n- [x] `connection`: Emitted when a new connection is made.\n- [x] `close`: Emitted when the server stops accepting new connections.\n- [x] `error`: Emitted when an error occurs.\n\n#### `net.Socket`\n\n\u003e net.Socket is a class extending `EventEmitter` and implements `@@asyncIterator`.\n\n- [x] `connect(options)`: Opens the connection for a given socket.\n- [x] `setEncoding(encoding)`: Sets the encoding for the socket.\n- [x] `setTimeout(timeout)`: Sets the socket's timeout threshold when reading.\n- [x] `read()`: Reads data out of the socket.\n- [x] `write(data)`: Sends data on the socket.\n- [x] `end(data?)`: Half-closes the socket. i.e., it sends a FIN packet.\n- [x] `destroy()`: Closes and discards the TCP socket stream.\n- [x] `address()`: Returns the bound address.\n- [x] `remoteAddress`: The string representation of the remote IP address.\n- [x] `remotePort`: The numeric representation of the remote port.\n- [x] `bytesRead`: The amount of received bytes.\n- [x] `bytesWritten`: The amount of bytes sent.\n\n##### Events\n\n- [x] `connect`: Emitted when a socket connection is successfully established.\n- [x] `data`: Emitted when data is received.\n- [x] `end`: Emitted when the other end of the socket sends a FIN packet.\n- [x] `error`: Emitted when an error occurs.\n- [x] `close`: Emitted once the socket is fully closed.\n- [x] `timeout`: Emitted if the socket times out from (read) inactivity.\n\n### HTTP\n\n\u003e The HTTP package is inspired by Node.js' [undici](https://undici.nodejs.org/) package.\n\n- [x] `METHODS`: A list of the HTTP methods that are supported by the parser.\n- [x] `STATUS_CODES`: A collection of all the standard HTTP response status codes.\n- [x] `request(url, options?)`: Performs an HTTP request.\n- [x] `createServer(requestHandler?)`: Creates a new HTTP server.\n\n\u003cdetails\u003e\u003csummary\u003eDetails\u003c/summary\u003e\n\u003cp\u003e\u003c/p\u003e\n\n```js\nconst URL = 'http://localhost:3000/foo';\n\nconst { statusCode, headers, body } = await http.request(URL);\n```\n\nRequestOptions\n\n- `method`: (string) - Default: `GET`\n- `headers`: (object) - Default: `null`\n- `body`: (string | Uint8Array | stream.Readable) - Default: `null`\n- `timeout`: (number) - Default: `30000` (30 seconds) - Use `0` to disable it entirely.\n- `throwOnError`: (boolean) - Default: `false` - Whether should throw an error upon receiving a 4xx or 5xx response.\n- `signal`: (AbortSignal) - Default: `null` - Allows you to communicate with the request and abort it.\n\nBody Mixins\n\n\u003e The body mixins are the most common way to format the response body.\n\n- [x] `text()`: Produces a UTF-8 string representation of the body.\n- [x] `json()`: Formats the body using JSON parsing.\n\u003c/details\u003e\n\n#### `http.Server`\n\n\u003e http.Server is a class extending `EventEmitter` and implements `@@asyncIterator`.\n\n- [x] `listen(port, host?)`: Starts the HTTP server listening for connections.\n- [x] `close()`: Stops the server from accepting new connections.\n- [x] `accept()`: Waits for a client to connect and accepts the HTTP request.\n\n##### Events\n\n- [x] `request`: Emitted each time there is a request.\n- [x] `close`: Emitted when the server closes.\n- [x] `clientError`: Emitted when a client connection emits an 'error' event.\n\n#### `http.ServerRequest`\n\n\u003e http.ServerRequest implements `@@asyncIterator`.\n\n- [x] `headers`: The request headers object.\n- [x] `httpVersion`: The HTTP version sent by the client.\n- [x] `method`: The request method as a string.\n- [x] `url`: Request URL string.\n- [x] `text()`: Produces a UTF-8 string representation of the body.\n- [x] `json()`: Formats the body using JSON parsing.\n\n#### `http.ServerResponse`\n\n\u003e http.ServerResponse implements `stream.Writable`.\n\n- [x] `write(data)`: This sends a chunk of the response body.\n- [x] `end(data?)`: Signals that all of the response headers and body have been sent.\n- [x] `writeHead(code, message?, headers?)`: Sends the response headers to the client.\n- [x] `setHeader(name, value)`: Sets a single header value for implicit headers.\n- [x] `getHeader(name)`: Reads out a header that's already been queued but not sent to the client.\n- [x] `getHeaderNames()`: Returns an array containing the unique names of the current outgoing headers.\n- [x] `getHeaders()`: Returns a copy of the current outgoing headers.\n- [x] `hasHeader(name)`: Returns true if the header identified is currently set.\n- [x] `removeHeader(name)`: Removes a header that's queued for implicit sending.\n- [x] `headersSent`: Boolean (read-only). True if headers were sent, false otherwise.\n- [x] `socket`: Reference to the underlying socket.\n\n##### Events\n\n- [x] `finish`: Emitted when the (full) response has been sent.\n\n### Stream\n\n\u003e Streams are very different from Node.js and are based on [async-generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator).\n\n- [x] `pipe(source, ...targets)`: An alias of `pipeline()`.\n- [x] `pipeline(source, ...targets)`: Pipes between streams while forwarding errors.\n- [x] `compose(...targets)`: Combines two or more streams into a Duplex stream.\n\n### Performance Measurement\n\n- [x] `timeOrigin`: Specifies the millisecond timestamp at which the current process began.\n- [x] `now()`: Returns the millisecond timestamp, where 0 represents the start of the current process.\n\n### Test Runner\n\n- [x] `test(description, [options], testFn)`: Registers a test with the default test runner.\n- [x] `TestRunner`: (Class) A main executor to run JavaScript and TypeScript tests.\n\n\u003cdetails\u003e\u003csummary\u003eDetails\u003c/summary\u003e\n\u003cp\u003e\u003c/p\u003e\n\nOptions\n\n- `ignore`: (boolean) - Default: `false` - Ignore test based on a runtime check.\n\nCustom Executors\n\n\u003e You can attach tests to custom runners and run them manually.\n\n```js\nimport { TestRunner } from 'test';\nimport assert from 'assert';\n\nconst runner = new TestRunner();\n\nrunner.failFast = true;\nrunner.filter = null;\n\nrunner.test('a simple test', () =\u003e {\n  assert.equal(1 + 2, 3);\n});\n\nawait runner.run();\n```\n\n\u003c/details\u003e\n\n### Assert\n\n\u003e The assertion API is copied from: https://assert-js.norbert.tech/\n\n- [x] `true(value)`: Asserts that value is equal to true.\n- [x] `false(value)`: Asserts that value is equal to false.\n- [x] `instanceOf(value, class)`: Asserts that value is an instance of specific class.\n- [x] `integer(value)`: Asserts that value is valid integer.\n- [x] `number(value)`: Asserts that value is valid number (integer, float).\n- [x] `oddNumber(value)`: Asserts that value is odd number.\n- [x] `evenNumber(value)`: Asserts that value is event number.\n- [x] `greaterThan(value, limit)`: Asserts that number is greater than.\n- [x] `greaterThanOrEqual(value, limit)`: Asserts that number is greater than or equal.\n- [x] `lessThan(value, limit)`: Asserts that number is less than.\n- [x] `lessThanOrEqual(value, limit)`: Asserts that number is less than or equal.\n- [x] `string(value)`: Asserts that value is valid string.\n- [x] `boolean(value)`: Asserts that value is valid boolean.\n- [x] `equal(actual, expected)`: Asserts that value is equal to expected value.\n- [x] `objectEqual(actual, expected)`: Asserts that value is equal to expected value.\n- [x] `object(value)`: Asserts that value is valid object.\n- [x] `hasFunction(name, object)`: Asserts that object has function.\n- [x] `hasProperty(name, object)`: Asserts that object has property.\n- [x] `isFunction(fn)`: Asserts that value is valid function.\n- [x] `array(value)`: Asserts that value is valid array.\n- [x] `count(expected, arrayValue)`: Asserts that array have specific number of elements.\n- [x] `notEmpty(arrayValue)`: Asserts that array is not empty.\n- [x] `throws(fn, error)`: Asserts that function throws expected exception.\n\n## Testing\n\nDune has a built-in test runner that you can use for testing JavaScript or TypeScript code.\n\n```js\nimport test from 'test';\nimport assert from 'assert';\n\nfunction doSomeMath(a, b) {\n  return a + b;\n}\n\ntest('checking multiple addition values', () =\u003e {\n  for (let a = 1; a \u003c 10; a++) {\n    assert.equal(doSomeMath(a, 5), a + 5);\n  }\n});\n```\n\nYou can run the above suite using the `dune test` subcommand:\n\n```sh\n$ dune test example_test.js\n\nOK  checking multiple addition values\n\nTest result: 1 ok; 0 failed; 0 ignored (0 ms)\n```\n\nFor more testing examples look at the \u003ca href=\"./examples/testing/\"\u003eexamples/testing\u003c/a\u003e directory.\n\n## Debugging Your Code\n\nDune embraces the [V8 Inspector Protocol](https://v8.dev/docs/inspector), a standard employed by Chrome, Edge, and Node.js. This enables the debugging of Dune programs through the utilization of Chrome DevTools or other clients that are compatible with this protocol.\n\nTo enable debugging capabilities, execute Dune with either the `--inspect` or `--inspect-brk` flags.\n\nThe `--inspect` flag permits attaching the debugger at any moment, whereas the `--inspect-brk` option will await the debugger to attach and will pause the execution on the next statement.\n\n\u003e When employing the `--inspect` flag, the code will commence execution promptly. If your program is brief, there may not be sufficient time to establish a debugger connection before the program concludes its execution. In such scenarios, consider using the `--inspect-brk` flag instead.\n\n### Chrome DevTools\n\nLet's attempt debugging a program using Chrome DevTools:\n\n```sh\n$ dune run examples/httpServer.js --inspect-brk\nDebugger listening on ws://127.0.0.1:9229/1513ff37-2f3e-48a3-a4bf-9e3330dc4544\nVisit chrome://inspect to connect to the debugger.\n...\n```\n\nIn a Chromium-based browser like Google Chrome or Microsoft Edge, navigate to `chrome://inspect` and select \"Inspect\" next to the target.\n\n### VS Code\n\nCurrently, there is no extension available for Dune in VS Code. However, you can debug your application in VS Code, by utilizing the following launch configuration in `.vscode/launch.json`:\n\n```json\n{\n  \"type\": \"node\",\n  \"request\": \"launch\",\n  \"name\": \"Debug 'Dune' application\",\n  \"cwd\": \"${workspaceFolder}\",\n  \"program\": \"\u003cSCRIPT\u003e\",\n  \"runtimeExecutable\": \"dune\",\n  \"runtimeArgs\": [\"run\", \"--inspect-brk\"],\n  \"attachSimplePort\": 9229,\n  \"console\": \"integratedTerminal\"\n}\n```\n\n## Contributing\n\nContributions are always welcome!\n\nSee [CONTRIBUTING.md](https://github.com/aalykiot/dune/blob/main/CONTRIBUTING.md) for ways to get started.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faalykiot%2Fdune","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faalykiot%2Fdune","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faalykiot%2Fdune/lists"}