├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── node.js.yml │ └── publish.yml ├── .gitignore ├── .gitmodules ├── .jsdoc.conf ├── .ncurc.js ├── .npmrc ├── .yarnrc.yml ├── LICENSE.md ├── README.md ├── ava.config.cjs ├── eslint.config.mjs ├── package.json ├── packages ├── browserify-demo │ ├── .gitignore │ ├── .npmrc │ ├── LICENSE.md │ ├── package.json │ └── src │ │ ├── index-bf.html │ │ ├── index.js │ │ └── style.css ├── cbor-bigdecimal │ ├── .npmignore │ ├── .npmrc │ ├── LICENSE.md │ ├── README.md │ ├── bigdecimal.js │ ├── dist │ │ └── cbor-bigdecimal.js │ ├── package.json │ ├── test │ │ └── bigdecimal.ava.js │ └── webpack.config.js ├── cbor-cli │ ├── .npmignore │ ├── .npmrc │ ├── LICENSE.md │ ├── README.md │ ├── bin │ │ ├── cbor.js │ │ ├── cbor2comment.js │ │ ├── cbor2diag.js │ │ ├── cbor2js.js │ │ ├── cbor2json.js │ │ ├── js2cbor.js │ │ └── json2cbor.js │ ├── lib │ │ └── utils.js │ ├── man │ │ ├── cbor.1.gz │ │ ├── cbor2comment.1.gz │ │ ├── cbor2diag.1.gz │ │ ├── cbor2json.1.gz │ │ └── json2cbor.1.gz │ ├── man_src │ │ ├── cbor.md │ │ ├── cbor2comment.md │ │ ├── cbor2diag.md │ │ ├── cbor2json.md │ │ └── json2cbor.md │ ├── package.json │ └── test │ │ ├── exec.ava.js │ │ ├── fixtures │ │ ├── function.js │ │ └── object.js │ │ └── utils.ava.js ├── cbor-rn-prereqs │ ├── .npmignore │ ├── .npmrc │ ├── LICENSE.md │ ├── README.md │ ├── index.js │ ├── package.json │ └── test │ │ └── index.ava.js ├── cbor-web │ ├── .npmignore │ ├── .npmrc │ ├── LICENSE.md │ ├── README.md │ ├── dist │ │ ├── cbor.js │ │ └── cbor.js.LICENSE.txt │ ├── lib │ │ └── cbor.js │ ├── package.json │ ├── types │ │ ├── lib │ │ │ ├── cbor.d.ts │ │ │ ├── commented.d.ts │ │ │ ├── constants.d.ts │ │ │ ├── decoder.d.ts │ │ │ ├── diagnose.d.ts │ │ │ ├── encoder.d.ts │ │ │ ├── map.d.ts │ │ │ ├── objectRecorder.d.ts │ │ │ ├── sharedValueEncoder.d.ts │ │ │ ├── simple.d.ts │ │ │ ├── tagged.d.ts │ │ │ └── utils.d.ts │ │ └── vendor │ │ │ └── binary-parse-stream │ │ │ └── index.d.ts │ └── webpack.config.js ├── cbor │ ├── .dockerignore │ ├── .npmignore │ ├── .npmrc │ ├── Dockerfile │ ├── LICENSE.md │ ├── README.md │ ├── lib │ │ ├── cbor.js │ │ ├── commented.js │ │ ├── constants.js │ │ ├── decoder.js │ │ ├── diagnose.js │ │ ├── encoder.js │ │ ├── map.js │ │ ├── objectRecorder.js │ │ ├── sharedValueEncoder.js │ │ ├── simple.js │ │ ├── tagged.js │ │ └── utils.js │ ├── package.json │ ├── test │ │ ├── cases.js │ │ ├── commented.ava.js │ │ ├── decoder.ava.js │ │ ├── diagnose.ava.js │ │ ├── encoder.ava.js │ │ ├── garbage.ava.js │ │ ├── implementation_matrix.js │ │ ├── map.ava.js │ │ ├── objectRecorder.ava.js │ │ ├── plugins.ava.js │ │ ├── sharedValueEncoder.ava.js │ │ ├── simple.ava.js │ │ ├── streams.js │ │ ├── tagged.ava.js │ │ ├── test-vectors.ava.js │ │ └── utils.ava.js │ ├── tsconfig.json │ ├── types │ │ ├── lib │ │ │ ├── cbor.d.ts │ │ │ ├── commented.d.ts │ │ │ ├── constants.d.ts │ │ │ ├── decoder.d.ts │ │ │ ├── diagnose.d.ts │ │ │ ├── encoder.d.ts │ │ │ ├── map.d.ts │ │ │ ├── objectRecorder.d.ts │ │ │ ├── sharedValueEncoder.d.ts │ │ │ ├── simple.d.ts │ │ │ ├── tagged.d.ts │ │ │ └── utils.d.ts │ │ └── vendor │ │ │ └── binary-parse-stream │ │ │ └── index.d.ts │ └── vendor │ │ └── binary-parse-stream │ │ ├── README.md │ │ └── index.js ├── parcel-demo │ ├── .gitignore │ ├── LICENSE.md │ ├── package.json │ └── src │ │ ├── index-p.html │ │ ├── index-p.js │ │ └── style.css ├── plain-demo │ ├── .gitignore │ ├── .npmrc │ ├── build.js │ ├── package.json │ └── src │ │ ├── index-plain.html │ │ ├── index-plain.js │ │ ├── index.html │ │ └── style.css ├── puppeteer-demo │ ├── .npmrc │ ├── index.js │ └── package.json └── webpack-demo │ ├── .gitignore │ ├── .npmrc │ ├── LICENSE.md │ ├── package.json │ ├── src │ ├── index-wp.js │ ├── style.css │ └── webpack.html │ └── webpack.config.js ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── test └── spot-check-web.ava.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | charset = utf-8 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | *.{png,jpg,jpeg,gif,gz,ttf,webp,woff,woff2} binary 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [hildjj] 2 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Tests 3 | 4 | on: 5 | push: 6 | branches: [master, main] 7 | pull_request: 8 | branches: [master, main] 9 | workflow_call: 10 | secrets: 11 | codecov_token: 12 | required: true 13 | 14 | jobs: 15 | build: 16 | 17 | strategy: 18 | matrix: 19 | node-version: [20, 22, 23] 20 | platform: [ubuntu-latest, windows-latest] 21 | 22 | runs-on: ${{ matrix.platform }} 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | with: 27 | submodules: true 28 | - uses: pnpm/action-setup@v4 29 | - name: Use Node.js ${{ matrix.node-version }} 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version: ${{ matrix.node-version }} 33 | cache: 'pnpm' 34 | - name: Install dependencies 35 | run: pnpm i -r --filter '!*-demo' --filter '!cbor-web' 36 | - name: Test ${{ matrix.node-version }} 37 | run: npm run coverage 38 | - name: Upload coverage reports to Codecov 39 | uses: codecov/codecov-action@v5 40 | with: 41 | token: ${{ secrets.CODECOV_TOKEN }} 42 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npmjs 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | contents: write 10 | id-token: write 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: pnpm/action-setup@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: '22' 17 | registry-url: 'https://registry.npmjs.org' 18 | cache: pnpm 19 | - run: pnpm i -r 20 | - run: npm run build 21 | - run: npm run docs || true 22 | - run: npm run copy 23 | - name: Deploy Docs 24 | uses: peaceiris/actions-gh-pages@v4 25 | with: 26 | github_token: ${{ secrets.GITHUB_TOKEN }} 27 | publish_dir: docs 28 | publish_branch: gh-pages 29 | - run: npx monopub delete devDependencies,scripts 30 | - run: npx monopub exec 'npm publish --access public --provenance' 31 | env: 32 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .nyc_output/ 3 | .parcel-cache/ 4 | .vscode/ 5 | *.js.map 6 | coverage/ 7 | docs/ 8 | jsconfig.json 9 | node_modules/ 10 | npm-debug.log 11 | shrinkwrap.yaml 12 | t.js 13 | TAGS 14 | typings.json 15 | typings/ 16 | yarn-error.log 17 | yarn.lock 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test-vectors"] 2 | path = test-vectors 3 | url = https://github.com/hildjj/test-vectors.git 4 | branch = failures 5 | -------------------------------------------------------------------------------- /.jsdoc.conf: -------------------------------------------------------------------------------- 1 | { 2 | "source" : { 3 | "include": ["packages/cbor/lib/", "packages/cbor/vendor/binary-parse-stream", "packages/cbor/README.md"], 4 | "exclude": ["packages/cbor/lib/constants.js"] 5 | }, 6 | "opts": { 7 | "template": "node_modules/docdash", 8 | "destination": "docs", 9 | "encoding": "utf8" 10 | }, 11 | "templates": { 12 | "cleverLinks": false, 13 | "monospaceLinks": false, 14 | "sort": true, 15 | "default": { 16 | "includeDate": false 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.ncurc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | reject: [ 5 | 'json-text-sequence', 6 | 'nofilter', 7 | 'p-event', 8 | 'rimraf', 9 | 'webpack-cli', 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | changesetIgnorePatterns: 2 | - "./packages/*/test/*.js" 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CBOR 2 | 3 | Encode and parse data in the Concise Binary Object Representation (CBOR) data 4 | format ([RFC8949](https://www.rfc-editor.org/rfc/rfc8949.html)). 5 | 6 | ## MOVE TO CBOR2 7 | 8 | **NOTE** 9 | 10 | All new users and most existing users of these libraries should move to the 11 | [cbor2](https://github.com/hildjj/cbor2) library. It is where most 12 | maintenance and support and all new features are happening. 13 | 14 | *Only* catastrophic bugs will be fixed in these libraries going forward. 15 | 16 | ## Pointers 17 | 18 | This is a monorepo that holds a few related packages: 19 | 20 | - [cbor](packages/cbor): a node-centric CBOR processor 21 | - [cbor-web](packages/cbor-web): the `cbor` package compiled for use on the 22 | web, including all of its non-optional dependencies 23 | - [cbor-cli](packages/cbor-cli): a set of command-line tools for working with 24 | the `cbor` package 25 | - Examples: 26 | - [webpack-demo](packages/webpack-demo): bundle `cbor` using [webpack](https://webpack.js.org/) 27 | - [parcel-demo](packages/parcel-demo): bundle `cbor` using [parcel](https://parceljs.org/) 28 | - [browserify-demo](packages/browserify-demo): bundle `cbor` using [browserify](http://browserify.org/) 29 | - [plain-demo](packages/plain-demo): bundle `cbor` by just using `cbor-web` directly 30 | 31 | ## Tooling 32 | 33 | - Install with `pnpm install -r`, [see](https://pnpm.js.org/). The important 34 | thing (for example) is that the `cbor-cli` package ends up depending on the 35 | local version of `cbor`. 36 | - monorepo-wide scripts: 37 | - `install-global` (make available everywhere) or `install-local` (use 38 | `npx` if you want to us it outside a package script) install all of the 39 | tooling that might be needed locally, but isn't needed on CI 40 | - `deploy`: build and deploy `cbor-web` and all of the actions 41 | - `coverage`: run tests and report coverage; look in `coverage/lcov-report/index.html`. 42 | - `lint`: run eslint over all projects 43 | 44 | ## GitHub dependencies 45 | 46 | If you really need to get at a specific rev from GitHub, you can no longer do 47 | `npm install hildjj/node-cbor`. Instead you need: 48 | 49 | npm install https://gitpkg.now.sh/hildjj/node-cbor/packages/cbor?main 50 | 51 | ## Supported Node.js versions 52 | 53 | This project now only supports versions of Node that the Node team is [currently supporting](https://github.com/nodejs/Release#release-schedule). Ava's [support statement](https://github.com/avajs/ava/blob/main/docs/support-statement.md) is what we will be using as well. Currently, that means Node `16`+ is required. If you need to support an older version of Node (back to version 6), use cbor version 5.2.x, which will get nothing but security updates from here on out. 54 | -------------------------------------------------------------------------------- /ava.config.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('node:path'); 4 | const config = { 5 | files: ['./packages/*/test/*.ava.js'], 6 | timeout: '5m', 7 | }; 8 | 9 | if (process.env.CBOR_PACKAGE) { 10 | const NODE_PATH = [ 11 | path.resolve(__dirname, 'packages', 'cbor', 'node_modules'), 12 | ]; 13 | if (process.env.NODE_PATH) { 14 | NODE_PATH.push(...process.env.NODE_PATH.split(path.delimiter)); 15 | } 16 | config.environmentVariables = { 17 | NODE_PATH: NODE_PATH.join(path.delimiter), 18 | }; 19 | } 20 | module.exports = config; 21 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import ava from '@cto.af/eslint-config/ava.js'; 2 | import base from '@cto.af/eslint-config'; 3 | import globals from '@cto.af/eslint-config/globals.js'; 4 | import markdown from '@cto.af/eslint-config/markdown.js'; 5 | 6 | export default [ 7 | { 8 | ignores: [ 9 | 'packages/browserify-demo/dist/**', 10 | 'packages/cbor-bigdecimal/dist/**', 11 | 'packages/cbor-web/dist/**', 12 | 'packages/plain-demo/dist/**', 13 | 'packages/webpack-demo/dist/**', 14 | '**/*.d.ts', 15 | ], 16 | }, 17 | ...base, 18 | ...markdown, 19 | ...ava, 20 | { 21 | files: [ 22 | 'packages/cbor/lib/**', 23 | 'packages/cbor/test/**', 24 | 'packages/browserify-demo/src/**', 25 | 'packages/webpack-demo/src/**', 26 | ], 27 | rules: { 28 | 'n/prefer-node-protocol': 'off', 29 | }, 30 | }, 31 | { 32 | files: [ 33 | 'packages/cbor-cli/**', 34 | ], 35 | rules: { 36 | 'no-console': 'off', 37 | }, 38 | }, 39 | { 40 | files: [ 41 | 'packages/cbor-web/lib/**', 42 | 'packages/parcel-demo/src/**', 43 | ], 44 | languageOptions: { 45 | sourceType: 'module', 46 | globals: globals.browser, 47 | }, 48 | rules: { 49 | 'n/prefer-node-protocol': 'off', 50 | }, 51 | }, 52 | { 53 | files: [ 54 | 'test-vectors/appendix_a.json', 55 | ], 56 | rules: { 57 | 'json/no-unsafe-values': 'off', 58 | }, 59 | }, 60 | ]; 61 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cbor-monorepo", 3 | "private": true, 4 | "main": "./packages/cbor/lib/cbor.js", 5 | "version": "10.0.3", 6 | "author": { 7 | "name": "Joe Hildebrand", 8 | "email": "joe-github@cursive.net" 9 | }, 10 | "license": "MIT", 11 | "scripts": { 12 | "clean": "rimraf pnpm-lock.yaml .parcel-cache docs node_modules coverage .nyc_output packages/*/node_modules packages/*/coverage packages/*/.nyc_output packages/*/pnpm-lock.yaml", 13 | "docs": "jsdoc -c .jsdoc.conf", 14 | "lint": "eslint .", 15 | "test": "ava packages/*/test/*.ava.js", 16 | "test:versions": "nve --continue --arch x64 --parallel 23,22,20,18 npm test", 17 | "test:bigendian": "docker run --rm -it -v ${PWD}:/root/cbor -w /root/cbor s390x/node npm test", 18 | "test:spot-check": "ava test/*.ava.js && CBOR_PACKAGE=${INIT_CWD}/packages/cbor-web/dist/cbor.js npm run test", 19 | "test:web": "node packages/puppeteer-demo/index.js", 20 | "test:all": "npm run test:versions && npm run test:spot-check && npm run test:bigendian && npm run test:web", 21 | "build": "pnpm run -r --sort build", 22 | "coverage": "nyc -r lcov npm test", 23 | "coverage:all": "nyc -r lcov npm run test:all", 24 | "precopy": "rimraf docs/example/*", 25 | "copy": "pnpm -r copy", 26 | "version": "monopub -P version" 27 | }, 28 | "dependencies": { 29 | "nofilter": "^3.0.2" 30 | }, 31 | "devDependencies": { 32 | "@cto.af/eslint-config": "^6.0.0", 33 | "@cto.af/monopub": "0.1.3", 34 | "@parcel/core": "2.14.4", 35 | "@parcel/optimizer-data-url": "2.14.4", 36 | "@parcel/transformer-inline-string": "2.14.4", 37 | "ava": "6.2.0", 38 | "bignumber.js": "^9.3.0", 39 | "buffer": "^6.0.3", 40 | "copyfiles": "2.4.1", 41 | "docdash": "2.0.2", 42 | "eslint": "^9.25.1", 43 | "eslint-plugin-ava": "^15.0.1", 44 | "eslint-plugin-jsdoc": "^50.6.11", 45 | "eslint-plugin-markdown": "^5.1.0", 46 | "eslint-plugin-node": "^11.1.0", 47 | "events": "^3.3.0", 48 | "jsdoc": "^4.0.4", 49 | "minami": "*", 50 | "nve": "^18.0.2", 51 | "nyc": "^17.1.0", 52 | "process": "^0.11.10", 53 | "rimraf": "5.0.10", 54 | "stream-browserify": "^3.0.0", 55 | "svgo": "3.3.2", 56 | "typescript": "^5.8.3" 57 | }, 58 | "packageManager": "pnpm@10.10.0", 59 | "engines": { 60 | "node": ">=20" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/browserify-demo/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /packages/browserify-demo/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/browserify-demo/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/browserify-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browserify-demo", 3 | "version": "10.0.3", 4 | "description": "", 5 | "private": true, 6 | "scripts": { 7 | "prebuild": "rimraf dist && mkdir dist", 8 | "build": "browserify --standalone cbor ../cbor/lib/cbor.js -t [ babelify ] | terser --compress -o dist/bundle-bf.js && browserify src/index.js -t [ babelify ] -o dist/index-bf.js && copyfiles -u1 src/*.css src/*.html dist", 9 | "precopy": "npm run build", 10 | "copy": "copyfiles -u1 dist/* ../../docs/example" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 15 | "directory": "packages/browserify-demo" 16 | }, 17 | "keywords": [], 18 | "author": "Joe Hildebrand ", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "@babel/core": "^7.26.10", 22 | "babelify": "^10.0.0", 23 | "browserify": "^17.0.1", 24 | "cbor-bigdecimal": "^10.0.3", 25 | "copyfiles": "^2.4.1", 26 | "node-inspect-extracted": "*", 27 | "rimraf": "5.0.10", 28 | "terser": "^5.39.0" 29 | }, 30 | "engines": { 31 | "node": ">=20" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/browserify-demo/src/index-bf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CBOR/web (browserify) 6 | 7 | 8 | 11 | 12 | 13 |

CBOR converter

14 |
15 |
16 |

Input

17 |
18 | 23 | →→→ to →→→ 24 |
25 | 28 |
29 |
30 |

Output

31 |
32 | 40 | 41 |
42 | 43 |
44 |
45 |
46 | Powered by node-cbor. 47 | Source 48 |
49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /packages/browserify-demo/src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 'use strict'; 3 | 4 | const {inspect} = require('node-inspect-extracted'); 5 | const {Buffer} = require('buffer'); 6 | const bdec = require('cbor-bigdecimal'); 7 | 8 | bdec(cbor); 9 | 10 | const ofmt = document.getElementById('output-fmt'); 11 | const otxt = document.getElementById('output-text'); 12 | const itxt = document.getElementById('input-text'); 13 | const ifmt = document.getElementById('input-fmt'); 14 | const copy = document.getElementById('copy'); 15 | 16 | function error(e) { 17 | copy.disabled = true; 18 | otxt.value = e.toString(); 19 | } 20 | 21 | // Convert any input to a buffer 22 | function input() { 23 | const inp = ifmt.selectedOptions[0].label; 24 | const txt = itxt.value; 25 | switch (inp) { 26 | case 'JSON': 27 | return cbor.encodeOne(JSON.parse(txt), {canonical: true}); 28 | case 'hex': 29 | case 'base64': 30 | return Buffer.from(txt, inp); 31 | default: 32 | throw new Error(`Unknown input: "${inp}"`); 33 | } 34 | } 35 | 36 | // Convert a buffer to the desired output format 37 | function output(buf, _typ) { 38 | const outp = ofmt.selectedOptions[0].label; 39 | switch (outp) { 40 | case 'hex': 41 | case 'base64': 42 | copy.disabled = false; 43 | otxt.value = buf.toString(outp); 44 | break; 45 | case 'commented': 46 | copy.disabled = true; 47 | cbor.comment(buf).then(txt => { 48 | otxt.value = txt; 49 | }, error); 50 | break; 51 | case 'diagnostic': 52 | copy.disabled = true; 53 | cbor.diagnose(buf).then(txt => { 54 | otxt.value = txt; 55 | }, error); 56 | break; 57 | case 'js': 58 | copy.disabled = true; 59 | cbor.decodeFirst(buf).then(o => { 60 | otxt.value = inspect(o, { 61 | depth: Infinity, 62 | compact: 1, 63 | maxArrayLength: Infinity, 64 | breakLength: otxt.cols - 1, 65 | }); 66 | }, error); 67 | break; 68 | case 'JSON': 69 | copy.disabled = false; 70 | cbor.decodeFirst(buf, {bigint: true, preferWeb: true}).then(o => { 71 | otxt.value = JSON.stringify(o, null, 2); 72 | }, error); 73 | break; 74 | default: 75 | throw new Error(`Unknown output: "${outp}"`); 76 | } 77 | } 78 | 79 | function convert() { 80 | try { 81 | output(input()); 82 | } catch (e) { 83 | error(e); 84 | } 85 | } 86 | 87 | ofmt.oninput = convert; 88 | ifmt.oninput = convert; 89 | copy.onclick = () => { 90 | // Copy output to input, and guess the new input format 91 | itxt.value = otxt.value; 92 | const sel = ofmt.selectedOptions[0].label; 93 | for (const o of ifmt.options) { 94 | if (o.label === sel) { 95 | ifmt.selectedIndex = o.index; 96 | break; 97 | } 98 | } 99 | }; 100 | 101 | // Debounce 102 | let timeout = null; 103 | itxt.oninput = () => { 104 | clearTimeout(timeout); 105 | timeout = setTimeout(() => { 106 | timeout = null; 107 | convert(); 108 | }, 300); 109 | }; 110 | 111 | // Make sure that initial output is set 112 | convert(); 113 | -------------------------------------------------------------------------------- /packages/browserify-demo/src/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | background-color:cornsilk; 4 | } 5 | 6 | .container { 7 | display: flex; 8 | flex-flow: row wrap; 9 | align-items: flex-start; 10 | } 11 | 12 | .cmd { 13 | margin: 0 10px 5px 10px; 14 | } 15 | 16 | #to { 17 | float: right; 18 | } 19 | 20 | h3 { 21 | margin: 0 10px 5px 10px; 22 | } 23 | 24 | textarea { 25 | margin: 0 10px 0 10px; 26 | } 27 | 28 | .power { 29 | margin: 10px; 30 | } 31 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/.npmignore: -------------------------------------------------------------------------------- 1 | .nyc_output/ 2 | coverage/ 3 | test/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/README.md: -------------------------------------------------------------------------------- 1 | # cbor-bignumber 2 | 3 | This package adds support for BigDecimal and BigFloats to the [cbor](../cbor) 4 | package, relying on [bignumber.js](https://github.com/MikeMcl/bignumber.js). 5 | 6 | ## MOVE TO CBOR2 7 | 8 | **NOTE** 9 | 10 | All new users and most existing users of this library should move to the 11 | [cbor2](https://github.com/hildjj/cbor2) library. It is where most 12 | maintenance and support and all new features are happening. cbor2 has 13 | support for JavaScript bigints enabled by default. 14 | 15 | *Only* catastrophic bugs will be fixed in this library going forward. 16 | 17 | ## Installation 18 | 19 | ```sh 20 | npm install cbor cbor-bignumber 21 | ``` 22 | 23 | ## Usage 24 | 25 | Before trying to encode or decode: 26 | 27 | ```js 28 | const cbor = require('cbor'); 29 | const bdec = require('cbor-bigdecimal'); 30 | bdec(cbor); 31 | ``` 32 | 33 | If you want to remove the added encoders and decoders: 34 | 35 | ```js 36 | cbor.reset(); 37 | ``` 38 | 39 | If you need to access the same BigNumber class that `cbor-bigdecimal` is (e.g. 40 | because the class has been mangled by your compressor), it is available as 41 | `bdec.BigNumber`. 42 | 43 | ## Supported Types 44 | 45 | Decoding supports the following CBOR tag numbers: 46 | 47 | | Tag | Generated Type | 48 | |-----|---------------------| 49 | | 4 | bignumber | 50 | | 5 | bignumber | 51 | 52 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/bigdecimal.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {BigNumber} = require('bignumber.js'); 4 | let cbor = null; 5 | 6 | const MAXINT = new BigNumber('0x20000000000000'); 7 | const TWO = new BigNumber(2); 8 | 9 | function pushBigNumber(gen, obj) { 10 | if (obj.isNaN()) { 11 | return gen._pushNaN(); 12 | } 13 | if (!obj.isFinite()) { 14 | return gen._pushInfinity(obj.isNegative() ? -Infinity : Infinity); 15 | } 16 | if (obj.isInteger()) { 17 | return gen._pushJSBigint(BigInt(obj.toFixed())); 18 | } 19 | 20 | // Section 3.4.4, decimal fraction 21 | if (!(gen._pushTag(4) && 22 | gen._pushInt(2, 4))) { // Array 23 | return false; 24 | } 25 | 26 | const dec = obj.decimalPlaces(); 27 | const slide = obj.shiftedBy(dec); 28 | if (!gen._pushIntNum(-dec)) { 29 | return false; 30 | } 31 | if (slide.abs().isLessThan(MAXINT)) { 32 | return gen._pushIntNum(slide.toNumber()); 33 | } 34 | return gen._pushJSBigint(BigInt(slide.toFixed())); 35 | } 36 | 37 | // Decimal fraction; see Section 3.4.4 38 | function tag_4(v) { 39 | return new BigNumber(v[1]).shiftedBy(v[0]); 40 | } 41 | 42 | // Bigfloat; see Section 3.4.4 43 | function tag_5(v) { 44 | return TWO.pow(v[0]).times(v[1]); 45 | } 46 | 47 | function addBigDecimal(inCBOR) { 48 | cbor = inCBOR; 49 | cbor.Encoder.SEMANTIC_TYPES[BigNumber.name] = pushBigNumber; 50 | cbor.Tagged.TAGS[4] = tag_4; 51 | cbor.Tagged.TAGS[5] = tag_5; 52 | return cbor; 53 | } 54 | 55 | addBigDecimal.BigNumber = BigNumber; 56 | module.exports = addBigDecimal; 57 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/dist/cbor-bigdecimal.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("bignumber.js")):"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.cborBigDecimal=t(require("bignumber.js")):e.cborBigDecimal=t(e.BigNumber)}(this,(e=>(()=>{"use strict";var t={68:(e,t,i)=>{const{BigNumber:n}=i(905);let r=null;const u=new n("0x20000000000000"),s=new n(2);function o(e,t){if(t.isNaN())return e._pushNaN();if(!t.isFinite())return e._pushInfinity(t.isNegative()?-1/0:1/0);if(t.isInteger())return e._pushJSBigint(BigInt(t.toFixed()));if(!e._pushTag(4)||!e._pushInt(2,4))return!1;const i=t.decimalPlaces(),n=t.shiftedBy(i);return!!e._pushIntNum(-i)&&(n.abs().isLessThan(u)?e._pushIntNum(n.toNumber()):e._pushJSBigint(BigInt(n.toFixed())))}function p(e){return new n(e[1]).shiftedBy(e[0])}function f(e){return s.pow(e[0]).times(e[1])}function c(e){return r=e,r.Encoder.SEMANTIC_TYPES[n.name]=o,r.Tagged.TAGS[4]=p,r.Tagged.TAGS[5]=f,r}c.BigNumber=n,e.exports=c},905:t=>{t.exports=e}},i={};return function e(n){var r=i[n];if(void 0!==r)return r.exports;var u=i[n]={exports:{}};return t[n](u,u.exports,e),u.exports}(68)})())); -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cbor-bigdecimal", 3 | "version": "10.0.3", 4 | "description": "Plugin for node-cbor to add BigDecimal and BigFloat support. Requires bignumber.js", 5 | "browser": "dist/cbor-bigdecimal.js", 6 | "main": "./bigdecimal.js", 7 | "scripts": { 8 | "build": "webpack", 9 | "clean": "rimraf dist", 10 | "coverage": "nyc -r lcov npm test", 11 | "test": "ava test/*.ava.js", 12 | "dev": "light-server -q -s. -w 'lib/*.js,test/*.js # npm run coverage' -o /coverage/lcov-report/index.html" 13 | }, 14 | "keywords": [ 15 | "CBOR", 16 | "BigNumber", 17 | "BigDecimal", 18 | "BigFloat", 19 | "tag" 20 | ], 21 | "author": "Joe Hildebrand ", 22 | "license": "MIT", 23 | "repository": { 24 | "type": "git", 25 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 26 | "directory": "packages/cbor-bigdecimal" 27 | }, 28 | "peerDependencies": { 29 | "bignumber.js": "^9.1.0" 30 | }, 31 | "devDependencies": { 32 | "bignumber.js": "^9.3.0", 33 | "webpack": "^5.99.7", 34 | "webpack-cli": "^5.1.4" 35 | }, 36 | "engines": { 37 | "node": ">=20" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/test/bigdecimal.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const cbor = require(process.env.CBOR_PACKAGE || '../../cbor'); 4 | const bigdec = require('..'); 5 | const cases = require('../../cbor/test/cases'); 6 | const test = require('ava'); 7 | const {BigNumber} = bigdec; 8 | 9 | function enc(t, n, expected) { 10 | t.is(cbor.encodeOne(new BigNumber(n)).toString('hex'), expected); 11 | } 12 | 13 | test.before(() => { 14 | bigdec(cbor); 15 | }); 16 | 17 | test.after(() => { 18 | cbor.reset(); 19 | }); 20 | 21 | test('encode', t => { 22 | enc(t, NaN, 'f97e00'); 23 | enc(t, Infinity, 'f97c00'); 24 | enc(t, -Infinity, 'f9fc00'); 25 | enc(t, 0, 'c24100'); 26 | enc(t, 1, 'c24101'); 27 | enc(t, -1, 'c34100'); 28 | enc(t, 29 | new BigNumber(Number.MAX_SAFE_INTEGER).pow(2), 30 | 'c24e03ffffffffffffc0000000000001'); 31 | enc(t, 10.1, 'c482201865'); 32 | enc(t, 100.1, 'c482201903e9'); 33 | enc(t, 0.1, 'c4822001'); 34 | enc(t, -0.1, 'c4822020'); 35 | enc(t, 36 | new BigNumber(Math.PI).pow(3), 37 | 'c482382cc254056e5e99b1be81b6eefa3964490ac18c69399361'); 38 | enc(t, 39 | new BigNumber('18446744073709551615.1'), 40 | 'c48220c24909fffffffffffffff7'); 41 | }); 42 | 43 | test('failures', t => { 44 | cases.EncodeFailer.tryAll(t, new BigNumber(-0.1)); 45 | }); 46 | 47 | test('decode', async t => { 48 | t.deepEqual(await cbor.decodeFirst('c4822001'), new BigNumber(0.1)); 49 | t.deepEqual(await cbor.decodeFirst('c5822003'), new BigNumber(1.5)); 50 | }); 51 | -------------------------------------------------------------------------------- /packages/cbor-bigdecimal/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const path = require('node:path'); 3 | 4 | module.exports = { 5 | entry: './bigdecimal.js', 6 | mode: 'production', 7 | output: { 8 | path: path.resolve(__dirname, 'dist'), 9 | filename: 'cbor-bigdecimal.js', 10 | library: 'cborBigDecimal', 11 | libraryTarget: 'umd', 12 | globalObject: 'this', 13 | }, 14 | externals: { 15 | 'bignumber.js': { 16 | root: 'BigNumber', 17 | commonjs: 'bignumber.js', 18 | commonjs2: 'bignumber.js', 19 | }, 20 | }, 21 | target: 'web', 22 | }; 23 | -------------------------------------------------------------------------------- /packages/cbor-cli/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | .DS_Store 4 | TAGS 5 | .nyc_output/ 6 | *.js.map 7 | jsconfig.json 8 | typings/ 9 | typings.json 10 | .vscode/ 11 | tools/ 12 | docs/ 13 | test/ 14 | man_src/ 15 | Dockerfile 16 | .editorconfig 17 | .eslintrc.js 18 | .gitmodules 19 | .jsdoc.conf 20 | .travis.yml 21 | .waiting.html 22 | test-vectors/ 23 | .dockerignore 24 | npm-debug.log 25 | cli/ 26 | .ncurc.json 27 | -------------------------------------------------------------------------------- /packages/cbor-cli/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /packages/cbor-cli/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/cbor-cli/README.md: -------------------------------------------------------------------------------- 1 | # cbor-cli 2 | 3 | A command-line interface for encoding and parse data in the Concise Binary 4 | Object Representation (CBOR) data format 5 | ([RFC8949](https://www.rfc-editor.org/rfc/rfc8949.html)). 6 | 7 | ## MOVE TO CBOR2 8 | 9 | **NOTE** 10 | 11 | All new users and most existing users of this library should move to the 12 | [cbor2](https://github.com/hildjj/cbor2) library. It is where most 13 | maintenance and support and all new features are happening. The easiest way 14 | to get this functionality on cbor2 is to use the web 15 | [playground](https://hildjj.github.io/cbor2/playground/). 16 | 17 | *Only* catastrophic bugs will be fixed in this package going forward. 18 | 19 | ## Supported Node.js versions 20 | 21 | This project now only supports versions of Node that the Node team is 22 | [currently supporting](https://github.com/nodejs/Release#release-schedule). 23 | Ava's [support 24 | statement](https://github.com/avajs/ava/blob/main/docs/support-statement.md) 25 | is what we will be using as well. Currently, that means Node `10`+ is 26 | required. If you need to support an older version of Node (back to version 27 | 6), use cbor version 5.2.x, which will get nothing but security updates from 28 | here on out. 29 | 30 | ## Installation: 31 | 32 | ```bash 33 | $ npm install -g cbor-cli 34 | ``` 35 | 36 | ## Documentation: 37 | 38 | There is a full [API](../cbor) that this library depends on. 39 | 40 | For all of these tools, if a hex string is not specified, or if the file name provided is `-`, they will read from stdin and write to stdout. 41 | 42 | From the command line: 43 | 44 | ### `cbor` 45 | 46 | ``` 47 | $ cbor.js -h 48 | Usage: cbor [options] 49 | 50 | Options: 51 | -V, --version output the version number 52 | -c, --color Force color output even if stdout is not a TTY 53 | -t, --type Output type (one of: javascript, diagnose, comment) (default: "javascript") 54 | -h, --help display help for command 55 | ``` 56 | 57 | Starts a Read, Edit, Print Loop (REPL), with the cbor package and all of its 58 | symbols already available. Almost everything you do in the REPL will also 59 | output the CBOR encoding of the result in hex, after the normal result. 60 | 61 | ### `cbor2comment` 62 | 63 | ``` 64 | $ cbor2comment -h 65 | Usage: cbor2comment [options] 66 | 67 | Options: 68 | -V, --version output the version number 69 | -x, --hex Hex string input 70 | -t, --tabsize [spaces] Indent amount 71 | -h, --help display help for command 72 | ``` 73 | 74 | Convert the given file or hex string into the CBOR comment format. This is 75 | useful for understanding what each byte means. 76 | 77 | ### `cbor2diag` 78 | 79 | ``` 80 | $ cbor2diag -h 81 | Usage: cbor2diag [options] 82 | 83 | Options: 84 | -V, --version output the version number 85 | -x, --hex Hex string input 86 | -h, --help display help for command 87 | ``` 88 | 89 | Convert the given file or hex string into the CBOR [diagnostic 90 | format](https://www.rfc-editor.org/rfc/rfc8949.html#name-diagnostic-notation). 91 | This is useful for getting a slightly more nuanced view into what CBOR came in 92 | on the wire than you would if you turned it all the way into javascript. 93 | 94 | ### `cbor2js` 95 | 96 | ``` 97 | $ cbor2js -h 98 | Usage: cbor2js [options] 99 | 100 | Options: 101 | -V, --version output the version number 102 | -x, --hex Hex string input 103 | -H, --hidden Include non-enumerable symbols and properties 104 | -h, --help display help for command 105 | ``` 106 | 107 | Convert the given file or hex string into javascript objects, then use 108 | [`util.inspect`](https://nodejs.org/api/util.html#util_util_inspect_object_options) 109 | to format them for consumption. This usually gives a much better idea of type 110 | information, and is easier to read than JSON. 111 | 112 | ### `cbor2json` 113 | 114 | ``` 115 | $ cbor2json -h 116 | Usage: cbor2json [options] 117 | 118 | Options: 119 | -V, --version output the version number 120 | -x, --hex Hex string input 121 | -h, --help display help for command 122 | ``` 123 | 124 | Convert the given file or hex string into [JSON](https://tools.ietf.org/html/rfc8259). This loses type information, but does the best it can if you want interoperability with existing JSON tooling. For example, JSON can't express Dates, so they are output as [ISO 8601](https://xkcd.com/1179/) strings. 125 | 126 | ### `js2cbor` 127 | 128 | ``` 129 | $ js2cbor -h 130 | Usage: js2cbor [options] 131 | 132 | Options: 133 | -V, --version output the version number 134 | -x, --hex Hex string output 135 | -c, --canonical Canonical output 136 | -h, --help display help for command 137 | ``` 138 | 139 | Read the input files or stdin as if it were a commonjs package 140 | 141 | ### `json2cbor` 142 | 143 | ``` 144 | $ json2cbor -h 145 | Usage: json2cbor [options] 146 | 147 | Options: 148 | -V, --version output the version number 149 | -x, --hex Hex string output 150 | -c, --canonical Canonical output 151 | -h, --help display help for command 152 | ``` 153 | 154 | Converts the given JSON or [JSON Text 155 | Sequence](https://tools.ietf.org/html/rfc7464) file into binary CBOR. If `-x` 156 | is given, instead outputs a hex-encoded version of the CBOR. 157 | -------------------------------------------------------------------------------- /packages/cbor-cli/bin/cbor2comment.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | const cbor = require('cbor'); 5 | const utils = require('../lib/utils'); 6 | const pkg = require('../package.json'); 7 | const {program} = require('commander'); 8 | 9 | const opts = program 10 | .version(pkg.version) 11 | .argument('[file...]', 'Files to read, "-" for stdin') 12 | .usage('[options] [file ...]') 13 | .option('-x, --hex ', 'Hex string input') 14 | .option('-t, --tabsize [spaces]', 'Indent amount') 15 | .parse(process.argv) 16 | .opts(); 17 | 18 | const numTabs = (opts.tabsize | 0) || 10; 19 | const argv = program.args; 20 | if (opts.hex) { 21 | argv.push(new utils.DeHexStream(opts.hex)); 22 | } 23 | 24 | if (argv.length === 0) { 25 | argv.push('-'); 26 | } 27 | 28 | utils.streamFiles(argv, () => { 29 | const c = new cbor.Commented({ 30 | // Backwards-compat 31 | max_depth: numTabs, 32 | }); 33 | c.pipe(process.stdout); 34 | return c; 35 | }).catch(utils.printError); 36 | -------------------------------------------------------------------------------- /packages/cbor-cli/bin/cbor2diag.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | const cbor = require('cbor'); 5 | const utils = require('../lib/utils'); 6 | const pkg = require('../package.json'); 7 | const {program} = require('commander'); 8 | 9 | program 10 | .version(pkg.version) 11 | .argument('[file...]', 'Files to read, "-" for stdin') 12 | .usage('[options] [file ...]') 13 | .option('-x, --hex ', 'Hex string input') 14 | .parse(process.argv); 15 | 16 | const opts = program.opts(); 17 | const argv = program.args; 18 | if (opts.hex) { 19 | argv.push(new utils.DeHexStream(opts.hex)); 20 | } 21 | 22 | if (argv.length === 0) { 23 | argv.push('-'); 24 | } 25 | 26 | utils.streamFiles(argv, () => { 27 | const d = new cbor.Diagnose(); 28 | d.pipe(process.stdout); 29 | return d; 30 | }).catch(utils.printError); 31 | -------------------------------------------------------------------------------- /packages/cbor-cli/bin/cbor2js.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | const cbor = require('cbor'); 5 | const utils = require('../lib/utils'); 6 | const pkg = require('../package.json'); 7 | const util = require('node:util'); 8 | const bdec = require('cbor-bigdecimal'); 9 | bdec(cbor); 10 | 11 | const {program} = require('commander'); 12 | 13 | program 14 | .version(pkg.version) 15 | .argument('[file...]', 'Files to read, "-" for stdin') 16 | .usage('[options] [file ...]') 17 | .option('-x, --hex ', 'Hex string input') 18 | .option('-e, --exports', 'add module.exports= to the beginning') 19 | .option('-H, --hidden', 'Include non-enumerable symbols and properties') 20 | .parse(process.argv); 21 | 22 | const opts = program.opts(); 23 | const argv = program.args; 24 | if (opts.hex) { 25 | argv.push(new utils.DeHexStream(opts.hex)); 26 | } 27 | 28 | if (argv.length === 0) { 29 | argv.push('-'); 30 | } 31 | 32 | utils.streamFiles(argv, () => { 33 | const d = new cbor.Decoder(); 34 | d.on('data', v => { 35 | if (opts.exports) { 36 | process.stdout.write('module.exports = '); 37 | } 38 | console.log(util.inspect(v, { 39 | compact: false, 40 | colors: process.stdout.isTTY, 41 | showHidden: opts.hidden, 42 | showProxy: opts.hidden, 43 | depth: Infinity, 44 | sorted: true, 45 | breakLength: process.env.COLS || 80, 46 | })); 47 | }); 48 | return d; 49 | }).catch(utils.printError); 50 | -------------------------------------------------------------------------------- /packages/cbor-cli/bin/cbor2json.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | const cbor = require('cbor'); 5 | const utils = require('../lib/utils'); 6 | const pkg = require('../package.json'); 7 | const bdec = require('cbor-bigdecimal'); 8 | bdec(cbor); 9 | 10 | const {program} = require('commander'); 11 | 12 | program 13 | .version(pkg.version) 14 | .argument('[file...]', 'Files to read, "-" for stdin') 15 | .usage('[options] [file ...]') 16 | .option('-x, --hex ', 'Hex string input') 17 | .parse(process.argv); 18 | 19 | const opts = program.opts(); 20 | const argv = program.args; 21 | if (opts.hex) { 22 | argv.push(new utils.DeHexStream(opts.hex)); 23 | } 24 | 25 | if (argv.length === 0) { 26 | argv.push('-'); 27 | } 28 | 29 | utils.streamFiles(argv, () => { 30 | const d = new cbor.Decoder(); 31 | d.on('data', v => { 32 | console.log(JSON.stringify(v)); 33 | }); 34 | return d; 35 | }).catch(utils.printError); 36 | -------------------------------------------------------------------------------- /packages/cbor-cli/bin/js2cbor.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | const cbor = require('cbor'); 5 | const utils = require('../lib/utils'); 6 | const pkg = require('../package.json'); 7 | const {program} = require('commander'); 8 | const path = require('node:path'); 9 | const stream = require('node:stream'); 10 | const Module = require('node:module'); 11 | const {Buffer} = require('node:buffer'); // Not the mangled version 12 | const bdec = require('cbor-bigdecimal'); 13 | bdec(cbor); 14 | 15 | program 16 | .version(pkg.version) 17 | .argument('[file...]', 'Files to read, "-" for stdin') 18 | .usage('[options] [file...]') 19 | .option('-x, --hex', 'Hex string output') 20 | .option('-c, --canonical', 'Canonical output') 21 | .parse(process.argv); 22 | 23 | const opts = program.opts(); 24 | const argv = program.args; 25 | if (argv.length === 0) { 26 | argv.push('-'); 27 | } 28 | 29 | // Overly-fancy `require`, so we can take modules on stdin. 30 | // reads stream until it's done, then eval's the code and returns 31 | // module.exports. 32 | class ModuleStream extends stream.Transform { 33 | constructor(filename) { 34 | super({ 35 | readableObjectMode: true, 36 | }); 37 | this.bufs = []; 38 | this.filename = filename; 39 | } 40 | 41 | _transform(chunk, _encoding, callback) { 42 | this.bufs.push(chunk); 43 | callback(); 44 | } 45 | 46 | _flush() { 47 | const m = new Module(this.filename, module); 48 | m.filename = this.filename; 49 | m.paths = Module._nodeModulePaths(path.dirname(this.filename)); 50 | m._compile(Buffer.concat(this.bufs).toString('utf8'), this.filename); 51 | this.push(m.exports); 52 | } 53 | } 54 | 55 | utils.streamFiles(argv, f => { 56 | const m = new ModuleStream(f); 57 | const d = new cbor.Encoder({canonical: opts.canonical}); 58 | m.on('data', mod => { 59 | if (typeof mod === 'function') { 60 | mod = mod(f); 61 | } 62 | d.end(mod); 63 | }); 64 | let o = d; 65 | if (opts.hex) { 66 | o = new utils.HexStream(); 67 | d.pipe(o); 68 | o.on('end', () => process.stdout.write('\n')); 69 | } 70 | o.pipe(process.stdout); 71 | return m; 72 | }).catch(utils.printError); 73 | -------------------------------------------------------------------------------- /packages/cbor-cli/bin/json2cbor.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | const cbor = require('cbor'); 5 | const utils = require('../lib/utils'); 6 | const pkg = require('../package.json'); 7 | const {program} = require('commander'); 8 | 9 | program 10 | .version(pkg.version) 11 | .argument('[file...]', 'Files to read, "-" for stdin') 12 | .usage('[options] [file ...]') 13 | .option('-x, --hex', 'Hex string output') 14 | .option('-c, --canonical', 'Canonical output') 15 | .parse(process.argv); 16 | 17 | const opts = program.opts(); 18 | const argv = program.args; 19 | if (argv.length === 0) { 20 | argv.push('-'); 21 | } 22 | 23 | utils.streamFiles(argv, () => { 24 | const Parser = require('json-text-sequence').parser; 25 | const p = new Parser(); 26 | const d = new cbor.Encoder({canonical: opts.canonical}); 27 | p.pipe(d); 28 | p.on('truncated', b => { 29 | try { 30 | d.write(JSON.parse(b)); 31 | } catch (e) { 32 | e.message += ` for input ${b.inspect()}`; 33 | throw e; 34 | } 35 | }); 36 | let o = d; 37 | if (opts.hex) { 38 | o = new utils.HexStream(); 39 | d.pipe(o); 40 | o.on('end', () => process.stdout.write('\n')); 41 | } 42 | o.pipe(process.stdout); 43 | return p; 44 | }).catch(utils.printError); 45 | -------------------------------------------------------------------------------- /packages/cbor-cli/lib/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('node:fs'); 4 | const stream = require('node:stream'); 5 | const {Buffer} = require('node:buffer'); // Not the mangled version 6 | 7 | exports.DeHexStream = class DeHexStream extends stream.Readable { 8 | constructor(hex) { 9 | super(); 10 | hex = hex.replace(/^0x/, ''); 11 | if (hex) { 12 | this.push(Buffer.from(hex, 'hex')); 13 | } 14 | this.push(null); 15 | } 16 | }; 17 | 18 | exports.HexStream = class HexStream extends stream.Transform { 19 | constructor(options) { 20 | super(options); 21 | } 22 | 23 | _transform(fresh, _encoding, cb) { 24 | this.push(fresh.toString('hex')); 25 | return cb(); 26 | } 27 | }; 28 | 29 | exports.printError = function printError(er) { 30 | if (er != null) { 31 | console.error(er); 32 | } 33 | }; 34 | 35 | exports.streamFiles = async function streamFiles(files, streamFunc) { 36 | for (const f of files) { 37 | await new Promise((resolve, reject) => { 38 | const sf = streamFunc(f); 39 | sf.on('end', resolve); 40 | sf.on('error', reject); 41 | 42 | let s = (f === '-') ? process.stdin : f; 43 | if (!(s instanceof stream.Stream)) { 44 | s = fs.createReadStream(s); 45 | } 46 | s.on('error', reject); 47 | s.pipe(sf); 48 | }); 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /packages/cbor-cli/man/cbor.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hildjj/node-cbor/8eb2548a01337295bff569a1ddc37936339a9aa1/packages/cbor-cli/man/cbor.1.gz -------------------------------------------------------------------------------- /packages/cbor-cli/man/cbor2comment.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hildjj/node-cbor/8eb2548a01337295bff569a1ddc37936339a9aa1/packages/cbor-cli/man/cbor2comment.1.gz -------------------------------------------------------------------------------- /packages/cbor-cli/man/cbor2diag.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hildjj/node-cbor/8eb2548a01337295bff569a1ddc37936339a9aa1/packages/cbor-cli/man/cbor2diag.1.gz -------------------------------------------------------------------------------- /packages/cbor-cli/man/cbor2json.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hildjj/node-cbor/8eb2548a01337295bff569a1ddc37936339a9aa1/packages/cbor-cli/man/cbor2json.1.gz -------------------------------------------------------------------------------- /packages/cbor-cli/man/json2cbor.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hildjj/node-cbor/8eb2548a01337295bff569a1ddc37936339a9aa1/packages/cbor-cli/man/json2cbor.1.gz -------------------------------------------------------------------------------- /packages/cbor-cli/man_src/cbor.md: -------------------------------------------------------------------------------- 1 | cbor(1) -- Batteries-included CBOR Read, Edit, Print Loop 2 | ========================================================= 3 | 4 | SYNOPSIS 5 | -------- 6 | 7 | ``` 8 | # cbor 9 | cbor [VERSION] (javascript output from typing 0x00) 10 | cbor> ... 11 | ^D 12 | ``` 13 | 14 | DESCRIPTION 15 | ----------- 16 | 17 | `cbor` is a version of the Node Read, Edit, Print Loop 18 | ([REPL](https://nodejs.org/api/repl.html)). In this REPL: 19 | 20 | - most interactive results output are followed by their CBOR representation 21 | - input that starts with `0x`, `'`, `"`, or`` ` ``and is followed only by 22 | hex digits is taken as a hex-encoded binary string, decoded, and displayed 23 | in a format based on the `--type` option 24 | - the following are already imported and in-scope of the REPL: 25 | - the `cbor` package 26 | - the `nofilter` package (as `NoFilter`) 27 | - all of the properties and functions of the cbor package (e.g. `encode`, `decode`) 28 | - Promises are automatically awaited, their results printed, and their results 29 | going into the `_` variable rather than the promise itself 30 | 31 | Note that by default this command shares its history with the main Node REPL, 32 | in the file `~/.node_repl_history`. If you want to modify that, set the 33 | `NODE_REPL_HISTORY` environment variable to the name of a file, or `''` to 34 | disable history. 35 | 36 | OPTIONS 37 | ------- 38 | 39 | `-V, --version`: output the version number 40 | 41 | `-c, --color`: Force color output even if stdout is not a TTY 42 | 43 | `-t, --type `: Output type (one of: javascript, diagnose, comment) (default: "javascript") 44 | 45 | `-h, --help`: display help for 46 | 47 | ENVIRONMENT VARIABLES 48 | --------------------- 49 | 50 | All of the normal environment variables from Node apply. In particular: 51 | 52 | `NODE_REPL_HISTORY`: When a valid path is given, persistent REPL history will 53 | be saved to the specified file rather than `.node_repl_history` in the user's 54 | home directory. Setting this value to `''` (an empty string) will disable 55 | persistent REPL history. Whitespace will be trimmed from the value. On Windows 56 | platforms environment variables with empty values are invalid so set this 57 | variable to one or more spaces to disable persistent REPL history. 58 | 59 | `NODE_REPL_HISTORY_SIZE`: Controls how many lines of history will be 60 | persisted if history is available. Must be a positive number. Default: 1000. 61 | 62 | `NODE_REPL_MODE`: May be either 'sloppy' or 'strict'. Default: 'sloppy', which 63 | will allow non-strict mode code to be run. 64 | 65 | SEE ALSO 66 | -------- 67 | 68 | * [node-cbor](https://github.com/hildjj/node-cbor/) 69 | * [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html) 70 | -------------------------------------------------------------------------------- /packages/cbor-cli/man_src/cbor2comment.md: -------------------------------------------------------------------------------- 1 | cbor2comment(1) -- convert CBOR wire protocol to commented version 2 | ================================================================== 3 | 4 | SYNOPSIS 5 | -------- 6 | 7 | ``` 8 | cbor2comment test.cbor > test.txt 9 | ``` 10 | 11 | DESCRIPTION 12 | ----------- 13 | 14 | `cbor2comment` creates a commented version of an input bytestream. For 15 | example, if the input contained the two bytes (in hex) `61 61`, the output 16 | would be: 17 | 18 | 61 -- String, length: 1 19 | 61 -- "a" 20 | 0x6161 21 | 22 | OPTIONS 23 | ------- 24 | 25 | `-`: read from stdin instead of a file. This is the default. 26 | 27 | `-t NUM, --tabsize NUM`: the number of 2-space tab indents to move the '--' to the right. 28 | Eventually, this will be replaced with an algorithm that takes two passes 29 | over the input. 30 | 31 | `-x [string]`: read the input from the hex-encoded string on the command line 32 | 33 | `-V, --version`: print the node-cbor version and exit 34 | 35 | `-h, --help`: print some help text and exit 36 | 37 | TODO 38 | ---- 39 | 40 | * `cbor2comment` is not built for execution speed or reuse. 41 | * Make 2 passes over the input. 42 | * Move the summary hex output to the beginning. 43 | 44 | SEE ALSO 45 | -------- 46 | 47 | * [node-cbor](https://github.com/hildjj/node-cbor) 48 | * [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html) 49 | -------------------------------------------------------------------------------- /packages/cbor-cli/man_src/cbor2diag.md: -------------------------------------------------------------------------------- 1 | cbor2diag(1) -- convert CBOR wire protocol to diagnostic text 2 | ============================================================= 3 | 4 | SYNOPSIS 5 | -------- 6 | 7 | ``` 8 | cbor2diag test.cbor > test.txt 9 | ``` 10 | 11 | DESCRIPTION 12 | ----------- 13 | 14 | `cbor2diag` outputs the diagnostic format from RFC 8949 that corresponds to the 15 | CBOR files that were input. For example, the following input: 16 | 17 | 0xc100 18 | c1 -- Tag 1 (Date) 19 | 00 -- 0 20 | 21 | produces: 22 | 23 | 1(0) 24 | 25 | OPTIONS 26 | ------- 27 | 28 | `-`: read from stdin instead of a file. This is the default. 29 | 30 | `-x [string]`: read the input from the hex-encoded string on the command line 31 | 32 | `-V, --version`: print the node-cbor version and exit 33 | 34 | `-h, --help`: print some help text and exit 35 | 36 | SEE ALSO 37 | -------- 38 | 39 | * [node-cbor](https://github.com/hildjj/node-cbor) 40 | * [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html) 41 | -------------------------------------------------------------------------------- /packages/cbor-cli/man_src/cbor2json.md: -------------------------------------------------------------------------------- 1 | cbor2json(1) -- convert CBOR wire protocol to JSON 2 | ================================================================== 3 | 4 | SYNOPSIS 5 | -------- 6 | 7 | ``` 8 | cbor2json test.cbor > test.json 9 | ``` 10 | 11 | DESCRIPTION 12 | ----------- 13 | 14 | `cbor2json` creates a JSON file that mirrors (somewhat) the intent of the input 15 | set of CBOR files. For the subset of CBOR that directly maps to JSON, the 16 | output will seem reasonable. For CBOR inputs that do not map nicely to JSON, 17 | substitutions are made that may or may not match your expectations. For 18 | example, the input: 19 | 20 | 0xc100 21 | c1 -- Tag 1 (Date) 22 | 00 -- 0 23 | 24 | produces the following output that does not round-trip back to the same CBOR 25 | input: 26 | 27 | "1970-01-01T00:00:00.000Z" 28 | 29 | OPTIONS 30 | ------- 31 | 32 | `-`: read from stdin instead of a file. This is the default. 33 | 34 | `-x [string]`: read the input from the hex-encoded string on the command line 35 | 36 | `-V, --version`: print the node-cbor version and exit 37 | 38 | `-h, --help`: print some help text and exit 39 | 40 | SEE ALSO 41 | -------- 42 | 43 | * [node-cbor](https://github.com/hildjj/node-cbor) 44 | * [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html) 45 | -------------------------------------------------------------------------------- /packages/cbor-cli/man_src/json2cbor.md: -------------------------------------------------------------------------------- 1 | json2cbor(1) -- convert JSON formatted text to CBOR 2 | =================================================== 3 | 4 | SYNOPSIS 5 | -------- 6 | 7 | ``` 8 | json2cbor test.json > test.cbor 9 | ``` 10 | 11 | DESCRIPTION 12 | ----------- 13 | 14 | `json2cbor` output a CBOR data stream for an input set of files. The files 15 | can either consist of a single JSON item, or an 16 | [RFC 7464](https://tools.ietf.org/html/rfc7464) encoded JSON text series. 17 | In the latter case, each JSON item starts with the byte "1e" (hex), "30" (dec), 18 | otherwise known as "Record Separator" (RS), and finishes with a newline. 19 | 20 | An example sequence: 21 | 22 | ␞{"d":"2014-09-22T21:58:35.270Z","value":6}␤ 23 | ␞{"d":"2014-09-22T21:59:15.117Z","value":12}␤ 24 | 25 | You can generate a sequence like this from a newline-separated JSON file like 26 | this: 27 | 28 | sed -e s/^/\x1e/g [FILE] 29 | 30 | (note: your shell might need $'' around the sed pattern to work. I'll look 31 | for a more shell-inspecific way of encdoding this later.) 32 | 33 | The reason I'm making you go through this pain is that more of your JSON items 34 | have newlines embedded in them than you think. Ideally, you would write 35 | your files out using RFC 7464, and you'd also get some of the benefits of 36 | that format, including: 37 | 38 | * Detect a truncated file due to a process dying in the middle of writing 39 | your data. 40 | * Recovery while parsing from such a truncated file that was later appended to. 41 | * Detect when multiple processes are writing to the same file in an 42 | uncoordinated way. 43 | * Maintain newlines in your JSON. They'll sneak in there anyway. 44 | 45 | OPTIONS 46 | ------- 47 | 48 | `-`: read from stdin instead of a file. This is the default. 49 | 50 | `-c, --canonical`: Canonical output 51 | 52 | `-x, --hex`: output a hex-encoded version of the CBOR data, instead of the native 53 | CBOR data 54 | 55 | `-V, --version`: print the node-cbor version and exit 56 | 57 | `-h, --help`: print some help text and exit 58 | 59 | 60 | SEE ALSO 61 | -------- 62 | 63 | * [node-cbor](https://github.com/hildjj/node-cbor) 64 | * [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html) 65 | -------------------------------------------------------------------------------- /packages/cbor-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cbor-cli", 3 | "version": "10.0.3", 4 | "description": "Command line tools to encode and parse data in the Concise Binary Object Representation (CBOR) data format (RFC8949).", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 8 | "directory": "pacakges/cbor-cli" 9 | }, 10 | "homepage": "https://github.com/hildjj/node-cbor/tree/main/packages/cbor-cli", 11 | "bin": { 12 | "cbor": "bin/cbor.js", 13 | "cbor2comment": "bin/cbor2comment.js", 14 | "cbor2diag": "bin/cbor2diag.js", 15 | "cbor2js": "bin/cbor2js.js", 16 | "cbor2json": "bin/cbor2json.js", 17 | "js2cbor": "bin/js2cbor.js", 18 | "json2cbor": "bin/json2cbor.js" 19 | }, 20 | "directories": { 21 | "man": "man" 22 | }, 23 | "scripts": { 24 | "clean": "rimraf coverage .nyc_output/ man/*", 25 | "lint": "eslint lib/*.js bin/* test/*.js", 26 | "test": "ava", 27 | "man": "mkdir -p man; for f in man_src/*.md; do b=`basename $f`; marked-man $f -o man/${b%.md}.1; gzip -9f man/${b%.md}.1; done", 28 | "release": "npm version patch && git push --follow-tags && npm publish", 29 | "typecheck": "tsc --allowJs --checkJs --noEmit --target ES6 --moduleResolution node lib/*.js", 30 | "coverage": "nyc -r html ava", 31 | "dev": "light-server -q -s. -w 'lib/*.js,test/*.js,bin/*.js # npm run coverage' -o /coverage/index.html" 32 | }, 33 | "keywords": [ 34 | "coap", 35 | "cbor", 36 | "json", 37 | "cli" 38 | ], 39 | "author": { 40 | "name": "Joe Hildebrand", 41 | "email": "joe-github@cursive.net" 42 | }, 43 | "devDependencies": { 44 | "marked": "^15.0.11", 45 | "marked-man": "^2.1.0", 46 | "mock-stdio": "^1.0.3", 47 | "nofilter": "^3.0.2", 48 | "p-event": "^4.2.0", 49 | "rimraf": "5.0.10" 50 | }, 51 | "license": "MIT", 52 | "readmeFilename": "README.md", 53 | "dependencies": { 54 | "bignumber.js": "^9.3.0", 55 | "cbor": "^10.0.3", 56 | "cbor-bigdecimal": "^10.0.3", 57 | "commander": "^13.1.0", 58 | "json-text-sequence": "1.0.1" 59 | }, 60 | "engines": { 61 | "node": ">=20" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/cbor-cli/test/fixtures/function.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('node:path'); 4 | const {Buffer} = require('node:buffer'); 5 | 6 | module.exports = f => ({ 7 | foo: new Date(1612908664662), 8 | bar: Buffer.from('01612908664662'), 9 | file: path.resolve(process.cwd(), f) 10 | .split(path.sep) 11 | .slice(-2), 12 | }); 13 | -------------------------------------------------------------------------------- /packages/cbor-cli/test/fixtures/object.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {Buffer} = require('node:buffer'); 4 | module.exports = { 5 | foo: new Date(1612908664662), 6 | bar: Buffer.from('01612908664662'), 7 | }; 8 | -------------------------------------------------------------------------------- /packages/cbor-cli/test/utils.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const NoFilter = require('nofilter'); 5 | const pEvent = require('p-event'); 6 | const mockIo = require('mock-stdio'); 7 | const utils = require('../lib/utils'); 8 | const {Buffer} = require('node:buffer'); // Not the mangled version 9 | 10 | const BAD_FILE = '/tmp/hopefully-does-not-exist'; 11 | 12 | test('DeHexStream', t => { 13 | [ 14 | ['6161', 'aa'], 15 | ['0x00', '\x00'], 16 | ].forEach(hd => { 17 | const d = new utils.DeHexStream(hd[0]); 18 | t.deepEqual(d.read().toString(), hd[1]); 19 | }); 20 | [ 21 | ['', null], 22 | ['0x', null], 23 | ].forEach(hd => { 24 | const d = new utils.DeHexStream(hd[0]); 25 | t.deepEqual(d.read(), hd[1]); 26 | }); 27 | }); 28 | 29 | test('HexStream', async t => { 30 | const h = new utils.HexStream(); 31 | const bs = new NoFilter(); 32 | h.pipe(bs); 33 | h.end(Buffer.from([0x61])); 34 | await pEvent(h, 'end'); 35 | t.is(bs.toString('utf8'), '61'); 36 | }); 37 | 38 | test('streamFilesNone', async t => { 39 | await utils.streamFiles([], () => null); 40 | await t.throwsAsync(() => utils.streamFiles( 41 | [BAD_FILE], () => new utils.HexStream() 42 | )); 43 | }); 44 | 45 | test('streamFilesDash', async t => { 46 | const u = new utils.HexStream(); 47 | const bs = new NoFilter(); 48 | u.pipe(bs); 49 | await utils.streamFiles([new utils.DeHexStream('6161')], () => u); 50 | t.is(bs.toString('utf8'), '6161'); 51 | }); 52 | 53 | test('streamFilesInputs', async t => { 54 | t.plan(1); 55 | const u = new utils.HexStream(); 56 | const bs = new NoFilter(); 57 | u.pipe(bs); 58 | 59 | await utils.streamFiles([ 60 | new utils.DeHexStream('48656c6c6f2c20576f726c64210a'), 61 | ], () => u); 62 | t.is(bs.read().toString(), '48656c6c6f2c20576f726c64210a'); 63 | }); 64 | 65 | test('printError', t => { 66 | mockIo.start(); 67 | utils.printError(null); 68 | t.deepEqual(mockIo.end(), {stderr: '', stdout: ''}); 69 | mockIo.start(); 70 | utils.printError(new Error('Fake error')); 71 | const res = mockIo.end(); 72 | t.is(res.stdout, ''); 73 | t.truthy(res.stderr.startsWith('Error: Fake error')); 74 | }); 75 | -------------------------------------------------------------------------------- /packages/cbor-rn-prereqs/.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | -------------------------------------------------------------------------------- /packages/cbor-rn-prereqs/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/cbor-rn-prereqs/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/cbor-rn-prereqs/README.md: -------------------------------------------------------------------------------- 1 | # cbor-rn-prereqs 2 | 3 | Make it easier to use the cbor package in React Native. 4 | 5 | ## MOVE TO CBOR2 6 | 7 | **NOTE** 8 | 9 | All users of this library should move to the 10 | [cbor2](https://github.com/hildjj/cbor2) library. It is where most 11 | maintenance and support and all new features are happening. This set of 12 | workarounds has always been lightly-maintained, since React Native's JS 13 | implementation is... not that similar to other modern runtimes. 14 | 15 | *Only* catastrophic bugs will be fixed in this library going forward. 16 | 17 | ## Installation: 18 | 19 | ```bash 20 | $ npm install --save cbor cbor-rn-prereqs 21 | ``` 22 | 23 | Ensure you have a file named `metro.config.js` in your project root, and that 24 | it contains at least this: 25 | 26 | ```js 27 | module.exports = { 28 | resolver: { 29 | extraNodeModules: { 30 | stream: require.resolve('stream-browserify'), 31 | }, 32 | }, 33 | }; 34 | ``` 35 | 36 | `require` this package *before* importing or requiring `cbor`: 37 | 38 | ```js 39 | require('cbor-rn-prereqs'); 40 | const cbor = require('cbor'); 41 | ``` 42 | 43 | ## What this does 44 | 45 | This package bundles up a few additions to the JavaScript-like environment 46 | that React Native provides. In particular: 47 | 48 | - BigInt support using [big-integer](https://github.com/peterolson/BigInteger.js#readme), which gets installed globally if React Native's version of JSC is too old to have BigInt support. IMO, this is fixing a React Native bug. 49 | - process.nextTick() from [process](https://github.com/shtylman/node-process#readme). If there is no `process` in your environment, all of the `process` package gets installed globally. If there is, but it doesn't have `nextTick`, just `nextTick` will be added to the existing global `process` instance. 50 | - A small and non-full-featured implementation of TextDecoder from [@cto.af/textdecoder](https://github.com/hildjj/ctoaf-textdecoder#readme), which gets installed globally. IMO this is also a React Native bug. 51 | - A few dependencies that replace functionality available in node, from [buffer](https://github.com/feross/buffer), [events](https://github.com/Gozala/events#readme), and [stream-browserify](https://github.com/browserify/stream-browserify) 52 | 53 | `stream-browserify` needs to be made available when packages do `require('stream')`, which is enabled by the `metro.config.js` change above. 54 | 55 | -------------------------------------------------------------------------------- /packages/cbor-rn-prereqs/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function patchGlobal(g) { 4 | const fixes = []; 5 | 6 | if (g.BigInt === undefined) { 7 | const bi = require('big-integer'); 8 | 9 | // Allow BigInt('0xffffffffffffffff') or BigInt('0x777777777777777777') 10 | g.BigInt = value => { 11 | if (typeof value === 'string') { 12 | // eslint-disable-next-line prefer-named-capture-group 13 | const match = value.match(/^0([xo])([0-9a-f]+)$/i); 14 | if (match) { 15 | return bi(match[2], match[1].toLowerCase() === 'x' ? 16 : 8); 16 | } 17 | } 18 | return bi(value); 19 | }; 20 | fixes.push('BigInt'); 21 | } 22 | 23 | if (g.process === undefined) { 24 | // eslint-disable-next-line n/prefer-node-protocol 25 | g.process = require('process'); 26 | fixes.push('process'); 27 | } else if (g.process.nextTick === undefined) { 28 | // eslint-disable-next-line n/prefer-node-protocol 29 | g.process.nextTick = require('process').nextTick; 30 | fixes.push('nextTick'); 31 | } 32 | 33 | if (g.TextDecoder === undefined) { 34 | const TextDecoder = require('@cto.af/textdecoder'); 35 | g.TextDecoder = TextDecoder; 36 | fixes.push('TextDecoder'); 37 | } 38 | 39 | return fixes; 40 | } 41 | 42 | exports.patchGlobal = patchGlobal; 43 | exports.fixes = patchGlobal(global); 44 | 45 | -------------------------------------------------------------------------------- /packages/cbor-rn-prereqs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cbor-rn-prereqs", 3 | "version": "10.0.3", 4 | "description": "React Native pre-requisites for cbor", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "ava test/*.ava.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 12 | "directory": "packages/cbor-rn-prereqs" 13 | }, 14 | "homepage": "https://github.com/hildjj/node-cbor/tree/main/packages/cbor-rn-prereqs", 15 | "keywords": [ 16 | "react native", 17 | "react-native", 18 | "cbor" 19 | ], 20 | "author": "Joe Hildebrand ", 21 | "license": "MIT", 22 | "dependencies": { 23 | "@cto.af/textdecoder": "^0.2.0", 24 | "big-integer": "^1.6.52", 25 | "buffer": "^6.0.3", 26 | "events": "^3.3.0", 27 | "process": "^0.11.10", 28 | "stream-browserify": "^3.0.0" 29 | }, 30 | "engines": { 31 | "node": ">=20" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/cbor-rn-prereqs/test/index.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const {fixes, patchGlobal} = require('../'); 5 | 6 | test('node environment', t => { 7 | t.deepEqual(fixes, []); 8 | }); 9 | 10 | test('some potential broken environments', t => { 11 | const fakeGlobal = {}; 12 | const fakeFixes = patchGlobal(fakeGlobal); 13 | t.deepEqual(fakeFixes, ['BigInt', 'process', 'TextDecoder']); 14 | const fakeGlobal2 = {process: {}}; 15 | const fakeFixes2 = patchGlobal(fakeGlobal2); 16 | t.deepEqual(fakeFixes2, ['BigInt', 'nextTick', 'TextDecoder']); 17 | }); 18 | 19 | test('BigInt', t => { 20 | const fakeGlobal = {}; 21 | patchGlobal(fakeGlobal); 22 | 23 | const hex = fakeGlobal.BigInt('0xffffffffffffffff'); 24 | t.is(hex.toString(16), 'ffffffffffffffff'); 25 | 26 | const oct = fakeGlobal.BigInt('0o7777777777777777'); 27 | t.is(oct.toString(8), '7777777777777777'); 28 | 29 | const i = fakeGlobal.BigInt(0xffffffff); 30 | t.is(i.toString(16), 'ffffffff'); 31 | 32 | const j = fakeGlobal.BigInt('16'); 33 | t.is(j.toString(), '16'); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/cbor-web/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | .DS_Store 4 | TAGS 5 | .nyc_output/ 6 | *.js.map 7 | jsconfig.json 8 | typings/ 9 | typings.json 10 | .vscode/ 11 | shrinkwrap.yaml 12 | npm-debug.log 13 | t.js 14 | pnpm-lock.yaml 15 | yarn.lock 16 | yarn-error.log 17 | .eslintrc.js 18 | webpack.config.js 19 | lib/ 20 | -------------------------------------------------------------------------------- /packages/cbor-web/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /packages/cbor-web/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/cbor-web/README.md: -------------------------------------------------------------------------------- 1 | # cbor-web 2 | 3 | This package bundles the [cbor](../cbor) package for easy use on the web. The following packages are bundled in as well, to reduce the degree of difficulty: 4 | 5 | - [buffer](https://github.com/feross/buffer) 6 | - [nofilter](https://github.com/hildjj/nofilter) 7 | - [process](https://github.com/shtylman/node-process) 8 | - [stream-browserify](https://github.com/browserify/stream-browserify) 9 | 10 | ## MOVE TO CBOR2 11 | 12 | **NOTE** 13 | 14 | ALL users of this library should move to the 15 | [cbor2](https://github.com/hildjj/cbor2) library. It is where most 16 | maintenance and support and all new features are happening. cbor2 works 17 | natively on the web and does not this set of work-arounds and dependencies. 18 | 19 | *Only* catastrophic bugs will be fixed in this library going forward. 20 | 21 | ## Examples 22 | 23 | You can see `cbor-web` in action on the web [here](https://hildjj.github.io/node-cbor/example/). 24 | 25 | ## Ways to use this 26 | 27 | - you can load this in a script tag, which puts a `cbor` property on the 28 | window object: 29 | 30 | ```html 31 | 32 | 33 | 34 | ``` 35 | 36 | - You can bundle this with [parcel](https://github.com/parcel-bundler/parcel), [webpack](https://github.com/webpack/webpack), [browserify](https://github.com/browserify/browserify), etc. 37 | - You can `require('cbor-web')` from node.js, but I wouldn't recommend that unless you're trying to use the exact same paths for backend and frontend codebases, for example. 38 | - You can `import cbor from 'cbor-web'` in either node or in some web contexts. Caveats to using in node are the same as above, but someimes you might *really* want an ES6 module, and be willing to deal with the downsides. Note that as soon as Node 10 is no longer supported, the main `cbor` package will work toward becoming a native ES6 module. 39 | -------------------------------------------------------------------------------- /packages/cbor-web/dist/cbor.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * The buffer module from node.js, for the browser. 3 | * 4 | * @author Feross Aboukhadijeh 5 | * @license MIT 6 | */ 7 | 8 | /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ 9 | 10 | /*! safe-buffer. MIT License. Feross Aboukhadijeh */ 11 | -------------------------------------------------------------------------------- /packages/cbor-web/lib/cbor.js: -------------------------------------------------------------------------------- 1 | export * from 'cbor'; 2 | -------------------------------------------------------------------------------- /packages/cbor-web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cbor-web", 3 | "version": "10.0.3", 4 | "description": "", 5 | "main": "dist/cbor.js", 6 | "types": "./types/lib/cbor.d.ts", 7 | "scripts": { 8 | "build": "webpack", 9 | "copy": "webpack" 10 | }, 11 | "keywords": [], 12 | "author": "Joe Hildebrand ", 13 | "license": "MIT", 14 | "homepage": "https://github.com/hildjj/node-cbor/tree/main/packages/cbor-web", 15 | "repository": { 16 | "type": "git", 17 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 18 | "directory": "packages/cbor-web" 19 | }, 20 | "devDependencies": { 21 | "abort-controller": "3.0.0", 22 | "base64-js": "^1.5.1", 23 | "buffer": "^6.0.3", 24 | "cbor": "^10.0.3", 25 | "events": "^3.3.0", 26 | "ieee754": "^1.2.1", 27 | "inherits": "^2.0.4", 28 | "nofilter": "^3.0.2", 29 | "process": "^0.11.10", 30 | "readable-stream": "^4.7.0", 31 | "safe-buffer": "^5.2.1", 32 | "stream-browserify": "^3.0.0", 33 | "string_decoder": "^1.3.0", 34 | "util-deprecate": "^1.0.2", 35 | "webpack": "^5.99.7", 36 | "webpack-cli": "^5.1.4" 37 | }, 38 | "engines": { 39 | "node": ">=20" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/cbor.d.ts: -------------------------------------------------------------------------------- 1 | import Commented = require("./commented"); 2 | import Diagnose = require("./diagnose"); 3 | import Decoder = require("./decoder"); 4 | import Encoder = require("./encoder"); 5 | import Simple = require("./simple"); 6 | import Tagged = require("./tagged"); 7 | import Map = require("./map"); 8 | import SharedValueEncoder = require("./sharedValueEncoder"); 9 | export declare let comment: typeof import("./commented").comment; 10 | export declare let decodeAll: typeof import("./decoder").decodeAll; 11 | export declare let decodeFirst: typeof import("./decoder").decodeFirst; 12 | export declare let decodeAllSync: typeof import("./decoder").decodeAllSync; 13 | export declare let decodeFirstSync: typeof import("./decoder").decodeFirstSync; 14 | export declare let diagnose: typeof import("./diagnose").diagnose; 15 | export declare let encode: typeof import("./encoder").encode; 16 | export declare let encodeCanonical: typeof import("./encoder").encodeCanonical; 17 | export declare let encodeOne: typeof import("./encoder").encodeOne; 18 | export declare let encodeAsync: typeof import("./encoder").encodeAsync; 19 | export declare let decode: typeof import("./decoder").decodeFirstSync; 20 | export declare namespace leveldb { 21 | let decode_1: typeof Decoder.decodeFirstSync; 22 | export { decode_1 as decode }; 23 | let encode_1: typeof Encoder.encode; 24 | export { encode_1 as encode }; 25 | export let buffer: boolean; 26 | export let name: string; 27 | } 28 | /** 29 | * Reset everything that we can predict a plugin might have altered in good 30 | * faith. For now that includes the default set of tags that decoding and 31 | * encoding will use. 32 | */ 33 | export declare function reset(): void; 34 | export { Commented, Diagnose, Decoder, Encoder, Simple, Tagged, Map, SharedValueEncoder }; 35 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/commented.d.ts: -------------------------------------------------------------------------------- 1 | export = Commented; 2 | /** 3 | * Generate the expanded format of RFC 8949, section 3.2.2. 4 | * 5 | * @extends stream.Transform 6 | */ 7 | declare class Commented extends stream.Transform { 8 | /** 9 | * Comment on an input Buffer or string, creating a string passed to the 10 | * callback. If callback not specified, a promise is returned. 11 | * 12 | * @param {string|Buffer|ArrayBuffer|Uint8Array|Uint8ClampedArray 13 | * |DataView|stream.Readable} input Something to parse. 14 | * @param {CommentOptions|commentCallback|string|number} [options={}] 15 | * Encoding, max_depth, or callback. 16 | * @param {commentCallback} [cb] If specified, called on completion. 17 | * @returns {Promise} If cb not specified. 18 | * @throws {Error} Input required. 19 | * @static 20 | */ 21 | static comment(input: string | Buffer | ArrayBuffer | Uint8Array | Uint8ClampedArray | DataView | stream.Readable, options?: CommentOptions | commentCallback | string | number, cb?: commentCallback): Promise; 22 | /** 23 | * Create a CBOR commenter. 24 | * 25 | * @param {CommentOptions} [options={}] Stream options. 26 | */ 27 | constructor(options?: CommentOptions); 28 | depth: number; 29 | max_depth: number; 30 | all: NoFilter; 31 | parser: Decoder; 32 | /** 33 | * @param {Buffer} v Descend into embedded CBOR. 34 | * @private 35 | */ 36 | private _tag_24; 37 | /** 38 | * @ignore 39 | */ 40 | _on_error(er: any): void; 41 | /** 42 | * @ignore 43 | */ 44 | _on_read(buf: any): void; 45 | /** 46 | * @ignore 47 | */ 48 | _on_more(mt: any, len: any, parent_mt: any, pos: any): void; 49 | /** 50 | * @ignore 51 | */ 52 | _on_start_string(mt: any, len: any, parent_mt: any, pos: any): void; 53 | /** 54 | * @ignore 55 | */ 56 | _on_start(mt: any, tag: any, parent_mt: any, pos: any): void; 57 | /** 58 | * @ignore 59 | */ 60 | _on_stop(mt: any): void; 61 | /** 62 | * @private 63 | */ 64 | private _on_value; 65 | /** 66 | * @ignore 67 | */ 68 | _on_data(): void; 69 | } 70 | declare namespace Commented { 71 | export { CommentOptions, commentCallback }; 72 | } 73 | import stream = require("stream"); 74 | import NoFilter = require("nofilter"); 75 | import Decoder = require("./decoder"); 76 | import { Buffer } from "buffer"; 77 | type CommentOptions = { 78 | /** 79 | * How many times to indent 80 | * the dashes. 81 | */ 82 | max_depth?: number; 83 | /** 84 | * Initial indentation depth. 85 | */ 86 | depth?: number; 87 | /** 88 | * If true, omit the summary 89 | * of the full bytes read at the end. 90 | */ 91 | no_summary?: boolean; 92 | /** 93 | * Mapping from tag number to function(v), 94 | * where v is the decoded value that comes after the tag, and where the 95 | * function returns the correctly-created value for that tag. 96 | */ 97 | tags?: object; 98 | /** 99 | * If true, prefer Uint8Arrays to 100 | * be generated instead of node Buffers. This might turn on some more 101 | * changes in the future, so forward-compatibility is not guaranteed yet. 102 | */ 103 | preferWeb?: boolean; 104 | /** 105 | * Encoding to use for input, if it 106 | * is a string. 107 | */ 108 | encoding?: BufferEncoding; 109 | }; 110 | type commentCallback = (error?: Error, commented?: string) => void; 111 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/constants.d.ts: -------------------------------------------------------------------------------- 1 | export namespace MT { 2 | let POS_INT: number; 3 | let NEG_INT: number; 4 | let BYTE_STRING: number; 5 | let UTF8_STRING: number; 6 | let ARRAY: number; 7 | let MAP: number; 8 | let TAG: number; 9 | let SIMPLE_FLOAT: number; 10 | } 11 | export type MT = number; 12 | export namespace TAG { 13 | let DATE_STRING: number; 14 | let DATE_EPOCH: number; 15 | let POS_BIGINT: number; 16 | let NEG_BIGINT: number; 17 | let DECIMAL_FRAC: number; 18 | let BIGFLOAT: number; 19 | let BASE64URL_EXPECTED: number; 20 | let BASE64_EXPECTED: number; 21 | let BASE16_EXPECTED: number; 22 | let CBOR: number; 23 | let URI: number; 24 | let BASE64URL: number; 25 | let BASE64: number; 26 | let REGEXP: number; 27 | let MIME: number; 28 | let SET: number; 29 | } 30 | export type TAG = number; 31 | export namespace NUMBYTES { 32 | let ZERO: number; 33 | let ONE: number; 34 | let TWO: number; 35 | let FOUR: number; 36 | let EIGHT: number; 37 | let INDEFINITE: number; 38 | } 39 | export type NUMBYTES = number; 40 | export namespace SIMPLE { 41 | let FALSE: number; 42 | let TRUE: number; 43 | let NULL: number; 44 | let UNDEFINED: number; 45 | } 46 | export type SIMPLE = number; 47 | export namespace SYMS { 48 | let NULL_1: symbol; 49 | export { NULL_1 as NULL }; 50 | let UNDEFINED_1: symbol; 51 | export { UNDEFINED_1 as UNDEFINED }; 52 | export let PARENT: symbol; 53 | export let BREAK: symbol; 54 | export let STREAM: symbol; 55 | } 56 | export const SHIFT32: 4294967296; 57 | export namespace BI { 58 | let MINUS_ONE: bigint; 59 | let NEG_MAX: bigint; 60 | let MAXINT32: bigint; 61 | let MAXINT64: bigint; 62 | let SHIFT32: bigint; 63 | } 64 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/diagnose.d.ts: -------------------------------------------------------------------------------- 1 | export = Diagnose; 2 | /** 3 | * Output the diagnostic format from a stream of CBOR bytes. 4 | * 5 | * @extends stream.Transform 6 | */ 7 | declare class Diagnose extends stream.Transform { 8 | /** 9 | * Convenience function to return a string in diagnostic format. 10 | * 11 | * @param {BufferLike} input The CBOR bytes to format. 12 | * @param {DiagnoseOptions |diagnoseCallback|string} [options={}] 13 | * Options, the callback, or the input encoding. 14 | * @param {diagnoseCallback} [cb] Callback. 15 | * @returns {Promise} If callback not specified. 16 | * @throws {TypeError} Input not provided. 17 | */ 18 | static diagnose(input: BufferLike, options?: DiagnoseOptions | diagnoseCallback | string, cb?: diagnoseCallback): Promise; 19 | /** 20 | * Creates an instance of Diagnose. 21 | * 22 | * @param {DiagnoseOptions} [options={}] Options for creation. 23 | */ 24 | constructor(options?: DiagnoseOptions); 25 | float_bytes: number; 26 | separator: string; 27 | stream_errors: boolean; 28 | parser: Decoder; 29 | /** 30 | * @ignore 31 | */ 32 | _on_error(er: any): void; 33 | /** @private */ 34 | private _on_more; 35 | /** @private */ 36 | private _fore; 37 | /** @private */ 38 | private _on_value; 39 | /** @private */ 40 | private _on_start; 41 | /** @private */ 42 | private _on_stop; 43 | /** @private */ 44 | private _on_data; 45 | } 46 | declare namespace Diagnose { 47 | export { BufferLike, DiagnoseOptions, diagnoseCallback }; 48 | } 49 | import stream = require("stream"); 50 | import Decoder = require("./decoder"); 51 | /** 52 | * Things that can act as inputs, from which a NoFilter can be created. 53 | */ 54 | type BufferLike = string | Buffer | ArrayBuffer | Uint8Array | Uint8ClampedArray | DataView | stream.Readable; 55 | type DiagnoseOptions = { 56 | /** 57 | * Output between detected objects. 58 | */ 59 | separator?: string; 60 | /** 61 | * Put error info into the 62 | * output stream. 63 | */ 64 | stream_errors?: boolean; 65 | /** 66 | * The maximum depth to parse. 67 | * Use -1 for "until you run out of memory". Set this to a finite 68 | * positive number for un-trusted inputs. Most standard inputs won't nest 69 | * more than 100 or so levels; I've tested into the millions before 70 | * running out of memory. 71 | */ 72 | max_depth?: number; 73 | /** 74 | * Mapping from tag number to function(v), 75 | * where v is the decoded value that comes after the tag, and where the 76 | * function returns the correctly-created value for that tag. 77 | */ 78 | tags?: object; 79 | /** 80 | * If true, prefer Uint8Arrays to 81 | * be generated instead of node Buffers. This might turn on some more 82 | * changes in the future, so forward-compatibility is not guaranteed yet. 83 | */ 84 | preferWeb?: boolean; 85 | /** 86 | * The encoding of input, ignored if 87 | * input is not string. 88 | */ 89 | encoding?: BufferEncoding; 90 | }; 91 | type diagnoseCallback = (error?: Error, value?: string) => void; 92 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/map.d.ts: -------------------------------------------------------------------------------- 1 | export = CborMap; 2 | /** 3 | * Wrapper around a JavaScript Map object that allows the keys to be 4 | * any complex type. The base Map object allows this, but will only 5 | * compare the keys by identity, not by value. CborMap translates keys 6 | * to CBOR first (and base64's them to ensure by-value comparison). 7 | * 8 | * This is not a subclass of Object, because it would be tough to get 9 | * the semantics to be an exact match. 10 | * 11 | * @extends Map 12 | */ 13 | declare class CborMap extends Map { 14 | /** 15 | * @ignore 16 | * @param {unknown} key 17 | * @returns {string} 18 | */ 19 | static _encode(key: unknown): string; 20 | /** 21 | * @ignore 22 | * @param {string} key 23 | * @returns {unknown} 24 | */ 25 | static _decode(key: string): unknown; 26 | /** 27 | * Creates an instance of CborMap. 28 | * 29 | * @param {Iterable} [iterable] An Array or other iterable 30 | * object whose elements are key-value pairs (arrays with two elements, e.g. 31 | * [[ 1, 'one' ],[ 2, 'two' ]]). Each key-value pair is added 32 | * to the new CborMap; null values are treated as undefined. 33 | */ 34 | constructor(iterable?: Iterable); 35 | /** 36 | * Adds or updates an element with a specified key and value. 37 | * 38 | * @param {any} key The key identifying the element to store. 39 | * Can be any type, which will be serialized into CBOR and compared by 40 | * value. 41 | * @param {any} val The element to store. 42 | * @returns {this} This object. 43 | */ 44 | set(key: any, val: any): this; 45 | /** 46 | * Returns a new Iterator object that contains the [key, value] pairs for 47 | * each element in the Map object in insertion order. 48 | * 49 | * @returns {IterableIterator} Key value pairs. 50 | * @yields {any[]} Key value pairs. 51 | */ 52 | entries(): IterableIterator; 53 | /** 54 | * Executes a provided function once per each key/value pair in the Map 55 | * object, in insertion order. 56 | * 57 | * @param {function(any, any, Map): undefined} fun Function to 58 | * execute for each element, which takes a value, a key, and the Map 59 | * being traversed. 60 | * @param {any} thisArg Value to use as this when executing callback. 61 | * @throws {TypeError} Invalid function. 62 | */ 63 | forEach(fun: (arg0: any, arg1: any, arg2: Map) => undefined, thisArg?: any): void; 64 | /** 65 | * Push the simple value onto the CBOR stream. 66 | * 67 | * @param {import('./encoder.js')} gen The generator to push onto. 68 | * @returns {boolean} True on success. 69 | */ 70 | encodeCBOR(gen: import("./encoder.js")): boolean; 71 | /** 72 | * Returns a new Iterator object that contains the [key, value] pairs for 73 | * each element in the Map object in insertion order. 74 | * 75 | * @returns {IterableIterator} Key value pairs. 76 | */ 77 | [Symbol.iterator](): IterableIterator; 78 | } 79 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/objectRecorder.d.ts: -------------------------------------------------------------------------------- 1 | export = ObjectRecorder; 2 | /** 3 | * Record objects that pass by in a stream. If the same object is used more 4 | * than once, it can be value-shared using shared values. 5 | * 6 | * @see {@link http://cbor.schmorp.de/value-sharing} 7 | */ 8 | declare class ObjectRecorder { 9 | /** 10 | * Clear all of the objects that have been seen. Revert to recording mode. 11 | */ 12 | clear(): void; 13 | map: WeakMap; 14 | count: number; 15 | recording: boolean; 16 | /** 17 | * Stop recording. 18 | */ 19 | stop(): void; 20 | /** 21 | * Determine if wrapping a tag 28 or 29 around an object that has been 22 | * reused is appropriate. This method stores state for which objects have 23 | * been seen. 24 | * 25 | * @param {object} obj Any object about to be serialized. 26 | * @returns {number} If recording: -1 for first use, index for second use. 27 | * If not recording, -1 for never-duplicated, -2 for first use, index for 28 | * subsequent uses. 29 | * @throws {Error} Recording does not match playback. 30 | */ 31 | check(obj: object): number; 32 | } 33 | declare namespace ObjectRecorder { 34 | let NEVER: number; 35 | let FIRST: number; 36 | } 37 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/sharedValueEncoder.d.ts: -------------------------------------------------------------------------------- 1 | export = SharedValueEncoder; 2 | /** 3 | * Implement value sharing. 4 | * 5 | * @see {@link cbor.schmorp.de/value-sharing} 6 | */ 7 | declare class SharedValueEncoder extends Encoder { 8 | constructor(opts: any); 9 | valueSharing: ObjectRecorder; 10 | /** 11 | * Between encoding runs, stop recording, and start outputing correct tags. 12 | */ 13 | stopRecording(): void; 14 | /** 15 | * Remove the existing recording and start over. Do this between encoding 16 | * pairs. 17 | */ 18 | clearRecording(): void; 19 | } 20 | import Encoder = require("./encoder"); 21 | import ObjectRecorder = require("./objectRecorder"); 22 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/simple.d.ts: -------------------------------------------------------------------------------- 1 | export = Simple; 2 | /** 3 | * A CBOR Simple Value that does not map onto a known constant. 4 | */ 5 | declare class Simple { 6 | /** 7 | * Is the given object a Simple? 8 | * 9 | * @param {any} obj Object to test. 10 | * @returns {boolean} Is it Simple? 11 | */ 12 | static isSimple(obj: any): boolean; 13 | /** 14 | * Decode from the CBOR additional information into a JavaScript value. 15 | * If the CBOR item has no parent, return a "safe" symbol instead of 16 | * `null` or `undefined`, so that the value can be passed through a 17 | * stream in object mode. 18 | * 19 | * @param {number} val The CBOR additional info to convert. 20 | * @param {boolean} [has_parent=true] Does the CBOR item have a parent? 21 | * @param {boolean} [parent_indefinite=false] Is the parent element 22 | * indefinitely encoded? 23 | * @returns {(null|undefined|boolean|symbol|Simple)} The decoded value. 24 | * @throws {Error} Invalid BREAK. 25 | */ 26 | static decode(val: number, has_parent?: boolean, parent_indefinite?: boolean): (null | undefined | boolean | symbol | Simple); 27 | /** 28 | * Creates an instance of Simple. 29 | * 30 | * @param {number} value The simple value's integer value. 31 | */ 32 | constructor(value: number); 33 | value: number; 34 | /** 35 | * Debug string for simple value. 36 | * 37 | * @returns {string} Formated string of `simple(value)`. 38 | */ 39 | toString(): string; 40 | /** 41 | * Push the simple value onto the CBOR stream. 42 | * 43 | * @param {object} gen The generator to push onto. 44 | * @returns {boolean} True on success. 45 | */ 46 | encodeCBOR(gen: object): boolean; 47 | } 48 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/tagged.d.ts: -------------------------------------------------------------------------------- 1 | export = Tagged; 2 | /** 3 | * A CBOR tagged item, where the tag does not have semantics specified at the 4 | * moment, or those semantics threw an error during parsing. Typically this will 5 | * be an extension point you're not yet expecting. 6 | */ 7 | declare class Tagged { 8 | static set TAGS(val: { 9 | [x: string]: TagFunction; 10 | }); 11 | /** 12 | * The current set of supported tags. May be modified by plugins. 13 | * 14 | * @type {TagMap} 15 | * @static 16 | */ 17 | static get TAGS(): { 18 | [x: string]: TagFunction; 19 | }; 20 | /** 21 | * Reset the supported tags to the original set, before any plugins modified 22 | * the list. 23 | */ 24 | static reset(): void; 25 | /** 26 | * Creates an instance of Tagged. 27 | * 28 | * @param {number} tag The number of the tag. 29 | * @param {any} value The value inside the tag. 30 | * @param {Error} [err] The error that was thrown parsing the tag, or null. 31 | */ 32 | constructor(tag: number, value: any, err?: Error); 33 | tag: number; 34 | value: any; 35 | err: Error; 36 | toJSON(): any; 37 | /** 38 | * Convert to a String. 39 | * 40 | * @returns {string} String of the form '1(2)'. 41 | */ 42 | toString(): string; 43 | /** 44 | * Push the simple value onto the CBOR stream. 45 | * 46 | * @param {object} gen The generator to push onto. 47 | * @returns {boolean} True on success. 48 | */ 49 | encodeCBOR(gen: object): boolean; 50 | /** 51 | * If we have a converter for this type, do the conversion. Some converters 52 | * are built-in. Additional ones can be passed in. If you want to remove 53 | * a built-in converter, pass a converter in whose value is 'null' instead 54 | * of a function. 55 | * 56 | * @param {object} converters Keys in the object are a tag number, the value 57 | * is a function that takes the decoded CBOR and returns a JavaScript value 58 | * of the appropriate type. Throw an exception in the function on errors. 59 | * @returns {any} The converted item. 60 | */ 61 | convert(converters: object): any; 62 | } 63 | declare namespace Tagged { 64 | export { INTERNAL_JSON, TagFunction, TagMap }; 65 | } 66 | declare const INTERNAL_JSON: unique symbol; 67 | /** 68 | * Convert a tagged value to a more interesting JavaScript type. Errors 69 | * thrown in this function will be captured into the "err" property of the 70 | * original Tagged instance. 71 | */ 72 | type TagFunction = (value: any, tag: Tagged) => any; 73 | /** 74 | * A mapping from tag number to a tag decoding function. 75 | */ 76 | type TagMap = { 77 | [x: string]: TagFunction; 78 | }; 79 | -------------------------------------------------------------------------------- /packages/cbor-web/types/lib/utils.d.ts: -------------------------------------------------------------------------------- 1 | export function utf8(buf: any): string; 2 | export namespace utf8 { 3 | let checksUTF8: boolean; 4 | } 5 | export function isBufferish(b: any): boolean; 6 | export function bufferishToBuffer(b: any): Buffer; 7 | export function parseCBORint(ai: any, buf: any): any; 8 | export function writeHalf(buf: any, half: any): boolean; 9 | export function parseHalf(buf: any): number; 10 | export function parseCBORfloat(buf: any): any; 11 | export function hex(s: any): Buffer; 12 | export function bin(s: any): Buffer; 13 | export function arrayEqual(a: any, b: any): any; 14 | export function bufferToBigInt(buf: any): bigint; 15 | export function cborValueToString(val: any, float_bytes?: number): any; 16 | export function guessEncoding(input: any, encoding: any): any; 17 | export function base64url(buf: Buffer | Uint8Array | Uint8ClampedArray | ArrayBuffer | DataView): string; 18 | export function base64(buf: Buffer | Uint8Array | Uint8ClampedArray | ArrayBuffer | DataView): string; 19 | export function isBigEndian(): boolean; 20 | import { Buffer } from "buffer"; 21 | -------------------------------------------------------------------------------- /packages/cbor-web/types/vendor/binary-parse-stream/index.d.ts: -------------------------------------------------------------------------------- 1 | export = BinaryParseStream; 2 | /** 3 | * BinaryParseStream is a TransformStream that consumes buffers and outputs 4 | * objects on the other end. It expects your subclass to implement a `_parse` 5 | * method that is a generator. When your generator yields a number, it'll be 6 | * fed a buffer of that length from the input. When your generator returns, 7 | * the return value will be pushed to the output side. 8 | * 9 | * @extends stream.Transform 10 | */ 11 | declare class BinaryParseStream extends stream.Transform { 12 | /** 13 | * Creates an instance of BinaryParseStream. 14 | * 15 | * @memberof BinaryParseStream 16 | * @param {stream.TransformOptions} options Stream options. 17 | */ 18 | constructor(options: stream.TransformOptions); 19 | bs: NoFilter; 20 | __fresh: boolean; 21 | __needed: any; 22 | /** 23 | * Subclasses must override this to set their parsing behavior. Yield a 24 | * number to receive a Buffer of that many bytes. 25 | * 26 | * @abstract 27 | * @returns {Generator} 28 | */ 29 | _parse(): Generator; 30 | __restart(): void; 31 | __parser: Generator; 32 | } 33 | import stream = require("stream"); 34 | import NoFilter = require("nofilter"); 35 | -------------------------------------------------------------------------------- /packages/cbor-web/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('node:path'); 4 | const webpack = require('webpack'); 5 | 6 | module.exports = { 7 | entry: './lib/cbor.js', 8 | mode: 'production', 9 | output: { 10 | path: path.resolve(__dirname, 'dist'), 11 | filename: 'cbor.js', 12 | library: 'cbor', 13 | libraryTarget: 'umd', 14 | globalObject: 'this', 15 | }, 16 | target: 'web', 17 | resolve: { 18 | symlinks: false, 19 | fallback: { 20 | stream: 'stream-browserify', 21 | }, 22 | }, 23 | plugins: [ 24 | new webpack.ProvidePlugin({ 25 | process: 'process/browser', 26 | Buffer: ['buffer', 'Buffer'], 27 | }), 28 | ], 29 | }; 30 | -------------------------------------------------------------------------------- /packages/cbor/.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules 3 | coverage 4 | -------------------------------------------------------------------------------- /packages/cbor/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | .DS_Store 4 | TAGS 5 | .nyc_output/ 6 | *.js.map 7 | jsconfig.json 8 | typings/ 9 | typings.json 10 | .vscode/ 11 | tools/ 12 | docs/ 13 | test/ 14 | man_src/ 15 | Dockerfile 16 | .editorconfig 17 | .eslintrc.js 18 | .gitmodules 19 | .jsdoc.conf 20 | .travis.yml 21 | .waiting.html 22 | test-vectors/ 23 | .dockerignore 24 | npm-debug.log 25 | cli/ 26 | .ncurc.json 27 | t.js 28 | tsconfig.json 29 | webpack-demo/ 30 | .github/ 31 | examples/ 32 | pnpm-lock.yaml 33 | .ncurc.js 34 | -------------------------------------------------------------------------------- /packages/cbor/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /packages/cbor/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | MAINTAINER Joe Hildebrand 3 | 4 | VOLUME /root/.npm 5 | RUN npm install -g nodeunit grunt grunt-cli istanbul 6 | 7 | ADD . /opt/cbor 8 | WORKDIR /opt/cbor 9 | 10 | RUN npm install 11 | 12 | CMD ["nodeunit", "test"] 13 | -------------------------------------------------------------------------------- /packages/cbor/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/cbor/lib/cbor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Commented = require('./commented'); 4 | const Diagnose = require('./diagnose'); 5 | const Decoder = require('./decoder'); 6 | const Encoder = require('./encoder'); 7 | const Simple = require('./simple'); 8 | const Tagged = require('./tagged'); 9 | const Map = require('./map'); 10 | const SharedValueEncoder = require('./sharedValueEncoder'); 11 | 12 | module.exports = { 13 | Commented, 14 | Diagnose, 15 | Decoder, 16 | Encoder, 17 | Simple, 18 | Tagged, 19 | Map, 20 | SharedValueEncoder, 21 | 22 | /** 23 | * Convenience name for {@linkcode Commented.comment}. 24 | */ 25 | comment: Commented.comment, 26 | 27 | /** 28 | * Convenience name for {@linkcode Decoder.decodeAll}. 29 | */ 30 | decodeAll: Decoder.decodeAll, 31 | 32 | /** 33 | * Convenience name for {@linkcode Decoder.decodeFirst}. 34 | */ 35 | decodeFirst: Decoder.decodeFirst, 36 | 37 | /** 38 | * Convenience name for {@linkcode Decoder.decodeAllSync}. 39 | */ 40 | decodeAllSync: Decoder.decodeAllSync, 41 | 42 | /** 43 | * Convenience name for {@linkcode Decoder.decodeFirstSync}. 44 | */ 45 | decodeFirstSync: Decoder.decodeFirstSync, 46 | 47 | /** 48 | * Convenience name for {@linkcode Diagnose.diagnose}. 49 | */ 50 | diagnose: Diagnose.diagnose, 51 | 52 | /** 53 | * Convenience name for {@linkcode Encoder.encode}. 54 | */ 55 | encode: Encoder.encode, 56 | 57 | /** 58 | * Convenience name for {@linkcode Encoder.encodeCanonical}. 59 | */ 60 | encodeCanonical: Encoder.encodeCanonical, 61 | 62 | /** 63 | * Convenience name for {@linkcode Encoder.encodeOne}. 64 | */ 65 | encodeOne: Encoder.encodeOne, 66 | 67 | /** 68 | * Convenience name for {@linkcode Encoder.encodeAsync}. 69 | */ 70 | encodeAsync: Encoder.encodeAsync, 71 | 72 | /** 73 | * Convenience name for {@linkcode Decoder.decodeFirstSync}. 74 | */ 75 | decode: Decoder.decodeFirstSync, 76 | 77 | /** 78 | * The codec information for 79 | * {@link https://github.com/Level/encoding-down encoding-down}, which is a 80 | * codec framework for leveldb. CBOR is a particularly convenient format for 81 | * both keys and values, as it can deal with a lot of types that JSON can't 82 | * handle without losing type information. 83 | * 84 | * @example 85 | * const level = require('level') 86 | * const cbor = require('cbor') 87 | * 88 | * async function putget() { 89 | * const db = level('./db', { 90 | * keyEncoding: cbor.leveldb, 91 | * valueEncoding: cbor.leveldb, 92 | * }) 93 | * 94 | * await db.put({a: 1}, 9857298342094820394820394820398234092834n) 95 | * const val = await db.get({a: 1}) 96 | * } 97 | */ 98 | leveldb: { 99 | decode: Decoder.decodeFirstSync, 100 | encode: Encoder.encode, 101 | buffer: true, 102 | name: 'cbor', 103 | }, 104 | 105 | /** 106 | * Reset everything that we can predict a plugin might have altered in good 107 | * faith. For now that includes the default set of tags that decoding and 108 | * encoding will use. 109 | */ 110 | reset() { 111 | Encoder.reset(); 112 | Tagged.reset(); 113 | }, 114 | }; 115 | -------------------------------------------------------------------------------- /packages/cbor/lib/constants.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @enum {number} 5 | */ 6 | exports.MT = { 7 | POS_INT: 0, 8 | NEG_INT: 1, 9 | BYTE_STRING: 2, 10 | UTF8_STRING: 3, 11 | ARRAY: 4, 12 | MAP: 5, 13 | TAG: 6, 14 | SIMPLE_FLOAT: 7, 15 | }; 16 | 17 | /** 18 | * @enum {number} 19 | */ 20 | exports.TAG = { 21 | DATE_STRING: 0, 22 | DATE_EPOCH: 1, 23 | POS_BIGINT: 2, 24 | NEG_BIGINT: 3, 25 | DECIMAL_FRAC: 4, 26 | BIGFLOAT: 5, 27 | BASE64URL_EXPECTED: 21, 28 | BASE64_EXPECTED: 22, 29 | BASE16_EXPECTED: 23, 30 | CBOR: 24, 31 | URI: 32, 32 | BASE64URL: 33, 33 | BASE64: 34, 34 | REGEXP: 35, 35 | MIME: 36, 36 | // https://github.com/input-output-hk/cbor-sets-spec/blob/master/CBOR_SETS.md 37 | SET: 258, 38 | }; 39 | 40 | /** 41 | * @enum {number} 42 | */ 43 | exports.NUMBYTES = { 44 | ZERO: 0, 45 | ONE: 24, 46 | TWO: 25, 47 | FOUR: 26, 48 | EIGHT: 27, 49 | INDEFINITE: 31, 50 | }; 51 | 52 | /** 53 | * @enum {number} 54 | */ 55 | exports.SIMPLE = { 56 | FALSE: 20, 57 | TRUE: 21, 58 | NULL: 22, 59 | UNDEFINED: 23, 60 | }; 61 | 62 | exports.SYMS = { 63 | NULL: Symbol.for('github.com/hildjj/node-cbor/null'), 64 | UNDEFINED: Symbol.for('github.com/hildjj/node-cbor/undef'), 65 | PARENT: Symbol.for('github.com/hildjj/node-cbor/parent'), 66 | BREAK: Symbol.for('github.com/hildjj/node-cbor/break'), 67 | STREAM: Symbol.for('github.com/hildjj/node-cbor/stream'), 68 | }; 69 | 70 | exports.SHIFT32 = 0x100000000; 71 | 72 | exports.BI = { 73 | MINUS_ONE: BigInt(-1), 74 | NEG_MAX: BigInt(-1) - BigInt(Number.MAX_SAFE_INTEGER), 75 | MAXINT32: BigInt('0xffffffff'), 76 | MAXINT64: BigInt('0xffffffffffffffff'), 77 | SHIFT32: BigInt(exports.SHIFT32), 78 | }; 79 | 80 | -------------------------------------------------------------------------------- /packages/cbor/lib/map.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {Buffer} = require('buffer'); 4 | const encoder = require('./encoder'); 5 | const decoder = require('./decoder'); 6 | const {MT} = require('./constants'); 7 | 8 | /** 9 | * Wrapper around a JavaScript Map object that allows the keys to be 10 | * any complex type. The base Map object allows this, but will only 11 | * compare the keys by identity, not by value. CborMap translates keys 12 | * to CBOR first (and base64's them to ensure by-value comparison). 13 | * 14 | * This is not a subclass of Object, because it would be tough to get 15 | * the semantics to be an exact match. 16 | * 17 | * @extends Map 18 | */ 19 | class CborMap extends Map { 20 | /** 21 | * Creates an instance of CborMap. 22 | * 23 | * @param {Iterable} [iterable] An Array or other iterable 24 | * object whose elements are key-value pairs (arrays with two elements, e.g. 25 | * [[ 1, 'one' ],[ 2, 'two' ]]). Each key-value pair is added 26 | * to the new CborMap; null values are treated as undefined. 27 | */ 28 | constructor(iterable) { 29 | super(iterable); 30 | } 31 | 32 | /** 33 | * @ignore 34 | * @param {unknown} key 35 | * @returns {string} 36 | */ 37 | static _encode(key) { 38 | return encoder.encodeCanonical(key).toString('base64'); 39 | } 40 | 41 | /** 42 | * @ignore 43 | * @param {string} key 44 | * @returns {unknown} 45 | */ 46 | static _decode(key) { 47 | return decoder.decodeFirstSync(key, 'base64'); 48 | } 49 | 50 | /** 51 | * Retrieve a specified element. 52 | * 53 | * @param {any} key The key identifying the element to retrieve. 54 | * Can be any type, which will be serialized into CBOR and compared by 55 | * value. 56 | * @returns {any} The element if it exists, or undefined. 57 | */ 58 | get(key) { 59 | return super.get(CborMap._encode(key)); 60 | } 61 | 62 | /** 63 | * Adds or updates an element with a specified key and value. 64 | * 65 | * @param {any} key The key identifying the element to store. 66 | * Can be any type, which will be serialized into CBOR and compared by 67 | * value. 68 | * @param {any} val The element to store. 69 | * @returns {this} This object. 70 | */ 71 | set(key, val) { 72 | return super.set(CborMap._encode(key), val); 73 | } 74 | 75 | /** 76 | * Removes the specified element. 77 | * 78 | * @param {any} key The key identifying the element to delete. Can be any 79 | * type, which will be serialized into CBOR and compared by value. 80 | * @returns {boolean} True if an element in the Map object existed and has 81 | * been removed, or false if the element does not exist. 82 | */ 83 | delete(key) { 84 | return super.delete(CborMap._encode(key)); 85 | } 86 | 87 | /** 88 | * Does an element with the specified key exist? 89 | * 90 | * @param {any} key The key identifying the element to check. 91 | * Can be any type, which will be serialized into CBOR and compared by 92 | * value. 93 | * @returns {boolean} True if an element with the specified key exists in 94 | * the Map object; otherwise false. 95 | */ 96 | has(key) { 97 | return super.has(CborMap._encode(key)); 98 | } 99 | 100 | /** 101 | * Returns a new Iterator object that contains the keys for each element 102 | * in the Map object in insertion order. The keys are decoded into their 103 | * original format. 104 | * 105 | * @returns {MapIterator} 106 | */ 107 | *keys() { 108 | for (const k of super.keys()) { 109 | yield CborMap._decode(k); 110 | } 111 | } 112 | 113 | /** 114 | * Returns a new Iterator object that contains the [key, value] pairs for 115 | * each element in the Map object in insertion order. 116 | * 117 | * @returns {IterableIterator} Key value pairs. 118 | * @yields {any[]} Key value pairs. 119 | */ 120 | *entries() { 121 | for (const kv of super.entries()) { 122 | yield [CborMap._decode(kv[0]), kv[1]]; 123 | } 124 | } 125 | 126 | /** 127 | * Returns a new Iterator object that contains the [key, value] pairs for 128 | * each element in the Map object in insertion order. 129 | * 130 | * @returns {IterableIterator} Key value pairs. 131 | */ 132 | [Symbol.iterator]() { 133 | return this.entries(); 134 | } 135 | 136 | /** 137 | * Executes a provided function once per each key/value pair in the Map 138 | * object, in insertion order. 139 | * 140 | * @param {function(any, any, Map): undefined} fun Function to 141 | * execute for each element, which takes a value, a key, and the Map 142 | * being traversed. 143 | * @param {any} thisArg Value to use as this when executing callback. 144 | * @throws {TypeError} Invalid function. 145 | */ 146 | forEach(fun, thisArg = this) { 147 | if (typeof fun !== 'function') { 148 | throw new TypeError('Must be function'); 149 | } 150 | for (const kv of super.entries()) { 151 | fun.call(thisArg, kv[1], CborMap._decode(kv[0]), this); 152 | } 153 | } 154 | 155 | /** 156 | * Push the simple value onto the CBOR stream. 157 | * 158 | * @param {import('./encoder.js')} gen The generator to push onto. 159 | * @returns {boolean} True on success. 160 | */ 161 | encodeCBOR(gen) { 162 | if (!gen._pushInt(this.size, MT.MAP)) { 163 | return false; 164 | } 165 | if (gen.canonical) { 166 | const entries = Array.from(super.entries()) 167 | .map(kv => [Buffer.from(kv[0], 'base64'), kv[1]]); 168 | entries.sort((a, b) => a[0].compare(b[0])); 169 | for (const kv of entries) { 170 | if (!(gen.push(kv[0]) && gen.pushAny(kv[1]))) { 171 | return false; 172 | } 173 | } 174 | } else { 175 | for (const kv of super.entries()) { 176 | if (!(gen.push(Buffer.from(kv[0], 'base64')) && gen.pushAny(kv[1]))) { 177 | return false; 178 | } 179 | } 180 | } 181 | return true; 182 | } 183 | } 184 | 185 | module.exports = CborMap; 186 | -------------------------------------------------------------------------------- /packages/cbor/lib/objectRecorder.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Record objects that pass by in a stream. If the same object is used more 5 | * than once, it can be value-shared using shared values. 6 | * 7 | * @see {@link http://cbor.schmorp.de/value-sharing} 8 | */ 9 | class ObjectRecorder { 10 | constructor() { 11 | this.clear(); 12 | } 13 | 14 | /** 15 | * Clear all of the objects that have been seen. Revert to recording mode. 16 | */ 17 | clear() { 18 | this.map = new WeakMap(); 19 | this.count = 0; 20 | this.recording = true; 21 | } 22 | 23 | /** 24 | * Stop recording. 25 | */ 26 | stop() { 27 | this.recording = false; 28 | } 29 | 30 | /** 31 | * Determine if wrapping a tag 28 or 29 around an object that has been 32 | * reused is appropriate. This method stores state for which objects have 33 | * been seen. 34 | * 35 | * @param {object} obj Any object about to be serialized. 36 | * @returns {number} If recording: -1 for first use, index for second use. 37 | * If not recording, -1 for never-duplicated, -2 for first use, index for 38 | * subsequent uses. 39 | * @throws {Error} Recording does not match playback. 40 | */ 41 | check(obj) { 42 | const val = this.map.get(obj); 43 | if (val) { 44 | if (val.length > 1) { 45 | if (val[0] || this.recording) { 46 | return val[1]; 47 | } 48 | 49 | val[0] = true; 50 | return ObjectRecorder.FIRST; 51 | } 52 | if (!this.recording) { 53 | return ObjectRecorder.NEVER; 54 | } 55 | val.push(this.count++); 56 | // Second use while recording 57 | return val[1]; 58 | } 59 | if (!this.recording) { 60 | throw new Error('New object detected when not recording'); 61 | } 62 | this.map.set(obj, [false]); 63 | // First use while recording 64 | return ObjectRecorder.NEVER; 65 | } 66 | } 67 | 68 | ObjectRecorder.NEVER = -1; 69 | ObjectRecorder.FIRST = -2; 70 | 71 | module.exports = ObjectRecorder; 72 | -------------------------------------------------------------------------------- /packages/cbor/lib/sharedValueEncoder.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Encoder = require('./encoder'); 4 | const ObjectRecorder = require('./objectRecorder'); 5 | const {Buffer} = require('buffer'); 6 | 7 | /** 8 | * Implement value sharing. 9 | * 10 | * @see {@link cbor.schmorp.de/value-sharing} 11 | */ 12 | class SharedValueEncoder extends Encoder { 13 | constructor(opts) { 14 | super(opts); 15 | this.valueSharing = new ObjectRecorder(); 16 | } 17 | 18 | /** 19 | * @param {object} obj Object to encode. 20 | * @param {import('./encoder').ObjectOptions} [opts] Options for encoding 21 | * this object. 22 | * @returns {boolean} True on success. 23 | * @throws {Error} Loop detected. 24 | * @ignore 25 | */ 26 | _pushObject(obj, opts) { 27 | if (obj !== null) { 28 | const shared = this.valueSharing.check(obj); 29 | switch (shared) { 30 | case ObjectRecorder.FIRST: 31 | // Prefix with tag 28 32 | this._pushTag(28); 33 | break; 34 | case ObjectRecorder.NEVER: 35 | // Do nothing 36 | break; 37 | default: 38 | return this._pushTag(29) && this._pushIntNum(shared); 39 | } 40 | } 41 | return super._pushObject(obj, opts); 42 | } 43 | 44 | /** 45 | * Between encoding runs, stop recording, and start outputing correct tags. 46 | */ 47 | stopRecording() { 48 | this.valueSharing.stop(); 49 | } 50 | 51 | /** 52 | * Remove the existing recording and start over. Do this between encoding 53 | * pairs. 54 | */ 55 | clearRecording() { 56 | this.valueSharing.clear(); 57 | } 58 | 59 | /** 60 | * Encode one or more JavaScript objects, and return a Buffer containing the 61 | * CBOR bytes. 62 | * 63 | * @param {...any} objs The objects to encode. 64 | * @returns {Buffer} The encoded objects. 65 | */ 66 | static encode(...objs) { 67 | const enc = new SharedValueEncoder(); 68 | // eslint-disable-next-line no-empty-function 69 | enc.on('data', () => {}); // Sink all writes 70 | 71 | for (const o of objs) { 72 | enc.pushAny(o); 73 | } 74 | enc.stopRecording(); 75 | enc.removeAllListeners('data'); 76 | return enc._encodeAll(objs); 77 | } 78 | 79 | /** 80 | * Encode one or more JavaScript objects canonically (slower!), and return 81 | * a Buffer containing the CBOR bytes. 82 | * 83 | * @param {...any} _objs The objects to encode. 84 | * @returns {Buffer} Never. 85 | * @throws {Error} Always. This combination doesn't work at the moment. 86 | */ 87 | static encodeCanonical(..._objs) { 88 | throw new Error('Cannot encode canonically in a SharedValueEncoder, which serializes objects multiple times.'); 89 | } 90 | 91 | /** 92 | * Encode one JavaScript object using the given options. 93 | * 94 | * @param {any} obj The object to encode. 95 | * @param {import('./encoder').EncodingOptions} [options={}] 96 | * Passed to the Encoder constructor. 97 | * @returns {Buffer} The encoded objects. 98 | * @static 99 | */ 100 | static encodeOne(obj, options) { 101 | const enc = new SharedValueEncoder(options); 102 | // eslint-disable-next-line no-empty-function 103 | enc.on('data', () => {}); // Sink all writes 104 | enc.pushAny(obj); 105 | enc.stopRecording(); 106 | enc.removeAllListeners('data'); 107 | return enc._encodeAll([obj]); 108 | } 109 | 110 | /** 111 | * Encode one JavaScript object using the given options in a way that 112 | * is more resilient to objects being larger than the highWaterMark 113 | * number of bytes. As with the other static encode functions, this 114 | * will still use a large amount of memory. Use a stream-based approach 115 | * directly if you need to process large and complicated inputs. 116 | * 117 | * @param {any} obj The object to encode. 118 | * @param {import('./encoder').EncodingOptions} [options={}] 119 | * Passed to the Encoder constructor. 120 | * @returns {Promise} A promise for the encoded buffer. 121 | */ 122 | static encodeAsync(obj, options) { 123 | return new Promise((resolve, reject) => { 124 | /** @type {Buffer[]} */ 125 | const bufs = []; 126 | const enc = new SharedValueEncoder(options); 127 | // eslint-disable-next-line no-empty-function 128 | enc.on('data', () => {}); 129 | enc.on('error', reject); 130 | enc.on('finish', () => resolve(Buffer.concat(bufs))); 131 | enc.pushAny(obj); 132 | enc.stopRecording(); 133 | enc.removeAllListeners('data'); 134 | enc.on('data', buf => bufs.push(buf)); 135 | enc.pushAny(obj); 136 | enc.end(); 137 | }); 138 | } 139 | } 140 | 141 | module.exports = SharedValueEncoder; 142 | -------------------------------------------------------------------------------- /packages/cbor/lib/simple.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const {MT, SIMPLE, SYMS} = require('./constants'); 4 | 5 | /** 6 | * A CBOR Simple Value that does not map onto a known constant. 7 | */ 8 | class Simple { 9 | /** 10 | * Creates an instance of Simple. 11 | * 12 | * @param {number} value The simple value's integer value. 13 | */ 14 | constructor(value) { 15 | if (typeof value !== 'number') { 16 | throw new Error(`Invalid Simple type: ${typeof value}`); 17 | } 18 | if ((value < 0) || (value > 255) || ((value | 0) !== value)) { 19 | throw new Error(`value must be a small positive integer: ${value}`); 20 | } 21 | this.value = value; 22 | } 23 | 24 | /** 25 | * Debug string for simple value. 26 | * 27 | * @returns {string} Formated string of `simple(value)`. 28 | */ 29 | toString() { 30 | return `simple(${this.value})`; 31 | } 32 | 33 | /** 34 | * Debug string for simple value. 35 | * 36 | * @param {number} _depth How deep are we? 37 | * @param {object} _opts Options. 38 | * @returns {string} Formatted string of `simple(value)`. 39 | */ 40 | [Symbol.for('nodejs.util.inspect.custom')](_depth, _opts) { 41 | return `simple(${this.value})`; 42 | } 43 | 44 | /** 45 | * Push the simple value onto the CBOR stream. 46 | * 47 | * @param {object} gen The generator to push onto. 48 | * @returns {boolean} True on success. 49 | */ 50 | encodeCBOR(gen) { 51 | return gen._pushInt(this.value, MT.SIMPLE_FLOAT); 52 | } 53 | 54 | /** 55 | * Is the given object a Simple? 56 | * 57 | * @param {any} obj Object to test. 58 | * @returns {boolean} Is it Simple? 59 | */ 60 | static isSimple(obj) { 61 | return obj instanceof Simple; 62 | } 63 | 64 | /** 65 | * Decode from the CBOR additional information into a JavaScript value. 66 | * If the CBOR item has no parent, return a "safe" symbol instead of 67 | * `null` or `undefined`, so that the value can be passed through a 68 | * stream in object mode. 69 | * 70 | * @param {number} val The CBOR additional info to convert. 71 | * @param {boolean} [has_parent=true] Does the CBOR item have a parent? 72 | * @param {boolean} [parent_indefinite=false] Is the parent element 73 | * indefinitely encoded? 74 | * @returns {(null|undefined|boolean|symbol|Simple)} The decoded value. 75 | * @throws {Error} Invalid BREAK. 76 | */ 77 | static decode(val, has_parent = true, parent_indefinite = false) { 78 | switch (val) { 79 | case SIMPLE.FALSE: 80 | return false; 81 | case SIMPLE.TRUE: 82 | return true; 83 | case SIMPLE.NULL: 84 | if (has_parent) { 85 | return null; 86 | } 87 | return SYMS.NULL; 88 | case SIMPLE.UNDEFINED: 89 | if (has_parent) { 90 | return undefined; 91 | } 92 | return SYMS.UNDEFINED; 93 | case -1: 94 | if (!has_parent || !parent_indefinite) { 95 | throw new Error('Invalid BREAK'); 96 | } 97 | return SYMS.BREAK; 98 | default: 99 | return new Simple(val); 100 | } 101 | } 102 | } 103 | 104 | module.exports = Simple; 105 | -------------------------------------------------------------------------------- /packages/cbor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cbor", 3 | "version": "10.0.3", 4 | "description": "Encode and parse data in the Concise Binary Object Representation (CBOR) data format (RFC8949).", 5 | "main": "./lib/cbor.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 9 | "directory": "packages/cbor" 10 | }, 11 | "homepage": "https://github.com/hildjj/node-cbor/tree/main/packages/cbor", 12 | "directories": { 13 | "lib": "lib" 14 | }, 15 | "browser": { 16 | "fs": false 17 | }, 18 | "scripts": { 19 | "clean": "rimraf coverage .nyc_output/ docs", 20 | "lint": "eslint lib/*.js test/*.js", 21 | "coverage": "nyc -r lcov npm test", 22 | "test": "ava test/*.ava.js", 23 | "release": "npm version patch && git push --follow-tags && npm publish", 24 | "predev": "npm run coverage", 25 | "dev": "light-server -q -s. -w 'lib/*.js,test/*.js # npm run coverage' -o /coverage/lcov-report/index.html", 26 | "types": "tsc && npm run copy-types", 27 | "copy-types": "copyfiles \"./types/**\" \"../cbor-web/\"" 28 | }, 29 | "keywords": [ 30 | "coap", 31 | "cbor", 32 | "json", 33 | "rfc7049", 34 | "rfc8949" 35 | ], 36 | "author": { 37 | "name": "Joe Hildebrand", 38 | "email": "joe-github@cursive.net" 39 | }, 40 | "contributors": [ 41 | "Patrick Gansterer (http://paroga.com/)", 42 | "Artyom Yagilev (http://scorpi.org/)", 43 | "Denis Lapaev (http://lapaev.me/)", 44 | "Ruben Bridgewater ", 45 | "Burt Harris ", 46 | "Jakub Arbet (https://jakubarbet.me/)", 47 | "Rouzbeh Karimi (https://github.com/rouzwelt)" 48 | ], 49 | "types": "./types/lib/cbor.d.ts", 50 | "dependencies": { 51 | "nofilter": "^3.0.2" 52 | }, 53 | "devDependencies": { 54 | "@types/node": "^22", 55 | "bignumber.js": "^9.3.0", 56 | "garbage": "~0.0.0", 57 | "p-event": "^4.2.0", 58 | "rimraf": "5.0.10" 59 | }, 60 | "license": "MIT", 61 | "readmeFilename": "README.md", 62 | "engines": { 63 | "node": ">=20" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/cbor/test/commented.ava.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @stylistic/semi 2 | 'use strict' 3 | 4 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 5 | const test = require('ava'); 6 | const pEvent = require('p-event'); 7 | const util = require('node:util'); 8 | const cases = require('./cases'); 9 | const streams = require('./streams'); 10 | // Use mangled version 11 | const NoFilter = new cbor.Commented().all.constructor; 12 | const pcomment = util.promisify(cbor.comment); 13 | 14 | function testAll(t, list) { 15 | t.plan(list.length); 16 | return Promise.all( 17 | list.map( 18 | c => cbor.comment(cases.toBuffer(c)) 19 | .then(d => t.is(`\n${d}`, `${c[2]}\n`)) 20 | ) 21 | ); 22 | } 23 | 24 | function failAll(t, list) { 25 | t.plan(list.length); 26 | return Promise.all(list.map(c => t.throwsAsync( 27 | cbor.comment(cases.toBuffer(c)) 28 | ))); 29 | } 30 | 31 | test('good', async t => { 32 | await testAll(t, cases.good); 33 | }); 34 | test('encode', async t => { 35 | await testAll(t, cases.encodeGood); 36 | }); 37 | test('decode', async t => { 38 | await testAll(t, cases.decodeGood); 39 | }); 40 | test('fail', async t => { 41 | await failAll(t, cases.decodeBad); 42 | }); 43 | 44 | test('input_errors', async t => { 45 | t.throws(() => { 46 | cbor.comment(null, null); 47 | }); 48 | t.throws(() => { 49 | cbor.comment('00', true); 50 | }); 51 | await t.throwsAsync(cbor.comment('d8184181')); 52 | t.is(await cbor.comment('', null), ''); 53 | }); 54 | 55 | test('max_depth', async t => { 56 | const str = await pcomment('01', 2); 57 | t.is(str, `\ 58 | 01 -- 1 59 | 0x01 60 | `); 61 | }); 62 | 63 | test('stream', async t => { 64 | const bs = new NoFilter(); 65 | const parser = new cbor.Commented(); 66 | parser.pipe(bs); 67 | parser.on('error', er => t.fail(`Failed: ${er}`)); 68 | 69 | const h = new streams.DeHexStream('6161'); 70 | h.pipe(parser); 71 | 72 | await pEvent(parser, 'end'); 73 | t.is(bs.toString('utf8'), `\ 74 | 61 -- String, length: 1 75 | 61 -- "a" 76 | 0x6161 77 | `); 78 | }); 79 | 80 | test('function', async t => { 81 | const str = await pcomment('00'); 82 | t.is(str, `\ 83 | 00 -- 0 84 | 0x00 85 | `); 86 | }); 87 | 88 | test('inputs', async t => { 89 | let c = await cbor.comment( 90 | 'mB4AAQIDBAUGBwgJAAECAwQFBgcICQABAgMEBQYHCAk=', 91 | 'base64' 92 | ); 93 | t.is(c, `\ 94 | 98 -- Array, length next 1 byte 95 | 1e -- Array, 30 items 96 | 00 -- [0], 0 97 | 01 -- [1], 1 98 | 02 -- [2], 2 99 | 03 -- [3], 3 100 | 04 -- [4], 4 101 | 05 -- [5], 5 102 | 06 -- [6], 6 103 | 07 -- [7], 7 104 | 08 -- [8], 8 105 | 09 -- [9], 9 106 | 00 -- [10], 0 107 | 01 -- [11], 1 108 | 02 -- [12], 2 109 | 03 -- [13], 3 110 | 04 -- [14], 4 111 | 05 -- [15], 5 112 | 06 -- [16], 6 113 | 07 -- [17], 7 114 | 08 -- [18], 8 115 | 09 -- [19], 9 116 | 00 -- [20], 0 117 | 01 -- [21], 1 118 | 02 -- [22], 2 119 | 03 -- [23], 3 120 | 04 -- [24], 4 121 | 05 -- [25], 5 122 | 06 -- [26], 6 123 | 07 -- [27], 7 124 | 08 -- [28], 8 125 | 09 -- [29], 9 126 | 0x981e000102030405060708090001020304050607080900010203040506070809 127 | `); 128 | c = await cbor.comment('x\u001e012345678901234567890123456789', 129 | {encoding: 'utf8'}); 130 | t.is(c, `\ 131 | 78 -- String, length next 1 byte 132 | 1e -- String, length: 30 133 | 303132333435363738393031323334353637383930313233343536373839 -- "012345678901234567890123456789" 134 | 0x781e303132333435363738393031323334353637383930313233343536373839 135 | `); 136 | c = await cbor.comment('381d', {max_depth: 12}); 137 | t.is(c, `\ 138 | 38 -- Negative number, next 1 byte 139 | 1d -- -30 140 | 0x381d 141 | `); 142 | }); 143 | 144 | test('options', t => { 145 | function newTag24() { 146 | return null; 147 | } 148 | const c = new cbor.Commented({ 149 | tags: { 150 | 24: newTag24, 151 | }, 152 | }); 153 | t.is(c.parser.tags[24], newTag24); 154 | }); 155 | -------------------------------------------------------------------------------- /packages/cbor/test/diagnose.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 4 | const test = require('ava'); 5 | const pEvent = require('p-event'); 6 | const util = require('util'); 7 | const cases = require('./cases'); 8 | const pdiagnose = util.promisify(cbor.diagnose); 9 | // Use mangled versions 10 | const Buffer = cbor.encode(0).constructor; 11 | const NoFilter = new cbor.Commented().all.constructor; 12 | 13 | function testAll(t, list) { 14 | t.plan(list.length); 15 | return Promise.all( 16 | list.map( 17 | c => cbor.diagnose(cases.toBuffer(c)).then(d => t.is(d, `${c[1]}\n`)) 18 | ) 19 | ); 20 | } 21 | 22 | function failAll(t, list) { 23 | t.plan(list.length); 24 | return Promise.all(list.map(c => t.throwsAsync( 25 | cbor.diagnose(cases.toBuffer(c)) 26 | ))); 27 | } 28 | 29 | test('diagnose', async t => { 30 | await testAll(t, cases.good); 31 | }); 32 | test('decode', async t => { 33 | await testAll(t, cases.decodeGood); 34 | }); 35 | test('edges', async t => { 36 | await failAll(t, cases.decodeBad); 37 | }); 38 | 39 | test('construct', async t => { 40 | const d = new cbor.Diagnose(); 41 | t.is(d.stream_errors, false); 42 | d.stream_errors = true; 43 | const bs = new NoFilter(); 44 | d.pipe(bs); 45 | d.end(Buffer.from([0x18])); 46 | await pEvent(d, 'end'); 47 | t.is(bs.toString('utf8'), 'Error: unexpected end of input'); 48 | }); 49 | 50 | test('stream', async t => { 51 | const dt = new cbor.Diagnose({ 52 | separator: '-', 53 | }); 54 | const bs = new NoFilter(); 55 | dt.pipe(bs); 56 | dt.end(Buffer.from('01', 'hex')); 57 | await pEvent(dt, 'end'); 58 | t.is(bs.toString('utf8'), '1-'); 59 | }); 60 | 61 | test('inputs', async t => { 62 | t.throws(() => { 63 | cbor.diagnose(); 64 | }); 65 | const d = await pdiagnose('01'); 66 | t.truthy(d); 67 | const d2 = await cbor.diagnose('AQ==', {encoding: 'base64'}); 68 | t.truthy(d2); 69 | const d3 = await pdiagnose('AQ==', {encoding: 'base64'}); 70 | t.truthy(d3); 71 | }); 72 | 73 | test('async', async t => { 74 | let d = await cbor.diagnose('01', {}); 75 | t.is(d, '1\n'); 76 | d = await cbor.diagnose('01', 'hex'); 77 | t.is(d, '1\n'); 78 | }); 79 | 80 | test('stream errors', async t => { 81 | const d = await cbor.diagnose('01', { 82 | encoding: 'hex', 83 | stream_errors: true, 84 | }); 85 | t.is(d, '1\n'); 86 | }); 87 | 88 | test('static', async t => { 89 | t.throws(() => cbor.diagnose()); 90 | t.throws(() => cbor.diagnose('01', 12)); 91 | t.is(await cbor.diagnose('01', null), '1\n'); 92 | t.is(await cbor.diagnose('01', {encoding: null}), '1\n'); 93 | t.is(await cbor.diagnose('01', {encoding: undefined}), '1\n'); 94 | }); 95 | -------------------------------------------------------------------------------- /packages/cbor/test/garbage.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 5 | const garbage = require('garbage'); 6 | 7 | const REPEATS = parseInt(process.env.NODE_CBOR_GARBAGE || 10000, 10); 8 | test('garbage', t => { 9 | if (process.env.NO_GARBAGE) { 10 | t.pass(); 11 | return null; 12 | } 13 | t.plan(REPEATS); 14 | const inp = []; 15 | for (let i = 0; i < REPEATS; i++) { 16 | inp.push(garbage(100)); 17 | } 18 | return Promise.all(inp.map(async g => { 19 | const c = cbor.encode(g); 20 | const val = await cbor.decodeFirst(c); 21 | t.deepEqual(val, g); 22 | })); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/cbor/test/implementation_matrix.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 'use strict'; 3 | 4 | // Data to fill out: 5 | // https://github.com/cbor-wg/CBORbis/wiki/Implementation-matrix 6 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 7 | const Buffer = cbor.encode(0).constructor; 8 | const assert = require('assert'); 9 | 10 | const all = [ 11 | ['Major type 0 (uint)', 1, '01'], 12 | ['Major type 1 (nint)', -1, '20'], 13 | ['Major type 2 (bstr)', Buffer.from('0001', 'hex'), '420001'], 14 | ['Major type 3 (tstr)', 'foo', '63666f6f'], 15 | ['Major type 4 (array)', [0], '8100'], 16 | ['Major type 5 (map)', {a: 1}, 'a1616101'], 17 | ['Major type 6 (tag)', new cbor.Tagged(0xaa, 0), 'd8aa00'], 18 | ['Major type 7 (simple)', new cbor.Simple(0xaa), 'f8aa'], 19 | ['Float16', 0.5, 'f93800', true], 20 | ['Float32', 3.4028234663852886e+38, 'fa7f7fffff', true], 21 | ['Float64', 3002399751580330.5, 'fb4325555555555555'], 22 | // ['Indefinite length array/map', [], '9fff'], 23 | // ['Indefinite length string', 'streaming', '7f657374726561646d696e67ff'], 24 | ['Canonical CBOR', {b: 1, a: 2}, 'a2616102616201', true], // Note: re-ordering 25 | ['Tag 0', 26 | new Date(1500000000000), // 2017-07-14T02:40:00.000Z 27 | 'c07818323031372d30372d31345430323a34303a30302e3030305a', 28 | false, 29 | 'string'], 30 | ['Tag 1', new Date(1500000000000), 'c11a59682f00', false, 'number'], 31 | ['Tag 2', 18446744073709551616n, 'c249010000000000000000'], 32 | ['Tag 3', -18446744073709551617n, 'c349010000000000000000'], 33 | // Didn't implement because I continue to think they're not useful 34 | ['Tag 21', 0, ''], 35 | ['Tag 22', 0, ''], 36 | ['Tag 23', 0, ''], 37 | // This one is only useful in certain circumstances 38 | ['Tag 24', 0, ''], 39 | ['Tag 32', 40 | new URL('https://mozilla.com/'), 41 | 'd8207468747470733a2f2f6d6f7a696c6c612e636f6d2f'], 42 | ['Tag 33', 0, ''], 43 | ['Tag 34', 0, ''], 44 | ['Tag 35', /foo/, 'd82363666f6f'], 45 | ['Tag 36', 0, ''], 46 | ['Tag 55799', 0, ''], 47 | ]; 48 | 49 | function deepEqual(actual, expected) { 50 | assert.deepEqual(actual, expected); 51 | return true; 52 | } 53 | 54 | function markdownOut(title, decode, encode) { 55 | const DE = (decode ? 'D' : ' ') + (encode ? 'E' : ' '); 56 | console.log( 57 | `| ${title.padEnd(28)}| | ${DE} | | |` 58 | ); 59 | } 60 | 61 | // eslint-disable-next-line max-params 62 | function test(title, native, encoded, canonical, dateType) { 63 | if (encoded.length > 0) { 64 | const e = cbor.Encoder.encodeOne(native, { 65 | canonical, 66 | dateType, 67 | }); 68 | const d = cbor.decodeFirstSync(encoded); 69 | markdownOut( 70 | title, 71 | deepEqual(native, d), 72 | deepEqual(e, Buffer.from(encoded, 'hex')) 73 | ); 74 | } else { 75 | markdownOut(title); 76 | } 77 | } 78 | 79 | for (const t of all) { 80 | test(...t); 81 | } 82 | -------------------------------------------------------------------------------- /packages/cbor/test/map.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 4 | const test = require('ava'); 5 | const cases = require('./cases'); 6 | 7 | test('create', t => { 8 | const m = new cbor.Map(); 9 | t.truthy(m instanceof Map); 10 | }); 11 | 12 | test('basic', t => { 13 | const m = new cbor.Map(); 14 | t.is(m.size, 0); 15 | m.set(1, 2); 16 | m.set(3, 4); 17 | t.is(m.size, 2); 18 | t.is(m.get(1), 2); 19 | t.is(m.get(3), 4); 20 | t.truthy(m.has(1)); 21 | t.truthy(m.has(3)); 22 | t.falsy(m.has(8)); 23 | t.deepEqual(Array.from(m.keys()), [1, 3]); 24 | t.deepEqual(Array.from(m.entries()), [[1, 2], [3, 4]]); 25 | 26 | t.is(m.delete(1), true); 27 | t.is(m.delete(1), false); 28 | t.is(m.size, 1); 29 | t.falsy(m.has(1)); 30 | t.deepEqual(Array.from(m.keys()), [3]); 31 | for (const [k, v] of m) { // [Symbol.iterator] 32 | t.is(k, 3); 33 | t.is(v, 4); 34 | } 35 | m.forEach((v, k, n) => { 36 | t.is(k, 3); 37 | t.is(v, 4); 38 | t.is(k, 3); 39 | t.is(n, m); 40 | }); 41 | }); 42 | 43 | test('errors', t => { 44 | const m = new cbor.Map([[1, 2], [3, 4]]); 45 | t.is(m.size, 2); 46 | t.throws(() => { 47 | m.forEach(); 48 | }); 49 | t.throws(() => { 50 | m.forEach('boo'); 51 | }); 52 | }); 53 | 54 | test('complex', t => { 55 | const m = new cbor.Map([[[], 2], [[], 4]]); 56 | t.is(m.size, 1); 57 | t.is(m.get([]), 4); 58 | }); 59 | 60 | test('encode', t => { 61 | const m = new cbor.Map([ 62 | [false, true], 63 | [1, 'one'], 64 | [0, 'hi'], 65 | [-1, 'neg'], 66 | [[0, 1], 'array'], 67 | [{a: 1, b: 2}, 'map'], 68 | ]); 69 | const buf = cbor.encode(m); 70 | t.is(buf.toString('hex'), 71 | 'a6f4f501636f6e650062686920636e6567820001656172726179a2616101616202636d6170'); 72 | const bufCanon = cbor.encodeCanonical(m); 73 | t.is(bufCanon.toString('hex'), 74 | 'a60062686901636f6e6520636e6567820001656172726179a2616101616202636d6170f4f5'); 75 | }); 76 | 77 | test('encodefail', t => { 78 | const m = new cbor.Map([ 79 | [false, true], 80 | [1, 'one'], 81 | [0, 'hi'], 82 | [-1, 'neg'], 83 | [[0, 1], 'array'], 84 | [{a: 1, b: 2}, 'map'], 85 | ]); 86 | cases.EncodeFailer.tryAll(t, m); 87 | cases.EncodeFailer.tryAll(t, m, true); 88 | }); 89 | -------------------------------------------------------------------------------- /packages/cbor/test/objectRecorder.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const ObjectRecorder = require('../lib/objectRecorder'); 5 | 6 | test('create', t => { 7 | const o = new ObjectRecorder(); 8 | t.truthy(o); 9 | t.is(o.check({}), ObjectRecorder.NEVER); 10 | const a = {}; 11 | const b = {}; 12 | t.is(o.check(a), ObjectRecorder.NEVER); 13 | t.is(o.check(a), 0); 14 | t.is(o.check(b), ObjectRecorder.NEVER); 15 | o.stop(); 16 | t.is(o.check(a), ObjectRecorder.FIRST); 17 | t.is(o.check(a), 0); 18 | t.is(o.check(b), ObjectRecorder.NEVER); 19 | t.throws(() => o.check({})); 20 | o.clear(); 21 | t.is(o.check(a), ObjectRecorder.NEVER); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/cbor/test/plugins.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const cbor_src = process.env.CBOR_PACKAGE || '../'; 4 | const cbor = require(cbor_src); 5 | const test = require('ava'); 6 | 7 | test('reset', t => { 8 | cbor.Encoder.SEMANTIC_TYPES.UNKNOWN_TYPE = () => null; 9 | cbor.reset(); 10 | t.is(cbor.Encoder.SEMANTIC_TYPES.UNKNOWN_TYPE, undefined); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/cbor/test/sharedValueEncoder.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const SharedValueEncoder = require('../lib/sharedValueEncoder'); 5 | const {Buffer} = require('buffer'); 6 | 7 | test('create SVE', async t => { 8 | const a = {}; 9 | a.b = a; 10 | 11 | const sve = new SharedValueEncoder(); 12 | t.truthy(sve); 13 | // eslint-disable-next-line no-empty-function 14 | sve.on('data', () => {}); 15 | sve.pushAny(a); 16 | sve.stopRecording(); 17 | let bufs = []; 18 | sve.on('data', b => bufs.push(b)); 19 | sve.pushAny(a); 20 | t.is(Buffer.concat(bufs).toString('hex'), 'd81ca16162d81d00'); 21 | bufs = []; 22 | sve.clearRecording(); 23 | sve.pushAny(a); 24 | t.is(Buffer.concat(bufs).toString('hex'), 'a16162d81d00'); 25 | 26 | t.is(SharedValueEncoder.encode(a).toString('hex'), 'd81ca16162d81d00'); 27 | t.is(SharedValueEncoder.encode(null).toString('hex'), 'f6'); 28 | 29 | const buf = await SharedValueEncoder.encodeAsync(a); 30 | t.is(buf.toString('hex'), 'd81ca16162d81d00'); 31 | 32 | t.is(SharedValueEncoder.encodeOne(a).toString('hex'), 'd81ca16162d81d00'); 33 | 34 | t.throws(() => SharedValueEncoder.encodeCanonical(a)); 35 | }); 36 | -------------------------------------------------------------------------------- /packages/cbor/test/simple.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 5 | const constants = require('../lib/constants'); 6 | 7 | test('create', t => { 8 | const u = new cbor.Simple(0); 9 | t.is(u.value, 0); 10 | 11 | t.is(cbor.Simple.isSimple(u), true); 12 | t.is(cbor.Simple.isSimple('foo'), false); 13 | t.is(u.toString(), 'simple(0)'); 14 | 15 | t.throws(() => new cbor.Simple('0')); 16 | t.throws(() => new cbor.Simple(-1)); 17 | t.throws(() => new cbor.Simple(256)); 18 | t.throws(() => new cbor.Simple(1.1)); 19 | }); 20 | 21 | test('decode', t => { 22 | t.is(cbor.Simple.decode(constants.SIMPLE.NULL), null); 23 | t.is(typeof (cbor.Simple.decode(constants.SIMPLE.UNDEFINED)), 'undefined'); 24 | t.throws(() => cbor.Simple.decode(-1, false)); 25 | }); 26 | 27 | test('inspect', t => { 28 | const u = new cbor.Simple(0); 29 | t.is(u[Symbol.for('nodejs.util.inspect.custom')](), 'simple(0)'); 30 | }); 31 | -------------------------------------------------------------------------------- /packages/cbor/test/streams.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const stream = require('stream'); 4 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 5 | const Buffer = cbor.encode(0).constructor; 6 | 7 | exports.DeHexStream = class DeHexStream extends stream.Readable { 8 | constructor(hex) { 9 | super(); 10 | hex = hex.replace(/^0x/, ''); 11 | if (hex) { 12 | this.push(Buffer.from(hex, 'hex')); 13 | } 14 | this.push(null); 15 | } 16 | }; 17 | 18 | exports.HexStream = class HexStream extends stream.Transform { 19 | constructor(options) { 20 | super(options); 21 | } 22 | 23 | _transform(fresh, _encoding, cb) { 24 | this.push(fresh.toString('hex')); 25 | return cb(); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /packages/cbor/test/tagged.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 5 | const Buffer = cbor.encode(0).constructor; 6 | 7 | test('create', t => { 8 | const tag = new cbor.Tagged(1, 'one'); 9 | t.truthy(tag); 10 | t.is(tag.tag, 1); 11 | t.is(tag.value, 'one'); 12 | t.is(tag.toString(), '1("one")'); 13 | 14 | t.is(cbor.encode(tag).toString('hex'), 'c1636f6e65'); 15 | }); 16 | 17 | test('edges', t => { 18 | t.throws(() => new cbor.Tagged(-11, 'one')); 19 | t.throws(() => new cbor.Tagged(1.1, 'one')); 20 | t.throws(() => new cbor.Tagged('zero', 'one')); 21 | }); 22 | 23 | test('convert', t => { 24 | const tag = new cbor.Tagged(2, Buffer.from([2])); 25 | t.deepEqual(tag.convert(), BigInt(2)); 26 | }); 27 | 28 | test('tag 21', t => { 29 | let tag = new cbor.Tagged(21, Buffer.from('foo')).convert(); 30 | t.is(JSON.stringify(tag), '"Zm9v"'); 31 | tag = new cbor.Tagged(21, [Buffer.from('fo')]).convert(); 32 | t.is(JSON.stringify(tag), '{"tag":21,"value":["Zm8"]}'); 33 | tag = new cbor.Tagged(21, [{a: Buffer.from('f')}]).convert(); 34 | t.is(JSON.stringify(tag), '{"tag":21,"value":[{"a":"Zg"}]}'); 35 | 36 | tag = new cbor.Tagged(21, [ 37 | {a: new cbor.Tagged(22, Buffer.from('f')).convert()}, 38 | ]).convert(); 39 | t.is(JSON.stringify(tag), '{"tag":21,"value":[{"a":"Zg=="}]}'); 40 | tag = new cbor.Tagged(21, 12).convert(); 41 | t.is(JSON.stringify(tag), '{"tag":21,"value":12}'); 42 | 43 | tag = new cbor.Tagged(1, 2, 'this is an error'); 44 | t.is(JSON.stringify(tag), '{"tag":1,"value":2,"err":"this is an error"}'); 45 | }); 46 | 47 | test('tag 22', t => { 48 | let tag = new cbor.Tagged(22, Buffer.from('fo')).convert(); 49 | t.is(JSON.stringify(tag), '"Zm8="'); 50 | tag = new cbor.Tagged(22, [Buffer.from('fo')]).convert(); 51 | t.is(JSON.stringify(tag), '{"tag":22,"value":["Zm8="]}'); 52 | tag = new cbor.Tagged(22, [{a: Buffer.from('f')}]).convert(); 53 | t.is(JSON.stringify(tag), '{"tag":22,"value":[{"a":"Zg=="}]}'); 54 | }); 55 | 56 | test('tag 23', t => { 57 | let tag = new cbor.Tagged(23, Buffer.from('fo')).convert(); 58 | t.is(JSON.stringify(tag), '"666f"'); 59 | tag = new cbor.Tagged(23, [Buffer.from('fo')]).convert(); 60 | t.is(JSON.stringify(tag), '{"tag":23,"value":["666f"]}'); 61 | tag = new cbor.Tagged(23, [{a: Buffer.from('f')}]).convert(); 62 | t.is(JSON.stringify(tag), '{"tag":23,"value":[{"a":"66"}]}'); 63 | }); 64 | 65 | test('tag 33', t => { 66 | let tag = new cbor.Tagged(33, ';;').convert(); 67 | t.truthy(tag.err); 68 | tag = new cbor.Tagged(33, 'A').convert(); 69 | t.truthy(tag.err); 70 | tag = new cbor.Tagged(33, 'AB').convert(); 71 | t.truthy(tag.err); 72 | tag = new cbor.Tagged(33, 'AA').convert(); 73 | t.falsy(tag.err); 74 | tag = new cbor.Tagged(33, 'AAq').convert(); 75 | t.truthy(tag.err); 76 | tag = new cbor.Tagged(33, 'AAA').convert(); 77 | t.falsy(tag.err); 78 | tag = new cbor.Tagged(33, 'AAAA').convert(); 79 | t.falsy(tag.err); 80 | }); 81 | 82 | test('tag 34', t => { 83 | let tag = new cbor.Tagged(34, ';;').convert(); 84 | t.truthy(tag.err); 85 | tag = new cbor.Tagged(34, '====').convert(); 86 | t.truthy(tag.err); 87 | tag = new cbor.Tagged(34, 'A').convert(); 88 | t.truthy(tag.err); 89 | tag = new cbor.Tagged(34, 'AB==').convert(); 90 | t.truthy(tag.err); 91 | tag = new cbor.Tagged(34, 'AA==').convert(); 92 | t.falsy(tag.err); 93 | tag = new cbor.Tagged(34, 'AAq=').convert(); 94 | t.truthy(tag.err); 95 | tag = new cbor.Tagged(34, 'AAA=').convert(); 96 | t.falsy(tag.err); 97 | tag = new cbor.Tagged(34, 'AAAA').convert(); 98 | t.falsy(tag.err); 99 | }); 100 | 101 | test('converters', t => { 102 | let res = new cbor.Tagged(1, 1).convert({ 103 | 1() { 104 | throw new Error(); 105 | }, 106 | }); 107 | t.truthy(res.err instanceof Error); 108 | res = new cbor.Tagged(1, 1).convert({ 109 | 1() { 110 | const e = new Error(); 111 | delete e.message; 112 | throw e; 113 | }, 114 | }); 115 | t.truthy(res.err instanceof Error); 116 | }); 117 | 118 | test('Typed Arrays', t => { 119 | let tag = new cbor.Tagged(64, 'foo'); 120 | tag.convert(); 121 | t.is(tag.err, 'val not a buffer'); 122 | tag = new cbor.Tagged(90, 'foo'); 123 | 124 | const {64: toTypedArray} = cbor.Tagged.TAGS; 125 | t.throws(() => toTypedArray(tag.value, tag)); 126 | tag = new cbor.Tagged(76, 'foo'); 127 | t.throws(() => toTypedArray(tag.value, tag)); 128 | tag = new cbor.Tagged(90, Buffer.from('000100020003', 'hex')); 129 | t.throws(() => toTypedArray(tag.value, tag)); 130 | 131 | // Endian 132 | tag = new cbor.Tagged(65, Buffer.from('000100020003', 'hex')); 133 | t.deepEqual(toTypedArray(tag.value, tag), new Uint16Array([1, 2, 3])); 134 | 135 | tag = new cbor.Tagged(68, Buffer.from('010203', 'hex')); 136 | t.deepEqual(toTypedArray(tag.value, tag), new Uint8ClampedArray([1, 2, 3])); 137 | 138 | tag = new cbor.Tagged(73, Buffer.from('000100020003', 'hex')); 139 | t.deepEqual(toTypedArray(tag.value, tag), new Int16Array([1, 2, 3])); 140 | }); 141 | 142 | test('null converter', t => { 143 | const buf = Buffer.from('c100', 'hex'); 144 | t.deepEqual(cbor.decode(buf), new Date(0)); 145 | t.deepEqual(cbor.decode(buf, {tags: {1: null}}), new cbor.Tagged(1, 0)); 146 | }); 147 | -------------------------------------------------------------------------------- /packages/cbor/test/test-vectors.ava.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 'use strict'; 3 | const cbor = require(process.env.CBOR_PACKAGE || '../'); 4 | const test = require('ava'); 5 | const util = require('util'); 6 | const fs = require('fs'); 7 | const path = require('path'); 8 | const Buffer = cbor.encode(0).constructor; 9 | const readFile = util.promisify ? 10 | util.promisify(fs.readFile) : 11 | (...args) => new Promise((resolve, reject) => { 12 | fs.readFile(...args, (er, res) => (er ? reject(er) : resolve(res))); 13 | }); 14 | 15 | let vectors = null; 16 | let failures = null; 17 | 18 | test.before(async t => { 19 | // Read tests in. Edit them to make the big integers come out correctly. 20 | let vecStr = null; 21 | const vectorDir = path.resolve( 22 | __dirname, '..', '..', '..', 'test-vectors' 23 | ); 24 | const appendix_a = path.join(vectorDir, 'appendix_a.json'); 25 | try { 26 | vecStr = await readFile(appendix_a, {encoding: 'utf8'}); 27 | } catch (ignored) { 28 | t.fail(`"${appendix_a}" not found. 29 | use command \`git submodule update --init\` to load test-vectors`); 30 | return; 31 | } 32 | 33 | // HACK: don't lose data when JSON parsing 34 | vecStr = vecStr.replace( 35 | /"decoded":\s*(?-?\d+(?:\.\d+)?(?:e[+-]\d+)?)\r?\n/g, 36 | `"decoded": { 37 | "___TYPE___": "number", 38 | "___VALUE___": "$" 39 | }` 40 | ); 41 | vectors = JSON.parse(vecStr, (_key, value) => { 42 | if (!value) { 43 | return value; 44 | } 45 | if (value.___TYPE___ === 'number') { 46 | const v = value.___VALUE___; 47 | const f = Number.parseFloat(v); 48 | try { 49 | const bi = BigInt(v); 50 | if ((bi > Number.MAX_SAFE_INTEGER) || (bi < Number.MIN_SAFE_INTEGER)) { 51 | return bi; 52 | } 53 | } catch (ignored) { 54 | // Ignored 55 | } 56 | return f; 57 | } 58 | return value; 59 | }); 60 | 61 | let failStr = null; 62 | const fail = path.join(vectorDir, 'fail.json'); 63 | try { 64 | failStr = await readFile(fail, {encoding: 'utf8'}); 65 | } catch (ignored) { 66 | t.fail(`"${fail}" not found. 67 | use command \`git submodule update --init\` to load test-vectors`); 68 | return; 69 | } 70 | failures = JSON.parse(failStr); 71 | }); 72 | 73 | test('vectors', t => { 74 | t.truthy(Array.isArray(vectors)); 75 | for (const v of vectors) { 76 | t.truthy(v.hex); 77 | const buffer = Buffer.from(v.hex, 'hex'); 78 | 79 | let decoded = null; 80 | try { 81 | decoded = cbor.decode(buffer); 82 | } catch (e) { 83 | console.log('DECODE ERROR', buffer.toString('hex')); 84 | throw e; 85 | } 86 | const encoded = cbor.encodeCanonical(decoded); 87 | const redecoded = cbor.decode(encoded); 88 | 89 | t.truthy(Object.prototype.hasOwnProperty.call(v, 'cbor')); 90 | t.deepEqual( 91 | Buffer.from(v.cbor, 'base64'), 92 | buffer, 93 | 'base64 and hex encoded bytes mismatched ' 94 | ); 95 | 96 | if (decoded && (typeof decoded === 'object')) { 97 | delete decoded[cbor.Tagged.INTERNAL_JSON]; 98 | delete redecoded[cbor.Tagged.INTERNAL_JSON]; 99 | } 100 | t.deepEqual( 101 | decoded, 102 | redecoded, 103 | `round trip error: ${v.hex} -> ${encoded.toString('hex')}` 104 | ); 105 | 106 | if (Object.prototype.hasOwnProperty.call(v, 'diagnostic')) { 107 | cbor.diagnose(buffer) 108 | .then(d => t.deepEqual( 109 | d.trim().replace(/_\d+(?$|\))/, '$'), 110 | v.diagnostic 111 | )); 112 | } 113 | 114 | if (Object.prototype.hasOwnProperty.call(v, 'decoded')) { 115 | t.deepEqual(decoded, v.decoded, `Hex: "${v.hex}"`); 116 | 117 | if (v.roundtrip) { 118 | // TODO: Don't know how to make these round-trip. See: 119 | // https://github.com/cbor/test-vectors/issues/3 120 | if ([ 121 | 'f90000', 122 | 'f93c00', 123 | 'f97bff', 124 | 'fa47c35000', 125 | 'f9c400', 126 | ].indexOf(v.hex) === -1) { 127 | t.deepEqual(encoded.toString('hex'), v.hex); 128 | } else { 129 | // Trigger if assumptions change 130 | t.notDeepEqual(encoded, buffer); 131 | } 132 | } 133 | } 134 | } 135 | }); 136 | 137 | test('errors', async t => { 138 | t.plan(failures.length); 139 | for (const f of failures) { 140 | await t.throwsAsync(async _ => { 141 | await cbor.decodeAll(f.hex, 'hex'); 142 | console.log('NO THROW', f); 143 | }); 144 | } 145 | }); 146 | -------------------------------------------------------------------------------- /packages/cbor/test/utils.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const utils = require('../lib/utils'); 5 | const {lbe} = require('./cases'); 6 | const {hex, bin} = utils; 7 | const {Buffer} = require('buffer'); // NOT the mangled version 8 | 9 | test('bin', t => { 10 | t.deepEqual(utils.bin('1'), hex('01')); 11 | t.deepEqual(utils.bin('11'), hex('03')); 12 | t.deepEqual(utils.bin('1100 0000 0000'), hex('0c00')); 13 | }); 14 | 15 | test('parseCBORint', t => { 16 | t.is(utils.parseCBORint(24, hex('ff')), 255); 17 | t.is(utils.parseCBORint(25, hex('ffff')), 65535); 18 | t.is(utils.parseCBORint(26, hex('00010000')), 65536); 19 | t.is(utils.parseCBORint(27, hex('0000000100000000')), 4294967296); 20 | t.throws(() => { 21 | utils.parseCBORint(28, hex('ff')); 22 | }); 23 | t.throws(() => { 24 | utils.parseCBORint(27, hex('ff')); 25 | }); 26 | }); 27 | 28 | test('parseCBORfloat', t => { 29 | t.is(utils.parseCBORfloat(bin('0 00000 0000000000')), 0); 30 | t.is(utils.parseCBORfloat(bin('0 00000000 00000000000000000000000')), 31 | 0); 32 | t.is(utils.parseCBORfloat(bin( 33 | '0 00000000000 0000000000000000000000000000000000000000000000000000' 34 | )), 0); 35 | t.throws(() => { 36 | utils.parseCBORfloat(hex('ff')); 37 | }); 38 | t.throws(() => { 39 | utils.parseCBORfloat(hex('ff')); 40 | }); 41 | }); 42 | 43 | test('parseHalf', t => { 44 | t.is(utils.parseHalf(bin('0 01111 0000000000')), 1); 45 | t.deepEqual(utils.parseHalf(bin('1 10000 0000000000')), -2); 46 | t.is(utils.parseHalf(bin('0 11110 1111111111')), 65504); 47 | t.is(utils.parseHalf(bin('0 00001 0000000000')), 0.00006103515625); 48 | t.is(utils.parseHalf(bin('0 00000 0000000000')), 0); 49 | t.deepEqual(utils.parseHalf(bin('1 00000 0000000000')), -0); 50 | t.deepEqual(utils.parseHalf(bin('0 11111 0000000000')), Infinity); 51 | t.deepEqual(utils.parseHalf(bin('1 11111 0000000000')), -Infinity); 52 | }); 53 | 54 | test('arrayEqual', t => { 55 | t.is(utils.arrayEqual(), true); 56 | t.is(utils.arrayEqual([]), false); 57 | t.is(utils.arrayEqual([], []), true); 58 | t.is(utils.arrayEqual([1], []), false); 59 | t.is(utils.arrayEqual([1, 2, 3], [1, 2, 3]), true); 60 | t.is(utils.arrayEqual([1, 2, 3], [1, 2, 4]), false); 61 | }); 62 | 63 | test('guessEncoding', t => { 64 | const buf = Buffer.from('0102', 'hex'); 65 | const nof = utils.guessEncoding( 66 | buf.buffer.slice(buf.offset, buf.offset + buf.length) 67 | ); 68 | t.is(nof.read().toString('hex'), '0102'); 69 | const ab = new ArrayBuffer(256); 70 | const u16 = new Uint16Array(ab, 100, 3); 71 | u16[0] = 512; 72 | u16[1] = 256; 73 | u16[2] = 1; 74 | const nof2 = utils.guessEncoding(u16); 75 | t.is(nof2.read().toString('hex'), lbe('000200010100', '020001000001')); 76 | t.throws(() => utils.guessEncoding()); 77 | }); 78 | 79 | test('cborValueToString', t => { 80 | // eslint-disable-next-line symbol-description 81 | t.is(utils.cborValueToString(Symbol()), 'Symbol'); 82 | t.is(utils.cborValueToString(Symbol(')')), ')'); 83 | t.is(utils.cborValueToString(Symbol('))')), '))'); 84 | t.is(utils.cborValueToString(Symbol('(()')), '(()'); 85 | t.is(utils.cborValueToString(Symbol('foo')), 'foo'); 86 | t.is(utils.cborValueToString(Symbol('')), 'Symbol'); 87 | }); 88 | -------------------------------------------------------------------------------- /packages/cbor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["lib/*.js", "vendor/**/*.js"], 3 | 4 | "compilerOptions": { 5 | "allowJs": true, 6 | "checkJs": true, 7 | "declaration": true, 8 | "emitDeclarationOnly": true, 9 | "strict": false, 10 | "moduleResolution": "node", 11 | "outDir": "types", 12 | "target": "ES2020" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/cbor.d.ts: -------------------------------------------------------------------------------- 1 | import Commented = require("./commented"); 2 | import Diagnose = require("./diagnose"); 3 | import Decoder = require("./decoder"); 4 | import Encoder = require("./encoder"); 5 | import Simple = require("./simple"); 6 | import Tagged = require("./tagged"); 7 | import Map = require("./map"); 8 | import SharedValueEncoder = require("./sharedValueEncoder"); 9 | export declare let comment: typeof import("./commented").comment; 10 | export declare let decodeAll: typeof import("./decoder").decodeAll; 11 | export declare let decodeFirst: typeof import("./decoder").decodeFirst; 12 | export declare let decodeAllSync: typeof import("./decoder").decodeAllSync; 13 | export declare let decodeFirstSync: typeof import("./decoder").decodeFirstSync; 14 | export declare let diagnose: typeof import("./diagnose").diagnose; 15 | export declare let encode: typeof import("./encoder").encode; 16 | export declare let encodeCanonical: typeof import("./encoder").encodeCanonical; 17 | export declare let encodeOne: typeof import("./encoder").encodeOne; 18 | export declare let encodeAsync: typeof import("./encoder").encodeAsync; 19 | export declare let decode: typeof import("./decoder").decodeFirstSync; 20 | export declare namespace leveldb { 21 | let decode_1: typeof Decoder.decodeFirstSync; 22 | export { decode_1 as decode }; 23 | let encode_1: typeof Encoder.encode; 24 | export { encode_1 as encode }; 25 | export let buffer: boolean; 26 | export let name: string; 27 | } 28 | /** 29 | * Reset everything that we can predict a plugin might have altered in good 30 | * faith. For now that includes the default set of tags that decoding and 31 | * encoding will use. 32 | */ 33 | export declare function reset(): void; 34 | export { Commented, Diagnose, Decoder, Encoder, Simple, Tagged, Map, SharedValueEncoder }; 35 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/commented.d.ts: -------------------------------------------------------------------------------- 1 | export = Commented; 2 | /** 3 | * Generate the expanded format of RFC 8949, section 3.2.2. 4 | * 5 | * @extends stream.Transform 6 | */ 7 | declare class Commented extends stream.Transform { 8 | /** 9 | * Comment on an input Buffer or string, creating a string passed to the 10 | * callback. If callback not specified, a promise is returned. 11 | * 12 | * @param {string|Buffer|ArrayBuffer|Uint8Array|Uint8ClampedArray 13 | * |DataView|stream.Readable} input Something to parse. 14 | * @param {CommentOptions|commentCallback|string|number} [options={}] 15 | * Encoding, max_depth, or callback. 16 | * @param {commentCallback} [cb] If specified, called on completion. 17 | * @returns {Promise} If cb not specified. 18 | * @throws {Error} Input required. 19 | * @static 20 | */ 21 | static comment(input: string | Buffer | ArrayBuffer | Uint8Array | Uint8ClampedArray | DataView | stream.Readable, options?: CommentOptions | commentCallback | string | number, cb?: commentCallback): Promise; 22 | /** 23 | * Create a CBOR commenter. 24 | * 25 | * @param {CommentOptions} [options={}] Stream options. 26 | */ 27 | constructor(options?: CommentOptions); 28 | depth: number; 29 | max_depth: number; 30 | all: NoFilter; 31 | parser: Decoder; 32 | /** 33 | * @param {Buffer} v Descend into embedded CBOR. 34 | * @private 35 | */ 36 | private _tag_24; 37 | /** 38 | * @ignore 39 | */ 40 | _on_error(er: any): void; 41 | /** 42 | * @ignore 43 | */ 44 | _on_read(buf: any): void; 45 | /** 46 | * @ignore 47 | */ 48 | _on_more(mt: any, len: any, parent_mt: any, pos: any): void; 49 | /** 50 | * @ignore 51 | */ 52 | _on_start_string(mt: any, len: any, parent_mt: any, pos: any): void; 53 | /** 54 | * @ignore 55 | */ 56 | _on_start(mt: any, tag: any, parent_mt: any, pos: any): void; 57 | /** 58 | * @ignore 59 | */ 60 | _on_stop(mt: any): void; 61 | /** 62 | * @private 63 | */ 64 | private _on_value; 65 | /** 66 | * @ignore 67 | */ 68 | _on_data(): void; 69 | } 70 | declare namespace Commented { 71 | export { CommentOptions, commentCallback }; 72 | } 73 | import stream = require("stream"); 74 | import NoFilter = require("nofilter"); 75 | import Decoder = require("./decoder"); 76 | import { Buffer } from "buffer"; 77 | type CommentOptions = { 78 | /** 79 | * How many times to indent 80 | * the dashes. 81 | */ 82 | max_depth?: number; 83 | /** 84 | * Initial indentation depth. 85 | */ 86 | depth?: number; 87 | /** 88 | * If true, omit the summary 89 | * of the full bytes read at the end. 90 | */ 91 | no_summary?: boolean; 92 | /** 93 | * Mapping from tag number to function(v), 94 | * where v is the decoded value that comes after the tag, and where the 95 | * function returns the correctly-created value for that tag. 96 | */ 97 | tags?: object; 98 | /** 99 | * If true, prefer Uint8Arrays to 100 | * be generated instead of node Buffers. This might turn on some more 101 | * changes in the future, so forward-compatibility is not guaranteed yet. 102 | */ 103 | preferWeb?: boolean; 104 | /** 105 | * Encoding to use for input, if it 106 | * is a string. 107 | */ 108 | encoding?: BufferEncoding; 109 | }; 110 | type commentCallback = (error?: Error, commented?: string) => void; 111 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/constants.d.ts: -------------------------------------------------------------------------------- 1 | export namespace MT { 2 | let POS_INT: number; 3 | let NEG_INT: number; 4 | let BYTE_STRING: number; 5 | let UTF8_STRING: number; 6 | let ARRAY: number; 7 | let MAP: number; 8 | let TAG: number; 9 | let SIMPLE_FLOAT: number; 10 | } 11 | export type MT = number; 12 | export namespace TAG { 13 | let DATE_STRING: number; 14 | let DATE_EPOCH: number; 15 | let POS_BIGINT: number; 16 | let NEG_BIGINT: number; 17 | let DECIMAL_FRAC: number; 18 | let BIGFLOAT: number; 19 | let BASE64URL_EXPECTED: number; 20 | let BASE64_EXPECTED: number; 21 | let BASE16_EXPECTED: number; 22 | let CBOR: number; 23 | let URI: number; 24 | let BASE64URL: number; 25 | let BASE64: number; 26 | let REGEXP: number; 27 | let MIME: number; 28 | let SET: number; 29 | } 30 | export type TAG = number; 31 | export namespace NUMBYTES { 32 | let ZERO: number; 33 | let ONE: number; 34 | let TWO: number; 35 | let FOUR: number; 36 | let EIGHT: number; 37 | let INDEFINITE: number; 38 | } 39 | export type NUMBYTES = number; 40 | export namespace SIMPLE { 41 | let FALSE: number; 42 | let TRUE: number; 43 | let NULL: number; 44 | let UNDEFINED: number; 45 | } 46 | export type SIMPLE = number; 47 | export namespace SYMS { 48 | let NULL_1: symbol; 49 | export { NULL_1 as NULL }; 50 | let UNDEFINED_1: symbol; 51 | export { UNDEFINED_1 as UNDEFINED }; 52 | export let PARENT: symbol; 53 | export let BREAK: symbol; 54 | export let STREAM: symbol; 55 | } 56 | export const SHIFT32: 4294967296; 57 | export namespace BI { 58 | let MINUS_ONE: bigint; 59 | let NEG_MAX: bigint; 60 | let MAXINT32: bigint; 61 | let MAXINT64: bigint; 62 | let SHIFT32: bigint; 63 | } 64 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/diagnose.d.ts: -------------------------------------------------------------------------------- 1 | export = Diagnose; 2 | /** 3 | * Output the diagnostic format from a stream of CBOR bytes. 4 | * 5 | * @extends stream.Transform 6 | */ 7 | declare class Diagnose extends stream.Transform { 8 | /** 9 | * Convenience function to return a string in diagnostic format. 10 | * 11 | * @param {BufferLike} input The CBOR bytes to format. 12 | * @param {DiagnoseOptions |diagnoseCallback|string} [options={}] 13 | * Options, the callback, or the input encoding. 14 | * @param {diagnoseCallback} [cb] Callback. 15 | * @returns {Promise} If callback not specified. 16 | * @throws {TypeError} Input not provided. 17 | */ 18 | static diagnose(input: BufferLike, options?: DiagnoseOptions | diagnoseCallback | string, cb?: diagnoseCallback): Promise; 19 | /** 20 | * Creates an instance of Diagnose. 21 | * 22 | * @param {DiagnoseOptions} [options={}] Options for creation. 23 | */ 24 | constructor(options?: DiagnoseOptions); 25 | float_bytes: number; 26 | separator: string; 27 | stream_errors: boolean; 28 | parser: Decoder; 29 | /** 30 | * @ignore 31 | */ 32 | _on_error(er: any): void; 33 | /** @private */ 34 | private _on_more; 35 | /** @private */ 36 | private _fore; 37 | /** @private */ 38 | private _on_value; 39 | /** @private */ 40 | private _on_start; 41 | /** @private */ 42 | private _on_stop; 43 | /** @private */ 44 | private _on_data; 45 | } 46 | declare namespace Diagnose { 47 | export { BufferLike, DiagnoseOptions, diagnoseCallback }; 48 | } 49 | import stream = require("stream"); 50 | import Decoder = require("./decoder"); 51 | /** 52 | * Things that can act as inputs, from which a NoFilter can be created. 53 | */ 54 | type BufferLike = string | Buffer | ArrayBuffer | Uint8Array | Uint8ClampedArray | DataView | stream.Readable; 55 | type DiagnoseOptions = { 56 | /** 57 | * Output between detected objects. 58 | */ 59 | separator?: string; 60 | /** 61 | * Put error info into the 62 | * output stream. 63 | */ 64 | stream_errors?: boolean; 65 | /** 66 | * The maximum depth to parse. 67 | * Use -1 for "until you run out of memory". Set this to a finite 68 | * positive number for un-trusted inputs. Most standard inputs won't nest 69 | * more than 100 or so levels; I've tested into the millions before 70 | * running out of memory. 71 | */ 72 | max_depth?: number; 73 | /** 74 | * Mapping from tag number to function(v), 75 | * where v is the decoded value that comes after the tag, and where the 76 | * function returns the correctly-created value for that tag. 77 | */ 78 | tags?: object; 79 | /** 80 | * If true, prefer Uint8Arrays to 81 | * be generated instead of node Buffers. This might turn on some more 82 | * changes in the future, so forward-compatibility is not guaranteed yet. 83 | */ 84 | preferWeb?: boolean; 85 | /** 86 | * The encoding of input, ignored if 87 | * input is not string. 88 | */ 89 | encoding?: BufferEncoding; 90 | }; 91 | type diagnoseCallback = (error?: Error, value?: string) => void; 92 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/map.d.ts: -------------------------------------------------------------------------------- 1 | export = CborMap; 2 | /** 3 | * Wrapper around a JavaScript Map object that allows the keys to be 4 | * any complex type. The base Map object allows this, but will only 5 | * compare the keys by identity, not by value. CborMap translates keys 6 | * to CBOR first (and base64's them to ensure by-value comparison). 7 | * 8 | * This is not a subclass of Object, because it would be tough to get 9 | * the semantics to be an exact match. 10 | * 11 | * @extends Map 12 | */ 13 | declare class CborMap extends Map { 14 | /** 15 | * @ignore 16 | * @param {unknown} key 17 | * @returns {string} 18 | */ 19 | static _encode(key: unknown): string; 20 | /** 21 | * @ignore 22 | * @param {string} key 23 | * @returns {unknown} 24 | */ 25 | static _decode(key: string): unknown; 26 | /** 27 | * Creates an instance of CborMap. 28 | * 29 | * @param {Iterable} [iterable] An Array or other iterable 30 | * object whose elements are key-value pairs (arrays with two elements, e.g. 31 | * [[ 1, 'one' ],[ 2, 'two' ]]). Each key-value pair is added 32 | * to the new CborMap; null values are treated as undefined. 33 | */ 34 | constructor(iterable?: Iterable); 35 | /** 36 | * Adds or updates an element with a specified key and value. 37 | * 38 | * @param {any} key The key identifying the element to store. 39 | * Can be any type, which will be serialized into CBOR and compared by 40 | * value. 41 | * @param {any} val The element to store. 42 | * @returns {this} This object. 43 | */ 44 | set(key: any, val: any): this; 45 | /** 46 | * Returns a new Iterator object that contains the [key, value] pairs for 47 | * each element in the Map object in insertion order. 48 | * 49 | * @returns {IterableIterator} Key value pairs. 50 | * @yields {any[]} Key value pairs. 51 | */ 52 | entries(): IterableIterator; 53 | /** 54 | * Executes a provided function once per each key/value pair in the Map 55 | * object, in insertion order. 56 | * 57 | * @param {function(any, any, Map): undefined} fun Function to 58 | * execute for each element, which takes a value, a key, and the Map 59 | * being traversed. 60 | * @param {any} thisArg Value to use as this when executing callback. 61 | * @throws {TypeError} Invalid function. 62 | */ 63 | forEach(fun: (arg0: any, arg1: any, arg2: Map) => undefined, thisArg?: any): void; 64 | /** 65 | * Push the simple value onto the CBOR stream. 66 | * 67 | * @param {import('./encoder.js')} gen The generator to push onto. 68 | * @returns {boolean} True on success. 69 | */ 70 | encodeCBOR(gen: import("./encoder.js")): boolean; 71 | /** 72 | * Returns a new Iterator object that contains the [key, value] pairs for 73 | * each element in the Map object in insertion order. 74 | * 75 | * @returns {IterableIterator} Key value pairs. 76 | */ 77 | [Symbol.iterator](): IterableIterator; 78 | } 79 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/objectRecorder.d.ts: -------------------------------------------------------------------------------- 1 | export = ObjectRecorder; 2 | /** 3 | * Record objects that pass by in a stream. If the same object is used more 4 | * than once, it can be value-shared using shared values. 5 | * 6 | * @see {@link http://cbor.schmorp.de/value-sharing} 7 | */ 8 | declare class ObjectRecorder { 9 | /** 10 | * Clear all of the objects that have been seen. Revert to recording mode. 11 | */ 12 | clear(): void; 13 | map: WeakMap; 14 | count: number; 15 | recording: boolean; 16 | /** 17 | * Stop recording. 18 | */ 19 | stop(): void; 20 | /** 21 | * Determine if wrapping a tag 28 or 29 around an object that has been 22 | * reused is appropriate. This method stores state for which objects have 23 | * been seen. 24 | * 25 | * @param {object} obj Any object about to be serialized. 26 | * @returns {number} If recording: -1 for first use, index for second use. 27 | * If not recording, -1 for never-duplicated, -2 for first use, index for 28 | * subsequent uses. 29 | * @throws {Error} Recording does not match playback. 30 | */ 31 | check(obj: object): number; 32 | } 33 | declare namespace ObjectRecorder { 34 | let NEVER: number; 35 | let FIRST: number; 36 | } 37 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/sharedValueEncoder.d.ts: -------------------------------------------------------------------------------- 1 | export = SharedValueEncoder; 2 | /** 3 | * Implement value sharing. 4 | * 5 | * @see {@link cbor.schmorp.de/value-sharing} 6 | */ 7 | declare class SharedValueEncoder extends Encoder { 8 | constructor(opts: any); 9 | valueSharing: ObjectRecorder; 10 | /** 11 | * Between encoding runs, stop recording, and start outputing correct tags. 12 | */ 13 | stopRecording(): void; 14 | /** 15 | * Remove the existing recording and start over. Do this between encoding 16 | * pairs. 17 | */ 18 | clearRecording(): void; 19 | } 20 | import Encoder = require("./encoder"); 21 | import ObjectRecorder = require("./objectRecorder"); 22 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/simple.d.ts: -------------------------------------------------------------------------------- 1 | export = Simple; 2 | /** 3 | * A CBOR Simple Value that does not map onto a known constant. 4 | */ 5 | declare class Simple { 6 | /** 7 | * Is the given object a Simple? 8 | * 9 | * @param {any} obj Object to test. 10 | * @returns {boolean} Is it Simple? 11 | */ 12 | static isSimple(obj: any): boolean; 13 | /** 14 | * Decode from the CBOR additional information into a JavaScript value. 15 | * If the CBOR item has no parent, return a "safe" symbol instead of 16 | * `null` or `undefined`, so that the value can be passed through a 17 | * stream in object mode. 18 | * 19 | * @param {number} val The CBOR additional info to convert. 20 | * @param {boolean} [has_parent=true] Does the CBOR item have a parent? 21 | * @param {boolean} [parent_indefinite=false] Is the parent element 22 | * indefinitely encoded? 23 | * @returns {(null|undefined|boolean|symbol|Simple)} The decoded value. 24 | * @throws {Error} Invalid BREAK. 25 | */ 26 | static decode(val: number, has_parent?: boolean, parent_indefinite?: boolean): (null | undefined | boolean | symbol | Simple); 27 | /** 28 | * Creates an instance of Simple. 29 | * 30 | * @param {number} value The simple value's integer value. 31 | */ 32 | constructor(value: number); 33 | value: number; 34 | /** 35 | * Debug string for simple value. 36 | * 37 | * @returns {string} Formated string of `simple(value)`. 38 | */ 39 | toString(): string; 40 | /** 41 | * Push the simple value onto the CBOR stream. 42 | * 43 | * @param {object} gen The generator to push onto. 44 | * @returns {boolean} True on success. 45 | */ 46 | encodeCBOR(gen: object): boolean; 47 | } 48 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/tagged.d.ts: -------------------------------------------------------------------------------- 1 | export = Tagged; 2 | /** 3 | * A CBOR tagged item, where the tag does not have semantics specified at the 4 | * moment, or those semantics threw an error during parsing. Typically this will 5 | * be an extension point you're not yet expecting. 6 | */ 7 | declare class Tagged { 8 | static set TAGS(val: { 9 | [x: string]: TagFunction; 10 | }); 11 | /** 12 | * The current set of supported tags. May be modified by plugins. 13 | * 14 | * @type {TagMap} 15 | * @static 16 | */ 17 | static get TAGS(): { 18 | [x: string]: TagFunction; 19 | }; 20 | /** 21 | * Reset the supported tags to the original set, before any plugins modified 22 | * the list. 23 | */ 24 | static reset(): void; 25 | /** 26 | * Creates an instance of Tagged. 27 | * 28 | * @param {number} tag The number of the tag. 29 | * @param {any} value The value inside the tag. 30 | * @param {Error} [err] The error that was thrown parsing the tag, or null. 31 | */ 32 | constructor(tag: number, value: any, err?: Error); 33 | tag: number; 34 | value: any; 35 | err: Error; 36 | toJSON(): any; 37 | /** 38 | * Convert to a String. 39 | * 40 | * @returns {string} String of the form '1(2)'. 41 | */ 42 | toString(): string; 43 | /** 44 | * Push the simple value onto the CBOR stream. 45 | * 46 | * @param {object} gen The generator to push onto. 47 | * @returns {boolean} True on success. 48 | */ 49 | encodeCBOR(gen: object): boolean; 50 | /** 51 | * If we have a converter for this type, do the conversion. Some converters 52 | * are built-in. Additional ones can be passed in. If you want to remove 53 | * a built-in converter, pass a converter in whose value is 'null' instead 54 | * of a function. 55 | * 56 | * @param {object} converters Keys in the object are a tag number, the value 57 | * is a function that takes the decoded CBOR and returns a JavaScript value 58 | * of the appropriate type. Throw an exception in the function on errors. 59 | * @returns {any} The converted item. 60 | */ 61 | convert(converters: object): any; 62 | } 63 | declare namespace Tagged { 64 | export { INTERNAL_JSON, TagFunction, TagMap }; 65 | } 66 | declare const INTERNAL_JSON: unique symbol; 67 | /** 68 | * Convert a tagged value to a more interesting JavaScript type. Errors 69 | * thrown in this function will be captured into the "err" property of the 70 | * original Tagged instance. 71 | */ 72 | type TagFunction = (value: any, tag: Tagged) => any; 73 | /** 74 | * A mapping from tag number to a tag decoding function. 75 | */ 76 | type TagMap = { 77 | [x: string]: TagFunction; 78 | }; 79 | -------------------------------------------------------------------------------- /packages/cbor/types/lib/utils.d.ts: -------------------------------------------------------------------------------- 1 | export function utf8(buf: any): string; 2 | export namespace utf8 { 3 | let checksUTF8: boolean; 4 | } 5 | export function isBufferish(b: any): boolean; 6 | export function bufferishToBuffer(b: any): Buffer; 7 | export function parseCBORint(ai: any, buf: any): any; 8 | export function writeHalf(buf: any, half: any): boolean; 9 | export function parseHalf(buf: any): number; 10 | export function parseCBORfloat(buf: any): any; 11 | export function hex(s: any): Buffer; 12 | export function bin(s: any): Buffer; 13 | export function arrayEqual(a: any, b: any): any; 14 | export function bufferToBigInt(buf: any): bigint; 15 | export function cborValueToString(val: any, float_bytes?: number): any; 16 | export function guessEncoding(input: any, encoding: any): any; 17 | export function base64url(buf: Buffer | Uint8Array | Uint8ClampedArray | ArrayBuffer | DataView): string; 18 | export function base64(buf: Buffer | Uint8Array | Uint8ClampedArray | ArrayBuffer | DataView): string; 19 | export function isBigEndian(): boolean; 20 | import { Buffer } from "buffer"; 21 | -------------------------------------------------------------------------------- /packages/cbor/types/vendor/binary-parse-stream/index.d.ts: -------------------------------------------------------------------------------- 1 | export = BinaryParseStream; 2 | /** 3 | * BinaryParseStream is a TransformStream that consumes buffers and outputs 4 | * objects on the other end. It expects your subclass to implement a `_parse` 5 | * method that is a generator. When your generator yields a number, it'll be 6 | * fed a buffer of that length from the input. When your generator returns, 7 | * the return value will be pushed to the output side. 8 | * 9 | * @extends stream.Transform 10 | */ 11 | declare class BinaryParseStream extends stream.Transform { 12 | /** 13 | * Creates an instance of BinaryParseStream. 14 | * 15 | * @memberof BinaryParseStream 16 | * @param {stream.TransformOptions} options Stream options. 17 | */ 18 | constructor(options: stream.TransformOptions); 19 | bs: NoFilter; 20 | __fresh: boolean; 21 | __needed: any; 22 | /** 23 | * Subclasses must override this to set their parsing behavior. Yield a 24 | * number to receive a Buffer of that many bytes. 25 | * 26 | * @abstract 27 | * @returns {Generator} 28 | */ 29 | _parse(): Generator; 30 | __restart(): void; 31 | __parser: Generator; 32 | } 33 | import stream = require("stream"); 34 | import NoFilter = require("nofilter"); 35 | -------------------------------------------------------------------------------- /packages/cbor/vendor/binary-parse-stream/README.md: -------------------------------------------------------------------------------- 1 | # binary-parse-stream 2 | 3 | Painless streaming binary protocol parsers using generators. 4 | 5 | ## Installation 6 | 7 | npm install binary-parse-stream 8 | 9 | ## Synchronous 10 | 11 | This module uses the exact same generator interface as [binary-parse-stream](https://github.com/nathan7/binary-parse-stream), which presents a synchronous interface to a generator parser. 12 | 13 | ## Usage 14 | 15 | ```js 16 | const BinaryParseStream = require('binary-parse-stream'); 17 | const {One} = BinaryParseStream; // -1 18 | ``` 19 | 20 | BinaryParseStream is a TransformStream that consumes buffers and outputs objects on the other end. 21 | It expects your subclass to implement a `_parse` method that is a generator. 22 | When your generator yields a number, it'll be fed a buffer of that length from the input. 23 | If it yields -1, it'll be given the value of the first byte instead of a single-byte buffer. 24 | When your generator returns, the return value will be pushed to the output side. 25 | 26 | ## Example 27 | 28 | The following module parses a protocol that consists of a 32-bit unsigned big-endian type parameter, an unsigned 8-bit length parameter, and a buffer of the specified length. 29 | It outputs `{type, buf}` objects. 30 | 31 | ```js 32 | class SillyProtocolParseStream extends BinaryParseStream { 33 | constructor(options) { 34 | super(options); 35 | this.count = 0; 36 | } 37 | 38 | *_parse() { 39 | const type = (yield 4).readUInt32BE(0, true); 40 | const length = yield -1; 41 | const buf = yield length; 42 | this.count++; 43 | return {type, buf}; 44 | } 45 | } 46 | ``` 47 | 48 | There is also a shorter syntax for when you don't want to explicitly subclass: `BinaryParseStream.extend(function*())`. 49 | 50 | -------------------------------------------------------------------------------- /packages/cbor/vendor/binary-parse-stream/index.js: -------------------------------------------------------------------------------- 1 | // Tweaked version of nathan7's binary-parse-stream 2 | // (see https://github.com/nathan7/binary-parse-stream) 3 | // Uses NoFilter instead of the readable in the original. Removes 4 | // the ability to read -1, which was odd and un-needed. 5 | // License for binary-parse-stream: MIT 6 | 7 | // binary-parse-stream is now unmaintained, so I have rewritten it as 8 | // more modern JS so I can get tsc to help check types. 9 | 10 | 'use strict'; 11 | // eslint-disable-next-line n/prefer-node-protocol 12 | const stream = require('stream'); 13 | const NoFilter = require('nofilter'); 14 | 15 | /** 16 | * BinaryParseStream is a TransformStream that consumes buffers and outputs 17 | * objects on the other end. It expects your subclass to implement a `_parse` 18 | * method that is a generator. When your generator yields a number, it'll be 19 | * fed a buffer of that length from the input. When your generator returns, 20 | * the return value will be pushed to the output side. 21 | * 22 | * @extends stream.Transform 23 | */ 24 | class BinaryParseStream extends stream.Transform { 25 | /** 26 | * Creates an instance of BinaryParseStream. 27 | * 28 | * @memberof BinaryParseStream 29 | * @param {stream.TransformOptions} options Stream options. 30 | */ 31 | constructor(options) { 32 | super(options); 33 | // Doesn't work to pass these in as opts, for some reason 34 | // also, work around typescript not knowing TransformStream internals 35 | // eslint-disable-next-line dot-notation 36 | this['_writableState'].objectMode = false; 37 | // eslint-disable-next-line dot-notation 38 | this['_readableState'].objectMode = true; 39 | 40 | this.bs = new NoFilter(); 41 | this.__restart(); 42 | } 43 | 44 | /** 45 | * Transforming. 46 | * 47 | * @param {any} fresh Buffer to transcode. 48 | * @param {BufferEncoding} _encoding Name of encoding. 49 | * @param {stream.TransformCallback} cb Callback when done. 50 | * @ignore 51 | */ 52 | _transform(fresh, _encoding, cb) { 53 | this.bs.write(fresh); 54 | 55 | while (this.bs.length >= this.__needed) { 56 | let ret = null; 57 | const chunk = (this.__needed === null) ? 58 | undefined : 59 | this.bs.read(this.__needed); 60 | 61 | try { 62 | ret = this.__parser.next(chunk); 63 | } catch (e) { 64 | return cb(e); 65 | } 66 | 67 | if (this.__needed) { 68 | this.__fresh = false; 69 | } 70 | 71 | if (ret.done) { 72 | this.push(ret.value); 73 | this.__restart(); 74 | } else { 75 | this.__needed = ret.value || Infinity; 76 | } 77 | } 78 | 79 | return cb(); 80 | } 81 | 82 | /** 83 | * Subclasses must override this to set their parsing behavior. Yield a 84 | * number to receive a Buffer of that many bytes. 85 | * 86 | * @abstract 87 | * @returns {Generator} 88 | */ 89 | /* istanbul ignore next */ 90 | *_parse() { // eslint-disable-line class-methods-use-this, require-yield 91 | throw new Error('Must be implemented in subclass'); 92 | } 93 | 94 | __restart() { 95 | this.__needed = null; 96 | this.__parser = this._parse(); 97 | this.__fresh = true; 98 | } 99 | 100 | /** 101 | * Flushing. 102 | * 103 | * @param {stream.TransformCallback} cb Callback when done. 104 | * @ignore 105 | */ 106 | _flush(cb) { 107 | cb(this.__fresh ? null : new Error('unexpected end of input')); 108 | } 109 | } 110 | 111 | module.exports = BinaryParseStream; 112 | -------------------------------------------------------------------------------- /packages/parcel-demo/.gitignore: -------------------------------------------------------------------------------- 1 | .cache/ 2 | node_modules/ 3 | dist/ 4 | package-lock.json 5 | .parcel-cache/ 6 | -------------------------------------------------------------------------------- /packages/parcel-demo/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/parcel-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parcel-demo", 3 | "version": "10.0.3", 4 | "description": "", 5 | "private": true, 6 | "type": "module", 7 | "scripts": { 8 | "prebuild": "rimraf -rf dist", 9 | "build": "parcel build src/index-p.html --dist-dir dist --no-source-maps --public-url ./ --no-content-hash", 10 | "precopy": "npm run build", 11 | "copy": "copyfiles -u1 dist/* ../../docs/example" 12 | }, 13 | "keywords": [], 14 | "author": "Joe Hildebrand ", 15 | "license": "MIT", 16 | "repository": { 17 | "type": "git", 18 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 19 | "directory": "packages/parcel-demo" 20 | }, 21 | "devDependencies": { 22 | "@parcel/core": "2.14.4", 23 | "@parcel/optimizer-data-url": "2.14.4", 24 | "@parcel/transformer-inline-string": "2.14.4", 25 | "bignumber.js": "9.3.0", 26 | "buffer": "6.0.3", 27 | "cbor": "^10.0.3", 28 | "cbor-bigdecimal": "^10.0.3", 29 | "copyfiles": "^2.4.1", 30 | "events": "3.3.0", 31 | "node-inspect-extracted": "^3.0.2", 32 | "parcel": "2.14.4", 33 | "postcss": "^8.5.3", 34 | "process": "0.11.10", 35 | "regenerator-runtime": "^0.14.1", 36 | "rimraf": "5.0.10", 37 | "stream-browserify": "3.0.0", 38 | "svgo": "3.3.2" 39 | }, 40 | "engines": { 41 | "node": ">=20" 42 | }, 43 | "browserslist": [ 44 | "> 0.2%", 45 | "not dead" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /packages/parcel-demo/src/index-p.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CBOR/web (parcel) 6 | 7 | 8 | 9 |

