diff --git a/.github/auto-publish-action.js b/.github/auto-publish-action.js new file mode 100644 index 0000000..7d0d321 --- /dev/null +++ b/.github/auto-publish-action.js @@ -0,0 +1,111 @@ +const path = require('path'); +const { EOL } = require('os'); +const { existsSync } = require('fs'); +const { spawn } = require('child_process'); + +const workspace = process.env.GITHUB_WORKSPACE; +const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'; + +(async () => { + const event = process.env.GITHUB_EVENT_PATH ? require(process.env.GITHUB_EVENT_PATH) : {}; + + console.log('release event action:', event.action); + + if (event.action !== 'published' || !event.release) { + exitSuccess('This action is only run when a release is published.'); + return; + } + + console.log('release tag name:', event.release.tag_name); + + if (!event.release.tag_name) { + exitSuccess('This action is only run when a release is published with a tag name.'); + return; + } + + const releaseTargetBranch = event.release.target_commitish; + + console.log('release target branch:', releaseTargetBranch); + + if (releaseTargetBranch !== 'main') { + exitSuccess('This action is only run when a release is published from the main branch.'); + return; + } + + const releaseVersion = event.release.tag_name.startsWith('v') + ? event.release.tag_name.slice(1) + : event.release.tag_name; + + console.log('release version:', releaseVersion); + + const pkg = getPackageJson(); + const packageVersion = pkg.version.toString(); + + console.log('package.json version:', packageVersion); + + if (packageVersion !== releaseVersion) { + exitFailure('The version in package.json and the release tag version do not match.'); + return; + } + + try { + console.log('publishing package...'); + + await runInWorkspace(npmCommand, ['publish']); + + exitSuccess(`Package version v${releaseVersion} published!`); + } catch (e) { + logError(e); + exitFailure('Failed to publish package'); + return; + } +})(); + +function getPackageJson() { + const pathToPackage = path.join(workspace, 'package.json'); + if (!existsSync(pathToPackage)) + throw new Error("package.json could not be found in your project's root."); + return require(pathToPackage); +} + +function exitSuccess(message) { + console.info(`✔ success ${message}`); + process.exit(0); +} + +function exitFailure(message) { + logError(message); + process.exit(1); +} + +function logError(error) { + console.error(`✖ fatal ${error.stack || error}`); +} + +function runInWorkspace(command, args) { + return new Promise((resolve, reject) => { + const child = spawn(command, args, { cwd: workspace }); + + const errorMessages = []; + let isDone = false; + + child.on('error', (error) => { + if (!isDone) { + isDone = true; + reject(error); + } + }); + + child.stderr.on('data', (chunk) => errorMessages.push(chunk)); + + child.on('exit', (code) => { + if (!isDone) { + if (code === 0) { + resolve(); + } else { + reject(`${errorMessages.join('')}${EOL}${command} exited with code ${code}`); + } + } + }); + }); +} diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml new file mode 100644 index 0000000..38feb59 --- /dev/null +++ b/.github/workflows/formatting.yml @@ -0,0 +1,38 @@ +# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: JS and C++ Formatting + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + js-formatting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js 16 + uses: actions/setup-node@v2 + with: + node-version: '16.x' + cache: 'yarn' + + - run: yarn install + - run: yarn format:check + + cpp-formatting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Check C++ formatting with clang-format + uses: DoozyX/clang-format-lint-action@v0.13 + with: + source: './src' + exclude: './src/mio ./src/xxhash ./src/zstr' + extensions: 'h,c,cpp,hpp' + clangFormatVersion: 12 diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 0000000..521b467 --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,32 @@ +# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Node.js CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build-and-test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest, windows-2019, macos-latest] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + node-version: [12.x, 14.x, 16.x] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + cache: 'yarn' + + - run: yarn install + - run: yarn test diff --git a/.github/workflows/publish-to-npm.yml b/.github/workflows/publish-to-npm.yml new file mode 100644 index 0000000..63f9048 --- /dev/null +++ b/.github/workflows/publish-to-npm.yml @@ -0,0 +1,26 @@ +name: Publish to npm + +on: + release: + types: [published] + +jobs: + publish_to_npm: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + ref: main + + # Installs Node and sets up up the .npmrc file to publish to npm + - uses: actions/setup-node@v2 + with: + node-version: '16.x' + registry-url: 'https://registry.npmjs.org' + cache: 'yarn' + + - run: yarn install + - run: yarn test + - run: node .github/auto-publish-action.js + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 08a33a6..70a14c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vscode build node_modules -yarn-error.log \ No newline at end of file +yarn-error.log +_deleted diff --git a/README.md b/README.md index ade7ee1..4ad0bbe 100644 --- a/README.md +++ b/README.md @@ -20,20 +20,24 @@ The following example shows a typical usage pattern of creating a decoder with n const { NbsDecoder } = require('nbsjs'); // Create a decoder instance -const decoder = new NbsDecoder(['/path/to/file/a.nbs', '/path/to/file/b.nbs', '/path/to/file/c.nbs']); +const decoder = new NbsDecoder([ + '/path/to/file/a.nbs', + '/path/to/file/b.nbs', + '/path/to/file/c.nbs', +]); // Get a list of all types present in the NBS files, and get the first type const types = decoder.getAvailableTypes(); -const firstType = types[0] +const firstType = types[0]; // Set the timestamp range for the first available type const [start, end] = decoder.getTimestampRange(firstType); // Get the packet at the given timestamp for the first type -const packets = decoder.getPackets(start, [firstType]) +const packets = decoder.getPackets(start, [firstType]); // Log all the values for inspection -console.log({ types, firstType, start, end, packets }) +console.log({ types, firstType, start, end, packets }); ``` ## API diff --git a/binding.gyp b/binding.gyp index 4e27d20..58206f5 100644 --- a/binding.gyp +++ b/binding.gyp @@ -24,13 +24,13 @@ 'OS=="linux"', { "ccflags": [ - "-std=c++17", + "-std=c++14", "-fPIC", "-fext-numeric-literals", "-fexceptions", ], "ccflags!": ["-fno-exceptions"], - "cflags_cc": ["-std=c++17", "-fext-numeric-literals"], + "cflags_cc": ["-std=c++14", "-fext-numeric-literals"], "cflags_cc!": ["-fno-exceptions", "-fno-rtti"], }, ], @@ -38,19 +38,19 @@ 'OS=="mac"', { "ccflags": [ - "-std=c++17", + "-std=c++14", "-fPIC", "-fext-numeric-literals", "-fexceptions", ], "ccflags!": ["-fno-exceptions"], - "cflags_cc": ["-std=c++17", "-fext-numeric-literals"], + "cflags_cc": ["-std=c++14", "-fext-numeric-literals"], "cflags_cc!": ["-fno-exceptions", "-fno-rtti"], "xcode_settings": { "MACOSX_DEPLOYMENT_TARGET": "10.9", "GCC_ENABLE_CPP_EXCEPTIONS": "YES", "GCC_ENABLE_CPP_RTTI": "YES", - "OTHER_CPLUSPLUSFLAGS": ["-std=c++17", "-stdlib=libc++"], + "OTHER_CPLUSPLUSFLAGS": ["-std=c++14", "-stdlib=libc++"], "OTHER_LDFLAGS": ["-stdlib=libc++"], }, }, @@ -61,7 +61,7 @@ "defines": ["_HAS_EXCEPTIONS=1"], "msvs_settings": { "VCCLCompilerTool": { - "AdditionalOptions": ["-std:c++17"], + "AdditionalOptions": ["-std:c++14"], }, }, }, diff --git a/nbs.d.ts b/nbs.d.ts index ce8cedf..37d87a4 100644 --- a/nbs.d.ts +++ b/nbs.d.ts @@ -40,8 +40,8 @@ export interface NbsTypeSubtype { * A (type, subtype) pair that uniquely identifies a specific type of message, * where the type is always a Buffer */ - export interface NbsTypeSubtypeBuffer extends NbsTypeSubtype { - type: Buffer +export interface NbsTypeSubtypeBuffer extends NbsTypeSubtype { + type: Buffer; } /** diff --git a/package.json b/package.json index 3734c8d..0806b19 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "scripts": { "build": "node-gyp configure && node-gyp build", "test": "node tests/test.js", - "format": "prettier --write *.js *.d.ts .github/**/*.js tests/*.js", - "format:check": "prettier --check *.js *.d.ts .github/**/*.js tests/*.js" + "format": "prettier --write \"*.{js,ts,json,md}\" \".github/**/*.{js,yml}\" \"tests/*.js\"", + "format:check": "prettier --check \"*.{js,ts,json,md}\" \".github/**/*.{js,yml}\" \"tests/*.js\"" }, "repository": { "type": "git", diff --git a/src/Index.hpp b/src/Index.hpp index 31c0436..b1490fe 100755 --- a/src/Index.hpp +++ b/src/Index.hpp @@ -1,9 +1,9 @@ #ifndef NBS_INDEX_HPP #define NBS_INDEX_HPP -#include #include #include +#include #include #include "IndexItem.hpp" @@ -11,6 +11,7 @@ #include "zstr/zstr.hpp" namespace nbs { + class Index { public: /// Empty default constructor @@ -24,17 +25,17 @@ namespace nbs { template Index(const T& paths) { for (size_t i = 0; i < paths.size(); i++) { - auto& nbsPath = paths[i]; - std::filesystem::path idxPath = nbsPath + ".idx"; + auto& nbsPath = paths[i]; + std::string idxPath = nbsPath + ".idx"; // Currently we only handle nbs files that have an index file // If there's no index file, throw - if (!std::filesystem::exists(idxPath)) { + if (!this->fileExists(idxPath)) { throw std::runtime_error("nbs index not found for file: " + nbsPath); } // Load the index file - zstr::ifstream input(idxPath.string()); + zstr::ifstream input(idxPath, zstr::ifstream::binary); // Read the index items from the file while (input.good()) { @@ -111,7 +112,9 @@ namespace nbs { /// Get the first and last timestamps across all items in the index std::pair getTimestampRange() { - std::pair range{std::numeric_limits::max(), 0}; + // std::numeric_limits::max is wrapped in () here to workaround an issue on Windows + // See https://stackoverflow.com/a/27443191 + std::pair range{(std::numeric_limits::max)(), 0}; for (auto& mapEntry : this->typeMap) { const IndexItem& firstItem = mapEntry.second.first->item; @@ -150,6 +153,13 @@ namespace nbs { /// Maps a (type, subtype) to the iterator over the index items for that type and subtype std::map::iterator, std::vector::iterator>> typeMap; + + /// Check if a file exists at the given path + bool fileExists(const std::string& path) { + // Shamelessly stolen from: http://stackoverflow.com/a/12774387/1387006 + struct stat buffer {}; + return (stat(path.c_str(), &buffer) == 0); + } }; } // namespace nbs diff --git a/src/IndexItem.hpp b/src/IndexItem.hpp index 2147501..d4cad03 100755 --- a/src/IndexItem.hpp +++ b/src/IndexItem.hpp @@ -2,7 +2,6 @@ #define NBS_INDEXITEM_HPP #include -#include #include #include diff --git a/src/mio/README.md b/src/mio/README.md new file mode 100644 index 0000000..463e8ea --- /dev/null +++ b/src/mio/README.md @@ -0,0 +1,3 @@ +# mio: 3f86a95c0784d73ce6815237ec33ed25f233b643 + +Downloaded from https://github.com/mandreyel/mio/tree/3f86a95c0784d73ce6815237ec33ed25f233b643, on 2 Mar 2022 to use for memory mapping. diff --git a/src/zstr/README.md b/src/zstr/README.md new file mode 100644 index 0000000..36b9d2e --- /dev/null +++ b/src/zstr/README.md @@ -0,0 +1,7 @@ +# zstr: 1.0.5 + +Used for reading g-zipped files using an `ifstream`. Downloaded from https://github.com/mateidavid/zstr/releases/tag/v1.0.5, on 2 Mar 2022. + +Made these changes: + +- Changed the #include type from `<>` to `""` on lines 15 and 20 in `zstr.hpp`.