diff --git a/.github/workflows/node.js.yml b/.github/workflows/ci.yml similarity index 96% rename from .github/workflows/node.js.yml rename to .github/workflows/ci.yml index 118d040..0504096 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - node-version: [14.x] + node-version: [20.x] steps: - uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 14c5c55..c2c3f14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ node_modules/ package-lock.json -*.nbt -*.dat -*.json !package.json -yarn.lock \ No newline at end of file +yarn.lock + +# Generated test output +test/bigtest.json \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..5e45c23 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,6 @@ +# This configuration file was automatically generated by Gitpod. +# Please adjust to your needs (see https://www.gitpod.io/docs/introduction/learn-gitpod/gitpod-yaml) +# and commit this file to your remote git repository to share the goodness with others. +# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart +tasks: + - init: npm install diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8f39819 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 extremeheat + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 5e162f3..464fd0c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # nbt-dump +[![NPM version](https://img.shields.io/npm/v/nbt-dump.svg)](http://npmjs.com/package/nbt-dump) +[![Build Status](https://github.com/extremeheat/nbt-dump/actions/workflows/ci.yml/badge.svg)](https://github.com/extremeheat/nbt-dump/actions/workflows/) +[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/extremeheat/nbt-dump) A simple command line Node.js tool to read and write NBT files to JSON and back. Supports big, little and little-varint encoding. @@ -23,14 +26,23 @@ Parse an NBT file to JSON: nbt-dump [out-json-file] [little|big|varint] nbt-dump level.dat + (Dump the contents of level.dat to terminal) nbt-dump level.dat to level.json + (Dump the contents of level.dat to JSON) nbt-dump level.dat as little to level.json + (Dump the contents of little endian encoded level.dat to JSON) Write an JSON file to uncompressed NBT (defaults to big endian): nbt-dump write [out-nbt-file] [little|big|varint] nbt-dump write level.json to level.dat nbt-dump write level.json to level.dat as little + +You can also pipe the input to nbt-dump: + cat level.dat | nbt-dump + cat level.dat | nbt-dump to level.json + cat level.json | nbt-dump write + cat level.json | nbt-dump write to level.dat ``` ### Example diff --git a/cli.js b/cli.js new file mode 100755 index 0000000..f6e6490 --- /dev/null +++ b/cli.js @@ -0,0 +1,4 @@ +#!/usr/bin/env node +const { main } = require('./lib') +const args = process.argv.slice(2) +main(args, args.join(' ')) diff --git a/index.js b/lib.js similarity index 72% rename from index.js rename to lib.js index 6143536..6b60dfc 100644 --- a/index.js +++ b/lib.js @@ -1,4 +1,3 @@ -#!/usr/bin/env node const fs = require('fs') const nbt = require('prismarine-nbt') @@ -23,15 +22,29 @@ You can also pipe the input to nbt-dump: cat level.json | nbt-dump write to level.dat ` -async function main(args, argsStr) { - if ((args.length == 0 || argsStr.includes('help')) && !!process.stdin.isTTY) { +// async function isPipedInput (fd = 0) { +// return new Promise((resolve, reject) => { +// fs.fstat(fd, function (err, stats) { +// if (err) { +// reject(err) +// } else { +// resolve(stats.isFIFO()) +// } +// }) +// }) +// } + +async function main (args, argsStr) { + if ((args.length === 0 || argsStr.includes('help')) && !!process.stdin.isTTY) { console.warn(usage) process.exit(1) } - if (args[0] == 'read') args.shift() + if (args[0] === 'read') args.shift() let files = [] - if (!process.stdin.isTTY) files.push(undefined) - for (var arg of args) { + if (!process.stdin.isTTY && !process.env.CI) { + files.push(undefined) + } + for (const arg of args) { if (arg.includes('.')) files.push(arg) } const getFmt = () => { @@ -40,10 +53,10 @@ async function main(args, argsStr) { if (args.includes('little')) return 'little' return undefined } - if (args[0] == 'write') { + if (args[0] === 'write') { if (!files.length && args[1]) files.push(args[1]) - if (files.length == 1) files.push(files[0] || 'stdin' + '.nbt') - if (files.length == 2) return (await write(...files, getFmt())) + if (files.length === 1) files.push(files[0] || 'stdin' + '.nbt') + if (files.length === 2) return (await write(...files, getFmt())) } else { if (!files.length) files = [args[0], args[0] + '.json'] return read(files[0], files[1], getFmt()) @@ -53,13 +66,13 @@ async function main(args, argsStr) { console.warn(arguments) } -async function write(inpf, outf, fmt) { +async function write (inpf, outf, fmt) { console.log(`* Writing JSON from "${inpf || 'stdin'}" to "${outf}" as ${fmt || 'big'} endian`) - let json; + let json if (!inpf) { const chunks = [] - for await (const chunk of process.stdin) chunks.push(chunk); + for await (const chunk of process.stdin) chunks.push(chunk) json = JSON.parse(Buffer.concat(chunks).toString()) } else { json = JSON.parse(fs.readFileSync(inpf)) @@ -74,16 +87,15 @@ async function write(inpf, outf, fmt) { console.warn('Failed to write. Make sure that the JSON schema matches the prismarine-nbt ProtoDef schema. See https://github.com/PrismarineJS/prismarine-nbt') throw e } - return } -async function read(inpf, outf, fmt) { +async function read (inpf, outf, fmt) { console.log(`* Dumping NBT ${inpf ? 'file "' + inpf + '"' : '"stdin"'} to "${outf || 'stdout'}" as JSON ${fmt ? 'as ' + fmt : ''}`) - let buffer; + let buffer if (!inpf) { const chunks = [] - for await (const chunk of process.stdin) chunks.push(chunk); + for await (const chunk of process.stdin) chunks.push(chunk) buffer = Buffer.concat(chunks) } else { buffer = await fs.promises.readFile(inpf) @@ -101,5 +113,4 @@ async function read(inpf, outf, fmt) { return true } -const args = process.argv.slice(2) -main(args, args.join(' ')) \ No newline at end of file +module.exports = { main, write, read } diff --git a/package.json b/package.json index b3c9a83..178a3ab 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,15 @@ "name": "nbt-dump", "version": "1.0.2", "description": "Read and write Minecraft Named Binary Tag files in big, little and little-varint encoding", - "main": "index.js", + "main": "lib.js", "bin": { - "nbt-dump": "./index.js" + "nbt-dump": "./cli.js" }, "scripts": { - "test": "node test.js" + "lint": "standard", + "fix": "standard --fix", + "pretest": "npm run lint", + "test": "mocha --bail --exit" }, "repository": { "type": "git", @@ -30,5 +33,10 @@ "homepage": "https://github.com/extremeheat/nbt-dump#readme", "dependencies": { "prismarine-nbt": "^2.0.0" + }, + "devDependencies": { + "mocha": "^10.3.0", + "standard": "^17.1.0", + "nbt-dump": "file:." } } diff --git a/test.js b/test.js deleted file mode 100644 index 96e1788..0000000 --- a/test.js +++ /dev/null @@ -1,4 +0,0 @@ -const cp = require('child_process') - -cp.execSync(`node index.js file.nbt`, { stdio: 'inherit' }) -console.log('✔ Done') \ No newline at end of file diff --git a/test/basic.test.js b/test/basic.test.js new file mode 100644 index 0000000..6e504d5 --- /dev/null +++ b/test/basic.test.js @@ -0,0 +1,16 @@ +/* eslint-env mocha */ +/* eslint-disable n/no-path-concat */ +const lib = require('nbt-dump') +const fs = require('fs') +const assert = require('assert') + +describe('basic tests', () => { + it('writes bigtest.nbt to bigtest.json', async () => { + const bigNBT = `${__dirname}/bigtest.nbt` + const bigJSON = `${__dirname}/bigtest.json` + fs.rmSync(bigJSON, { force: true }) + const args = [bigNBT, bigJSON] + await lib.main(args, args.join(' ')) + assert(fs.existsSync(bigJSON)) + }) +}) diff --git a/test/bigtest.nbt b/test/bigtest.nbt new file mode 100644 index 0000000..a2021df Binary files /dev/null and b/test/bigtest.nbt differ