@hatchkit/dev-plugin-vite 0.1.45

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.
@@ -0,0 +1,9 @@
1
+ import type { Plugin } from "vite";
2
+ export interface LocalDevOptions {
3
+ slug?: string;
4
+ /** Suppress all stdout output (Caddy fragment + tailscale probe
5
+ * still run, just no banner). */
6
+ silent?: boolean;
7
+ }
8
+ export declare function localDev(options?: LocalDevOptions): Plugin;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiDA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;sCACkC;IAClC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,MAAM,CAgC9D"}
package/dist/index.js ADDED
@@ -0,0 +1,137 @@
1
+ /*
2
+ * @hatchkit/dev-plugin-vite — Vite integration for hatchkit's
3
+ * Tailscale-served dev URL flow.
4
+ *
5
+ * Usage:
6
+ *
7
+ * // vite.config.ts
8
+ * import { defineConfig } from "vite";
9
+ * import react from "@vitejs/plugin-react";
10
+ * import { localDev } from "@hatchkit/dev-plugin-vite";
11
+ *
12
+ * export default defineConfig({
13
+ * plugins: [react(), localDev({ slug: "raptor-runner" })],
14
+ * });
15
+ *
16
+ * What it does on `vite` (dev server) startup:
17
+ *
18
+ * 1. Resolves the project's slug from (in order): the explicit
19
+ * `slug` option → `.hatchkit.json` (walking up from cwd) →
20
+ * package.json `name`.
21
+ * 2. Reads the live dev port from the running server's
22
+ * `httpServer.address()` — so `--port` overrides are respected.
23
+ * 3. Writes ~/.config/dev/projects/<slug>.caddy with a
24
+ * `reverse_proxy 127.0.0.1:<port>` directive. Caddy's --watch
25
+ * picks the change up without a restart.
26
+ * 4. Probes `tailscale serve status` for the TCP=443 bridge that
27
+ * `hatchkit dev-setup init` registers once per machine.
28
+ * 5. Replaces Vite's default `Local / Network` URL banner with
29
+ * `Local / Tailscale`. Network-IP entries are dropped — the
30
+ * Tailscale URL covers every device that matters.
31
+ *
32
+ * Failure modes surface inline with actionable hints (see the banner
33
+ * cases in initLocalDev). The plugin never throws — a broken local-dev
34
+ * pipeline should not break the dev server.
35
+ *
36
+ * Opt out entirely with `HATCHKIT_LOCAL_DEV=0`. Production builds
37
+ * (`apply: "serve"`) are pass-through.
38
+ */
39
+ import { isLocalDevActive, localDevUrl, readCaddyPort, resolveSlug, tailscaleIdentity, tailscaleServeTcpTarget, writeProjectFragment, } from "@hatchkit/dev-shared";
40
+ export function localDev(options = {}) {
41
+ return {
42
+ name: "@hatchkit/dev-plugin-vite",
43
+ apply: "serve",
44
+ configureServer(server) {
45
+ if (process.env.HATCHKIT_LOCAL_DEV === "0")
46
+ return;
47
+ const originalPrintUrls = server.printUrls.bind(server);
48
+ server.printUrls = () => {
49
+ const info = server.config.logger.info;
50
+ const resolved = server.resolvedUrls;
51
+ // resolvedUrls is null when the host check rejected every binding;
52
+ // fall back to Vite's own printer so the user still sees something.
53
+ if (!resolved) {
54
+ originalPrintUrls();
55
+ return;
56
+ }
57
+ for (const url of resolved.local) {
58
+ info(` \x1b[32m➜\x1b[0m \x1b[1mLocal\x1b[0m: \x1b[36m${url}\x1b[0m`);
59
+ }
60
+ const addr = server.httpServer?.address();
61
+ const port = typeof addr === "object" && addr ? addr.port : null;
62
+ if (port === null)
63
+ return;
64
+ // Tailscale state is async; fire-and-forget so the banner
65
+ // appends after Local. Vite's logger handles ordering fine
66
+ // even when we trail behind by a few hundred ms.
67
+ void appendTailscaleBanner({ port, options, info });
68
+ };
69
+ },
70
+ };
71
+ }
72
+ async function appendTailscaleBanner({ port, options, info }) {
73
+ const label = (text) => `\x1b[1mTailscale\x1b[0m: ${text}`;
74
+ const greenArrow = "\x1b[32m➜\x1b[0m";
75
+ const yellowArrow = "\x1b[33m➜\x1b[0m";
76
+ const dimArrow = "\x1b[2m➜\x1b[0m";
77
+ const resolved = resolveSlug({ explicit: options.slug });
78
+ if (!resolved) {
79
+ info(` ${yellowArrow} ${label("local-dev disabled (no slug — set { slug } or add a package.json name).")}`);
80
+ return;
81
+ }
82
+ let fragmentResult = "unchanged";
83
+ try {
84
+ fragmentResult = writeProjectFragment(resolved.slug, port);
85
+ }
86
+ catch (err) {
87
+ info(` ${yellowArrow} ${label(`Caddy fragment write failed: ${err.message}`)}`);
88
+ return;
89
+ }
90
+ if (fragmentResult === "created" || fragmentResult === "updated") {
91
+ info(` ${dimArrow} ${label(`rewriting Caddy fragment for port ${port}…`)}`);
92
+ }
93
+ if (!isLocalDevActive()) {
94
+ info(` ${yellowArrow} ${label("host bridge not configured.")}`);
95
+ info(" Run once: `hatchkit dev-setup init` (sets up Caddy + tailscale serve).");
96
+ return;
97
+ }
98
+ const caddyPort = readCaddyPort();
99
+ if (caddyPort === null) {
100
+ info(` ${yellowArrow} ${label("Caddyfile has no https_port directive — re-run `hatchkit dev-setup init`.")}`);
101
+ return;
102
+ }
103
+ const tsId = await tailscaleIdentity();
104
+ if (!tsId) {
105
+ // Tailscale offline / not installed — silent no-op, the user simply
106
+ // isn't on the tailnet today. The Caddy fragment is still in place
107
+ // for when they come back.
108
+ return;
109
+ }
110
+ const tcpTarget = await tailscaleServeTcpTarget();
111
+ if (tcpTarget === null) {
112
+ info(` ${yellowArrow} ${label("no port-443 bridge configured.")}`);
113
+ info(` Run once: \x1b[2mtailscale serve --bg --tcp=443 tcp://localhost:${caddyPort}\x1b[0m`);
114
+ return;
115
+ }
116
+ if (tcpTarget !== caddyPort) {
117
+ info(` ${yellowArrow} ${label(`bridge points at localhost:${tcpTarget} but Caddy listens on ${caddyPort}.`)}`);
118
+ info(" Run: `hatchkit dev-setup init` to reconcile.");
119
+ return;
120
+ }
121
+ if (options.silent)
122
+ return;
123
+ const url = localDevUrl(resolved.slug);
124
+ const where = describeSource(resolved);
125
+ info(` ${greenArrow} ${label(`\x1b[36m${url}\x1b[0m \x1b[2m(slug: ${where})\x1b[0m`)}`);
126
+ }
127
+ function describeSource(resolved) {
128
+ switch (resolved.source) {
129
+ case "explicit":
130
+ return "option";
131
+ case "manifest":
132
+ return ".hatchkit.json";
133
+ case "package-json":
134
+ return "package.json";
135
+ }
136
+ }
137
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@hatchkit/dev-plugin-vite",
3
+ "version": "0.1.45",
4
+ "description": "Vite plugin for hatchkit's local-dev integration. Writes the project's Caddy fragment on dev startup, replaces Vite's Local/Network URL banner with Local/Tailscale.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "dependencies": {
19
+ "@hatchkit/dev-shared": "0.1.45"
20
+ },
21
+ "peerDependencies": {
22
+ "vite": ">=5"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^22.0.0",
26
+ "typescript": "^5.6.0",
27
+ "vite": "^5.4.0"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "typecheck": "tsc --noEmit"
32
+ }
33
+ }