Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@oxc-node/cli",
"version": "1.0.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@oxc-node/core",
"version": "1.0.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "migration-oxnode",
"type": "module",
"scripts": {
"dev": "oxnode watch --clear-screen=false ./scripts/seed.ts",
"seed": "oxnode -C dev ./scripts/seed.ts",
"loader": "node --import @oxc-node/core/register ./scripts/seed.ts",
"loader-eval": "node --import=@oxc-node/core/register.mjs --eval \"import('./scripts/seed.ts')\"",
"loader-test": "node --import @oxc-node/core/register --test --test-reporter=dot ./scripts/seed.ts",
"env-loader": "NODE_OPTIONS='--import @oxc-node/core/register' node ./scripts/seed.ts"
},
"devDependencies": {
"@oxc-node/cli": "file:.fixture/oxc-cli",
"@oxc-node/core": "file:.fixture/oxc-core",
"vite": "^7.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env oxnode
const version: string = '1.0.0';
console.log(version);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
enum State {
Ready = 'ready',
}
console.log(State.Ready);
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[[case]]
name = "migration_oxnode_scripts"
vp = "local"
comment = "The oxc-node dependencies use local stub packages. Migrated scripts run the bundled loader."
steps = [
{ argv = ["vp", "migrate", "--no-interactive", "--no-hooks", "--no-agent", "--no-editor"], comment = "oxnode commands and shebangs migrate to vpx; preloads keep Node.js" },
["vpt", "print-file", "package.json"],
["vpt", "print-file", "scripts/release.ts"],
{ argv = ["vp", "run", "seed"], comment = "the migrated command runs TypeScript with Node conditions" },
{ argv = ["vp", "run", "loader"], comment = "the migrated Node loader command runs without standalone oxc-node" },
{ argv = ["vp", "run", "loader-eval"], comment = "the migrated preload keeps native Node.js eval behavior" },
["vp", "run", "loader-test"],
]

[[case]]
name = "migration_oxnode_kept"
vp = "local"
steps = [
{ argv = ["vpt", "json-edit", "package.json", "scripts.node-watch", "oxnode --watch ./scripts/seed.ts"], snapshot = false },
{ argv = ["vpt", "write-file", "scripts/importer.ts", "import '@oxc-node/core/register';\n"], snapshot = false },
{ argv = ["vp", "migrate", "--no-interactive", "--no-hooks", "--no-agent", "--no-editor"], comment = "Node watch mode and remaining loader imports keep the dependencies" },
["vpt", "print-file", "package.json"],
]

[[case]]
name = "migration_oxnode_already_vite_plus"
vp = "local"
steps = [
{ argv = ["vpt", "json-edit", "package.json", "devDependencies.vite-plus", "latest"], snapshot = false },
{ argv = ["vp", "migrate", "--no-interactive"], comment = "a plain upgrade leaves oxnode migration to --full" },
{ argv = ["vp", "migrate", "--no-interactive", "--full", "--no-hooks", "--no-agent", "--no-editor"], comment = "--full migrates oxnode on an existing Vite+ project" },
["vpt", "print-file", "package.json"],
["vp", "run", "seed"],
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# migration_oxnode_already_vite_plus

## `vpt json-edit package.json devDependencies.vite-plus latest`


## `vp migrate --no-interactive`

a plain upgrade leaves oxnode migration to --full

```
VITE+ - The Unified Toolchain for the Web

◇ Updated . to Vite+ <version>
• Node <version> pnpm <version>
• Dependencies:
vite-plus latest → <version>
vite → <version>
• Package manager settings configured
• Skipped editor, hooks, and lint setup. Run `vp migrate --full` to apply them.
```

## `vp migrate --no-interactive --full --no-hooks --no-agent --no-editor`

--full migrates oxnode on an existing Vite+ project

```
VITE+ - The Unified Toolchain for the Web

▲ No package manager is declared in package.json; using pnpm for this migration without adding a pin. Run `vp env pin` to declare it explicitly.
● oxnode scripts detected. Auto-migrating to Vite+...
◇ Updated . to Vite+ <version>
• Node <version> pnpm <version>
• Dependencies:
vite → <version>
• oxnode scripts migrated to Vite+
```

## `vpt print-file package.json`

```
{
"devDependencies": {
"vite": "catalog:",
"vite-plus": "catalog:"
},
"name": "migration-oxnode",
"scripts": {
"dev": "vpx --watch --clear-screen=false ./scripts/seed.ts",
"env-loader": "NODE_OPTIONS='--import vite-plus/register' node ./scripts/seed.ts",
"loader": "node --import vite-plus/register ./scripts/seed.ts",
"loader-eval": "node --import=vite-plus/register --eval \"import('./scripts/seed.ts')\"",
"loader-test": "node --import vite-plus/register --test --test-reporter=dot ./scripts/seed.ts",
"seed": "vpx -C dev ./scripts/seed.ts"
},
"type": "module"
}
```

## `vp run seed`

```
$ vpx -C dev ./scripts/seed.ts ⊘ cache disabled
ready
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# migration_oxnode_kept

## `vpt json-edit package.json scripts.node-watch 'oxnode --watch ./scripts/seed.ts'`


## `vpt write-file scripts/importer.ts 'import '\''@oxc-node/core/register'\'';
'`


## `vp migrate --no-interactive --no-hooks --no-agent --no-editor`

Node watch mode and remaining loader imports keep the dependencies

```
VITE+ - The Unified Toolchain for the Web

● oxnode scripts detected. Auto-migrating to Vite+...
◇ Migrated . to Vite+ <version>
• Node <version> pnpm <version>
• 1 config update applied
• oxnode scripts migrated to Vite+
! Warnings:
- Kept oxnode in package.json scripts "node-watch": oxnode --watch starts the Node.js watcher, while `vpx --watch` uses its own watcher; use oxnode watch to migrate it.
- Kept the @oxc-node/cli / @oxc-node/core devDependency in package.json: `scripts` in package.json still uses oxnode.
```

## `vpt print-file package.json`

```
{
"devDependencies": {
"@oxc-node/cli": "file:.fixture/oxc-cli",
"@oxc-node/core": "file:.fixture/oxc-core",
"vite": "catalog:",
"vite-plus": "catalog:"
},
"name": "migration-oxnode",
"scripts": {
"dev": "vpx --watch --clear-screen=false ./scripts/seed.ts",
"env-loader": "NODE_OPTIONS='--import vite-plus/register' node ./scripts/seed.ts",
"loader": "node --import vite-plus/register ./scripts/seed.ts",
"loader-eval": "node --import=vite-plus/register --eval \"import('./scripts/seed.ts')\"",
"loader-test": "node --import vite-plus/register --test --test-reporter=dot ./scripts/seed.ts",
"node-watch": "oxnode --watch ./scripts/seed.ts",
"seed": "vpx -C dev ./scripts/seed.ts"
},
"type": "module"
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# migration_oxnode_scripts

The oxc-node dependencies use local stub packages. Migrated scripts run the bundled loader.

## `vp migrate --no-interactive --no-hooks --no-agent --no-editor`

oxnode commands and shebangs migrate to vpx; preloads keep Node.js

```
VITE+ - The Unified Toolchain for the Web

● oxnode scripts detected. Auto-migrating to Vite+...
◇ Migrated . to Vite+ <version>
• Node <version> pnpm <version>
• 1 config update applied
• oxnode scripts migrated to Vite+
```

## `vpt print-file package.json`

```
{
"name": "migration-oxnode",
"type": "module",
"scripts": {
"dev": "vpx --watch --clear-screen=false ./scripts/seed.ts",
"seed": "vpx -C dev ./scripts/seed.ts",
"loader": "node --import vite-plus/register ./scripts/seed.ts",
"loader-eval": "node --import=vite-plus/register --eval \"import('./scripts/seed.ts')\"",
"loader-test": "node --import vite-plus/register --test --test-reporter=dot ./scripts/seed.ts",
"env-loader": "NODE_OPTIONS='--import vite-plus/register' node ./scripts/seed.ts"
},
"devDependencies": {
"vite": "catalog:",
"vite-plus": "catalog:"
}
}
```

## `vpt print-file scripts/release.ts`

```
#!/usr/bin/env vpx
const version: string = '1.0.0';
console.log(version);
```

## `vp run seed`

the migrated command runs TypeScript with Node conditions

```
$ vpx -C dev ./scripts/seed.ts ⊘ cache disabled
ready
```

## `vp run loader`

the migrated Node loader command runs without standalone oxc-node

```
$ node --import vite-plus/register ./scripts/seed.ts ⊘ cache disabled
ready
```

## `vp run loader-eval`

the migrated preload keeps native Node.js eval behavior

```
$ node --import=vite-plus/register --eval "import('./scripts/seed.ts')" ⊘ cache disabled
ready
```

## `vp run loader-test`

```
$ node --import vite-plus/register --test --test-reporter=dot ./scripts/seed.ts ⊘ cache disabled
.
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env -S node --no-warnings --experimental-specifier-resolution=node --import @oxc-node/core/register --loader ./scripts/variant-loader.js --loader ./scripts/image-loader.js
import('../src/main.ts');
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "migration-oxnode-custom-loaders",
"type": "module",
"scripts": {
"loader": "node --no-warnings --experimental-specifier-resolution=node --import @oxc-node/core/register --loader ./scripts/variant-loader.js --loader ./scripts/image-loader.js ./scripts/build-assets.tsx",
"shebang": "./scripts/build-assets.tsx",
"extensionless": "./bin/build-assets"
},
"devDependencies": {
"@oxc-node/core": "0.1.0",
"vite-plus": "latest"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env -S node --no-warnings --experimental-specifier-resolution=node --import @oxc-node/core/register --loader ./scripts/variant-loader.js --loader ./scripts/image-loader.js
import '../src/main.ts';
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Representative project loader: turn an image into an ESM value.
import { readFile } from 'node:fs/promises';

export async function load(url, context, nextLoad) {
if (url.endsWith('.svg')) {
const text = await readFile(new URL(url), 'utf8');
return {
format: 'module',
shortCircuit: true,
source: `export default ${JSON.stringify({ name: 'logo.svg', bytes: text.length })};`,
};
}
if (url.endsWith('/generated.cjs')) {
return {
format: 'commonjs',
shortCircuit: true,
source: `module.exports = { local: require('./dependency.cjs'), builtin: require('node:path').basename('/parent/child') };`,
};
}
const result = await nextLoad(url, context);
return url.endsWith('/order.js')
? { ...result, source: `${result.source}\norder.push('image');` }
: result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Representative project loader: choose a TypeScript variant and record load order.
export async function resolve(specifier, context, nextResolve) {
return nextResolve(
specifier === '#variant' ? new URL('../src/variant.ts', import.meta.url).href : specifier,
context,
);
}

export async function load(url, context, nextLoad) {
const result = await nextLoad(url, context);
return url.endsWith('/order.js')
? { ...result, source: `${result.source}\norder.push('variant');` }
: result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[[case]]
name = "migration_oxnode_custom_loaders"
vp = "local"
local-registry = true
env = { VP_NODE_VERSION = "22.23.2" }
unset-env = ["NODE_OPTIONS", "VP_SCRIPT_TSCONFIG", "TSX_TSCONFIG_PATH", "OXC_TSCONFIG_PATH", "TS_NODE_PROJECT"]
comment = "The local registry supplies published oxc-node 0.1.0 to compare original and migrated loader chains. The variant and image loaders are locally authored fixtures; the referenced Athena Crisis loaders are not in its public tree."
steps = [
{ argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
{ argv = ["vp", "run", "loader"], comment = "The original register runs TypeScript, variant resolution, image imports, and both custom loaders in order." },
["vp", "migrate", "--full", "--no-interactive", "--no-hooks", "--no-agent", "--no-editor"],
{ argv = ["vpt", "print-file", "package.json", "scripts/build-assets.tsx", "bin/build-assets"], comment = "Only the register import changes; Node.js flags, custom loader order, and script bodies stay intact." },
{ argv = ["vpt", "rm", "-rf", "node_modules"], snapshot = false },
{ argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
{ argv = ["vpt", "stat-file", "node_modules/@oxc-node/core"], comment = "A fresh install no longer includes standalone oxc-node." },
{ argv = ["vp", "run", "loader"], comment = "The migrated register produces the same values and loader order." },
]

[[case]]
name = "migration_oxnode_shebang_async"
vp = "local"
local-registry = true
env = { VP_NODE_VERSION = "22.18.0" }
unset-env = ["NODE_OPTIONS", "VP_SCRIPT_TSCONFIG", "TSX_TSCONFIG_PATH", "OXC_TSCONFIG_PATH", "TS_NODE_PROJECT"]
skip-platforms = ["windows"]
comment = "The local registry supplies published oxc-node 1.0.1 to compare original and migrated loader chains. The variant and image loaders are locally authored fixtures; the referenced Athena Crisis loaders are not in its public tree."
steps = [
{ argv = ["vpt", "json-edit", "package.json", "devDependencies.@oxc-node/core", "1.0.1"], snapshot = false },
{ argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
{ argv = ["vp", "run", "loader"], comment = "The original register runs TypeScript, variant resolution, image imports, and both custom loaders in order." },
["vp", "run", "shebang"],
["vp", "run", "extensionless"],
["vp", "migrate", "--full", "--no-interactive", "--no-hooks", "--no-agent", "--no-editor"],
{ argv = ["vpt", "print-file", "package.json", "scripts/build-assets.tsx", "bin/build-assets"], comment = "Only the register import changes; Node.js flags, custom loader order, and script bodies stay intact." },
{ argv = ["vpt", "rm", "-rf", "node_modules"], snapshot = false },
{ argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
{ argv = ["vpt", "stat-file", "node_modules/@oxc-node/core"], comment = "A fresh install no longer includes standalone oxc-node." },
{ argv = ["vp", "run", "loader"], comment = "The migrated register produces the same values and loader order." },
["vp", "run", "shebang"],
["vp", "run", "extensionless"],
]

[[case]]
name = "migration_oxnode_shebang_sync"
vp = "local"
local-registry = true
env = { VP_NODE_VERSION = "26.5.0" }
unset-env = ["NODE_OPTIONS", "VP_SCRIPT_TSCONFIG", "TSX_TSCONFIG_PATH", "OXC_TSCONFIG_PATH", "TS_NODE_PROJECT"]
skip-platforms = ["windows"]
comment = "The local registry supplies published oxc-node 1.0.1 to compare original and migrated loader chains. The variant and image loaders are locally authored fixtures; the referenced Athena Crisis loaders are not in its public tree."
steps = [
{ argv = ["vpt", "json-edit", "package.json", "devDependencies.@oxc-node/core", "1.0.1"], snapshot = false },
{ argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
{ argv = ["vp", "run", "loader"], comment = "The original register runs TypeScript, variant resolution, image imports, and both custom loaders in order." },
["vp", "run", "shebang"],
["vp", "run", "extensionless"],
["vp", "migrate", "--full", "--no-interactive", "--no-hooks", "--no-agent", "--no-editor"],
{ argv = ["vpt", "print-file", "package.json", "scripts/build-assets.tsx", "bin/build-assets"], comment = "Only the register import changes; Node.js flags, custom loader order, and script bodies stay intact." },
{ argv = ["vpt", "rm", "-rf", "node_modules"], snapshot = false },
{ argv = ["vp", "install", "--ignore-scripts"], snapshot = false },
{ argv = ["vpt", "stat-file", "node_modules/@oxc-node/core"], comment = "A fresh install no longer includes standalone oxc-node." },
{ argv = ["vp", "run", "loader"], comment = "The migrated register produces the same values and loader order." },
["vp", "run", "shebang"],
["vp", "run", "extensionless"],
]
Loading
Loading