Skip to content

Commit b1a996a

Browse files
authored
docs: add architecture notes (#1290)
1 parent c06d3c6 commit b1a996a

4 files changed

Lines changed: 99 additions & 3 deletions

File tree

docs/.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export default defineConfig({
6868
{ text: 'Process Promise', link: '/process-promise' },
6969
{ text: 'Process Output', link: '/process-output' },
7070
{ text: 'Contribution Guide', link: '/contribution' },
71+
{ text: 'Architecture', link: '/architecture' },
7172
{ text: 'Migration from v7', link: '/migration-from-v7' },
7273
{ text: '⚡ zx@lite', link: '/lite' },
7374
],

docs/api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ syncProcessCwd(false) // pass false to disable the hook
244244
245245
## `retry()`
246246

247-
Retries a callback for a few times. Will return after the first
248-
successful attempt, or will throw after specifies attempts count.
247+
Retries a callback for a few times. Will return the first
248+
successful result, or will throw after the specified attempts count.
249249

250250
```js
251251
const p = await retry(10, () => $`curl https://medv.io`)

docs/architecture.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# The zx architecture
2+
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.
3+
4+
## High-level modules
5+
| Module | Description |
6+
|-------------------------------------------------------------------------|---------------------------------------------------------------------|
7+
| [zurk](https://github.com/webpod/zurk) | Execution engine for spawning and managing child processes. |
8+
| [./src/core.ts](https://github.com/google/zx/blob/main/src/core.ts) | `$` factory, presets, utilities, high-level APIs. |
9+
| [./src/goods.ts](https://github.com/google/zx/blob/main/src/goods.ts) | Utilities for common tasks like fs ops, glob search, fetching, etc. |
10+
| [./src/cli.ts](https://github.com/google/zx/blob/main/src/cli.ts) | CLI interface and scripts pre-processors. |
11+
| [./src/deps.ts](https://github.com/google/zx/blob/main/src/deps.ts) | Dependency analyzing and installation. |
12+
| [./src/vendor.ts](https://github.com/google/zx/blob/main/src/vendor.ts) | Third-party libraries. |
13+
| [./src/utils.ts](https://github.com/google/zx/blob/main/src/utils.ts) | Generic helpers. |
14+
| [./src/md.ts](https://github.com/google/zx/blob/main/src/md.ts) | Markdown scripts extractor. |
15+
| [./src/error.ts](https://github.com/google/zx/blob/main/src/error.ts) | Error handling and formatting. |
16+
| [./src/global.ts](https://github.com/google/zx/blob/main/src/global.ts) | Global injectors. |
17+
18+
19+
## Core design
20+
21+
### `Options`
22+
A set of options for `$` and `ProcessPromise` configuration. `defaults` holds the initial library preset. `Snapshot` captures the current `Options `context and attaches isolated subparts.
23+
24+
### `$`
25+
A piece of template literal magic.
26+
```ts
27+
interface Shell<
28+
S = false,
29+
R = S extends true ? ProcessOutput : ProcessPromise,
30+
> {
31+
(pieces: TemplateStringsArray, ...args: any[]): R
32+
<O extends Partial<Options> = Partial<Options>, R = O extends { sync: true } ? Shell<true> : Shell>(opts: O): R
33+
sync: {
34+
(pieces: TemplateStringsArray, ...args: any[]): ProcessOutput
35+
(opts: Partial<Omit<Options, 'sync'>>): Shell<true>
36+
}
37+
}
38+
39+
$`cmd ${arg}` // ProcessPromise
40+
$(opts)`cmd ${arg}` // ProcessPromise
41+
$.sync`cmd ${arg}` // ProcessOutput
42+
$.sync(opts)`cmd ${arg}` // ProcessOutput
43+
```
44+
45+
The `$` factory creates `ProcessPromise` instances and bounds with snapshot-context via `Proxy` and `AsyncLocalStorage`. The trick:
46+
```ts
47+
const storage = new AsyncLocalStorage<Options>()
48+
49+
const getStore = () => storage.getStore() || defaults
50+
51+
function within<R>(callback: () => R): R {
52+
return storage.run({ ...getStore() }, callback)
53+
}
54+
// Inside $ factory ...
55+
const opts = getStore()
56+
if (!Array.isArray(pieces)) {
57+
return function (this: any, ...args: any) {
58+
return within(() => Object.assign($, opts, pieces).apply(this, args))
59+
}
60+
}
61+
```
62+
63+
### `ProcessPromise`
64+
A promise-inherited class represents and operates a child process, provides methods for piping, killing, response formatting.
65+
66+
#### Lifecycle
67+
| Stage | Description |
68+
|--------------|------------------------|
69+
| `initial` | Blank instance |
70+
| `halted` | Awaits running |
71+
| `running` | Process in action |
72+
| `fulfilled` | Successfully completed |
73+
| `rejected` | Failed |
74+
75+
| Gear | Description |
76+
|--------------|---------------------------------------------------------------------------------------------|
77+
| `build()` | Produces `cmd` from template and context, applies `quote` to arguments |
78+
| `run()` | Spawns the process and captures its data via `zurk` events listeners |
79+
| `finalize()` | Assigns the result to the instance: analyzes status code, invokes `_resolve()`, `_reject()` |
80+
81+
### `ProcessOutput`
82+
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.
83+
84+
### `Fail`
85+
Consolidates error handling functionality across the zx library: errors codes mapping, formatting, stack parsing.
86+
87+
## Building
88+
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.
89+
90+
| Script | Description |
91+
|----------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
92+
| [`./scripts/build-dts.mjs`](https://github.com/google/zx/blob/main/scripts/build-dts.mjs) | Extracts and merges 3rd-party types, generates `dts` files. |
93+
| [`./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 |
94+
| [`./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 |
95+
| [`./scripts/build-tests.mjs`](https://github.com/google/zx/blob/main/scripts/build-test.mjs) | Generates autotests to verify exports consistency |

docs/contribution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ You generally only need to submit a CLA once, so if you've already submitted one
2828
again.
2929

3030
## How to Contribute
31-
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:
31+
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:
3232

3333
* Prepare your development environment.
3434
* Switch to the recommended version of Node.js

0 commit comments

Comments
 (0)