Commit b1a996a
Changed files (4)
docs
docs/.vitepress/config.mts
@@ -68,6 +68,7 @@ export default defineConfig({
{ text: 'Process Promise', link: '/process-promise' },
{ text: 'Process Output', link: '/process-output' },
{ text: 'Contribution Guide', link: '/contribution' },
+ { text: 'Architecture', link: '/architecture' },
{ text: 'Migration from v7', link: '/migration-from-v7' },
{ text: '⚡ zx@lite', link: '/lite' },
],
docs/api.md
@@ -244,8 +244,8 @@ syncProcessCwd(false) // pass false to disable the hook
## `retry()`
-Retries a callback for a few times. Will return after the first
-successful attempt, or will throw after specifies attempts count.
+Retries a callback for a few times. Will return the first
+successful result, or will throw after the specified attempts count.
```js
const p = await retry(10, () => $`curl https://medv.io`)
docs/architecture.md
@@ -0,0 +1,95 @@
+# The zx architecture
+This section helps to better understand the `zx` concepts and logic, and will be useful for those who want to become a project contributor, make tools based on it, or create something similar from scratch.
+
+## High-level modules
+| Module | Description |
+|-------------------------------------------------------------------------|---------------------------------------------------------------------|
+| [zurk](https://github.com/webpod/zurk) | Execution engine for spawning and managing child processes. |
+| [./src/core.ts](https://github.com/google/zx/blob/main/src/core.ts) | `$` factory, presets, utilities, high-level APIs. |
+| [./src/goods.ts](https://github.com/google/zx/blob/main/src/goods.ts) | Utilities for common tasks like fs ops, glob search, fetching, etc. |
+| [./src/cli.ts](https://github.com/google/zx/blob/main/src/cli.ts) | CLI interface and scripts pre-processors. |
+| [./src/deps.ts](https://github.com/google/zx/blob/main/src/deps.ts) | Dependency analyzing and installation. |
+| [./src/vendor.ts](https://github.com/google/zx/blob/main/src/vendor.ts) | Third-party libraries. |
+| [./src/utils.ts](https://github.com/google/zx/blob/main/src/utils.ts) | Generic helpers. |
+| [./src/md.ts](https://github.com/google/zx/blob/main/src/md.ts) | Markdown scripts extractor. |
+| [./src/error.ts](https://github.com/google/zx/blob/main/src/error.ts) | Error handling and formatting. |
+| [./src/global.ts](https://github.com/google/zx/blob/main/src/global.ts) | Global injectors. |
+
+
+## Core design
+
+### `Options`
+A set of options for `$` and `ProcessPromise` configuration. `defaults` holds the initial library preset. `Snapshot` captures the current `Options `context and attaches isolated subparts.
+
+### `$`
+A piece of template literal magic.
+```ts
+interface Shell<
+ S = false,
+ R = S extends true ? ProcessOutput : ProcessPromise,
+> {
+ (pieces: TemplateStringsArray, ...args: any[]): R
+ <O extends Partial<Options> = Partial<Options>, R = O extends { sync: true } ? Shell<true> : Shell>(opts: O): R
+ sync: {
+ (pieces: TemplateStringsArray, ...args: any[]): ProcessOutput
+ (opts: Partial<Omit<Options, 'sync'>>): Shell<true>
+ }
+}
+
+$`cmd ${arg}` // ProcessPromise
+$(opts)`cmd ${arg}` // ProcessPromise
+$.sync`cmd ${arg}` // ProcessOutput
+$.sync(opts)`cmd ${arg}` // ProcessOutput
+```
+
+The `$` factory creates `ProcessPromise` instances and bounds with snapshot-context via `Proxy` and `AsyncLocalStorage`. The trick:
+```ts
+const storage = new AsyncLocalStorage<Options>()
+
+const getStore = () => storage.getStore() || defaults
+
+function within<R>(callback: () => R): R {
+ return storage.run({ ...getStore() }, callback)
+}
+// Inside $ factory ...
+const opts = getStore()
+if (!Array.isArray(pieces)) {
+ return function (this: any, ...args: any) {
+ return within(() => Object.assign($, opts, pieces).apply(this, args))
+ }
+}
+```
+
+### `ProcessPromise`
+A promise-inherited class represents and operates a child process, provides methods for piping, killing, response formatting.
+
+#### Lifecycle
+| Stage | Description |
+|--------------|------------------------|
+| `initial` | Blank instance |
+| `halted` | Awaits running |
+| `running` | Process in action |
+| `fulfilled` | Successfully completed |
+| `rejected` | Failed |
+
+| Gear | Description |
+|--------------|---------------------------------------------------------------------------------------------|
+| `build()` | Produces `cmd` from template and context, applies `quote` to arguments |
+| `run()` | Spawns the process and captures its data via `zurk` events listeners |
+| `finalize()` | Assigns the result to the instance: analyzes status code, invokes `_resolve()`, `_reject()` |
+
+### `ProcessOutput`
+A class that represents the output of a `ProcessPromise`. It provides methods to access the process's stdout, stderr, exit code and extra methods for formatting the output and checking the process's success.
+
+### `Fail`
+Consolidates error handling functionality across the zx library: errors codes mapping, formatting, stack parsing.
+
+## Building
+In the early stages of the project, we [had some difficulties](https://dev.to/antongolub/how-and-why-do-we-bundle-zx-1ca6) with zx packaging. We couldn't find a suitable tool for assembly, so we made our own toolkit based on [esbuild](https://github.com/evanw/esbuild) and [dts-bundle-generator](https://github.com/timocov/dts-bundle-generator). This process is divided into several scripts.
+
+| Script | Description |
+|----------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
+| [`./scripts/build-dts.mjs`](https://github.com/google/zx/blob/main/scripts/build-dts.mjs) | Extracts and merges 3rd-party types, generates `dts` files. |
+| [`./scripts/build-js.mjs`](https://github.com/google/zx/blob/main/scripts/build-js.mjs) | Produces [hybrid bundles](./setup#hybrid) for each package entry point |
+| [`./scripts/build-jsr.mjs`](https://github.com/google/zx/blob/main/scripts/build-jsr.mjs) | Builds extra assets for [JSR](https://jsr.io/@webpod/zx) publishing |
+| [`./scripts/build-tests.mjs`](https://github.com/google/zx/blob/main/scripts/build-test.mjs) | Generates autotests to verify exports consistency |
docs/contribution.md
@@ -28,7 +28,7 @@ You generally only need to submit a CLA once, so if you've already submitted one
again.
## How to Contribute
-Before proposing changes, look for similar ones in the project's [issues](https://github.com/google/zx/issues) and [pull requests](https://github.com/google/zx/pulls). If you can't decide, create a new [discussion](https://github.com/google/zx/discussions) topic, and we will help you figure it out. When ready to move on:
+Before proposing changes, look for similar ones in the project's [issues](https://github.com/google/zx/issues) and [pull requests](https://github.com/google/zx/pulls). If you can't decide, create a new [discussion](https://github.com/google/zx/discussions) topic, and we will help you figure it out. Dive also into [architecture notes](/architecture) to observe design concepts. When ready to move on:
* Prepare your development environment.
* Switch to the recommended version of Node.js