void 0.10.6 → 0.10.8
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/dist/cli/cli.mjs
CHANGED
|
@@ -1967,7 +1967,7 @@ else if (command === "domain") runSubcommandGroup("domain", domainSubcommands, p
|
|
|
1967
1967
|
else if (command === "db") runSubcommandGroup("db", dbSubcommands, parseDbArgs, (root, parsed) => import("../db-DjKE2-A-.mjs").then(({ runDbCommand }) => runDbCommand(root, parsed)));
|
|
1968
1968
|
else if (command === "env") runSubcommandGroup("env", envSubcommands, parseEnvArgs, (root, parsed) => import("../env-CO5XAS9t.mjs").then(({ runEnvCommand }) => runEnvCommand(root, parsed)));
|
|
1969
1969
|
else if (command === "gen") runSubcommandGroup("gen", genSubcommands, parseGenArgs, (root, parsed) => import("../gen-Cf79J4aw.mjs").then(({ runGenCommand }) => runGenCommand(root, parsed)));
|
|
1970
|
-
else if (command === "github") runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (root, parsed) => import("../github-cmd-
|
|
1970
|
+
else if (command === "github") runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (root, parsed) => import("../github-cmd-B6OX9c7d.mjs").then(({ runGithubCommand }) => runGithubCommand(root, parsed)));
|
|
1971
1971
|
else if (command === "build") runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (root, parsed) => import("../build-cmd-Br8qL0rA.mjs").then(({ runBuildCommand }) => runBuildCommand(root, parsed)));
|
|
1972
1972
|
else if (command === "prepare") {
|
|
1973
1973
|
const root = process.cwd();
|
|
@@ -2103,7 +2103,7 @@ else if (command === "-v" || command === "--version") {
|
|
|
2103
2103
|
case "project": return runSubcommandGroup("project", projectSubcommands, parseProjectArgs, (r, p) => import("../project-cmd-DnU7u9QF.mjs").then(({ runProjectCommand }) => runProjectCommand(r, p)));
|
|
2104
2104
|
case "secret": return runSubcommandGroup("secret", secretSubcommands, parseSecretArgs, (r, p) => import("../secret-u7FRvg8d.mjs").then(({ runSecretCommand }) => runSecretCommand(r, p)));
|
|
2105
2105
|
case "domain": return runSubcommandGroup("domain", domainSubcommands, parseDomainArgs, (r, p) => import("../domain-_luIsM_B.mjs").then(({ runDomainCommand }) => runDomainCommand(r, p)));
|
|
2106
|
-
case "github": return runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (r, p) => import("../github-cmd-
|
|
2106
|
+
case "github": return runSubcommandGroup("github", githubSubcommands, parseGithubArgs, (r, p) => import("../github-cmd-B6OX9c7d.mjs").then(({ runGithubCommand }) => runGithubCommand(r, p)));
|
|
2107
2107
|
case "build": return runSubcommandGroup("build", buildSubcommands, parseBuildArgs, (r, p) => import("../build-cmd-Br8qL0rA.mjs").then(({ runBuildCommand }) => runBuildCommand(r, p)));
|
|
2108
2108
|
case "db": return runSubcommandGroup("db", dbSubcommands, parseDbArgs, (r, p) => import("../db-DjKE2-A-.mjs").then(({ runDbCommand }) => runDbCommand(r, p)));
|
|
2109
2109
|
case "env": return runSubcommandGroup("env", envSubcommands, parseEnvArgs, (r, p) => import("../env-CO5XAS9t.mjs").then(({ runEnvCommand }) => runEnvCommand(r, p)));
|
|
@@ -187,35 +187,38 @@ async function runGithubLink(root, client) {
|
|
|
187
187
|
else log.success("GitHub account linked.");
|
|
188
188
|
}
|
|
189
189
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
* instance.
|
|
190
|
+
* Browser round-trip (localhost + PKCE) that joins the caller to their
|
|
191
|
+
* organization's shared GitHub App installations. Returns the number of
|
|
192
|
+
* installations joined. Throws PlatformApiError — including the 503
|
|
193
|
+
* `github_oauth_not_configured` — so callers own the user-facing handling
|
|
194
|
+
* (`runGithubJoin` prints and exits; the connect auto-join fallback falls
|
|
195
|
+
* through to its install-first error).
|
|
197
196
|
*/
|
|
198
|
-
async function
|
|
197
|
+
async function performGithubJoin(client) {
|
|
199
198
|
const verifier = createCodeVerifier();
|
|
200
199
|
const challenge = createCodeChallenge(verifier);
|
|
201
200
|
const state = randomBytes(32).toString("hex");
|
|
201
|
+
const { count } = await awaitBrowserCallback({
|
|
202
|
+
state,
|
|
203
|
+
buildAuthUrl: async (callback) => {
|
|
204
|
+
callback.searchParams.set("state", state);
|
|
205
|
+
const { url } = await client.getGithubJoinUrl(callback.href, challenge);
|
|
206
|
+
return url;
|
|
207
|
+
},
|
|
208
|
+
describeError: (p) => p.get("error") ? "GitHub authorization failed." : null,
|
|
209
|
+
onUrl: (url) => log.message(`Open this URL to join your organization's shared GitHub App installations:\n${import_picocolors.default.cyan(url)}`),
|
|
210
|
+
finalize: async (params) => {
|
|
211
|
+
const joinCode = params.get("join_code");
|
|
212
|
+
if (!joinCode) throw new Error("github: join callback did not return a join code.");
|
|
213
|
+
return client.completeGithubJoin(joinCode, verifier);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
return count;
|
|
217
|
+
}
|
|
218
|
+
async function runGithubJoin(root, client) {
|
|
202
219
|
let count;
|
|
203
220
|
try {
|
|
204
|
-
|
|
205
|
-
state,
|
|
206
|
-
buildAuthUrl: async (callback) => {
|
|
207
|
-
callback.searchParams.set("state", state);
|
|
208
|
-
const { url } = await client.getGithubJoinUrl(callback.href, challenge);
|
|
209
|
-
return url;
|
|
210
|
-
},
|
|
211
|
-
describeError: (p) => p.get("error") ? "GitHub authorization failed." : null,
|
|
212
|
-
onUrl: (url) => log.message(`Open this URL to join your organization's shared GitHub App installations:\n${import_picocolors.default.cyan(url)}`),
|
|
213
|
-
finalize: async (params) => {
|
|
214
|
-
const joinCode = params.get("join_code");
|
|
215
|
-
if (!joinCode) throw new Error("github: join callback did not return a join code.");
|
|
216
|
-
return client.completeGithubJoin(joinCode, verifier);
|
|
217
|
-
}
|
|
218
|
-
}));
|
|
221
|
+
count = await performGithubJoin(client);
|
|
219
222
|
} catch (err) {
|
|
220
223
|
if (err instanceof PlatformApiError && err.status === 503 && err.code === "github_oauth_not_configured") {
|
|
221
224
|
log.error("Organization installation sharing is not enabled on this Void instance.");
|
|
@@ -281,6 +284,26 @@ async function runGithubConnectAuthorize(client, installationId, repoFullName) {
|
|
|
281
284
|
codeVerifier: verifier
|
|
282
285
|
};
|
|
283
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Free-text repository prompt used when the installation's repository list is
|
|
289
|
+
* not enumerable client-side: `repository_selection === 'all'`, or a shared
|
|
290
|
+
* org installation whose list the server redacts for non-owner members. The
|
|
291
|
+
* server re-verifies actual access on connect, so this is DX, not security.
|
|
292
|
+
*/
|
|
293
|
+
async function promptRepoFullName(root) {
|
|
294
|
+
const gitDefault = parseGithubRepoFullName(collectGitDeployMetadata(root, null).repositoryUrl);
|
|
295
|
+
const input = await text({
|
|
296
|
+
message: "Repository (owner/repo):",
|
|
297
|
+
placeholder: gitDefault ?? "owner/repo",
|
|
298
|
+
initialValue: gitDefault ?? "",
|
|
299
|
+
validate: (value) => /^[^/\s]+\/[^/\s]+$/.test((value ?? "").trim()) ? void 0 : "Enter the repository as owner/repo."
|
|
300
|
+
});
|
|
301
|
+
if (isCancel(input)) {
|
|
302
|
+
cancel("Cancelled.");
|
|
303
|
+
process.exit(0);
|
|
304
|
+
}
|
|
305
|
+
return input.trim();
|
|
306
|
+
}
|
|
284
307
|
async function runConnect(root, client, args) {
|
|
285
308
|
const isTTY = process.stdin.isTTY === true;
|
|
286
309
|
let projectId;
|
|
@@ -318,14 +341,36 @@ async function runConnect(root, client, args) {
|
|
|
318
341
|
projectId = picked;
|
|
319
342
|
}
|
|
320
343
|
}
|
|
321
|
-
const
|
|
344
|
+
const listActiveInstallations = async () => (await client.listGithubInstallations()).filter((i) => i.status === "active");
|
|
345
|
+
let autoJoinAttempted = false;
|
|
346
|
+
const attemptAutoJoin = async () => {
|
|
347
|
+
autoJoinAttempted = true;
|
|
348
|
+
try {
|
|
349
|
+
return await performGithubJoin(client);
|
|
350
|
+
} catch (err) {
|
|
351
|
+
if (err instanceof PlatformApiError && err.status === 503 && err.code === "github_oauth_not_configured") return 0;
|
|
352
|
+
throw err;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
let installations = await listActiveInstallations();
|
|
356
|
+
if (installations.length === 0 && isTTY) {
|
|
357
|
+
log.info("No GitHub App installation is linked to your account yet — checking whether your organization already installed the Void GitHub App…");
|
|
358
|
+
if (await attemptAutoJoin() > 0) installations = await listActiveInstallations();
|
|
359
|
+
}
|
|
322
360
|
if (installations.length === 0) {
|
|
323
|
-
log.error("No active GitHub App installation. Run `void github install` first.");
|
|
361
|
+
log.error(isTTY ? "No GitHub App installation found for your account or your organizations. Run `void github install` first." : "No active GitHub App installation. Run `void github install` first, or `void github join` if your organization already installed the Void GitHub App.");
|
|
324
362
|
process.exit(1);
|
|
325
363
|
}
|
|
326
364
|
let installation;
|
|
327
365
|
if (args.installationId) {
|
|
328
|
-
|
|
366
|
+
let found = installations.find((i) => i.installation_id === args.installationId);
|
|
367
|
+
if (!found && isTTY && !autoJoinAttempted) {
|
|
368
|
+
log.info(`Installation '${args.installationId}' is not linked to your account yet — checking whether your organization shares it…`);
|
|
369
|
+
if (await attemptAutoJoin() > 0) {
|
|
370
|
+
installations = await listActiveInstallations();
|
|
371
|
+
found = installations.find((i) => i.installation_id === args.installationId);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
329
374
|
if (!found) {
|
|
330
375
|
log.error(`connect: No active installation found with id '${args.installationId}'.`);
|
|
331
376
|
process.exit(1);
|
|
@@ -352,8 +397,11 @@ async function runConnect(root, client, args) {
|
|
|
352
397
|
let repoFullName;
|
|
353
398
|
if (args.repo) repoFullName = args.repo;
|
|
354
399
|
else if (installation.repository_selection === "selected") if (installation.repositories.length === 0) {
|
|
355
|
-
|
|
356
|
-
|
|
400
|
+
if (!isTTY) {
|
|
401
|
+
log.error("connect: --repo <owner/repo> is required — this installation does not expose a repository list to your account.");
|
|
402
|
+
process.exit(1);
|
|
403
|
+
}
|
|
404
|
+
repoFullName = await promptRepoFullName(root);
|
|
357
405
|
} else if (installation.repositories.length === 1) repoFullName = installation.repositories[0].full_name;
|
|
358
406
|
else if (!isTTY) {
|
|
359
407
|
log.error("connect: Multiple repositories available. Pass --repo <owner/repo>.");
|
|
@@ -377,21 +425,7 @@ async function runConnect(root, client, args) {
|
|
|
377
425
|
log.error("connect: --repo <owner/repo> is required in non-interactive mode for an all-repositories installation.");
|
|
378
426
|
process.exit(1);
|
|
379
427
|
}
|
|
380
|
-
|
|
381
|
-
const input = await text({
|
|
382
|
-
message: "Repository (owner/repo):",
|
|
383
|
-
placeholder: gitDefault ?? "owner/repo",
|
|
384
|
-
initialValue: gitDefault ?? ""
|
|
385
|
-
});
|
|
386
|
-
if (isCancel(input)) {
|
|
387
|
-
cancel("Cancelled.");
|
|
388
|
-
process.exit(0);
|
|
389
|
-
}
|
|
390
|
-
repoFullName = input.trim();
|
|
391
|
-
if (!repoFullName) {
|
|
392
|
-
log.error("connect: Repository is required.");
|
|
393
|
-
process.exit(1);
|
|
394
|
-
}
|
|
428
|
+
repoFullName = await promptRepoFullName(root);
|
|
395
429
|
}
|
|
396
430
|
const branchDefault = args.branch ?? collectGitDeployMetadata(root, null).gitRef ?? "main";
|
|
397
431
|
let branch;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "void",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.8",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -353,7 +353,7 @@
|
|
|
353
353
|
"valibot": ">=1.0.0-beta.7",
|
|
354
354
|
"vite": "^8.0.0",
|
|
355
355
|
"zod": "^3.25.0 || ^4.0.0",
|
|
356
|
-
"@void/md": "0.10.
|
|
356
|
+
"@void/md": "0.10.8"
|
|
357
357
|
},
|
|
358
358
|
"peerDependenciesMeta": {
|
|
359
359
|
"@void/md": {
|
|
@@ -47,7 +47,8 @@ nums = [x for x in range(10)]
|
|
|
47
47
|
|
|
48
48
|
Output:
|
|
49
49
|
```html
|
|
50
|
-
<pre data="asdf"
|
|
50
|
+
<pre><code data="asdf" class="language-python">
|
|
51
|
+
nums = [x for x in range(10)]
|
|
51
52
|
</code></pre>
|
|
52
53
|
```
|
|
53
54
|
|
|
@@ -292,53 +293,35 @@ Output:
|
|
|
292
293
|
If you need finer control, [decorate](https://github.com/rstacruz/markdown-it-decorate) might help you.
|
|
293
294
|
|
|
294
295
|
## Custom rendering
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
If you prefer markdown-it's default behavior (attributes on `<code>`), opt out:
|
|
296
|
+
If you would like some other output, you can override renderers:
|
|
298
297
|
|
|
299
298
|
```js
|
|
300
299
|
const md = require('markdown-it')();
|
|
301
300
|
const markdownItAttrs = require('markdown-it-attrs');
|
|
302
301
|
|
|
303
|
-
md.use(markdownItAttrs
|
|
304
|
-
fenceAttrsOnPre: false
|
|
305
|
-
});
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
If you need fully custom output, define your own `fence` renderer. The plugin
|
|
309
|
-
will not override an existing custom `fence` renderer.
|
|
310
|
-
|
|
311
|
-
```js
|
|
312
|
-
const md = require('markdown-it')();
|
|
313
|
-
const markdownItAttrs = require('markdown-it-attrs');
|
|
302
|
+
md.use(markdownItAttrs);
|
|
314
303
|
|
|
304
|
+
// custom renderer for fences
|
|
315
305
|
md.renderer.rules.fence = function (tokens, idx, options, env, slf) {
|
|
316
306
|
const token = tokens[idx];
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
return '<pre' + slf.renderAttrs(token) + '><code' + langClass + '>'
|
|
323
|
-
+ content
|
|
324
|
-
+ '</code></pre>\n';
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
md.use(markdownItAttrs);
|
|
307
|
+
return '<pre' + slf.renderAttrs(token) + '>'
|
|
308
|
+
+ '<code>' + token.content + '</code>'
|
|
309
|
+
+ '</pre>';
|
|
310
|
+
}
|
|
328
311
|
|
|
329
|
-
|
|
312
|
+
let src = [
|
|
330
313
|
'',
|
|
331
314
|
'```js {.abcd}',
|
|
332
315
|
'var a = 1;',
|
|
333
316
|
'```'
|
|
334
|
-
].join('\n')
|
|
317
|
+
].join('\n')
|
|
335
318
|
|
|
336
319
|
console.log(md.render(src));
|
|
337
320
|
```
|
|
338
321
|
|
|
339
322
|
Output:
|
|
340
323
|
```html
|
|
341
|
-
<pre class="abcd"><code
|
|
324
|
+
<pre class="abcd"><code>var a = 1;
|
|
342
325
|
</code></pre>
|
|
343
326
|
```
|
|
344
327
|
|
|
@@ -609,6 +609,8 @@ void github join
|
|
|
609
609
|
|
|
610
610
|
Join the GitHub App installations your organization already has. If a teammate installed the Void GitHub App on a shared GitHub organization, run `void github join` to gain access to those installations without re-installing. Void opens your browser to authorize (a localhost + PKCE handshake, the same mechanics as `void github link`), confirms with GitHub which installations you can manage, and records your membership. Afterwards `void github installations` lists them and `void github connect` can connect your own projects to their repositories.
|
|
611
611
|
|
|
612
|
+
In an interactive terminal you rarely need to run this yourself — `void github connect` runs the same join automatically when no active installations are linked to your account. Running `void github join` yourself matters mainly for non-interactive use (without a TTY, `void github connect` never opens a browser), or to link installations ahead of time.
|
|
613
|
+
|
|
612
614
|
Requires an authenticated CLI (`void auth login` first) and organization-installation sharing enabled on your Void instance; when it is not enabled the command fails closed with a clear message. You can only join installations your GitHub authorization actually returns — you cannot name or join one you cannot access on GitHub.
|
|
613
615
|
|
|
614
616
|
### `void github connect`
|
|
@@ -619,6 +621,8 @@ void github connect [project] [options]
|
|
|
619
621
|
|
|
620
622
|
Connect a GitHub repository to a Void project for automatic deploys. On every push to the configured branch, Void builds and deploys your project automatically.
|
|
621
623
|
|
|
624
|
+
Interactively (TTY), if your account has no active installations linked, `void github connect` first runs the same browser authorize as `void github join` automatically — if a teammate already installed the Void GitHub App on your organization, you join it on the spot and the connect continues. Only when no shared installation is found does it ask you to run `void github install`. The same recovery runs when `--installation <id>` names an installation your account is not linked to yet. Without a TTY, connect never opens a browser: it fails closed and tells you to run `void github install`, or `void github join` if your organization already installed the App.
|
|
625
|
+
|
|
622
626
|
**Options**
|
|
623
627
|
|
|
624
628
|
| Flag | Description |
|
|
@@ -636,7 +640,7 @@ Interactively (TTY), after resolving the repository and branch, `void github con
|
|
|
636
640
|
|
|
637
641
|
**Non-interactive use (CI)**
|
|
638
642
|
|
|
639
|
-
When stdin is not a TTY, `void github connect` never prompts — it fails closed and names any flag it needs. `--branch` is always required. `--project` must be resolvable (positional / `--project` / `VOID_PROJECT` / linked `.void/project.json`). `--installation` is required only when your account has more than one installation; otherwise the sole installation is used. `--repo` is required when the installation grants access to all repos or to more than one selected repo; when it grants exactly one repo that repo is used automatically. Use `void github installations` to discover the `installation_id`.
|
|
643
|
+
When stdin is not a TTY, `void github connect` never prompts — it fails closed and names any flag it needs. `--branch` is always required. `--project` must be resolvable (positional / `--project` / `VOID_PROJECT` / linked `.void/project.json`). `--installation` is required only when your account has more than one installation; otherwise the sole installation is used. `--repo` is required when the installation grants access to all repos or to more than one selected repo; when it grants exactly one repo that repo is used automatically. `--repo` is also required when the installation does not expose a repository list to your account (shared org installations hide it). Use `void github installations` to discover the `installation_id`.
|
|
640
644
|
|
|
641
645
|
```
|
|
642
646
|
void github connect my-app \
|
|
@@ -649,7 +653,7 @@ void github connect my-app \
|
|
|
649
653
|
|
|
650
654
|
**Connecting as an organization member**
|
|
651
655
|
|
|
652
|
-
If you are a member of a GitHub organization but not the person who installed the App, `void github connect` first confirms that you personally have access to the specific repository.
|
|
656
|
+
If you are a member of a GitHub organization but not the person who installed the App, `void github connect` first confirms that you personally have access to the specific repository. Interactively (TTY), when it detects this it opens your browser once to authorize access to that repo on GitHub (a localhost + PKCE handshake), then completes the connection automatically — no extra flags. Without a TTY, this per-repo authorization never opens a browser: connect fails closed with an error explaining that the installation requires per-repo authorization, which needs an interactive browser sign-in, and telling you to run `void github connect` locally to authorize, then retry. Interactively, connect joins the shared installation automatically when your account has no active installations linked, so running `void github join` first is optional — useful mainly to see the installation in `void github installations` beforehand. You can only connect repositories you can access on GitHub; one you cannot see is refused with a clear message.
|
|
653
657
|
|
|
654
658
|
### `void github update`
|
|
655
659
|
|