@nbt-dev/nbt 0.1.0 → 0.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/README.md +7 -6
- package/dist/nbt.js +195 -422
- package/package.json +8 -4
- package/stdlib/auth/schema.nbt +6 -3
- package/stdlib/dns/schema.nbt +1 -1
- package/stdlib/ingest/schema.nbt +1 -1
- package/stdlib/phone/schema.nbt +1 -1
- package/stdlib/registry/schema.nbt +1 -1
- package/stdlib/secrets/schema.nbt +16 -0
- package/stdlib/workflows/schema.nbt +27 -0
- package/vendor/linux-x64/cartridges/auth/schema.nbt +6 -3
- package/vendor/linux-x64/cartridges/dns/schema.nbt +1 -1
- package/vendor/linux-x64/cartridges/ingest/schema.nbt +1 -1
- package/vendor/linux-x64/cartridges/phone/schema.nbt +1 -1
- package/vendor/linux-x64/cartridges/registry/schema.nbt +1 -1
- package/vendor/linux-x64/cartridges/secrets/schema.nbt +16 -0
- package/vendor/linux-x64/cartridges/workflows/schema.nbt +27 -0
- package/vendor/linux-x64/console +0 -0
- package/vendor/linux-x64/esbuild +0 -0
- package/vendor/linux-x64/nbt +0 -0
- package/stdlib/design/migrations/20260501210107_initial/migration.nbt +0 -19
- package/stdlib/design/migrations/20260501210107_initial/schema_snapshot.nbt +0 -21
- package/stdlib/design/migrations/20260610130000_design_system/migration.nbt +0 -50
- package/stdlib/design/migrations/20260610130000_design_system/schema_snapshot.nbt +0 -80
- package/stdlib/design/schema.nbt +0 -140
- package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/migration.nbt +0 -19
- package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/schema_snapshot.nbt +0 -21
- package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/migration.nbt +0 -50
- package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/schema_snapshot.nbt +0 -80
- package/vendor/linux-x64/cartridges/design/schema.nbt +0 -140
package/dist/nbt.js
CHANGED
|
@@ -3134,9 +3134,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3134
3134
|
* @param {string} [path]
|
|
3135
3135
|
* @return {(string|null|Command)}
|
|
3136
3136
|
*/
|
|
3137
|
-
executableDir(
|
|
3138
|
-
if (
|
|
3139
|
-
this._executableDir =
|
|
3137
|
+
executableDir(path3) {
|
|
3138
|
+
if (path3 === void 0) return this._executableDir;
|
|
3139
|
+
this._executableDir = path3;
|
|
3140
3140
|
return this;
|
|
3141
3141
|
}
|
|
3142
3142
|
/**
|
|
@@ -3393,48 +3393,33 @@ var program = new Command();
|
|
|
3393
3393
|
|
|
3394
3394
|
// src/nbt.ts
|
|
3395
3395
|
var import_node_child_process2 = require("node:child_process");
|
|
3396
|
-
var net = __toESM(require("node:net"));
|
|
3397
|
-
var path3 = __toESM(require("node:path"));
|
|
3398
|
-
var fs2 = __toESM(require("node:fs"));
|
|
3399
|
-
var readline = __toESM(require("node:readline/promises"));
|
|
3400
|
-
|
|
3401
|
-
// src/bundler.ts
|
|
3402
|
-
var import_esbuild = __toESM(require("esbuild"));
|
|
3403
3396
|
var path2 = __toESM(require("node:path"));
|
|
3404
|
-
var
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
delete g.__nbt_bundler__;
|
|
3415
|
-
await import((0, import_node_url.pathToFileURL)(path2.resolve(options.outfile)).href);
|
|
3416
|
-
const bundler = g.__nbt_bundler__;
|
|
3417
|
-
console.log(bundler.workflows, bundler.steps, bundler.actions);
|
|
3418
|
-
}
|
|
3419
|
-
|
|
3420
|
-
// src/nbt.ts
|
|
3421
|
-
if (process.platform !== "linux" || process.arch !== "x64") {
|
|
3397
|
+
var fs2 = __toESM(require("node:fs"));
|
|
3398
|
+
var os = __toESM(require("node:os"));
|
|
3399
|
+
var VENDOR_DIRS = {
|
|
3400
|
+
"linux-x64": "linux-x64",
|
|
3401
|
+
"darwin-arm64": "darwin-arm64",
|
|
3402
|
+
"darwin-x64": "darwin-x64"
|
|
3403
|
+
};
|
|
3404
|
+
var PLATFORM_KEY = `${process.platform}-${process.arch}`;
|
|
3405
|
+
var VENDOR_SUBDIR = VENDOR_DIRS[PLATFORM_KEY];
|
|
3406
|
+
if (!VENDOR_SUBDIR) {
|
|
3422
3407
|
console.error(
|
|
3423
|
-
`@nbt-dev/nbt
|
|
3408
|
+
`@nbt-dev/nbt has no prebuilt binaries for ${PLATFORM_KEY} (supported: ${Object.keys(VENDOR_DIRS).join(", ")}).`
|
|
3424
3409
|
);
|
|
3425
3410
|
process.exit(1);
|
|
3426
3411
|
}
|
|
3427
|
-
var
|
|
3428
|
-
var
|
|
3429
|
-
var NBT_BIN =
|
|
3430
|
-
var CONSOLE_BIN =
|
|
3412
|
+
var IS_MAC = process.platform === "darwin";
|
|
3413
|
+
var VENDOR = path2.join(__dirname, "..", "vendor", VENDOR_SUBDIR);
|
|
3414
|
+
var NBT_BIN = path2.join(VENDOR, "nbt");
|
|
3415
|
+
var CONSOLE_BIN = path2.join(VENDOR, "console");
|
|
3431
3416
|
function nativeEnv() {
|
|
3432
3417
|
return { ...process.env };
|
|
3433
3418
|
}
|
|
3434
3419
|
function corsOriginsFromNbtJson() {
|
|
3435
3420
|
let dir = process.cwd();
|
|
3436
3421
|
for (let i = 0; i < 32; i++) {
|
|
3437
|
-
const candidate =
|
|
3422
|
+
const candidate = path2.join(dir, "nbt.json");
|
|
3438
3423
|
if (fs2.existsSync(candidate)) {
|
|
3439
3424
|
try {
|
|
3440
3425
|
const cfg = JSON.parse(fs2.readFileSync(candidate, "utf8"));
|
|
@@ -3446,7 +3431,7 @@ function corsOriginsFromNbtJson() {
|
|
|
3446
3431
|
}
|
|
3447
3432
|
return [];
|
|
3448
3433
|
}
|
|
3449
|
-
const parent =
|
|
3434
|
+
const parent = path2.dirname(dir);
|
|
3450
3435
|
if (parent === dir) break;
|
|
3451
3436
|
dir = parent;
|
|
3452
3437
|
}
|
|
@@ -3460,15 +3445,49 @@ function consoleEnv() {
|
|
|
3460
3445
|
}
|
|
3461
3446
|
return env;
|
|
3462
3447
|
}
|
|
3448
|
+
function projectUpPort() {
|
|
3449
|
+
let dir = process.cwd();
|
|
3450
|
+
for (let i = 0; i < 32; i++) {
|
|
3451
|
+
const candidate = path2.join(dir, "nbt.json");
|
|
3452
|
+
if (fs2.existsSync(candidate)) {
|
|
3453
|
+
try {
|
|
3454
|
+
const cfg = JSON.parse(fs2.readFileSync(candidate, "utf8"));
|
|
3455
|
+
return Number(cfg?.environments?.dev?.port) || 8080;
|
|
3456
|
+
} catch {
|
|
3457
|
+
break;
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
const parent = path2.dirname(dir);
|
|
3461
|
+
if (parent === dir) break;
|
|
3462
|
+
dir = parent;
|
|
3463
|
+
}
|
|
3464
|
+
return 8080;
|
|
3465
|
+
}
|
|
3466
|
+
function withProjectUpDefaults(argv2) {
|
|
3467
|
+
const hasPort = argv2.some(
|
|
3468
|
+
(arg) => arg === "--port" || arg === "-p" || arg.startsWith("--port=")
|
|
3469
|
+
);
|
|
3470
|
+
if (hasPort) return argv2;
|
|
3471
|
+
return [...argv2, "--port", String(projectUpPort())];
|
|
3472
|
+
}
|
|
3463
3473
|
function forwardToNative(argv2) {
|
|
3464
|
-
const
|
|
3474
|
+
const cmd = argv2[0];
|
|
3475
|
+
const isConsole = consoleCommands.has(cmd);
|
|
3465
3476
|
const bin = isConsole ? CONSOLE_BIN : NBT_BIN;
|
|
3466
|
-
const
|
|
3467
|
-
const
|
|
3477
|
+
const bootsDaemon = isConsole || cmd === "dev";
|
|
3478
|
+
const env = bootsDaemon ? consoleEnv() : nativeEnv();
|
|
3479
|
+
const nativeArgv = cmd === "up" ? withProjectUpDefaults(argv2) : argv2;
|
|
3468
3480
|
if (!fs2.existsSync(bin)) {
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3481
|
+
if (isConsole && IS_MAC) {
|
|
3482
|
+
console.error(
|
|
3483
|
+
`@nbt-dev/nbt: \`${cmd}\` runs the console daemon, which is Linux-only on macOS.
|
|
3484
|
+
Run it in Docker, then point the CLI at it with NBT_CONSOLE_URL.`
|
|
3485
|
+
);
|
|
3486
|
+
} else {
|
|
3487
|
+
console.error(
|
|
3488
|
+
`@nbt-dev/nbt: bundled binary not found at ${bin} (broken install?)`
|
|
3489
|
+
);
|
|
3490
|
+
}
|
|
3472
3491
|
process.exit(1);
|
|
3473
3492
|
}
|
|
3474
3493
|
try {
|
|
@@ -3485,417 +3504,167 @@ function forwardToNative(argv2) {
|
|
|
3485
3504
|
}
|
|
3486
3505
|
process.exit(r.status === null ? 1 : r.status);
|
|
3487
3506
|
}
|
|
3488
|
-
function
|
|
3507
|
+
function resolveAgentEntry() {
|
|
3508
|
+
const rel = path2.join(
|
|
3509
|
+
"packages",
|
|
3510
|
+
"coding-agent",
|
|
3511
|
+
"dist",
|
|
3512
|
+
"cli.js"
|
|
3513
|
+
);
|
|
3514
|
+
const candidates = [
|
|
3515
|
+
path2.join(__dirname, "..", "agent", rel),
|
|
3516
|
+
// published: agent vendored under this package
|
|
3517
|
+
path2.join(__dirname, "..", "..", "agent", rel)
|
|
3518
|
+
// dev monorepo: npm/agent
|
|
3519
|
+
];
|
|
3520
|
+
for (const c of candidates) if (fs2.existsSync(c)) return c;
|
|
3489
3521
|
try {
|
|
3490
|
-
|
|
3491
|
-
fs2.readFileSync(path3.join(__dirname, "..", "package.json"), "utf8")
|
|
3492
|
-
);
|
|
3493
|
-
return typeof pkg?.version === "string" ? pkg.version : "unknown";
|
|
3522
|
+
return require.resolve("@nbt-dev/agent/dist/cli.js");
|
|
3494
3523
|
} catch {
|
|
3495
|
-
return
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
var program2 = new Command();
|
|
3499
|
-
program2.name("nbt").description("nbt.dev CLI").version(packageVersion(), "-v, --version", "Print the @nbt-dev/nbt version");
|
|
3500
|
-
var NBT = [
|
|
3501
|
-
["install", "Install a cartridge on a live instance"],
|
|
3502
|
-
["generate", "Generate a typed client from contracts"],
|
|
3503
|
-
["migrate", "Create migrations and deploy local cartridges"],
|
|
3504
|
-
["lsp", "Run the NBT language server over stdio (editors)"],
|
|
3505
|
-
["editor", "Install the NBT VS Code extension (editor install)"]
|
|
3506
|
-
];
|
|
3507
|
-
var CONSOLE = [
|
|
3508
|
-
["up", "Boot the console daemon"],
|
|
3509
|
-
["gen-cluster-key", "Generate a cluster signing key (copy to every node)"]
|
|
3510
|
-
];
|
|
3511
|
-
var consoleCommands = new Set(CONSOLE.map(([n]) => n));
|
|
3512
|
-
for (const [name, summary] of [...NBT, ...CONSOLE]) {
|
|
3513
|
-
program2.command(name).description(`${summary} (native)`);
|
|
3514
|
-
}
|
|
3515
|
-
var customCommands = /* @__PURE__ */ new Set();
|
|
3516
|
-
customCommands.add("init");
|
|
3517
|
-
program2.command("init").description("Scaffold an nbt project (nbt.json, nbt/, generated/)").argument(
|
|
3518
|
-
"[dir]",
|
|
3519
|
-
"directory to create the project in (default: current directory)"
|
|
3520
|
-
).option("-y, --yes", "skip prompts; include the hello-world example").option("--no-example", "skip the hello-world example cartridge").action(
|
|
3521
|
-
(dir, opts) => {
|
|
3522
|
-
runInit(dir, opts).catch((e) => {
|
|
3523
|
-
console.error(`nbt init: ${e?.message ?? e}`);
|
|
3524
|
-
process.exit(1);
|
|
3525
|
-
});
|
|
3526
|
-
}
|
|
3527
|
-
);
|
|
3528
|
-
var NBT_JSON_TEMPLATE = `{
|
|
3529
|
-
"carts": "nbt",
|
|
3530
|
-
"generated": "generated",
|
|
3531
|
-
"environments": {
|
|
3532
|
-
"dev": { "host": "127.0.0.1", "port": 8080 }
|
|
3533
|
-
}
|
|
3534
|
-
}
|
|
3535
|
-
`;
|
|
3536
|
-
var HELLO_SCHEMA = `# A minimal entity. CRUD routes are generated automatically:
|
|
3537
|
-
# GET /api/hello/note list
|
|
3538
|
-
# POST /api/hello/note create
|
|
3539
|
-
# GET /api/hello/note/:id get
|
|
3540
|
-
# PUT /api/hello/note/:id update
|
|
3541
|
-
# DELETE /api/hello/note/:id delete
|
|
3542
|
-
entity Note {
|
|
3543
|
-
id: ulid
|
|
3544
|
-
createdAt: DateTime @default(now())
|
|
3545
|
-
updatedAt: DateTime @updatedAt
|
|
3546
|
-
title: string
|
|
3547
|
-
body: string
|
|
3548
|
-
|
|
3549
|
-
@@index([title])
|
|
3550
|
-
}
|
|
3551
|
-
`;
|
|
3552
|
-
async function runInit(dir, opts) {
|
|
3553
|
-
const root = dir ? path3.resolve(process.cwd(), dir) : process.cwd();
|
|
3554
|
-
if (dir) fs2.mkdirSync(root, { recursive: true });
|
|
3555
|
-
if (fs2.existsSync(path3.join(root, "nbt.json"))) {
|
|
3556
|
-
throw new Error(
|
|
3557
|
-
`nbt.json already exists ${dir ? `in ${dir}` : "here"} \u2014 this is already an nbt project`
|
|
3558
|
-
);
|
|
3559
|
-
}
|
|
3560
|
-
if (!fs2.existsSync(path3.join(STDLIB, "auth", "schema.nbt"))) {
|
|
3561
|
-
throw new Error("bundled auth cartridge is missing (broken install)");
|
|
3562
|
-
}
|
|
3563
|
-
if (fs2.existsSync(path3.join(root, "nbt", "auth"))) {
|
|
3564
|
-
throw new Error(
|
|
3565
|
-
"nbt/auth already exists; refusing to overwrite it during init"
|
|
3566
|
-
);
|
|
3567
|
-
}
|
|
3568
|
-
fs2.writeFileSync(path3.join(root, "nbt.json"), NBT_JSON_TEMPLATE);
|
|
3569
|
-
fs2.mkdirSync(path3.join(root, "nbt"), { recursive: true });
|
|
3570
|
-
fs2.mkdirSync(path3.join(root, "generated"), { recursive: true });
|
|
3571
|
-
addStandardCartridge("auth", path3.join(root, "nbt"), false);
|
|
3572
|
-
console.log("Created project:");
|
|
3573
|
-
console.log(" nbt.json (dev environment configured)");
|
|
3574
|
-
console.log(" nbt/auth/ (local core auth cartridge)");
|
|
3575
|
-
console.log(" generated/ (typed client output \u2014 nbt generate)");
|
|
3576
|
-
const example = opts.example !== false && (opts.yes === true || await wantExample());
|
|
3577
|
-
if (example) {
|
|
3578
|
-
scaffoldHelloCart(path3.join(root, "nbt", "hello"));
|
|
3579
|
-
console.log("\nCreated example cartridge nbt/hello/ (entity Note).");
|
|
3580
|
-
console.log("\nNext:");
|
|
3581
|
-
if (dir) console.log(` cd ${dir}`);
|
|
3582
|
-
console.log(
|
|
3583
|
-
" nbt dev # boot the console + live-reload on save"
|
|
3584
|
-
);
|
|
3585
|
-
} else {
|
|
3586
|
-
if (dir)
|
|
3587
|
-
console.log(
|
|
3588
|
-
`
|
|
3589
|
-
Next: cd ${dir}, then run \`nbt dev\` or add a standard cartridge with \`nbt add <name>\`.`
|
|
3590
|
-
);
|
|
3591
|
-
else
|
|
3592
|
-
console.log(
|
|
3593
|
-
"\nNext: run `nbt dev`, or add another standard cartridge with `nbt add <name>`."
|
|
3594
|
-
);
|
|
3595
|
-
}
|
|
3596
|
-
}
|
|
3597
|
-
async function wantExample() {
|
|
3598
|
-
if (!process.stdin.isTTY) return true;
|
|
3599
|
-
const rl = readline.createInterface({
|
|
3600
|
-
input: process.stdin,
|
|
3601
|
-
output: process.stdout
|
|
3602
|
-
});
|
|
3603
|
-
try {
|
|
3604
|
-
const ans = (await rl.question("Add a hello-world example cartridge? [Y/n] ")).trim().toLowerCase();
|
|
3605
|
-
return ans === "" || ans === "y" || ans === "yes";
|
|
3606
|
-
} finally {
|
|
3607
|
-
rl.close();
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
function scaffoldHelloCart(dir) {
|
|
3611
|
-
fs2.mkdirSync(path3.join(dir, "migrations"), { recursive: true });
|
|
3612
|
-
fs2.writeFileSync(path3.join(dir, "schema.nbt"), HELLO_SCHEMA);
|
|
3613
|
-
}
|
|
3614
|
-
customCommands.add("add");
|
|
3615
|
-
program2.command("add").description("Vendor standard-library cartridges into this project").argument("<cartridge...>", "standard cartridge name(s)").option("--overwrite", "replace an existing local cartridge").action((cartridges, opts) => {
|
|
3616
|
-
try {
|
|
3617
|
-
const proj = loadNbtProject();
|
|
3618
|
-
for (const name of cartridges) {
|
|
3619
|
-
const dest = addStandardCartridge(
|
|
3620
|
-
name,
|
|
3621
|
-
proj.cartsDir,
|
|
3622
|
-
opts.overwrite === true
|
|
3623
|
-
);
|
|
3624
|
-
console.log(`Added ${name} -> ${path3.relative(proj.rootDir, dest)}`);
|
|
3625
|
-
}
|
|
3626
|
-
console.log(
|
|
3627
|
-
"Run `nbt migrate deploy` to deploy the local cartridge set."
|
|
3628
|
-
);
|
|
3629
|
-
} catch (e) {
|
|
3630
|
-
console.error(`nbt add: ${e?.message ?? e}`);
|
|
3631
|
-
process.exit(1);
|
|
3632
|
-
}
|
|
3633
|
-
});
|
|
3634
|
-
function addStandardCartridge(name, cartsDir, overwrite) {
|
|
3635
|
-
if (!/^[a-z0-9][a-z0-9_-]*$/.test(name)) {
|
|
3636
|
-
throw new Error(`invalid cartridge name '${name}'`);
|
|
3637
|
-
}
|
|
3638
|
-
const src = path3.join(STDLIB, name);
|
|
3639
|
-
if (!fs2.existsSync(path3.join(src, "schema.nbt"))) {
|
|
3640
|
-
const available = fs2.existsSync(STDLIB) ? fs2.readdirSync(STDLIB, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort().join(", ") : "";
|
|
3641
|
-
throw new Error(
|
|
3642
|
-
`unknown standard cartridge '${name}'${available ? ` (available: ${available})` : " (broken install: stdlib missing)"}`
|
|
3643
|
-
);
|
|
3644
|
-
}
|
|
3645
|
-
const dest = path3.join(cartsDir, name);
|
|
3646
|
-
if (fs2.existsSync(dest)) {
|
|
3647
|
-
if (!overwrite)
|
|
3648
|
-
throw new Error(`${dest} already exists; use --overwrite to replace it`);
|
|
3649
|
-
fs2.rmSync(dest, { recursive: true, force: true });
|
|
3524
|
+
return null;
|
|
3650
3525
|
}
|
|
3651
|
-
fs2.mkdirSync(cartsDir, { recursive: true });
|
|
3652
|
-
fs2.cpSync(src, dest, { recursive: true });
|
|
3653
|
-
return dest;
|
|
3654
3526
|
}
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
}
|
|
3670
|
-
|
|
3671
|
-
program2.command("update").description(
|
|
3672
|
-
"Update vendored standard-library modules from the bundled stdlib"
|
|
3673
|
-
).argument("<module...>", "standard module name(s)").action((modules) => {
|
|
3674
|
-
try {
|
|
3675
|
-
const proj = loadNbtProject();
|
|
3676
|
-
for (const name of modules) {
|
|
3677
|
-
const src = path3.join(STDLIB, name);
|
|
3678
|
-
if (!fs2.existsSync(path3.join(src, "schema.nbt"))) {
|
|
3679
|
-
throw new Error(`unknown standard module '${name}' (see: nbt list)`);
|
|
3680
|
-
}
|
|
3681
|
-
const dest = path3.join(proj.cartsDir, name);
|
|
3682
|
-
if (!fs2.existsSync(path3.join(dest, "schema.nbt"))) {
|
|
3683
|
-
throw new Error(
|
|
3684
|
-
`'${name}' is not installed in this project \u2014 run: nbt add ${name}`
|
|
3685
|
-
);
|
|
3527
|
+
function projectConsoleUrl() {
|
|
3528
|
+
if (process.env.NBT_CONSOLE_URL) return process.env.NBT_CONSOLE_URL;
|
|
3529
|
+
let dir = process.cwd();
|
|
3530
|
+
for (let i = 0; i < 32; i++) {
|
|
3531
|
+
const candidate = path2.join(dir, "nbt.json");
|
|
3532
|
+
if (fs2.existsSync(candidate)) {
|
|
3533
|
+
try {
|
|
3534
|
+
const cfg = JSON.parse(fs2.readFileSync(candidate, "utf8"));
|
|
3535
|
+
const dev = cfg?.environments?.dev ?? {};
|
|
3536
|
+
const explicit = cfg?.agent?.consoleUrl ?? dev?.consoleUrl;
|
|
3537
|
+
if (typeof explicit === "string" && explicit) return explicit;
|
|
3538
|
+
const host = typeof dev?.host === "string" && dev.host ? dev.host : "127.0.0.1";
|
|
3539
|
+
const port = Number(dev?.port) || 8080;
|
|
3540
|
+
return `http://${host}:${port}`;
|
|
3541
|
+
} catch {
|
|
3542
|
+
break;
|
|
3686
3543
|
}
|
|
3687
|
-
const written = copyStdlibOver(src, dest);
|
|
3688
|
-
for (const f of written)
|
|
3689
|
-
console.log(` wrote ${path3.relative(proj.rootDir, f)}`);
|
|
3690
|
-
console.log(`Updated ${name}.`);
|
|
3691
3544
|
}
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
} catch (e) {
|
|
3696
|
-
console.error(`nbt update: ${e?.message ?? e}`);
|
|
3697
|
-
process.exit(1);
|
|
3545
|
+
const parent = path2.dirname(dir);
|
|
3546
|
+
if (parent === dir) break;
|
|
3547
|
+
dir = parent;
|
|
3698
3548
|
}
|
|
3699
|
-
|
|
3700
|
-
function copyStdlibOver(src, dest) {
|
|
3701
|
-
const written = [];
|
|
3702
|
-
const walk = (s, d) => {
|
|
3703
|
-
fs2.mkdirSync(d, { recursive: true });
|
|
3704
|
-
for (const e of fs2.readdirSync(s, { withFileTypes: true })) {
|
|
3705
|
-
const sp = path3.join(s, e.name);
|
|
3706
|
-
const dp = path3.join(d, e.name);
|
|
3707
|
-
if (e.isDirectory()) walk(sp, dp);
|
|
3708
|
-
else {
|
|
3709
|
-
fs2.copyFileSync(sp, dp);
|
|
3710
|
-
written.push(dp);
|
|
3711
|
-
}
|
|
3712
|
-
}
|
|
3713
|
-
};
|
|
3714
|
-
walk(src, dest);
|
|
3715
|
-
return written;
|
|
3549
|
+
return "http://127.0.0.1:8080";
|
|
3716
3550
|
}
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
"-p, --port <port>",
|
|
3720
|
-
"console HTTP port (default: nbt.json dev env, else 8080)"
|
|
3721
|
-
).option("-d, --data-dir <dir>", "console data dir (default: ./data)").action((opts) => {
|
|
3722
|
-
runDev(opts).catch((e) => {
|
|
3723
|
-
console.error(`nbt dev: ${e?.message ?? e}`);
|
|
3724
|
-
process.exit(1);
|
|
3725
|
-
});
|
|
3726
|
-
});
|
|
3727
|
-
function loadNbtProject() {
|
|
3551
|
+
function projectLlmUrl() {
|
|
3552
|
+
if (process.env.NBT_LLM_URL) return process.env.NBT_LLM_URL;
|
|
3728
3553
|
let dir = process.cwd();
|
|
3729
3554
|
for (let i = 0; i < 32; i++) {
|
|
3730
|
-
const candidate =
|
|
3555
|
+
const candidate = path2.join(dir, "nbt.json");
|
|
3731
3556
|
if (fs2.existsSync(candidate)) {
|
|
3732
3557
|
try {
|
|
3733
3558
|
const cfg = JSON.parse(fs2.readFileSync(candidate, "utf8"));
|
|
3734
|
-
const
|
|
3735
|
-
const
|
|
3736
|
-
|
|
3559
|
+
const dev = cfg?.environments?.dev ?? {};
|
|
3560
|
+
const explicit = cfg?.agent?.llmUrl ?? dev?.llmUrl;
|
|
3561
|
+
if (typeof explicit === "string" && explicit) return explicit;
|
|
3737
3562
|
} catch {
|
|
3738
3563
|
break;
|
|
3739
3564
|
}
|
|
3565
|
+
return void 0;
|
|
3740
3566
|
}
|
|
3741
|
-
const parent =
|
|
3567
|
+
const parent = path2.dirname(dir);
|
|
3742
3568
|
if (parent === dir) break;
|
|
3743
3569
|
dir = parent;
|
|
3744
3570
|
}
|
|
3745
|
-
return
|
|
3746
|
-
rootDir: process.cwd(),
|
|
3747
|
-
cartsDir: path3.resolve(process.cwd(), "nbt"),
|
|
3748
|
-
port: 8080
|
|
3749
|
-
};
|
|
3750
|
-
}
|
|
3751
|
-
function withProjectUpDefaults(argv2) {
|
|
3752
|
-
const hasPort = argv2.some(
|
|
3753
|
-
(arg) => arg === "--port" || arg === "-p" || arg.startsWith("--port=")
|
|
3754
|
-
);
|
|
3755
|
-
if (hasPort) return argv2;
|
|
3756
|
-
return [...argv2, "--port", String(loadNbtProject().port)];
|
|
3757
|
-
}
|
|
3758
|
-
function discoverCarts(cartsDir) {
|
|
3759
|
-
if (!fs2.existsSync(cartsDir)) return [];
|
|
3760
|
-
return fs2.readdirSync(cartsDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path3.join(cartsDir, e.name)).filter((d) => fs2.existsSync(path3.join(d, "schema.nbt")));
|
|
3571
|
+
return void 0;
|
|
3761
3572
|
}
|
|
3762
|
-
function
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
if (e.name !== ".dist" && e.name !== "node_modules") walk(p);
|
|
3775
|
-
} else if (e.name.endsWith(".nbt")) {
|
|
3776
|
-
try {
|
|
3777
|
-
const m = fs2.statSync(p).mtimeMs;
|
|
3778
|
-
if (m > newest) newest = m;
|
|
3779
|
-
} catch {
|
|
3780
|
-
}
|
|
3573
|
+
function projectBranchId() {
|
|
3574
|
+
if (process.env.NBT_BRANCH_ID) return process.env.NBT_BRANCH_ID;
|
|
3575
|
+
let dir = process.cwd();
|
|
3576
|
+
for (let i = 0; i < 32; i++) {
|
|
3577
|
+
const candidate = path2.join(dir, "nbt.json");
|
|
3578
|
+
if (fs2.existsSync(candidate)) {
|
|
3579
|
+
try {
|
|
3580
|
+
const cfg = JSON.parse(fs2.readFileSync(candidate, "utf8"));
|
|
3581
|
+
const b = cfg?.branch;
|
|
3582
|
+
if (typeof b === "string" && b) return b;
|
|
3583
|
+
} catch {
|
|
3584
|
+
break;
|
|
3781
3585
|
}
|
|
3586
|
+
return void 0;
|
|
3782
3587
|
}
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
}
|
|
3787
|
-
|
|
3788
|
-
return new Promise((resolve3) => {
|
|
3789
|
-
const sock = net.connect({ port, host });
|
|
3790
|
-
sock.once("connect", () => {
|
|
3791
|
-
sock.destroy();
|
|
3792
|
-
resolve3(true);
|
|
3793
|
-
});
|
|
3794
|
-
sock.once("error", () => resolve3(false));
|
|
3795
|
-
sock.setTimeout(500, () => {
|
|
3796
|
-
sock.destroy();
|
|
3797
|
-
resolve3(false);
|
|
3798
|
-
});
|
|
3799
|
-
});
|
|
3588
|
+
const parent = path2.dirname(dir);
|
|
3589
|
+
if (parent === dir) break;
|
|
3590
|
+
dir = parent;
|
|
3591
|
+
}
|
|
3592
|
+
return void 0;
|
|
3800
3593
|
}
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
);
|
|
3811
|
-
return r.status === 0;
|
|
3594
|
+
function storedApiKey() {
|
|
3595
|
+
try {
|
|
3596
|
+
const p = path2.join(os.homedir(), ".nbt", "credentials.json");
|
|
3597
|
+
const creds = JSON.parse(fs2.readFileSync(p, "utf-8"));
|
|
3598
|
+
const key = creds?.apiKey;
|
|
3599
|
+
return typeof key === "string" && key.length > 0 ? key : void 0;
|
|
3600
|
+
} catch {
|
|
3601
|
+
return void 0;
|
|
3602
|
+
}
|
|
3812
3603
|
}
|
|
3813
|
-
|
|
3814
|
-
const
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
const upArgs = ["up", "--port", String(port)];
|
|
3819
|
-
if (opts.dataDir) upArgs.push("--data-dir", opts.dataDir);
|
|
3820
|
-
console.log(`nbt dev: starting console on :${port}`);
|
|
3821
|
-
const daemon = (0, import_node_child_process2.spawn)(CONSOLE_BIN, upArgs, {
|
|
3822
|
-
stdio: "inherit",
|
|
3823
|
-
env: consoleEnv()
|
|
3824
|
-
});
|
|
3825
|
-
let shuttingDown = false;
|
|
3826
|
-
const shutdown = (code = 0) => {
|
|
3827
|
-
if (shuttingDown) return;
|
|
3828
|
-
shuttingDown = true;
|
|
3829
|
-
try {
|
|
3830
|
-
daemon.kill("SIGTERM");
|
|
3831
|
-
} catch {
|
|
3832
|
-
}
|
|
3833
|
-
process.exit(code);
|
|
3834
|
-
};
|
|
3835
|
-
process.on("SIGINT", () => shutdown(0));
|
|
3836
|
-
process.on("SIGTERM", () => shutdown(0));
|
|
3837
|
-
daemon.on("exit", (code) => {
|
|
3838
|
-
if (!shuttingDown) {
|
|
3839
|
-
console.error(`nbt dev: console exited (${code ?? "signal"})`);
|
|
3840
|
-
process.exit(code ?? 1);
|
|
3841
|
-
}
|
|
3842
|
-
});
|
|
3843
|
-
let ready = false;
|
|
3844
|
-
for (let i = 0; i < 60; i++) {
|
|
3845
|
-
if (await tcpUp(port)) {
|
|
3846
|
-
ready = true;
|
|
3847
|
-
break;
|
|
3848
|
-
}
|
|
3849
|
-
await sleep(250);
|
|
3850
|
-
}
|
|
3851
|
-
if (!ready) {
|
|
3852
|
-
console.error("nbt dev: console did not come up in time");
|
|
3853
|
-
return shutdown(1);
|
|
3854
|
-
}
|
|
3855
|
-
const carts = discoverCarts(proj.cartsDir);
|
|
3856
|
-
if (carts.length === 0) {
|
|
3857
|
-
console.warn(
|
|
3858
|
-
`nbt dev: no carts found under ${proj.cartsDir} (nothing to watch)`
|
|
3604
|
+
function forwardToAgent(args) {
|
|
3605
|
+
const entry = resolveAgentEntry();
|
|
3606
|
+
if (!entry) {
|
|
3607
|
+
console.error(
|
|
3608
|
+
"@nbt-dev/nbt: coding agent not found (expected agent/packages/coding-agent/dist/cli.js). Build it with `npm run build` in npm/agent."
|
|
3859
3609
|
);
|
|
3610
|
+
process.exit(1);
|
|
3860
3611
|
}
|
|
3861
|
-
const
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3612
|
+
const env = nativeEnv();
|
|
3613
|
+
env.NBT_CONSOLE_URL = projectConsoleUrl();
|
|
3614
|
+
const llmUrl = projectLlmUrl();
|
|
3615
|
+
if (llmUrl) env.NBT_LLM_URL = llmUrl;
|
|
3616
|
+
const branchId = projectBranchId();
|
|
3617
|
+
if (branchId) env.NBT_BRANCH_ID = branchId;
|
|
3618
|
+
if (!env.NBT_API_KEY) {
|
|
3619
|
+
const key = storedApiKey();
|
|
3620
|
+
if (key) env.NBT_API_KEY = key;
|
|
3621
|
+
}
|
|
3622
|
+
const r = (0, import_node_child_process2.spawnSync)(process.execPath, [entry, ...args], {
|
|
3623
|
+
stdio: "inherit",
|
|
3624
|
+
env
|
|
3625
|
+
});
|
|
3626
|
+
if (r.error) {
|
|
3627
|
+
console.error(`@nbt-dev/nbt: failed to launch agent: ${r.error.message}`);
|
|
3628
|
+
process.exit(1);
|
|
3866
3629
|
}
|
|
3867
|
-
|
|
3868
|
-
`nbt dev: watching ${proj.cartsDir} \u2014 edit .nbt to reload (Ctrl-C to stop)`
|
|
3869
|
-
);
|
|
3870
|
-
let busy = false;
|
|
3871
|
-
setInterval(async () => {
|
|
3872
|
-
if (busy || shuttingDown) return;
|
|
3873
|
-
busy = true;
|
|
3874
|
-
try {
|
|
3875
|
-
for (const c of discoverCarts(proj.cartsDir)) {
|
|
3876
|
-
const m = newestNbtMtime(c);
|
|
3877
|
-
const prev = applied.get(c) ?? 0;
|
|
3878
|
-
if (m > prev) {
|
|
3879
|
-
await sleep(150);
|
|
3880
|
-
const settled = newestNbtMtime(c);
|
|
3881
|
-
console.log(`nbt dev: reload ${path3.basename(c)}`);
|
|
3882
|
-
installCart(c, port);
|
|
3883
|
-
applied.set(c, settled);
|
|
3884
|
-
}
|
|
3885
|
-
}
|
|
3886
|
-
} finally {
|
|
3887
|
-
busy = false;
|
|
3888
|
-
}
|
|
3889
|
-
}, 400);
|
|
3630
|
+
process.exit(r.status === null ? 1 : r.status);
|
|
3890
3631
|
}
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3632
|
+
function packageVersion() {
|
|
3633
|
+
try {
|
|
3634
|
+
const pkg = JSON.parse(
|
|
3635
|
+
fs2.readFileSync(path2.join(__dirname, "..", "package.json"), "utf8")
|
|
3636
|
+
);
|
|
3637
|
+
return typeof pkg?.version === "string" ? pkg.version : "unknown";
|
|
3638
|
+
} catch {
|
|
3639
|
+
return "unknown";
|
|
3896
3640
|
}
|
|
3897
|
-
|
|
3898
|
-
|
|
3641
|
+
}
|
|
3642
|
+
var program2 = new Command();
|
|
3643
|
+
program2.name("nbt").description("nbt.dev CLI").version(packageVersion(), "-v, --version", "Print the @nbt-dev/nbt version");
|
|
3644
|
+
var NBT = [
|
|
3645
|
+
["init", "Scaffold an nbt project"],
|
|
3646
|
+
["add", "Vendor standard cartridges into this project"],
|
|
3647
|
+
["list", "List available standard-library cartridges"],
|
|
3648
|
+
["update", "Refresh vendored cartridges from the stdlib"],
|
|
3649
|
+
["dev", "Boot the NBT runtime with live reload"],
|
|
3650
|
+
["build", "Build the frontend (esbuild SPA + SSR)"],
|
|
3651
|
+
["install", "Install a cartridge on a live instance"],
|
|
3652
|
+
["generate", "Generate a typed client from contracts"],
|
|
3653
|
+
["routes", "Generate file-based routes from app/"],
|
|
3654
|
+
["migrate", "Create migrations and deploy local cartridges"],
|
|
3655
|
+
["lsp", "Run the NBT language server over stdio (editors)"],
|
|
3656
|
+
["editor", "Install the NBT VS Code extension (editor install)"]
|
|
3657
|
+
];
|
|
3658
|
+
var CONSOLE = [
|
|
3659
|
+
["up", "Boot the NBT runtime"],
|
|
3660
|
+
["gen-cluster-key", "Generate a cluster signing key (copy to every node)"]
|
|
3661
|
+
];
|
|
3662
|
+
var consoleCommands = new Set(CONSOLE.map(([n]) => n));
|
|
3663
|
+
for (const [name, summary] of [...NBT, ...CONSOLE]) {
|
|
3664
|
+
program2.command(name).description(`${summary} (native)`);
|
|
3665
|
+
}
|
|
3666
|
+
program2.command("agent").description("Launch the nbt coding agent (defaults to the nbt provider)");
|
|
3667
|
+
var customCommands = /* @__PURE__ */ new Set();
|
|
3899
3668
|
customCommands.add("version");
|
|
3900
3669
|
program2.command("version").description("Print the @nbt-dev/nbt version").action(() => {
|
|
3901
3670
|
process.stdout.write(packageVersion() + "\n");
|
|
@@ -3942,6 +3711,7 @@ function runCompletion(words) {
|
|
|
3942
3711
|
if (words.length <= 1) {
|
|
3943
3712
|
const prefix = words[0] ?? "";
|
|
3944
3713
|
const names = [
|
|
3714
|
+
"agent",
|
|
3945
3715
|
...NBT.map(([n]) => n),
|
|
3946
3716
|
...CONSOLE.map(([n]) => n),
|
|
3947
3717
|
...customCommands
|
|
@@ -3966,6 +3736,9 @@ var first = argv[0];
|
|
|
3966
3736
|
if (first === "__complete__") {
|
|
3967
3737
|
runCompletion(argv.slice(1));
|
|
3968
3738
|
}
|
|
3739
|
+
if (first === "agent") {
|
|
3740
|
+
forwardToAgent(argv.slice(1));
|
|
3741
|
+
}
|
|
3969
3742
|
if (!first || first === "-h" || first === "--help" || first === "help") {
|
|
3970
3743
|
program2.outputHelp();
|
|
3971
3744
|
process.exit(first ? 0 : 1);
|