From fd71e71de4c44cac159d305b651a164ef217ae8b Mon Sep 17 00:00:00 2001 From: Yukan Date: Thu, 8 Oct 2020 00:25:03 -0400 Subject: [PATCH] feat: build update for common, encryption and storage packages --- packages/common/package.json | 34 ++++++----- packages/common/src/errors.ts | 6 +- packages/common/src/utils.ts | 4 +- packages/common/tests/utils.test.ts | 37 +----------- packages/common/tsconfig.json | 52 +++++++++++++++-- packages/common/tsdx.config.js | 15 +++++ packages/encryption/package.json | 34 ++++++----- packages/encryption/src/cryptoRandom.ts | 4 +- packages/encryption/src/encryption.ts | 4 +- packages/encryption/src/keys.ts | 4 +- packages/encryption/src/wallet.ts | 6 +- packages/encryption/tests/encryption.test.ts | 2 +- packages/encryption/tsconfig.json | 50 ++++++++++++++-- packages/encryption/tsdx.config.js | 15 +++++ packages/keychain/tests/identity.test.ts | 8 +-- packages/profile/src/index.ts | 2 +- .../src/profileSchemas/creativework.ts | 46 --------------- packages/profile/src/profileSchemas/index.ts | 2 - .../src/profileSchemas/organization.ts | 41 ------------- packages/profile/tests/schema.test.ts | 4 +- packages/storage/package.json | 32 ++++++---- packages/storage/src/hub.ts | 5 +- packages/storage/src/storage.ts | 58 +++++++++---------- packages/storage/tests/storage.test.ts | 51 ++++++++-------- packages/storage/tsconfig.json | 52 +++++++++++++++-- packages/storage/tsdx.config.js | 15 +++++ 26 files changed, 322 insertions(+), 261 deletions(-) create mode 100644 packages/common/tsdx.config.js create mode 100644 packages/encryption/tsdx.config.js delete mode 100644 packages/profile/src/profileSchemas/creativework.ts delete mode 100644 packages/profile/src/profileSchemas/organization.ts create mode 100644 packages/storage/tsdx.config.js diff --git a/packages/common/package.json b/packages/common/package.json index 0db2c913b..12955137f 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -5,9 +5,6 @@ "author": "yknl ", "homepage": "https://blockstack.org", "license": "GPL-3.0-or-later", - "main": "./dist/index.js", - "umd:main": "./dist/common.umd.production.js", - "module": "./dist/common.esm.js", "directories": { "lib": "lib", "dist": "dist", @@ -24,12 +21,17 @@ "url": "git+https://github.com/blockstack/blockstack.js.git" }, "scripts": { - "build": "cross-env NODE_ENV=production tsdx build --format=cjs,esm,umd", - "build-all": "run-p build:*", - "build:cjs": "tsc --outDir ./lib -m commonjs -t es2017", - "build:esm": "tsc --outDir ./lib-esm -m es6 -t es2017", - "build:cjs:watch": "tsc --outDir ./lib -m commonjs -t es2017 --watch", - "build:esm:watch": "tsc --outDir ./lib-esm -m es6 -t es2017 --watch", + "dev": "yarn start", + "lint": "yarn lint:eslint && yarn lint:prettier", + "lint:eslint": "eslint \"src/**/*.{ts,tsx}\" -f unix", + "lint:fix": "eslint \"src/**/*.{ts,tsx}\" -f unix --fix", + "lint:prettier": "prettier --check \"src/**/*.{ts,tsx}\" *.js", + "lint:prettier:fix": "prettier --write \"src/**/*.{ts,tsx}\" *.js", + "start": "tsdx watch --verbose --noClean --onSuccess yalc publish --push", + "build": "tsdx build --format cjs,esm,umd", + "typecheck": "tsc --noEmit", + "typecheck:watch": "npm run typecheck -- --watch", + "prepublishOnly": "yarn build", "test": "jest", "test:watch": "jest --watch --coverage=false", "codecovUpload": "codecov" @@ -40,12 +42,18 @@ "dependencies": { "bitcoinjs-lib": "^5.1.10", "codecov": "^3.7.2", - "cross-fetch": "^3.0.5", - "tsdx": "^0.13.3" + "cross-fetch": "^3.0.5" }, "devDependencies": { "@types/jest": "24.9.0", "jest": "^24.9.0", - "jest-fetch-mock": "^3.0.3" - } + "jest-fetch-mock": "^3.0.3", + "tsdx": "^0.14.0" + }, + "sideEffects": false, + "main": "dist/index.js", + "module": "dist/index.esm.js", + "typings": "dist/auth/src/index.d.ts", + "umd:main": "dist/auth.umd.production.js", + "unpkg": "dist/auth.cjs.production.min.js" } diff --git a/packages/common/src/errors.ts b/packages/common/src/errors.ts index 782ee5d35..250b92eb3 100644 --- a/packages/common/src/errors.ts +++ b/packages/common/src/errors.ts @@ -75,7 +75,7 @@ export class BlockstackError extends Error { */ export class InvalidParameterError extends BlockstackError { constructor(parameter: string, message: string = '') { - super({ code: ERROR_CODES.MISSING_PARAMETER, message, parameter: '' }); + super({ code: ERROR_CODES.MISSING_PARAMETER, message, parameter }); this.name = 'MissingParametersError'; } } @@ -301,8 +301,8 @@ export class PayloadTooLargeError extends GaiaHubError { maxUploadByteSize: number; - constructor(message: string, response: GaiaHubErrorResponse, maxUploadByteSize: number) { - super({ message, code: ERROR_CODES.PAYLOAD_TOO_LARGE_ERROR }, response); + constructor(message: string, response: GaiaHubErrorResponse | null, maxUploadByteSize: number) { + super({ message, code: ERROR_CODES.PAYLOAD_TOO_LARGE_ERROR }, response!); this.name = 'PayloadTooLargeError'; this.maxUploadByteSize = maxUploadByteSize; } diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index b4bd802a5..dded30b4e 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -91,11 +91,11 @@ export function updateQueryStringParameter(uri: string, key: string, value: stri */ export function isLaterVersion(v1: string, v2: string) { - if (v1 === undefined) { + if (v1 === undefined || v1 === '') { v1 = '0.0.0'; } - if (v2 === undefined) { + if (v2 === undefined || v1 === '') { v2 = '0.0.0'; } diff --git a/packages/common/tests/utils.test.ts b/packages/common/tests/utils.test.ts index 441a62876..3d67f5a1c 100644 --- a/packages/common/tests/utils.test.ts +++ b/packages/common/tests/utils.test.ts @@ -1,42 +1,7 @@ -// import { SECP256K1Client } from 'jsontokens' -// import { -// getEntropy, makeECPrivateKey, publicKeyToAddress, isSameOriginAbsoluteUrl, -// ecPairToHexString, hexStringToECPair, ecPairToAddress, isLaterVersion -// } from '../src' - import { isSameOriginAbsoluteUrl, isLaterVersion } from '../src' -// test('makeECPrivateKey', () => { -// t.plan(5) - -// const entropy = getEntropy(32) -// t.ok(entropy, 'Entropy should have been created') - -// const privateKey = makeECPrivateKey() -// t.ok(privateKey, 'Private key should have been created') -// t.equal(typeof privateKey, 'string', 'Private key should be a string') - -// const publicKey = SECP256K1Client.derivePublicKey(privateKey) - -// const address = publicKeyToAddress(publicKey) -// t.ok(address, 'Address should have been created') -// t.equal(typeof address, 'string', 'Address should be a string') -// }) - -// test('ecPairToHexString', (t) => { -// t.plan(2) - -// const privateKey = '00cdce6b5f87d38f2a830cae0da82162e1b487f07c5affa8130f01fe1a2a25fb01' -// const expectedAddress = '1WykMawQRnLh7SWmmoRL4qTDNCgAsVRF1' - -// const computedECPair = hexStringToECPair(privateKey) -// t.equal(privateKey, ecPairToHexString(computedECPair), 'Should return same hex string') - -// t.equal(expectedAddress, ecPairToAddress(computedECPair), 'Should parse to correct address') -// }) - test('isLaterVersion', () => { - expect(isLaterVersion(undefined, '1.1.0')).toEqual(false) + expect(isLaterVersion('', '1.1.0')).toEqual(false) expect(isLaterVersion('1.2.0', '1.1.0')).toEqual(true) expect(isLaterVersion('1.1.0', '1.1.0')).toEqual(true) expect(isLaterVersion('1.1.0', '1.2.0')).toEqual(false) diff --git a/packages/common/tsconfig.json b/packages/common/tsconfig.json index 6b1c6c98a..6a0cf479a 100644 --- a/packages/common/tsconfig.json +++ b/packages/common/tsconfig.json @@ -1,7 +1,47 @@ { - "extends": "../../tsconfig.json", - "include": [ - "./src/**/*", - "./tests/**/*" - ] -} \ No newline at end of file + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "lib": ["dom", "esnext"], + "jsx": "react", + "importHelpers": true, + "declaration": true, + "sourceMap": true, + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, + "strict": true, + "pretty": true, + "removeComments": true, + "noImplicitAny": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "alwaysStrict": true, + "stripInternal": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "emitDecoratorMetadata": false, + "noEmit": false, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "suppressImplicitAnyIndexErrors": false, + "outDir": "./dist", + "baseUrl": "./src", + "skipLibCheck": true, + "esModuleInterop": true, + "strictNullChecks": true, + "paths": { + "@stacks/auth": ["../../auth/src"], + "@stacks/cli": ["../../cli/src"], + "@stacks/common": ["../../common/src"], + "@stacks/encryption": ["../../encryption/src"], + "@stacks/keychain": ["../../keychain/src"], + "@stacks/network": ["../../network/src"], + "@stacks/profile": ["../../profile/src"], + "@stacks/storage": ["../../storage/src"], + "@stacks/transactions": ["../../transactions/src"] + } + }, + "include": ["src/**/*", "tests/**/*"] +} diff --git a/packages/common/tsdx.config.js b/packages/common/tsdx.config.js new file mode 100644 index 000000000..d5839e6ad --- /dev/null +++ b/packages/common/tsdx.config.js @@ -0,0 +1,15 @@ +module.exports = { + rollup(config, options) { + if (options.format === 'esm') { + config.output = { + ...config.output, + dir: 'dist/', + entryFileNames: '[name].esm.js', + preserveModules: true, + preserveModulesRoot: 'src', + }; + delete config.output.file; + } + return config; + }, +}; diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 4f3569038..fc34ba0a3 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -5,9 +5,6 @@ "author": "yknl ", "homepage": "https://blockstack.org", "license": "GPL-3.0-or-later", - "main": "./dist/index.js", - "umd:main": "./dist/common.umd.production.js", - "module": "./dist/common.esm.js", "directories": { "lib": "lib", "dist": "dist", @@ -21,12 +18,17 @@ "url": "git+https://github.com/blockstack/blockstack.js.git" }, "scripts": { - "build": "cross-env NODE_ENV=production tsdx build --format=cjs,esm,umd", - "build-all": "run-p build:*", - "build:cjs": "tsc --outDir ./lib -m commonjs -t es2017", - "build:esm": "tsc --outDir ./lib-esm -m es6 -t es2017", - "build:cjs:watch": "tsc --outDir ./lib -m commonjs -t es2017 --watch", - "build:esm:watch": "tsc --outDir ./lib-esm -m es6 -t es2017 --watch", + "dev": "yarn start", + "lint": "yarn lint:eslint && yarn lint:prettier", + "lint:eslint": "eslint \"src/**/*.{ts,tsx}\" -f unix", + "lint:fix": "eslint \"src/**/*.{ts,tsx}\" -f unix --fix", + "lint:prettier": "prettier --check \"src/**/*.{ts,tsx}\" *.js", + "lint:prettier:fix": "prettier --write \"src/**/*.{ts,tsx}\" *.js", + "start": "tsdx watch --verbose --noClean --onSuccess yalc publish --push", + "build": "tsdx build --format cjs,esm,umd", + "typecheck": "tsc --noEmit", + "typecheck:watch": "npm run typecheck -- --watch", + "prepublishOnly": "yarn build", "test": "jest", "test:watch": "jest --watch --coverage=false", "codecovUpload": "codecov" @@ -43,12 +45,18 @@ "elliptic": "^6.5.2", "randombytes": "^2.1.0", "ripemd160-min": "^0.0.6", - "sha.js": "^2.4.11", - "tsdx": "^0.13.3" + "sha.js": "^2.4.11" }, "devDependencies": { "@types/jest": "24.9.0", "jest": "^24.9.0", - "jest-fetch-mock": "^3.0.3" - } + "jest-fetch-mock": "^3.0.3", + "tsdx": "^0.14.0" + }, + "sideEffects": false, + "main": "dist/index.js", + "module": "dist/index.esm.js", + "typings": "dist/auth/src/index.d.ts", + "umd:main": "dist/auth.umd.production.js", + "unpkg": "dist/auth.cjs.production.min.js" } diff --git a/packages/encryption/src/cryptoRandom.ts b/packages/encryption/src/cryptoRandom.ts index 4097127ac..699d00aac 100644 --- a/packages/encryption/src/cryptoRandom.ts +++ b/packages/encryption/src/cryptoRandom.ts @@ -1,6 +1,4 @@ -import * as randombytes_ from 'randombytes'; - -let randombytes = randombytes_; +import randombytes from 'randombytes'; export { randombytes as randomBytes }; diff --git a/packages/encryption/src/encryption.ts b/packages/encryption/src/encryption.ts index 04e0fa361..9591084a1 100644 --- a/packages/encryption/src/encryption.ts +++ b/packages/encryption/src/encryption.ts @@ -60,7 +60,7 @@ export async function encryptContent( options?: EncryptContentOptions ): Promise { const opts = Object.assign({}, options); - let privateKey: string; + let privateKey: string | undefined; if (!opts.publicKey) { if (!opts.privateKey) { throw new Error('Either public key or private key must be supplied for encryption.'); @@ -87,7 +87,7 @@ export async function encryptContent( } else if (!privateKey) { privateKey = opts.privateKey; } - const signatureObject = signECDSA(privateKey, cipherPayload); + const signatureObject = signECDSA(privateKey!, cipherPayload); const signedCipherObject: SignedCipherObject = { signature: signatureObject.signature, publicKey: signatureObject.publicKey, diff --git a/packages/encryption/src/keys.ts b/packages/encryption/src/keys.ts index e92da6d08..6a4a2fc15 100644 --- a/packages/encryption/src/keys.ts +++ b/packages/encryption/src/keys.ts @@ -21,7 +21,7 @@ export function getEntropy(arg: number): Buffer { */ export function makeECPrivateKey() { const keyPair = ECPair.makeRandom({ rng: getEntropy }); - return keyPair.privateKey.toString('hex'); + return keyPair.privateKey!.toString('hex'); } /** @@ -77,7 +77,7 @@ export function hexStringToECPair(skHex: string, network?: Network): ECPair.ECPa * @ignore */ export function ecPairToHexString(secretKey: ECPair.ECPairInterface) { - const ecPointHex = secretKey.privateKey.toString('hex'); + const ecPointHex = secretKey.privateKey!.toString('hex'); if (secretKey.compressed) { return `${ecPointHex}01`; } else { diff --git a/packages/encryption/src/wallet.ts b/packages/encryption/src/wallet.ts index b987df619..c584ee8fa 100644 --- a/packages/encryption/src/wallet.ts +++ b/packages/encryption/src/wallet.ts @@ -120,20 +120,20 @@ async function decryptMnemonicBuffer(dataBuffer: Buffer, password: string): Prom function decryptLegacy( dataBuffer: Buffer, password: string, - triplesecDecrypt: TriplesecDecryptSignature + triplesecDecrypt?: TriplesecDecryptSignature ): Promise { return new Promise((resolve, reject) => { if (!triplesecDecrypt) { reject(new Error('The `triplesec.decrypt` function must be provided')); } - triplesecDecrypt( + triplesecDecrypt!( { key: Buffer.from(password), data: dataBuffer, }, (err, plaintextBuffer) => { if (!err) { - resolve(plaintextBuffer); + resolve(plaintextBuffer!); } else { reject(err); } diff --git a/packages/encryption/tests/encryption.test.ts b/packages/encryption/tests/encryption.test.ts index f9bba9591..9d3f9c620 100644 --- a/packages/encryption/tests/encryption.test.ts +++ b/packages/encryption/tests/encryption.test.ts @@ -11,7 +11,7 @@ import * as aesCipher from '../src/aesCipher' import * as sha2Hash from '../src/sha2Hash' import * as hmacSha256 from '../src/hmacSha256' import * as ripemd160 from '../src/hashRipemd160' -import * as BN from 'bn.js' +import BN from 'bn.js' import { getBufferFromBN } from '../src/ec' const privateKey = 'a5c61c6ca7b3e7e55edee68566aeab22e4da26baa285c7bd10e8d2218aa3b229' diff --git a/packages/encryption/tsconfig.json b/packages/encryption/tsconfig.json index 0e3bcce17..6a0cf479a 100644 --- a/packages/encryption/tsconfig.json +++ b/packages/encryption/tsconfig.json @@ -1,7 +1,47 @@ { - "extends": "../../tsconfig.json", - "include": [ - "./src/**/*", - "./tests/**/*" - ] + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "lib": ["dom", "esnext"], + "jsx": "react", + "importHelpers": true, + "declaration": true, + "sourceMap": true, + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, + "strict": true, + "pretty": true, + "removeComments": true, + "noImplicitAny": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "alwaysStrict": true, + "stripInternal": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "emitDecoratorMetadata": false, + "noEmit": false, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "suppressImplicitAnyIndexErrors": false, + "outDir": "./dist", + "baseUrl": "./src", + "skipLibCheck": true, + "esModuleInterop": true, + "strictNullChecks": true, + "paths": { + "@stacks/auth": ["../../auth/src"], + "@stacks/cli": ["../../cli/src"], + "@stacks/common": ["../../common/src"], + "@stacks/encryption": ["../../encryption/src"], + "@stacks/keychain": ["../../keychain/src"], + "@stacks/network": ["../../network/src"], + "@stacks/profile": ["../../profile/src"], + "@stacks/storage": ["../../storage/src"], + "@stacks/transactions": ["../../transactions/src"] + } + }, + "include": ["src/**/*", "tests/**/*"] } diff --git a/packages/encryption/tsdx.config.js b/packages/encryption/tsdx.config.js new file mode 100644 index 000000000..d5839e6ad --- /dev/null +++ b/packages/encryption/tsdx.config.js @@ -0,0 +1,15 @@ +module.exports = { + rollup(config, options) { + if (options.format === 'esm') { + config.output = { + ...config.output, + dir: 'dist/', + entryFileNames: '[name].esm.js', + preserveModules: true, + preserveModulesRoot: 'src', + }; + delete config.output.file; + } + return config; + }, +}; diff --git a/packages/keychain/tests/identity.test.ts b/packages/keychain/tests/identity.test.ts index f7bb8bf8f..b154181a2 100644 --- a/packages/keychain/tests/identity.test.ts +++ b/packages/keychain/tests/identity.test.ts @@ -5,8 +5,6 @@ import { decodeToken } from 'jsontokens'; import { getIdentity, profileResponse, nameInfoResponse } from './helpers'; import { ecPairToAddress } from 'blockstack'; import { ECPair } from 'bitcoinjs-lib'; -import { getAddress } from '../src'; -import { TransactionVersion } from '@blockstack/stacks-transactions'; interface Decoded { [key: string]: any; @@ -97,7 +95,7 @@ test('gets default profile URL', async () => { test('can get a profile URL from a zone file', async () => { const identity = await getIdentity(); fetchMock.once(JSON.stringify(nameInfoResponse)); - const profileURL = await identity.profileUrl('asdf'); + await identity.profileUrl('asdf'); return; }); @@ -144,7 +142,7 @@ describe('refresh', () => { await identity.refresh(); expect(identity.profile).toBeTruthy(); - expect(identity.profile?.apps).toBeTruthy(); - expect(identity.profile?.name).toBeFalsy(); + expect(identity.profile!.apps).toBeTruthy(); + expect(identity.profile!.name).toBeFalsy(); }); }); diff --git a/packages/profile/src/index.ts b/packages/profile/src/index.ts index 432d6b5c2..7fcf50466 100644 --- a/packages/profile/src/index.ts +++ b/packages/profile/src/index.ts @@ -6,7 +6,7 @@ export { resolveZoneFileToProfile, } from './profile'; -export { Organization, CreativeWork, resolveZoneFileToPerson } from './profileSchemas'; +export { resolveZoneFileToPerson } from './profileSchemas'; export { signProfileToken, diff --git a/packages/profile/src/profileSchemas/creativework.ts b/packages/profile/src/profileSchemas/creativework.ts deleted file mode 100644 index 9a13ec657..000000000 --- a/packages/profile/src/profileSchemas/creativework.ts +++ /dev/null @@ -1,46 +0,0 @@ -// @ts-ignore: Could not find a declaration file for module -import inspector from 'schema-inspector'; -import { extractProfile } from '../profileTokens'; -import { Profile } from '../profile'; - -const schemaDefinition: { [key: string]: any } = { - type: 'object', - properties: { - '@context': { type: 'string', optional: true }, - '@type': { type: 'string' }, - '@id': { type: 'string', optional: true }, - }, -}; - -/** - * @ignore - */ -export class CreativeWork extends Profile { - constructor(profile = {}) { - super(profile); - this._profile = Object.assign( - {}, - { - '@type': 'CreativeWork', - }, - this._profile - ); - } - - /** - * - * @ignore - */ - static validateSchema(profile: any, strict = false) { - schemaDefinition.strict = strict; - return inspector.validate(schemaDefinition, profile); - } - - /** - * @ignore - */ - static fromToken(token: string, publicKeyOrAddress: string | null = null): CreativeWork { - const profile = extractProfile(token, publicKeyOrAddress); - return new CreativeWork(profile); - } -} diff --git a/packages/profile/src/profileSchemas/index.ts b/packages/profile/src/profileSchemas/index.ts index 27fdd6f02..aad07f1f9 100644 --- a/packages/profile/src/profileSchemas/index.ts +++ b/packages/profile/src/profileSchemas/index.ts @@ -1,4 +1,2 @@ -export { Organization } from './organization'; -export { CreativeWork } from './creativework'; export { getPersonFromLegacyFormat } from './personLegacy'; export { resolveZoneFileToPerson } from './personZoneFiles'; diff --git a/packages/profile/src/profileSchemas/organization.ts b/packages/profile/src/profileSchemas/organization.ts deleted file mode 100644 index 8e6bee412..000000000 --- a/packages/profile/src/profileSchemas/organization.ts +++ /dev/null @@ -1,41 +0,0 @@ -// TODO: replace with 'ajv' - its already a dependency and it is maintained -// @ts-ignore: Could not find a declaration file for module -import inspector from 'schema-inspector'; - -import { extractProfile } from '../profileTokens'; -import { Profile } from '../profile'; - -const schemaDefinition: { [key: string]: any } = { - type: 'object', - properties: { - '@context': { type: 'string', optional: true }, - '@type': { type: 'string' }, - '@id': { type: 'string', optional: true }, - }, -}; - -/** - * @ignore - */ -export class Organization extends Profile { - constructor(profile = {}) { - super(profile); - this._profile = Object.assign( - {}, - { - '@type': 'Organization', - }, - this._profile - ); - } - - static validateSchema(profile: any, strict = false) { - schemaDefinition.strict = strict; - return inspector.validate(schemaDefinition, profile); - } - - static fromToken(token: string, publicKeyOrAddress: string | null = null): Organization { - const profile = extractProfile(token, publicKeyOrAddress); - return new Organization(profile); - } -} diff --git a/packages/profile/tests/schema.test.ts b/packages/profile/tests/schema.test.ts index e5a14d4db..dbafab1e9 100644 --- a/packages/profile/tests/schema.test.ts +++ b/packages/profile/tests/schema.test.ts @@ -18,7 +18,7 @@ beforeEach(() => { }); const keyPair = ECPair.makeRandom({ rng: getEntropy }) -const privateKey = keyPair.privateKey.toString('hex') +const privateKey = keyPair.privateKey!.toString('hex') const publicKey = keyPair.publicKey.toString('hex') test('Profile', () => { @@ -72,7 +72,7 @@ test('Person', () => { const verifiedAccounts = personObject.verifiedAccounts([]) expect(verifiedAccounts).toBeTruthy() - expect(verifiedAccounts.length).toEqual(0) + expect(verifiedAccounts!.length).toEqual(0) const address = personObject.address() expect(address).toBeTruthy() diff --git a/packages/storage/package.json b/packages/storage/package.json index 550d7dff4..ca5675808 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -5,7 +5,6 @@ "author": "yknl ", "homepage": "https://blockstack.org", "license": "GPL-3.0-or-later", - "main": "lib/index.js", "directories": { "lib": "lib", "dist": "dist", @@ -19,12 +18,17 @@ "url": "git+https://github.com/blockstack/blockstack.js.git" }, "scripts": { - "build": "cross-env NODE_ENV=production tsdx build --format=cjs,esm,umd", - "build-all": "run-p build:*", - "build:cjs": "tsc --outDir ./lib -m commonjs -t es2017", - "build:esm": "tsc --outDir ./lib-esm -m es6 -t es2017", - "build:cjs:watch": "tsc --outDir ./lib -m commonjs -t es2017 --watch", - "build:esm:watch": "tsc --outDir ./lib-esm -m es6 -t es2017 --watch", + "dev": "yarn start", + "lint": "yarn lint:eslint && yarn lint:prettier", + "lint:eslint": "eslint \"src/**/*.{ts,tsx}\" -f unix", + "lint:fix": "eslint \"src/**/*.{ts,tsx}\" -f unix --fix", + "lint:prettier": "prettier --check \"src/**/*.{ts,tsx}\" *.js", + "lint:prettier:fix": "prettier --write \"src/**/*.{ts,tsx}\" *.js", + "start": "tsdx watch --verbose --noClean --onSuccess yalc publish --push", + "build": "tsdx build --format cjs,esm,umd", + "typecheck": "tsc --noEmit", + "typecheck:watch": "npm run typecheck -- --watch", + "prepublishOnly": "yarn build", "test": "jest", "test:watch": "jest --watch --coverage=false", "codecovUpload": "codecov" @@ -36,12 +40,18 @@ "@stacks/auth": "^1.0.0-beta.1", "@stacks/common": "^1.0.0-beta.1", "@stacks/encryption": "^1.0.0-beta.1", - "codecov": "^3.7.2", - "tsdx": "^0.13.3" + "codecov": "^3.7.2" }, "devDependencies": { "@types/jest": "24.9.0", "jest": "^24.9.0", - "jest-fetch-mock": "^3.0.3" - } + "jest-fetch-mock": "^3.0.3", + "tsdx": "^0.14.0" + }, + "sideEffects": false, + "main": "dist/index.js", + "module": "dist/index.esm.js", + "typings": "dist/auth/src/index.d.ts", + "umd:main": "dist/auth.umd.production.js", + "unpkg": "dist/auth.cjs.production.min.js" } diff --git a/packages/storage/src/hub.ts b/packages/storage/src/hub.ts index 8566b54d3..02c8406a5 100644 --- a/packages/storage/src/hub.ts +++ b/packages/storage/src/hub.ts @@ -191,8 +191,9 @@ function makeV1GaiaAuthToken( hubUrl, iss, salt, - associationToken, + associationToken: associationToken! }; + const token = new TokenSigner('ES256K', signerKeyHex).sign(payload); return `v1:${token}`; } @@ -287,7 +288,7 @@ export async function getBlockstackErrorFromResponse( } else if (gaiaResponse.status === 412) { return new PreconditionFailedError(errorMsg, gaiaResponse); } else if (gaiaResponse.status === 413) { - const maxBytes = megabytesToBytes(hubConfig?.max_file_upload_size_megabytes); + const maxBytes = hubConfig ? megabytesToBytes(hubConfig!.max_file_upload_size_megabytes!) : 0; return new PayloadTooLargeError(errorMsg, gaiaResponse, maxBytes); } else { return new Error(errorMsg); diff --git a/packages/storage/src/storage.ts b/packages/storage/src/storage.ts index b7cabc45a..b033e8780 100644 --- a/packages/storage/src/storage.ts +++ b/packages/storage/src/storage.ts @@ -108,7 +108,7 @@ export class Storage { userSession: UserSession; constructor(options: StorageOptions) { - this.userSession = options.userSession; + this.userSession = options.userSession!; } /** @@ -124,9 +124,7 @@ export class Storage { const defaults: GetFileOptions = { decrypt: true, verify: false, - username: null, - app: getGlobalObject('location', { returnEmptyObject: true }).origin, - zoneFileLookupURL: null, + app: getGlobalObject('location', { returnEmptyObject: true })!.origin, }; const opt = Object.assign({}, defaults, options); @@ -138,7 +136,7 @@ export class Storage { const storedContents = await this.getFileContents( path, - opt.app, + opt.app!, opt.username, opt.zoneFileLookupURL, !!opt.decrypt @@ -166,7 +164,7 @@ export class Storage { return this.handleSignedEncryptedContents( path, storedContents, - opt.app, + opt.app!, decryptionKey, opt.username, opt.zoneFileLookupURL @@ -194,9 +192,9 @@ export class Storage { username: string, appOrigin: string, zoneFileLookupURL?: string - ): Promise { + ): Promise { const profile = await lookupProfile({ username, zoneFileLookupURL }); - let bucketUrl: string = null; + let bucketUrl: string | undefined; if (profile.hasOwnProperty('apps')) { if (profile.apps.hasOwnProperty(appOrigin)) { const url = profile.apps[appOrigin]; @@ -218,14 +216,14 @@ export class Storage { zoneFileLookupURL?: string ): Promise { const opts = normalizeOptions(this.userSession, { app, username, zoneFileLookupURL }); - let fileUrl: string; + let fileUrl: string | undefined; if (username) { - fileUrl = await this.getUserAppFileUrl('/', opts.username, opts.app, opts.zoneFileLookupURL); + fileUrl = await this.getUserAppFileUrl('/', opts.username!, opts.app, opts.zoneFileLookupURL); } else { const gaiaHubConfig = await this.getOrSetLocalGaiaHubConnection(); fileUrl = await getFullReadUrl('/', gaiaHubConfig); } - const matches = fileUrl.match(/([13][a-km-zA-HJ-NP-Z0-9]{26,35})/); + const matches = fileUrl!.match(/([13][a-km-zA-HJ-NP-Z0-9]{26,35})/); if (!matches) { throw new Error('Failed to parse gaia address'); } @@ -242,9 +240,9 @@ export class Storage { async getFileUrl(path: string, options?: GetFileUrlOptions): Promise { const opts = normalizeOptions(this.userSession, options); - let readUrl: string; + let readUrl: string | undefined; if (opts.username) { - readUrl = await this.getUserAppFileUrl(path, opts.username, opts.app, opts.zoneFileLookupURL); + readUrl = await this.getUserAppFileUrl(path, opts.username, opts.app!, opts.zoneFileLookupURL); } else { const gaiaHubConfig = await this.getOrSetLocalGaiaHubConnection(); readUrl = await getFullReadUrl(path, gaiaHubConfig); @@ -283,7 +281,7 @@ export class Storage { const etag = response.headers.get('ETag'); if (etag) { const sessionData = this.userSession.store.getSessionData(); - sessionData.etags[path] = etag; + sessionData.etags![path] = etag; this.userSession.store.setSessionData(sessionData); } if ( @@ -312,9 +310,9 @@ export class Storage { const sigPath = `${path}${SIGNATURE_FILE_SUFFIX}`; try { const [fileContents, signatureContents, gaiaAddress] = await Promise.all([ - this.getFileContents(path, opt.app, opt.username, opt.zoneFileLookupURL, false), - this.getFileContents(sigPath, opt.app, opt.username, opt.zoneFileLookupURL, true), - this.getGaiaAddress(opt.app, opt.username, opt.zoneFileLookupURL), + this.getFileContents(path, opt.app!, opt.username, opt.zoneFileLookupURL, false), + this.getFileContents(sigPath, opt.app!, opt.username, opt.zoneFileLookupURL, true), + this.getGaiaAddress(opt.app!, opt.username, opt.zoneFileLookupURL), ]); if (!fileContents) { @@ -466,10 +464,10 @@ export class Storage { const opt = Object.assign({}, defaults, options); const gaiaHubConfig = await this.getOrSetLocalGaiaHubConnection(); - const maxUploadBytes = megabytesToBytes(gaiaHubConfig.max_file_upload_size_megabytes); + const maxUploadBytes = megabytesToBytes(gaiaHubConfig.max_file_upload_size_megabytes!); const hasMaxUpload = maxUploadBytes > 0; - const contentLoader = new FileContentLoader(content, opt.contentType); + const contentLoader = new FileContentLoader(content, opt.contentType!); let contentType = contentLoader.contentType; // When not encrypting the content length can be checked immediately. @@ -487,7 +485,7 @@ export class Storage { contentLength: contentLoader.contentByteLength, wasString: contentLoader.wasString, sign: !!opt.sign, - cipherTextEncoding: opt.cipherTextEncoding, + cipherTextEncoding: opt.cipherTextEncoding!, }); if (encryptedSize > maxUploadBytes) { const sizeErrMsg = `The max file upload size for this hub is ${maxUploadBytes} bytes, the given content is ${encryptedSize} bytes after encryption`; @@ -501,9 +499,9 @@ export class Storage { let newFile = true; const sessionData = this.userSession.store.getSessionData(); - if (sessionData.etags[path]) { + if (sessionData.etags![path]) { newFile = false; - etag = sessionData.etags[path]; + etag = sessionData.etags![path]; } let uploadFn: (hubConfig: GaiaHubConfig) => Promise; @@ -533,7 +531,7 @@ export class Storage { ]) )[0]; if (writeResponse.etag) { - sessionData.etags[path] = writeResponse.etag; + sessionData.etags![path] = writeResponse.etag; this.userSession.store.setSessionData(sessionData); } return writeResponse.publicURL; @@ -576,7 +574,7 @@ export class Storage { etag ); if (writeResponse.etag) { - sessionData.etags[path] = writeResponse.etag; + sessionData.etags![path] = writeResponse.etag; this.userSession.store.setSessionData(sessionData); } return writeResponse.publicURL; @@ -621,24 +619,24 @@ export class Storage { try { await deleteFromGaiaHub(path, gaiaHubConfig); await deleteFromGaiaHub(`${path}${SIGNATURE_FILE_SUFFIX}`, gaiaHubConfig); - delete sessionData.etags[path]; + delete sessionData.etags![path]; this.userSession.store.setSessionData(sessionData); } catch (error) { const freshHubConfig = await this.setLocalGaiaHubConnection(); await deleteFromGaiaHub(path, freshHubConfig); await deleteFromGaiaHub(`${path}${SIGNATURE_FILE_SUFFIX}`, gaiaHubConfig); - delete sessionData.etags[path]; + delete sessionData.etags![path]; this.userSession.store.setSessionData(sessionData); } } else { try { await deleteFromGaiaHub(path, gaiaHubConfig); - delete sessionData.etags[path]; + delete sessionData.etags![path]; this.userSession.store.setSessionData(sessionData); } catch (error) { const freshHubConfig = await this.setLocalGaiaHubConnection(); await deleteFromGaiaHub(path, freshHubConfig); - delete sessionData.etags[path]; + delete sessionData.etags![path]; this.userSession.store.setSessionData(sessionData); } } @@ -805,7 +803,7 @@ export class Storage { userData.gaiaHubConfig = gaiaConfig; const sessionData = this.userSession.store.getSessionData(); - sessionData.userData.gaiaHubConfig = gaiaConfig; + sessionData.userData!.gaiaHubConfig = gaiaConfig; this.userSession.store.setSessionData(sessionData); return gaiaConfig; @@ -845,7 +843,7 @@ function normalizeOptions( } const sessionData = userSession.store.getSessionData(); // Use the user specified coreNode if available, otherwise use the app specified coreNode. - const configuredCoreNode = sessionData.userData.coreNode || userSession.appConfig.coreNode; + const configuredCoreNode = sessionData.userData!.coreNode || userSession.appConfig.coreNode; if (configuredCoreNode) { opts.zoneFileLookupURL = `${configuredCoreNode}${NAME_LOOKUP_PATH}`; } diff --git a/packages/storage/tests/storage.test.ts b/packages/storage/tests/storage.test.ts index da812dd17..4b23a8acf 100644 --- a/packages/storage/tests/storage.test.ts +++ b/packages/storage/tests/storage.test.ts @@ -1,5 +1,3 @@ -import * as proxyquire from 'proxyquire' -import * as sinon from 'sinon' import * as crypto from 'crypto' import { TokenSigner, TokenVerifier, decodeToken } from 'jsontokens' import { @@ -105,10 +103,10 @@ test('deleteFile gets a new gaia config and tries again', async () => { expect(success).toHaveBeenCalled() expect(connectToGaiaHub).toHaveBeenCalledTimes(1) - expect(fetchMock.mock.calls[0][1].method).toEqual('DELETE') - expect(fetchMock.mock.calls[0][1].headers).toEqual({Authorization: 'bearer '}) - expect(fetchMock.mock.calls[1][1].method).toEqual('DELETE') - expect(fetchMock.mock.calls[1][1].headers).toEqual({Authorization: 'bearer valid'}) + expect(fetchMock.mock.calls[0][1]!.method).toEqual('DELETE') + expect(fetchMock.mock.calls[0][1]!.headers).toEqual({Authorization: 'bearer '}) + expect(fetchMock.mock.calls[1][1]!.method).toEqual('DELETE') + expect(fetchMock.mock.calls[1][1]!.headers).toEqual({Authorization: 'bearer valid'}) expect(fetchMock.mock.calls[1][0]).toEqual(fullDeleteUrl) }) @@ -136,9 +134,9 @@ test('deleteFile wasSigned deletes signature file', async () => { await storage.deleteFile(path, { wasSigned: true }) expect(fetchMock.mock.calls.length).toEqual(2) - expect(fetchMock.mock.calls[0][1].method).toEqual('DELETE') + expect(fetchMock.mock.calls[0][1]!.method).toEqual('DELETE') expect(fetchMock.mock.calls[0][0]).toEqual(fullDeleteUrl) - expect(fetchMock.mock.calls[1][1].method).toEqual('DELETE') + expect(fetchMock.mock.calls[1][1]!.method).toEqual('DELETE') expect(fetchMock.mock.calls[1][0]).toEqual(fullDeleteSigUrl) }) @@ -168,7 +166,7 @@ test('deleteFile throw on 404', async () => { .catch(error) expect(error).toHaveBeenCalledTimes(1) - expect(fetchMock.mock.calls[0][1].method).toEqual('DELETE') + expect(fetchMock.mock.calls[0][1]!.method).toEqual('DELETE') expect(fetchMock.mock.calls[0][0]).toEqual(fullDeleteUrl) }) @@ -233,7 +231,7 @@ test('getFile unencrypted, unsigned', async () => { url_prefix: 'https://gaia.testblockstack.org/hub/' } - const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json' + // const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json' const fileContent = { test: 'test' } const appConfig = new AppConfig(['store_write'], 'http://localhost:3000') @@ -300,7 +298,7 @@ test('core node preferences respected for name lookups', async () => { expect(fetchMock.mock.calls[0][0]).toEqual(appSpecifiedCoreNode + nameLookupPath) fetchMock.resetMocks() - userSession.store.getSessionData().userData.coreNode = userSpecifiedCoreNode + userSession.store.getSessionData().userData!.coreNode = userSpecifiedCoreNode storage = new Storage({ userSession }) await new Promise((resolve) => { fetchMock.once('_') @@ -327,10 +325,10 @@ test('getFile unencrypted, unsigned - multi-reader', async () => { gaiaHubConfig } - const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json' - const fileContent = { test: 'test' } + // const fullReadUrl = 'https://gaia.testblockstack.org/hub/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json' + // const fileContent = { test: 'test' } - const nameLookupUrl = 'https://core.blockstack.org/v1/names/yukan.id' + // const nameLookupUrl = 'https://core.blockstack.org/v1/names/yukan.id' const nameRecord = { status: 'registered', @@ -343,7 +341,7 @@ test('getFile unencrypted, unsigned - multi-reader', async () => { } const nameRecordContent = JSON.stringify(nameRecord) - const profileUrl = 'https://gaia.blockstack.org/hub/16zVUoP7f15nfTiHw2UNiX8NT5SWYqwNv3/0/profile.json' + // const profileUrl = 'https://gaia.blockstack.org/hub/16zVUoP7f15nfTiHw2UNiX8NT5SWYqwNv3/0/profile.json' /* eslint-disable */ const profileContent = [ @@ -415,7 +413,7 @@ test('getFile unencrypted, unsigned - multi-reader', async () => { ] /* eslint-enable */ - const fileUrl = 'https://gaia.blockstack.org/hub/1DDUqfKtQgYNt722wuB4Z2fPC7aiNGQa5R/file.json' + // const fileUrl = 'https://gaia.blockstack.org/hub/1DDUqfKtQgYNt722wuB4Z2fPC7aiNGQa5R/file.json' const fileContents = JSON.stringify({ key: 'value' }) const options = { @@ -812,7 +810,7 @@ test('putFile includes If-None-Match header in request when creating a new file' const fileContent = 'test-content' const options = { encrypt: false } - const storeURL = `${gaiaHubConfig.server}/store/${gaiaHubConfig.address}/${path}` + // const storeURL = `${gaiaHubConfig.server}/store/${gaiaHubConfig.address}/${path}` fetchMock.once('{}', { status: 202 }) @@ -820,7 +818,8 @@ test('putFile includes If-None-Match header in request when creating a new file' const storage = new Storage({ userSession }) // create new file await storage.putFile(path, fileContent, options) - expect(fetchMock.mock.calls[0][1].headers['If-None-Match']).toEqual('*') + const headers = fetchMock.mock.calls[0][1]!.headers as any; + expect(headers['If-None-Match']).toEqual('*') }) test('putFile throws correct error when server rejects etag', async () => { @@ -840,7 +839,7 @@ test('putFile throws correct error when server rejects etag', async () => { try { const content = 'test-content' - const storeURL = `${gaiaHubConfig.server}/store/${gaiaHubConfig.address}/${path}` + // const storeURL = `${gaiaHubConfig.server}/store/${gaiaHubConfig.address}/${path}` // Mock a PreconditionFailedError fetchMock.once('Precondition Failed', { @@ -903,7 +902,7 @@ test('putFile & getFile unencrypted, not signed, with contentType', async () => }) .then(() => { const decryptOptions = { decrypt: false } - return storage.getFile(path, decryptOptions).then((readContent) => { + return storage.getFile(path, decryptOptions).then((readContent: any) => { expect(readContent).toEqual(JSON.stringify(fileContent)) expect(typeof (readContent)).toEqual('string') }) @@ -1154,7 +1153,7 @@ test('putFile & getFile unencrypted, signed', async () => { const pathToReadUrl = ((fname: string) => `${readPrefix}/${fname}`) const uploadToGaiaHub = jest.fn().mockImplementation( - (fname, contents, hubConfig, contentType) => { + (fname, contents, _, contentType) => { const contentString = Buffer.from(contents as any).toString() putFiledContents.push([fname, contentString, contentType]) if (!fname.endsWith('.sig')) { @@ -1599,7 +1598,7 @@ test('promises reject', async () => { const appConfig = new AppConfig(['store_write'], 'http://localhost:3000') const userSession = new UserSession({ appConfig }) const path = 'file.json' - const fullReadUrl = 'https://hub.testblockstack.org/store/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json' + // const fullReadUrl = 'https://hub.testblockstack.org/store/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U/file.json' const gaiaHubConfig = { address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U', server: 'https://hub.testblockstack.org', @@ -1639,7 +1638,7 @@ test('promises reject', async () => { test('putFile gets a new gaia config and tries again', async () => { const path = 'file.json' - const fullWriteUrl = 'https://hub.testblockstack.org/store/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc/file.json' + // const fullWriteUrl = 'https://hub.testblockstack.org/store/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc/file.json' const invalidHubConfig = { address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc', server: 'https://hub.testblockstack.org', @@ -1975,7 +1974,7 @@ test('listFiles', async () => { } // manually set for testing let callCount = 0 - fetchMock.mockResponse(request => { + fetchMock.mockResponse(_ => { callCount += 1 if (callCount === 1) { return Promise.resolve(JSON.stringify({ entries: [path], page: callCount })) @@ -2009,7 +2008,7 @@ test('connect to gaia hub with a user session and association token', async () = latest_auth_version: 'v1' } - const address = '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U' + // const address = '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yg8U' const publicKey = '027d28f9951ce46538951e3697c62588a87f1f1f295de4a14fdd4c780fc52cfe69' const identityPrivateKey = '4dea04fe440d760664d96f1fd219e7a73324fc8faa28c7babd1a7813d05970aa01' @@ -2045,7 +2044,7 @@ test('connect to gaia hub with a user session and association token', async () = test('listFiles gets a new gaia config and tries again', async () => { const path = 'file.json' - const listFilesUrl = 'https://hub.testblockstack.org/list-files/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc' + // const listFilesUrl = 'https://hub.testblockstack.org/list-files/1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc' const invalidHubConfig = { address: '1NZNxhoxobqwsNvTb16pdeiqvFvce3Yabc', server: 'https://hub.testblockstack.org', diff --git a/packages/storage/tsconfig.json b/packages/storage/tsconfig.json index 6b1c6c98a..6a0cf479a 100644 --- a/packages/storage/tsconfig.json +++ b/packages/storage/tsconfig.json @@ -1,7 +1,47 @@ { - "extends": "../../tsconfig.json", - "include": [ - "./src/**/*", - "./tests/**/*" - ] -} \ No newline at end of file + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "lib": ["dom", "esnext"], + "jsx": "react", + "importHelpers": true, + "declaration": true, + "sourceMap": true, + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, + "strict": true, + "pretty": true, + "removeComments": true, + "noImplicitAny": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "alwaysStrict": true, + "stripInternal": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "emitDecoratorMetadata": false, + "noEmit": false, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "suppressImplicitAnyIndexErrors": false, + "outDir": "./dist", + "baseUrl": "./src", + "skipLibCheck": true, + "esModuleInterop": true, + "strictNullChecks": true, + "paths": { + "@stacks/auth": ["../../auth/src"], + "@stacks/cli": ["../../cli/src"], + "@stacks/common": ["../../common/src"], + "@stacks/encryption": ["../../encryption/src"], + "@stacks/keychain": ["../../keychain/src"], + "@stacks/network": ["../../network/src"], + "@stacks/profile": ["../../profile/src"], + "@stacks/storage": ["../../storage/src"], + "@stacks/transactions": ["../../transactions/src"] + } + }, + "include": ["src/**/*", "tests/**/*"] +} diff --git a/packages/storage/tsdx.config.js b/packages/storage/tsdx.config.js new file mode 100644 index 000000000..d5839e6ad --- /dev/null +++ b/packages/storage/tsdx.config.js @@ -0,0 +1,15 @@ +module.exports = { + rollup(config, options) { + if (options.format === 'esm') { + config.output = { + ...config.output, + dir: 'dist/', + entryFileNames: '[name].esm.js', + preserveModules: true, + preserveModulesRoot: 'src', + }; + delete config.output.file; + } + return config; + }, +};