CBOR converter

10 |
11 |
12 |

Input

13 |
14 | 19 | →→→ to →→→ 20 |
21 | 24 |
25 |
26 |

Output

27 |
28 | 36 | 37 |
38 | 39 |
40 |
41 |
42 | Powered by node-cbor. 43 | Source 44 |
45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /packages/parcel-demo/src/index-p.js: -------------------------------------------------------------------------------- 1 | import 'regenerator-runtime/runtime.js'; 2 | import * as cbor from 'cbor'; 3 | import {Buffer} from 'buffer'; 4 | import bdec from 'cbor-bigdecimal'; 5 | import {inspect} from 'node-inspect-extracted'; 6 | 7 | bdec(cbor); 8 | 9 | const ofmt = document.getElementById('output-fmt'); 10 | const otxt = document.getElementById('output-text'); 11 | const itxt = document.getElementById('input-text'); 12 | const ifmt = document.getElementById('input-fmt'); 13 | const copy = document.getElementById('copy'); 14 | 15 | function error(e) { 16 | copy.disabled = true; 17 | otxt.value = e.toString(); 18 | } 19 | 20 | // Convert any input to a buffer 21 | function input() { 22 | const inp = ifmt.selectedOptions[0].label; 23 | const txt = itxt.value; 24 | switch (inp) { 25 | case 'JSON': 26 | return cbor.encodeOne(JSON.parse(txt), {canonical: true}); 27 | case 'hex': 28 | case 'base64': 29 | return Buffer.from(txt, inp); 30 | default: 31 | throw new Error(`Unknown input: "${inp}"`); 32 | } 33 | } 34 | 35 | // Convert a buffer to the desired output format 36 | function output(buf, _typ) { 37 | const outp = ofmt.selectedOptions[0].label; 38 | switch (outp) { 39 | case 'hex': 40 | case 'base64': 41 | copy.disabled = false; 42 | otxt.value = buf.toString(outp); 43 | break; 44 | case 'commented': 45 | copy.disabled = true; 46 | cbor.comment(buf).then(txt => { 47 | otxt.value = txt; 48 | }, error); 49 | break; 50 | case 'diagnostic': 51 | copy.disabled = true; 52 | cbor.diagnose(buf).then(txt => { 53 | otxt.value = txt; 54 | }, error); 55 | break; 56 | case 'js': 57 | copy.disabled = true; 58 | cbor.decodeFirst(buf).then(o => { 59 | otxt.value = inspect(o, { 60 | depth: Infinity, 61 | compact: 1, 62 | maxArrayLength: Infinity, 63 | breakLength: otxt.cols - 1, 64 | }); 65 | }, error); 66 | break; 67 | case 'JSON': 68 | copy.disabled = false; 69 | cbor.decodeFirst(buf).then(o => { 70 | otxt.value = JSON.stringify(o, null, 2); 71 | }, error); 72 | break; 73 | default: 74 | throw new Error(`Unknown output: "${outp}"`); 75 | } 76 | } 77 | 78 | function convert() { 79 | try { 80 | output(input()); 81 | } catch (e) { 82 | error(e); 83 | } 84 | } 85 | 86 | ofmt.oninput = convert; 87 | ifmt.oninput = convert; 88 | copy.onclick = () => { 89 | // Copy output to input, and guess the new input format 90 | itxt.value = otxt.value; 91 | const sel = ofmt.selectedOptions[0].label; 92 | for (const o of ifmt.options) { 93 | if (o.label === sel) { 94 | ifmt.selectedIndex = o.index; 95 | break; 96 | } 97 | } 98 | }; 99 | 100 | // Debounce 101 | let timeout = null; 102 | itxt.oninput = () => { 103 | clearTimeout(timeout); 104 | timeout = setTimeout(() => { 105 | timeout = null; 106 | convert(); 107 | }, 300); 108 | }; 109 | 110 | // Make sure that initial output is set 111 | convert(); 112 | -------------------------------------------------------------------------------- /packages/parcel-demo/src/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | background-color:cornsilk; 4 | } 5 | 6 | .container { 7 | display: flex; 8 | flex-flow: row wrap; 9 | align-items: flex-start; 10 | } 11 | 12 | .cmd { 13 | margin: 0 10px 5px 10px; 14 | } 15 | 16 | #to { 17 | float: right; 18 | } 19 | 20 | h3 { 21 | margin: 0 10px 5px 10px; 22 | } 23 | 24 | textarea { 25 | margin: 0 10px 0 10px; 26 | } 27 | 28 | .power { 29 | margin: 10px; 30 | } 31 | -------------------------------------------------------------------------------- /packages/plain-demo/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /packages/plain-demo/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /packages/plain-demo/build.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 'use strict'; 3 | 4 | const fs = require('node:fs'); 5 | const path = require('node:path'); 6 | const bresolve = require('browser-resolve'); 7 | 8 | const src = path.join(__dirname, 'src'); 9 | const dist = path.join(__dirname, 'dist'); 10 | try { 11 | fs.rmSync(dist, { 12 | recursive: true, 13 | force: true, 14 | }); 15 | } catch (ignored) { 16 | console.warn(`Warning: could not delete "${dist}"`); 17 | } 18 | 19 | const have = new Set(); 20 | const needed = new Set(); 21 | const transform = new Set(); 22 | 23 | try { 24 | fs.mkdirSync(dist); 25 | } catch (ignored) { 26 | console.warn(`Warning: could not create "${dist}"`); 27 | } 28 | 29 | // eslint-disable-next-line prefer-named-capture-group 30 | const script = / !have.has(x))); 58 | // Find the scripts we don't have yet. Assume each one is 59 | // a single file. 60 | const scriptNames = {}; 61 | for (const s of scripts) { 62 | const scriptSrc = bresolve.sync(s, {filename: __filename}); 63 | const local = path.basename(scriptSrc); 64 | scriptNames[s] = local; 65 | 66 | console.log(`Resolve: ${s} (${path.relative(__dirname, scriptSrc)})`); 67 | fs.copyFileSync(scriptSrc, path.join(dist, local)); 68 | } 69 | 70 | for (const s of transform) { 71 | const srcFile = path.join(src, s); 72 | let html = fs.readFileSync(srcFile, 'utf8'); 73 | html = html.replace(script, (m, orig) => { 74 | const local = scriptNames[orig]; 75 | return local ? ` 8 | 9 | 10 | 11 | 12 | 13 |

