Bare Squid Works!

This commit is contained in:
Raven Scott
2026-07-30 23:18:12 -04:00
parent fd537ed47e
commit 501d1e5cfd
28 changed files with 6615 additions and 45 deletions
+211
View File
@@ -0,0 +1,211 @@
/**
* Flying Jib CLI — Bare entry (ADR-0013).
*
* Usage:
* bare bin.mjs create <name> [--version 1.21.1]
* bare bin.mjs list
* bare bin.mjs start <name> [--port 25565] [--no-updates]
* bare bin.mjs status
*/
import { createRequire } from 'module'
import { command, flag, arg, summary, header, footer } from 'paparam'
import path from 'path'
import process from 'process'
import { fileURLToPath } from 'url'
import pkg from './package.json' with { type: 'json' }
import App from './app.js'
const require = createRequire(import.meta.url)
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const appName = pkg.productName || pkg.name
const isBare = typeof Bare !== 'undefined'
const argv0 = isBare ? Bare.argv[0] : process.argv[0]
const base = path.basename(argv0)
// bare-runtime embeds as "bare"; packaged standalone uses product name
const isDev = base === 'bare' || base === 'node' || /bare-runtime/.test(argv0)
const rawArgv = isBare ? Bare.argv.slice(isDev ? 2 : 1) : process.argv.slice(2)
function resolveStorage(flagStorage) {
if (flagStorage) return path.resolve(flagStorage)
const os = require('os')
if (isBare) {
try {
const { persistent } = require('bare-storage')
return isDev ? path.join(os.tmpdir(), 'pear', appName) : path.join(persistent(), appName)
} catch {
return path.join(os.tmpdir(), 'pear', appName)
}
}
return path.join(os.tmpdir(), 'pear', appName)
}
function exit(code) {
if (isBare) Bare.exit(code)
else process.exit(code)
}
function makeApp(storage, updates = false) {
return new App({
dir: storage,
appPath: isDev ? null : argv0,
updates,
version: pkg.version,
upgrade: pkg.upgrade,
name: appName
})
}
const createCmd = command(
'create',
summary('Create a new local world'),
arg('<name>', 'world name / id'),
flag('--version [ver]', 'Minecraft version for Flying Squid'),
flag('--motd [text]', 'server MOTD'),
async (cmd) => {
const storage = resolveStorage(root.flags.storage)
const app = makeApp(storage, false)
await app.ready()
try {
const meta = app.createWorld({
name: cmd.args.name,
version: cmd.flags.version,
motd: cmd.flags.motd
})
console.log('Created world:', meta.id)
console.log(' version:', meta.version)
console.log(' path: ', path.join(storage, 'worlds', meta.id))
} finally {
await app.close()
}
}
)
const listCmd = command(
'list',
summary('List local worlds'),
async () => {
const storage = resolveStorage(root.flags.storage)
const app = makeApp(storage, false)
await app.ready()
try {
const worlds = app.listWorlds()
if (!worlds.length) {
console.log('No worlds yet. Create one: flying-jib create <name>')
return
}
for (const w of worlds) {
console.log(`- ${w.id} (${w.version}) ${w.name}`)
}
} finally {
await app.close()
}
}
)
const startCmd = command(
'start',
summary('Start local Flying Squid for a world (127.0.0.1 only)'),
arg('<name>', 'world name / id'),
flag('--port|-p [port]', 'local Minecraft port (default 25565)'),
flag('--version [ver]', 'override Minecraft version'),
flag('--no-updates', 'disable OTA updates for this run'),
async (cmd) => {
const storage = resolveStorage(root.flags.storage)
// paparam: --no-updates → flags.updates === false when present
const updates = cmd.flags.updates === false || root.flags.updates === false ? false : false
const app = makeApp(storage, updates)
app.on('message', (m) => console.log(m))
app.on('error', (err) => console.error('[error]', err))
const shutdown = async (code) => {
console.log('\nStopping…')
try {
await app.stopWorld()
} catch {
// ignore
}
await app.exit(code)
exit(code)
}
process.on('SIGINT', () => {
shutdown(130)
})
process.on('SIGTERM', () => {
shutdown(143)
})
await app.ready()
try {
const status = await app.startWorld({
world: cmd.args.name,
port: cmd.flags.port ? Number(cmd.flags.port) : 25565,
version: cmd.flags.version
})
console.log('')
console.log(`${appName} world running (Bare/Pear, ADR-0013)`)
console.log(` world: ${cmd.args.name}`)
console.log(` bind: ${status.host}:${status.port}`)
console.log(` listen: ${status.listen?.address}:${status.listen?.port}`)
console.log(` version:${status.version}`)
console.log('')
console.log('Connect Java Edition to:')
console.log(` ${status.host}:${status.port}`)
console.log('')
console.log('Press Ctrl+C to stop.')
await new Promise(() => {})
} catch (err) {
console.error('[start failed]', err)
await app.close()
exit(1)
}
}
)
const statusCmd = command(
'status',
summary('Show storage path and worlds'),
async () => {
const storage = resolveStorage(root.flags.storage)
console.log('storage:', storage)
const app = makeApp(storage, false)
await app.ready()
try {
const worlds = app.listWorlds()
console.log('worlds:', worlds.length)
for (const w of worlds) console.log(' -', w.id, w.version)
} finally {
await app.close()
}
}
)
const root = command(
appName,
header(`${appName} — decentralized P2P Minecraft (Bare/Pear)`),
summary(pkg.description),
flag('--version|-v', 'Print version'),
flag('--storage <dir>', 'App storage directory'),
footer('Docs: living_docs/ | agent/ADRs/0013-bare-pear-only-runtime-and-distribution.md'),
createCmd,
listCmd,
startCmd,
statusCmd
)
const program = root.parse(rawArgv)
if (root.flags.version) {
console.log(`${appName} v${pkg.version}`)
exit(0)
}
if (program === null && !rawArgv.length) {
exit(0)
}
// silence unused in some linters
void __dirname
void __filename