first commit
This commit is contained in:
33
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.d.ts
generated
vendored
Normal file
33
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { ExtensionMap } from './extensions';
|
||||
export declare function average(value: unknown[]): number;
|
||||
export declare namespace average {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
examples: {
|
||||
example: string;
|
||||
evaluated: string;
|
||||
}[];
|
||||
returnType: string;
|
||||
docURL: string;
|
||||
};
|
||||
}
|
||||
export declare function toJsonString(value: unknown[]): string;
|
||||
export declare namespace toJsonString {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
examples: {
|
||||
example: string;
|
||||
evaluated: string;
|
||||
}[];
|
||||
docURL: string;
|
||||
returnType: string;
|
||||
};
|
||||
}
|
||||
export declare function toInt(): undefined;
|
||||
export declare function toFloat(): undefined;
|
||||
export declare function toBoolean(): undefined;
|
||||
export declare function toDateTime(): undefined;
|
||||
export declare const arrayExtensions: ExtensionMap;
|
||||
//# sourceMappingURL=array-extensions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"array-extensions.d.ts","sourceRoot":"","sources":["../../../src/extensions/array-extensions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,cAAc,CAAC;AAsH5D,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,UASvC;yBATe,OAAO;;;;;;;;;;;;AAiMvB,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,UAE5C;yBAFe,YAAY;;;;;;;;;;;;AAI5B,wBAAgB,KAAK,cAEpB;AAED,wBAAgB,OAAO,cAEtB;AAED,wBAAgB,SAAS,cAExB;AAED,wBAAgB,UAAU,cAEzB;AAiVD,eAAO,MAAM,eAAe,EAAE,YA8B7B,CAAC"}
|
||||
605
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.js
generated
vendored
Normal file
605
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.js
generated
vendored
Normal file
@@ -0,0 +1,605 @@
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import uniqWith from 'lodash/uniqWith';
|
||||
import { compact as oCompact } from './object-extensions';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
import { ExpressionError } from '../errors/expression.error';
|
||||
import { randomInt } from '../utils';
|
||||
function first(value) {
|
||||
return value[0];
|
||||
}
|
||||
function isEmpty(value) {
|
||||
return value.length === 0;
|
||||
}
|
||||
function isNotEmpty(value) {
|
||||
return value.length > 0;
|
||||
}
|
||||
function last(value) {
|
||||
return value[value.length - 1];
|
||||
}
|
||||
function pluck(value, extraArgs) {
|
||||
if (!Array.isArray(extraArgs)) {
|
||||
throw new ExpressionError('arguments must be passed to pluck');
|
||||
}
|
||||
if (!extraArgs || extraArgs.length === 0) {
|
||||
return value;
|
||||
}
|
||||
const plucked = value.reduce((pluckedFromObject, current) => {
|
||||
if (current && typeof current === 'object') {
|
||||
const p = [];
|
||||
Object.keys(current).forEach((k) => {
|
||||
extraArgs.forEach((field) => {
|
||||
if (current && field === k) {
|
||||
p.push(current[k]);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (p.length > 0) {
|
||||
pluckedFromObject.push(p.length === 1 ? p[0] : p);
|
||||
}
|
||||
}
|
||||
return pluckedFromObject;
|
||||
}, new Array());
|
||||
return plucked;
|
||||
}
|
||||
function randomItem(value) {
|
||||
const len = value === undefined ? 0 : value.length;
|
||||
return len ? value[randomInt(len)] : undefined;
|
||||
}
|
||||
function unique(value, extraArgs) {
|
||||
const mapForEqualityCheck = (item) => {
|
||||
if (extraArgs.length > 0 && item && typeof item === 'object') {
|
||||
return extraArgs.reduce((acc, key) => {
|
||||
acc[key] = item[key];
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
return item;
|
||||
};
|
||||
return uniqWith(value, (a, b) => isEqual(mapForEqualityCheck(a), mapForEqualityCheck(b)));
|
||||
}
|
||||
const ensureNumberArray = (arr, { fnName }) => {
|
||||
if (arr.some((i) => typeof i !== 'number')) {
|
||||
throw new ExpressionExtensionError(`${fnName}(): all array elements must be numbers`);
|
||||
}
|
||||
};
|
||||
function sum(value) {
|
||||
ensureNumberArray(value, { fnName: 'sum' });
|
||||
return value.reduce((p, c) => {
|
||||
if (typeof c === 'string') {
|
||||
return p + parseFloat(c);
|
||||
}
|
||||
if (typeof c !== 'number') {
|
||||
return NaN;
|
||||
}
|
||||
return p + c;
|
||||
}, 0);
|
||||
}
|
||||
function min(value) {
|
||||
ensureNumberArray(value, { fnName: 'min' });
|
||||
return Math.min(...value.map((v) => {
|
||||
if (typeof v === 'string') {
|
||||
return parseFloat(v);
|
||||
}
|
||||
if (typeof v !== 'number') {
|
||||
return NaN;
|
||||
}
|
||||
return v;
|
||||
}));
|
||||
}
|
||||
function max(value) {
|
||||
ensureNumberArray(value, { fnName: 'max' });
|
||||
return Math.max(...value.map((v) => {
|
||||
if (typeof v === 'string') {
|
||||
return parseFloat(v);
|
||||
}
|
||||
if (typeof v !== 'number') {
|
||||
return NaN;
|
||||
}
|
||||
return v;
|
||||
}));
|
||||
}
|
||||
export function average(value) {
|
||||
ensureNumberArray(value, { fnName: 'average' });
|
||||
// This would usually be NaN but I don't think users
|
||||
// will expect that
|
||||
if (value.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return sum(value) / value.length;
|
||||
}
|
||||
function compact(value) {
|
||||
return value
|
||||
.filter((v) => {
|
||||
if (v && typeof v === 'object' && Object.keys(v).length === 0)
|
||||
return false;
|
||||
return v !== null && v !== undefined && v !== 'nil' && v !== '';
|
||||
})
|
||||
.map((v) => {
|
||||
if (typeof v === 'object' && v !== null) {
|
||||
return oCompact(v);
|
||||
}
|
||||
return v;
|
||||
});
|
||||
}
|
||||
function smartJoin(value, extraArgs) {
|
||||
const [keyField, valueField] = extraArgs;
|
||||
if (!keyField || !valueField || typeof keyField !== 'string' || typeof valueField !== 'string') {
|
||||
throw new ExpressionExtensionError('smartJoin(): expected two string args, e.g. .smartJoin("name", "value")');
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
|
||||
return value.reduce((o, v) => {
|
||||
if (typeof v === 'object' && v !== null && keyField in v && valueField in v) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
||||
o[v[keyField]] = v[valueField];
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return o;
|
||||
}, {});
|
||||
}
|
||||
function chunk(value, extraArgs) {
|
||||
const [chunkSize] = extraArgs;
|
||||
if (typeof chunkSize !== 'number' || chunkSize === 0) {
|
||||
throw new ExpressionExtensionError('chunk(): expected non-zero numeric arg, e.g. .chunk(5)');
|
||||
}
|
||||
const chunks = [];
|
||||
for (let i = 0; i < value.length; i += chunkSize) {
|
||||
// I have no clue why eslint thinks 2 numbers could be anything but that but here we are
|
||||
chunks.push(value.slice(i, i + chunkSize));
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
function renameKeys(value, extraArgs) {
|
||||
if (extraArgs.length === 0 || extraArgs.length % 2 !== 0) {
|
||||
throw new ExpressionExtensionError('renameKeys(): expected an even amount of args: from1, to1 [, from2, to2, ...]. e.g. .renameKeys("name", "title")');
|
||||
}
|
||||
return value.map((v) => {
|
||||
if (typeof v !== 'object' || v === null) {
|
||||
return v;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
|
||||
const newObj = { ...v };
|
||||
const chunkedArgs = chunk(extraArgs, [2]);
|
||||
chunkedArgs.forEach(([from, to]) => {
|
||||
if (from in newObj) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
||||
newObj[to] = newObj[from];
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
delete newObj[from];
|
||||
}
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return newObj;
|
||||
});
|
||||
}
|
||||
function mergeObjects(value, extraArgs) {
|
||||
const [other] = extraArgs;
|
||||
if (!other) {
|
||||
return value;
|
||||
}
|
||||
if (typeof other !== 'object') {
|
||||
throw new ExpressionExtensionError('merge(): expected object arg');
|
||||
}
|
||||
const newObject = { ...value };
|
||||
for (const [key, val] of Object.entries(other)) {
|
||||
if (!(key in newObject)) {
|
||||
newObject[key] = val;
|
||||
}
|
||||
}
|
||||
return newObject;
|
||||
}
|
||||
function merge(value, extraArgs) {
|
||||
const [others] = extraArgs;
|
||||
if (others === undefined) {
|
||||
// If there are no arguments passed, merge all objects within the array
|
||||
const merged = value.reduce((combined, current) => {
|
||||
if (current !== null && typeof current === 'object' && !Array.isArray(current)) {
|
||||
combined = mergeObjects(combined, [current]);
|
||||
}
|
||||
return combined;
|
||||
}, {});
|
||||
return merged;
|
||||
}
|
||||
if (!Array.isArray(others)) {
|
||||
throw new ExpressionExtensionError('merge(): expected array arg, e.g. .merge([{ id: 1, otherValue: 3 }])');
|
||||
}
|
||||
const listLength = value.length > others.length ? value.length : others.length;
|
||||
let merged = {};
|
||||
for (let i = 0; i < listLength; i++) {
|
||||
if (value[i] !== undefined) {
|
||||
if (typeof value[i] === 'object' && typeof others[i] === 'object') {
|
||||
merged = Object.assign(merged, mergeObjects(value[i], [others[i]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
function union(value, extraArgs) {
|
||||
const [others] = extraArgs;
|
||||
if (!Array.isArray(others)) {
|
||||
throw new ExpressionExtensionError('union(): expected array arg, e.g. .union([1, 2, 3, 4])');
|
||||
}
|
||||
const newArr = Array.from(value);
|
||||
for (const v of others) {
|
||||
if (newArr.findIndex((w) => isEqual(w, v)) === -1) {
|
||||
newArr.push(v);
|
||||
}
|
||||
}
|
||||
return unique(newArr, []);
|
||||
}
|
||||
function difference(value, extraArgs) {
|
||||
const [others] = extraArgs;
|
||||
if (!Array.isArray(others)) {
|
||||
throw new ExpressionExtensionError('difference(): expected array arg, e.g. .difference([1, 2, 3, 4])');
|
||||
}
|
||||
const newArr = [];
|
||||
for (const v of value) {
|
||||
if (others.findIndex((w) => isEqual(w, v)) === -1) {
|
||||
newArr.push(v);
|
||||
}
|
||||
}
|
||||
return unique(newArr, []);
|
||||
}
|
||||
function intersection(value, extraArgs) {
|
||||
const [others] = extraArgs;
|
||||
if (!Array.isArray(others)) {
|
||||
throw new ExpressionExtensionError('intersection(): expected array arg, e.g. .intersection([1, 2, 3, 4])');
|
||||
}
|
||||
const newArr = [];
|
||||
for (const v of value) {
|
||||
if (others.findIndex((w) => isEqual(w, v)) !== -1) {
|
||||
newArr.push(v);
|
||||
}
|
||||
}
|
||||
for (const v of others) {
|
||||
if (value.findIndex((w) => isEqual(w, v)) !== -1) {
|
||||
newArr.push(v);
|
||||
}
|
||||
}
|
||||
return unique(newArr, []);
|
||||
}
|
||||
function append(value, extraArgs) {
|
||||
return value.concat(extraArgs);
|
||||
}
|
||||
export function toJsonString(value) {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
export function toInt() {
|
||||
return undefined;
|
||||
}
|
||||
export function toFloat() {
|
||||
return undefined;
|
||||
}
|
||||
export function toBoolean() {
|
||||
return undefined;
|
||||
}
|
||||
export function toDateTime() {
|
||||
return undefined;
|
||||
}
|
||||
average.doc = {
|
||||
name: 'average',
|
||||
description: 'Returns the average of the numbers in the array. Throws an error if there are any non-numbers.',
|
||||
examples: [{ example: '[12, 1, 5].average()', evaluated: '6' }],
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-average',
|
||||
};
|
||||
compact.doc = {
|
||||
name: 'compact',
|
||||
description: 'Removes any empty values from the array. <code>null</code>, <code>""</code> and <code>undefined</code> count as empty.',
|
||||
examples: [{ example: '[2, null, 1, ""].compact()', evaluated: '[2, 1]' }],
|
||||
returnType: 'Array',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-compact',
|
||||
};
|
||||
isEmpty.doc = {
|
||||
name: 'isEmpty',
|
||||
description: 'Returns <code>true</code> if the array has no elements or is <code>null</code>',
|
||||
examples: [
|
||||
{ example: '[].isEmpty()', evaluated: 'true' },
|
||||
{ example: "['quick', 'brown', 'fox'].isEmpty()", evaluated: 'false' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-isEmpty',
|
||||
};
|
||||
isNotEmpty.doc = {
|
||||
name: 'isNotEmpty',
|
||||
description: 'Returns <code>true</code> if the array has at least one element',
|
||||
examples: [
|
||||
{ example: "['quick', 'brown', 'fox'].isNotEmpty()", evaluated: 'true' },
|
||||
{ example: '[].isNotEmpty()', evaluated: 'false' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-isNotEmpty',
|
||||
};
|
||||
first.doc = {
|
||||
name: 'first',
|
||||
description: 'Returns the first element of the array',
|
||||
examples: [{ example: "['quick', 'brown', 'fox'].first()", evaluated: "'quick'" }],
|
||||
returnType: 'any',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-first',
|
||||
};
|
||||
last.doc = {
|
||||
name: 'last',
|
||||
description: 'Returns the last element of the array',
|
||||
examples: [{ example: "['quick', 'brown', 'fox'].last()", evaluated: "'fox'" }],
|
||||
returnType: 'any',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-last',
|
||||
};
|
||||
max.doc = {
|
||||
name: 'max',
|
||||
description: 'Returns the largest number in the array. Throws an error if there are any non-numbers.',
|
||||
examples: [{ example: '[1, 12, 5].max()', evaluated: '12' }],
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-max',
|
||||
};
|
||||
min.doc = {
|
||||
name: 'min',
|
||||
description: 'Returns the smallest number in the array. Throws an error if there are any non-numbers.',
|
||||
examples: [{ example: '[12, 1, 5].min()', evaluated: '1' }],
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-min',
|
||||
};
|
||||
randomItem.doc = {
|
||||
name: 'randomItem',
|
||||
description: 'Returns a randomly-chosen element from the array',
|
||||
examples: [
|
||||
{ example: "['quick', 'brown', 'fox'].randomItem()", evaluated: "'brown'" },
|
||||
{ example: "['quick', 'brown', 'fox'].randomItem()", evaluated: "'quick'" },
|
||||
],
|
||||
returnType: 'any',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-randomItem',
|
||||
};
|
||||
sum.doc = {
|
||||
name: 'sum',
|
||||
description: 'Returns the total of all the numbers in the array. Throws an error if there are any non-numbers.',
|
||||
examples: [{ example: '[12, 1, 5].sum()', evaluated: '18' }],
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-sum',
|
||||
};
|
||||
chunk.doc = {
|
||||
name: 'chunk',
|
||||
description: 'Splits the array into an array of sub-arrays, each with the given length',
|
||||
examples: [{ example: '[1, 2, 3, 4, 5, 6].chunk(2)', evaluated: '[[1,2],[3,4],[5,6]]' }],
|
||||
returnType: 'Array',
|
||||
args: [
|
||||
{
|
||||
name: 'length',
|
||||
optional: false,
|
||||
description: 'The number of elements in each chunk',
|
||||
type: 'number',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-chunk',
|
||||
};
|
||||
difference.doc = {
|
||||
name: 'difference',
|
||||
description: "Compares two arrays. Returns all elements in the base array that aren't present\nin <code>otherArray</code>.",
|
||||
examples: [{ example: '[1, 2, 3].difference([2, 3])', evaluated: '[1]' }],
|
||||
returnType: 'Array',
|
||||
args: [
|
||||
{
|
||||
name: 'otherArray',
|
||||
optional: false,
|
||||
description: 'The array to compare to the base array',
|
||||
type: 'Array',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-difference',
|
||||
};
|
||||
intersection.doc = {
|
||||
name: 'intersection',
|
||||
description: 'Compares two arrays. Returns all elements in the base array that are also present in the other array.',
|
||||
examples: [{ example: '[1, 2].intersection([2, 3])', evaluated: '[2]' }],
|
||||
returnType: 'Array',
|
||||
args: [
|
||||
{
|
||||
name: 'otherArray',
|
||||
optional: false,
|
||||
description: 'The array to compare to the base array',
|
||||
type: 'Array',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-intersection',
|
||||
};
|
||||
merge.doc = {
|
||||
name: 'merge',
|
||||
description: 'Merges two Object-arrays into one object by merging the key-value pairs of each element.',
|
||||
examples: [
|
||||
{
|
||||
example: "[{ name: 'Nathan' }, { age: 42 }].merge([{ city: 'Berlin' }, { country: 'Germany' }])",
|
||||
evaluated: "{ name: 'Nathan', age: 42, city: 'Berlin', country: 'Germany' }",
|
||||
},
|
||||
],
|
||||
returnType: 'Object',
|
||||
args: [
|
||||
{
|
||||
name: 'otherArray',
|
||||
optional: false,
|
||||
description: 'The array to merge into the base array',
|
||||
type: 'Array',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-merge',
|
||||
};
|
||||
pluck.doc = {
|
||||
name: 'pluck',
|
||||
description: 'Returns an array containing the values of the given field(s) in each Object of the array. Ignores any array elements that aren’t Objects or don’t have a key matching the field name(s) provided.',
|
||||
examples: [
|
||||
{
|
||||
example: "[{ name: 'Nathan', age: 42 },{ name: 'Jan', city: 'Berlin' }].pluck('name')",
|
||||
evaluated: '["Nathan", "Jan"]',
|
||||
},
|
||||
{
|
||||
example: "[{ name: 'Nathan', age: 42 },{ name: 'Jan', city: 'Berlin' }].pluck('age')",
|
||||
evaluated: '[42]',
|
||||
},
|
||||
],
|
||||
returnType: 'Array',
|
||||
args: [
|
||||
{
|
||||
name: 'fieldNames',
|
||||
optional: false,
|
||||
variadic: true,
|
||||
description: 'The keys to retrieve the value of',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-pluck',
|
||||
};
|
||||
renameKeys.doc = {
|
||||
name: 'renameKeys',
|
||||
description: 'Changes all matching keys (field names) of any Objects in the array. Rename more than one key by\nadding extra arguments, i.e. <code>from1, to1, from2, to2, ...</code>.',
|
||||
examples: [
|
||||
{
|
||||
example: "[{ name: 'bob' }, { name: 'meg' }].renameKeys('name', 'x')",
|
||||
evaluated: "[{ x: 'bob' }, { x: 'meg' }]",
|
||||
},
|
||||
],
|
||||
returnType: 'Array',
|
||||
args: [
|
||||
{
|
||||
name: 'from',
|
||||
optional: false,
|
||||
description: 'The key to rename',
|
||||
type: 'string',
|
||||
},
|
||||
{ name: 'to', optional: false, description: 'The new key name', type: 'string' },
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-renameKeys',
|
||||
};
|
||||
smartJoin.doc = {
|
||||
name: 'smartJoin',
|
||||
description: 'Creates a single Object from an array of Objects. Each Object in the array provides one field for the returned Object. Each Object in the array must contain a field with the key name and a field with the value.',
|
||||
examples: [
|
||||
{
|
||||
example: "[{ field: 'age', value: 2 }, { field: 'city', value: 'Berlin' }].smartJoin('field', 'value')",
|
||||
evaluated: "{ age: 2, city: 'Berlin' }",
|
||||
},
|
||||
],
|
||||
returnType: 'Object',
|
||||
args: [
|
||||
{
|
||||
name: 'keyField',
|
||||
optional: false,
|
||||
description: 'The field in each Object containing the key name',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
name: 'nameField',
|
||||
optional: false,
|
||||
description: 'The field in each Object containing the value',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-smartJoin',
|
||||
};
|
||||
union.doc = {
|
||||
name: 'union',
|
||||
description: 'Concatenates two arrays and then removes any duplicates',
|
||||
examples: [{ example: '[1, 2].union([2, 3])', evaluated: '[1, 2, 3]' }],
|
||||
returnType: 'Array',
|
||||
args: [
|
||||
{
|
||||
name: 'otherArray',
|
||||
optional: false,
|
||||
description: 'The array to union with the base array',
|
||||
type: 'Array',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-union',
|
||||
};
|
||||
unique.doc = {
|
||||
name: 'unique',
|
||||
description: 'Removes any duplicate elements from the array',
|
||||
examples: [
|
||||
{ example: "['quick', 'brown', 'quick'].unique()", evaluated: "['quick', 'brown']" },
|
||||
{
|
||||
example: "[{ name: 'Nathan', age: 42 }, { name: 'Nathan', age: 22 }].unique()",
|
||||
evaluated: "[{ name: 'Nathan', age: 42 }, { name: 'Nathan', age: 22 }]",
|
||||
},
|
||||
{
|
||||
example: "[{ name: 'Nathan', age: 42 }, { name: 'Nathan', age: 22 }].unique('name')",
|
||||
evaluated: "[{ name: 'Nathan', age: 42 }]",
|
||||
},
|
||||
],
|
||||
returnType: 'any',
|
||||
aliases: ['removeDuplicates'],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-unique',
|
||||
args: [
|
||||
{
|
||||
name: 'fieldNames',
|
||||
optional: false,
|
||||
variadic: true,
|
||||
description: 'The object keys to check for equality',
|
||||
type: 'any',
|
||||
},
|
||||
],
|
||||
};
|
||||
toJsonString.doc = {
|
||||
name: 'toJsonString',
|
||||
description: "Converts the array to a JSON string. The same as JavaScript's <code>JSON.stringify()</code>.",
|
||||
examples: [
|
||||
{
|
||||
example: "['quick', 'brown', 'fox'].toJsonString()",
|
||||
evaluated: '\'["quick","brown","fox"]\'',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-toJsonString',
|
||||
returnType: 'string',
|
||||
};
|
||||
append.doc = {
|
||||
name: 'append',
|
||||
description: 'Adds new elements to the end of the array. Similar to <code>push()</code>, but returns the modified array. Consider using spread syntax instead (see examples).',
|
||||
examples: [
|
||||
{ example: "['forget', 'me'].append('not')", evaluated: "['forget', 'me', 'not']" },
|
||||
{ example: '[9, 0, 2].append(1, 0)', evaluated: '[9, 0, 2, 1, 0]' },
|
||||
{
|
||||
example: '[...[9, 0, 2], 1, 0]',
|
||||
evaluated: '[9, 0, 2, 1, 0]',
|
||||
description: 'Consider using spread syntax instead',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-append',
|
||||
returnType: 'Array',
|
||||
args: [
|
||||
{
|
||||
name: 'elements',
|
||||
optional: false,
|
||||
variadic: true,
|
||||
description: 'The elements to append, in order',
|
||||
type: 'any',
|
||||
},
|
||||
],
|
||||
};
|
||||
const removeDuplicates = unique.bind({});
|
||||
removeDuplicates.doc = { ...unique.doc, hidden: true };
|
||||
export const arrayExtensions = {
|
||||
typeName: 'Array',
|
||||
functions: {
|
||||
removeDuplicates,
|
||||
unique,
|
||||
first,
|
||||
last,
|
||||
pluck,
|
||||
randomItem,
|
||||
sum,
|
||||
min,
|
||||
max,
|
||||
average,
|
||||
isNotEmpty,
|
||||
isEmpty,
|
||||
compact,
|
||||
smartJoin,
|
||||
chunk,
|
||||
renameKeys,
|
||||
merge,
|
||||
union,
|
||||
difference,
|
||||
intersection,
|
||||
append,
|
||||
toJsonString,
|
||||
toInt,
|
||||
toFloat,
|
||||
toBoolean,
|
||||
toDateTime,
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=array-extensions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/array-extensions.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
6
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.d.ts
generated
vendored
Normal file
6
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { ExtensionMap } from './extensions';
|
||||
export declare function toBoolean(value: boolean): boolean;
|
||||
export declare function toInt(value: boolean): 1 | 0;
|
||||
export declare function toDateTime(): undefined;
|
||||
export declare const booleanExtensions: ExtensionMap;
|
||||
//# sourceMappingURL=boolean-extensions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"boolean-extensions.d.ts","sourceRoot":"","sources":["../../../src/extensions/boolean-extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5D,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,WAEvC;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,SAEnC;AAED,wBAAgB,UAAU,cAEzB;AAmBD,eAAO,MAAM,iBAAiB,EAAE,YAS/B,CAAC"}
|
||||
33
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.js
generated
vendored
Normal file
33
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
export function toBoolean(value) {
|
||||
return value;
|
||||
}
|
||||
export function toInt(value) {
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
export function toDateTime() {
|
||||
return undefined;
|
||||
}
|
||||
const toFloat = toInt;
|
||||
const toNumber = toInt.bind({});
|
||||
toNumber.doc = {
|
||||
name: 'toNumber',
|
||||
description: 'Converts <code>true</code> to <code>1</code> and <code>false</code> to <code>0</code>.',
|
||||
examples: [
|
||||
{ example: 'true.toNumber()', evaluated: '1' },
|
||||
{ example: 'false.toNumber()', evaluated: '0' },
|
||||
],
|
||||
section: 'cast',
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/booleans/#boolean-toNumber',
|
||||
};
|
||||
export const booleanExtensions = {
|
||||
typeName: 'Boolean',
|
||||
functions: {
|
||||
toBoolean,
|
||||
toInt,
|
||||
toFloat,
|
||||
toNumber,
|
||||
toDateTime,
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=boolean-extensions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/boolean-extensions.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"boolean-extensions.js","sourceRoot":"","sources":["../../../src/extensions/boolean-extensions.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,KAAc;IACvC,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAc;IACnC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,UAAU;IACzB,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,KAAK,CAAC;AACtB,MAAM,QAAQ,GAAc,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAE3C,QAAQ,CAAC,GAAG,GAAG;IACd,IAAI,EAAE,UAAU;IAChB,WAAW,EACV,wFAAwF;IACzF,QAAQ,EAAE;QACT,EAAE,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,GAAG,EAAE;QAC9C,EAAE,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,GAAG,EAAE;KAC/C;IACD,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,QAAQ;IACpB,MAAM,EACL,2FAA2F;CAC5F,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAiB;IAC9C,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE;QACV,SAAS;QACT,KAAK;QACL,OAAO;QACP,QAAQ;QACR,UAAU;KACV;CACD,CAAC"}
|
||||
3
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.d.ts
generated
vendored
Normal file
3
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import type { ExtensionMap } from './extensions';
|
||||
export declare const dateExtensions: ExtensionMap;
|
||||
//# sourceMappingURL=date-extensions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"date-extensions.d.ts","sourceRoot":"","sources":["../../../src/extensions/date-extensions.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA+kBjD,eAAO,MAAM,cAAc,EAAE,YAsB5B,CAAC"}
|
||||
515
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.js
generated
vendored
Normal file
515
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.js
generated
vendored
Normal file
@@ -0,0 +1,515 @@
|
||||
import { DateTime } from 'luxon';
|
||||
import { toDateTime as stringToDateTime } from './string-extensions';
|
||||
import { convertToDateTime } from './utils';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
const durationUnits = [
|
||||
'milliseconds',
|
||||
'seconds',
|
||||
'minutes',
|
||||
'hours',
|
||||
'days',
|
||||
'weeks',
|
||||
'months',
|
||||
'quarters',
|
||||
'years',
|
||||
];
|
||||
const dateParts = [
|
||||
'day',
|
||||
'week',
|
||||
'month',
|
||||
'year',
|
||||
'hour',
|
||||
'minute',
|
||||
'second',
|
||||
'millisecond',
|
||||
'weekNumber',
|
||||
'yearDayNumber',
|
||||
'weekday',
|
||||
];
|
||||
const DURATION_MAP = {
|
||||
day: 'days',
|
||||
month: 'months',
|
||||
year: 'years',
|
||||
week: 'weeks',
|
||||
hour: 'hours',
|
||||
minute: 'minutes',
|
||||
second: 'seconds',
|
||||
millisecond: 'milliseconds',
|
||||
ms: 'milliseconds',
|
||||
sec: 'seconds',
|
||||
secs: 'seconds',
|
||||
hr: 'hours',
|
||||
hrs: 'hours',
|
||||
min: 'minutes',
|
||||
mins: 'minutes',
|
||||
};
|
||||
const DATETIMEUNIT_MAP = {
|
||||
days: 'day',
|
||||
months: 'month',
|
||||
years: 'year',
|
||||
hours: 'hour',
|
||||
minutes: 'minute',
|
||||
seconds: 'second',
|
||||
milliseconds: 'millisecond',
|
||||
hrs: 'hour',
|
||||
hr: 'hour',
|
||||
mins: 'minute',
|
||||
min: 'minute',
|
||||
secs: 'second',
|
||||
sec: 'second',
|
||||
ms: 'millisecond',
|
||||
};
|
||||
function isDateTime(date) {
|
||||
return date ? DateTime.isDateTime(date) : false;
|
||||
}
|
||||
function toDateTime(date) {
|
||||
if (isDateTime(date))
|
||||
return date;
|
||||
if (typeof date === 'string') {
|
||||
return stringToDateTime(date);
|
||||
}
|
||||
return DateTime.fromJSDate(date);
|
||||
}
|
||||
function generateDurationObject(durationValue, unit) {
|
||||
const convertedUnit = DURATION_MAP[unit] || unit;
|
||||
return { [`${convertedUnit}`]: durationValue };
|
||||
}
|
||||
function beginningOf(date, extraArgs) {
|
||||
const [rawUnit = 'week'] = extraArgs;
|
||||
const unit = DATETIMEUNIT_MAP[rawUnit] || rawUnit;
|
||||
if (isDateTime(date))
|
||||
return date.startOf(unit);
|
||||
return DateTime.fromJSDate(date).startOf(unit).toJSDate();
|
||||
}
|
||||
function endOfMonth(date) {
|
||||
if (isDateTime(date))
|
||||
return date.endOf('month');
|
||||
return DateTime.fromJSDate(date).endOf('month').toJSDate();
|
||||
}
|
||||
function extract(date, args) {
|
||||
let [part = 'week'] = args;
|
||||
if (part === 'yearDayNumber') {
|
||||
date = isDateTime(date) ? date.toJSDate() : date;
|
||||
const firstDayOfTheYear = new Date(date.getFullYear(), 0, 0);
|
||||
const diff = date.getTime() -
|
||||
firstDayOfTheYear.getTime() +
|
||||
(firstDayOfTheYear.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000;
|
||||
return Math.floor(diff / (1000 * 60 * 60 * 24));
|
||||
}
|
||||
if (part === 'week')
|
||||
part = 'weekNumber';
|
||||
const unit = DATETIMEUNIT_MAP[part] || part;
|
||||
if (isDateTime(date))
|
||||
return date.get(unit);
|
||||
return DateTime.fromJSDate(date).get(unit);
|
||||
}
|
||||
function format(date, extraArgs) {
|
||||
const [dateFormat, localeOpts = {}] = extraArgs;
|
||||
if (isDateTime(date)) {
|
||||
return date.toFormat(dateFormat, { ...localeOpts });
|
||||
}
|
||||
return DateTime.fromJSDate(date).toFormat(dateFormat, { ...localeOpts });
|
||||
}
|
||||
function isBetween(date, extraArgs) {
|
||||
if (extraArgs.length !== 2) {
|
||||
throw new ExpressionExtensionError('isBetween(): expected exactly two args');
|
||||
}
|
||||
const [first, second] = extraArgs;
|
||||
const firstDate = convertToDateTime(first);
|
||||
const secondDate = convertToDateTime(second);
|
||||
if (!firstDate || !secondDate) {
|
||||
return;
|
||||
}
|
||||
if (firstDate > secondDate) {
|
||||
return secondDate < date && date < firstDate;
|
||||
}
|
||||
return secondDate > date && date > firstDate;
|
||||
}
|
||||
function isDst(date) {
|
||||
if (isDateTime(date)) {
|
||||
return date.isInDST;
|
||||
}
|
||||
return DateTime.fromJSDate(date).isInDST;
|
||||
}
|
||||
function isInLast(date, extraArgs) {
|
||||
const [durationValue = 0, unit = 'minutes'] = extraArgs;
|
||||
const dateInThePast = DateTime.now().minus(generateDurationObject(durationValue, unit));
|
||||
let thisDate = date;
|
||||
if (!isDateTime(thisDate)) {
|
||||
thisDate = DateTime.fromJSDate(thisDate);
|
||||
}
|
||||
return dateInThePast <= thisDate && thisDate <= DateTime.now();
|
||||
}
|
||||
const WEEKEND_DAYS = [6, 7];
|
||||
function isWeekend(date) {
|
||||
const { weekday } = isDateTime(date) ? date : DateTime.fromJSDate(date);
|
||||
return WEEKEND_DAYS.includes(weekday);
|
||||
}
|
||||
function minus(date, args) {
|
||||
if (args.length === 1) {
|
||||
const [arg] = args;
|
||||
if (isDateTime(date))
|
||||
return date.minus(arg);
|
||||
return DateTime.fromJSDate(date).minus(arg).toJSDate();
|
||||
}
|
||||
const [durationValue = 0, unit = 'minutes'] = args;
|
||||
const duration = generateDurationObject(durationValue, unit);
|
||||
if (isDateTime(date))
|
||||
return date.minus(duration);
|
||||
return DateTime.fromJSDate(date).minus(duration).toJSDate();
|
||||
}
|
||||
function plus(date, args) {
|
||||
if (args.length === 1) {
|
||||
const [arg] = args;
|
||||
if (isDateTime(date))
|
||||
return date.plus(arg);
|
||||
return DateTime.fromJSDate(date).plus(arg).toJSDate();
|
||||
}
|
||||
const [durationValue = 0, unit = 'minutes'] = args;
|
||||
const duration = generateDurationObject(durationValue, unit);
|
||||
if (isDateTime(date))
|
||||
return date.plus(duration);
|
||||
return DateTime.fromJSDate(date).plus(duration).toJSDate();
|
||||
}
|
||||
function diffTo(date, args) {
|
||||
const [otherDate, unit = 'days'] = args;
|
||||
let units = Array.isArray(unit) ? unit : [unit];
|
||||
if (units.length === 0) {
|
||||
units = ['days'];
|
||||
}
|
||||
const allowedUnitSet = new Set([...dateParts, ...durationUnits]);
|
||||
const errorUnit = units.find((u) => !allowedUnitSet.has(u));
|
||||
if (errorUnit) {
|
||||
throw new ExpressionExtensionError(`Unsupported unit '${String(errorUnit)}'. Supported: ${durationUnits
|
||||
.map((u) => `'${u}'`)
|
||||
.join(', ')}.`);
|
||||
}
|
||||
const diffResult = date.diff(toDateTime(otherDate), units);
|
||||
if (units.length > 1) {
|
||||
return diffResult.toObject();
|
||||
}
|
||||
return diffResult.as(units[0]);
|
||||
}
|
||||
function diffToNow(date, args) {
|
||||
const [unit] = args;
|
||||
return diffTo(date, [DateTime.now(), unit]);
|
||||
}
|
||||
function toInt(date) {
|
||||
if (isDateTime(date)) {
|
||||
return date.toMillis();
|
||||
}
|
||||
return date.getTime();
|
||||
}
|
||||
const toFloat = toInt;
|
||||
function toBoolean() {
|
||||
return undefined;
|
||||
}
|
||||
// Only null/undefined return true, this is handled in ExpressionExtension.ts
|
||||
function isEmpty() {
|
||||
return false;
|
||||
}
|
||||
function isNotEmpty() {
|
||||
return true;
|
||||
}
|
||||
endOfMonth.doc = {
|
||||
name: 'endOfMonth',
|
||||
returnType: 'DateTime',
|
||||
hidden: true,
|
||||
description: 'Transforms a date to the last possible moment that lies within the month.',
|
||||
section: 'edit',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-endOfMonth',
|
||||
};
|
||||
isDst.doc = {
|
||||
name: 'isDst',
|
||||
returnType: 'boolean',
|
||||
hidden: true,
|
||||
description: 'Checks if a Date is within Daylight Savings Time.',
|
||||
section: 'query',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-isDst',
|
||||
};
|
||||
isWeekend.doc = {
|
||||
name: 'isWeekend',
|
||||
returnType: 'boolean',
|
||||
hidden: true,
|
||||
description: 'Checks if the Date falls on a Saturday or Sunday.',
|
||||
section: 'query',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-isWeekend',
|
||||
};
|
||||
beginningOf.doc = {
|
||||
name: 'beginningOf',
|
||||
description: 'Transform a Date to the start of the given time period. Default unit is `week`.',
|
||||
section: 'edit',
|
||||
hidden: true,
|
||||
returnType: 'DateTime',
|
||||
args: [{ name: 'unit?', type: 'DurationUnit' }],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-beginningOf',
|
||||
};
|
||||
extract.doc = {
|
||||
name: 'extract',
|
||||
description: 'Extracts a part of the date or time, e.g. the month, as a number. To extract textual names instead, see <code>format()</code>.',
|
||||
examples: [
|
||||
{ example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.extract('month')", evaluated: '3' },
|
||||
{ example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.extract('hour')", evaluated: '18' },
|
||||
],
|
||||
section: 'query',
|
||||
returnType: 'number',
|
||||
args: [
|
||||
{
|
||||
name: 'unit',
|
||||
optional: true,
|
||||
description: 'The part of the date or time to return. One of: <code>year</code>, <code>month</code>, <code>week</code>, <code>day</code>, <code>hour</code>, <code>minute</code>, <code>second</code>',
|
||||
default: '"week"',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-extract',
|
||||
};
|
||||
format.doc = {
|
||||
name: 'format',
|
||||
description: 'Converts the DateTime to a string, using the format specified. <a target="_blank" href="https://moment.github.io/luxon/#/formatting?id=table-of-tokens">Formatting guide</a>. For common formats, <code>toLocaleString()</code> may be easier.',
|
||||
examples: [
|
||||
{
|
||||
example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.format('dd/LL/yyyy')",
|
||||
evaluated: "'30/04/2024'",
|
||||
},
|
||||
{
|
||||
example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.format('dd LLL yy')",
|
||||
evaluated: "'30 Apr 24'",
|
||||
},
|
||||
{
|
||||
example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.setLocale('fr').format('dd LLL yyyy')",
|
||||
evaluated: "'30 avr. 2024'",
|
||||
},
|
||||
{
|
||||
example: "dt = '2024-04-30T18:49'.toDateTime()\ndt.format(\"HH 'hours and' mm 'minutes'\")",
|
||||
evaluated: "'18 hours and 49 minutes'",
|
||||
},
|
||||
],
|
||||
returnType: 'string',
|
||||
section: 'format',
|
||||
args: [
|
||||
{
|
||||
name: 'fmt',
|
||||
description: 'The <a target="_blank" href="https://moment.github.io/luxon/#/formatting?id=table-of-tokens">format</a> of the string to return ',
|
||||
default: "'yyyy-MM-dd'",
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-format',
|
||||
};
|
||||
isBetween.doc = {
|
||||
name: 'isBetween',
|
||||
description: 'Returns <code>true</code> if the DateTime lies between the two moments specified',
|
||||
examples: [
|
||||
{
|
||||
example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.isBetween('2020-06-01', '2025-06-01')",
|
||||
evaluated: 'true',
|
||||
},
|
||||
{
|
||||
example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.isBetween('2020', '2025')",
|
||||
evaluated: 'true',
|
||||
},
|
||||
],
|
||||
section: 'compare',
|
||||
returnType: 'boolean',
|
||||
args: [
|
||||
{
|
||||
name: 'date1',
|
||||
description: 'The moment that the base DateTime must be after. Can be an ISO date string or a Luxon DateTime.',
|
||||
type: 'string | DateTime',
|
||||
},
|
||||
{
|
||||
name: 'date2',
|
||||
description: 'The moment that the base DateTime must be before. Can be an ISO date string or a Luxon DateTime.',
|
||||
type: 'string | DateTime',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-isBetween',
|
||||
};
|
||||
isInLast.doc = {
|
||||
name: 'isInLast',
|
||||
hidden: true,
|
||||
description: 'Checks if a Date is within a given time period. Default unit is `minute`.',
|
||||
section: 'query',
|
||||
returnType: 'boolean',
|
||||
args: [
|
||||
{ name: 'n', type: 'number' },
|
||||
{ name: 'unit?', type: 'DurationUnit' },
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-isInLast',
|
||||
};
|
||||
toDateTime.doc = {
|
||||
name: 'toDateTime',
|
||||
description: 'Converts a JavaScript Date to a Luxon DateTime. The DateTime contains the same information, but is easier to manipulate.',
|
||||
examples: [
|
||||
{
|
||||
example: "jsDate = new Date('2024-03-30T18:49')\njsDate.toDateTime().plus(5, 'days')",
|
||||
evaluated: '[DateTime: 2024-05-05T18:49:00.000Z]',
|
||||
},
|
||||
],
|
||||
returnType: 'DateTime',
|
||||
hidden: true,
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-toDateTime',
|
||||
};
|
||||
minus.doc = {
|
||||
name: 'minus',
|
||||
description: 'Subtracts a given period of time from the DateTime',
|
||||
examples: [
|
||||
{
|
||||
example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.minus(7, 'days')",
|
||||
evaluated: '[DateTime: 2024-04-23T18:49:00.000Z]',
|
||||
},
|
||||
{
|
||||
example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.minus(4, 'years')",
|
||||
evaluated: '[DateTime: 2020-04-30T18:49:00.000Z]',
|
||||
},
|
||||
],
|
||||
section: 'edit',
|
||||
returnType: 'DateTime',
|
||||
args: [
|
||||
{
|
||||
name: 'n',
|
||||
description: 'The number of units to subtract. Or use a Luxon <a target="_blank" href=”https://moment.github.io/luxon/api-docs/index.html#duration”>Duration</a> object to subtract multiple units at once.',
|
||||
type: 'number | object',
|
||||
},
|
||||
{
|
||||
name: 'unit',
|
||||
optional: true,
|
||||
description: 'The units of the number. One of: <code>years</code>, <code>months</code>, <code>weeks</code>, <code>days</code>, <code>hours</code>, <code>minutes</code>, <code>seconds</code>, <code>milliseconds</code>',
|
||||
default: '"milliseconds"',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-minus',
|
||||
};
|
||||
plus.doc = {
|
||||
name: 'plus',
|
||||
description: 'Adds a given period of time to the DateTime',
|
||||
examples: [
|
||||
{
|
||||
example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.plus(7, 'days')",
|
||||
evaluated: '[DateTime: 2024-04-07T18:49:00.000Z]',
|
||||
},
|
||||
{
|
||||
example: "dt = '2024-03-30T18:49'.toDateTime()\ndt.plus(4, 'years')",
|
||||
evaluated: '[DateTime: 2028-03-30T18:49:00.000Z]',
|
||||
},
|
||||
],
|
||||
section: 'edit',
|
||||
returnType: 'DateTime',
|
||||
args: [
|
||||
{
|
||||
name: 'n',
|
||||
description: 'The number of units to add. Or use a Luxon <a target="_blank" href=”https://moment.github.io/luxon/api-docs/index.html#duration”>Duration</a> object to add multiple units at once.',
|
||||
type: 'number | object',
|
||||
},
|
||||
{
|
||||
name: 'unit',
|
||||
optional: true,
|
||||
description: 'The units of the number. One of: <code>years</code>, <code>months</code>, <code>weeks</code>, <code>days</code>, <code>hours</code>, <code>minutes</code>, <code>seconds</code>, <code>milliseconds</code>',
|
||||
default: '"milliseconds"',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-plus',
|
||||
};
|
||||
diffTo.doc = {
|
||||
name: 'diffTo',
|
||||
description: 'Returns the difference between two DateTimes, in the given unit(s)',
|
||||
examples: [
|
||||
{
|
||||
example: "dt = '2025-01-01'.toDateTime()\ndt.diffTo('2024-03-30T18:49:07.234', 'days')",
|
||||
evaluated: '276.21',
|
||||
},
|
||||
{
|
||||
example: "dt1 = '2025-01-01T00:00:00.000'.toDateTime();\ndt2 = '2024-03-30T18:49:07.234'.toDateTime();\ndt1.diffTo(dt2, ['months', 'days'])",
|
||||
evaluated: '{ months: 9, days: 1.21 }',
|
||||
},
|
||||
],
|
||||
section: 'compare',
|
||||
returnType: 'number | Record<DurationUnit, number>',
|
||||
args: [
|
||||
{
|
||||
name: 'otherDateTime',
|
||||
default: '$now',
|
||||
description: 'The moment to subtract the base DateTime from. Can be an ISO date string or a Luxon DateTime.',
|
||||
type: 'string | DateTime',
|
||||
},
|
||||
{
|
||||
name: 'unit',
|
||||
default: "'days'",
|
||||
description: 'The unit, or array of units, to return the result in. Possible values: <code>years</code>, <code>months</code>, <code>weeks</code>, <code>days</code>, <code>hours</code>, <code>minutes</code>, <code>seconds</code>, <code>milliseconds</code>.',
|
||||
type: 'string | string[]',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-diffTo',
|
||||
};
|
||||
diffToNow.doc = {
|
||||
name: 'diffToNow',
|
||||
description: 'Returns the difference between the current moment and the DateTime, in the given unit(s). For a textual representation, use <code>toRelative()</code> instead.',
|
||||
examples: [
|
||||
{
|
||||
example: "dt = '2023-03-30T18:49:07.234'.toDateTime()\ndt.diffToNow('days')",
|
||||
evaluated: '371.9',
|
||||
},
|
||||
{
|
||||
example: "dt = '2023-03-30T18:49:07.234'.toDateTime()\ndt.diffToNow(['months', 'days'])",
|
||||
evaluated: '{ months: 12, days: 5.9 }',
|
||||
},
|
||||
],
|
||||
section: 'compare',
|
||||
returnType: 'number | Record<DurationUnit, number>',
|
||||
args: [
|
||||
{
|
||||
name: 'unit',
|
||||
description: 'The unit, or array of units, to return the result in. Possible values: <code>years</code>, <code>months</code>, <code>weeks</code>, <code>days</code>, <code>hours</code>, <code>minutes</code>, <code>seconds</code>, <code>milliseconds</code>.',
|
||||
default: "'days'",
|
||||
type: 'string | string[]',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/dates/#date-diffToNow',
|
||||
};
|
||||
isEmpty.doc = {
|
||||
name: 'isEmpty',
|
||||
description: 'Returns <code>false</code> for all DateTimes. Returns <code>true</code> for <code>null</code>.',
|
||||
examples: [
|
||||
{ example: "dt = '2023-03-30T18:49:07.234'.toDateTime()\ndt.isEmpty()", evaluated: 'false' },
|
||||
{ example: 'dt = null\ndt.isEmpty()', evaluated: 'true' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-isEmpty',
|
||||
};
|
||||
isNotEmpty.doc = {
|
||||
name: 'isNotEmpty',
|
||||
description: 'Returns <code>true</code> for all DateTimes. Returns <code>false</code> for <code>null</code>.',
|
||||
examples: [
|
||||
{ example: "dt = '2023-03-30T18:49:07.234'.toDateTime()\ndt.isNotEmpty()", evaluated: 'true' },
|
||||
{ example: 'dt = null\ndt.isNotEmpty()', evaluated: 'false' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/arrays/#array-isNotEmpty',
|
||||
};
|
||||
export const dateExtensions = {
|
||||
typeName: 'Date',
|
||||
functions: {
|
||||
beginningOf,
|
||||
endOfMonth,
|
||||
extract,
|
||||
isBetween,
|
||||
isDst,
|
||||
isInLast,
|
||||
isWeekend,
|
||||
minus,
|
||||
plus,
|
||||
format,
|
||||
toDateTime,
|
||||
diffTo,
|
||||
diffToNow,
|
||||
toInt,
|
||||
toFloat,
|
||||
toBoolean,
|
||||
isEmpty,
|
||||
isNotEmpty,
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=date-extensions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/date-extensions.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
32
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.d.ts
generated
vendored
Normal file
32
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.d.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { ExtensionMap } from './extensions';
|
||||
export declare const EXTENSION_OBJECTS: ExtensionMap[];
|
||||
export declare const hasExpressionExtension: (str: string) => boolean;
|
||||
export declare const hasNativeMethod: (method: string) => boolean;
|
||||
/**
|
||||
* A function to inject an extender function call into the AST of an expression.
|
||||
* This uses recast to do the transform.
|
||||
*
|
||||
* This function also polyfills optional chaining if using extended functions.
|
||||
*
|
||||
* ```ts
|
||||
* 'a'.method('x') // becomes
|
||||
* extend('a', 'method', ['x']);
|
||||
*
|
||||
* 'a'.first('x').second('y') // becomes
|
||||
* extend(extend('a', 'first', ['x']), 'second', ['y']));
|
||||
* ```
|
||||
*/
|
||||
export declare const extendTransform: (expression: string) => {
|
||||
code: string;
|
||||
} | undefined;
|
||||
/**
|
||||
* Extender function injected by expression extension plugin to allow calls to extensions.
|
||||
*
|
||||
* ```ts
|
||||
* extend(input, "functionName", [...args]);
|
||||
* ```
|
||||
*/
|
||||
export declare function extend(input: unknown, functionName: string, args: unknown[]): any;
|
||||
export declare function extendOptional(input: unknown, functionName: string): Function | undefined;
|
||||
export declare function extendSyntax(bracketedExpression: string, forceExtend?: boolean): string;
|
||||
//# sourceMappingURL=expression-extension.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"expression-extension.d.ts","sourceRoot":"","sources":["../../../src/extensions/expression-extension.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAkBjD,eAAO,MAAM,iBAAiB,EAAE,YAAY,EAO3C,CAAC;AA0BF,eAAO,MAAM,sBAAsB,GAAI,KAAK,MAAM,KAAG,OAChB,CAAC;AAEtC,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,KAAG,OAmBhD,CAAC;AAsBF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,GAAI,YAAY,MAAM,KAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SA0TvE,CAAC;AAgEF;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAkC3E;AAED,wBAAgB,cAAc,CAC7B,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,MAAM,GAElB,QAAQ,GAAG,SAAS,CAgBtB;AAID,wBAAgB,YAAY,CAAC,mBAAmB,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,MAAM,CAsDrF"}
|
||||
472
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.js
generated
vendored
Normal file
472
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.js
generated
vendored
Normal file
@@ -0,0 +1,472 @@
|
||||
import { parse as esprimaParse } from 'esprima-next';
|
||||
import { DateTime } from 'luxon';
|
||||
import { parse, visit, types, print } from 'recast';
|
||||
import { getOption } from 'recast/lib/util';
|
||||
import { arrayExtensions } from './array-extensions';
|
||||
import { booleanExtensions } from './boolean-extensions';
|
||||
import { dateExtensions } from './date-extensions';
|
||||
import { joinExpression, splitExpression } from './expression-parser';
|
||||
import { numberExtensions } from './number-extensions';
|
||||
import { objectExtensions } from './object-extensions';
|
||||
import { stringExtensions } from './string-extensions';
|
||||
import { checkIfValueDefinedOrThrow } from './utils';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
const EXPRESSION_EXTENDER = 'extend';
|
||||
const EXPRESSION_EXTENDER_OPTIONAL = 'extendOptional';
|
||||
function isEmpty(value) {
|
||||
return value === null || value === undefined || !value;
|
||||
}
|
||||
function isNotEmpty(value) {
|
||||
return !isEmpty(value);
|
||||
}
|
||||
export const EXTENSION_OBJECTS = [
|
||||
arrayExtensions,
|
||||
dateExtensions,
|
||||
numberExtensions,
|
||||
objectExtensions,
|
||||
stringExtensions,
|
||||
booleanExtensions,
|
||||
];
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
||||
const genericExtensions = {
|
||||
isEmpty,
|
||||
isNotEmpty,
|
||||
};
|
||||
const EXPRESSION_EXTENSION_METHODS = Array.from(new Set([
|
||||
...Object.keys(stringExtensions.functions),
|
||||
...Object.keys(numberExtensions.functions),
|
||||
...Object.keys(dateExtensions.functions),
|
||||
...Object.keys(arrayExtensions.functions),
|
||||
...Object.keys(objectExtensions.functions),
|
||||
...Object.keys(booleanExtensions.functions),
|
||||
...Object.keys(genericExtensions),
|
||||
]));
|
||||
const EXPRESSION_EXTENSION_REGEX = new RegExp(`(\\$if|\\.(${EXPRESSION_EXTENSION_METHODS.join('|')})\\s*(\\?\\.)?)\\s*\\(`);
|
||||
const isExpressionExtension = (str) => EXPRESSION_EXTENSION_METHODS.some((m) => m === str);
|
||||
export const hasExpressionExtension = (str) => EXPRESSION_EXTENSION_REGEX.test(str);
|
||||
export const hasNativeMethod = (method) => {
|
||||
if (hasExpressionExtension(method)) {
|
||||
return false;
|
||||
}
|
||||
const methods = method
|
||||
.replace(/[^\w\s]/gi, ' ')
|
||||
.split(' ')
|
||||
.filter(Boolean); // DateTime.now().toLocaleString().format() => [DateTime,now,toLocaleString,format]
|
||||
return methods.every((methodName) => {
|
||||
return [String.prototype, Array.prototype, Number.prototype, Date.prototype].some((nativeType) => {
|
||||
if (methodName in nativeType) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
// /**
|
||||
// * recast's types aren't great and we need to use a lot of anys
|
||||
// */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function parseWithEsprimaNext(source, options) {
|
||||
const ast = esprimaParse(source, {
|
||||
loc: true,
|
||||
locations: true,
|
||||
comment: true,
|
||||
range: getOption(options, 'range', false),
|
||||
tolerant: getOption(options, 'tolerant', true),
|
||||
tokens: true,
|
||||
jsx: getOption(options, 'jsx', false),
|
||||
sourceType: getOption(options, 'sourceType', 'module'),
|
||||
});
|
||||
return ast;
|
||||
}
|
||||
/**
|
||||
* A function to inject an extender function call into the AST of an expression.
|
||||
* This uses recast to do the transform.
|
||||
*
|
||||
* This function also polyfills optional chaining if using extended functions.
|
||||
*
|
||||
* ```ts
|
||||
* 'a'.method('x') // becomes
|
||||
* extend('a', 'method', ['x']);
|
||||
*
|
||||
* 'a'.first('x').second('y') // becomes
|
||||
* extend(extend('a', 'first', ['x']), 'second', ['y']));
|
||||
* ```
|
||||
*/
|
||||
export const extendTransform = (expression) => {
|
||||
try {
|
||||
const ast = parse(expression, { parser: { parse: parseWithEsprimaNext } });
|
||||
let currentChain = 1;
|
||||
// Polyfill optional chaining
|
||||
visit(ast, {
|
||||
// eslint-disable-next-line complexity
|
||||
visitChainExpression(path) {
|
||||
this.traverse(path);
|
||||
const chainNumber = currentChain;
|
||||
currentChain += 1;
|
||||
// This is to match behavior in our original expression evaluator (tmpl)
|
||||
const globalIdentifier = types.builders.identifier(typeof window !== 'object' ? 'global' : 'window');
|
||||
// We want to define all of our commonly used identifiers and member
|
||||
// expressions now so we don't have to create multiple instances
|
||||
const undefinedIdentifier = types.builders.identifier('undefined');
|
||||
const cancelIdentifier = types.builders.identifier(`chainCancelToken${chainNumber}`);
|
||||
const valueIdentifier = types.builders.identifier(`chainValue${chainNumber}`);
|
||||
const cancelMemberExpression = types.builders.memberExpression(globalIdentifier, cancelIdentifier);
|
||||
const valueMemberExpression = types.builders.memberExpression(globalIdentifier, valueIdentifier);
|
||||
const patchedStack = [];
|
||||
// This builds the cancel check. This lets us slide to the end of the expression
|
||||
// if it's undefined/null at any of the optional points of the chain.
|
||||
const buildCancelCheckWrapper = (node) => {
|
||||
return types.builders.conditionalExpression(types.builders.binaryExpression('===', cancelMemberExpression, types.builders.booleanLiteral(true)), undefinedIdentifier, node);
|
||||
};
|
||||
// This is just a quick small wrapper to create the assignment expression
|
||||
// for the running value.
|
||||
const buildValueAssignWrapper = (node) => {
|
||||
return types.builders.assignmentExpression('=', valueMemberExpression, node);
|
||||
};
|
||||
// This builds what actually does the comparison. It wraps the current
|
||||
// chunk of the expression with a nullish coalescing operator that returns
|
||||
// undefined if it's null or undefined. We do this because optional chains
|
||||
// always return undefined if they fail part way, even if the value they
|
||||
// fail on is null.
|
||||
const buildOptionalWrapper = (node) => {
|
||||
return types.builders.binaryExpression('===', types.builders.logicalExpression('??', buildValueAssignWrapper(node), undefinedIdentifier), undefinedIdentifier);
|
||||
};
|
||||
// Another small wrapper, but for assigning to the cancel token this time.
|
||||
const buildCancelAssignWrapper = (node) => {
|
||||
return types.builders.assignmentExpression('=', cancelMemberExpression, node);
|
||||
};
|
||||
let currentNode = path.node.expression;
|
||||
let currentPatch = null;
|
||||
let patchTop = null;
|
||||
let wrapNextTopInOptionalExtend = false;
|
||||
// This patches the previous node to use our current one as it's left hand value.
|
||||
// It takes `window.chainValue1.test1` and `window.chainValue1.test2` and turns it
|
||||
// into `window.chainValue1.test2.test1`.
|
||||
const updatePatch = (toPatch, node) => {
|
||||
if (toPatch.type === 'MemberExpression' || toPatch.type === 'OptionalMemberExpression') {
|
||||
toPatch.object = node;
|
||||
}
|
||||
else if (toPatch.type === 'CallExpression' ||
|
||||
toPatch.type === 'OptionalCallExpression') {
|
||||
toPatch.callee = node;
|
||||
}
|
||||
};
|
||||
// This loop walks down an optional chain from the top. This will walk
|
||||
// from right to left through an optional chain. We keep track of our current
|
||||
// top of the chain (furthest right) and create a chain below it. This chain
|
||||
// contains all of the (member and call) expressions that we need. These are
|
||||
// patched versions that reference our current chain value. We then push this
|
||||
// chain onto a stack when we hit an optional point in our chain.
|
||||
while (true) {
|
||||
// This should only ever be these types but you can optional chain on
|
||||
// JSX nodes, which we don't support.
|
||||
if (currentNode.type === 'MemberExpression' ||
|
||||
currentNode.type === 'OptionalMemberExpression' ||
|
||||
currentNode.type === 'CallExpression' ||
|
||||
currentNode.type === 'OptionalCallExpression') {
|
||||
let patchNode;
|
||||
// Here we take the current node and extract the parts we actually care
|
||||
// about.
|
||||
// In the case of a member expression we take the property it's trying to
|
||||
// access and make the object it's accessing be our chain value.
|
||||
if (currentNode.type === 'MemberExpression' ||
|
||||
currentNode.type === 'OptionalMemberExpression') {
|
||||
patchNode = types.builders.memberExpression(valueMemberExpression, currentNode.property);
|
||||
// In the case of a call expression we take the arguments and make the
|
||||
// callee our chain value.
|
||||
}
|
||||
else {
|
||||
patchNode = types.builders.callExpression(valueMemberExpression, currentNode.arguments);
|
||||
}
|
||||
// If we have a previous node we patch it here.
|
||||
if (currentPatch) {
|
||||
updatePatch(currentPatch, patchNode);
|
||||
}
|
||||
// If we have no top patch (first run, or just pushed onto the stack) we
|
||||
// note it here.
|
||||
if (!patchTop) {
|
||||
patchTop = patchNode;
|
||||
}
|
||||
currentPatch = patchNode;
|
||||
// This is an optional in our chain. In here we'll push the node onto the
|
||||
// stack. We also do a polyfill if the top of the stack is function call
|
||||
// that might be a extended function.
|
||||
if (currentNode.optional) {
|
||||
// Implement polyfill described below
|
||||
if (wrapNextTopInOptionalExtend) {
|
||||
wrapNextTopInOptionalExtend = false;
|
||||
// This shouldn't ever happen
|
||||
if (patchTop.type === 'MemberExpression' &&
|
||||
patchTop.property.type === 'Identifier') {
|
||||
patchTop = types.builders.callExpression(types.builders.identifier(EXPRESSION_EXTENDER_OPTIONAL), [patchTop.object, types.builders.stringLiteral(patchTop.property.name)]);
|
||||
}
|
||||
}
|
||||
patchedStack.push(patchTop);
|
||||
patchTop = null;
|
||||
currentPatch = null;
|
||||
// Attempting to optional chain on an extended function. If we don't
|
||||
// polyfill this most calls will always be undefined. Marking that the
|
||||
// next part of the chain should be wrapped in our polyfill.
|
||||
if ((currentNode.type === 'CallExpression' ||
|
||||
currentNode.type === 'OptionalCallExpression') &&
|
||||
(currentNode.callee.type === 'MemberExpression' ||
|
||||
currentNode.callee.type === 'OptionalMemberExpression') &&
|
||||
currentNode.callee.property.type === 'Identifier' &&
|
||||
isExpressionExtension(currentNode.callee.property.name)) {
|
||||
wrapNextTopInOptionalExtend = true;
|
||||
}
|
||||
}
|
||||
// Finally we get the next point AST to walk down.
|
||||
if (currentNode.type === 'MemberExpression' ||
|
||||
currentNode.type === 'OptionalMemberExpression') {
|
||||
currentNode = currentNode.object;
|
||||
}
|
||||
else {
|
||||
currentNode = currentNode.callee;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We update the final patch to point to the first part of the optional chain
|
||||
// which is probably an identifier for an object.
|
||||
if (currentPatch) {
|
||||
updatePatch(currentPatch, currentNode);
|
||||
if (!patchTop) {
|
||||
patchTop = currentPatch;
|
||||
}
|
||||
}
|
||||
if (wrapNextTopInOptionalExtend) {
|
||||
wrapNextTopInOptionalExtend = false;
|
||||
// This shouldn't ever happen
|
||||
if (patchTop?.type === 'MemberExpression' &&
|
||||
patchTop.property.type === 'Identifier') {
|
||||
patchTop = types.builders.callExpression(types.builders.identifier(EXPRESSION_EXTENDER_OPTIONAL), [patchTop.object, types.builders.stringLiteral(patchTop.property.name)]);
|
||||
}
|
||||
}
|
||||
// Push the first part of our chain to stack.
|
||||
if (patchTop) {
|
||||
patchedStack.push(patchTop);
|
||||
}
|
||||
else {
|
||||
patchedStack.push(currentNode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Since we're working from right to left we need to flip the stack
|
||||
// for the correct order of operations
|
||||
patchedStack.reverse();
|
||||
// Walk the node stack and wrap all our expressions in cancel/assignment
|
||||
// wrappers.
|
||||
for (let i = 0; i < patchedStack.length; i++) {
|
||||
let node = patchedStack[i];
|
||||
// We don't wrap the last expression in an assignment wrapper because
|
||||
// it's going to be returned anyway. We just wrap it in a cancel check
|
||||
// wrapper.
|
||||
if (i !== patchedStack.length - 1) {
|
||||
node = buildCancelAssignWrapper(buildOptionalWrapper(node));
|
||||
}
|
||||
// Don't wrap the first part in a cancel wrapper because the cancel
|
||||
// token will always be undefined.
|
||||
if (i !== 0) {
|
||||
node = buildCancelCheckWrapper(node);
|
||||
}
|
||||
// Replace the node in the stack with our wrapped one
|
||||
patchedStack[i] = node;
|
||||
}
|
||||
// Put all our expressions in a sequence expression (also called a
|
||||
// group operator). These will all be executed in order and the value
|
||||
// of the final expression will be returned.
|
||||
const sequenceNode = types.builders.sequenceExpression(patchedStack);
|
||||
path.replace(sequenceNode);
|
||||
},
|
||||
});
|
||||
// Extended functions
|
||||
visit(ast, {
|
||||
visitCallExpression(path) {
|
||||
this.traverse(path);
|
||||
if (path.node.callee.type === 'MemberExpression' &&
|
||||
path.node.callee.property.type === 'Identifier' &&
|
||||
isExpressionExtension(path.node.callee.property.name)) {
|
||||
path.replace(types.builders.callExpression(types.builders.identifier(EXPRESSION_EXTENDER), [
|
||||
path.node.callee.object,
|
||||
types.builders.stringLiteral(path.node.callee.property.name),
|
||||
types.builders.arrayExpression(path.node.arguments),
|
||||
]));
|
||||
}
|
||||
else if (path.node.callee.type === 'Identifier' &&
|
||||
path.node.callee.name === '$if' &&
|
||||
path.node.arguments.every((v) => v.type !== 'SpreadElement')) {
|
||||
if (path.node.arguments.length < 2) {
|
||||
throw new ExpressionExtensionError('$if requires at least 2 parameters: test, value_if_true[, and value_if_false]');
|
||||
}
|
||||
const test = path.node.arguments[0];
|
||||
const consequent = path.node.arguments[1];
|
||||
const alternative = path.node.arguments[2] === undefined
|
||||
? types.builders.booleanLiteral(false)
|
||||
: path.node.arguments[2];
|
||||
path.replace(types.builders.conditionalExpression(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
||||
test,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
||||
consequent,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
|
||||
alternative));
|
||||
}
|
||||
},
|
||||
});
|
||||
return print(ast);
|
||||
}
|
||||
catch (e) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
function isDate(input) {
|
||||
if (typeof input !== 'string' || !input.length) {
|
||||
return false;
|
||||
}
|
||||
if (!/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(input)) {
|
||||
return false;
|
||||
}
|
||||
const d = new Date(input);
|
||||
return d instanceof Date && !isNaN(d.valueOf()) && d.toISOString() === input;
|
||||
}
|
||||
function findExtendedFunction(input, functionName) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
||||
let foundFunction;
|
||||
if (Array.isArray(input)) {
|
||||
foundFunction = arrayExtensions.functions[functionName];
|
||||
}
|
||||
else if (isDate(input) && functionName !== 'toDate' && functionName !== 'toDateTime') {
|
||||
// If it's a string date (from $json), convert it to a Date object,
|
||||
// unless that function is `toDate`, since `toDate` does something
|
||||
// very different on date objects
|
||||
input = new Date(input);
|
||||
foundFunction = dateExtensions.functions[functionName];
|
||||
}
|
||||
else if (typeof input === 'string') {
|
||||
foundFunction = stringExtensions.functions[functionName];
|
||||
}
|
||||
else if (typeof input === 'number') {
|
||||
foundFunction = numberExtensions.functions[functionName];
|
||||
}
|
||||
else if (input && (DateTime.isDateTime(input) || input instanceof Date)) {
|
||||
foundFunction = dateExtensions.functions[functionName];
|
||||
}
|
||||
else if (input !== null && typeof input === 'object') {
|
||||
foundFunction = objectExtensions.functions[functionName];
|
||||
}
|
||||
else if (typeof input === 'boolean') {
|
||||
foundFunction = booleanExtensions.functions[functionName];
|
||||
}
|
||||
// Look for generic or builtin
|
||||
if (!foundFunction) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const inputAny = input;
|
||||
// This is likely a builtin we're implementing for another type
|
||||
// (e.g. toLocaleString). We'll return that instead
|
||||
if (inputAny && functionName && typeof inputAny[functionName] === 'function') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
return { type: 'native', function: inputAny[functionName] };
|
||||
}
|
||||
// Use a generic version if available
|
||||
foundFunction = genericExtensions[functionName];
|
||||
}
|
||||
if (!foundFunction) {
|
||||
return undefined;
|
||||
}
|
||||
return { type: 'extended', function: foundFunction };
|
||||
}
|
||||
/**
|
||||
* Extender function injected by expression extension plugin to allow calls to extensions.
|
||||
*
|
||||
* ```ts
|
||||
* extend(input, "functionName", [...args]);
|
||||
* ```
|
||||
*/
|
||||
export function extend(input, functionName, args) {
|
||||
const foundFunction = findExtendedFunction(input, functionName);
|
||||
// No type specific or generic function found. Check to see if
|
||||
// any types have a function with that name. Then throw an error
|
||||
// letting the user know the available types.
|
||||
if (!foundFunction) {
|
||||
checkIfValueDefinedOrThrow(input, functionName);
|
||||
const haveFunction = EXTENSION_OBJECTS.filter((v) => functionName in v.functions);
|
||||
if (!haveFunction.length) {
|
||||
// This shouldn't really be possible but we should cover it anyway
|
||||
throw new ExpressionExtensionError(`Unknown expression function: ${functionName}`);
|
||||
}
|
||||
if (haveFunction.length > 1) {
|
||||
const lastType = `"${haveFunction.pop().typeName}"`;
|
||||
const typeNames = `${haveFunction.map((v) => `"${v.typeName}"`).join(', ')}, and ${lastType}`;
|
||||
throw new ExpressionExtensionError(`${functionName}() is only callable on types ${typeNames}`);
|
||||
}
|
||||
else {
|
||||
throw new ExpressionExtensionError(`${functionName}() is only callable on type "${haveFunction[0].typeName}"`);
|
||||
}
|
||||
}
|
||||
if (foundFunction.type === 'native') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return foundFunction.function.apply(input, args);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return foundFunction.function(input, args);
|
||||
}
|
||||
export function extendOptional(input, functionName) {
|
||||
const foundFunction = findExtendedFunction(input, functionName);
|
||||
if (!foundFunction) {
|
||||
return undefined;
|
||||
}
|
||||
if (foundFunction.type === 'native') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return foundFunction.function.bind(input);
|
||||
}
|
||||
return (...args) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return foundFunction.function(input, args);
|
||||
};
|
||||
}
|
||||
const EXTENDED_SYNTAX_CACHE = {};
|
||||
export function extendSyntax(bracketedExpression, forceExtend = false) {
|
||||
const chunks = splitExpression(bracketedExpression);
|
||||
const codeChunks = chunks
|
||||
.filter((c) => c.type === 'code')
|
||||
.map((c) => c.text.replace(/("|').*?("|')/, '').trim());
|
||||
if ((!codeChunks.some(hasExpressionExtension) || hasNativeMethod(bracketedExpression)) &&
|
||||
!forceExtend) {
|
||||
return bracketedExpression;
|
||||
}
|
||||
// If we've seen this expression before grab it from the cache
|
||||
if (bracketedExpression in EXTENDED_SYNTAX_CACHE) {
|
||||
return EXTENDED_SYNTAX_CACHE[bracketedExpression];
|
||||
}
|
||||
const extendedChunks = chunks.map((chunk) => {
|
||||
if (chunk.type === 'code') {
|
||||
let output = extendTransform(chunk.text);
|
||||
// esprima fails to parse bare objects (e.g. `{ data: something }`), we can
|
||||
// work around this by wrapping it in an parentheses
|
||||
if (!output?.code && chunk.text.trim()[0] === '{') {
|
||||
output = extendTransform(`(${chunk.text})`);
|
||||
}
|
||||
if (!output?.code) {
|
||||
throw new ExpressionExtensionError('invalid syntax');
|
||||
}
|
||||
let text = output.code;
|
||||
// We need to cut off any trailing semicolons. These cause issues
|
||||
// with certain types of expression and cause the whole expression
|
||||
// to fail.
|
||||
if (text.trim().endsWith(';')) {
|
||||
text = text.trim().slice(0, -1);
|
||||
}
|
||||
return {
|
||||
...chunk,
|
||||
text,
|
||||
};
|
||||
}
|
||||
return chunk;
|
||||
});
|
||||
const expression = joinExpression(extendedChunks);
|
||||
// Cache the expression so we don't have to do this transform again
|
||||
EXTENDED_SYNTAX_CACHE[bracketedExpression] = expression;
|
||||
return expression;
|
||||
}
|
||||
//# sourceMappingURL=expression-extension.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/expression-extension.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
14
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.d.ts
generated
vendored
Normal file
14
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.d.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface ExpressionText {
|
||||
type: 'text';
|
||||
text: string;
|
||||
}
|
||||
export interface ExpressionCode {
|
||||
type: 'code';
|
||||
text: string;
|
||||
hasClosingBrackets: boolean;
|
||||
}
|
||||
export type ExpressionChunk = ExpressionCode | ExpressionText;
|
||||
export declare const escapeCode: (text: string) => string;
|
||||
export declare const splitExpression: (expression: string) => ExpressionChunk[];
|
||||
export declare const joinExpression: (parts: ExpressionChunk[]) => string;
|
||||
//# sourceMappingURL=expression-parser.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"expression-parser.d.ts","sourceRoot":"","sources":["../../../src/extensions/expression-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IAIb,kBAAkB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,cAAc,CAAC;AAK9D,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,MAEzC,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,YAAY,MAAM,KAAG,eAAe,EA4DnE,CAAC;AAOF,eAAO,MAAM,cAAc,GAAI,OAAO,eAAe,EAAE,KAAG,MASzD,CAAC"}
|
||||
78
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.js
generated
vendored
Normal file
78
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.js
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
const OPEN_BRACKET = /(?<escape>\\|)(?<brackets>\{\{)/;
|
||||
const CLOSE_BRACKET = /(?<escape>\\|)(?<brackets>\}\})/;
|
||||
export const escapeCode = (text) => {
|
||||
return text.replace('\\}}', '}}');
|
||||
};
|
||||
export const splitExpression = (expression) => {
|
||||
const chunks = [];
|
||||
let searchingFor = 'open';
|
||||
let activeRegex = OPEN_BRACKET;
|
||||
let buffer = '';
|
||||
let index = 0;
|
||||
while (index < expression.length) {
|
||||
const expr = expression.slice(index);
|
||||
const res = activeRegex.exec(expr);
|
||||
// No more brackets. If it's a closing bracket
|
||||
// this is sort of valid so we accept it but mark
|
||||
// that it has no closing bracket.
|
||||
if (!res?.groups) {
|
||||
buffer += expr;
|
||||
if (searchingFor === 'open') {
|
||||
chunks.push({
|
||||
type: 'text',
|
||||
text: buffer,
|
||||
});
|
||||
}
|
||||
else {
|
||||
chunks.push({
|
||||
type: 'code',
|
||||
text: escapeCode(buffer),
|
||||
hasClosingBrackets: false,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (res.groups.escape) {
|
||||
buffer += expr.slice(0, res.index + 3);
|
||||
index += res.index + 3;
|
||||
}
|
||||
else {
|
||||
buffer += expr.slice(0, res.index);
|
||||
if (searchingFor === 'open') {
|
||||
chunks.push({
|
||||
type: 'text',
|
||||
text: buffer,
|
||||
});
|
||||
searchingFor = 'close';
|
||||
activeRegex = CLOSE_BRACKET;
|
||||
}
|
||||
else {
|
||||
chunks.push({
|
||||
type: 'code',
|
||||
text: escapeCode(buffer),
|
||||
hasClosingBrackets: true,
|
||||
});
|
||||
searchingFor = 'open';
|
||||
activeRegex = OPEN_BRACKET;
|
||||
}
|
||||
index += res.index + 2;
|
||||
buffer = '';
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
};
|
||||
// Expressions only have closing brackets escaped
|
||||
const escapeTmplExpression = (part) => {
|
||||
return part.replace('}}', '\\}}');
|
||||
};
|
||||
export const joinExpression = (parts) => {
|
||||
return parts
|
||||
.map((chunk) => {
|
||||
if (chunk.type === 'code') {
|
||||
return `{{${escapeTmplExpression(chunk.text)}${chunk.hasClosingBrackets ? '}}' : ''}`;
|
||||
}
|
||||
return chunk.text;
|
||||
})
|
||||
.join('');
|
||||
};
|
||||
//# sourceMappingURL=expression-parser.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/expression-parser.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"expression-parser.js","sourceRoot":"","sources":["../../../src/extensions/expression-parser.ts"],"names":[],"mappings":"AAgBA,MAAM,YAAY,GAAG,iCAAiC,CAAC;AACvD,MAAM,aAAa,GAAG,iCAAiC,CAAC;AAExD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE;IAClD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAAkB,EAAqB,EAAE;IACxE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,IAAI,YAAY,GAAqB,MAAM,CAAC;IAC5C,IAAI,WAAW,GAAG,YAAY,CAAC;IAE/B,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,8CAA8C;QAC9C,iDAAiD;QACjD,kCAAkC;QAClC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,IAAI,CAAC;YACf,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,MAAM;iBACZ,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;oBACxB,kBAAkB,EAAE,KAAK;iBACzB,CAAC,CAAC;YACJ,CAAC;YACD,MAAM;QACP,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACvC,KAAK,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;YAEnC,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;gBAC7B,MAAM,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,MAAM;iBACZ,CAAC,CAAC;gBACH,YAAY,GAAG,OAAO,CAAC;gBACvB,WAAW,GAAG,aAAa,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;oBACxB,kBAAkB,EAAE,IAAI;iBACxB,CAAC,CAAC;gBACH,YAAY,GAAG,MAAM,CAAC;gBACtB,WAAW,GAAG,YAAY,CAAC;YAC5B,CAAC;YAED,KAAK,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;YACvB,MAAM,GAAG,EAAE,CAAC;QACb,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AAEF,iDAAiD;AACjD,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAE,EAAE;IAC7C,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAwB,EAAU,EAAE;IAClE,OAAO,KAAK;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACd,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,OAAO,KAAK,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACvF,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC;IACnB,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACZ,CAAC,CAAC"}
|
||||
28
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.d.ts
generated
vendored
Normal file
28
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
declare function ifEmpty<T, V>(value: V, defaultValue: T): T | (V & {});
|
||||
declare namespace ifEmpty {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
returnType: string;
|
||||
args: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
docURL: string;
|
||||
};
|
||||
}
|
||||
export declare const extendedFunctions: {
|
||||
min: (...values: number[]) => number;
|
||||
max: (...values: number[]) => number;
|
||||
not: (value: unknown) => boolean;
|
||||
average: (...args: number[]) => number;
|
||||
numberList: (start: number, end: number) => number[];
|
||||
zip: (keys: unknown[], values: unknown[]) => unknown;
|
||||
$min: (...values: number[]) => number;
|
||||
$max: (...values: number[]) => number;
|
||||
$average: (...args: number[]) => number;
|
||||
$not: (value: unknown) => boolean;
|
||||
$ifEmpty: typeof ifEmpty;
|
||||
};
|
||||
export {};
|
||||
//# sourceMappingURL=extended-functions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"extended-functions.d.ts","sourceRoot":"","sources":["../../../src/extensions/extended-functions.ts"],"names":[],"mappings":"AA0CA,iBAAS,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,gBAgB/C;kBAhBQ,OAAO;;;;;;;;;;;;AA8BhB,eAAO,MAAM,iBAAiB;;;iBAlCV,OAAO,KAAG,OAAO;uBAJX,MAAM,EAAE;wBA3BP,MAAM,OAAO,MAAM,KAAG,MAAM,EAAE;gBAgBtC,OAAO,EAAE,UAAU,OAAO,EAAE,KAAG,OAAO;;;wBAW/B,MAAM,EAAE;kBAId,OAAO,KAAG,OAAO;;CA8CpC,CAAC"}
|
||||
76
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.js
generated
vendored
Normal file
76
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import { average as aAverage } from './array-extensions';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
import { ExpressionError } from '../errors/expression.error';
|
||||
const min = Math.min;
|
||||
const max = Math.max;
|
||||
const numberList = (start, end) => {
|
||||
const size = Math.abs(start - end) + 1;
|
||||
const arr = new Array(size);
|
||||
let curr = start;
|
||||
for (let i = 0; i < size; i++) {
|
||||
if (start < end) {
|
||||
arr[i] = curr++;
|
||||
}
|
||||
else {
|
||||
arr[i] = curr--;
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
const zip = (keys, values) => {
|
||||
if (keys.length !== values.length) {
|
||||
throw new ExpressionExtensionError('keys and values not of equal length');
|
||||
}
|
||||
return keys.reduce((p, c, i) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
||||
p[c] = values[i];
|
||||
return p;
|
||||
}, {});
|
||||
};
|
||||
const average = (...args) => {
|
||||
return aAverage(args);
|
||||
};
|
||||
const not = (value) => {
|
||||
return !value;
|
||||
};
|
||||
function ifEmpty(value, defaultValue) {
|
||||
if (arguments.length !== 2) {
|
||||
throw new ExpressionError('expected two arguments (value, defaultValue) for this function');
|
||||
}
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return defaultValue;
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
if (Array.isArray(value) && !value.length) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (!Object.keys(value).length) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
ifEmpty.doc = {
|
||||
name: 'ifEmpty',
|
||||
description: 'Returns the default value if the value is empty. Empty values are undefined, null, empty strings, arrays without elements and objects without keys.',
|
||||
returnType: 'any',
|
||||
args: [
|
||||
{ name: 'value', type: 'any' },
|
||||
{ name: 'defaultValue', type: 'any' },
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/convenience',
|
||||
};
|
||||
export const extendedFunctions = {
|
||||
min,
|
||||
max,
|
||||
not,
|
||||
average,
|
||||
numberList,
|
||||
zip,
|
||||
$min: min,
|
||||
$max: max,
|
||||
$average: average,
|
||||
$not: not,
|
||||
$ifEmpty: ifEmpty,
|
||||
};
|
||||
//# sourceMappingURL=extended-functions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/extended-functions.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"extended-functions.js","sourceRoot":"","sources":["../../../src/extensions/extended-functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;AACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;AAErB,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,GAAW,EAAY,EAAE;IAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,IAAI,CAAC,CAAC;IAEpC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YACjB,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC;QACjB,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC;QACjB,CAAC;IACF,CAAC;IAED,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,IAAe,EAAE,MAAiB,EAAW,EAAE;IAC3D,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,IAAI,wBAAwB,CAAC,qCAAqC,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;QAC9B,0GAA0G;QACzG,CAAS,CAAC,CAAQ,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACjC,OAAO,CAAC,CAAC;IACV,CAAC,EAAE,EAAE,CAAC,CAAC;AACR,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,CAAC,GAAG,IAAc,EAAE,EAAE;IACrC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,KAAc,EAAW,EAAE;IACvC,OAAO,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,SAAS,OAAO,CAAO,KAAQ,EAAE,YAAe;IAC/C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,eAAe,CAAC,gEAAgE,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QAC3D,OAAO,YAAY,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,OAAO,YAAY,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YAChC,OAAO,YAAY,CAAC;QACrB,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,OAAO,CAAC,GAAG,GAAG;IACb,IAAI,EAAE,SAAS;IACf,WAAW,EACV,qJAAqJ;IACtJ,UAAU,EAAE,KAAK;IACjB,IAAI,EAAE;QACL,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE;QAC9B,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE;KACrC;IACD,MAAM,EAAE,8CAA8C;CACtD,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,GAAG;IACH,GAAG;IACH,GAAG;IACH,OAAO;IACP,UAAU;IACV,GAAG;IACH,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,QAAQ,EAAE,OAAO;IACjB,IAAI,EAAE,GAAG;IACT,QAAQ,EAAE,OAAO;CACjB,CAAC"}
|
||||
42
node_modules/n8n-workflow/dist/esm/extensions/extensions.d.ts
generated
vendored
Normal file
42
node_modules/n8n-workflow/dist/esm/extensions/extensions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
export interface ExtensionMap {
|
||||
typeName: string;
|
||||
functions: Record<string, Extension>;
|
||||
}
|
||||
export type Extension = Function & {
|
||||
doc?: DocMetadata;
|
||||
};
|
||||
export type NativeDoc = {
|
||||
typeName: string;
|
||||
properties?: Record<string, {
|
||||
doc?: DocMetadata;
|
||||
}>;
|
||||
functions: Record<string, {
|
||||
doc?: DocMetadata;
|
||||
}>;
|
||||
};
|
||||
export type DocMetadataArgument = {
|
||||
name: string;
|
||||
type?: string;
|
||||
optional?: boolean;
|
||||
variadic?: boolean;
|
||||
description?: string;
|
||||
default?: string;
|
||||
args?: DocMetadataArgument[];
|
||||
};
|
||||
export type DocMetadataExample = {
|
||||
example: string;
|
||||
evaluated?: string;
|
||||
description?: string;
|
||||
};
|
||||
export type DocMetadata = {
|
||||
name: string;
|
||||
returnType: string;
|
||||
description?: string;
|
||||
section?: string;
|
||||
hidden?: boolean;
|
||||
aliases?: string[];
|
||||
args?: DocMetadataArgument[];
|
||||
examples?: DocMetadataExample[];
|
||||
docURL?: string;
|
||||
};
|
||||
//# sourceMappingURL=extensions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/extensions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/extensions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../src/extensions/extensions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACrC;AAGD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IAAE,GAAG,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAEzD,MAAM,MAAM,SAAS,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACnD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,IAAI,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7B,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC"}
|
||||
2
node_modules/n8n-workflow/dist/esm/extensions/extensions.js
generated
vendored
Normal file
2
node_modules/n8n-workflow/dist/esm/extensions/extensions.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=extensions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/extensions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/extensions.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../src/extensions/extensions.ts"],"names":[],"mappings":""}
|
||||
3
node_modules/n8n-workflow/dist/esm/extensions/index.d.ts
generated
vendored
Normal file
3
node_modules/n8n-workflow/dist/esm/extensions/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export { extend, extendOptional, hasExpressionExtension, hasNativeMethod, extendTransform, EXTENSION_OBJECTS as ExpressionExtensions, } from './expression-extension';
|
||||
export type { DocMetadata, NativeDoc, Extension, DocMetadataArgument, DocMetadataExample, } from './extensions';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/index.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/index.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,MAAM,EACN,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,iBAAiB,IAAI,oBAAoB,GACzC,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EACX,WAAW,EACX,SAAS,EACT,SAAS,EACT,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,cAAc,CAAC"}
|
||||
2
node_modules/n8n-workflow/dist/esm/extensions/index.js
generated
vendored
Normal file
2
node_modules/n8n-workflow/dist/esm/extensions/index.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export { extend, extendOptional, hasExpressionExtension, hasNativeMethod, extendTransform, EXTENSION_OBJECTS as ExpressionExtensions, } from './expression-extension';
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/index.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/index.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,MAAM,EACN,cAAc,EACd,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,iBAAiB,IAAI,oBAAoB,GACzC,MAAM,wBAAwB,CAAC"}
|
||||
27
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.d.ts
generated
vendored
Normal file
27
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { DateTime } from 'luxon';
|
||||
import type { ExtensionMap } from './extensions';
|
||||
type DateTimeFormat = 'ms' | 's' | 'us' | 'excel';
|
||||
export declare function toDateTime(value: number, extraArgs: [DateTimeFormat]): DateTime;
|
||||
export declare namespace toDateTime {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
examples: {
|
||||
example: string;
|
||||
evaluated: string;
|
||||
}[];
|
||||
section: string;
|
||||
returnType: string;
|
||||
args: {
|
||||
name: string;
|
||||
optional: boolean;
|
||||
description: string;
|
||||
default: string;
|
||||
type: string;
|
||||
}[];
|
||||
docURL: string;
|
||||
};
|
||||
}
|
||||
export declare const numberExtensions: ExtensionMap;
|
||||
export {};
|
||||
//# sourceMappingURL=number-extensions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"number-extensions.d.ts","sourceRoot":"","sources":["../../../src/extensions/number-extensions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA2DjD,KAAK,cAAc,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,OAAO,CAAC;AAClD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,cAAc,CAAC,YA4BpE;yBA5Be,UAAU;;;;;;;;;;;;;;;;;;;;AA4L1B,eAAO,MAAM,gBAAgB,EAAE,YAgB9B,CAAC"}
|
||||
222
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.js
generated
vendored
Normal file
222
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.js
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
// @vitest-environment jsdom
|
||||
import { DateTime } from 'luxon';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
function format(value, extraArgs) {
|
||||
const [locales = 'en-US', config = {}] = extraArgs;
|
||||
return new Intl.NumberFormat(locales, config).format(value);
|
||||
}
|
||||
function isEven(value) {
|
||||
if (!Number.isInteger(value)) {
|
||||
throw new ExpressionExtensionError('isEven() is only callable on integers');
|
||||
}
|
||||
return value % 2 === 0;
|
||||
}
|
||||
function isOdd(value) {
|
||||
if (!Number.isInteger(value)) {
|
||||
throw new ExpressionExtensionError('isOdd() is only callable on integers');
|
||||
}
|
||||
return Math.abs(value) % 2 === 1;
|
||||
}
|
||||
function floor(value) {
|
||||
return Math.floor(value);
|
||||
}
|
||||
function ceil(value) {
|
||||
return Math.ceil(value);
|
||||
}
|
||||
function abs(value) {
|
||||
return Math.abs(value);
|
||||
}
|
||||
function isInteger(value) {
|
||||
return Number.isInteger(value);
|
||||
}
|
||||
function round(value, extraArgs) {
|
||||
const [decimalPlaces = 0] = extraArgs;
|
||||
return +value.toFixed(decimalPlaces);
|
||||
}
|
||||
function toBoolean(value) {
|
||||
return value !== 0;
|
||||
}
|
||||
function toInt(value) {
|
||||
return round(value, []);
|
||||
}
|
||||
function toFloat(value) {
|
||||
return value;
|
||||
}
|
||||
export function toDateTime(value, extraArgs) {
|
||||
const [valueFormat = 'ms'] = extraArgs;
|
||||
if (!['ms', 's', 'us', 'excel'].includes(valueFormat)) {
|
||||
throw new ExpressionExtensionError(`Unsupported format '${String(valueFormat)}'. toDateTime() supports 'ms', 's', 'us' and 'excel'.`);
|
||||
}
|
||||
switch (valueFormat) {
|
||||
// Excel format is days since 1900
|
||||
// There is a bug where 1900 is incorrectly treated as a leap year
|
||||
case 'excel': {
|
||||
const DAYS_BETWEEN_1900_1970 = 25567;
|
||||
const DAYS_LEAP_YEAR_BUG_ADJUST = 2;
|
||||
const SECONDS_IN_DAY = 86_400;
|
||||
return DateTime.fromSeconds((value - (DAYS_BETWEEN_1900_1970 + DAYS_LEAP_YEAR_BUG_ADJUST)) * SECONDS_IN_DAY);
|
||||
}
|
||||
case 's':
|
||||
return DateTime.fromSeconds(value);
|
||||
case 'us':
|
||||
return DateTime.fromMillis(value / 1000);
|
||||
case 'ms':
|
||||
default:
|
||||
return DateTime.fromMillis(value);
|
||||
}
|
||||
}
|
||||
ceil.doc = {
|
||||
name: 'ceil',
|
||||
description: 'Rounds the number up to the next whole number',
|
||||
examples: [{ example: '(1.234).ceil()', evaluated: '2' }],
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-ceil',
|
||||
};
|
||||
floor.doc = {
|
||||
name: 'floor',
|
||||
description: 'Rounds the number down to the nearest whole number',
|
||||
examples: [{ example: '(1.234).floor()', evaluated: '1' }],
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-floor',
|
||||
};
|
||||
isEven.doc = {
|
||||
name: 'isEven',
|
||||
description: "Returns <code>true</code> if the number is even or <code>false</code> if not. Throws an error if the number isn't a whole number.",
|
||||
examples: [
|
||||
{ example: '(33).isEven()', evaluated: 'false' },
|
||||
{ example: '(42).isEven()', evaluated: 'true' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-isEven',
|
||||
};
|
||||
isOdd.doc = {
|
||||
name: 'isOdd',
|
||||
description: "Returns <code>true</code> if the number is odd or <code>false</code> if not. Throws an error if the number isn't a whole number.",
|
||||
examples: [
|
||||
{ example: '(33).isOdd()', evaluated: 'true' },
|
||||
{ example: '(42).isOdd()', evaluated: 'false' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-isOdd',
|
||||
};
|
||||
format.doc = {
|
||||
name: 'format',
|
||||
description: 'Returns a formatted string representing the number. Useful for formatting for a specific language or currency. The same as <a target="_blank" href=”https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat”><code>Intl.NumberFormat()</code></a>.',
|
||||
examples: [
|
||||
{ example: "(123456.789).format('de-DE')", evaluated: '123.456,789' },
|
||||
{
|
||||
example: "(123456.789).format('de-DE', {'style': 'currency', 'currency': 'EUR'})",
|
||||
evaluated: '123.456,79 €',
|
||||
},
|
||||
],
|
||||
returnType: 'string',
|
||||
args: [
|
||||
{
|
||||
name: 'locale',
|
||||
optional: true,
|
||||
description: 'A <a target="_blank" href=”https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument”>locale tag</a> for formatting the number, e.g. <code>fr-FR</code>, <code>en-GB</code>, <code>pr-BR</code>',
|
||||
default: '"en-US"',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
name: 'options',
|
||||
optional: true,
|
||||
description: 'Configuration options for number formatting. <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat" target="_blank">More info</a>',
|
||||
type: 'object',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-format',
|
||||
};
|
||||
round.doc = {
|
||||
name: 'round',
|
||||
description: 'Rounds the number to the nearest integer (or decimal place)',
|
||||
examples: [
|
||||
{ example: '(1.256).round()', evaluated: '1' },
|
||||
{ example: '(1.256).round(1)', evaluated: '1.3' },
|
||||
{ example: '(1.256).round(2)', evaluated: '1.26' },
|
||||
],
|
||||
returnType: 'number',
|
||||
args: [
|
||||
{
|
||||
name: 'decimalPlaces',
|
||||
optional: true,
|
||||
description: 'The number of decimal places to round to',
|
||||
default: '0',
|
||||
type: 'number',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-round',
|
||||
};
|
||||
toBoolean.doc = {
|
||||
name: 'toBoolean',
|
||||
description: 'Returns <code>false</code> for <code>0</code> and <code>true</code> for any other number (including negative numbers).',
|
||||
examples: [
|
||||
{ example: '(12).toBoolean()', evaluated: 'true' },
|
||||
{ example: '(0).toBoolean()', evaluated: 'false' },
|
||||
{ example: '(-1.3).toBoolean()', evaluated: 'true' },
|
||||
],
|
||||
section: 'cast',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-toBoolean',
|
||||
};
|
||||
toDateTime.doc = {
|
||||
name: 'toDateTime',
|
||||
description: 'Converts a numerical timestamp into a <a target="_blank" href="https://moment.github.io/luxon/api-docs/">Luxon</a> DateTime. The format of the timestamp must be specified if it\'s not in milliseconds. Uses the timezone specified in workflow settings if available; otherwise, it defaults to the timezone set for the instance.',
|
||||
examples: [
|
||||
{ example: "(1708695471).toDateTime('s')", evaluated: '2024-02-23T14:37:51.000+01:00' },
|
||||
{ example: "(1708695471000).toDateTime('ms')", evaluated: '2024-02-23T14:37:51.000+01:00' },
|
||||
{ example: "(1708695471000000).toDateTime('us')", evaluated: '2024-02-23T14:37:51.000+01:00' },
|
||||
{ example: "(45345).toDateTime('excel')", evaluated: '2024-02-23T01:00:00.000+01:00' },
|
||||
],
|
||||
section: 'cast',
|
||||
returnType: 'DateTime',
|
||||
args: [
|
||||
{
|
||||
name: 'format',
|
||||
optional: true,
|
||||
description: 'The type of timestamp to convert. Options are <code>ms</code> (for Unix timestamp in milliseconds), <code>s</code> (for Unix timestamp in seconds), <code>us</code> (for Unix timestamp in microseconds) or <code>excel</code> (for days since 1900).',
|
||||
default: '"ms"',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-toDateTime',
|
||||
};
|
||||
abs.doc = {
|
||||
name: 'abs',
|
||||
description: "Returns the number's absolute value, i.e. removes any minus sign",
|
||||
examples: [
|
||||
{ example: '(-1.7).abs()', evaluated: '1.7' },
|
||||
{ example: '(1.7).abs()', evaluated: '1.7' },
|
||||
],
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-abs',
|
||||
};
|
||||
isInteger.doc = {
|
||||
name: 'isInteger',
|
||||
description: 'Returns <code>true</code> if the number is a whole number',
|
||||
examples: [
|
||||
{ example: '(4).isInteger()', evaluated: 'true' },
|
||||
{ example: '(4.12).isInteger()', evaluated: 'false' },
|
||||
{ example: '(-4).isInteger()', evaluated: 'true' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/numbers/#number-isInteger',
|
||||
};
|
||||
export const numberExtensions = {
|
||||
typeName: 'Number',
|
||||
functions: {
|
||||
ceil,
|
||||
floor,
|
||||
format,
|
||||
round,
|
||||
abs,
|
||||
isInteger,
|
||||
isEven,
|
||||
isOdd,
|
||||
toBoolean,
|
||||
toInt,
|
||||
toFloat,
|
||||
toDateTime,
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=number-extensions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/number-extensions.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
46
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.d.ts
generated
vendored
Normal file
46
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import type { ExtensionMap } from './extensions';
|
||||
export declare function compact(value: object): object;
|
||||
export declare namespace compact {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
examples: {
|
||||
example: string;
|
||||
evaluated: string;
|
||||
}[];
|
||||
returnType: string;
|
||||
docURL: string;
|
||||
};
|
||||
}
|
||||
export declare function urlEncode(value: object): string;
|
||||
export declare namespace urlEncode {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
examples: {
|
||||
example: string;
|
||||
evaluated: string;
|
||||
}[];
|
||||
returnType: string;
|
||||
docURL: string;
|
||||
};
|
||||
}
|
||||
export declare function toJsonString(value: object): string;
|
||||
export declare namespace toJsonString {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
examples: {
|
||||
example: string;
|
||||
evaluated: string;
|
||||
}[];
|
||||
docURL: string;
|
||||
returnType: string;
|
||||
};
|
||||
}
|
||||
export declare function toInt(): undefined;
|
||||
export declare function toFloat(): undefined;
|
||||
export declare function toBoolean(): undefined;
|
||||
export declare function toDateTime(): undefined;
|
||||
export declare const objectExtensions: ExtensionMap;
|
||||
//# sourceMappingURL=object-extensions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"object-extensions.d.ts","sourceRoot":"","sources":["../../../src/extensions/object-extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAmEjD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB7C;yBAjBe,OAAO;;;;;;;;;;;;AAmBvB,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,UAEtC;yBAFe,SAAS;;;;;;;;;;;;AAIzB,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,UAEzC;yBAFe,YAAY;;;;;;;;;;;;AAI5B,wBAAgB,KAAK,cAEpB;AAED,wBAAgB,OAAO,cAEtB;AAED,wBAAgB,SAAS,cAExB;AAED,wBAAgB,UAAU,cAEzB;AA8LD,eAAO,MAAM,gBAAgB,EAAE,YAmB9B,CAAC"}
|
||||
276
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.js
generated
vendored
Normal file
276
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.js
generated
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
function isEmpty(value) {
|
||||
return Object.keys(value).length === 0;
|
||||
}
|
||||
function isNotEmpty(value) {
|
||||
return !isEmpty(value);
|
||||
}
|
||||
function keys(value) {
|
||||
return Object.keys(value);
|
||||
}
|
||||
function values(value) {
|
||||
return Object.values(value);
|
||||
}
|
||||
function hasField(value, extraArgs) {
|
||||
const [name] = extraArgs;
|
||||
return name in value;
|
||||
}
|
||||
function removeField(value, extraArgs) {
|
||||
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[name];
|
||||
return newObject;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function removeFieldsContaining(value, extraArgs) {
|
||||
const [match] = extraArgs;
|
||||
if (typeof match !== 'string' || match === '') {
|
||||
throw new ExpressionExtensionError('removeFieldsContaining(): expected non-empty string arg');
|
||||
}
|
||||
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[key];
|
||||
}
|
||||
}
|
||||
return newObject;
|
||||
}
|
||||
function keepFieldsContaining(value, extraArgs) {
|
||||
const [match] = extraArgs;
|
||||
if (typeof match !== 'string' || match === '') {
|
||||
throw new ExpressionExtensionError('argument of keepFieldsContaining must be a non-empty string');
|
||||
}
|
||||
const newObject = { ...value };
|
||||
for (const [key, val] of Object.entries(value)) {
|
||||
if (typeof val !== 'string' || (typeof val === 'string' && !val.includes(match))) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
||||
delete newObject[key];
|
||||
}
|
||||
}
|
||||
return newObject;
|
||||
}
|
||||
export function compact(value) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const newObj = {};
|
||||
for (const [key, val] of Object.entries(value)) {
|
||||
if (val !== null && val !== undefined && val !== 'nil' && val !== '') {
|
||||
if (typeof val === 'object') {
|
||||
if (Object.keys(val).length === 0)
|
||||
continue;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
|
||||
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) {
|
||||
return new URLSearchParams(value).toString();
|
||||
}
|
||||
export function toJsonString(value) {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
export function toInt() {
|
||||
return undefined;
|
||||
}
|
||||
export function toFloat() {
|
||||
return undefined;
|
||||
}
|
||||
export function toBoolean() {
|
||||
return undefined;
|
||||
}
|
||||
export function toDateTime() {
|
||||
return undefined;
|
||||
}
|
||||
isEmpty.doc = {
|
||||
name: 'isEmpty',
|
||||
description: 'Returns <code>true</code> if the Object has no keys (fields) set or is <code>null</code>',
|
||||
examples: [
|
||||
{ example: "({'name': 'Nathan'}).isEmpty()", evaluated: 'false' },
|
||||
{ example: '({}).isEmpty()', evaluated: 'true' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-isEmpty',
|
||||
};
|
||||
isNotEmpty.doc = {
|
||||
name: 'isNotEmpty',
|
||||
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' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-isNotEmpty',
|
||||
};
|
||||
compact.doc = {
|
||||
name: 'compact',
|
||||
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',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-compact',
|
||||
};
|
||||
urlEncode.doc = {
|
||||
name: 'urlEncode',
|
||||
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'",
|
||||
},
|
||||
],
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-urlEncode',
|
||||
};
|
||||
hasField.doc = {
|
||||
name: 'hasField',
|
||||
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' },
|
||||
],
|
||||
returnType: 'boolean',
|
||||
args: [
|
||||
{
|
||||
name: 'name',
|
||||
optional: false,
|
||||
description: 'The name of the key to search for',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-hasField',
|
||||
};
|
||||
removeField.doc = {
|
||||
name: 'removeField',
|
||||
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',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-removeField',
|
||||
};
|
||||
removeFieldsContaining.doc = {
|
||||
name: 'removeFieldsContaining',
|
||||
description: "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',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-removeFieldsContaining',
|
||||
};
|
||||
keepFieldsContaining.doc = {
|
||||
name: 'keepFieldsContaining',
|
||||
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',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-keepFieldsContaining',
|
||||
};
|
||||
keys.doc = {
|
||||
name: 'keys',
|
||||
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']" }],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-keys',
|
||||
returnType: 'Array',
|
||||
};
|
||||
values.doc = {
|
||||
name: 'values',
|
||||
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]" },
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-values',
|
||||
returnType: 'Array',
|
||||
};
|
||||
toJsonString.doc = {
|
||||
name: 'toJsonString',
|
||||
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}\'',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/objects/#object-toJsonString',
|
||||
returnType: 'string',
|
||||
};
|
||||
export const objectExtensions = {
|
||||
typeName: 'Object',
|
||||
functions: {
|
||||
isEmpty,
|
||||
isNotEmpty,
|
||||
hasField,
|
||||
removeField,
|
||||
removeFieldsContaining,
|
||||
keepFieldsContaining,
|
||||
compact,
|
||||
urlEncode,
|
||||
keys,
|
||||
values,
|
||||
toJsonString,
|
||||
toInt,
|
||||
toFloat,
|
||||
toBoolean,
|
||||
toDateTime,
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=object-extensions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/object-extensions.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
38
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.d.ts
generated
vendored
Normal file
38
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { DateTime } from 'luxon';
|
||||
import type { ExtensionMap } from './extensions';
|
||||
export declare const SupportedHashAlgorithms: readonly ["md5", "sha1", "sha224", "sha256", "sha384", "sha512", "sha3"];
|
||||
export declare function toJsonString(value: string): string;
|
||||
export declare namespace toJsonString {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
section: string;
|
||||
returnType: string;
|
||||
docURL: string;
|
||||
examples: {
|
||||
example: string;
|
||||
evaluated: string;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
export declare function toDateTime(value: string, extraArgs?: [string]): DateTime;
|
||||
export declare namespace toDateTime {
|
||||
var doc: {
|
||||
name: string;
|
||||
description: string;
|
||||
section: string;
|
||||
returnType: string;
|
||||
docURL: string;
|
||||
examples: {
|
||||
example: string;
|
||||
}[];
|
||||
args: {
|
||||
name: string;
|
||||
optional: boolean;
|
||||
description: string;
|
||||
type: string;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
export declare const stringExtensions: ExtensionMap;
|
||||
//# sourceMappingURL=string-extensions.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"string-extensions.d.ts","sourceRoot":"","sources":["../../../src/extensions/string-extensions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAKjC,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,cAAc,CAAC;AAK5D,eAAO,MAAM,uBAAuB,0EAQ1B,CAAC;AA6IX,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;yBAFe,YAAY;;;;;;;;;;;;;AA+D5B,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,CAAC,MAAM,CAAQ,GAAG,QAAQ,CAoB9E;yBApBe,UAAU;;;;;;;;;;;;;;;;;;AAwoB1B,eAAO,MAAM,gBAAgB,EAAE,YAqC9B,CAAC"}
|
||||
770
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.js
generated
vendored
Normal file
770
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.js
generated
vendored
Normal file
@@ -0,0 +1,770 @@
|
||||
import { toBase64, fromBase64 } from 'js-base64';
|
||||
import SHA from 'jssha';
|
||||
import { DateTime } from 'luxon';
|
||||
import MD5 from 'md5';
|
||||
import { titleCase } from 'title-case';
|
||||
import { transliterate } from 'transliteration';
|
||||
import { toDateTime as numberToDateTime } from './number-extensions';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
import { tryToParseDateTime } from '../type-validation';
|
||||
export const SupportedHashAlgorithms = [
|
||||
'md5',
|
||||
'sha1',
|
||||
'sha224',
|
||||
'sha256',
|
||||
'sha384',
|
||||
'sha512',
|
||||
'sha3',
|
||||
];
|
||||
// All symbols from https://www.xe.com/symbols/ as for 2022/11/09
|
||||
const CURRENCY_REGEXP = /(\u004c\u0065\u006b|\u060b|\u0024|\u0192|\u20bc|\u0042\u0072|\u0042\u005a\u0024|\u0024\u0062|\u004b\u004d|\u0050|\u043b\u0432|\u0052\u0024|\u17db|\u00a5|\u20a1|\u006b\u006e|\u20b1|\u004b\u010d|\u006b\u0072|\u0052\u0044\u0024|\u00a3|\u20ac|\u00a2|\u0051|\u004c|\u0046\u0074|\u20b9|\u0052\u0070|\ufdfc|\u20aa|\u004a\u0024|\u20a9|\u20ad|\u0434\u0435\u043d|\u0052\u004d|\u20a8|\u20ae|\u004d\u0054|\u0043\u0024|\u20a6|\u0042\u002f\u002e|\u0047\u0073|\u0053\u002f\u002e|\u007a\u0142|\u006c\u0065\u0069|\u20bd|\u0414\u0438\u043d\u002e|\u0053|\u0052|\u0043\u0048\u0046|\u004e\u0054\u0024|\u0e3f|\u0054\u0054\u0024|\u20ba|\u20b4|\u0024\u0055|\u0042\u0073|\u20ab|\u005a\u0024)/gu;
|
||||
/*
|
||||
Extract the domain part from various inputs, including URLs, email addresses, and plain domains.
|
||||
|
||||
/^(?:(?:https?|ftp):\/\/)? // Match optional http, https, or ftp protocols
|
||||
(?:mailto:)? // Match optional mailto:
|
||||
(?:\/\/)? // Match optional double slashes
|
||||
(?:www\.)? // Match optional www prefix
|
||||
(?:[-\w]*\.)? // Match any optional subdomain
|
||||
( // Capture the domain part
|
||||
(?:(?:[-\w]+\.)+ // Match one or more subdomains
|
||||
(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9]+) // Match top-level domain or Punycode encoded IDN(xn--80aswg.xn--p1ai)
|
||||
|localhost // Match localhost
|
||||
|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} // Match IPv4 addresses
|
||||
)
|
||||
)
|
||||
(?::\d+)? // Match optional port number
|
||||
(?:\/[^\s?]*)? // Match optional path
|
||||
(?:\?[^\s#]*)? // Match optional query string
|
||||
(?:#[^\s]*)?$/i; // Match optional hash fragment
|
||||
*/
|
||||
const DOMAIN_EXTRACT_REGEXP = /^(?:(?:https?|ftp):\/\/)?(?:mailto:)?(?:\/\/)?((?:www\.)?(?:(?:[-\w]+\.)+(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9]+)|localhost|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(?::\d+)?(?:\/[^\s?]*)?(?:\?[^\s#]*)?(?:#[^\s]*)?$/i;
|
||||
/*
|
||||
Matches domain names without the protocol or optional subdomains
|
||||
|
||||
/^(?:www\.)? // Match optional www prefix
|
||||
( // Capture the domain part
|
||||
(?:(?:[-\w]+\.)+ // Match one or more subdomains
|
||||
(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9]+) // Match top-level domain or Punycode encoded IDN
|
||||
|localhost // Match localhost
|
||||
|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} // Match IPv4 addresses
|
||||
)
|
||||
)
|
||||
(?::\d+)? // Match optional port number
|
||||
(?:\/[^\s?]*)? // Match optional path
|
||||
(?:\?[^\s#]*)? // Match optional query string
|
||||
(?:#[^\s]*)?$/i; // Match optional fragment at the end of the string
|
||||
*/
|
||||
const DOMAIN_REGEXP = /^(?:www\.)?((?:(?:[-\w]+\.)+(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9]+)|localhost|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(?::\d+)?(?:\/[^\s?]*)?(?:\?[^\s#]*)?(?:#[^\s]*)?$/i;
|
||||
/*
|
||||
Matches email addresses
|
||||
|
||||
/(
|
||||
( // Capture local part of the email address
|
||||
([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*) // One or more characters not in the set, followed by
|
||||
a period, followed by one or more characters not in the set
|
||||
|(".+") // Or one or more characters inside quotes
|
||||
)
|
||||
)
|
||||
@ // Match @ symbol
|
||||
(?<domain>( // Capture the domain part of the email address
|
||||
\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\] // Match IPv4 address inside brackets
|
||||
|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}) // Or match domain with at least two subdomains and TLD
|
||||
))/;
|
||||
*/
|
||||
const EMAIL_REGEXP = /(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@(?<domain>(\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;
|
||||
/*
|
||||
Matches URLs with strict beginning and end of the string checks
|
||||
|
||||
/^(?:(?:https?|ftp):\/\/) // Match http, https, or ftp protocols at the start of the string
|
||||
(?:www\.)? // Match optional www prefix
|
||||
( // Capture the domain part
|
||||
(?:(?:[-\w]+\.)+ // Match one or more subdomains
|
||||
(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9]+) // Match top-level domain or Punycode encoded IDN
|
||||
|localhost // Match localhost
|
||||
|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} // Match IPv4 addresses
|
||||
)
|
||||
)
|
||||
(?::\d+)? // Match optional port number
|
||||
(?:\/[^\s?#]*)? // Match optional path
|
||||
(?:\?[^\s#]*)? // Match optional query string
|
||||
(?=([^\s]+#.*)?) // Positive lookahead for the fragment identifier
|
||||
#?[^\s]*$/i; // Match optional fragment at the end of the string
|
||||
*/
|
||||
const URL_REGEXP_EXACT = /^(?:(?:https?|ftp):\/\/)(?:www\.)?((?:(?:[-\w]+\.)+(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9]+)|localhost|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(?::\d+)?(?:\/[^\s?#]*)?(?:\?[^\s#]*)?(?=([^\s]+#.*)?)#?[^\s]*$/i;
|
||||
/*
|
||||
Same as URL_REGEXP_EXACT but without the strict beginning and end of the string checks to allow for
|
||||
matching URLs in the middle of a string
|
||||
*/
|
||||
const URL_REGEXP = /(?:(?:https?|ftp):\/\/)(?:www\.)?((?:(?:[-\w]+\.)+(?:[a-zA-Z]{2,}|xn--[a-zA-Z0-9]+)|localhost|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(?::\d+)?(?:\/[^\s?#]*)?(?:\?[^\s#]*)?(?=([^\s]+#.*)?)#?[^\s]*/i;
|
||||
const CHAR_TEST_REGEXP = /\p{L}/u;
|
||||
const PUNC_TEST_REGEXP = /[!?.]/;
|
||||
function hash(value, extraArgs) {
|
||||
const algorithm = extraArgs[0]?.toLowerCase() ?? 'md5';
|
||||
switch (algorithm) {
|
||||
case 'base64':
|
||||
return toBase64(value);
|
||||
case 'md5':
|
||||
return MD5(value);
|
||||
case 'sha1':
|
||||
case 'sha224':
|
||||
case 'sha256':
|
||||
case 'sha384':
|
||||
case 'sha512':
|
||||
case 'sha3':
|
||||
const variant = {
|
||||
sha1: 'SHA-1',
|
||||
sha224: 'SHA-224',
|
||||
sha256: 'SHA-256',
|
||||
sha384: 'SHA-384',
|
||||
sha512: 'SHA-512',
|
||||
sha3: 'SHA3-512',
|
||||
}[algorithm];
|
||||
return new SHA(variant, 'TEXT').update(value).getHash('HEX');
|
||||
default:
|
||||
throw new ExpressionExtensionError(`Unknown algorithm ${algorithm}. Available algorithms are: ${SupportedHashAlgorithms.join()}, and Base64.`);
|
||||
}
|
||||
}
|
||||
function isEmpty(value) {
|
||||
return value === '';
|
||||
}
|
||||
function isNotEmpty(value) {
|
||||
return !isEmpty(value);
|
||||
}
|
||||
function length(value) {
|
||||
return value.length;
|
||||
}
|
||||
export function toJsonString(value) {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
function removeMarkdown(value) {
|
||||
let output = value;
|
||||
try {
|
||||
output = output.replace(/^([\s\t]*)([*\-+]|\d\.)\s+/gm, '$1');
|
||||
output = output
|
||||
// Header
|
||||
.replace(/\n={2,}/g, '\n')
|
||||
// Strikethrough
|
||||
.replace(/~~/g, '')
|
||||
// Fenced codeblocks
|
||||
.replace(/`{3}.*\n/g, '');
|
||||
output = output
|
||||
// Remove HTML tags
|
||||
.replace(/<[\w|\s|=|'|"|:|(|)|,|;|/|0-9|.|-]+[>|\\>]/g, '')
|
||||
// Remove setext-style headers
|
||||
.replace(/^[=-]{2,}\s*$/g, '')
|
||||
// Remove footnotes?
|
||||
.replace(/\[\^.+?\](: .*?$)?/g, '')
|
||||
.replace(/\s{0,2}\[.*?\]: .*?$/g, '')
|
||||
// Remove images
|
||||
.replace(/!\[.*?\][[(].*?[\])]/g, '')
|
||||
// Remove inline links
|
||||
.replace(/\[(.*?)\][[(].*?[\])]/g, '$1')
|
||||
// Remove Blockquotes
|
||||
.replace(/>/g, '')
|
||||
// Remove reference-style links?
|
||||
.replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '')
|
||||
// Remove atx-style headers
|
||||
.replace(/^#{1,6}\s*([^#]*)\s*(#{1,6})?/gm, '$1')
|
||||
.replace(/([*_]{1,3})(\S.*?\S)\1/g, '$2')
|
||||
.replace(/(`{3,})(.*?)\1/gm, '$2')
|
||||
.replace(/^-{3,}\s*$/g, '')
|
||||
.replace(/`(.+?)`/g, '$1')
|
||||
.replace(/\n{2,}/g, '\n\n');
|
||||
}
|
||||
catch (e) {
|
||||
return value;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
function removeTags(value) {
|
||||
return value.replace(/<[^>]*>?/gm, '');
|
||||
}
|
||||
function toDate(value) {
|
||||
const date = new Date(Date.parse(value));
|
||||
if (date.toString() === 'Invalid Date') {
|
||||
throw new ExpressionExtensionError('cannot convert to date');
|
||||
}
|
||||
// If time component is not specified, force 00:00h
|
||||
if (!/:/.test(value)) {
|
||||
date.setHours(0, 0, 0);
|
||||
}
|
||||
return date;
|
||||
}
|
||||
export function toDateTime(value, extraArgs = ['']) {
|
||||
try {
|
||||
const [valueFormat] = extraArgs;
|
||||
if (valueFormat) {
|
||||
if (valueFormat === 'ms' ||
|
||||
valueFormat === 's' ||
|
||||
valueFormat === 'us' ||
|
||||
valueFormat === 'excel') {
|
||||
return numberToDateTime(Number(value), [valueFormat]);
|
||||
}
|
||||
return DateTime.fromFormat(value, valueFormat);
|
||||
}
|
||||
return tryToParseDateTime(value);
|
||||
}
|
||||
catch (error) {
|
||||
throw new ExpressionExtensionError('cannot convert to Luxon DateTime');
|
||||
}
|
||||
}
|
||||
function urlDecode(value, extraArgs) {
|
||||
const [entireString = false] = extraArgs;
|
||||
if (entireString) {
|
||||
return decodeURI(value.toString());
|
||||
}
|
||||
return decodeURIComponent(value.toString());
|
||||
}
|
||||
function urlEncode(value, extraArgs) {
|
||||
const [entireString = false] = extraArgs;
|
||||
if (entireString) {
|
||||
return encodeURI(value.toString());
|
||||
}
|
||||
return encodeURIComponent(value.toString());
|
||||
}
|
||||
function toInt(value, extraArgs) {
|
||||
const [radix] = extraArgs;
|
||||
const int = parseInt(value.replace(CURRENCY_REGEXP, ''), radix);
|
||||
if (isNaN(int)) {
|
||||
throw new ExpressionExtensionError('cannot convert to integer');
|
||||
}
|
||||
return int;
|
||||
}
|
||||
function toFloat(value) {
|
||||
if (value.includes(',')) {
|
||||
throw new ExpressionExtensionError('cannot convert to float, expected . as decimal separator');
|
||||
}
|
||||
const float = parseFloat(value.replace(CURRENCY_REGEXP, ''));
|
||||
if (isNaN(float)) {
|
||||
throw new ExpressionExtensionError('cannot convert to float');
|
||||
}
|
||||
return float;
|
||||
}
|
||||
function toNumber(value) {
|
||||
const num = Number(value.replace(CURRENCY_REGEXP, ''));
|
||||
if (isNaN(num)) {
|
||||
throw new ExpressionExtensionError('cannot convert to number');
|
||||
}
|
||||
return num;
|
||||
}
|
||||
function quote(value, extraArgs) {
|
||||
const [quoteChar = '"'] = extraArgs;
|
||||
return `${quoteChar}${value
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(new RegExp(`\\${quoteChar}`, 'g'), `\\${quoteChar}`)}${quoteChar}`;
|
||||
}
|
||||
function isNumeric(value) {
|
||||
if (value.includes(' '))
|
||||
return false;
|
||||
return !isNaN(value) && !isNaN(parseFloat(value));
|
||||
}
|
||||
function isUrl(value) {
|
||||
return URL_REGEXP_EXACT.test(value);
|
||||
}
|
||||
function isDomain(value) {
|
||||
return DOMAIN_REGEXP.test(value);
|
||||
}
|
||||
function isEmail(value) {
|
||||
const result = EMAIL_REGEXP.test(value);
|
||||
// email regex is loose so check manually for now
|
||||
if (result && value.includes(' ')) {
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function toTitleCase(value) {
|
||||
return titleCase(value);
|
||||
}
|
||||
function replaceSpecialChars(value) {
|
||||
return transliterate(value, { unknown: '?' });
|
||||
}
|
||||
function toSentenceCase(value) {
|
||||
let current = value.slice();
|
||||
let buffer = '';
|
||||
while (CHAR_TEST_REGEXP.test(current)) {
|
||||
const charIndex = current.search(CHAR_TEST_REGEXP);
|
||||
current =
|
||||
current.slice(0, charIndex) +
|
||||
current[charIndex].toLocaleUpperCase() +
|
||||
current.slice(charIndex + 1).toLocaleLowerCase();
|
||||
const puncIndex = current.search(PUNC_TEST_REGEXP);
|
||||
if (puncIndex === -1) {
|
||||
buffer += current;
|
||||
current = '';
|
||||
break;
|
||||
}
|
||||
buffer += current.slice(0, puncIndex + 1);
|
||||
current = current.slice(puncIndex + 1);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
function toSnakeCase(value) {
|
||||
return value
|
||||
.toLocaleLowerCase()
|
||||
.replace(/[ \-]/g, '_')
|
||||
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,.\/:;<=>?@\[\]^`{|}~]/g, '');
|
||||
}
|
||||
function extractEmail(value) {
|
||||
const matched = EMAIL_REGEXP.exec(value);
|
||||
if (!matched) {
|
||||
return undefined;
|
||||
}
|
||||
return matched[0];
|
||||
}
|
||||
function extractDomain(value) {
|
||||
if (isEmail(value)) {
|
||||
const matched = EMAIL_REGEXP.exec(value);
|
||||
// This shouldn't happen
|
||||
if (!matched) {
|
||||
return undefined;
|
||||
}
|
||||
return matched.groups?.domain;
|
||||
}
|
||||
const domainMatch = value.match(DOMAIN_EXTRACT_REGEXP);
|
||||
if (domainMatch) {
|
||||
return domainMatch[1];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function extractUrl(value) {
|
||||
const matched = URL_REGEXP.exec(value);
|
||||
if (!matched) {
|
||||
return undefined;
|
||||
}
|
||||
return matched[0];
|
||||
}
|
||||
function extractUrlPath(value) {
|
||||
try {
|
||||
const url = new URL(value);
|
||||
return url.pathname;
|
||||
}
|
||||
catch (error) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
function parseJson(value) {
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
catch (error) {
|
||||
if (value.includes("'")) {
|
||||
throw new ExpressionExtensionError("Parsing failed. Check you're using double quotes");
|
||||
}
|
||||
throw new ExpressionExtensionError('Parsing failed');
|
||||
}
|
||||
}
|
||||
function toBoolean(value) {
|
||||
const normalized = value.toLowerCase();
|
||||
const FALSY = new Set(['false', 'no', '0']);
|
||||
return normalized.length > 0 && !FALSY.has(normalized);
|
||||
}
|
||||
function base64Encode(value) {
|
||||
return toBase64(value);
|
||||
}
|
||||
function base64Decode(value) {
|
||||
return fromBase64(value);
|
||||
}
|
||||
removeMarkdown.doc = {
|
||||
name: 'removeMarkdown',
|
||||
description: 'Removes any Markdown formatting from the string. Also removes HTML tags.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-removeMarkdown',
|
||||
examples: [{ example: '"*bold*, [link]()".removeMarkdown()', evaluated: '"bold, link"' }],
|
||||
};
|
||||
removeTags.doc = {
|
||||
name: 'removeTags',
|
||||
description: 'Removes tags, such as HTML or XML, from the string.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-removeTags',
|
||||
examples: [{ example: '"<b>bold</b>, <a>link</a>".removeTags()', evaluated: '"bold, link"' }],
|
||||
};
|
||||
toDate.doc = {
|
||||
name: 'toDate',
|
||||
description: 'Converts a string to a date.',
|
||||
section: 'cast',
|
||||
returnType: 'Date',
|
||||
hidden: true,
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toDate',
|
||||
};
|
||||
toDateTime.doc = {
|
||||
name: 'toDateTime',
|
||||
description: 'Converts the string to a <a target="_blank" href="https://moment.github.io/luxon/api-docs/">Luxon</a> DateTime. Useful for further transformation. Supported formats for the string are ISO 8601, HTTP, RFC2822, SQL and Unix timestamp in milliseconds. To parse other formats, use <a target="_blank" href=”https://moment.github.io/luxon/api-docs/index.html#datetimefromformat”> <code>DateTime.fromFormat()</code></a>.',
|
||||
section: 'cast',
|
||||
returnType: 'DateTime',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toDateTime',
|
||||
examples: [
|
||||
{ example: '"2024-03-29T18:06:31.798+01:00".toDateTime()' },
|
||||
{ example: '"Fri, 29 Mar 2024 18:08:01 +0100".toDateTime()' },
|
||||
{ example: '"20240329".toDateTime()' },
|
||||
{ example: '"1711732132990".toDateTime("ms")' },
|
||||
{ example: '"31-01-2024".toDateTime("dd-MM-yyyy")' },
|
||||
],
|
||||
args: [
|
||||
{
|
||||
name: 'format',
|
||||
optional: true,
|
||||
description: 'The format of the date string. Options are <code>ms</code> (for Unix timestamp in milliseconds), <code>s</code> (for Unix timestamp in seconds), <code>us</code> (for Unix timestamp in microseconds) or <code>excel</code> (for days since 1900). Custom formats can be specified using <a href="https://moment.github.io/luxon/#/formatting?id=table-of-tokens">Luxon tokens</a>.',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
};
|
||||
toBoolean.doc = {
|
||||
name: 'toBoolean',
|
||||
description: 'Converts the string to a boolean value. <code>0</code>, <code>false</code> and <code>no</code> resolve to <code>false</code>, everything else to <code>true</code>. Case-insensitive.',
|
||||
section: 'cast',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toBoolean',
|
||||
examples: [
|
||||
{ example: '"true".toBoolean()', evaluated: 'true' },
|
||||
{ example: '"false".toBoolean()', evaluated: 'false' },
|
||||
{ example: '"0".toBoolean()', evaluated: 'false' },
|
||||
{ example: '"hello".toBoolean()', evaluated: 'true' },
|
||||
],
|
||||
};
|
||||
toFloat.doc = {
|
||||
name: 'toFloat',
|
||||
description: 'Converts a string to a decimal number.',
|
||||
section: 'cast',
|
||||
returnType: 'number',
|
||||
aliases: ['toDecimalNumber'],
|
||||
hidden: true,
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toDecimalNumber',
|
||||
};
|
||||
toInt.doc = {
|
||||
name: 'toInt',
|
||||
description: 'Converts a string to an integer.',
|
||||
section: 'cast',
|
||||
returnType: 'number',
|
||||
args: [{ name: 'radix?', type: 'number' }],
|
||||
aliases: ['toWholeNumber'],
|
||||
hidden: true,
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toInt',
|
||||
};
|
||||
toSentenceCase.doc = {
|
||||
name: 'toSentenceCase',
|
||||
description: 'Changes the capitalization of the string to sentence case. The first letter of each sentence is capitalized and all others are lowercased.',
|
||||
examples: [{ example: '"quick! brown FOX".toSentenceCase()', evaluated: '"Quick! Brown fox"' }],
|
||||
section: 'case',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toSentenceCase',
|
||||
};
|
||||
toSnakeCase.doc = {
|
||||
name: 'toSnakeCase',
|
||||
description: 'Changes the format of the string to snake case. Spaces and dashes are replaced by <code>_</code>, symbols are removed and all letters are lowercased.',
|
||||
examples: [{ example: '"quick brown $FOX".toSnakeCase()', evaluated: '"quick_brown_fox"' }],
|
||||
section: 'case',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toSnakeCase',
|
||||
};
|
||||
toTitleCase.doc = {
|
||||
name: 'toTitleCase',
|
||||
description: "Changes the capitalization of the string to title case. The first letter of each word is capitalized and the others left unchanged. Short prepositions and conjunctions aren't capitalized (e.g. 'a', 'the').",
|
||||
examples: [{ example: '"quick a brown FOX".toTitleCase()', evaluated: '"Quick a Brown Fox"' }],
|
||||
section: 'case',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toTitleCase',
|
||||
};
|
||||
urlEncode.doc = {
|
||||
name: 'urlEncode',
|
||||
description: 'Encodes the string so that it can be used in a URL. Spaces and special characters are replaced with codes of the form <code>%XX</code>.',
|
||||
section: 'edit',
|
||||
args: [
|
||||
{
|
||||
name: 'allChars',
|
||||
optional: true,
|
||||
description: 'Whether to encode characters that are part of the URI syntax (e.g. <code>=</code>, <code>?</code>)',
|
||||
default: 'false',
|
||||
type: 'boolean',
|
||||
},
|
||||
],
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-urlEncode',
|
||||
examples: [
|
||||
{ example: '"name=Nathan Automat".urlEncode()', evaluated: '"name%3DNathan%20Automat"' },
|
||||
{ example: '"name=Nathan Automat".urlEncode(true)', evaluated: '"name=Nathan%20Automat"' },
|
||||
],
|
||||
};
|
||||
urlDecode.doc = {
|
||||
name: 'urlDecode',
|
||||
description: 'Decodes a URL-encoded string. Replaces any character codes in the form of <code>%XX</code> with their corresponding characters.',
|
||||
args: [
|
||||
{
|
||||
name: 'allChars',
|
||||
optional: true,
|
||||
description: 'Whether to decode characters that are part of the URI syntax (e.g. <code>=</code>, <code>?</code>)',
|
||||
default: 'false',
|
||||
type: 'boolean',
|
||||
},
|
||||
],
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-urlDecode',
|
||||
examples: [
|
||||
{ example: '"name%3DNathan%20Automat".urlDecode()', evaluated: '"name=Nathan Automat"' },
|
||||
{ example: '"name%3DNathan%20Automat".urlDecode(true)', evaluated: '"name%3DNathan Automat"' },
|
||||
],
|
||||
};
|
||||
replaceSpecialChars.doc = {
|
||||
name: 'replaceSpecialChars',
|
||||
description: 'Replaces special characters in the string with the closest ASCII character',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-replaceSpecialChars',
|
||||
examples: [{ example: '"déjà".replaceSpecialChars()', evaluated: '"deja"' }],
|
||||
};
|
||||
length.doc = {
|
||||
name: 'length',
|
||||
section: 'query',
|
||||
hidden: true,
|
||||
description: 'Returns the character count of a string.',
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings',
|
||||
};
|
||||
isDomain.doc = {
|
||||
name: 'isDomain',
|
||||
description: 'Returns <code>true</code> if a string is a domain.',
|
||||
section: 'validation',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isDomain',
|
||||
examples: [
|
||||
{ example: '"n8n.io".isDomain()', evaluated: 'true' },
|
||||
{ example: '"http://n8n.io".isDomain()', evaluated: 'false' },
|
||||
{ example: '"hello".isDomain()', evaluated: 'false' },
|
||||
],
|
||||
};
|
||||
isEmail.doc = {
|
||||
name: 'isEmail',
|
||||
description: 'Returns <code>true</code> if the string is an email.',
|
||||
section: 'validation',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isEmail',
|
||||
examples: [
|
||||
{ example: '"me@example.com".isEmail()', evaluated: 'true' },
|
||||
{ example: '"It\'s me@example.com".isEmail()', evaluated: 'false' },
|
||||
{ example: '"hello".isEmail()', evaluated: 'false' },
|
||||
],
|
||||
};
|
||||
isNumeric.doc = {
|
||||
name: 'isNumeric',
|
||||
description: 'Returns <code>true</code> if the string represents a number.',
|
||||
section: 'validation',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isNumeric',
|
||||
examples: [
|
||||
{ example: '"1.2234".isNumeric()', evaluated: 'true' },
|
||||
{ example: '"hello".isNumeric()', evaluated: 'false' },
|
||||
{ example: '"123E23".isNumeric()', evaluated: 'true' },
|
||||
],
|
||||
};
|
||||
isUrl.doc = {
|
||||
name: 'isUrl',
|
||||
description: 'Returns <code>true</code> if a string is a valid URL',
|
||||
section: 'validation',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isUrl',
|
||||
examples: [
|
||||
{ example: '"https://n8n.io".isUrl()', evaluated: 'true' },
|
||||
{ example: '"n8n.io".isUrl()', evaluated: 'false' },
|
||||
{ example: '"hello".isUrl()', evaluated: 'false' },
|
||||
],
|
||||
};
|
||||
isEmpty.doc = {
|
||||
name: 'isEmpty',
|
||||
description: 'Returns <code>true</code> if the string has no characters or is <code>null</code>',
|
||||
section: 'validation',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isEmpty',
|
||||
examples: [
|
||||
{ example: '"".isEmpty()', evaluated: 'true' },
|
||||
{ example: '"hello".isEmpty()', evaluated: 'false' },
|
||||
],
|
||||
};
|
||||
isNotEmpty.doc = {
|
||||
name: 'isNotEmpty',
|
||||
description: 'Returns <code>true</code> if the string has at least one character.',
|
||||
section: 'validation',
|
||||
returnType: 'boolean',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-isNotEmpty',
|
||||
examples: [
|
||||
{ example: '"hello".isNotEmpty()', evaluated: 'true' },
|
||||
{ example: '"".isNotEmpty()', evaluated: 'false' },
|
||||
],
|
||||
};
|
||||
toJsonString.doc = {
|
||||
name: 'toJsonString',
|
||||
description: 'Prepares the string to be inserted into a JSON object. Escapes any quotes and special characters (e.g. new lines), and wraps the string in quotes.The same as JavaScript’s JSON.stringify().',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toJsonString',
|
||||
examples: [
|
||||
{
|
||||
example: 'The "best" colours: red\nbrown.toJsonString()',
|
||||
evaluated: '"The \\"best\\" colours: red\\nbrown"',
|
||||
},
|
||||
{ example: 'foo.toJsonString()', evaluated: '"foo"' },
|
||||
],
|
||||
};
|
||||
extractEmail.doc = {
|
||||
name: 'extractEmail',
|
||||
description: 'Extracts the first email found in the string. Returns <code>undefined</code> if none is found.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractEmail',
|
||||
examples: [
|
||||
{ example: '"My email is me@example.com".extractEmail()', evaluated: "'me@example.com'" },
|
||||
],
|
||||
};
|
||||
extractDomain.doc = {
|
||||
name: 'extractDomain',
|
||||
description: 'If the string is an email address or URL, returns its domain (or <code>undefined</code> if nothing found). If the string also contains other content, try using <code>extractEmail()</code> or <code>extractUrl()</code> first.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractDomain',
|
||||
examples: [
|
||||
{ example: '"me@example.com".extractDomain()', evaluated: "'example.com'" },
|
||||
{ example: '"http://n8n.io/workflows".extractDomain()', evaluated: "'n8n.io'" },
|
||||
{
|
||||
example: '"It\'s me@example.com".extractEmail().extractDomain()',
|
||||
evaluated: "'example.com'",
|
||||
},
|
||||
],
|
||||
};
|
||||
extractUrl.doc = {
|
||||
name: 'extractUrl',
|
||||
description: 'Extracts the first URL found in the string. Returns <code>undefined</code> if none is found. Only recognizes full URLs, e.g. those starting with <code>http</code>.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractUrl',
|
||||
examples: [{ example: '"Check out http://n8n.io".extractUrl()', evaluated: "'http://n8n.io'" }],
|
||||
};
|
||||
extractUrlPath.doc = {
|
||||
name: 'extractUrlPath',
|
||||
description: 'Returns the part of a URL after the domain, or <code>undefined</code> if no URL found. If the string also contains other content, try using <code>extractUrl()</code> first.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-extractUrlPath',
|
||||
examples: [
|
||||
{ example: '"http://n8n.io/workflows".extractUrlPath()', evaluated: "'/workflows'" },
|
||||
{
|
||||
example: '"Check out http://n8n.io/workflows".extractUrl().extractUrlPath()',
|
||||
evaluated: "'/workflows'",
|
||||
},
|
||||
],
|
||||
};
|
||||
hash.doc = {
|
||||
name: 'hash',
|
||||
description: 'Returns the string hashed with the given algorithm. Defaults to md5 if not specified.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
args: [
|
||||
{
|
||||
name: 'algo',
|
||||
optional: true,
|
||||
description: 'The hashing algorithm to use. One of <code>md5</code>, <code>base64</code>, <code>sha1</code>, <code>sha224</code>, <code>sha256</code>, <code>sha384</code>, <code>sha512</code>, <code>sha3</code>, <code>ripemd160</code>\n ',
|
||||
default: '"md5"',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-hash',
|
||||
examples: [{ example: '"hello".hash()', evaluated: "'5d41402abc4b2a76b9719d911017c592'" }],
|
||||
};
|
||||
quote.doc = {
|
||||
name: 'quote',
|
||||
description: 'Wraps a string in quotation marks, and escapes any quotation marks already in the string. Useful when constructing JSON, SQL, etc.',
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
args: [
|
||||
{
|
||||
name: 'mark',
|
||||
optional: true,
|
||||
description: 'The type of quotation mark to use',
|
||||
default: '"',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-quote',
|
||||
examples: [{ example: '\'Nathan says "hi"\'.quote()', evaluated: '\'"Nathan says \\"hi\\""\'' }],
|
||||
};
|
||||
parseJson.doc = {
|
||||
name: 'parseJson',
|
||||
description: "Returns the JavaScript value or object represented by the string, or <code>undefined</code> if the string isn't valid JSON. Single-quoted JSON is not supported.",
|
||||
section: 'cast',
|
||||
returnType: 'any',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-parseJson',
|
||||
examples: [
|
||||
{ example: '\'{"name":"Nathan"}\'.parseJson()', evaluated: '\'{"name":"Nathan"}\'' },
|
||||
{ example: "\"{'name':'Nathan'}\".parseJson()", evaluated: 'undefined' },
|
||||
{ example: "'hello'.parseJson()", evaluated: 'undefined' },
|
||||
],
|
||||
};
|
||||
base64Encode.doc = {
|
||||
name: 'base64Encode',
|
||||
description: 'Converts plain text to a base64-encoded string',
|
||||
examples: [{ example: '"hello".base64Encode()', evaluated: '"aGVsbG8="' }],
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-base64Encode',
|
||||
};
|
||||
base64Decode.doc = {
|
||||
name: 'base64Decode',
|
||||
description: 'Converts a base64-encoded string to plain text',
|
||||
examples: [{ example: '"aGVsbG8=".base64Decode()', evaluated: '"hello"' }],
|
||||
section: 'edit',
|
||||
returnType: 'string',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-base64Decode',
|
||||
};
|
||||
toNumber.doc = {
|
||||
name: 'toNumber',
|
||||
description: "Converts a string representing a number to a number. Errors if the string doesn't start with a valid number.",
|
||||
section: 'cast',
|
||||
returnType: 'number',
|
||||
docURL: 'https://docs.n8n.io/code/builtin/data-transformation-functions/strings/#string-toNumber',
|
||||
examples: [
|
||||
{ example: '"123".toNumber()', evaluated: '123' },
|
||||
{ example: '"1.23E10".toNumber()', evaluated: '12300000000' },
|
||||
],
|
||||
};
|
||||
const toDecimalNumber = toFloat.bind({});
|
||||
const toWholeNumber = toInt.bind({});
|
||||
export const stringExtensions = {
|
||||
typeName: 'String',
|
||||
functions: {
|
||||
hash,
|
||||
removeMarkdown,
|
||||
removeTags,
|
||||
toDate,
|
||||
toDateTime,
|
||||
toBoolean,
|
||||
toDecimalNumber,
|
||||
toNumber,
|
||||
toFloat,
|
||||
toInt,
|
||||
toWholeNumber,
|
||||
toSentenceCase,
|
||||
toSnakeCase,
|
||||
toTitleCase,
|
||||
urlDecode,
|
||||
urlEncode,
|
||||
quote,
|
||||
replaceSpecialChars,
|
||||
length,
|
||||
isDomain,
|
||||
isEmail,
|
||||
isNumeric,
|
||||
isUrl,
|
||||
isEmpty,
|
||||
isNotEmpty,
|
||||
toJsonString,
|
||||
extractEmail,
|
||||
extractDomain,
|
||||
extractUrl,
|
||||
extractUrlPath,
|
||||
parseJson,
|
||||
base64Encode,
|
||||
base64Decode,
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=string-extensions.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/string-extensions.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
4
node_modules/n8n-workflow/dist/esm/extensions/utils.d.ts
generated
vendored
Normal file
4
node_modules/n8n-workflow/dist/esm/extensions/utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import { DateTime } from 'luxon';
|
||||
export declare const convertToDateTime: (value: string | Date | DateTime) => DateTime | undefined;
|
||||
export declare function checkIfValueDefinedOrThrow<T>(value: T, functionName: string): void;
|
||||
//# sourceMappingURL=utils.d.ts.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/utils.d.ts.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/utils.d.ts.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/extensions/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMjC,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,GAAG,IAAI,GAAG,QAAQ,KAAG,QAAQ,GAAG,SAc9E,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAMlF"}
|
||||
27
node_modules/n8n-workflow/dist/esm/extensions/utils.js
generated
vendored
Normal file
27
node_modules/n8n-workflow/dist/esm/extensions/utils.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { DateTime } from 'luxon';
|
||||
import { ExpressionExtensionError } from '../errors/expression-extension.error';
|
||||
// Utility functions and type guards for expression extensions
|
||||
export const convertToDateTime = (value) => {
|
||||
let converted;
|
||||
if (typeof value === 'string') {
|
||||
converted = DateTime.fromJSDate(new Date(value));
|
||||
if (converted.invalidReason !== null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (value instanceof Date) {
|
||||
converted = DateTime.fromJSDate(value);
|
||||
}
|
||||
else if (DateTime.isDateTime(value)) {
|
||||
converted = value;
|
||||
}
|
||||
return converted;
|
||||
};
|
||||
export function checkIfValueDefinedOrThrow(value, functionName) {
|
||||
if (value === undefined || value === null) {
|
||||
throw new ExpressionExtensionError(`${functionName} can't be used on ${String(value)} value`, {
|
||||
description: `To ignore this error, add a ? to the variable before this function, e.g. my_var?.${functionName}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/n8n-workflow/dist/esm/extensions/utils.js.map
generated
vendored
Normal file
1
node_modules/n8n-workflow/dist/esm/extensions/utils.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/extensions/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAEhF,8DAA8D;AAE9D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAA+B,EAAwB,EAAE;IAC1F,IAAI,SAA+B,CAAC;IAEpC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACjD,IAAI,SAAS,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;YACtC,OAAO;QACR,CAAC;IACF,CAAC;SAAM,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAClC,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;SAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,SAAS,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAI,KAAQ,EAAE,YAAoB;IAC3E,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC3C,MAAM,IAAI,wBAAwB,CAAC,GAAG,YAAY,qBAAqB,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC7F,WAAW,EAAE,oFAAoF,YAAY,EAAE;SAC/G,CAAC,CAAC;IACJ,CAAC;AACF,CAAC"}
|
||||
Reference in New Issue
Block a user