CBOR converter

14 |
15 |
16 |

Input

17 |
18 | 23 | →→→ to →→→ 24 |
25 | 28 |
29 |
30 |

Output

31 |
32 | 40 | 41 |
42 | 43 |
44 |
45 |
46 | Powered by node-cbor. 47 | Source 48 |
49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /packages/plain-demo/src/index-plain.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 'use strict'; 3 | 4 | cborBigDecimal(cbor); 5 | 6 | const ofmt = document.getElementById('output-fmt'); 7 | const otxt = document.getElementById('output-text'); 8 | const itxt = document.getElementById('input-text'); 9 | const ifmt = document.getElementById('input-fmt'); 10 | const copy = document.getElementById('copy'); 11 | 12 | function error(e) { 13 | copy.disabled = true; 14 | otxt.value = e.toString(); 15 | } 16 | 17 | // Convert any input to a buffer 18 | function input() { 19 | const inp = ifmt.selectedOptions[0].label; 20 | const txt = itxt.value; 21 | switch (inp) { 22 | case 'JSON': 23 | return cbor.encodeOne(JSON.parse(txt), {canonical: true}); 24 | case 'hex': 25 | if (!txt) { 26 | return new Uint8Array(0); 27 | } 28 | return new Uint8Array(txt 29 | .match(/.{1,2}/g) 30 | .map(byte => parseInt(byte, 16))); 31 | case 'base64': 32 | return new Uint8Array([...atob(txt)].map(c => c.charCodeAt(0))); 33 | default: 34 | throw new Error(`Unknown input: "${inp}"`); 35 | } 36 | } 37 | 38 | // Convert a buffer to the desired output format 39 | function output(buf, _typ) { 40 | const outp = ofmt.selectedOptions[0].label; 41 | switch (outp) { 42 | case 'hex': 43 | copy.disabled = false; 44 | otxt.value = Array.prototype.map.call( 45 | buf, 46 | x => (`00${x.toString(16)}`).slice(-2) 47 | ).join(''); 48 | break; 49 | case 'base64': 50 | copy.disabled = false; 51 | otxt.value = btoa(Array.prototype.reduce.call( 52 | buf, (t, b) => t + String.fromCharCode(b), '' 53 | )); 54 | break; 55 | case 'commented': 56 | copy.disabled = true; 57 | cbor.comment(buf).then(txt => { 58 | otxt.value = txt; 59 | }, error); 60 | break; 61 | case 'diagnostic': 62 | copy.disabled = true; 63 | cbor.diagnose(buf).then(txt => { 64 | otxt.value = txt; 65 | }, error); 66 | break; 67 | case 'js': 68 | copy.disabled = true; 69 | cbor.decodeFirst(buf).then(o => { 70 | otxt.value = util.inspect(o, { 71 | depth: Infinity, 72 | compact: 1, 73 | maxArrayLength: Infinity, 74 | breakLength: otxt.cols - 1, 75 | }); 76 | }, error); 77 | break; 78 | case 'JSON': 79 | copy.disabled = false; 80 | cbor.decodeFirst(buf, {bigint: true, preferWeb: true}).then(o => { 81 | otxt.value = JSON.stringify(o, null, 2); 82 | }, error); 83 | break; 84 | default: 85 | throw new Error(`Unknown output: "${outp}"`); 86 | } 87 | } 88 | 89 | function convert() { 90 | try { 91 | output(input()); 92 | } catch (e) { 93 | error(e); 94 | throw e; 95 | } 96 | } 97 | 98 | ofmt.oninput = convert; 99 | ifmt.oninput = convert; 100 | copy.onclick = () => { 101 | // Copy output to input, and guess the new input format 102 | itxt.value = otxt.value; 103 | const sel = ofmt.selectedOptions[0].label; 104 | for (const o of ifmt.options) { 105 | if (o.label === sel) { 106 | ifmt.selectedIndex = o.index; 107 | break; 108 | } 109 | } 110 | }; 111 | 112 | // Debounce 113 | let timeout = null; 114 | itxt.oninput = () => { 115 | clearTimeout(timeout); 116 | timeout = setTimeout(() => { 117 | timeout = null; 118 | convert(); 119 | }, 300); 120 | }; 121 | 122 | // Make sure that initial output is set 123 | convert(); 124 | -------------------------------------------------------------------------------- /packages/plain-demo/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CBOR examples for the web 6 | 7 | 8 | 9 | 10 |

