seedcord 0.17.4 → 0.18.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/README.md +58 -9
- package/dist/cli.mjs +63 -49
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-i-qherg7.mjs → src-duSEbkfe.mjs} +3 -3
- package/dist/src-duSEbkfe.mjs.map +1 -0
- package/package.json +28 -19
- package/dist/src-i-qherg7.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,18 +1,67 @@
|
|
|
1
|
-
<
|
|
1
|
+
<div align="center">
|
|
2
2
|
<picture>
|
|
3
3
|
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.seedcord.org/assets/wordmark-dark.webp" />
|
|
4
4
|
<img src="https://cdn.seedcord.org/assets/wordmark-light.webp" alt="seedcord" width="440" />
|
|
5
5
|
</picture>
|
|
6
|
-
</
|
|
6
|
+
</div>
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
<div align="center">
|
|
9
|
+
<h3>The whole Discord bot, wired and typed</h3>
|
|
10
|
+
<a href="https://seedcord.org">Website</a> ·
|
|
11
|
+
<a href="https://guide.seedcord.org">Guide</a> ·
|
|
12
|
+
<a href="https://docs.seedcord.org">Reference</a> ·
|
|
13
|
+
<a href="https://discord.gg/DzFxY58WXf">Discord</a>
|
|
14
|
+
</div>
|
|
9
15
|
|
|
10
|
-
|
|
16
|
+
<br />
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
<div align="center">
|
|
13
19
|
|
|
14
|
-
-
|
|
15
|
-
- Until a major v1.0.0 release for seedcord, expect breaking changes in minor versions.
|
|
16
|
-
- Documentation will come soon as well!
|
|
20
|
+
[](https://www.npmjs.com/package/seedcord) [](https://nodejs.org) [](LICENSE)
|
|
17
21
|
|
|
18
|
-
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
## About
|
|
25
|
+
|
|
26
|
+
`seedcord` is the CLI a bot project runs during development and at build time. It reads `seedcord.config.ts` and gives you a dev server with hot reload, a production build, the codegen that types your commands, and a cleanup tool for stale guild commands.
|
|
27
|
+
|
|
28
|
+
Until v1.0.0, minor versions can break.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
`pnpm create seedcord` adds it to a new project. To add it to an existing one:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
pnpm add -D seedcord
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Commands
|
|
39
|
+
|
|
40
|
+
<!-- prettier-ignore-start -->
|
|
41
|
+
|
|
42
|
+
| command | what it does |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `seedcord dev` | runs the bot from the config file, reloading changed modules in place |
|
|
45
|
+
| `seedcord build` | compiles the project from the config file |
|
|
46
|
+
| `seedcord codegen` | writes the typed augmentations for your commands and config |
|
|
47
|
+
| `seedcord commands` | inspects and cleans commands already deployed to Discord |
|
|
48
|
+
|
|
49
|
+
<!-- prettier-ignore-end -->
|
|
50
|
+
|
|
51
|
+
`codegen --check` verifies the committed augmentations match your source. Run it in CI.
|
|
52
|
+
|
|
53
|
+
`commands --clean` reports guild commands that duplicate a global one. It runs as a dry run until you pass `--apply`.
|
|
54
|
+
|
|
55
|
+
On the http transport, `dev` also opens a cloudflared tunnel and points Discord's interactions URL at it.
|
|
56
|
+
|
|
57
|
+
## Config
|
|
58
|
+
|
|
59
|
+
`defineConfig` types `seedcord.config.ts`:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { defineConfig } from 'seedcord';
|
|
63
|
+
|
|
64
|
+
export default defineConfig({
|
|
65
|
+
// ...
|
|
66
|
+
});
|
|
67
|
+
```
|
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { n as SEEDCORD_CONFIG_FILENAMES, t as version } from "./src-
|
|
1
|
+
import { n as SEEDCORD_CONFIG_FILENAMES, t as version } from "./src-duSEbkfe.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { Command } from "@commander-js/extra-typings";
|
|
4
|
-
import { LEVEL_COLOR, Logger, LoggerChannelRegistry
|
|
4
|
+
import { LEVEL_COLOR, Logger, LoggerChannelRegistry } from "@seedcord/logger";
|
|
5
5
|
import { formatBody, installNodeDefaults } from "@seedcord/logger/node";
|
|
6
6
|
import { Envapter, Environment } from "envapt";
|
|
7
|
-
import { SeedcordErrorCode, isSeedcordError } from "@seedcord/errors";
|
|
7
|
+
import { SeedcordErrorCode, isSeedcordError, paint } from "@seedcord/errors";
|
|
8
8
|
import { existsSync, realpathSync } from "node:fs";
|
|
9
9
|
import { BRAND, SeedcordError, validateDiscordToken } from "@seedcord/errors/internal";
|
|
10
10
|
import { delimiter, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -18,7 +18,6 @@ import { isTsOrJsFile } from "@seedcord/utils/node";
|
|
|
18
18
|
import { ApplicationCommandOptionType, ApplicationCommandType, RESTJSONErrorCodes, Routes } from "discord-api-types/v10";
|
|
19
19
|
import { routeLeavesOf } from "@seedcord/utils/internal";
|
|
20
20
|
import { DiscordAPIError, REST } from "@discordjs/rest";
|
|
21
|
-
import chalk from "chalk";
|
|
22
21
|
import { autocompleteMultiselect, cancel, confirm, intro, isCancel, log, multiselect, note, outro, select, spinner } from "@clack/prompts";
|
|
23
22
|
import { createInterface } from "node:readline";
|
|
24
23
|
import { Box, Text, measureElement, render, useAnimation, useInput, useWindowSize } from "ink";
|
|
@@ -32,6 +31,7 @@ import { assertNever } from "@seedcord/utils";
|
|
|
32
31
|
import { settleWithin } from "@seedcord/core/node/internal";
|
|
33
32
|
import { createServer, createServerModuleRunner, defineConfig, mergeConfig } from "vite";
|
|
34
33
|
import { EvaluatedModules } from "vite/module-runner";
|
|
34
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
35
35
|
import { wrapHot } from "@seedcord/core/internal";
|
|
36
36
|
import { minimatch } from "minimatch";
|
|
37
37
|
import { createServer as createServer$1 } from "node:net";
|
|
@@ -74,28 +74,31 @@ function isOptionalString(value) {
|
|
|
74
74
|
function isStringArray(value) {
|
|
75
75
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
76
76
|
}
|
|
77
|
+
function invalidField(field, expected) {
|
|
78
|
+
return new SeedcordError(SeedcordErrorCode.CliConfigInvalidField, [field, expected]);
|
|
79
|
+
}
|
|
77
80
|
function validateBuild(value) {
|
|
78
81
|
if (value === void 0) return;
|
|
79
|
-
if (!isPlainObject(value)) throw
|
|
80
|
-
if (!isOptionalString(value.outDir)) throw
|
|
81
|
-
if (!isOptionalString(value.tsconfig)) throw
|
|
82
|
-
if (!isOptionalString(value.bootstrap)) throw
|
|
82
|
+
if (!isPlainObject(value)) throw invalidField("build", "an object");
|
|
83
|
+
if (!isOptionalString(value.outDir)) throw invalidField("build.outDir", "a string");
|
|
84
|
+
if (!isOptionalString(value.tsconfig)) throw invalidField("build.tsconfig", "a string");
|
|
85
|
+
if (!isOptionalString(value.bootstrap)) throw invalidField("build.bootstrap", "a string");
|
|
83
86
|
}
|
|
84
87
|
function validateTypecheck(value) {
|
|
85
88
|
if (value === void 0 || typeof value === "boolean") return;
|
|
86
|
-
if (!isPlainObject(value)) throw
|
|
87
|
-
if (!isOptionalString(value.tsconfig)) throw
|
|
89
|
+
if (!isPlainObject(value)) throw invalidField("hmr.typecheck", "a boolean or an object");
|
|
90
|
+
if (!isOptionalString(value.tsconfig)) throw invalidField("hmr.typecheck.tsconfig", "a string");
|
|
88
91
|
}
|
|
89
92
|
function validateHmr(value) {
|
|
90
93
|
if (value === void 0) return;
|
|
91
|
-
if (!isPlainObject(value)) throw
|
|
92
|
-
if (value.restart !== void 0 && !isStringArray(value.restart)) throw
|
|
93
|
-
if (value.rollback !== void 0 && typeof value.rollback !== "boolean") throw
|
|
94
|
+
if (!isPlainObject(value)) throw invalidField("hmr", "an object");
|
|
95
|
+
if (value.restart !== void 0 && !isStringArray(value.restart)) throw invalidField("hmr.restart", "an array of strings");
|
|
96
|
+
if (value.rollback !== void 0 && typeof value.rollback !== "boolean") throw invalidField("hmr.rollback", "a boolean");
|
|
94
97
|
validateTypecheck(value.typecheck);
|
|
95
98
|
}
|
|
96
99
|
function validateTunnel(value) {
|
|
97
100
|
if (value === void 0 || typeof value === "boolean") return;
|
|
98
|
-
if (typeof value !== "string" || URL.parse(value)?.protocol !== "https:") throw
|
|
101
|
+
if (typeof value !== "string" || URL.parse(value)?.protocol !== "https:") throw invalidField("tunnel", "a boolean or an https URL");
|
|
99
102
|
}
|
|
100
103
|
function resolveTunnel(value) {
|
|
101
104
|
if (value === false) return { mode: "off" };
|
|
@@ -117,8 +120,8 @@ function validateConfig(raw) {
|
|
|
117
120
|
if (!isPlainObject(raw)) throw new SeedcordError(SeedcordErrorCode.CliConfigInvalidExport);
|
|
118
121
|
if (typeof raw.instance !== "string" || raw.instance.length === 0) throw new SeedcordError(SeedcordErrorCode.CliConfigMissingInstance);
|
|
119
122
|
if (typeof raw.entry !== "string" || raw.entry.length === 0) throw new SeedcordError(SeedcordErrorCode.CliConfigMissingEntry);
|
|
120
|
-
if (!isOptionalString(raw.root)) throw
|
|
121
|
-
if (raw.idleAnimation !== void 0 && typeof raw.idleAnimation !== "boolean") throw
|
|
123
|
+
if (!isOptionalString(raw.root)) throw invalidField("root", "a string");
|
|
124
|
+
if (raw.idleAnimation !== void 0 && typeof raw.idleAnimation !== "boolean") throw invalidField("idleAnimation", "a boolean");
|
|
122
125
|
validateTunnel(raw.tunnel);
|
|
123
126
|
validateBuild(raw.build);
|
|
124
127
|
validateHmr(raw.hmr);
|
|
@@ -328,7 +331,7 @@ var TypeScriptProjectBuilder = class {
|
|
|
328
331
|
this.logger.info(`Building Seedcord project via tsc using ${tsconfigPath}`);
|
|
329
332
|
try {
|
|
330
333
|
await this.runTsc(projectDir, tsconfigPath);
|
|
331
|
-
await this.
|
|
334
|
+
await this.rewriteSpecifiers(projectDir, tsconfigPath);
|
|
332
335
|
} catch (error) {
|
|
333
336
|
if (isSeedcordError(error)) throw error;
|
|
334
337
|
const reason = Error.isError(error) ? error.message : "Unknown build error";
|
|
@@ -367,11 +370,17 @@ var TypeScriptProjectBuilder = class {
|
|
|
367
370
|
return false;
|
|
368
371
|
}
|
|
369
372
|
}
|
|
370
|
-
async
|
|
371
|
-
const
|
|
372
|
-
const result = await this.runNodeScript(
|
|
373
|
+
async rewriteSpecifiers(projectDir, tsconfigPath) {
|
|
374
|
+
const binPath = this.resolveTscAlias();
|
|
375
|
+
const result = await this.runNodeScript(projectDir, binPath, [
|
|
376
|
+
"-p",
|
|
377
|
+
tsconfigPath,
|
|
378
|
+
"--resolve-full-paths",
|
|
379
|
+
"--resolve-full-extension",
|
|
380
|
+
".js"
|
|
381
|
+
]);
|
|
373
382
|
if (result.exitCode === 0) return;
|
|
374
|
-
throw new SeedcordError(SeedcordErrorCode.CliBuildFailed, [`Failed to
|
|
383
|
+
throw new SeedcordError(SeedcordErrorCode.CliBuildFailed, [`Failed to rewrite import specifiers:\n${this.truncateOutput(result.output)}`]);
|
|
375
384
|
}
|
|
376
385
|
resolveProjectTsc(projectDir) {
|
|
377
386
|
const projectRequire = this.createProjectRequire(projectDir);
|
|
@@ -382,13 +391,8 @@ var TypeScriptProjectBuilder = class {
|
|
|
382
391
|
throw new SeedcordError(SeedcordErrorCode.CliBuildFailed, [`Unable to resolve typescript. Ensure it is installed in this project.\n${reason}`]);
|
|
383
392
|
}
|
|
384
393
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
try {
|
|
388
|
-
return selfRequire.resolve("fix-esm-import-path/fix-esm-import-path.js");
|
|
389
|
-
} catch {
|
|
390
|
-
return selfRequire.resolve("fix-esm-import-path");
|
|
391
|
-
}
|
|
394
|
+
resolveTscAlias() {
|
|
395
|
+
return createRequire(import.meta.url).resolve("tsc-alias/dist/bin/index.js");
|
|
392
396
|
}
|
|
393
397
|
createProjectRequire(projectDir) {
|
|
394
398
|
const candidate = resolve(projectDir, "package.json");
|
|
@@ -1165,7 +1169,7 @@ var InteractivePresenter = class {
|
|
|
1165
1169
|
}
|
|
1166
1170
|
}
|
|
1167
1171
|
preview(scan) {
|
|
1168
|
-
const body = groupByGuild(scan.flagged).map((group) => `${
|
|
1172
|
+
const body = groupByGuild(scan.flagged).map((group) => `${paint.bold(group.guildName)}\n${group.commands.map((c) => ` ${c.name}`).join("\n")}`).join("\n\n");
|
|
1169
1173
|
note(body, `Will delete ${plural(scan.flagged.length, "guild command")} (nothing deleted yet)`);
|
|
1170
1174
|
if (scan.skipped.length > 0) log.warn(skippedSummary(scan.skipped));
|
|
1171
1175
|
}
|
|
@@ -1209,9 +1213,9 @@ var FlagPresenter = class {
|
|
|
1209
1213
|
return task();
|
|
1210
1214
|
}
|
|
1211
1215
|
preview(scan) {
|
|
1212
|
-
this.logger.info(
|
|
1216
|
+
this.logger.info(paint.bold(`${plural(scan.flagged.length, "guild command")} selected for deletion`));
|
|
1213
1217
|
for (const group of groupByGuild(scan.flagged)) {
|
|
1214
|
-
this.logger.info(
|
|
1218
|
+
this.logger.info(paint.sky(group.guildName));
|
|
1215
1219
|
for (const command of group.commands) this.logger.info(` ${command.name}`);
|
|
1216
1220
|
}
|
|
1217
1221
|
for (const skip of scan.skipped) this.logger.warn(`Skipped ${skip.guildName} (${skip.reason}).`);
|
|
@@ -1229,15 +1233,15 @@ var FlagPresenter = class {
|
|
|
1229
1233
|
result(deletion, skipped) {
|
|
1230
1234
|
for (const failure of deletion.failed) this.logger.warn(`Could not delete ${failure.command.name} in ${failure.command.guildName} (${failure.reason}).`);
|
|
1231
1235
|
if (skipped.length > 0) this.logger.warn(skippedSummary(skipped));
|
|
1232
|
-
this.logger.info(
|
|
1236
|
+
this.logger.info(paint.mint(`Deleted ${plural(deletion.deleted, "guild command")}. Global commands untouched.`));
|
|
1233
1237
|
}
|
|
1234
1238
|
nothingToClean(scan, outcome) {
|
|
1235
1239
|
const lines = emptyLines(scan, outcome);
|
|
1236
1240
|
for (const line of lines.info) this.logger.info(line);
|
|
1237
|
-
this.logger.info(
|
|
1241
|
+
this.logger.info(paint.mint(lines.outro));
|
|
1238
1242
|
}
|
|
1239
1243
|
dryRunHint() {
|
|
1240
|
-
this.logger.info(
|
|
1244
|
+
this.logger.info(paint.italic("Dry run. Re-run with --apply to delete the above."));
|
|
1241
1245
|
}
|
|
1242
1246
|
};
|
|
1243
1247
|
|
|
@@ -2298,7 +2302,7 @@ function FilterKeys() {
|
|
|
2298
2302
|
//#endregion
|
|
2299
2303
|
//#region src/ui/components/primitives/Sidebar.tsx
|
|
2300
2304
|
const MAX_RAIL = 40;
|
|
2301
|
-
const META_LABEL_WIDTH =
|
|
2305
|
+
const META_LABEL_WIDTH = 8;
|
|
2302
2306
|
const LOG_DIR = "logs/";
|
|
2303
2307
|
function Meta({ label, value }) {
|
|
2304
2308
|
return /* @__PURE__ */ React.createElement(Text, null, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, label.padEnd(META_LABEL_WIDTH)), value);
|
|
@@ -2306,11 +2310,17 @@ function Meta({ label, value }) {
|
|
|
2306
2310
|
function tunnelValue(status) {
|
|
2307
2311
|
return status === "live" || status === "lost" ? status : `${status}…`;
|
|
2308
2312
|
}
|
|
2313
|
+
function transportLabel({ name }) {
|
|
2314
|
+
return name.replace("@seedcord/", "");
|
|
2315
|
+
}
|
|
2309
2316
|
function StatusBlock({ state, uptimeMs }) {
|
|
2310
2317
|
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(StatusBadge, {
|
|
2311
2318
|
phase: state.phase,
|
|
2312
2319
|
animate: state.idleAnimation
|
|
2313
|
-
}), state.status ? /* @__PURE__ */ React.createElement(Text, null, state.status) : null,
|
|
2320
|
+
}), state.status ? /* @__PURE__ */ React.createElement(Text, null, state.status) : null, state.transport === null ? null : /* @__PURE__ */ React.createElement(Meta, {
|
|
2321
|
+
label: transportLabel(state.transport),
|
|
2322
|
+
value: `v${state.transport.version}`
|
|
2323
|
+
}), uptimeMs === null ? null : /* @__PURE__ */ React.createElement(Meta, {
|
|
2314
2324
|
label: "up",
|
|
2315
2325
|
value: formatUptime(uptimeMs)
|
|
2316
2326
|
}), state.port === null ? null : /* @__PURE__ */ React.createElement(Meta, {
|
|
@@ -2333,7 +2343,7 @@ function Sidebar({ state, enabled, enabledLevels, uptimeMs, following, interacti
|
|
|
2333
2343
|
flexShrink: 0,
|
|
2334
2344
|
paddingX: 1,
|
|
2335
2345
|
overflow: "hidden"
|
|
2336
|
-
}, /* @__PURE__ */ React.createElement(Box, { flexShrink: 0 }, /* @__PURE__ */ React.createElement(Banner, { version
|
|
2346
|
+
}, /* @__PURE__ */ React.createElement(Box, { flexShrink: 0 }, /* @__PURE__ */ React.createElement(Banner, { version })), /* @__PURE__ */ React.createElement(Box, {
|
|
2337
2347
|
flexShrink: 0,
|
|
2338
2348
|
marginTop: 1
|
|
2339
2349
|
}, /* @__PURE__ */ React.createElement(StatusBlock, {
|
|
@@ -2702,13 +2712,13 @@ function profileReport() {
|
|
|
2702
2712
|
|
|
2703
2713
|
//#endregion
|
|
2704
2714
|
//#region src/ui/tier.ts
|
|
2705
|
-
const FULL_ROWS =
|
|
2706
|
-
const COMPACT_ROWS =
|
|
2715
|
+
const FULL_ROWS = 30;
|
|
2716
|
+
const COMPACT_ROWS = 21;
|
|
2707
2717
|
const RAIL_COLUMNS = 80;
|
|
2708
2718
|
function tierFor(rows, columns) {
|
|
2709
2719
|
if (columns < 80) return "logs";
|
|
2710
|
-
if (rows >=
|
|
2711
|
-
if (rows >=
|
|
2720
|
+
if (rows >= 30) return "full";
|
|
2721
|
+
if (rows >= 21) return "compact";
|
|
2712
2722
|
return "logs";
|
|
2713
2723
|
}
|
|
2714
2724
|
|
|
@@ -2796,7 +2806,7 @@ const INITIAL = {
|
|
|
2796
2806
|
status: "Initializing…",
|
|
2797
2807
|
error: null,
|
|
2798
2808
|
isBusy: true,
|
|
2799
|
-
|
|
2809
|
+
transport: null,
|
|
2800
2810
|
restartRequired: false,
|
|
2801
2811
|
commandUpdatePrompt: null,
|
|
2802
2812
|
port: null,
|
|
@@ -2821,8 +2831,8 @@ var DevStore = class extends TypedEventEmitter {
|
|
|
2821
2831
|
setError(error) {
|
|
2822
2832
|
this.patch({ error });
|
|
2823
2833
|
}
|
|
2824
|
-
|
|
2825
|
-
this.patch({
|
|
2834
|
+
setTransport(transport) {
|
|
2835
|
+
this.patch({ transport });
|
|
2826
2836
|
}
|
|
2827
2837
|
setTunnel(tunnel) {
|
|
2828
2838
|
this.patch({ tunnel });
|
|
@@ -3025,7 +3035,10 @@ var DevSession = class {
|
|
|
3025
3035
|
const instance = await Promise.resolve(exported);
|
|
3026
3036
|
if (!isSeedcordInstance(instance)) throw new SeedcordError(SeedcordErrorCode.CliInstanceInvalid);
|
|
3027
3037
|
this.instance = instance;
|
|
3028
|
-
this.store.
|
|
3038
|
+
this.store.setTransport({
|
|
3039
|
+
name: instance.augmentTarget,
|
|
3040
|
+
version: instance.version
|
|
3041
|
+
});
|
|
3029
3042
|
try {
|
|
3030
3043
|
this.store.setPhase("starting");
|
|
3031
3044
|
this.store.setStatus("Starting Seedcord instance…");
|
|
@@ -3033,7 +3046,7 @@ var DevSession = class {
|
|
|
3033
3046
|
await this.startupPromise;
|
|
3034
3047
|
if (this.isStopped) return;
|
|
3035
3048
|
this.store.setPhase("running");
|
|
3036
|
-
this.store.setStatus(`${
|
|
3049
|
+
this.store.setStatus(`${paint.bold(instance.username ?? "Bot")} is ready!`);
|
|
3037
3050
|
profileMark("ready");
|
|
3038
3051
|
onReady?.();
|
|
3039
3052
|
this.startTypecheck();
|
|
@@ -3294,8 +3307,9 @@ var ViteDevRuntime = class {
|
|
|
3294
3307
|
this.hmrPlugin = hmrPlugin;
|
|
3295
3308
|
const config = mergeConfig(vite_config_default, {
|
|
3296
3309
|
root: projectRoot,
|
|
3310
|
+
configFile: false,
|
|
3297
3311
|
server: { watch: { ignored: [logsIgnore(projectRoot)] } },
|
|
3298
|
-
plugins: [hmrPlugin.plugin]
|
|
3312
|
+
plugins: [tsconfigPaths({ root: dirname(this.context.config.configFile) }), hmrPlugin.plugin]
|
|
3299
3313
|
});
|
|
3300
3314
|
this.viteServer = await createServer(config);
|
|
3301
3315
|
this.evaluatedModules = new EvaluatedModules();
|
|
@@ -3585,10 +3599,10 @@ var TunnelCoordinator = class {
|
|
|
3585
3599
|
let patched = false;
|
|
3586
3600
|
try {
|
|
3587
3601
|
this.deps.onStatus("opening");
|
|
3588
|
-
this.deps.logger.info(`${opening(this.deps.kind)} ${paint.
|
|
3602
|
+
this.deps.logger.info(`${opening(this.deps.kind)} ${paint.sky.bold(String(port))}`);
|
|
3589
3603
|
const url = await tunnel.open(attempt.signal, port, () => this.deps.onStatus("resolving"));
|
|
3590
3604
|
if (superseded(attempt)) return;
|
|
3591
|
-
this.deps.logger.info(`Reachable at ${paint.sky.
|
|
3605
|
+
this.deps.logger.info(`Reachable at ${paint.sky.bold(url)} ${since()}`);
|
|
3592
3606
|
this.deps.onStatus("registering");
|
|
3593
3607
|
patched = true;
|
|
3594
3608
|
await this.deps.endpoint.set(url, attempt.signal);
|