From 54ce8695579b7e4af2a806c36b76356dd4e87a0d Mon Sep 17 00:00:00 2001 From: Vivek Singh <47470314+heyitsvi@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:50:41 +0530 Subject: [PATCH] Add bare reference to docs (#88) * add files in bare ref * update SUMMARY to contain bare ref * update README to point to bare ref * typo fix * move modules section * add intro to API * tiny fix * add intro to bare modules * add description to cond exports * remove api section from bare modules --------- Co-authored-by: Vivek Singh Co-authored-by: Vivek Singh --- README.md | 2 +- SUMMARY.md | 6 + bare-reference/api.md | 175 ++++++++++++++++ bare-reference/bare-modules.md | 186 ++++++++++++++++++ .../nodejs-compatibility-with-bare.md | 108 ++++++++++ bare-reference/overview.md | 90 +++++++++ 6 files changed, 566 insertions(+), 1 deletion(-) create mode 100644 bare-reference/api.md create mode 100644 bare-reference/bare-modules.md create mode 100644 bare-reference/nodejs-compatibility-with-bare.md create mode 100644 bare-reference/overview.md diff --git a/README.md b/README.md index 5b88663..39881e9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ References for utilizing the Pear runtime. * [Application-Programming-Interface (API)](./reference/api.md) * [Application Configuration](./reference/configuration.md) -> The Pear runtime uses [Bare](https://github.com/holepunchto/bare) JavaScript runtime, which is a small and modular JavaScript runtime for desktop and mobile. +> The Pear runtime uses [Bare](https://github.com/holepunchto/bare) JavaScript runtime, which is a small and modular JavaScript runtime for desktop and mobile. To learn more, see [Bare Reference](./bare-reference/overview.md). ### Guides diff --git a/SUMMARY.md b/SUMMARY.md index 5fea4c2..0d4901d 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -8,6 +8,12 @@ * [Application-Programming-Interface (API)](./reference/api.md) * [Application Configuration](./reference/configuration.md) +### Bare reference +* [Overview](./bare-reference/overview.md) +* [Application-Programming-Interface (API)](./bare-reference/api.md) +* [Node.js Compatibility with Bare](./bare-reference/nodejs-compatibility-with-bare.md) +* [Bare Modules](./bare-reference/bare-modules.md) + ### Guides * [Getting Started](./guide/getting-started.md) diff --git a/bare-reference/api.md b/bare-reference/api.md new file mode 100644 index 0000000..68dc216 --- /dev/null +++ b/bare-reference/api.md @@ -0,0 +1,175 @@ +# API + +This documentation serves as the comprehensive guide to the Bare API, the core JavaScript functionality offered by the Bare runtime environment. + +## `Bare` + +The core JavaScript API of Bare is available through the global `Bare` namespace. + +### `Bare.platform` + +The identifier of the operating system for which Bare was compiled. The possible values are `android`, `darwin`, `ios`, `linux`, and `win32`. + +### `Bare.arch` + +The identifier of the processor architecture for which Bare was compiled. The possible values are `arm`, `arm64`, `ia32`, and `x64`. + +### `Bare.argv` + +The command line arguments passed to the process when launched. + +### `Bare.pid` + +The ID of the current process. + +### `Bare.exitCode` + +The code that will be returned once the process exits. If the process is exited using `Bare.exit()` without specifying a code, `Bare.exitCode` is used. + +### `Bare.suspended` + +Whether or not the process is currently suspended. + +### `Bare.exiting` + +Whether or not the process is currently exiting. + +### `Bare.version` + +The Bare version string. + +### `Bare.versions` + +An object containing the version strings of Bare and its dependencies. + +### `Bare.exit([code])` + +Immediately terminate the process or current thread with an exit status of `code` which defaults to `Bare.exitCode`. + +### `Bare.suspend()` + +Suspend the process and all threads. This will emit a `suspend` event signalling that all work should stop immediately. When all work has stopped and the process would otherwise exit, an `idle` event will be emitted. If the process is not resumed from an `idle` event listener and no additional work is scheduled, the loop will block until the process is resumed. If additional work is scheduled from an `idle` event, the `idle` event will be emitted again once all work has stopped unless the process was resumed. + +### `Bare.resume()` + +Resume the process and all threads after suspension. This can be used to cancel suspension after the `suspend` event has been emitted and up until all `idle` event listeners have run. + +### `Bare.on('uncaughtException', err)` + +Emitted when a JavaScript exception is thrown within an execution context without being caught by any exception handlers within that execution context. By default, uncaught exceptions are printed to `stderr` and the processes aborted. Adding an event listener for the `uncaughtException` event overrides the default behavior. + +### `Bare.on('unhandledRejection', reason, promise)` + +Emitted when a JavaScript promise is rejected within an execution context without that rejection being handled within that execution context. By default, unhandled rejections are printed to `stderr` and the process aborted. Adding an event listener for the `unhandledRejection` event overrides the default behavior. + +### `Bare.on('beforeExit', code)` + +Emitted when the loop runs out of work and before the process or current thread exits. This provides a chance to schedule additional work and keep the process from exiting. If additional work is scheduled, `beforeExit` will be emitted again once the loop runs out of work. + +If the process is exited explicitly, such as by calling `Bare.exit()` or as the result of an uncaught exception, the `beforeExit` event will not be emitted. + +### `Bare.on('exit', code)` + +Emitted just before the process or current thread terminates. Additional work scheduled from an `exit` event listener will be given a chance to run after which the process will terminate. If the process is forcefully terminated from an `exit` event listener, the remaining listeners will not run. + +> [!IMPORTANT] +> Only cleanup work may be scheduled from an `exit` event listener. All I/O, including timers, will be closed on `exit` and can therefore not be used. + +### `Bare.on('teardown')` + +Emitted after the process or current thread has terminated and just before the JavaScript environment is torn down. Additional work must not be scheduled from a `teardown` event listener. Bare itself will register `teardown` event listeners to join dangling threads and unload native addons. + +> [!IMPORTANT] +> `teardown` listeners should generally be prepended to have the listeners run in last in, first out order: +> +> ```js +> Bare.prependListener('teardown', () => { ... }) +> ``` + +### `Bare.on('suspend')` + +Emitted when the process or current thread is suspended. Any in-progress or outstanding work, such as network activity or file system access, should be deferred, cancelled, or paused when the `suspend` event is emitted and no additional work may be scheduled. + +### `Bare.on('idle')` + +Emitted when the process or current thread becomes idle after suspension. If no additional work is scheduled from this event, the loop will block and no additional work be performed until the process is resumed. An `idle` event listener may call `Bare.resume()` to cancel the suspension. + +### `Bare.on('resume')` + +Emitted when the process or current thread resumes after suspension. Deferred and paused work should be continued when the `resume` event is emitted and new work may again be scheduled. + +## `Bare.Addon` + +The `Bare.Addon` namespace provides support for loading native addons, which are typically written in C/C++ and distributed as shared libraries. + +### `const addon = Addon.load(url)` + +Load a static or dynamic native addon identified by `url`. If `url` is not a static native addon, Bare will instead look for a matching dynamic object library. + +### `const unloaded = Addon.unload(url)` + +Unload a dynamic native addon identified by `url`. If the function returns `true`, the addon was unloaded from memory. If it instead returns `false`, the addon is still in use by one or more threads and will only be unloaded from memory when those threads either exit or explicitly unload the addon. + +### `const url = Addon.resolve(specifier, parentURL[, options])` + +Resolve a native addon specifier by searching for a static native addon or dynamic object library matching `specifier` imported from `parentURL`. + +Options include: + +```js +{ + // The name of the addon. If `null`, it will instead be read from the + // resolved `package.json`. + name: null, + // The version of the addon. If `null`, it will instead be read from the + // resolved `package.json`. + version: null +} +``` + +## `Bare.Thread` + +The `Bare.Thread` provides support for lightweight threads. Threads are similar to workers in Node.js, but provide only minimal API surface for creating and joining threads. + +### `Thread.isMainThread` + +`true` if the current thread is the main thread. + +### `Thread.self` + +A reference to the current thread as a `ThreadProxy` object. Will be `null` on the main thread. + +### `Thread.self.data` + +A copy of or, if shared, reference to the `data` buffer that was passed to the current thread on creation. Will be `null` if no buffer was passed. + +### `const thread = new Thread([filename][, options][, callback])` + +Start a new thread that will run the contents of `filename`. If `callback` is provided, its function body will be treated as the contents of `filename` and invoked on the new thread with `Thread.self.data` passed as an argument. + +Options include: + +```js +{ + // Optional data to pass to the thread + data: Buffer | ArrayBuffer | SharedArrayBuffer | External, + // Optional file source, will be read from `filename` if neither `source` nor `callback` are provided + source: string | Buffer, + // Optional source encoding if `source` is a string + encoding: 'utf8', + // Optional stack size in bytes, pass 0 for default + stackSize: 0 +} +``` + +### `const thread = Thread.create([filename][, options][, callback])` + +Convenience method for the `new Thread()` constructor. + +### `thread.joined` + +Whether or not the thread has been joined with the current thread. + +### `thread.join()` + +Block and wait for the thread to exit. diff --git a/bare-reference/bare-modules.md b/bare-reference/bare-modules.md new file mode 100644 index 0000000..bb3e140 --- /dev/null +++ b/bare-reference/bare-modules.md @@ -0,0 +1,186 @@ +# Bare Modules + +Bare modules provide a robust system for managing code dependencies within Bare applications. This section delves into the details of Bare's module system. + +``` +npm i bare-module +``` + +## Usage + +```js +const Module = require('bare-module') +```` + +## External Modules for Bare +Supported Modules | +:--- | + + + + + + + + + + + + + + + + + + + + + + + + + + +## Packages + +A package is directory with a `package.json` file. + +### Fields + +#### `"name"` + +```json +{ + "name": "my-package" +} +``` + +The name of the package. This is used for [addon resolution](https://github.com/holepunchto/bare-addon-resolve#algorithm), [self-referencing](#self-referencing), and importing packages by name. + +#### `"version"` + +```json +{ + "version": "1.2.3" +} +``` + +The current version of the package. This is used for [addon resolution](https://github.com/holepunchto/bare-addon-resolve#algorithm). + +#### `"type"` + +```json +{ + "type": "module" +} +``` + +The module format used for `.js` files. If not defined, `.js` files are interpreted as CommonJS. If set to `"module"` the `.js` files are instead interpreted as ES modules. + +#### `"exports"` + +```json +{ + "exports": { + ".": "./index.js" + } +} +``` + +The entry points of the package. If defined, only the modules explicitly exported by the package may be imported when importing the package by name. + +##### Subpath exports + +A package may define more than one entry point by declaring several subpaths with the main export being `"."`: + +```json +{ + "exports": { + ".": "./index.js", + "./submodule": "./lib/submodule.js" + } +} +``` + +When importing the package by name, `require('my-package')` will resolve to `/my-package/index.js` whereas `require('my-package/submodule')` will resolve to `/my-package/lib/submodule.js`. + +##### Conditional exports + +Conditional exports allow packages to provide different exports for different conditions, such as the module format of the importing module: + +```json +{ + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.cjs" + } + } +} +``` + +When importing the package by name, `require('my-package')` will resolve to `/my-package/index.cjs` whereas `import 'my-package'` will resolve to `/my-package/index.mjs`. + +Similarly, conditional exports can be used to provide different entry points for different runtimes: + +```json +{ + "exports": { + ".": { + "bare": "./bare.js", + "node": "./node.js" + } + } +} +``` + +To provide a fallback for when no other conditions match, the `"default"` condition can be declared: + +```json +{ + "exports": { + ".": { + "bare": "./bare.js", + "node": "./node.js", + "default": "./fallback.js" + } + } +} +``` + +The following conditions are supported, listed in order from most specific to least specific as conditions should be defined: + +Condition | Description +:-- | :-- +`"bare"` | This applies when the module is being imported from another Bare module. +`"node"` | This applies when the module is being imported within a Node.js environment. +`"import"` | This applies when the module is being imported using an ES module import statement. +`"require"` | This applies when the module is being imported using the CommonJS require() function. +`"default"` | This serves as a fallback export if none of the more specific conditions (bare, node, import, require) are met. + +##### Self-referencing + +Within a package, exports defined in the `"exports"` field can be referenced by importing the package by name. For example, given the following `package.json`... + +```json +{ + "name": "my-package", + "exports": { + ".": "./index.js", + "./submodule": "./lib/submodule.js" + } +} +``` + +...any module within `my-package` may reference these entry points using either `require('my-package')` or `require('my-package/submodule')`. + +##### Exports sugar + +If a package defines only a single export, `"."`, it may leave out the subpath entirely: + +```json +{ + "exports": "./index.js" +} +``` + diff --git a/bare-reference/nodejs-compatibility-with-bare.md b/bare-reference/nodejs-compatibility-with-bare.md new file mode 100644 index 0000000..23dbe5a --- /dev/null +++ b/bare-reference/nodejs-compatibility-with-bare.md @@ -0,0 +1,108 @@ +# Node.js Compatibility with Bare +Bare offers seamless compatibility with Node.js counterparts. +Most of the modules and APIs used by developers are covered and supported. + +## Currently supported modules + +* `child_process`: [`bare-subprocess`](https://github.com/holepunchto/bare-subprocess) (through `npm:bare-node-child-process)` +* `console`: [`bare-console`](https://github.com/holepunchto/bare-console) (through `npm:bare-node-console)` +* `events`: [`bare-events`](https://github.com/holepunchto/bare-events) (through `npm:bare-node-events)` +* `fs`: [`bare-fs`](https://github.com/holepunchto/bare-fs) (through `npm:bare-node-fs)` +* `http`: [`bare-http1`](https://github.com/holepunchto/bare-http1) (through `npm:bare-node-http)` +* `inspector`: [`bare-inspector`](https://github.com/holepunchto/bare-inspector) (through `npm:bare-node-inspector)` +* `os`: [`bare-os`](https://github.com/holepunchto/bare-os) (through `npm:bare-node-os)` +* `path`: [`bare-path`](https://github.com/holepunchto/bare-path) (through `npm:bare-node-path)` +* `process`: [`bare-process`](https://github.com/holepunchto/bare-process) (through `npm:bare-node-process)` +* `readline`: [`bare-readline`](https://github.com/holepunchto/bare-readline) (through `npm:bare-node-readline)` +* `repl`: [`bare-repl`](https://github.com/holepunchto/bare-repl) (through `npm:bare-node-repl)` +* `tty`: [`bare-tty`](https://github.com/holepunchto/bare-tty) (through `npm:bare-node-tty)` +* `url`: [`bare-url`](https://github.com/holepunchto/bare-url) (through `npm:bare-node-url)` + +## Config for the Node.js stdlib + +To get the full Node.js compatible layer that Bare currently supports add the following lines to the package.json file. + +```json +{ + "dependencies": { + "bare-subprocess": "^2.0.4", + "child_process": "npm:bare-node-child-process", + "bare-console": "^4.1.0", + "console": "npm:bare-node-console", + "bare-events": "^2.2.0", + "events": "npm:bare-node-events", + "bare-fs": "^2.1.5", + "fs": "npm:bare-node-fs", + "bare-http1": "^2.0.3", + "http": "npm:bare-node-http", + "bare-inspector": "^1.1.2", + "inspector": "npm:bare-node-inspector", + "bare-os": "^2.2.0", + "os": "npm:bare-node-os", + "bare-path": "^2.1.0", + "path": "npm:bare-node-path", + "bare-process": "^1.3.0", + "process": "npm:bare-node-process", + "bare-readline": "^1.0.0", + "readline": "npm:bare-node-readline", + "bare-repl": "^1.0.3", + "repl": "npm:bare-node-repl", + "bare-tty": "^3.2.0", + "tty": "npm:bare-node-tty", + "bare-url": "^1.0.7", + "url": "npm:bare-node-url" + } +} +``` +## Example + +### Support for 'fs' + +Simply add the following lines in the package.json file for using 'fs' in a Bare Application. + +```json +{ + "dependencies": { + "bare-fs": "^2.1.5", + "fs": "npm:bare-node-fs" + } +} +``` + +Firstly, install `bare-fs` newer than `^2.1.5`. +Then, alias `fs` to the wrapper `npm:bare-node-fs`. + +The only thing the wrapper does is `module.exports = require('bare-fs')` and at version `*`, +meaning the version that is specified is used. + +Using the wrapper saves space as npm will only include `bare-fs` once if something else installs it. + +## Using import maps + +When writing a module that uses `fs` the mapping can be specified directly in the module instead of relying on the compatible. This can be achieved using an 'import map'. + +For example [Localdrive](https://github.com/holepunchto/localdrive) uses `fs` and to work in both Bare and Node.js it adds the following import map +to the package.json file. + +```json +{ + "imports": { + "fs": { + "bare": "bare-fs", + "default": "fs" + }, + "fs/*": { + "bare": "bare-fs/*", + "default": "fs/*" + } + }, + "optionalDependencies": { + "bare-fs": "^2.1.5" + } +} +``` + +This way the module is in full control of exactly which version of `fs` is bound to Bare. + +This is the best option, as it provides the best of both worlds. Node.js compatibility, but with full control of the dependencies. + diff --git a/bare-reference/overview.md b/bare-reference/overview.md new file mode 100644 index 0000000..55c3a06 --- /dev/null +++ b/bare-reference/overview.md @@ -0,0 +1,90 @@ +# Bare + +[Bare](https://github.com/holepunchto/bare) is a small and modular JavaScript runtime for desktop and mobile. Like Node.js, it provides an asynchronous, event-driven architecture for writing applications in the lingua franca of modern software. Unlike Node.js, it makes embedding and cross-device support core use cases, aiming to run well on any system whether that is a phone or desktop. The result is a runtime ideal for networked, peer-to-peer applications that can run on a wide selection of hardware. + +## Installation + +Prebuilt binaries are provided by [Bare Runtime](https://github.com/holepunchto/bare-runtime) and can be installed using `npm`: + +```sh +npm i -g bare-runtime +``` + +## Usage + +```sh +bare [-e, --eval