zet-execute 1.0.0
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/LICENSE +21 -0
- package/README.md +352 -0
- package/bin/x.mjs +154 -0
- package/dist/context.d.ts +40 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +199 -0
- package/dist/context.js.map +1 -0
- package/dist/dts-content.js +1 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +820 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +12 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +10 -0
- package/dist/loader.js.map +1 -0
- package/dist/publish.d.ts +7 -0
- package/dist/publish.d.ts.map +1 -0
- package/dist/publish.js +89 -0
- package/dist/publish.js.map +1 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +3 -0
- package/dist/register.js.map +1 -0
- package/dist/runner.d.ts +2 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +23 -0
- package/dist/runner.js.map +1 -0
- package/dist/shared.d.ts +22 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +58 -0
- package/dist/shared.js.map +1 -0
- package/dist/types-generator.d.ts +2 -0
- package/dist/types-generator.d.ts.map +1 -0
- package/dist/types-generator.js +22 -0
- package/dist/types-generator.js.map +1 -0
- package/dist/util.d.ts +4 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +11 -0
- package/dist/util.js.map +1 -0
- package/package.json +53 -0
- package/templates/ai-reference.md +106 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ZET Digital
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# zet-execute
|
|
2
|
+
|
|
3
|
+
A project-level task runner for teams. Define dev commands in a config file, run them with `x <command>`.
|
|
4
|
+
|
|
5
|
+
Built for the team at ZET Digital for internal use. You're welcome to use it too.
|
|
6
|
+
|
|
7
|
+
> This is not a CLI framework like Commander or Yargs. Those help you build CLIs. This is a task runner — it runs your project's commands.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install -g zet-execute
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Node.js ^18.19 or >=20.6.
|
|
16
|
+
|
|
17
|
+
## Getting Started
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
mkdir my-project && cd my-project
|
|
21
|
+
x init
|
|
22
|
+
x hello
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`x init` creates an `x.config.mjs` with a starter command. Edit it to add your own. Run `x` or `x --help` to see all registered commands.
|
|
26
|
+
|
|
27
|
+
## Configuration File
|
|
28
|
+
|
|
29
|
+
`x` traverses up from the current directory looking for `x.config.mjs`. Commands are registered as side effects via named imports.
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
import { register } from 'zet-execute';
|
|
33
|
+
|
|
34
|
+
register('up', 'Start containers')
|
|
35
|
+
.run`docker compose up -d`;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API Reference
|
|
39
|
+
|
|
40
|
+
### Command Registration
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
import { register, group } from 'zet-execute';
|
|
44
|
+
|
|
45
|
+
// Simple command
|
|
46
|
+
register('up', 'Start containers')
|
|
47
|
+
.run`docker compose up -d`;
|
|
48
|
+
|
|
49
|
+
// With signature (args, options, rest)
|
|
50
|
+
register('deploy {env} {--Force}', 'Deploy to environment')
|
|
51
|
+
.callback(async ($) => {
|
|
52
|
+
const env = $.arg('env');
|
|
53
|
+
$.info(`Deploying to ${env}...`);
|
|
54
|
+
if ($.option('--force')) $.warn('Force deploy enabled');
|
|
55
|
+
await $.mustRun`deploy.sh ${env}`;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Group
|
|
59
|
+
const db = group('db', 'Database');
|
|
60
|
+
db.register('migrate ...', 'Run migrations').run`docker compose exec app migrate ...`;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Signature Syntax
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
command-name {arg} {arg?} {arg desc} {--option} {--option=} {--Option} {--Opt-Name=} ...
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
| Token | Meaning |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `{name}` | Required positional argument |
|
|
72
|
+
| `{name?}` | Optional positional argument |
|
|
73
|
+
| `{name description}` | Required argument with description |
|
|
74
|
+
| `{name? description}` | Optional argument with description |
|
|
75
|
+
| `{--name}` | Boolean option (flag) |
|
|
76
|
+
| `{--name=}` | Option that accepts a value |
|
|
77
|
+
| `{--Name}` | Boolean option with short flag `-N` |
|
|
78
|
+
| `{--Preserve-Cache=}` | Value option with short flag `-PC` |
|
|
79
|
+
| `...` | Accept extra arguments (rest) |
|
|
80
|
+
|
|
81
|
+
Short flags are derived from uppercase letters at the start of hyphen-separated segments: `--Preserve-Cache` -> `-PC`. The long name is always stored lowercase.
|
|
82
|
+
|
|
83
|
+
### `.run` — Defining Commands
|
|
84
|
+
|
|
85
|
+
`.run` works as both a tagged template (recommended) and a regular function call.
|
|
86
|
+
|
|
87
|
+
**Tagged template (recommended)** — whitespace in static parts is split into separate arguments. Interpolated values are kept as single tokens (safe for paths with spaces).
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
register('build', 'Build project').run`npm run build`;
|
|
91
|
+
|
|
92
|
+
// Interpolation keeps the value as one token
|
|
93
|
+
const target = 'my output dir';
|
|
94
|
+
register('clean', 'Clean output').run`rm -rf ${target}`;
|
|
95
|
+
|
|
96
|
+
// Rest args with ...
|
|
97
|
+
register('npm ...', 'Run npm').run`npm ...`;
|
|
98
|
+
// x npm install lodash -> npm install lodash
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Function call** — also accepts variadic string arguments for programmatic use.
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
register('up', 'Start containers').run('docker', 'compose', 'up', '-d');
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `.userCwd()` Method
|
|
108
|
+
|
|
109
|
+
Run a command from the user's current working directory instead of the project root:
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
register('ls', 'List files')
|
|
113
|
+
.userCwd()
|
|
114
|
+
.run`ls -la`;
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Templates
|
|
118
|
+
|
|
119
|
+
Reuse common command prefixes:
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
import { register, template } from 'zet-execute';
|
|
123
|
+
|
|
124
|
+
const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
|
|
125
|
+
|
|
126
|
+
register('shell', 'Open shell')
|
|
127
|
+
.run`${compose('app')} bash`;
|
|
128
|
+
|
|
129
|
+
register('migrate ...', 'Run migrations')
|
|
130
|
+
.run`${compose('app')} migrate ...`;
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Template functions can return an array of strings or a single string (which gets split on whitespace). Templates validate argument count based on `fn.length`. Zero-arg templates can be used without `()` — `${compose}` works the same as `${compose()}`.
|
|
134
|
+
|
|
135
|
+
### Callback with `$` Context
|
|
136
|
+
|
|
137
|
+
Callbacks receive an `ExecutionContext` object (`$`) with everything needed to run commands and access parsed arguments:
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
register('deploy {env} {--Verbose}')
|
|
141
|
+
.callback(async ($) => {
|
|
142
|
+
const env = $.arg('env'); // string | null
|
|
143
|
+
const verbose = $.option('--verbose'); // string | true | null
|
|
144
|
+
|
|
145
|
+
// Run a command (output visible) — does not throw on failure
|
|
146
|
+
await $.run`deploy.sh ${env}`;
|
|
147
|
+
|
|
148
|
+
// Run and throw on failure
|
|
149
|
+
await $.mustRun`deploy.sh ${env}`;
|
|
150
|
+
|
|
151
|
+
// Run silently (capture output)
|
|
152
|
+
const result = await $.silent`git rev-parse HEAD`;
|
|
153
|
+
$.info(`Deployed ${result.stdout.trim()}`);
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`$.run` and `$.silent` also accept variadic args: `await $.run('docker', 'compose', 'up')`.
|
|
158
|
+
|
|
159
|
+
`$.run` does not throw on failure — use `$.mustRun` or chain `.throw()` to stop on errors.
|
|
160
|
+
|
|
161
|
+
#### `$` Methods
|
|
162
|
+
|
|
163
|
+
| Method | Description |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `$.arg(name)` | Get parsed argument (`string \| null`) |
|
|
166
|
+
| `$.option('--name')` | Get option (`string \| true \| null`) |
|
|
167
|
+
| `$.run\`cmd\`` | Spawn with inherited stdio |
|
|
168
|
+
| `$.mustRun\`cmd\`` | Like `$.run` but throws on non-zero exit code |
|
|
169
|
+
| `$.silent\`cmd\`` | Spawn with piped stdio, returns `CommandOutput` |
|
|
170
|
+
| `$.mustSilent\`cmd\`` | Like `$.silent` but throws on non-zero exit code |
|
|
171
|
+
| `$.info(msg)` | Green message to stdout |
|
|
172
|
+
| `$.warn(msg)` | Yellow message to stderr |
|
|
173
|
+
| `$.error(msg)` | Red message to stderr |
|
|
174
|
+
| `$.confirm(msg)` | Yellow prompt `[y/N]`, returns `boolean` |
|
|
175
|
+
| `$.prompt(msg)` | Cyan prompt, returns the answer |
|
|
176
|
+
| `$.root` | Project root — callable: `$.root('src')`, or string: `` `${$.root}` `` |
|
|
177
|
+
| `$.user` | User CWD — callable: `$.user('test')`, or string: `` `${$.user}` `` |
|
|
178
|
+
| `$.cd(path)` | Change working directory for subsequent `run`/`silent` calls |
|
|
179
|
+
|
|
180
|
+
`$.root` and `$.user` are `PathHelper` objects — they work as both functions and strings via `Symbol.toPrimitive`.
|
|
181
|
+
|
|
182
|
+
#### `CommandOutput`
|
|
183
|
+
|
|
184
|
+
Returned by `$.silent`:
|
|
185
|
+
|
|
186
|
+
| Property | Type |
|
|
187
|
+
|---|---|
|
|
188
|
+
| `.code` | `number` |
|
|
189
|
+
| `.output` | `string \| null` (combined stdout+stderr) |
|
|
190
|
+
| `.stdout` | `string \| null` |
|
|
191
|
+
| `.stderr` | `string \| null` |
|
|
192
|
+
| `.succeeded` | `boolean` |
|
|
193
|
+
| `.failed` | `boolean` |
|
|
194
|
+
| `.throw()` | Throws if failed, returns `this` if succeeded |
|
|
195
|
+
|
|
196
|
+
### Groups
|
|
197
|
+
|
|
198
|
+
Organize commands under a prefix:
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
import { group } from 'zet-execute';
|
|
202
|
+
|
|
203
|
+
const db = group('db', 'Database');
|
|
204
|
+
db.register('migrate ...', 'Run migrations').run`docker compose exec app migrate ...`;
|
|
205
|
+
db.register('seed', 'Seed database').run`docker compose exec app db-seed`;
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
x db migrate --fresh
|
|
210
|
+
x db seed
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The names `init` and `cli` are reserved and cannot be used as group prefixes or command names.
|
|
214
|
+
|
|
215
|
+
### Splitting Config Files
|
|
216
|
+
|
|
217
|
+
Use standard ES module imports to split your config across multiple files:
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
// x.config.mjs
|
|
221
|
+
import { register } from 'zet-execute';
|
|
222
|
+
import './x/docker.mjs';
|
|
223
|
+
import './x/deploy.mjs';
|
|
224
|
+
|
|
225
|
+
register('hello', 'Say hello').run`echo hi`;
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
// x/docker.mjs
|
|
230
|
+
import { register, template } from 'zet-execute';
|
|
231
|
+
|
|
232
|
+
const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
|
|
233
|
+
register('shell', 'Open shell').run`${compose('app')} bash`;
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Templates and groups defined in one file are available to all files — they share the same module singleton. Export a template from a shared file and import it wherever needed:
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
// x/shared.mjs
|
|
240
|
+
import { template } from 'zet-execute';
|
|
241
|
+
export const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
// x/docker.mjs
|
|
246
|
+
import { register } from 'zet-execute';
|
|
247
|
+
import { compose } from './shared.mjs';
|
|
248
|
+
|
|
249
|
+
register('shell', 'Open shell').run`${compose('app')} bash`;
|
|
250
|
+
register('logs', 'View logs').run`docker compose logs -f`;
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Config Paths
|
|
254
|
+
|
|
255
|
+
```js
|
|
256
|
+
import { setAiPublishPath, setIdePublishPath, autoPublishIde } from 'zet-execute';
|
|
257
|
+
|
|
258
|
+
setAiPublishPath('docs/'); // zet-execute.md -> docs/zet-execute.md
|
|
259
|
+
setAiPublishPath('.claude/skills/project/SKILL.md'); // exact file path
|
|
260
|
+
setIdePublishPath('.types/'); // .d.ts -> .types/.x/index.d.ts
|
|
261
|
+
autoPublishIde(); // auto-regenerate .x/index.d.ts on every run
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Built-in Commands
|
|
265
|
+
|
|
266
|
+
### `x init`
|
|
267
|
+
|
|
268
|
+
Creates `x.config.mjs` in the current directory with a starter command.
|
|
269
|
+
|
|
270
|
+
### `x cli publish ai`
|
|
271
|
+
|
|
272
|
+
Generates `zet-execute.md` — an AI agent reference for your project's commands. By default writes to the project root. Configure with `setAiPublishPath()`.
|
|
273
|
+
|
|
274
|
+
### `x cli publish ide`
|
|
275
|
+
|
|
276
|
+
Generates TypeScript declarations for IDE autocompletion. By default writes to `.x/` (with `.gitignore`). Configure with `setIdePublishPath()`.
|
|
277
|
+
|
|
278
|
+
### `x cli init-completion <bash|zsh>`
|
|
279
|
+
|
|
280
|
+
Outputs a shell completion script. Add to your shell profile:
|
|
281
|
+
|
|
282
|
+
```sh
|
|
283
|
+
# bash
|
|
284
|
+
eval "$(x cli init-completion bash)"
|
|
285
|
+
|
|
286
|
+
# zsh
|
|
287
|
+
eval "$(x cli init-completion zsh)"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Common shell profile locations:
|
|
291
|
+
- **bash**: `~/.bashrc` or `~/.bash_profile`
|
|
292
|
+
- **zsh**: `~/.zshrc`
|
|
293
|
+
|
|
294
|
+
### Auto-generated Help
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
x --help # global help
|
|
298
|
+
x <command> --help # command-specific help
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Auto-generated Types
|
|
302
|
+
|
|
303
|
+
When `autoPublishIde()` is called in your config, `x` regenerates `.x/index.d.ts` with TypeScript declarations for IDE support on every run. This happens silently and never breaks normal operation. You can also generate types on demand with `x cli publish ide`.
|
|
304
|
+
|
|
305
|
+
## Full Example
|
|
306
|
+
|
|
307
|
+
```js
|
|
308
|
+
import { register, group, template, setAiPublishPath } from 'zet-execute';
|
|
309
|
+
|
|
310
|
+
setAiPublishPath('docs/');
|
|
311
|
+
|
|
312
|
+
const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
|
|
313
|
+
|
|
314
|
+
// Groups
|
|
315
|
+
const db = group('db', 'Database');
|
|
316
|
+
db.register('migrate ...', 'Run migrations')
|
|
317
|
+
.run`${compose('app')} db-migrate ...`;
|
|
318
|
+
db.register('seed', 'Seed database')
|
|
319
|
+
.run`${compose('app')} db-seed`;
|
|
320
|
+
|
|
321
|
+
// Root commands
|
|
322
|
+
register('up', 'Start all containers')
|
|
323
|
+
.run`docker compose up -d`;
|
|
324
|
+
|
|
325
|
+
register('down', 'Stop all containers')
|
|
326
|
+
.run`docker compose down`;
|
|
327
|
+
|
|
328
|
+
register('deploy {env} {--Force}', 'Deploy to environment')
|
|
329
|
+
.callback(async ($) => {
|
|
330
|
+
const env = $.arg('env');
|
|
331
|
+
if ($.option('--force')) {
|
|
332
|
+
$.warn('Force deploy — skipping checks');
|
|
333
|
+
} else if (!await $.confirm(`Deploy to ${env}?`)) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
$.info(`Deploying to ${env}...`);
|
|
337
|
+
await $.mustRun`deploy.sh ${env}`;
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## How It Works
|
|
342
|
+
|
|
343
|
+
1. `x` binary traverses up from CWD to find `x.config.mjs`
|
|
344
|
+
2. Sets up a module resolution hook so the config can `import { register } from 'zet-execute'`
|
|
345
|
+
3. Imports the config (side effects register commands), then runs the matched command
|
|
346
|
+
4. Commands run from the project root — use `$.root` and `$.user` in callbacks to resolve paths, or `.userCwd()` to run from the user's directory
|
|
347
|
+
|
|
348
|
+
## Test
|
|
349
|
+
|
|
350
|
+
```sh
|
|
351
|
+
npm test
|
|
352
|
+
```
|
package/bin/x.mjs
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
|
+
|
|
8
|
+
const CONFIG_NAME = "x.config.mjs";
|
|
9
|
+
|
|
10
|
+
const cliArgs = process.argv.slice(2);
|
|
11
|
+
|
|
12
|
+
if (cliArgs[0] === "--version" || cliArgs[0] === "-v") {
|
|
13
|
+
const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"));
|
|
14
|
+
process.stdout.write(pkg.version + "\n");
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (cliArgs[0] === "init") {
|
|
19
|
+
const configFile = join(process.cwd(), "x.config.mjs");
|
|
20
|
+
if (existsSync(configFile)) {
|
|
21
|
+
process.stderr.write("x is already initialized in this directory\n");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
writeFileSync(
|
|
25
|
+
configFile,
|
|
26
|
+
`import { register } from 'zet-execute';
|
|
27
|
+
|
|
28
|
+
register('hello', 'Say hello')
|
|
29
|
+
.callback(($) => {
|
|
30
|
+
$.info('Hello from ZET Execute!');
|
|
31
|
+
});
|
|
32
|
+
`
|
|
33
|
+
);
|
|
34
|
+
process.stdout.write("Created x.config.mjs\n");
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if (cliArgs[0] === "cli" && cliArgs[1] === "init-completion") {
|
|
40
|
+
const shell = cliArgs[2];
|
|
41
|
+
if (shell === "bash") {
|
|
42
|
+
process.stdout.write(`_x_completions() {
|
|
43
|
+
local cur=\${COMP_WORDS[COMP_CWORD]}
|
|
44
|
+
local completions
|
|
45
|
+
if [ $COMP_CWORD -eq 1 ]; then
|
|
46
|
+
completions=$(x --completions 2>/dev/null)
|
|
47
|
+
elif [ $COMP_CWORD -eq 2 ]; then
|
|
48
|
+
completions=$(x --completions "\${COMP_WORDS[1]}" 2>/dev/null)
|
|
49
|
+
elif [ $COMP_CWORD -eq 3 ]; then
|
|
50
|
+
completions=$(x --completions "\${COMP_WORDS[1]}" "\${COMP_WORDS[2]}" 2>/dev/null)
|
|
51
|
+
fi
|
|
52
|
+
COMPREPLY=( $(compgen -W "$completions" -- "$cur") )
|
|
53
|
+
}
|
|
54
|
+
complete -F _x_completions x
|
|
55
|
+
`);
|
|
56
|
+
process.exit(0);
|
|
57
|
+
} else if (shell === "zsh") {
|
|
58
|
+
process.stdout.write(`#compdef x
|
|
59
|
+
_x() {
|
|
60
|
+
local -a commands
|
|
61
|
+
if (( CURRENT == 2 )); then
|
|
62
|
+
commands=(\${(f)"$(x --completions 2>/dev/null)"})
|
|
63
|
+
_describe 'command' commands
|
|
64
|
+
elif (( CURRENT == 3 )); then
|
|
65
|
+
commands=(\${(f)"$(x --completions \${words[2]} 2>/dev/null)"})
|
|
66
|
+
_describe 'subcommand' commands
|
|
67
|
+
elif (( CURRENT == 4 )); then
|
|
68
|
+
commands=(\${(f)"$(x --completions \${words[2]} \${words[3]} 2>/dev/null)"})
|
|
69
|
+
_describe 'subcommand' commands
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
_x "$@"
|
|
73
|
+
`);
|
|
74
|
+
process.exit(0);
|
|
75
|
+
} else {
|
|
76
|
+
process.stderr.write("Usage: x cli init-completion <bash|zsh>\n");
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
function findConfig(startDir) {
|
|
83
|
+
let dir = startDir;
|
|
84
|
+
while (true) {
|
|
85
|
+
const candidate = join(dir, CONFIG_NAME);
|
|
86
|
+
if (existsSync(candidate)) return candidate;
|
|
87
|
+
const parent = dirname(dir);
|
|
88
|
+
if (parent === dir) break;
|
|
89
|
+
dir = parent;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const configPath = findConfig(process.cwd());
|
|
95
|
+
|
|
96
|
+
if (!configPath) {
|
|
97
|
+
process.stderr.write(
|
|
98
|
+
"x: cannot find x.config.mjs in the current or any parent directory\n"
|
|
99
|
+
);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Register a module resolution hook so configs can `import { register } from 'zet-execute'`
|
|
104
|
+
const pkgRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
105
|
+
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
106
|
+
|
|
107
|
+
const supported = (major === 18 && minor >= 19) || (major === 20 && minor >= 6) || major > 20;
|
|
108
|
+
if (!supported) {
|
|
109
|
+
const y = !process.env.NO_COLOR && process.stderr.isTTY ? "\x1b[1;33m" : "";
|
|
110
|
+
const r = y ? "\x1b[0m" : "";
|
|
111
|
+
process.stderr.write(
|
|
112
|
+
`${y}x: Node.js ${process.versions.node} is not supported. Requires ^18.19 or >=20.6.${r}\n`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const nodeArgs = [];
|
|
117
|
+
|
|
118
|
+
if (major > 20 || (major === 20 && minor >= 6) || (major === 18 && minor >= 19)) {
|
|
119
|
+
nodeArgs.push(
|
|
120
|
+
"--import",
|
|
121
|
+
pathToFileURL(join(pkgRoot, "dist", "register.js")).href
|
|
122
|
+
);
|
|
123
|
+
} else {
|
|
124
|
+
nodeArgs.push(
|
|
125
|
+
"--loader",
|
|
126
|
+
pathToFileURL(join(pkgRoot, "dist", "loader.js")).href
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const runnerPath = join(pkgRoot, "dist", "runner.js");
|
|
131
|
+
const projectRoot = dirname(configPath);
|
|
132
|
+
|
|
133
|
+
const child = spawn(
|
|
134
|
+
process.execPath,
|
|
135
|
+
[...nodeArgs, runnerPath, configPath, ...process.argv.slice(2)],
|
|
136
|
+
{
|
|
137
|
+
stdio: "inherit",
|
|
138
|
+
env: {
|
|
139
|
+
...process.env,
|
|
140
|
+
X_ROOT_DIR: projectRoot,
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
|
146
|
+
process.on("SIGINT", () => child.kill("SIGINT"));
|
|
147
|
+
|
|
148
|
+
child.on("close", (code, signal) => {
|
|
149
|
+
if (signal) {
|
|
150
|
+
process.kill(process.pid, signal);
|
|
151
|
+
} else {
|
|
152
|
+
process.exit(code ?? 1);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CommandOutput } from "./shared.js";
|
|
2
|
+
export declare const REST_SYMBOL: unique symbol;
|
|
3
|
+
export declare function buildRunParts(strings: TemplateStringsArray, values: unknown[]): (string | symbol)[];
|
|
4
|
+
export declare function expandRestSymbol(parts: (string | symbol)[], restArgs: string[]): string[];
|
|
5
|
+
export declare function spawnCommand(parts: string[], options: {
|
|
6
|
+
stdio: "inherit" | "pipe";
|
|
7
|
+
cwd?: string;
|
|
8
|
+
}): Promise<CommandOutput>;
|
|
9
|
+
export interface PathHelper {
|
|
10
|
+
(sub?: string): string;
|
|
11
|
+
[Symbol.toPrimitive](): string;
|
|
12
|
+
toString(): string;
|
|
13
|
+
}
|
|
14
|
+
export declare function createPathHelper(basePath: string): PathHelper;
|
|
15
|
+
export declare class ExecutionContext {
|
|
16
|
+
private _args;
|
|
17
|
+
private _options;
|
|
18
|
+
private _restArgs;
|
|
19
|
+
private _rootDir;
|
|
20
|
+
private _userDir;
|
|
21
|
+
private _cwd;
|
|
22
|
+
private _rootHelper;
|
|
23
|
+
private _userHelper;
|
|
24
|
+
constructor(args: Record<string, string>, options: Record<string, string | true>, restArgs: string[], rootDir: string, userDir: string, initialCwd: string);
|
|
25
|
+
arg(name: string): string | null;
|
|
26
|
+
option(name: string): string | true | null;
|
|
27
|
+
run(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
|
|
28
|
+
mustRun(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
|
|
29
|
+
silent(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
|
|
30
|
+
mustSilent(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
|
|
31
|
+
info(msg: string): void;
|
|
32
|
+
warn(msg: string): void;
|
|
33
|
+
error(msg: string): void;
|
|
34
|
+
confirm(msg: string): Promise<boolean>;
|
|
35
|
+
prompt(msg: string): Promise<string>;
|
|
36
|
+
get root(): PathHelper;
|
|
37
|
+
get user(): PathHelper;
|
|
38
|
+
cd(path: string): void;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAgC,MAAM,aAAa,CAAC;AAG1E,eAAO,MAAM,WAAW,EAAE,OAAO,MAAuB,CAAC;AAGzD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CA4BnG;AAGD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAUzF;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CA6C1H;AAGD,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC;IAC/B,QAAQ,IAAI,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAK7D;AAGD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;gBAG9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACtC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM;IAYpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIhC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI;IAI1C,GAAG,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAW3F,OAAO,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAK3G,MAAM,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAW9F,UAAU,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAK9G,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIvB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIvB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIlB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAetC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc1C,IAAI,IAAI,IAAI,UAAU,CAErB;IAED,IAAI,IAAI,IAAI,UAAU,CAErB;IAED,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAGvB"}
|