CBOR examples for the web

11 | Using: 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/plain-demo/src/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | background-color:cornsilk; 4 | } 5 | 6 | .container { 7 | display: flex; 8 | flex-flow: row wrap; 9 | align-items: flex-start; 10 | } 11 | 12 | .cmd { 13 | margin: 0 10px 5px 10px; 14 | } 15 | 16 | #to { 17 | float: right; 18 | } 19 | 20 | h3 { 21 | margin: 0 10px 5px 10px; 22 | } 23 | 24 | textarea { 25 | margin: 0 10px 0 10px; 26 | } 27 | 28 | .power { 29 | margin: 10px; 30 | } 31 | -------------------------------------------------------------------------------- /packages/puppeteer-demo/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | package-lock=false 3 | puppeteer_skip_download=true 4 | PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true 5 | -------------------------------------------------------------------------------- /packages/puppeteer-demo/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 'use strict'; 3 | 4 | const puppeteer = require('puppeteer'); 5 | const path = require('node:path'); 6 | const assert = require('node:assert'); 7 | const fs = require('node:fs'); 8 | 9 | const TOP = `file://${path.resolve( 10 | __dirname, '..', '..', 'docs', 'example', 'index.html' 11 | )}`; 12 | 13 | let executablePath = process.env.PUPPETEER_EXECUTABLE_PATH; 14 | if (!executablePath && (process.platform === 'darwin')) { 15 | executablePath = path.resolve( 16 | '/', 17 | 'Applications', 18 | 'Google Chrome.app', 19 | 'Contents', 20 | 'MacOS', 21 | 'Google Chrome' 22 | ); 23 | } 24 | if (executablePath) { 25 | try { 26 | fs.accessSync(executablePath, fs.constants.X_OK); 27 | } catch (ignored) { 28 | executablePath = undefined; 29 | delete process.env.PUPPETEER_EXECUTABLE_PATH; 30 | } 31 | } 32 | 33 | async function main() { 34 | const browser = await puppeteer.launch({ 35 | executablePath, 36 | slowMo: 100, 37 | headless: false, 38 | defaultViewport: null, 39 | }); 40 | const pages = await browser.pages(); 41 | const page = (pages.length > 0) ? pages[0] : await browser.newPage(); 42 | page 43 | .on('console', message => { 44 | const txt = message.text(); 45 | const type = message 46 | .type() 47 | .substr(0, 3) 48 | .toUpperCase(); 49 | console.log(`${type} ${txt}`); 50 | }) 51 | .on('pageerror', ({message}) => console.log(message)) 52 | // .on('response', response => 53 | // console.log(`${response.status()} ${response.url()}`)) 54 | .on('requestfailed', request => console.log( 55 | `${request.failure().errorText} ${request.url()}` 56 | )); 57 | await page.goto(TOP, {waitUntil: 'load'}); 58 | const links = await page.$$('li a'); 59 | const len = links.length; 60 | for (let i = 0; i < len; i++) { 61 | await Promise.all([ 62 | page.waitForNavigation({waitUntil: 'load'}), 63 | page.click(`li:nth-child(${i + 1}) a`), 64 | ]); 65 | await page.$eval('#input-text', input => { 66 | input.value = 'c482382cc254056e5e99b1be81b6eefa3964490ac18c69399361'; 67 | }); 68 | await page.select('#input-fmt', 'hex'); 69 | await page.select('#output-fmt', 'js'); 70 | const txt = await page.$eval('#output-text', output => output.value); 71 | assert(txt.match(/ s:\s+\d+,/)); 72 | await page.goBack(); 73 | } 74 | await browser.close(); 75 | } 76 | 77 | main().catch(console.error); 78 | -------------------------------------------------------------------------------- /packages/puppeteer-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppeteer-demo", 3 | "version": "10.0.3", 4 | "description": "Run all web demos in puppeteer", 5 | "main": "index.js", 6 | "private": true, 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "Joe Hildebrand ", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "chrome-finder": "^1.0.7", 15 | "puppeteer": "^24.7.2" 16 | }, 17 | "engines": { 18 | "node": ">=20" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/webpack-demo/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json 3 | dist 4 | -------------------------------------------------------------------------------- /packages/webpack-demo/.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /packages/webpack-demo/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Joe Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/webpack-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-demo", 3 | "version": "10.0.3", 4 | "description": "", 5 | "private": true, 6 | "scripts": { 7 | "build": "webpack", 8 | "precopy": "npm run build", 9 | "copy": "copyfiles -u1 dist/* ../../docs/example" 10 | }, 11 | "keywords": [], 12 | "author": "Joe Hildebrand ", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "git+ssh://git@github.com/hildjj/node-cbor.git", 17 | "directory": "packages/webpack-demo" 18 | }, 19 | "devDependencies": { 20 | "@cto.af/textdecoder": "^0.2.0", 21 | "base64-js": "^1.5.1", 22 | "bignumber.js": "^9.3.0", 23 | "buffer": "^6.0.3", 24 | "cbor-bigdecimal": "^10.0.3", 25 | "cbor-web": "^10.0.3", 26 | "copyfiles": "^2.4.1", 27 | "css-loader": "^7.1.2", 28 | "events": "^3.3.0", 29 | "html-webpack-plugin": "^5.6.3", 30 | "ieee754": "^1.2.1", 31 | "inherits": "^2.0.4", 32 | "node-inspect-extracted": "*", 33 | "process": "^0.11.10", 34 | "readable-stream": "^4.7.0", 35 | "safe-buffer": "^5.2.1", 36 | "stream-browserify": "^3.0.0", 37 | "string_decoder": "^1.3.0", 38 | "style-loader": "^4.0.0", 39 | "util-deprecate": "^1.0.2", 40 | "webpack": "^5.99.7", 41 | "webpack-cli": "^5.1.4" 42 | }, 43 | "engines": { 44 | "node": ">=20" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/webpack-demo/src/index-wp.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 'use strict'; 3 | const cbor = require('cbor-web'); 4 | const {inspect} = require('node-inspect-extracted'); 5 | const {Buffer} = require('buffer'); 6 | const bdec = require('cbor-bigdecimal'); 7 | 8 | // eslint-disable-next-line no-unused-vars 9 | const style = require('./style.css'); 10 | 11 | bdec(cbor); 12 | const ofmt = document.getElementById('output-fmt'); 13 | const otxt = document.getElementById('output-text'); 14 | const itxt = document.getElementById('input-text'); 15 | const ifmt = document.getElementById('input-fmt'); 16 | const copy = document.getElementById('copy'); 17 | 18 | function error(e) { 19 | copy.disabled = true; 20 | otxt.value = e.toString(); 21 | } 22 | 23 | // Convert any input to a buffer 24 | function input() { 25 | const inp = ifmt.selectedOptions[0].label; 26 | const txt = itxt.value; 27 | switch (inp) { 28 | case 'JSON': 29 | return cbor.encodeOne(JSON.parse(txt), {canonical: true}); 30 | case 'hex': 31 | case 'base64': 32 | return Buffer.from(txt, inp); 33 | default: 34 | throw new Error(`Unknown input: "${inp}"`); 35 | } 36 | } 37 | 38 | // Convert a buffer to the desired output format 39 | function output(buf, _typ) { 40 | const outp = ofmt.selectedOptions[0].label; 41 | switch (outp) { 42 | case 'hex': 43 | case 'base64': 44 | copy.disabled = false; 45 | otxt.value = buf.toString(outp); 46 | break; 47 | case 'commented': 48 | copy.disabled = true; 49 | cbor.comment(buf).then(txt => { 50 | otxt.value = txt; 51 | }, error); 52 | break; 53 | case 'diagnostic': 54 | copy.disabled = true; 55 | cbor.diagnose(buf).then(txt => { 56 | otxt.value = txt; 57 | }, error); 58 | break; 59 | case 'js': 60 | copy.disabled = true; 61 | cbor.decodeFirst(buf).then(o => { 62 | otxt.value = inspect(o, { 63 | depth: Infinity, 64 | compact: 1, 65 | maxArrayLength: Infinity, 66 | breakLength: otxt.cols - 1, 67 | }); 68 | }, error); 69 | break; 70 | case 'JSON': 71 | copy.disabled = false; 72 | cbor.decodeFirst(buf).then(o => { 73 | otxt.value = JSON.stringify(o, null, 2); 74 | }, error); 75 | break; 76 | default: 77 | throw new Error(`Unknown output: "${outp}"`); 78 | } 79 | } 80 | 81 | function convert() { 82 | try { 83 | output(input()); 84 | } catch (e) { 85 | error(e); 86 | throw e; 87 | } 88 | } 89 | 90 | ofmt.oninput = convert; 91 | ifmt.oninput = convert; 92 | copy.onclick = () => { 93 | // Copy output to input, and guess the new input format 94 | itxt.value = otxt.value; 95 | const sel = ofmt.selectedOptions[0].label; 96 | for (const o of ifmt.options) { 97 | if (o.label === sel) { 98 | ifmt.selectedIndex = o.index; 99 | break; 100 | } 101 | } 102 | }; 103 | 104 | // Debounce 105 | let timeout = null; 106 | itxt.oninput = () => { 107 | clearTimeout(timeout); 108 | timeout = setTimeout(() => { 109 | timeout = null; 110 | convert(); 111 | }, 300); 112 | }; 113 | 114 | // Make sure that initial output is set 115 | convert(); 116 | -------------------------------------------------------------------------------- /packages/webpack-demo/src/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | background-color:cornsilk; 4 | } 5 | 6 | .container { 7 | display: flex; 8 | flex-flow: row wrap; 9 | align-items: flex-start; 10 | } 11 | 12 | .cmd { 13 | margin: 0 10px 5px 10px; 14 | } 15 | 16 | #to { 17 | float: right; 18 | } 19 | 20 | h3 { 21 | margin: 0 10px 5px 10px; 22 | } 23 | 24 | textarea { 25 | margin: 0 10px 0 10px; 26 | } 27 | 28 | .power { 29 | margin: 10px; 30 | } 31 | -------------------------------------------------------------------------------- /packages/webpack-demo/src/webpack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%= htmlWebpackPlugin.options.title %> 6 | 7 | 8 |

