Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,20 @@ directive parsing, and network operations, making it easier to debug apps withou

## Parking Lot

### IIFE Build Support

Provide an IIFE (Immediately Invoked Function Expression) build target for VoltX.js to support direct `<script>` tag usage without module systems.

**Deliverables:**

- IIFE build output (voltx.iife.js) alongside ESM build
- Global `Volt` namespace for browser environments
- CDN-friendly distribution (unpkg, jsdelivr)
- Update build pipeline to generate IIFE bundle
- Document usage: `<script src="voltx.iife.min.js"></script>`
- Ensure plugins work with IIFE build
- Add IIFE examples to documentation

### Evaluator & Binder Hardening

All expression evaluation now flows through a cached `new Function` compiler guarded by a hardened scope proxy, with the binder slimmed into a directive registry so plugins self-register while tests verify the sandboxed error surfaces.
83 changes: 83 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# create-voltx

CLI for creating and managing VoltX.js applications.

## Usage

### Create a New Project

```bash
# Using pnpm (recommended)
pnpm create voltx my-app

# Using npm
npm create voltx@latest my-app

# Using npx
npx create-voltx my-app
```

### Commands

#### `init [project-name]`

Create a new VoltX.js project with interactive template selection.

```bash
voltx init my-app
```

**Templates:**

- **Minimal** - Basic VoltX.js app with counter
- **With Router** - Multi-page app with routing
- **With Plugins** - All plugins demo
- **Styles Only** - Just HTML + CSS, no framework

#### `dev`

Start Vite development server.

```bash
voltx dev [--port 3000] [--open]
```

#### `build`

Build project for production.

```bash
voltx build [--out dist]
```

#### `download`

Download VoltX.js assets from CDN.

```bash
voltx download [--version latest] [--output .]
```

## Documentation

See the [CLI Guide](https://stormlightlabs.github.io/volt/cli) for complete documentation.

## Development

```bash
# Install dependencies
pnpm install

# Build CLI
pnpm build

# Run tests
pnpm test

# Type check
pnpm typecheck
```

## License

MIT
25 changes: 25 additions & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "create-voltx",
"version": "0.1.0",
"description": "CLI for creating and managing VoltX.js applications",
"type": "module",
"author": "Owais Jamil",
"license": "MIT",
"repository": { "type": "git", "url": "https://github.com/stormlightlabs/volt.git", "directory": "cli" },
"bin": { "create-voltx": "./dist/index.js", "voltx": "./dist/index.js" },
"files": ["dist", "templates"],
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": { ".": "./dist/index.js", "./package.json": "./package.json" },
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest",
"test:run": "vitest run",
"typecheck": "tsc --noEmit"
},
"devDependencies": { "tsdown": "^0.15.6", "@vitest/coverage-v8": "^3.2.4" },
"dependencies": { "chalk": "^5.6.2", "commander": "^14.0.1", "@inquirer/prompts": "^8.0.1" },
"keywords": ["voltx", "reactive", "framework", "cli", "scaffold", "create"]
}
39 changes: 39 additions & 0 deletions cli/src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { echo } from "$utils/echo.js";
import { spawn } from "node:child_process";

/**
* Builds the VoltX.js project for production using Vite.
*/
export async function buildCommand(options: { outDir?: string } = {}): Promise<void> {
const outDir = options.outDir || "dist";

echo.title("\n⚡ Building VoltX.js project for production...\n");

try {
const { existsSync } = await import("node:fs");
if (!existsSync("index.html")) {
echo.warn("Warning: No index.html found in current directory");
echo.info("Are you in a VoltX.js project?\n");
}

const viteArgs = ["vite", "build", "--outDir", outDir];
const viteProcess = spawn("npx", viteArgs, { stdio: "inherit", shell: true });

viteProcess.on("error", (error) => {
echo.err("Failed to build project:", error);
process.exit(1);
});

viteProcess.on("exit", (code) => {
if (code === 0) {
echo.success(`\n✓ Build completed successfully!\n`);
echo.info(`Output directory: ${outDir}\n`);
} else if (code !== null) {
process.exit(code);
}
});
} catch (error) {
echo.err("Error building project:", error);
process.exit(1);
}
}
47 changes: 47 additions & 0 deletions cli/src/commands/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { echo } from "$utils/echo.js";
import { spawn } from "node:child_process";

/**
* Starts a Vite development server for the current project.
*/
export async function devCommand(options: { port?: number; open?: boolean } = {}): Promise<void> {
const port = options.port || 3000;
const shouldOpen = options.open || false;

echo.title("\n⚡ Starting VoltX.js development server...\n");

try {
const { existsSync } = await import("node:fs");
if (!existsSync("index.html")) {
echo.warn("Warning: No index.html found in current directory");
echo.info("Are you in a VoltX.js project?\n");
}

const viteArgs = ["vite", "--port", port.toString(), "--host"];

if (shouldOpen) {
viteArgs.push("--open");
}

const viteProcess = spawn("npx", viteArgs, { stdio: "inherit", shell: true });

viteProcess.on("error", (error) => {
echo.err("Failed to start dev server:", error);
process.exit(1);
});

viteProcess.on("exit", (code) => {
if (code !== 0 && code !== null) {
process.exit(code);
}
});

process.on("SIGINT", () => {
viteProcess.kill("SIGINT");
process.exit(0);
});
} catch (error) {
echo.err("Error starting dev server:", error);
process.exit(1);
}
}
40 changes: 40 additions & 0 deletions cli/src/commands/download.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { downloadFile, getCDNUrls } from "$utils/download.js";
import { echo } from "$utils/echo.js";
import path from "node:path";

/**
* Downloads VoltX.js assets (JS and/or CSS) from the CDN.
*/
export async function downloadCommand(
options: { version?: string; js?: boolean; css?: boolean; output?: string } = {},
): Promise<void> {
const version = options.version || "latest";
const downloadJS = options.js !== false;
const downloadCSS = options.css !== false;
const outputDir = options.output || ".";

echo.title("\n⚡ Downloading VoltX.js assets...\n");

try {
const urls = getCDNUrls(version);

if (downloadJS) {
const jsPath = path.join(outputDir, "voltx.min.js");
echo.info(`Downloading voltx.min.js (${version})...`);
await downloadFile(urls.js, jsPath);
echo.ok(`✓ Downloaded: ${jsPath}`);
}

if (downloadCSS) {
const cssPath = path.join(outputDir, "voltx.min.css");
echo.info(`Downloading voltx.min.css (${version})...`);
await downloadFile(urls.css, cssPath);
echo.ok(`✓ Downloaded: ${cssPath}`);
}

echo.success("\n✓ Download completed successfully!\n");
} catch (error) {
echo.err("Failed to download assets:", error);
process.exit(1);
}
}
Loading