mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08:00
🚀 Release 0.222.0 (#5786)
This commit is contained in:
parent
dd20127961
commit
e92a993694
49
CHANGELOG.md
49
CHANGELOG.md
|
@ -1,3 +1,52 @@
|
|||
# [0.222.0](https://github.com/n8n-io/n8n/compare/n8n@0.221.2...n8n@0.222.0) (2023-03-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** Assign properties.success earlier to set executionStatus correctly ([#5773](https://github.com/n8n-io/n8n/issues/5773)) ([d33a1ac](https://github.com/n8n-io/n8n/commit/d33a1ac1e9a13985ff84f9271f75ebf368339b6d))
|
||||
* **core:** Do not mark duplicates as circular references in `jsonStringify` ([#5789](https://github.com/n8n-io/n8n/issues/5789)) ([f5183c6](https://github.com/n8n-io/n8n/commit/f5183c640109fb4c9552d6b2786f8ebc0e35ca4c))
|
||||
* **core:** Do not user `util.types.isProxy` for tracking of augmented objects ([#5836](https://github.com/n8n-io/n8n/issues/5836)) ([3e413f2](https://github.com/n8n-io/n8n/commit/3e413f2f80d6fa349dc6f6ea1b49027ae163df80))
|
||||
* **core:** Ensure that all non-lazy-loaded community nodes get post-processed correctly ([#5782](https://github.com/n8n-io/n8n/issues/5782)) ([30aeeb7](https://github.com/n8n-io/n8n/commit/30aeeb70b43ff3916ad79abbe49512a27e50d01d))
|
||||
* **core:** Force-upgrade `decode-uri-component` to address CVE-2022-38900 ([#5734](https://github.com/n8n-io/n8n/issues/5734)) ([8dd7f6e](https://github.com/n8n-io/n8n/commit/8dd7f6e1d4ac29b450a0af17d545ffd17038b005))
|
||||
* **core:** Force-upgrade `http-cache-semantics` to address CVE-2022-25881 ([#5733](https://github.com/n8n-io/n8n/issues/5733)) ([f7401fb](https://github.com/n8n-io/n8n/commit/f7401fb6133b9bf18f3825304c478d767e69fe27))
|
||||
* **core:** Handle Date and RegExp correctly in jsonStringify ([#5812](https://github.com/n8n-io/n8n/issues/5812)) ([753cfb8](https://github.com/n8n-io/n8n/commit/753cfb8b08ff68cc30e6e30959fd0900a44dae21))
|
||||
* **core:** Handle Date and RegExp objects in AugmentObject ([#5809](https://github.com/n8n-io/n8n/issues/5809)) ([e6d4e72](https://github.com/n8n-io/n8n/commit/e6d4e729a063cdbbf648c2815c3e55ddddef2b58))
|
||||
* **core:** Improve axios error handling in nodes ([#5699](https://github.com/n8n-io/n8n/issues/5699)) ([33d9784](https://github.com/n8n-io/n8n/commit/33d97843194c1cddfd27356c279c0f7a8c2674d3))
|
||||
* **core:** Improve community nodes loading ([#5608](https://github.com/n8n-io/n8n/issues/5608)) ([161de11](https://github.com/n8n-io/n8n/commit/161de110cedf2d5d8bc345349d4364ea202e2abd))
|
||||
* **core:** Initialize queue in the webhook server as well ([#5766](https://github.com/n8n-io/n8n/issues/5766)) ([e67ad29](https://github.com/n8n-io/n8n/commit/e67ad2962589b445592641a588024c02b4d99d3f))
|
||||
* **core:** Persist CurrentAuthenticationMethod setting change ([#5762](https://github.com/n8n-io/n8n/issues/5762)) ([4498c60](https://github.com/n8n-io/n8n/commit/4498c6013dc5b4646b1e3fdba3adef42bfc87952))
|
||||
* **core:** Remove circular refs from Code and push msg ([#5741](https://github.com/n8n-io/n8n/issues/5741)) ([b6d8a0f](https://github.com/n8n-io/n8n/commit/b6d8a0f98526bfc98a3d9a722dafce4a53e715ec))
|
||||
* **core:** Require Auth on icons and nodes/credentials types static files ([#5745](https://github.com/n8n-io/n8n/issues/5745)) ([5dda3f2](https://github.com/n8n-io/n8n/commit/5dda3f2c61b107ec24557c4bf7de284234e406ab))
|
||||
* **core:** Return SAML service provider urls with config ([#5759](https://github.com/n8n-io/n8n/issues/5759)) ([ac18c0b](https://github.com/n8n-io/n8n/commit/ac18c0b9ebb3a5a736fa72985ce5ae2cdab3b270))
|
||||
* **core:** Service account private key as a password field ([2b28470](https://github.com/n8n-io/n8n/commit/2b28470fb98a5810ce0d20fe995e2864230005d3))
|
||||
* **core:** Upgrade `luxon` to address CVE-2023-22467 ([#5731](https://github.com/n8n-io/n8n/issues/5731)) ([469ce32](https://github.com/n8n-io/n8n/commit/469ce32957ac5e4d342db17a2f680ca65c21d44f))
|
||||
* **core:** Upgrade `simple-git` to address CVE-2022-25912 ([#5730](https://github.com/n8n-io/n8n/issues/5730)) ([4a4e2be](https://github.com/n8n-io/n8n/commit/4a4e2be96c0ce096d100e08823aa6b256719c267))
|
||||
* **core:** Upgrade `sqlite3` to address CVE-2022-43441 ([#5732](https://github.com/n8n-io/n8n/issues/5732)) ([fd81c74](https://github.com/n8n-io/n8n/commit/fd81c742519882b04f98d25ca41b3fac16dbea8b))
|
||||
* **core:** Upgrade convict to address CVE-2023-0163 ([#5729](https://github.com/n8n-io/n8n/issues/5729)) ([564bc03](https://github.com/n8n-io/n8n/commit/564bc03d3fab59e4fe7fa904d5deeeb16da85af9))
|
||||
* **core:** Waiting workflows not stopping ([#5811](https://github.com/n8n-io/n8n/issues/5811)) ([8f50bb6](https://github.com/n8n-io/n8n/commit/8f50bb6ed13688d8a81a171c1f1fb9e85847f138))
|
||||
* **editor:** Fix connection lost hover text not showing ([#5828](https://github.com/n8n-io/n8n/issues/5828)) ([a2f4a05](https://github.com/n8n-io/n8n/commit/a2f4a05af7f20e007ef16357d71af6a0dbade55c))
|
||||
* **editor:** Fix issue preventing execution preview loading when in an iframe ([#5817](https://github.com/n8n-io/n8n/issues/5817)) ([d19a973](https://github.com/n8n-io/n8n/commit/d19a9732b7da188017e2141b3deed7ea004c04a6))
|
||||
* **editor:** Use credentials when fetching node and credential types ([#5760](https://github.com/n8n-io/n8n/issues/5760)) ([d3a34ab](https://github.com/n8n-io/n8n/commit/d3a34ab71bd7fc494fb90cda1aa9827a55c5ed69))
|
||||
* **Google Sheets Node:** Fix insertOrUpdate cell update with object ([1797cda](https://github.com/n8n-io/n8n/commit/1797cdab5b9e7f23c9f62ce7c6c34c1c2c26b07e))
|
||||
* **HTTP Request Node:** Add streaming to binary response ([#5701](https://github.com/n8n-io/n8n/issues/5701)) ([199a91b](https://github.com/n8n-io/n8n/commit/199a91b3981d40b7181f00702c938b9fa58d1ece)), closes [#5663](https://github.com/n8n-io/n8n/issues/5663)
|
||||
* **HTTP Request Node:** Fix AWS credentials to automatically deconstruct the url ([#5751](https://github.com/n8n-io/n8n/issues/5751)) ([d30b892](https://github.com/n8n-io/n8n/commit/d30b89239587562974cc87ae2e29fe57acddf79e))
|
||||
* **HTTP Request Node:** Fix AWS credentials to stop removing url params for STS ([#5790](https://github.com/n8n-io/n8n/issues/5790)) ([2c25959](https://github.com/n8n-io/n8n/commit/2c25959e595a48d9ae55c462bd47e014d8c43598))
|
||||
* **Split In Batches Node:** Roll back changes in v1 and create v2 ([#5747](https://github.com/n8n-io/n8n/issues/5747)) ([135b0d3](https://github.com/n8n-io/n8n/commit/135b0d3e27705b07fb1e9c39a47ac4b70c1bc25d))
|
||||
* Update Posthog no-capture ([#5693](https://github.com/n8n-io/n8n/issues/5693)) ([a732374](https://github.com/n8n-io/n8n/commit/a732374f24354e0c1f36247f4476e743b0fc78e5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add test overrides ([#5642](https://github.com/n8n-io/n8n/issues/5642)) ([696e43a](https://github.com/n8n-io/n8n/commit/696e43a919334d982188cc1f86d3e1b76da6a362))
|
||||
* **core:** Improve ldap/saml toggle and tests ([#5771](https://github.com/n8n-io/n8n/issues/5771)) ([47ee357](https://github.com/n8n-io/n8n/commit/47ee357059bb6d87607165d3c24ce0c99cf8bfc9))
|
||||
* **core:** Limit user invites when SAML is enabled ([#5761](https://github.com/n8n-io/n8n/issues/5761)) ([57748b7](https://github.com/n8n-io/n8n/commit/57748b71e5cd1399ccaedb9a115b821b34cf55e5))
|
||||
* **core:** Make OAuth2 error handling consistent with success handling ([#5555](https://github.com/n8n-io/n8n/issues/5555)) ([40aacf9](https://github.com/n8n-io/n8n/commit/40aacf9279c00c4e3c27669fc38a0ca196a788a4))
|
||||
* **editor:** Fix ResourceLocator dropdown style ([#5714](https://github.com/n8n-io/n8n/issues/5714)) ([02810a9](https://github.com/n8n-io/n8n/commit/02810a9ba3e792a2ec8966a2ca3bf7394740bf24))
|
||||
* Execution custom data saving and filtering ([#5496](https://github.com/n8n-io/n8n/issues/5496)) ([d78a41d](https://github.com/n8n-io/n8n/commit/d78a41db5420ff6711c30899aa2d71a85049374c)), closes [#5739](https://github.com/n8n-io/n8n/issues/5739)
|
||||
* **Filter Node:** New node ([cc9fe7b](https://github.com/n8n-io/n8n/commit/cc9fe7b91ffc4ea72c25e1242e0e477112cb283e))
|
||||
|
||||
|
||||
|
||||
## [0.221.2](https://github.com/n8n-io/n8n/compare/n8n@0.221.1...n8n@0.221.2) (2023-03-24)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "0.221.2",
|
||||
"version": "0.222.0",
|
||||
"private": true,
|
||||
"homepage": "https://n8n.io",
|
||||
"engines": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "0.221.2",
|
||||
"version": "0.222.0",
|
||||
"description": "n8n Workflow Automation Tool",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -165,7 +165,7 @@ export interface IExecutionBase {
|
|||
// Data in regular format with references
|
||||
export interface IExecutionDb extends IExecutionBase {
|
||||
data: IRunExecutionData;
|
||||
waitTill?: Date;
|
||||
waitTill?: Date | null;
|
||||
workflowData?: IWorkflowBase;
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ export interface IExecutionResponse extends IExecutionBase {
|
|||
data: IRunExecutionData;
|
||||
retryOf?: string;
|
||||
retrySuccessId?: string;
|
||||
waitTill?: Date;
|
||||
waitTill?: Date | null;
|
||||
workflowData: IWorkflowBase;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ export class WaitTracker {
|
|||
};
|
||||
|
||||
fullExecutionData.stoppedAt = new Date();
|
||||
fullExecutionData.waitTill = undefined;
|
||||
fullExecutionData.waitTill = null;
|
||||
fullExecutionData.status = 'canceled';
|
||||
|
||||
await Db.collections.Execution.update(
|
||||
|
|
|
@ -49,7 +49,7 @@ export class ExecutionEntity implements IExecutionFlattedDb {
|
|||
workflowId: string;
|
||||
|
||||
@Column({ type: datetimeColumnType, nullable: true })
|
||||
waitTill: Date;
|
||||
waitTill: Date | null;
|
||||
|
||||
@OneToMany('ExecutionMetadata', 'execution')
|
||||
metadata: ExecutionMetadata[];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-core",
|
||||
"version": "0.160.0",
|
||||
"version": "0.161.0",
|
||||
"description": "Core functionality of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-design-system",
|
||||
"version": "0.59.0",
|
||||
"version": "0.60.0",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
"author": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-editor-ui",
|
||||
"version": "0.187.0",
|
||||
"version": "0.188.0",
|
||||
"description": "Workflow Editor UI for n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<span>
|
||||
<div class="push-connection-lost primary-color" v-if="!rootStore.pushConnectionActive">
|
||||
<n8n-tooltip placement="bottom-end">
|
||||
<template #current>
|
||||
<template #content>
|
||||
<div v-html="$locale.baseText('pushConnectionTracker.cannotConnectToServer')"></div>
|
||||
</template>
|
||||
<span>
|
||||
|
|
|
@ -3885,8 +3885,8 @@ export default mixins(
|
|||
this.bindCanvasEvents();
|
||||
} catch {} // This will break if mounted after jsplumb has been initiated from executions preview, so continue if it breaks
|
||||
await this.initView();
|
||||
if (window.top) {
|
||||
window.top.postMessage(
|
||||
if (window.parent) {
|
||||
window.parent.postMessage(
|
||||
JSON.stringify({ command: 'n8nReady', version: this.rootStore.versionCli }),
|
||||
'*',
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-node-dev",
|
||||
"version": "0.99.0",
|
||||
"version": "0.100.0",
|
||||
"description": "CLI to simplify n8n credentials/node development",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -285,7 +285,7 @@ export class Aws implements ICredentialType {
|
|||
const method = requestOptions.method;
|
||||
let body = requestOptions.body;
|
||||
let region = credentials.region;
|
||||
const query = requestOptions.qs?.query as IDataObject;
|
||||
let query = requestOptions.qs?.query as IDataObject;
|
||||
|
||||
// ! Workaround as we still use the OptionsWithUri interface which uses uri instead of url
|
||||
// ! To change when we replace the interface with IHttpRequestOptions
|
||||
|
@ -295,8 +295,12 @@ export class Aws implements ICredentialType {
|
|||
endpoint = new URL(requestOptions.url);
|
||||
if (service === 'sts') {
|
||||
try {
|
||||
endpoint.searchParams.set('Action', 'GetCallerIdentity');
|
||||
endpoint.searchParams.set('Version', '2011-06-15');
|
||||
if (requestWithUri.qs?.Action !== 'GetCallerIdentity') {
|
||||
query = requestWithUri.qs;
|
||||
} else {
|
||||
endpoint.searchParams.set('Action', 'GetCallerIdentity');
|
||||
endpoint.searchParams.set('Version', '2011-06-15');
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
@ -342,6 +346,7 @@ export class Aws implements ICredentialType {
|
|||
endpoint = customUrl;
|
||||
}
|
||||
}
|
||||
|
||||
if (query && Object.keys(query).length !== 0) {
|
||||
Object.keys(query).forEach((key) => {
|
||||
endpoint.searchParams.append(key, query[key] as string);
|
||||
|
|
|
@ -29,6 +29,9 @@ export class GoogleApi implements ICredentialType {
|
|||
description:
|
||||
'Enter the private key located in the JSON file downloaded from Google Cloud Console',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
password: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Impersonate a User',
|
||||
|
|
|
@ -12,9 +12,7 @@ function isTraversable(maybe: unknown): maybe is IDataObject {
|
|||
* Stringify any non-standard JS objects (e.g. `Date`, `RegExp`) inside output items at any depth.
|
||||
*/
|
||||
export function standardizeOutput(output: IDataObject) {
|
||||
const knownObjects = new WeakSet();
|
||||
|
||||
function standardizeOutputRecursive(obj: IDataObject): IDataObject {
|
||||
function standardizeOutputRecursive(obj: IDataObject, knownObjects = new WeakSet()): IDataObject {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (!isTraversable(value)) continue;
|
||||
|
||||
|
@ -29,7 +27,7 @@ export function standardizeOutput(output: IDataObject) {
|
|||
obj[key] =
|
||||
value.constructor.name !== 'Object'
|
||||
? JSON.stringify(value) // Date, RegExp, etc.
|
||||
: standardizeOutputRecursive(value);
|
||||
: standardizeOutputRecursive(value, knownObjects);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
|
|
@ -536,9 +536,15 @@ export class GoogleSheet {
|
|||
columnNames.indexOf(name),
|
||||
);
|
||||
|
||||
let updateValue = item[name] as string;
|
||||
if (typeof updateValue === 'object') {
|
||||
try {
|
||||
updateValue = JSON.stringify(updateValue);
|
||||
} catch (error) {}
|
||||
}
|
||||
updateData.push({
|
||||
range: `${decodedRange.name}!${columnToUpdate}${updateRowIndex}`,
|
||||
values: [[item[name] as string]],
|
||||
values: [[updateValue]],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-nodes-base",
|
||||
"version": "0.219.0",
|
||||
"version": "0.220.0",
|
||||
"description": "Base nodes of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-workflow",
|
||||
"version": "0.142.0",
|
||||
"version": "0.143.0",
|
||||
"description": "Workflow base code of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
import type { IDataObject } from './Interfaces';
|
||||
import util from 'util';
|
||||
|
||||
const augmentedObjects = new WeakSet<object>();
|
||||
function augment<T>(value: T): T {
|
||||
if (
|
||||
typeof value !== 'object' ||
|
||||
value === null ||
|
||||
value instanceof RegExp ||
|
||||
augmentedObjects.has(value)
|
||||
)
|
||||
return value;
|
||||
|
||||
// Track augmented objects to prevent infinite recursion in cases where an object contains circular references
|
||||
augmentedObjects.add(value);
|
||||
|
||||
if (value instanceof Date) return new Date(value.valueOf()) as T;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
if (Array.isArray(value)) return augmentArray(value) as T;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
return augmentObject(value) as T;
|
||||
}
|
||||
|
||||
export function augmentArray<T>(data: T[]): T[] {
|
||||
let newData: unknown[] | undefined = undefined;
|
||||
|
@ -17,24 +38,12 @@ export function augmentArray<T>(data: T[]): T[] {
|
|||
},
|
||||
get(target, key: string, receiver): unknown {
|
||||
const value = Reflect.get(newData !== undefined ? newData : target, key, receiver) as unknown;
|
||||
|
||||
if (typeof value === 'object') {
|
||||
if (value === null || util.types.isProxy(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const newValue = augment(value);
|
||||
if (newValue !== value) {
|
||||
newData = getData();
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
Reflect.set(newData, key, augmentArray(value));
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
Reflect.set(newData, key, augmentObject(value as IDataObject));
|
||||
}
|
||||
|
||||
return Reflect.get(newData, key);
|
||||
Reflect.set(newData, key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
|
@ -83,18 +92,13 @@ export function augmentObject<T extends object>(data: T): T {
|
|||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const value = Reflect.get(target, key, receiver);
|
||||
|
||||
if (value !== null && typeof value === 'object') {
|
||||
if (Array.isArray(value)) {
|
||||
newData[key] = augmentArray(value);
|
||||
} else {
|
||||
newData[key] = augmentObject(value as IDataObject);
|
||||
}
|
||||
|
||||
return newData[key];
|
||||
const newValue = augment(value);
|
||||
if (newValue !== value) {
|
||||
Object.assign(newData, { [key]: newValue });
|
||||
return newValue;
|
||||
}
|
||||
|
||||
return value as string;
|
||||
return value;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
if (key in newData) {
|
||||
|
|
|
@ -1547,7 +1547,7 @@ export interface IRun {
|
|||
data: IRunExecutionData;
|
||||
finished?: boolean;
|
||||
mode: WorkflowExecuteMode;
|
||||
waitTill?: Date;
|
||||
waitTill?: Date | null;
|
||||
startedAt: Date;
|
||||
stoppedAt?: Date;
|
||||
status: ExecutionStatus;
|
||||
|
|
|
@ -64,27 +64,23 @@ export const jsonParse = <T>(jsonString: string, options?: JSONParseOptions<T>):
|
|||
|
||||
type JSONStringifyOptions = {
|
||||
replaceCircularRefs?: boolean;
|
||||
circularRefReplacement?: string;
|
||||
};
|
||||
|
||||
const getReplaceCircularReferencesFn = (options: JSONStringifyOptions) => {
|
||||
const knownObjects = new WeakSet();
|
||||
return (key: any, value: any) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
if (knownObjects.has(value)) {
|
||||
return options?.circularRefReplacement ?? '[Circular Reference]';
|
||||
}
|
||||
knownObjects.add(value);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
const replaceCircularReferences = <T>(value: T, knownObjects = new WeakSet()): T => {
|
||||
if (typeof value !== 'object' || value === null || value instanceof RegExp) return value;
|
||||
if ('toJSON' in value && typeof value.toJSON === 'function') return value.toJSON() as T;
|
||||
if (knownObjects.has(value)) return '[Circular Reference]' as T;
|
||||
knownObjects.add(value);
|
||||
const copy = (Array.isArray(value) ? [] : {}) as T;
|
||||
for (const key in value) {
|
||||
copy[key] = replaceCircularReferences(value[key], knownObjects);
|
||||
}
|
||||
knownObjects.delete(value);
|
||||
return copy;
|
||||
};
|
||||
|
||||
export const jsonStringify = (obj: unknown, options: JSONStringifyOptions = {}): string => {
|
||||
const replacer = options?.replaceCircularRefs
|
||||
? getReplaceCircularReferencesFn(options)
|
||||
: undefined;
|
||||
return JSON.stringify(obj, replacer);
|
||||
return JSON.stringify(options?.replaceCircularRefs ? replaceCircularReferences(obj) : obj);
|
||||
};
|
||||
|
||||
export const sleep = async (ms: number): Promise<void> =>
|
||||
|
|
|
@ -193,11 +193,15 @@ describe('AugmentObject', () => {
|
|||
|
||||
describe('augmentObject', () => {
|
||||
test('should work with simple values on first level', () => {
|
||||
const date = new Date(1680089084200);
|
||||
const regexp = new RegExp('^test$', 'ig');
|
||||
const originalObject: IDataObject = {
|
||||
1: 11,
|
||||
2: '22',
|
||||
a: 111,
|
||||
b: '222',
|
||||
d: date,
|
||||
r: regexp,
|
||||
};
|
||||
const copyOriginal = JSON.parse(JSON.stringify(originalObject));
|
||||
|
||||
|
@ -221,7 +225,7 @@ describe('AugmentObject', () => {
|
|||
|
||||
augmentedObject.c = 3;
|
||||
|
||||
expect(originalObject).toEqual(copyOriginal);
|
||||
expect({ ...originalObject, d: date.toJSON(), r: {} }).toEqual(copyOriginal);
|
||||
|
||||
expect(augmentedObject).toEqual({
|
||||
1: 911,
|
||||
|
@ -229,6 +233,8 @@ describe('AugmentObject', () => {
|
|||
a: 9111,
|
||||
b: '9222',
|
||||
c: 3,
|
||||
d: date,
|
||||
r: regexp,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('jsonParse', () => {
|
|||
});
|
||||
|
||||
describe('jsonStringify', () => {
|
||||
const source: any = { a: 1, b: 2 };
|
||||
const source: any = { a: 1, b: 2, d: new Date(1680089084200), r: new RegExp('^test$', 'ig') };
|
||||
source.c = source;
|
||||
|
||||
it('should throw errors on circular references by default', () => {
|
||||
|
@ -27,7 +27,15 @@ describe('jsonStringify', () => {
|
|||
|
||||
it('should break circular references when requested', () => {
|
||||
expect(jsonStringify(source, { replaceCircularRefs: true })).toEqual(
|
||||
'{"a":1,"b":2,"c":"[Circular Reference]"}',
|
||||
'{"a":1,"b":2,"d":"2023-03-29T11:24:44.200Z","r":{},"c":"[Circular Reference]"}',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not detect duplicates as circular references', () => {
|
||||
const y = { z: 5 };
|
||||
const x = [y, y, { y }];
|
||||
expect(jsonStringify(x, { replaceCircularRefs: true })).toEqual(
|
||||
'[{"z":5},{"z":5},{"y":{"z":5}}]',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue