From 398b73fded9879ffcc77429bd96c6989e32ade49 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Thu, 8 Oct 2020 16:48:12 -0700 Subject: [PATCH 1/6] feat: type checking & type generation --- .eslintrc | 13 ++ .github/workflows/mikeals-workflow.yml | 4 + package.json | 23 ++- src/bases/base.js | 7 +- src/bases/base32.js | 10 +- src/bases/base58.js | 8 +- src/bases/base64-browser.js | 4 +- src/block.js | 248 ++++++++++++++++++------- src/bytes.js | 6 +- src/cid.js | 35 ++-- src/hashes/digest.js | 4 +- src/hashes/hasher.js | 4 +- src/hashes/sha2-browser.js | 8 +- src/index.js | 2 - src/legacy.js | 15 +- src/varint.js | 1 - test/test-block.js | 6 +- tsconfig.json | 42 +++++ vendor/base-x.d.ts | 9 + vendor/varint.d.ts | 46 +++++ 20 files changed, 376 insertions(+), 119 deletions(-) create mode 100644 .eslintrc create mode 100644 tsconfig.json create mode 100644 vendor/base-x.d.ts create mode 100644 vendor/varint.d.ts diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..43f463c6 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,13 @@ +{ + "extends": [ + "standard", + "plugin:@typescript-eslint/recommended" + ], + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/ban-ts-comment": "off" + } +} diff --git a/.github/workflows/mikeals-workflow.yml b/.github/workflows/mikeals-workflow.yml index 1b88e24a..09d1bc4d 100644 --- a/.github/workflows/mikeals-workflow.yml +++ b/.github/workflows/mikeals-workflow.yml @@ -22,6 +22,8 @@ jobs: - name: Build if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install + - name: Typecheck + uses: andoshin11/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest publish: @@ -40,6 +42,8 @@ jobs: - name: Build if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install + - name: Typecheck + uses: andoshin11/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest diff --git a/package.json b/package.json index a4715aac..47930233 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,15 @@ "main": "index.js", "type": "module", "scripts": { - "build": "npm_config_yes=true npx ipjs@latest build --tests", + "build": "npm run build:js && npm run build:types", + "build:js": "npm_config_yes=true npx ipjs@latest build --tests", + "build:types": "tsc --emitDeclarationOnly --declarationDir dist/types", "build:vendor": "npm run build:vendor:varint && npm run build:vendor:base-x", "build:vendor:varint": "npx brrp -x varint > vendor/varint.js", "build:vendor:base-x": "npx brrp -x @multiformats/base-x > vendor/base-x.js", "publish": "npm_config_yes=true npx ipjs@latest publish", "lint": "standard", + "check": "tsc --noEmit", "test:cjs": "npm run build && mocha dist/cjs/node-test/test-*.js && npm run test:cjs:browser", "test:node": "hundreds mocha test/test-*.js", "test:cjs:browser": "polendina --cleanup dist/cjs/browser-test/test-*.js", @@ -78,11 +81,16 @@ "hundreds": "0.0.7", "mocha": "^8.1.1", "polendina": "^1.0.0", - "standard": "^14.3.4" + "standard": "^14.3.4", + "typescript": "^4.0.3", + "@types/node": "14.11.7", + "@typescript-eslint/eslint-plugin": "^4.4.0", + "@typescript-eslint/parser": "^4.4.0" }, "standard": { "ignore": [ - "dist" + "dist", + "vendor" ] }, "dependencies": { @@ -100,5 +108,12 @@ "bugs": { "url": "https://github.com/multiformats/js-multiformats/issues" }, - "homepage": "https://github.com/multiformats/js-multiformats#readme" + "homepage": "https://github.com/multiformats/js-multiformats#readme", + "typesVersions": { + "*": { + "*": [ + "dist/types/*" + ] + } + } } diff --git a/src/bases/base.js b/src/bases/base.js index 5b7b7046..0d1d9b94 100644 --- a/src/bases/base.js +++ b/src/bases/base.js @@ -1,5 +1,3 @@ -// @ts-check - /** * @typedef {import('./interface').BaseEncoder} BaseEncoder * @typedef {import('./interface').BaseDecoder} BaseDecoder @@ -162,7 +160,7 @@ class ComposedDecoder { * @returns {Uint8Array} */ decode (input) { - const prefix = input[0] + const prefix = /** @type {Prefix} */ (input[0]) const decoder = this.decoders[prefix] if (decoder) { return decoder.decode(input) @@ -211,6 +209,9 @@ export class Codec { return this.encoder.encode(input) } + /** + * @param {string} input + */ decode (input) { return this.decoder.decode(input) } diff --git a/src/bases/base32.js b/src/bases/base32.js index 85613596..0857a23c 100644 --- a/src/bases/base32.js +++ b/src/bases/base32.js @@ -1,7 +1,9 @@ -// @ts-check - import { withAlphabet } from './base.js' +/** + * @param {string} input + * @param {input} alphabet + */ function decode (input, alphabet) { input = input.replace(new RegExp('=', 'g'), '') const length = input.length @@ -25,6 +27,10 @@ function decode (input, alphabet) { return output } +/** + * @param {Uint8Array} buffer + * @param {string} alphabet + */ function encode (buffer, alphabet) { const length = buffer.byteLength const view = new Uint8Array(buffer) diff --git a/src/bases/base58.js b/src/bases/base58.js index 21931a66..cee2c2f8 100644 --- a/src/bases/base58.js +++ b/src/bases/base58.js @@ -1,13 +1,17 @@ -// @ts-check - import baseX from '../../vendor/base-x.js' import { coerce } from '../bytes.js' import { from } from './base.js' +/** + * @param {string} alphabet + */ const implement = (alphabet) => { const { encode, decode } = baseX(alphabet) return { encode, + /** + * @param {string} text + */ decode: text => coerce(decode(text)) } } diff --git a/src/bases/base64-browser.js b/src/bases/base64-browser.js index 372d81cd..22e0d941 100644 --- a/src/bases/base64-browser.js +++ b/src/bases/base64-browser.js @@ -1,10 +1,8 @@ -// @ts-check - /* globals btoa, atob */ import b64 from './base64.js' const { base64, base64pad, base64url, base64urlpad, __browser } = b64({ - encode: b => btoa([].reduce.call(b, (p, c) => p + String.fromCharCode(c), '')), + encode: b => btoa(b.reduce((p, c) => p + String.fromCharCode(c), '')), decode: str => Uint8Array.from(atob(str), c => c.charCodeAt(0)), __browser: true }) diff --git a/src/block.js b/src/block.js index d0349ad2..9a90ca3a 100644 --- a/src/block.js +++ b/src/block.js @@ -1,128 +1,209 @@ import { bytes as binary, CID } from './index.js' -const readonly = (value, enumerable) => ( - { - get: () => value, - set: /* c8 ignore next */ () => { throw new Error('Cannot set read-only property') }, - enumerable - } -) - -const setImmutable = (obj, key, value, enumerable = true) => { - if (typeof value === 'undefined') /* c8 ignore next */ throw new Error(`${key} cannot be undefined`) - Object.defineProperty(obj, key, readonly(value, enumerable)) -} +const readonly = ({ enumerable = true, configurable = false } = {}) => ({ + enumerable, + configurable, + writable: false +}) -/* eslint-disable max-depth */ -const links = function * (decoded, path = []) { - if (typeof decoded !== 'object' || !decoded) return - for (const key of Object.keys(decoded)) { - const _path = path.slice() - _path.push(key) - const val = decoded[key] - if (val && typeof val === 'object') { - if (Array.isArray(val)) { - for (let i = 0; i < val.length; i++) { - const __path = _path.slice() - __path.push(i) - const o = val[i] - const cid = CID.asCID(o) +/** + * @template T + * @param {T} source + * @param {Array} base + * @returns {Iterable<[string, CID]>} + */ +const links = function * (source, base) { + if (source == null) return + for (const [key, value] of Object.entries(source)) { + const path = [...base, key] + if (value != null && typeof value === 'object') { + if (Array.isArray(value)) { + for (const [index, element] of value.entries()) { + const elementPath = [...path, index] + const cid = CID.asCID(element) if (cid) { - yield [__path.join('/'), cid] - } else if (typeof o === 'object') { - yield * links(o, __path) + yield [elementPath.join('/'), cid] + } else if (typeof element === 'object') { + yield * links(element, elementPath) } } } else { - const cid = CID.asCID(val) + const cid = CID.asCID(value) if (cid) { - yield [_path.join('/'), cid] + yield [path.join('/'), cid] } else { - yield * links(val, _path) + yield * links(value, path) } } } } } -const tree = function * (decoded, path = []) { - if (typeof decoded !== 'object' || !decoded) return - for (const key of Object.keys(decoded)) { - const _path = path.slice() - _path.push(key) - yield _path.join('/') - const val = decoded[key] - if (val && typeof val === 'object' && !CID.asCID(val)) { - if (Array.isArray(val)) { - for (let i = 0; i < val.length; i++) { - const __path = _path.slice() - __path.push(i) - const o = val[i] - yield __path.join('/') - if (typeof o === 'object' && !CID.asCID(o)) { - yield * tree(o, __path) +/** + * @template T + * @param {T} source + * @param {Array} base + * @returns {Iterable} + */ +const tree = function * (source, base) { + if (source == null) return + for (const [key, value] of Object.entries(source)) { + const path = [...base, key] + yield path.join('/') + if (value != null && typeof value === 'object' && !CID.asCID(value)) { + if (Array.isArray(value)) { + for (const [index, element] of value.entries()) { + const elementPath = [...path, index] + yield elementPath.join('/') + if (typeof element === 'object' && !CID.asCID(element)) { + yield * tree(element, elementPath) } } } else { - yield * tree(val, _path) + yield * tree(value, path) } } } } -/* eslint-enable max-depth */ +/** + * @template T + * @param {T} source + * @param {string[]} path + */ +const get = (source, path) => { + /** @type {Record} */ + let node = source + for (const [index, key] of path.entries()) { + node = node[key] + if (node == null) { + throw new Error(`Object has no property at ${path.slice(0, index + 1).map(part => `[${JSON.stringify(part)}]`).join('')}`) + } + const cid = CID.asCID(node) + if (cid) { + return { value: cid, remaining: path.slice(index + 1).join('/') } + } + } + return { value: node } +} + +/** + * @template T + */ class Block { + /** + * @param {Object} options + * @param {CID} options.cid + * @param {ByteView} options.bytes + * @param {T} options.value + */ constructor ({ cid, bytes, value }) { if (!cid || !bytes || typeof value === 'undefined') throw new Error('Missing required argument') - setImmutable(this, 'bytes', bytes) - setImmutable(this, 'value', value) - setImmutable(this, 'cid', cid) - setImmutable(this, 'asBlock', this, false) + + this.cid = cid + this.bytes = bytes + this.value = value + this.asBlock = this + + // Mark all the properties immutable + Object.defineProperties(this, { + cid: readonly(), + bytes: readonly(), + value: readonly(), + asBlock: readonly() + }) } links () { - return links(this.value) + return links(this.value, []) } tree () { - return tree(this.value) + return tree(this.value, []) } - get (path) { - let node = this.value - path = path.split('/').filter(x => x) - while (path.length) { - const key = path.shift() - if (node[key] === undefined) { throw new Error(`Object has no property "${key}"`) } - node = node[key] - const cid = CID.asCID(node) - if (cid) return { value: cid, remaining: path.join('/') } - } - return { value: node } + /** + * @param {string} [path] + */ + get (path = '/') { + return get(this.value, path.split('/').filter(Boolean)) } } +/** + * @template T + * @template {number} Code + * @template {number} Algorithm + * @param {Object} options + * @param {T} options.value + * @param {BlockEncoder} options.codec + * @param {Hasher} options.hasher + * @returns {Promise>} + */ const encode = async ({ value, codec, hasher }) => { if (typeof value === 'undefined') throw new Error('Missing required argument "value"') if (!codec || !hasher) throw new Error('Missing required argument: codec or hasher') + const bytes = codec.encode(value) const hash = await hasher.digest(bytes) const cid = CID.create(1, codec.code, hash) + return new Block({ value, bytes, cid }) } + +/** + * @template T + * @template {number} Code + * @template {number} Algorithm + * @param {Object} options + * @param {ByteView} options.bytes + * @param {BlockDecoder} options.codec + * @param {Hasher} options.hasher + * @returns {Promise>} + */ const decode = async ({ bytes, codec, hasher }) => { if (!bytes) throw new Error('Missing required argument "bytes"') if (!codec || !hasher) throw new Error('Missing required argument: codec or hasher') + const value = codec.decode(bytes) const hash = await hasher.digest(bytes) const cid = CID.create(1, codec.code, hash) + return new Block({ value, bytes, cid }) } -const createUnsafe = ({ bytes, cid, value, codec }) => { - if (!codec) throw new Error('Missing required argument "codec"') - if (typeof value === 'undefined') value = codec.decode(bytes) - return new Block({ bytes, cid, value }) + +/** + * @typedef {Object} RequiredCreateOptions + * @property {CID} options.cid + */ + +/** + * @template T + * @template {number} Code + * @param {{ cid: CID, value:T, codec?: BlockDecoder, bytes: ByteView }|{cid:CID, bytes:ByteView, value?:void, codec:BlockDecoder}} options + * @returns {Block} + */ +const createUnsafe = ({ bytes, cid, value: maybeValue, codec }) => { + const value = maybeValue !== undefined + ? maybeValue + : (codec && codec.decode(bytes)) + + if (value === undefined) throw new Error('Missing required argument, must either provide "value" or "codec"') + + return new Block({ cid, bytes, value }) } + +/** + * @template T + * @template {number} Code + * @template {number} Algorithm + * @param {Object} options + * @param {CID} options.cid + * @param {ByteView} options.bytes + * @param {BlockDecoder} options.codec + * @param {Hasher} options.hasher + * @returns {Promise>} + */ const create = async ({ bytes, cid, hasher, codec }) => { if (!bytes) throw new Error('Missing required argument "bytes"') if (!hasher) throw new Error('Missing required argument "hasher"') @@ -131,7 +212,30 @@ const create = async ({ bytes, cid, hasher, codec }) => { if (!binary.equals(cid.multihash.bytes, hash.bytes)) { throw new Error('CID hash does not match bytes') } - return createUnsafe({ bytes, cid, value, codec, hasher }) + + return createUnsafe({ bytes, cid, value, codec }) } export { encode, decode, create, createUnsafe, Block } + +/** + * @template T + * @typedef {import('./codecs/interface').ByteView} ByteView + */ + +/** + * @template {number} Code + * @template T + * @typedef {import('./codecs/interface').BlockEncoder} BlockEncoder + */ + +/** + * @template {number} Code + * @template T + * @typedef {import('./codecs/interface').BlockDecoder} BlockDecoder + */ + +/** + * @template Algorithm + * @typedef {import('./hashes/interface').MultihashHasher} Hasher + */ diff --git a/src/bytes.js b/src/bytes.js index 5ed30fe1..6774d44a 100644 --- a/src/bytes.js +++ b/src/bytes.js @@ -1,5 +1,3 @@ -// @ts-check - const empty = new Uint8Array(0) /** @@ -11,8 +9,8 @@ const toHex = d => d.reduce((hex, byte) => hex + byte.toString(16).padStart(2, ' * @param {string} hex */ const fromHex = hex => { - if (!hex.length) return empty - return new Uint8Array(hex.match(/../g).map(b => parseInt(b, 16))) + const hexes = hex.match(/../g) + return hexes ? new Uint8Array(hexes.map(b => parseInt(b, 16))) : empty } /** diff --git a/src/cid.js b/src/cid.js index 7d2b54ca..88c7b4a6 100644 --- a/src/cid.js +++ b/src/cid.js @@ -1,5 +1,3 @@ -// @ts-check - import * as varint from './varint.js' import * as Digest from './hashes/digest.js' import { base58btc } from './bases/base58.js' @@ -150,6 +148,10 @@ export default class CID { // Deprecated + /** + * @param {any} value + * @returns {value is CID} + */ static isCID (value) { deprecate(/^0\.0/, IS_CID_DEPRECATION) return !!(value && (value[cidSymbol] || value.asCID === value)) @@ -291,15 +293,15 @@ export default class CID { } /** - * Takes cid in a string representation and creates an instance. If `base` - * decoder is not provided will use a default from the configuration. It will - * throw an error if encoding of the CID is not compatible with supplied (or - * a default decoder). - * - * @template {string} Prefix - * @param {string} source - * @param {MultibaseDecoder} [base] - */ + * Takes cid in a string representation and creates an instance. If `base` + * decoder is not provided will use a default from the configuration. It will + * throw an error if encoding of the CID is not compatible with supplied (or + * a default decoder). + * + * @template {string} Prefix + * @param {string} source + * @param {MultibaseDecoder} [base] + */ static parse (source, base) { const [prefix, bytes] = parseCIDtoBytes(source, base) @@ -312,6 +314,12 @@ export default class CID { } } +/** + * @template {string} Prefix + * @param {string} source + * @param {MultibaseDecoder} [base] + * @returns {[string, Uint8Array]} + */ const parseCIDtoBytes = (source, base) => { switch (source[0]) { // CIDv0 is parsed differently @@ -404,6 +412,11 @@ const hidden = { writable: false, enumerable: false, configurable: false } // should come from. To workaround it version is copied here. const version = '0.0.0-dev' // Start throwing exceptions on major version bump +/** + * + * @param {RegExp} range + * @param {string} message + */ const deprecate = (range, message) => { if (range.test(version)) { console.warn(message) diff --git a/src/hashes/digest.js b/src/hashes/digest.js index ea7a29bb..206e891b 100644 --- a/src/hashes/digest.js +++ b/src/hashes/digest.js @@ -1,5 +1,3 @@ -// @ts-check - import { coerce, equals as equalBytes } from '../bytes.js' import * as varint from '../varint.js' @@ -25,7 +23,7 @@ export const create = (code, digest) => { /** * Turns bytes representation of multihash digest into an instance. * @param {Uint8Array} multihash - * @returns {Digest} + * @returns {MultihashDigest} */ export const decode = (multihash) => { const bytes = coerce(multihash) diff --git a/src/hashes/hasher.js b/src/hashes/hasher.js index 6b14de2d..215bd74d 100644 --- a/src/hashes/hasher.js +++ b/src/hashes/hasher.js @@ -1,5 +1,3 @@ -// @ts-check - import * as Digest from './digest.js' /** @@ -36,7 +34,7 @@ export class Hasher { /** * @param {Uint8Array} input - * @returns {Promise} + * @returns {Promise>} */ async digest (input) { if (input instanceof Uint8Array) { diff --git a/src/hashes/sha2-browser.js b/src/hashes/sha2-browser.js index 18417e91..b89cd742 100644 --- a/src/hashes/sha2-browser.js +++ b/src/hashes/sha2-browser.js @@ -1,8 +1,12 @@ -// @ts-check - import { from } from './hasher.js' +/** + * @param {AlgorithmIdentifier} name + */ const sha = name => + /** + * @param {Uint8Array} data + */ async data => new Uint8Array(await window.crypto.subtle.digest(name, data)) export const sha256 = from({ diff --git a/src/index.js b/src/index.js index d3d3144e..989edc65 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,3 @@ -// @ts-check - import CID from './cid.js' import * as varint from './varint.js' import * as bytes from './bytes.js' diff --git a/src/legacy.js b/src/legacy.js index d189526d..de2753b2 100644 --- a/src/legacy.js +++ b/src/legacy.js @@ -1,18 +1,20 @@ -// @ts-check - import OldCID from 'cids' import * as bytes from './bytes.js' import { Buffer } from 'buffer' import CID from './cid.js' /** + * @template {number} Code * @template T - * @param {BlockCodec} codec + * @param {BlockCodec} codec * @param {Object} options * @param {Object} options.hashes */ const legacy = (codec, { hashes }) => { + /** + * @param {*} obj + */ const toLegacy = obj => { if (OldCID.isCID(obj)) { return obj @@ -40,6 +42,9 @@ const legacy = (codec, { hashes }) => { return obj } + /** + * @param {*} obj + */ const fromLegacy = obj => { const cid = CID.asCID(obj) if (cid) return cid @@ -94,6 +99,7 @@ const legacy = (codec, { hashes }) => { let value = codec.decode(buff) const entries = path.split('/').filter(x => x) while (entries.length) { + // @ts-ignore value = value[/** @type {string} */(entries.shift())] if (typeof value === 'undefined') throw new Error('Not found') if (OldCID.isCID(value)) { @@ -139,8 +145,9 @@ export default legacy */ /** + * @template {number} Code * @template T - * @typedef {import('./codecs/interface').BlockCodec} BlockCodec + * @typedef {import('./codecs/interface').BlockCodec} BlockCodec */ /** diff --git a/src/varint.js b/src/varint.js index 42d4976b..0fa7b319 100644 --- a/src/varint.js +++ b/src/varint.js @@ -6,7 +6,6 @@ import varint from '../vendor/varint.js' */ export const decode = (data) => { const code = varint.decode(data) - // @ts-ignore return [code, varint.decode.bytes] } diff --git a/test/test-block.js b/test/test-block.js index 1e976de2..a4cbf1ca 100644 --- a/test/test-block.js +++ b/test/test-block.js @@ -61,7 +61,7 @@ describe('block', () => { test('kitchen sink', () => { const sink = { one: { two: { arr: [true, false, null], three: 3, buff, link } } } - const block = main.createUnsafe({ value: sink, codec, hasher, bytes: true, cid: true }) + const block = main.createUnsafe({ value: sink, codec, bytes: true, cid: true }) same(sink, block.value) }) @@ -95,7 +95,7 @@ describe('block', () => { await errTest(main.decode, { bytes: true }, 'Missing required argument: codec or hasher') }) test('createUnsafe', async () => { - await errTest(main.createUnsafe, {}, 'Missing required argument "codec"') + await errTest(main.createUnsafe, {}, 'Missing required argument, must either provide "value" or "codec"') }) test('create', async () => { await errTest(main.create, {}, 'Missing required argument "bytes"') @@ -106,7 +106,7 @@ describe('block', () => { }) test('get', async () => { const block = await main.encode({ value: fixture, codec, hasher }) - await errTest(path => block.get(path), '/asd/fs/dfasd/f', 'Object has no property "asd"') + await errTest(path => block.get(path), '/asd/fs/dfasd/f', 'Object has no property at ["asd"]') }) }) }) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..f3a1d604 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,42 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": false, + "noImplicitAny": true, + "noImplicitThis": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "strictFunctionTypes": false, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "strictBindCallApply": true, + "strict": true, + "alwaysStrict": true, + "esModuleInterop": true, + "target": "ES2018", + "moduleResolution": "node", + "declaration": true, + "declarationMap": true, + "outDir": "dist", + "skipLibCheck": true, + "stripInternal": true, + "resolveJsonModule": true, + "paths": { + "multiformats": [ + "src" + ] + }, + "baseUrl": ".", + }, + "include": [ + "src", + ], + "exclude": [ + "vendor", + "node_modules" + ], + "compileOnSave": false +} diff --git a/vendor/base-x.d.ts b/vendor/base-x.d.ts new file mode 100644 index 00000000..f8555ef9 --- /dev/null +++ b/vendor/base-x.d.ts @@ -0,0 +1,9 @@ +declare function base(ALPHABET: string): base.BaseConverter; +export = base; +declare namespace base { + interface BaseConverter { + encode(buffer: Uint8Array | number[]): string; + decodeUnsafe(string: string): Uint8Array | undefined; + decode(string: string): Uint8Array; + } +} diff --git a/vendor/varint.d.ts b/vendor/varint.d.ts new file mode 100644 index 00000000..11e2e2d7 --- /dev/null +++ b/vendor/varint.d.ts @@ -0,0 +1,46 @@ +// Type definitions for varint 5.0 +// Project: https://github.com/chrisdickinson/varint#readme +// Definitions by: David Brockman Smoliansky +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +export const encode: { + /** + * Encodes `num` into `buffer` starting at `offset`. returns `buffer`, with the encoded varint written into it. + * `varint.encode.bytes` will now be set to the number of bytes modified. + */ + (num: number, buffer: Uint8Array, offset?: number): Buffer; + + /** + * Encodes `num` into `array` starting at `offset`. returns `array`, with the encoded varint written into it. + * If `array` is not provided, it will default to a new array. + * `varint.encode.bytes` will now be set to the number of bytes modified. + */ + (num: number, array?: number[], offset?: number): number[] + + /** + * Similar to `decode.bytes` when encoding a number it can be useful to know how many bytes where written (especially if you pass an output array). + * You can access this via `varint.encode.bytes` which holds the number of bytes written in the last encode. + */ + bytes: number +} + +export const decode: { + /** + * Decodes `data`, which can be either a buffer or array of integers, from position `offset` or default 0 and returns the decoded original integer. + * Throws a `RangeError` when `data` does not represent a valid encoding. + */ + (buf: Uint8Array | number[], offset?: number): number + + /** + * If you also require the length (number of bytes) that were required to decode the integer you can access it via `varint.decode.bytes`. + * This is an integer property that will tell you the number of bytes that the last .decode() call had to use to decode. + */ + bytes: number +} + +/** + * returns the number of bytes this number will be encoded as, up to a maximum of 8. + */ +export function encodingLength(num: number): number From 7c7ebfab95fbfc5d0a7d76e2bd848a8b0bf91b9a Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 9 Oct 2020 11:00:20 -0700 Subject: [PATCH 2/6] chore: use different github action --- .github/workflows/mikeals-workflow.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mikeals-workflow.yml b/.github/workflows/mikeals-workflow.yml index 09d1bc4d..b3fcc360 100644 --- a/.github/workflows/mikeals-workflow.yml +++ b/.github/workflows/mikeals-workflow.yml @@ -23,7 +23,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - name: Typecheck - uses: andoshin11/typescript-error-reporter-action@v1.0.2 + uses: icrawl/action-tsc@v1 - name: Test run: npm_config_yes=true npx best-test@latest publish: @@ -43,7 +43,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - name: Typecheck - uses: andoshin11/typescript-error-reporter-action@v1.0.2 + uses: icrawl/action-tsc@v1 - name: Test run: npm_config_yes=true npx best-test@latest diff --git a/package.json b/package.json index 47930233..ef0f3ab7 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build:vendor:base-x": "npx brrp -x @multiformats/base-x > vendor/base-x.js", "publish": "npm_config_yes=true npx ipjs@latest publish", "lint": "standard", - "check": "tsc --noEmit", + "check": "tsc --noEmit --noErrorTruncation", "test:cjs": "npm run build && mocha dist/cjs/node-test/test-*.js && npm run test:cjs:browser", "test:node": "hundreds mocha test/test-*.js", "test:cjs:browser": "polendina --cleanup dist/cjs/browser-test/test-*.js", From f63e5e09f02a894da519972c8d6e64c766cd4a44 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 9 Oct 2020 12:00:43 -0700 Subject: [PATCH 3/6] fix: tsconfig to be a valid json --- .github/workflows/mikeals-workflow.yml | 4 ++-- tsconfig.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mikeals-workflow.yml b/.github/workflows/mikeals-workflow.yml index b3fcc360..09d1bc4d 100644 --- a/.github/workflows/mikeals-workflow.yml +++ b/.github/workflows/mikeals-workflow.yml @@ -23,7 +23,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - name: Typecheck - uses: icrawl/action-tsc@v1 + uses: andoshin11/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest publish: @@ -43,7 +43,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - name: Typecheck - uses: icrawl/action-tsc@v1 + uses: andoshin11/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest diff --git a/tsconfig.json b/tsconfig.json index f3a1d604..4ce54b0e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,10 +29,10 @@ "src" ] }, - "baseUrl": ".", + "baseUrl": "." }, "include": [ - "src", + "src" ], "exclude": [ "vendor", From 4e58a2e0cd551938336e9a531051654c6043d6f1 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 9 Oct 2020 12:09:04 -0700 Subject: [PATCH 4/6] chore: use my own fork --- .github/workflows/mikeals-workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mikeals-workflow.yml b/.github/workflows/mikeals-workflow.yml index 09d1bc4d..64962a9c 100644 --- a/.github/workflows/mikeals-workflow.yml +++ b/.github/workflows/mikeals-workflow.yml @@ -23,7 +23,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - name: Typecheck - uses: andoshin11/typescript-error-reporter-action@v1.0.2 + uses: gozala/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest publish: @@ -43,7 +43,7 @@ jobs: if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - name: Typecheck - uses: andoshin11/typescript-error-reporter-action@v1.0.2 + uses: gozala/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest From eb3c81f3e951e3cc1450ff27416afb37f86638d4 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 9 Oct 2020 12:14:32 -0700 Subject: [PATCH 5/6] chore: split typecheck flow into separate action --- .github/workflows/mikeals-workflow.yml | 4 ---- .github/workflows/typecheck.yml | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/typecheck.yml diff --git a/.github/workflows/mikeals-workflow.yml b/.github/workflows/mikeals-workflow.yml index 64962a9c..1b88e24a 100644 --- a/.github/workflows/mikeals-workflow.yml +++ b/.github/workflows/mikeals-workflow.yml @@ -22,8 +22,6 @@ jobs: - name: Build if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - - name: Typecheck - uses: gozala/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest publish: @@ -42,8 +40,6 @@ jobs: - name: Build if: steps.cache-modules.outputs.cache-hit != 'true' run: npm install - - name: Typecheck - uses: gozala/typescript-error-reporter-action@v1.0.2 - name: Test run: npm_config_yes=true npx best-test@latest diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml new file mode 100644 index 00000000..2b0f59ab --- /dev/null +++ b/.github/workflows/typecheck.yml @@ -0,0 +1,18 @@ +on: [push, pull_request] +name: Typecheck +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [12.x] + steps: + - uses: actions/checkout@v1 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Install dependencies + run: npm install + - name: Typecheck + uses: gozala/typescript-error-reporter-action@v1.0.2 From 1ce28233601666d11e91db29df6fd057f2baba74 Mon Sep 17 00:00:00 2001 From: Irakli Gozalishvili Date: Fri, 9 Oct 2020 13:49:49 -0700 Subject: [PATCH 6/6] chore: improve CI integrations --- .github/workflows/typecheck.yml | 13 +++++++++++-- package.json | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 2b0f59ab..e618c217 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -1,7 +1,16 @@ -on: [push, pull_request] +on: + push: + branches: + - master + - main + - default + pull_request: + branches: + - '**' + name: Typecheck jobs: - test: + check: runs-on: ubuntu-latest strategy: matrix: diff --git a/package.json b/package.json index ef0f3ab7..be65bbd7 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "publish": "npm_config_yes=true npx ipjs@latest publish", "lint": "standard", "check": "tsc --noEmit --noErrorTruncation", - "test:cjs": "npm run build && mocha dist/cjs/node-test/test-*.js && npm run test:cjs:browser", + "test:cjs": "npm run build:js && mocha dist/cjs/node-test/test-*.js && npm run test:cjs:browser", "test:node": "hundreds mocha test/test-*.js", "test:cjs:browser": "polendina --cleanup dist/cjs/browser-test/test-*.js", "test": "npm run lint && npm run test:node && npm run test:cjs",