@pyreon/zero-cli 0.1.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present Vit Bokisch
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,33 @@
1
+ # zero-cli
2
+
3
+ CLI for [Pyreon Zero](https://github.com/user/pyreon-zero) — dev server, production builds, and preview.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun add -D zero-cli
9
+ ```
10
+
11
+ ## Commands
12
+
13
+ ```bash
14
+ zero dev [root] # Start development server
15
+ zero build [root] # Build for production
16
+ zero preview [root] # Preview production build
17
+ ```
18
+
19
+ ### Options
20
+
21
+ ```bash
22
+ # dev / preview
23
+ --port <port> # Server port (default: 3000)
24
+ --host [host] # Server host
25
+ --open # Open browser on start
26
+
27
+ # build
28
+ --mode <mode> # Rendering mode override (ssr, ssg, spa)
29
+ ```
30
+
31
+ ## License
32
+
33
+ [MIT](LICENSE)
package/bin/zero.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import('../lib/index.js')
package/lib/index.js ADDED
@@ -0,0 +1,136 @@
1
+ import cac from "cac";
2
+ import { existsSync } from "node:fs";
3
+ import { join, resolve } from "node:path";
4
+ import { build, createServer, preview } from "vite";
5
+
6
+ //#region src/commands/build.ts
7
+ /** Extract zero plugin config from a Vite config file. */
8
+ async function loadZeroConfig(configPath) {
9
+ try {
10
+ const { loadConfigFromFile } = await import("vite");
11
+ const loaded = await loadConfigFromFile({
12
+ command: "build",
13
+ mode: "production"
14
+ }, configPath);
15
+ if (!loaded) return void 0;
16
+ const zeroPlugin = (loaded.config.plugins ?? []).find((p) => p && typeof p === "object" && "name" in p && p.name === "pyreon-zero");
17
+ if (zeroPlugin && "_zeroConfig" in zeroPlugin) return zeroPlugin._zeroConfig;
18
+ } catch {}
19
+ }
20
+ /** Run SSG prerendering pass if configured. */
21
+ async function prerenderIfNeeded(projectRoot, zeroConfig) {
22
+ const serverEntry = join(projectRoot, "dist/server/entry-server.js");
23
+ if (!existsSync(serverEntry)) return;
24
+ try {
25
+ const { prerender } = await import("@pyreon/server");
26
+ const serverModule = await import(serverEntry);
27
+ const paths = await resolveSsgPaths(zeroConfig);
28
+ const result = await prerender({
29
+ handler: serverModule.default,
30
+ paths,
31
+ outDir: join(projectRoot, "dist/client")
32
+ });
33
+ for (const err of result.errors) console.warn("Prerender error:", err);
34
+ } catch {}
35
+ }
36
+ /** Resolve SSG paths from config (static array or async function). */
37
+ async function resolveSsgPaths(zeroConfig) {
38
+ const ssgConfig = zeroConfig?.ssg;
39
+ if (!ssgConfig?.paths) return ["/"];
40
+ return typeof ssgConfig.paths === "function" ? await ssgConfig.paths() : ssgConfig.paths;
41
+ }
42
+ /** Run the deploy adapter build step. */
43
+ async function runAdapter(projectRoot, zeroConfig) {
44
+ try {
45
+ const { resolveAdapter } = await import("@pyreon/zero");
46
+ await resolveAdapter(zeroConfig).build({
47
+ serverEntry: join(projectRoot, "dist/server/entry-server.js"),
48
+ clientOutDir: join(projectRoot, "dist/client"),
49
+ outDir: join(projectRoot, "dist/output"),
50
+ config: zeroConfig
51
+ });
52
+ } catch {}
53
+ }
54
+ async function build$1(root, options) {
55
+ try {
56
+ await runBuild(root, options);
57
+ } catch (error) {
58
+ console.error("Build failed:", error.message);
59
+ process.exit(1);
60
+ }
61
+ }
62
+ async function runBuild(root, options) {
63
+ const projectRoot = resolve(root ?? ".");
64
+ const start = performance.now();
65
+ await build({
66
+ root: projectRoot,
67
+ build: {
68
+ outDir: "dist/client",
69
+ ssrManifest: true
70
+ }
71
+ });
72
+ await build({
73
+ root: projectRoot,
74
+ build: {
75
+ outDir: "dist/server",
76
+ ssr: "src/entry-server.ts",
77
+ rollupOptions: { input: "src/entry-server.ts" }
78
+ }
79
+ });
80
+ const zeroConfig = await loadZeroConfig(join(projectRoot, "vite.config.ts"));
81
+ const renderMode = zeroConfig?.mode ?? options.mode ?? "ssr";
82
+ if (renderMode === "ssg" || renderMode === "isr") await prerenderIfNeeded(projectRoot, zeroConfig);
83
+ if (!((zeroConfig?.adapter ?? "node") === "static" && renderMode === "ssg")) await runAdapter(projectRoot, zeroConfig ?? {});
84
+ const elapsed = Math.round(performance.now() - start);
85
+ console.log(`Build completed in ${elapsed}ms`);
86
+ }
87
+
88
+ //#endregion
89
+ //#region src/commands/dev.ts
90
+ async function dev(root, options) {
91
+ try {
92
+ const server = await createServer({
93
+ root: resolve(root ?? "."),
94
+ server: {
95
+ port: options.port ?? 3e3,
96
+ host: options.host === true ? "0.0.0.0" : options.host,
97
+ open: options.open
98
+ }
99
+ });
100
+ await server.listen();
101
+ server.printUrls();
102
+ } catch (error) {
103
+ console.error("Failed to start dev server:", error.message);
104
+ process.exit(1);
105
+ }
106
+ }
107
+
108
+ //#endregion
109
+ //#region src/commands/preview.ts
110
+ async function preview$1(root, options) {
111
+ try {
112
+ (await preview({
113
+ root: resolve(root ?? "."),
114
+ preview: {
115
+ port: options.port ?? 3e3,
116
+ host: options.host === true ? "0.0.0.0" : options.host
117
+ }
118
+ })).printUrls();
119
+ } catch (error) {
120
+ console.error("Failed to start preview server:", error.message);
121
+ process.exit(1);
122
+ }
123
+ }
124
+
125
+ //#endregion
126
+ //#region src/index.ts
127
+ const cli = cac("zero");
128
+ cli.command("[root]", "Start dev server").alias("dev").option("--port <port>", "Server port", { default: 3e3 }).option("--host [host]", "Server host").option("--open", "Open browser on start").action(dev);
129
+ cli.command("build [root]", "Build for production").option("--mode <mode>", "Rendering mode override").action(build$1);
130
+ cli.command("preview [root]", "Preview production build").option("--port <port>", "Server port", { default: 3e3 }).option("--host [host]", "Server host").action(preview$1);
131
+ cli.help();
132
+ cli.version("0.0.1");
133
+ cli.parse();
134
+
135
+ //#endregion
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["build","viteBuild","preview","vitePreview","build","preview"],"sources":["../src/commands/build.ts","../src/commands/dev.ts","../src/commands/preview.ts","../src/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { build as viteBuild } from 'vite'\n\nexport interface BuildOptions {\n mode?: string\n}\n\n/** Extract zero plugin config from a Vite config file. */\nasync function loadZeroConfig(\n configPath: string,\n): Promise<Record<string, unknown> | undefined> {\n try {\n const { loadConfigFromFile } = await import('vite')\n const loaded = await loadConfigFromFile(\n { command: 'build', mode: 'production' },\n configPath,\n )\n if (!loaded) return undefined\n\n const plugins = (loaded.config.plugins ?? []) as Array<{\n name?: string\n _zeroConfig?: Record<string, unknown>\n }>\n const zeroPlugin = plugins.find(\n (p) =>\n p && typeof p === 'object' && 'name' in p && p.name === 'pyreon-zero',\n )\n if (zeroPlugin && '_zeroConfig' in zeroPlugin) {\n return zeroPlugin._zeroConfig as Record<string, unknown>\n }\n } catch {\n // Config loading is optional — fall back to defaults\n }\n return undefined\n}\n\n/** Run SSG prerendering pass if configured. */\nasync function prerenderIfNeeded(\n projectRoot: string,\n zeroConfig: Record<string, unknown> | undefined,\n) {\n const serverEntry = join(projectRoot, 'dist/server/entry-server.js')\n if (!existsSync(serverEntry)) return\n\n try {\n const { prerender } = await import('@pyreon/server')\n const serverModule = await import(serverEntry)\n\n const paths = await resolveSsgPaths(zeroConfig)\n const result = await prerender({\n handler: serverModule.default,\n paths,\n outDir: join(projectRoot, 'dist/client'),\n })\n\n for (const err of result.errors) {\n console.warn('Prerender error:', err)\n }\n } catch {\n // Prerender is best-effort — build continues without it\n }\n}\n\n/** Resolve SSG paths from config (static array or async function). */\nasync function resolveSsgPaths(\n zeroConfig: Record<string, unknown> | undefined,\n): Promise<string[]> {\n const ssgConfig = zeroConfig?.ssg as\n | { paths?: string[] | (() => string[] | Promise<string[]>) }\n | undefined\n if (!ssgConfig?.paths) return ['/']\n return typeof ssgConfig.paths === 'function'\n ? await ssgConfig.paths()\n : ssgConfig.paths\n}\n\n/** Run the deploy adapter build step. */\nasync function runAdapter(\n projectRoot: string,\n zeroConfig: Record<string, unknown>,\n) {\n try {\n const { resolveAdapter } = await import('@pyreon/zero')\n const adapter = resolveAdapter(zeroConfig)\n await adapter.build({\n serverEntry: join(projectRoot, 'dist/server/entry-server.js'),\n clientOutDir: join(projectRoot, 'dist/client'),\n outDir: join(projectRoot, 'dist/output'),\n config: zeroConfig,\n })\n } catch {\n // Adapter build is optional — output may not need it\n }\n}\n\nexport async function build(root: string | undefined, options: BuildOptions) {\n try {\n await runBuild(root, options)\n } catch (error) {\n console.error('Build failed:', (error as Error).message)\n process.exit(1)\n }\n}\n\nasync function runBuild(root: string | undefined, options: BuildOptions) {\n const projectRoot = resolve(root ?? '.')\n const start = performance.now()\n\n // Client build\n await viteBuild({\n root: projectRoot,\n build: { outDir: 'dist/client', ssrManifest: true },\n })\n\n // Server build\n await viteBuild({\n root: projectRoot,\n build: {\n outDir: 'dist/server',\n ssr: 'src/entry-server.ts',\n rollupOptions: { input: 'src/entry-server.ts' },\n },\n })\n\n const configPath = join(projectRoot, 'vite.config.ts')\n const zeroConfig = await loadZeroConfig(configPath)\n const renderMode = (zeroConfig?.mode as string) ?? options.mode ?? 'ssr'\n\n if (renderMode === 'ssg' || renderMode === 'isr') {\n await prerenderIfNeeded(projectRoot, zeroConfig)\n }\n\n const adapterName = (zeroConfig?.adapter as string) ?? 'node'\n if (!(adapterName === 'static' && renderMode === 'ssg')) {\n await runAdapter(projectRoot, zeroConfig ?? {})\n }\n\n const elapsed = Math.round(performance.now() - start)\n console.log(`Build completed in ${elapsed}ms`)\n}\n","import { resolve } from 'node:path'\nimport { createServer } from 'vite'\n\nexport interface DevOptions {\n port?: number\n host?: string | boolean\n open?: boolean\n}\n\nexport async function dev(root: string | undefined, options: DevOptions) {\n try {\n const projectRoot = resolve(root ?? '.')\n\n const server = await createServer({\n root: projectRoot,\n server: {\n port: options.port ?? 3000,\n host: options.host === true ? '0.0.0.0' : options.host,\n open: options.open,\n },\n })\n\n await server.listen()\n server.printUrls()\n } catch (error) {\n console.error('Failed to start dev server:', (error as Error).message)\n process.exit(1)\n }\n}\n","import { resolve } from 'node:path'\nimport { preview as vitePreview } from 'vite'\n\nexport interface PreviewOptions {\n port?: number\n host?: string | boolean\n}\n\nexport async function preview(\n root: string | undefined,\n options: PreviewOptions,\n) {\n try {\n const projectRoot = resolve(root ?? '.')\n\n const server = await vitePreview({\n root: projectRoot,\n preview: {\n port: options.port ?? 3000,\n host: options.host === true ? '0.0.0.0' : options.host,\n },\n })\n\n server.printUrls()\n } catch (error) {\n console.error('Failed to start preview server:', (error as Error).message)\n process.exit(1)\n }\n}\n","import cac from 'cac'\nimport { build } from './commands/build'\nimport { dev } from './commands/dev'\nimport { preview } from './commands/preview'\n\nconst cli = cac('zero')\n\ncli\n .command('[root]', 'Start dev server')\n .alias('dev')\n .option('--port <port>', 'Server port', { default: 3000 })\n .option('--host [host]', 'Server host')\n .option('--open', 'Open browser on start')\n .action(dev)\n\ncli\n .command('build [root]', 'Build for production')\n .option('--mode <mode>', 'Rendering mode override')\n .action(build)\n\ncli\n .command('preview [root]', 'Preview production build')\n .option('--port <port>', 'Server port', { default: 3000 })\n .option('--host [host]', 'Server host')\n .action(preview)\n\ncli.help()\ncli.version('0.0.1')\ncli.parse()\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@pyreon/zero-cli",
3
+ "version": "0.1.1",
4
+ "description": "CLI for Pyreon Zero — dev, build, preview",
5
+ "license": "MIT",
6
+ "author": "Vit Bokisch",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/pyreon/zero",
10
+ "directory": "packages/cli"
11
+ },
12
+ "type": "module",
13
+ "main": "./lib/index.js",
14
+ "files": [
15
+ "bin",
16
+ "lib",
17
+ "!lib/analysis",
18
+ "LICENSE",
19
+ "README.md"
20
+ ],
21
+ "bin": {
22
+ "zero": "./bin/zero.js"
23
+ },
24
+ "scripts": {
25
+ "build": "vl_rolldown_build",
26
+ "dev": "vl_rolldown_build-watch",
27
+ "typecheck": "tsc --noEmit"
28
+ },
29
+ "dependencies": {
30
+ "@pyreon/server": "^0.2.1",
31
+ "@pyreon/zero": "workspace:^",
32
+ "cac": "^7.0.0",
33
+ "vite": "^8.0.0"
34
+ }
35
+ }