From d5294203b7ed1f720bf73917cbe0f78f83d8d56c Mon Sep 17 00:00:00 2001 From: emizzle Date: Mon, 3 Feb 2020 20:56:18 +1100 Subject: [PATCH] fix(@embark/contracts-manager): Remove `logger` from serialized contract MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For all instances where a `Contract` instance is serialized using `JSON.stringify`, the `logger` property was being stringified and written to logs and contract artifact files. Add Serializer class that allows ignoring of class properties during serialization when using `JSON.stringify`. NOTE: The `Serializer` relies on TypeScript’s decorators which are still listed as experimental (requiring the necessary compiler flag) despite being around for several years. Decorators are a stage 2 proposal for JavaScript. --- packages/core/utils/src/index.ts | 2 + packages/core/utils/src/serialize.ts | 37 +++++++++++++++++++ .../stack/contracts-manager/src/contract.ts | 4 +- tsconfig.base.json | 3 +- 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 packages/core/utils/src/serialize.ts diff --git a/packages/core/utils/src/index.ts b/packages/core/utils/src/index.ts index c7d6a0837..bb181ab0b 100644 --- a/packages/core/utils/src/index.ts +++ b/packages/core/utils/src/index.ts @@ -3,6 +3,8 @@ const https = require('follow-redirects').https; const shelljs = require('shelljs'); const clipboardy = require('clipboardy'); +import * as Serialize from './serialize'; +export { Serialize }; import { canonicalHost } from './host'; export { canonicalHost, defaultCorsHost, defaultHost, dockerHostSwap, isDocker } from './host'; export { downloadFile, findNextPort, getJson, httpGet, httpsGet, httpGetJson, httpsGetJson, pingEndpoint } from './network'; diff --git a/packages/core/utils/src/serialize.ts b/packages/core/utils/src/serialize.ts new file mode 100644 index 000000000..7205f329a --- /dev/null +++ b/packages/core/utils/src/serialize.ts @@ -0,0 +1,37 @@ +export function Serializable(target: any) { + target.prototype.toJSON = function() { + const props = Object.getOwnPropertyDescriptors(this); + const map = {}; + Object.entries(props).map(([name, prop]) => { + if (Serialization.isIgnored(target.prototype, name)) { + return; + } + map[name] = prop.value; + }); + return map; + }; +} + +export function Ignore(target: any, propertyKey: string) { + Serialization.registerIgnore(target, propertyKey); +} + +class Serialization { + private static ignoreMap: Map = new Map(); + static registerIgnore(target: any, property: any): void { + let keys = this.ignoreMap.get(target); + if (!keys) { + keys = []; + this.ignoreMap.set(target, keys); + } + keys.push(property); + } + + static isIgnored(target: any, property: any): boolean { + const keys = this.ignoreMap.get(target); + if (!keys) { + return false; + } + return keys.includes(property); + } +} diff --git a/packages/stack/contracts-manager/src/contract.ts b/packages/stack/contracts-manager/src/contract.ts index 60a047bd9..6d743f967 100644 --- a/packages/stack/contracts-manager/src/contract.ts +++ b/packages/stack/contracts-manager/src/contract.ts @@ -1,9 +1,11 @@ import { ContractConfig } from "embark-core"; import { Logger } from 'embark-logger'; -import { sha3 } from "embark-utils"; +import { sha3, Serialize } from "embark-utils"; import { AbiItem } from "web3-utils"; +@Serialize.Serializable export default class Contract { + @Serialize.Ignore private logger: Logger; public abiDefinition?: AbiItem[]; public deployedAddress?: string; diff --git a/tsconfig.base.json b/tsconfig.base.json index f5e10fc7c..3e28ade0d 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -6,6 +6,7 @@ "declarationMap": true, "emitDeclarationOnly": true, "esModuleInterop": true, + "experimentalDecorators": true, "isolatedModules": true, "moduleResolution": "Node", "noImplicitAny": false, @@ -14,4 +15,4 @@ "strict": true, "target": "ESNext" } -} +} \ No newline at end of file