CBOR converter

9 |
10 |
11 |

Input

12 |
13 | 18 | →→→ to →→→ 19 |
20 | 23 |
24 |
25 |

Output

26 |
27 | 35 | 36 |
37 | 38 |
39 |
40 |
41 | Powered by node-cbor. 42 | Source 43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /packages/webpack-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('node:path'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | 6 | module.exports = { 7 | entry: './src/index-wp.js', 8 | output: { 9 | filename: 'bundle-wp.js', 10 | path: path.resolve(__dirname, 'dist'), 11 | }, 12 | mode: 'development', 13 | target: 'web', 14 | 15 | resolve: { 16 | // This causes things to work in a pnpm repo (with symlinks), 17 | // but means that the full set of dependencies of all dependencies 18 | // needs to be listed in package.json. 19 | symlinks: false, 20 | }, 21 | 22 | plugins: [ 23 | new HtmlWebpackPlugin({ 24 | filename: 'index-wp.html', 25 | title: 'CBOR/web (webpack)', 26 | template: 'src/webpack.html', 27 | }), 28 | ], 29 | 30 | module: { 31 | rules: [ 32 | { 33 | test: /\.css$/i, 34 | use: ['style-loader', 'css-loader'], 35 | }, 36 | ], 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | -------------------------------------------------------------------------------- /test/spot-check-web.ava.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('ava'); 4 | const cbor = require('../packages/cbor-web/dist/cbor'); 5 | const bdec = require('../packages/cbor-bigdecimal/dist/cbor-bigdecimal'); 6 | 7 | test('exists', t => { 8 | t.truthy(cbor); 9 | t.is(typeof cbor.encode, 'function'); 10 | t.is(typeof cbor.decode, 'function'); 11 | }); 12 | 13 | test('spot check', t => { 14 | t.is(cbor.encode({a: 1}).toString('hex'), 'a1616101'); 15 | t.deepEqual(cbor.decode('a1616101'), {a: 1}); 16 | }); 17 | 18 | test('bigdecimal', t => { 19 | bdec(cbor); 20 | const pi3 = new bdec.BigNumber(Math.PI).pow(3); 21 | const pi3cbor = cbor.encode(pi3).toString('hex'); 22 | t.is( 23 | pi3cbor, 24 | 'c482382cc254056e5e99b1be81b6eefa3964490ac18c69399361' 25 | ); 26 | t.deepEqual(cbor.decodeFirstSync(pi3cbor), pi3); 27 | cbor.reset(); 28 | }); 29 | --------------------------------------------------------------------------------