1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16const typeErrorCode = 401; 17class BusinessError extends Error { 18 code: number; 19 constructor(msg: string) { 20 super(msg); 21 this.name = 'BusinessError'; 22 this.code = typeErrorCode; 23 } 24} 25 26type TransformsFunc = (this: Object, key: string, value: Object) => Object | undefined | null; 27type ReplacerType = (number | string)[] | null | TransformsFunc; 28 29function parse(text: string, reviver?: TransformsFunc): Object | null { 30 if (typeof text !== 'string') { 31 let error = new BusinessError(`Parameter error. The type of ${text} must be string`); 32 throw error; 33 } 34 if (reviver) { 35 if (typeof reviver !== 'function') { 36 let error = new BusinessError(`Parameter error. The type of ${reviver} must be a method`); 37 throw error; 38 } 39 } 40 41 try { 42 return JSON.parse(text, reviver); 43 } catch (e) { 44 let error = new BusinessError(`e.message: `+ (e as Error).message + `, e.name: ` + (e as Error).name); 45 throw error; 46 } 47} 48 49function stringfyFun(value: Object, replacer?: (this: Object, key: string, value: Object) => Object, 50 space?: string | number): string { 51 if (arguments.length === 1) { 52 return JSON.stringify(value); 53 } else { 54 return JSON.stringify(value, replacer, space); 55 } 56} 57 58function stringfyArr(value: Object, replacer?: (number | string)[] | null, space?: string | number): string { 59 if (arguments.length === 1) { 60 return JSON.stringify(value); 61 } else { 62 return JSON.stringify(value, replacer, space); 63 } 64} 65 66function isParameterType(self: unknown): boolean { 67 return (Array.isArray(self) && self.every((item) => typeof item === 'number' || typeof item === 'string') || 68 self === null || typeof self === 'function'); 69} 70 71function isSpaceType(self: unknown): boolean { 72 return (typeof self === 'string' || typeof self === 'number'); 73} 74 75function isCirculateReference(value: Object, seenObjects: Set<Object> = new Set()): boolean { 76 if (value === null || !(value instanceof Object)) { 77 return false; 78 } 79 if (seenObjects.has(value)) { 80 return true; 81 } 82 seenObjects.add(value); 83 84 for (let key in value) { 85 if (isCirculateReference(value[key], seenObjects)) { 86 return true; 87 } 88 } 89 return false; 90} 91 92function stringify(value: Object, replacer?: ReplacerType, space?: string | number): string { 93 if (typeof (value as Object) === 'undefined' || !(value instanceof Object)) { 94 let error = new BusinessError(`Parameter error. The type of ${value} must be Object`); 95 throw error; 96 } 97 if (value === null) { 98 let error = new BusinessError(`Parameter error. The type of ${value} is null`); 99 throw error; 100 } 101 if (typeof value === 'bigint') { 102 let error = new BusinessError(`Parameter error. The type of ${value} is Bigint`); 103 throw error; 104 } 105 if (isCirculateReference(value)) { 106 let error = new BusinessError(`Parameter error. The object circular Reference`); 107 throw error; 108 } 109 if (replacer) { 110 if (!isParameterType(replacer)) { 111 let error = new BusinessError(`Parameter error. The type of ${replacer} must be a method or array`); 112 throw error; 113 } 114 if (space) { 115 if (!isSpaceType(space)) { 116 let error = new BusinessError(`Parameter error. The type of ${space} must be a string or number`); 117 throw error; 118 } 119 } else if (space === null) { 120 let error = new BusinessError(`Parameter error. The type of ${space} must be a string or number`); 121 throw error; 122 } 123 } 124 125 try { 126 if (arguments.length === 1) { 127 return stringfyArr(value); 128 } else { 129 if (typeof replacer === 'function') { 130 return stringfyFun(value, replacer, space); 131 } else { 132 return stringfyArr(value, replacer, space); 133 } 134 } 135 } catch (e) { 136 let error = new BusinessError((e as Error).message + `, e.name: ` + (e as Error).name); 137 throw error; 138 } 139} 140 141function has(value: object, key: string): boolean { 142 if (typeof value !== 'object' || typeof value === 'undefined' || value === null) { 143 let error = new BusinessError(`Parameter error. The type of ${value} must be object`); 144 throw error; 145 } 146 if (value instanceof Array) { 147 let error = new BusinessError(`Parameter error. The type of ${value} must be json object`); 148 throw error; 149 } 150 if (!(typeof key === 'string' && key.length)) { 151 let error = new BusinessError(`Parameter error. The type of ${key} must be string and not empty`); 152 throw error; 153 } 154 return Object.prototype.hasOwnProperty.call(value, key); 155} 156 157function remove(value: object, key: string): void { 158 if (typeof value !== 'object' || typeof value === 'undefined' || value === null) { 159 let error = new BusinessError(`Parameter error. The type of ${value} must be object`); 160 throw error; 161 } 162 if (value instanceof Array) { 163 let error = new BusinessError(`Parameter error. The type of ${value} must be json object`); 164 throw error; 165 } 166 if (!(typeof key === 'string' && key.length)) { 167 let error = new BusinessError(`Parameter error. The type of ${key} must be string and not empty`); 168 throw error; 169 } 170 if (Object.prototype.hasOwnProperty.call(value, key)) { 171 delete value[key]; 172 } 173} 174 175export default { 176 parse: parse, 177 stringify: stringify, 178 has: has, 179 remove: remove, 180}; 181