@ape-egg/vibe 1.0.5 → 1.1.2
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/CHANGELOG.md +112 -0
- package/README.md +228 -23
- package/compiler/bin/vibe-compile.js +109 -0
- package/compiler/native/.gitkeep +0 -0
- package/compiler/native/vibe-compiler-darwin-arm64 +0 -0
- package/compiler/src/Cargo.lock +1885 -0
- package/compiler/src/Cargo.toml +29 -0
- package/compiler/src/compiler/compile.rs +1209 -0
- package/compiler/src/compiler/mod.rs +5 -0
- package/compiler/src/config.rs +184 -0
- package/compiler/src/main.rs +284 -0
- package/compiler/src/parser/element.rs +96 -0
- package/compiler/src/parser/html.rs +335 -0
- package/compiler/src/parser/mod.rs +8 -0
- package/index.js +2 -248
- package/package.json +26 -3
- package/{affected.js → runtime/affected.js} +64 -4
- package/runtime/cleanup.js +59 -0
- package/runtime/component.js +116 -0
- package/{conditionals.js → runtime/conditionals.js} +25 -11
- package/{constants.js → runtime/constants.js} +23 -3
- package/runtime/debug.js +91 -0
- package/{hydrate.js → runtime/hydrate.js} +57 -7
- package/runtime/index.js +614 -0
- package/{iterate.js → runtime/iterate.js} +53 -45
- package/{iteration-utils.js → runtime/iteration-utils.js} +11 -1
- package/{parse.js → runtime/parse.js} +37 -7
- package/runtime/state.js +52 -0
- package/ROADMAP.md +0 -289
- package/llms.txt +0 -279
- package/state.js +0 -26
- /package/{_vibe-compiled-iteration-batch.js → runtime/_vibe-compiled-iteration-batch.js} +0 -0
- /package/{link.js → runtime/manifest.js} +0 -0
- /package/{utils.js → runtime/utils.js} +0 -0
- /package/{vibe.css → runtime/vibe.css} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,117 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.2] - 2026-02-01
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Compiler hotfix**: Empty custom element tags no longer cause HTML content to be cut out during compilation
|
|
8
|
+
- Root cause: `<Nav></Nav>` was compiled to `<component src="/components/Nav.html">` (no closing tag), causing the inlining regex to match from Nav's opening tag to the next component's closing tag (e.g., `<Headline>`'s `</component>`), treating all HTML in between as children of Nav
|
|
9
|
+
- Solution: All custom element tags now compile to properly closed `<component>...</component>` tags, even when empty
|
|
10
|
+
- Prevents regex from matching across multiple components
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## [1.1.1] - 2026-02-01
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Compiler CLI**: Modern command structure with subcommand support
|
|
19
|
+
- New bin command: `vibe`
|
|
20
|
+
- Subcommand syntax: `bunx vibe compile [options]` or shorthand `bunx vibe c [options]`
|
|
21
|
+
- Accessible directly via `bunx` without manual npm scripts
|
|
22
|
+
- Automatic detection of unknown subcommands with helpful error messages
|
|
23
|
+
- Backward compatibility: works with or without `compile` subcommand
|
|
24
|
+
- **Validation time tracking**: Compiler now reports component validation phase timing separately
|
|
25
|
+
- Shows time spent fetching external components
|
|
26
|
+
- Helps explain total compilation time vs individual phase times
|
|
27
|
+
- Displayed as: `* Validated components in XXms`
|
|
28
|
+
- **Component tree output**: Improved verbose logging for component compilation
|
|
29
|
+
- Tree structure with nested dependencies (e.g., nav.html → top-of-nav.html, menu.html)
|
|
30
|
+
- Usage counts for each unique component
|
|
31
|
+
- Color-coded: internal (green) vs external (magenta)
|
|
32
|
+
- Summary format: `Compiled components (X internal, Y external)`
|
|
33
|
+
- Clean hierarchical display with `└─` for children
|
|
34
|
+
- **Compiler documentation**: Updated READMEs with new CLI commands
|
|
35
|
+
- `/vibe/README.md` and `/vibe/compiler/README.md` now show `bunx vibe compile` syntax
|
|
36
|
+
- Added npm scripts examples for optional shortcuts
|
|
37
|
+
- Removed outdated `bun vibe:compile` references
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- **Compiler output formatting**: Consistent spacing between major sections (Vibe Compiler, Compiler config, Compiled components, etc.)
|
|
42
|
+
- **Verbose logging**: Removed redundant component loading list, streamlined validation output
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## [1.0.7] - 2026-01-30
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- **`<component>` element**: Runtime implementation of reusable HTML components
|
|
51
|
+
- Fetch HTML from local or remote sources: `<component src="/components/card.html">`
|
|
52
|
+
- Props system: Pass reactive bindings `headline="@[title]"` or static values `theme="dark"`
|
|
53
|
+
- Children via `<slot>`: Content between tags replaces `<slot></slot>` in fetched HTML
|
|
54
|
+
- Recursive resolution: Fetched HTML can contain more `<component>` elements
|
|
55
|
+
- Runtime-first with future compiler optimization planned (Phase 5)
|
|
56
|
+
- **Deep reactivity**: Nested property mutations now automatically trigger updates
|
|
57
|
+
- Recursive proxy implementation wraps all nested objects and arrays
|
|
58
|
+
- `$.obj.nested.prop = x` now triggers reactivity (previously required `$.obj = { ...$.obj, nested: { ...$.obj.nested, prop: x } }`)
|
|
59
|
+
- WeakMap cache prevents double-wrapping of proxies
|
|
60
|
+
- Tracks root property for each mutation to trigger correct affected element checks
|
|
61
|
+
- Same approach as Vue 3 - tiny performance cost for massive DX improvement
|
|
62
|
+
- **Scoped state for iterations**: Iteration instances now preserve local context for reactive updates
|
|
63
|
+
- Each `<!-- each items as item -->` instance stores its own `scopedState` (Proxy wrapper with local variables)
|
|
64
|
+
- When global state changes (e.g., `tutorialProgress`), affected elements inside iterations can access both local (`item`) and global variables
|
|
65
|
+
- Enables reactive attributes like `completed="@[tutorialProgress[item.id]]"` to update correctly without full re-render
|
|
66
|
+
- Scoped state flows through `affected.js` → `hydrate.js` pipeline for proper evaluation context
|
|
67
|
+
- **Compiler (first pass)**: Rust-based optional build tool
|
|
68
|
+
- Asset handling with whitelist approach (fonts, images, media, docs automatically copied)
|
|
69
|
+
- HTML/CSS/JS processing
|
|
70
|
+
- Configuration via `package.json` (`vibe-compiler` section)
|
|
71
|
+
- Node.js wrapper for cross-platform execution
|
|
72
|
+
- Foundation for future optimizations (component inlining, iteration optimization, two-way binding sugar)
|
|
73
|
+
- **Unit tests**: Comprehensive unit test suite (212 tests) for runtime modules using Bun's test framework - tests pure function layer (utils, state, iteration-utils, conditionals, affected, manifest) with aggressive edge case coverage
|
|
74
|
+
- **NPM scripts**: Added `bun unit` and `bun unit:watch` commands for running unit tests
|
|
75
|
+
- **Name bindings**: Bindings in attribute name position now supported
|
|
76
|
+
- Syntax: `<icon @[section.icon]></icon>` evaluates expression and sets it as attribute name
|
|
77
|
+
- HTML lowercases attribute names, so case-insensitive property lookup is used for simple properties
|
|
78
|
+
- Old attributes are automatically cleaned up when the bound value changes
|
|
79
|
+
- Useful for dynamic attribute names like icon libraries, custom elements, or conditional attributes
|
|
80
|
+
- Works in all contexts: root level, iterations, conditionals, and inside `<component>` elements
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- **Replace abort**: `<component>` elements now properly abort pending fetches (via `AbortController`) when removed from DOM before fetch completes, preventing "no parent node" errors and saving bandwidth
|
|
85
|
+
- **Nested iterations and conditionals**: Fixed issue where nested `<!-- each -->` and `<!-- if -->` blocks inside `<component>` elements would render then immediately disappear
|
|
86
|
+
- Root cause: MutationObserver re-parsing created fresh runtime state, causing iterations to think they needed re-rendering
|
|
87
|
+
- Solution: Added `__vibeRendered` marker on comment nodes that persists across re-parses
|
|
88
|
+
- Now properly handles complex nested structures like menu systems with dynamic sections and items
|
|
89
|
+
- **Conditionals wrapping iteration content**: Fixed conditionals in attribute name position (e.g., `<!-- if condition -->` wrapping `<nav-section>`) not being detected inside iteration templates
|
|
90
|
+
- Root cause: `initializeBlock()` only parsed the first element node, missing comment nodes like `<!-- if -->`
|
|
91
|
+
- Solution: Parse all template nodes in a container to capture comment nodes, ensuring tree element references match actual DOM nodes
|
|
92
|
+
- Enables patterns like conditional menu items: `<!-- each items as item --><!-- if condition --><item>...</item><!-- /if --><!-- /each -->`
|
|
93
|
+
- **StructuredClone with proxies**: Replaced `structuredClone()` with custom `deepClone()` that properly unwraps proxy objects for state snapshots in hooks
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## [1.0.6] - 2026-01-29
|
|
98
|
+
|
|
99
|
+
### Added
|
|
100
|
+
|
|
101
|
+
- **Debug mode**: New optional third parameter to enable colored console logging of Vibe's lifecycle phases (Attach, Parse, Manifest, Hydrate, Iterate, Condition, Observe, Fetch, Complete, Update, Mutate)
|
|
102
|
+
- **Debug helper**: Centralized `debugLog()` function with phase-specific color coding and tree-style indentation for nested operations
|
|
103
|
+
|
|
104
|
+
### Fixed
|
|
105
|
+
|
|
106
|
+
- **Nested brackets**: `BINDING_REGEX` and `PURE_BINDING_REGEX` now correctly parse bindings with one level of nested brackets (e.g., `@[items[0]]`, `@[obj[key]]`)
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
|
|
110
|
+
- **Internal naming**: Renamed `link.js` → `manifest.js` and `linkList` → `manifest` throughout codebase to better reflect its purpose as a DOM element registry/manifest
|
|
111
|
+
- **Phase constants**: Added `PHASE_*` constants for all lifecycle phases to ensure consistent naming across debug logs
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
3
115
|
## [1.0.5] - 2026-01-25
|
|
4
116
|
|
|
5
117
|
### Fixed
|
package/README.md
CHANGED
|
@@ -4,34 +4,71 @@ A runtime-first reactive library.
|
|
|
4
4
|
|
|
5
5
|
No virtual DOM. No build step. Just modern JavaScript.
|
|
6
6
|
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
7
|
```bash
|
|
10
8
|
npm install @ape-egg/vibe
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Vibe Runtime
|
|
14
|
+
|
|
15
|
+
The core reactive runtime. Works directly in the browser without any build tools.
|
|
16
|
+
|
|
17
|
+
### Quick Start
|
|
14
18
|
|
|
15
19
|
```html
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
<html>
|
|
21
|
+
<head>
|
|
22
|
+
<link rel="stylesheet" href="@ape-egg/vibe/vibe.css">
|
|
23
|
+
<script type="module">
|
|
24
|
+
import state from "@ape-egg/vibe";
|
|
25
|
+
// Attaches to element with attribute "vibe" by default
|
|
26
|
+
window.$ = state({ name: "World", count: 0 });
|
|
27
|
+
</script>
|
|
28
|
+
</head>
|
|
29
|
+
<body vibe>
|
|
20
30
|
|
|
21
31
|
<h1>Hello, @[name]!</h1>
|
|
22
32
|
<button onclick="$.count++">Clicked @[count] times</button>
|
|
33
|
+
|
|
34
|
+
</body>
|
|
35
|
+
</html>
|
|
23
36
|
```
|
|
24
37
|
|
|
25
|
-
|
|
38
|
+
### Prevent FOUC
|
|
39
|
+
|
|
40
|
+
To prevent a flash of unstyled content while Vibe hydrates:
|
|
41
|
+
|
|
42
|
+
1. Include `vibe.css` in your HTML
|
|
43
|
+
2. Add the `vibe` attribute to an element (typically `<body>`) to mark the hydration boundary
|
|
44
|
+
|
|
45
|
+
The CSS targets `[vibe]` and hides it until hydration completes. Once Vibe finishes processing, it removes the attribute, revealing your content.
|
|
26
46
|
|
|
27
47
|
### Reactive Bindings
|
|
28
48
|
|
|
29
|
-
|
|
49
|
+
Vibe supports bindings in three positions:
|
|
30
50
|
|
|
51
|
+
**Text content** — Inside element tags:
|
|
31
52
|
```html
|
|
32
53
|
<div>@[firstName] @[lastName]</div>
|
|
33
|
-
<
|
|
54
|
+
<h1>Hello, @[name]!</h1>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Attribute values** — In attribute value position:
|
|
58
|
+
```html
|
|
59
|
+
<input value="@[username]" />
|
|
60
|
+
<div class="@[theme]" style="color: @[color]"></div>
|
|
61
|
+
<a href="@[url]">Link</a>
|
|
62
|
+
```
|
|
34
63
|
|
|
64
|
+
**Attribute names** — In attribute name position (useful for dynamic attributes):
|
|
65
|
+
```html
|
|
66
|
+
<icon @[iconName]></icon>
|
|
67
|
+
<button @[state]>Click me</button>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**CSS** — Bindings also work in style tags:
|
|
71
|
+
```html
|
|
35
72
|
<style>
|
|
36
73
|
.box { background: @[themeColor]; }
|
|
37
74
|
</style>
|
|
@@ -65,6 +102,16 @@ Nested iteration with dot paths:
|
|
|
65
102
|
<!-- /if -->
|
|
66
103
|
```
|
|
67
104
|
|
|
105
|
+
### Components
|
|
106
|
+
|
|
107
|
+
Runtime component loading with props and slots:
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<component src="/components/card.html" title="@[pageTitle]" theme="dark">
|
|
111
|
+
<p>Content passed as slot</p>
|
|
112
|
+
</component>
|
|
113
|
+
```
|
|
114
|
+
|
|
68
115
|
### Dehydrate
|
|
69
116
|
|
|
70
117
|
Skip reactive processing for an element:
|
|
@@ -73,32 +120,190 @@ Skip reactive processing for an element:
|
|
|
73
120
|
<code dehydrate>@[this] displays literally</code>
|
|
74
121
|
```
|
|
75
122
|
|
|
76
|
-
###
|
|
123
|
+
### Deep Reactivity
|
|
77
124
|
|
|
78
|
-
|
|
125
|
+
Vibe uses recursive proxies to detect changes at any nesting level:
|
|
79
126
|
|
|
80
|
-
|
|
127
|
+
```javascript
|
|
128
|
+
// All of these trigger reactive updates:
|
|
129
|
+
$.user.name = "Alice";
|
|
130
|
+
$.todos[2].completed = true;
|
|
131
|
+
$.config.theme.colors.primary = "#007bff";
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
No need for immutable update patterns or spread operators. Just mutate and Vibe handles the rest.
|
|
135
|
+
|
|
136
|
+
### How It Works
|
|
81
137
|
|
|
82
138
|
1. **Proxy-based state** — `window.$` intercepts property changes
|
|
83
|
-
2. **
|
|
84
|
-
3. **
|
|
85
|
-
4. **
|
|
139
|
+
2. **Deep reactivity** — Nested mutations trigger updates automatically (`$.obj.nested.prop = x`)
|
|
140
|
+
3. **DOM parsing** — Finds all `@[...]` bindings on load
|
|
141
|
+
4. **Surgical updates** — Only affected elements re-render
|
|
142
|
+
5. **MutationObserver** — Tracks dynamically added elements
|
|
86
143
|
|
|
87
|
-
|
|
144
|
+
---
|
|
88
145
|
|
|
89
|
-
|
|
146
|
+
## Vibe Compiler
|
|
90
147
|
|
|
91
|
-
|
|
92
|
-
|
|
148
|
+
Optional build step for production optimization. The compiler processes HTML files, inlines components, and handles assets while preserving directory structure.
|
|
149
|
+
|
|
150
|
+
### Installation
|
|
151
|
+
|
|
152
|
+
The compiler requires Rust for non-macOS ARM64 platforms:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Note:** A prebuilt binary for macOS ARM64 is included. Other platforms will compile from source automatically.
|
|
159
|
+
|
|
160
|
+
### Usage
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Initialize config in package.json
|
|
164
|
+
bunx vibe compile --init
|
|
165
|
+
|
|
166
|
+
# Compile
|
|
167
|
+
bunx vibe compile
|
|
168
|
+
|
|
169
|
+
# With options
|
|
170
|
+
bunx vibe compile --verbose # Step-by-step logging
|
|
171
|
+
bunx vibe compile --minify # Minify output
|
|
172
|
+
bunx vibe compile --accessibility # Transform custom tags to divs
|
|
173
|
+
bunx vibe compile --validate # Validate HTML syntax
|
|
174
|
+
bunx vibe compile --create-manifest # Generate hydration manifest
|
|
175
|
+
bunx vibe compile --source-maps # Generate source maps
|
|
176
|
+
bunx vibe compile --node-modules-as-is # Copy node_modules as-is
|
|
177
|
+
bunx vibe compile --watch # Watch mode (future)
|
|
93
178
|
```
|
|
94
179
|
|
|
95
|
-
Or
|
|
180
|
+
Or via npm scripts:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"scripts": {
|
|
185
|
+
"vibe:compile": "vibe compile",
|
|
186
|
+
"vibe:compile:init": "vibe compile --init"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Then run with `bun vibe:compile` or `npm run vibe:compile`.
|
|
192
|
+
|
|
193
|
+
### Configuration
|
|
194
|
+
|
|
195
|
+
Add to your `package.json`:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"vibe-compiler": {
|
|
200
|
+
"source": "./",
|
|
201
|
+
"output": "./compiled",
|
|
202
|
+
"components": "components",
|
|
203
|
+
"pages": "pages",
|
|
204
|
+
"assets": "assets",
|
|
205
|
+
"minify": false,
|
|
206
|
+
"accessibility": false,
|
|
207
|
+
"excludeTags": [],
|
|
208
|
+
"nodeModulesAsIs": false
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Defaults** (when no config):
|
|
214
|
+
- `source`: `./`
|
|
215
|
+
- `output`: `./compiled`
|
|
216
|
+
- `components`: `<source>/components`
|
|
217
|
+
- `pages`: `<source>/pages`
|
|
218
|
+
- `assets`: `<source>/assets`
|
|
219
|
+
|
|
220
|
+
### Asset Handling
|
|
221
|
+
|
|
222
|
+
The compiler uses a whitelist approach. These file types are automatically copied:
|
|
223
|
+
|
|
224
|
+
**Fonts:** `.ttf`, `.otf`, `.woff`, `.woff2`, `.eot`
|
|
225
|
+
**Images:** `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.avif`, `.ico`
|
|
226
|
+
**Media:** `.mp4`, `.webm`, `.ogg`, `.mp3`, `.wav`, `.flac`, `.aac`
|
|
227
|
+
**Documents:** `.pdf`
|
|
228
|
+
**Data:** `.json`, `.xml`, `.csv`
|
|
229
|
+
|
|
230
|
+
HTML, CSS, and JavaScript files are processed by the compiler.
|
|
231
|
+
|
|
232
|
+
### Node Modules (Self-Contained Output)
|
|
233
|
+
|
|
234
|
+
By default, the compiler creates deployable output by installing production dependencies directly into the output directory:
|
|
235
|
+
|
|
236
|
+
1. Copies `package.json` and lockfile to output
|
|
237
|
+
2. Runs `<package-manager> install --production` in output directory
|
|
238
|
+
3. Removes `package.json` and lockfile from output (cleanup)
|
|
239
|
+
|
|
240
|
+
This ensures:
|
|
241
|
+
- Compiled output only includes runtime dependencies (from `dependencies`, not `devDependencies`)
|
|
242
|
+
- Local `node_modules` is never modified
|
|
243
|
+
- Faster than copying (no intermediate copy step)
|
|
244
|
+
|
|
245
|
+
**Package Manager Detection:**
|
|
246
|
+
Auto-detects based on lockfiles: `bun.lockb`, `pnpm-lock.yaml`, `yarn.lock`, `package-lock.json`
|
|
247
|
+
|
|
248
|
+
**Opt-out:**
|
|
249
|
+
Set `nodeModulesAsIs: true` in config or use `--node-modules-as-is` flag to copy node_modules as-is.
|
|
250
|
+
|
|
251
|
+
### Output Structure
|
|
252
|
+
|
|
253
|
+
Mirrors source structure:
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
src/ compiled/
|
|
257
|
+
├── pages/ ├── pages/
|
|
258
|
+
│ └── index.html │ └── index.html
|
|
259
|
+
├── components/ │ (components inlined)
|
|
260
|
+
│ └── counter.html
|
|
261
|
+
├── assets/ ├── assets/
|
|
262
|
+
│ └── image.png │ └── image.png
|
|
263
|
+
└── node_modules/ └── node_modules/
|
|
264
|
+
└── @ape-egg/ └── @ape-egg/
|
|
265
|
+
└── vibe/ └── vibe/
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Accessibility Mode
|
|
269
|
+
|
|
270
|
+
`--accessibility` transforms custom HTML elements to divs with classes:
|
|
96
271
|
|
|
97
272
|
```html
|
|
98
|
-
|
|
99
|
-
<
|
|
273
|
+
<!-- input -->
|
|
274
|
+
<counter-header>Count</counter-header>
|
|
275
|
+
|
|
276
|
+
<!-- output -->
|
|
277
|
+
<div class="counter-header">Count</div>
|
|
100
278
|
```
|
|
101
279
|
|
|
280
|
+
Exclude specific tags (e.g., web components) via `excludeTags` config.
|
|
281
|
+
|
|
282
|
+
### Building Native Binaries
|
|
283
|
+
|
|
284
|
+
For distribution without Rust:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
cd node_modules/@ape-egg/vibe/compiler/src
|
|
288
|
+
|
|
289
|
+
# Build for current platform
|
|
290
|
+
cargo build --release
|
|
291
|
+
|
|
292
|
+
# Copy binary to native directory
|
|
293
|
+
cp target/release/vibe-compiler ../native/vibe-compiler-darwin-arm64
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Supported platforms:
|
|
297
|
+
- `vibe-compiler-darwin-arm64` (macOS Apple Silicon) ✅ Included
|
|
298
|
+
- `vibe-compiler-darwin-x64` (macOS Intel)
|
|
299
|
+
- `vibe-compiler-linux-x64`
|
|
300
|
+
- `vibe-compiler-linux-arm64`
|
|
301
|
+
- `vibe-compiler-win32-x64.exe`
|
|
302
|
+
|
|
303
|
+
The CLI wrapper automatically falls back to `cargo run` when native binaries aren't present.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
102
307
|
## Browser Support
|
|
103
308
|
|
|
104
309
|
Modern browsers with Proxy and MutationObserver support.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { platform, arch } from 'node:os';
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const nativeDir = join(__dirname, '..', 'native');
|
|
11
|
+
const originalCwd = process.cwd();
|
|
12
|
+
|
|
13
|
+
// Map Node.js platform/arch to binary names
|
|
14
|
+
const getPlatformBinary = () => {
|
|
15
|
+
const os = platform();
|
|
16
|
+
const cpu = arch();
|
|
17
|
+
|
|
18
|
+
const platformMap = {
|
|
19
|
+
'darwin-arm64': 'vibe-compiler-darwin-arm64',
|
|
20
|
+
'darwin-x64': 'vibe-compiler-darwin-x64',
|
|
21
|
+
'linux-x64': 'vibe-compiler-linux-x64',
|
|
22
|
+
'linux-arm64': 'vibe-compiler-linux-arm64',
|
|
23
|
+
'win32-x64': 'vibe-compiler-win32-x64.exe',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const key = `${os}-${cpu}`;
|
|
27
|
+
const binary = platformMap[key];
|
|
28
|
+
|
|
29
|
+
if (!binary) {
|
|
30
|
+
console.error(`Unsupported platform: ${os}-${cpu}`);
|
|
31
|
+
console.error('Supported platforms: darwin-arm64, darwin-x64, linux-x64, linux-arm64, win32-x64');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return binary;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const run = () => {
|
|
39
|
+
const binary = getPlatformBinary();
|
|
40
|
+
const binaryPath = join(nativeDir, binary);
|
|
41
|
+
let userArgs = process.argv.slice(2);
|
|
42
|
+
|
|
43
|
+
// Handle subcommand: vibe compile [args]
|
|
44
|
+
// If first arg is "compile" or "c", remove it (the binary doesn't need it)
|
|
45
|
+
if (userArgs[0] === 'compile' || userArgs[0] === 'c') {
|
|
46
|
+
userArgs = userArgs.slice(1);
|
|
47
|
+
} else if (userArgs[0] && !userArgs[0].startsWith('-')) {
|
|
48
|
+
// Unknown subcommand
|
|
49
|
+
console.error(`Unknown subcommand: ${userArgs[0]}`);
|
|
50
|
+
console.error('Available subcommands: compile (or c)');
|
|
51
|
+
console.error('Usage: vibe compile [options]');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
// If no subcommand provided, default to compile behavior (pass args as-is)
|
|
55
|
+
|
|
56
|
+
// Check if native binary exists
|
|
57
|
+
if (!existsSync(binaryPath)) {
|
|
58
|
+
// Fall back to cargo run for development
|
|
59
|
+
console.info('[vibe-compile] Native binary not found, building with cargo...');
|
|
60
|
+
|
|
61
|
+
const srcDir = join(__dirname, '..', 'src');
|
|
62
|
+
|
|
63
|
+
if (!existsSync(join(srcDir, 'Cargo.toml'))) {
|
|
64
|
+
console.error('Neither native binary nor Rust source found.');
|
|
65
|
+
console.error(`Expected binary at: ${binaryPath}`);
|
|
66
|
+
console.error(`Or Cargo.toml at: ${srcDir}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Pass --cwd to tell the Rust binary the original working directory
|
|
71
|
+
const cargoArgs = ['run', '--release', '--', '--cwd', originalCwd, ...userArgs];
|
|
72
|
+
|
|
73
|
+
const cargo = spawn('cargo', cargoArgs, {
|
|
74
|
+
cwd: srcDir,
|
|
75
|
+
stdio: 'inherit',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
cargo.on('error', (err) => {
|
|
79
|
+
if (err.code === 'ENOENT') {
|
|
80
|
+
console.error('Cargo not found. Please install Rust: https://rustup.rs');
|
|
81
|
+
} else {
|
|
82
|
+
console.error('Failed to run cargo:', err.message);
|
|
83
|
+
}
|
|
84
|
+
process.exit(1);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
cargo.on('close', (code) => {
|
|
88
|
+
process.exit(code ?? 0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Run the native binary (it runs in the user's cwd, so no --cwd needed)
|
|
95
|
+
const child = spawn(binaryPath, userArgs, {
|
|
96
|
+
stdio: 'inherit',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
child.on('error', (err) => {
|
|
100
|
+
console.error('Failed to run vibe-compiler:', err.message);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
child.on('close', (code) => {
|
|
105
|
+
process.exit(code ?? 0);
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
run();
|
|
File without changes
|
|
Binary file
|