2023-01-10 05:06:12 -08:00
import type { ExtensionMap } from './Extensions' ;
2024-09-18 00:19:33 -07:00
import { ExpressionExtensionError } from '../errors/expression-extension.error' ;
2023-01-10 05:06:12 -08:00
function isEmpty ( value : object ) : boolean {
return Object . keys ( value ) . length === 0 ;
}
2023-02-02 03:35:38 -08:00
function isNotEmpty ( value : object ) : boolean {
return ! isEmpty ( value ) ;
}
2024-03-07 08:01:05 -08:00
function keys ( value : object ) : string [ ] {
return Object . keys ( value ) ;
}
function values ( value : object ) : unknown [ ] {
return Object . values ( value ) ;
}
2023-01-10 05:06:12 -08:00
function hasField ( value : object , extraArgs : string [ ] ) : boolean {
const [ name ] = extraArgs ;
return name in value ;
}
function removeField ( value : object , extraArgs : string [ ] ) : object {
const [ name ] = extraArgs ;
if ( name in value ) {
const newObject = { . . . value } ;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
delete ( newObject as any ) [ name ] ;
return newObject ;
}
return value ;
}
function removeFieldsContaining ( value : object , extraArgs : string [ ] ) : object {
const [ match ] = extraArgs ;
2023-02-15 01:50:16 -08:00
if ( typeof match !== 'string' || match === '' ) {
throw new ExpressionExtensionError ( 'removeFieldsContaining(): expected non-empty string arg' ) ;
2023-01-10 05:06:12 -08:00
}
const newObject = { . . . value } ;
for ( const [ key , val ] of Object . entries ( value ) ) {
if ( typeof val === 'string' && val . includes ( match ) ) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
delete ( newObject as any ) [ key ] ;
}
}
return newObject ;
}
function keepFieldsContaining ( value : object , extraArgs : string [ ] ) : object {
const [ match ] = extraArgs ;
2023-02-15 01:50:16 -08:00
if ( typeof match !== 'string' || match === '' ) {
throw new ExpressionExtensionError (
'argument of keepFieldsContaining must be a non-empty string' ,
) ;
2023-01-10 05:06:12 -08:00
}
const newObject = { . . . value } ;
for ( const [ key , val ] of Object . entries ( value ) ) {
2023-02-15 01:50:16 -08:00
if ( typeof val !== 'string' || ( typeof val === 'string' && ! val . includes ( match ) ) ) {
2023-01-10 05:06:12 -08:00
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
delete ( newObject as any ) [ key ] ;
}
}
return newObject ;
}
export function compact ( value : object ) : object {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const newObj : any = { } ;
for ( const [ key , val ] of Object . entries ( value ) ) {
2023-02-02 03:35:38 -08:00
if ( val !== null && val !== undefined && val !== 'nil' && val !== '' ) {
2023-01-10 05:06:12 -08:00
if ( typeof val === 'object' ) {
2023-02-02 03:35:38 -08:00
if ( Object . keys ( val as object ) . length === 0 ) continue ;
2023-07-31 02:00:48 -07:00
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
2023-01-10 05:06:12 -08:00
newObj [ key ] = compact ( val ) ;
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
newObj [ key ] = val ;
}
}
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return newObj ;
}
export function urlEncode ( value : object ) {
return new URLSearchParams ( value as Record < string , string > ) . toString ( ) ;
}
2024-03-20 04:05:54 -07:00
export function toJsonString ( value : object ) {
return JSON . stringify ( value ) ;
}
export function toInt() {
return undefined ;
}
export function toFloat() {
return undefined ;
}
export function toBoolean() {
return undefined ;
}
export function toDateTime() {
return undefined ;
}
2023-02-02 03:35:38 -08:00
isEmpty . doc = {
name : 'isEmpty' ,
2024-06-07 04:25:22 -07:00
description :
'Returns <code>true</code> if the Object has no keys (fields) set or is <code>null</code>' ,
2024-05-14 07:32:31 -07:00
examples : [
{ example : "({'name': 'Nathan'}).isEmpty()" , evaluated : 'false' } ,
{ example : '({}).isEmpty()' , evaluated : 'true' } ,
] ,
2023-02-02 03:35:38 -08:00
returnType : 'boolean' ,
2023-11-20 05:40:28 -08:00
docURL : 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-isEmpty' ,
2023-02-02 03:35:38 -08:00
} ;
isNotEmpty . doc = {
name : 'isNotEmpty' ,
2024-05-14 07:32:31 -07:00
description : 'Returns <code>true</code> if the Object has at least one key (field) set' ,
examples : [
{ example : "({'name': 'Nathan'}).isNotEmpty()" , evaluated : 'true' } ,
{ example : '({}).isNotEmpty()' , evaluated : 'false' } ,
] ,
2023-02-02 03:35:38 -08:00
returnType : 'boolean' ,
2023-02-27 20:34:03 -08:00
docURL :
2023-11-20 05:40:28 -08:00
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-isNotEmpty' ,
2023-02-02 03:35:38 -08:00
} ;
compact . doc = {
name : 'compact' ,
2024-05-14 07:32:31 -07:00
description :
'Removes all fields that have empty values, i.e. are <code>null</code>, <code>undefined</code>, <code>"nil"</code> or <code>""</code>' ,
examples : [ { example : "({ x: null, y: 2, z: '' }).compact()" , evaluated : '{ y: 2 }' } ] ,
returnType : 'Object' ,
2023-11-20 05:40:28 -08:00
docURL : 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-compact' ,
2023-02-02 03:35:38 -08:00
} ;
urlEncode . doc = {
name : 'urlEncode' ,
2024-05-14 07:32:31 -07:00
description :
"Generates a URL parameter string from the Object's keys and values. Only top-level keys are supported." ,
examples : [
{
example : "({ name: 'Mr Nathan', city: 'hanoi' }).urlEncode()" ,
evaluated : "'name=Mr+Nathan&city=hanoi'" ,
} ,
] ,
2023-02-02 03:35:38 -08:00
returnType : 'string' ,
2023-02-27 20:34:03 -08:00
docURL :
2023-11-20 05:40:28 -08:00
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-urlEncode' ,
2023-02-02 03:35:38 -08:00
} ;
hasField . doc = {
name : 'hasField' ,
2024-05-14 07:32:31 -07:00
description :
'Returns <code>true</code> if there is a field called <code>name</code>. Only checks top-level keys. Comparison is case-sensitive.' ,
examples : [
{ example : "({ name: 'Nathan', age: 42 }).hasField('name')" , evaluated : 'true' } ,
{ example : "({ name: 'Nathan', age: 42 }).hasField('Name')" , evaluated : 'false' } ,
{ example : "({ name: 'Nathan', age: 42 }).hasField('inventedField')" , evaluated : 'false' } ,
] ,
2023-02-02 03:35:38 -08:00
returnType : 'boolean' ,
2024-05-14 07:32:31 -07:00
args : [
{
name : 'name' ,
optional : false ,
description : 'The name of the key to search for' ,
type : 'string' ,
} ,
] ,
2023-11-20 05:40:28 -08:00
docURL : 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-hasField' ,
2023-02-02 03:35:38 -08:00
} ;
removeField . doc = {
name : 'removeField' ,
2024-05-14 07:32:31 -07:00
description : "Removes a field from the Object. The same as JavaScript's <code>delete</code>." ,
examples : [
{
example : "({ name: 'Nathan', city: 'hanoi' }).removeField('name')" ,
evaluated : "{ city: 'hanoi' }" ,
} ,
] ,
returnType : 'Object' ,
args : [
{
name : 'key' ,
optional : false ,
description : 'The name of the field to remove' ,
type : 'string' ,
} ,
] ,
2023-02-27 20:34:03 -08:00
docURL :
2023-11-20 05:40:28 -08:00
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-removeField' ,
2023-02-02 03:35:38 -08:00
} ;
removeFieldsContaining . doc = {
name : 'removeFieldsContaining' ,
2023-02-27 20:34:03 -08:00
description :
2024-05-14 07:32:31 -07:00
"Removes keys (fields) whose values at least partly match the given <code>value</code>. Comparison is case-sensitive. Fields that aren't strings are always kept." ,
examples : [
{
example : "({ name: 'Mr Nathan', city: 'hanoi', age: 42 }).removeFieldsContaining('Nathan')" ,
evaluated : "{ city: 'hanoi', age: 42 }" ,
} ,
{
example : "({ name: 'Mr Nathan', city: 'hanoi', age: 42 }).removeFieldsContaining('Han')" ,
evaluated : '{ age: 42 }' ,
} ,
{
example : "({ name: 'Mr Nathan', city: 'hanoi', age: 42 }).removeFieldsContaining('nathan')" ,
evaluated : "{ name: 'Mr Nathan', city: 'hanoi', age: 42 }" ,
} ,
] ,
returnType : 'Object' ,
args : [
{
name : 'value' ,
optional : false ,
description : 'The text that a value must contain in order to be removed' ,
type : 'string' ,
} ,
] ,
2023-02-27 20:34:03 -08:00
docURL :
2023-11-20 05:40:28 -08:00
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-removeFieldsContaining' ,
2023-02-02 03:35:38 -08:00
} ;
keepFieldsContaining . doc = {
name : 'keepFieldsContaining' ,
2024-05-14 07:32:31 -07:00
description :
"Removes any fields whose values don't at least partly match the given <code>value</code>. Comparison is case-sensitive. Fields that aren't strings will always be removed." ,
examples : [
{
example : "({ name: 'Mr Nathan', city: 'hanoi', age: 42 }).keepFieldsContaining('Nathan')" ,
evaluated : "{ name: 'Mr Nathan' }" ,
} ,
{
example : "({ name: 'Mr Nathan', city: 'hanoi', age: 42 }).keepFieldsContaining('nathan')" ,
evaluated : '{}' ,
} ,
{
example : "({ name: 'Mr Nathan', city: 'hanoi', age: 42 }).keepFieldsContaining('han')" ,
evaluated : "{ name: 'Mr Nathan', city: 'hanoi' }" ,
} ,
] ,
returnType : 'Object' ,
args : [
{
name : 'value' ,
optional : false ,
description : 'The text that a value must contain in order to be kept' ,
type : 'string' ,
} ,
] ,
2023-02-27 20:34:03 -08:00
docURL :
2023-11-20 05:40:28 -08:00
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-keepFieldsContaining' ,
2023-02-02 03:35:38 -08:00
} ;
2024-03-07 08:01:05 -08:00
keys . doc = {
name : 'keys' ,
2024-05-14 07:32:31 -07:00
description :
"Returns an array with all the field names (keys) the Object contains. The same as JavaScript's <code>Object.keys(obj)</code>." ,
examples : [ { example : "({ name: 'Mr Nathan', age: 42 }).keys()" , evaluated : "['name', 'age']" } ] ,
2024-03-07 08:01:05 -08:00
docURL : 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-keys' ,
returnType : 'Array' ,
} ;
values . doc = {
name : 'values' ,
2024-05-14 07:32:31 -07:00
description :
"Returns an array with all the values of the fields the Object contains. The same as JavaScript's <code>Object.values(obj)</code>." ,
examples : [
{ example : "({ name: 'Mr Nathan', age: 42 }).values()" , evaluated : "['Mr Nathan', 42]" } ,
] ,
2024-03-07 08:01:05 -08:00
docURL : 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-values' ,
returnType : 'Array' ,
} ;
2024-03-20 04:05:54 -07:00
toJsonString . doc = {
name : 'toJsonString' ,
2024-05-14 07:32:31 -07:00
description :
"Converts the Object to a JSON string. Similar to JavaScript's <code>JSON.stringify()</code>." ,
examples : [
{
example : "({ name: 'Mr Nathan', age: 42 }).toJsonString()" ,
evaluated : '\'{"name":"Nathan","age":42}\'' ,
} ,
] ,
2024-03-20 04:05:54 -07:00
docURL :
'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-toJsonString' ,
returnType : 'string' ,
} ;
2023-01-10 05:06:12 -08:00
export const objectExtensions : ExtensionMap = {
typeName : 'Object' ,
functions : {
isEmpty ,
2023-02-02 03:35:38 -08:00
isNotEmpty ,
2023-01-10 05:06:12 -08:00
hasField ,
removeField ,
removeFieldsContaining ,
keepFieldsContaining ,
compact ,
urlEncode ,
2024-03-07 08:01:05 -08:00
keys ,
values ,
2024-03-20 04:05:54 -07:00
toJsonString ,
toInt ,
toFloat ,
toBoolean ,
toDateTime ,
2023-01-10 05:06:12 -08:00
} ,
} ;