Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@integration-app/sdk

Package Overview
Dependencies
Maintainers
4
Versions
444
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@integration-app/sdk - npm Package Compare versions

Comparing version 1.2.3 to 1.2.4

src/udm/deal-stages.ts

2

package.json
{
"name": "@integration-app/sdk",
"version": "1.2.3",
"version": "1.2.4",
"description": "JavaScript SDK for Integration.app",

@@ -5,0 +5,0 @@ "author": "Integration.app",

@@ -41,2 +41,6 @@ import qs from 'qs'

getUniqueIdentifier() {
return this.getPath()
}
async get(): Promise<Element> {

@@ -144,2 +148,6 @@ return this.options.client.get(this.getPath())

getUniqueIdentifier() {
return this.getPath()
}
async get(): Promise<ElementInstance> {

@@ -146,0 +154,0 @@ return this.options.client.get(this.getPath())

@@ -20,2 +20,4 @@ import { FieldMappingDirection } from '../field-mappings'

RunJavascript = 'run-javascript',
/**

@@ -110,2 +112,6 @@ * @deprecated

},
[ActionType.RunJavascript]: {
name: 'Run Javascript',
description: 'Run custom Javascript code',
},
[ActionType.ApiRequest]: {

@@ -112,0 +118,0 @@ name: 'API Request',

@@ -16,3 +16,7 @@ import { ConnectorSpec } from '.'

export type ConnectorAuthType = typeof CONNECTOR_AUTH_TYPES[number]
export type ConnectorAuthOptions = { key: string; title?: string }[]
export type ConnectorAuthOptions = {
key: string
title?: string
type: ConnectorAuthType
}[]

@@ -19,0 +23,0 @@ interface ConnectorAuthMethodArgs {

@@ -60,4 +60,5 @@ import { HttpRequestMethod } from '../http-requests'

binary?: boolean
stream?: boolean
dynamicOptions?: (input: RestApiClientInput) => RestApiClientOptions
onError?: (error: any) => any
}

@@ -41,3 +41,2 @@ import { DataSchema } from '../data-schema'

hasAuth?: boolean
hasReadme?: boolean

@@ -44,0 +43,0 @@ hasDefaultParameters?: boolean

import {
getValueByLocator,
getVariableLocators,
removeEmptyFields,
processValue,
transformVars,
} from './formula-processors'
describe('processValue', () => {
it('should return original value if there are no formulas', () => {
expect(processValue('value', undefined)).toEqual('value')
expect(processValue(5, undefined)).toEqual(5)
expect(processValue(true, undefined)).toEqual(true)
expect(processValue([1], undefined)).toEqual([1])
expect(processValue({ key: 'value' }, undefined)).toEqual({ key: 'value' })
// Empty-ish values - should not erase them
expect(processValue('', undefined)).toEqual('')
expect(processValue(0, undefined)).toEqual(0)
expect(processValue(false, undefined)).toEqual(false)
expect(processValue([], undefined)).toEqual([])
expect(processValue({}, undefined)).toEqual({})
})
it('should remove values if formula was resolved to nothing', () => {
expect(processValue({ $var: 'nonExistentField' }, undefined)).toEqual(
undefined,
)
expect(processValue([{ $var: 'nonExistentField' }], undefined)).toEqual(
undefined,
)
expect(
processValue({ key: { $var: 'nonExistentField' } }, 'value'),
).toEqual(undefined)
})
})
describe('getValueByLocator', () => {

@@ -31,49 +60,2 @@ it('should return value at object property locator', () => {

describe('removeEmptyFields', () => {
it('should work with empty value', () => {
expect(removeEmptyFields(undefined)).toEqual(undefined)
expect(removeEmptyFields(null)).toEqual(null)
})
it('should work with simple data', () => {
expect(removeEmptyFields(0)).toEqual(0)
expect(removeEmptyFields(1)).toEqual(1)
expect(removeEmptyFields('')).toEqual('')
expect(removeEmptyFields('a')).toEqual('a')
expect(removeEmptyFields(true)).toEqual(true)
expect(removeEmptyFields(false)).toEqual(false)
expect(removeEmptyFields({ a: 'b' })).toEqual({ a: 'b' })
expect(removeEmptyFields([1])).toEqual([1])
})
it('should work with nested datas', () => {
const value = {
list: [
{
name: 'a',
},
],
}
expect(removeEmptyFields(value)).toEqual(value)
})
it('should remove empty lists from value', () => {
expect(removeEmptyFields([])).toEqual(undefined)
expect(removeEmptyFields({ a: [] })).toEqual(undefined)
expect(removeEmptyFields({ a: [], b: 1 })).toEqual({ b: 1 })
expect(removeEmptyFields({ a: [[]], b: 1 })).toEqual({ b: 1 })
})
it('should remove empty objects', () => {
expect(removeEmptyFields({})).toEqual(undefined)
expect(removeEmptyFields({ a: {} })).toEqual(undefined)
expect(removeEmptyFields({ a: {}, b: 1 })).toEqual({ b: 1 })
expect(removeEmptyFields({ a: [{}], b: 1 })).toEqual({ b: 1 })
})
it('should deep remove empty values', () => {
expect(removeEmptyFields({ a: [{ b: [{}] }] })).toEqual(undefined)
})
})
describe('transformVars', () => {

@@ -80,0 +62,0 @@ it('should transform $var formulas', () => {

@@ -45,2 +45,4 @@ import { BadRequestError, ConfigurationError } from '../errors'

if (Array.isArray(value)) {
if (!value?.length) return value
const result = []

@@ -59,2 +61,4 @@ for (const valueItem of value) {

} else {
if (Object.keys(value).length === 0) return value
const result = {}

@@ -222,36 +226,2 @@ for (const [key, val] of Object.entries(value)) {

export function removeEmptyFields(value: any): any {
if (typeof value === 'object') {
if (Array.isArray(value)) {
const result = []
for (const valueItem of value) {
const processedVal = removeEmptyFields(valueItem)
if (processedVal !== undefined) {
/* FIXME: strictNullCheck temporary fix */
// @ts-expect-error TS(2345): Argument of type 'any' is not assignable to parame... Remove this comment to see the full error message
result.push(processedVal)
}
}
return result.length > 0 ? result : undefined
} else if (value === null) {
return value
} else {
const result = {}
for (const [key, val] of Object.entries(value)) {
const processedVal = removeEmptyFields(val)
if (processedVal !== undefined) {
result[key] = processedVal
}
}
if (Object.keys(result).length > 0) {
return result
} else {
return undefined
}
}
} else {
return value
}
}
function executeLocatorStepObjectProperty(

@@ -258,0 +228,0 @@ value: any,

@@ -41,2 +41,15 @@ import { Formula } from '.'

export function hasFormulas(value) {
if (isFormula(value)) {
return true
}
if (Array.isArray(value)) {
return value.some((v) => hasFormulas(v))
} else if (typeof value === 'object' && value !== null) {
return Object.values(value).some((v) => hasFormulas(v))
} else {
return false
}
}
export function getFormula(value): Formula.Base {

@@ -43,0 +56,0 @@ if (typeof value === 'object' && value !== null) {

@@ -1,2 +0,2 @@

import { buildData } from '.'
import { buildData, hasFormulas } from '.'

@@ -199,4 +199,2 @@ describe('DataBuilder', () => {

it('should skip objects without fields', () => {
expect(buildData({})).toEqual(undefined)
expect(

@@ -225,4 +223,2 @@ buildData({

it('should skip arrays without values', () => {
expect(buildData([])).toEqual(undefined)
expect(

@@ -254,1 +250,35 @@ buildData({

})
describe('hasFormulas', () => {
it('should return false for values without formulas', () => {
expect(hasFormulas('value')).toBe(false)
expect(hasFormulas(42)).toBe(false)
expect(hasFormulas(true)).toBe(false)
expect(hasFormulas(null)).toBe(false)
expect(hasFormulas(undefined)).toBe(false)
expect(hasFormulas([])).toBe(false)
expect(hasFormulas({})).toBe(false)
expect(hasFormulas({ key: 'value' })).toBe(false)
})
it('should return true for values that are formulas', () => {
expect(hasFormulas({ $var: 'value' })).toBe(true)
expect(
hasFormulas({ $lookup: { uri: 'uri', query: { field: 'value' } } }),
).toBe(true)
expect(hasFormulas({ $map: { value: 'value', mapping: [] } })).toBe(true)
})
it('should return true for values inside object keys', () => {
expect(hasFormulas({ key: { $var: 'value' } })).toBe(true)
})
it('should return true for values inside array items', () => {
expect(hasFormulas([{ $var: 'value' }])).toBe(true)
})
it('should return true for nested formulas', () => {
expect(hasFormulas({ key: { subKey: { $var: 'value' } } })).toBe(true)
expect(hasFormulas({ key: { subKey: [{ $var: 'value' }] } })).toBe(true)
})
})

@@ -14,2 +14,4 @@ import { ErrorData } from '../errors'

outputFileUri?: string
errors?: ErrorData[]

@@ -55,2 +57,4 @@ }

outputFileUri?: string
errors: ErrorData[]

@@ -57,0 +61,0 @@ }

import { ErrorData } from '../errors'
import { PaginationResponse, PaginationQuery } from '../entity-repository'
import { User } from '../users'
import { Customer } from '../users'
import { FlowInstance } from '../flows'

@@ -10,3 +10,2 @@ import { Connection } from '../connections'

export * from './accessors'
export * from './api'

@@ -57,3 +56,3 @@ export enum FlowRunState {

user?: User
user?: Customer

@@ -118,2 +117,2 @@ input?: any

export class FindFlowRunsResponse extends PaginationResponse<FlowRun> {}
export interface FindFlowRunsResponse extends PaginationResponse<FlowRun> {}

@@ -6,11 +6,1 @@ export * from './accessors'

export * from './utils'
export {
getChildNodeKeys,
getDownstreamNodeKeys,
getFlowNode,
getOrderedNodeKeys,
getParentNodeKeys,
getRootNodeKeys,
getUpstreamNodeKeys,
} from './utils'
import { FieldMappingDirection } from '../../field-mappings'
import { FlowNode } from '../types'

@@ -15,2 +16,3 @@ /* FIXME: temporary fix to pass eslint test */

version?: number
getSubFlowRootNodeKey?: (node: FlowNode) => string
}

@@ -17,0 +19,0 @@

@@ -6,2 +6,3 @@ import { FlowNodeSpec } from './base'

description: 'Execute one or more steps for each item on a list.',
getSubFlowRootNodeKey: (node) => node.config?.rootNodeKey,
})
import { Flow, FlowNodeType, hasCycles } from '.'
import { getOrderedNodeKeys, getParentNodeKeys } from './utils'
import { getParentNodeKeys } from './utils'

@@ -37,83 +37,2 @@ describe('flows/utils', () => {

describe('getOrderedNodeKeys', () => {
it('should return nodes in order taking dependencies in account', () => {
// Structure:
// root-1 root 2
// | |
// | |
// | child-1
// | / | \
// | / | \
// child-2-1 child-2-2 \
// | | \ \
// | | \ \
// child-3-1 child-3-2 child-3-3
const flow = {
nodes: {
'root-1': {
links: [
{
key: 'child-2-1',
},
],
},
'root-2': {
links: [
{
key: 'child-1',
},
],
},
'child-1': {
links: [
{
key: 'child-2-1',
},
{
key: 'child-2-2',
},
{
key: 'child-3-3',
},
],
},
'child-2-1': {
links: [
{
key: 'child-3-1',
},
],
},
'child-2-2': {
links: [
{
key: 'child-3-2',
},
{
key: 'child-3-3',
},
],
},
'child-3-1': {},
'child-3-2': {},
'child-3-3': {},
},
}
const keysInOrder = [
'root-1',
'root-2',
'child-1',
'child-2-1',
'child-2-2',
'child-3-3',
'child-3-1',
'child-3-2',
]
expect(getOrderedNodeKeys(flow as any as Flow)).toEqual(keysInOrder)
})
})
describe('hasCycles', () => {

@@ -193,2 +112,20 @@ it('should return false for an empty graph', () => {

it('should return false for a flow with a nodes that is entered twice', () => {
const nodes = {
a: {
type: 'type1',
links: [{ key: 'b' }, { key: 'c' }],
},
b: {
type: 'type2',
links: [{ key: 'c' }],
},
c: {
type: 'type3',
},
}
expect(hasCycles(nodes)).toBe(false)
})
it('should return true for a flow with a cycle', () => {

@@ -266,3 +203,47 @@ const nodes = {

})
it('should return true if a node is used inside forEach and after forEach', () => {
const nodes = {
trigger: {
type: FlowNodeType.ApiTrigger,
links: [{ key: 'forEach' }],
},
forEach: {
type: FlowNodeType.ForEachV2,
config: {
rootNodeKey: 'insideForEach',
},
links: [{ key: 'insideForEach' }],
},
insideForEach: {
type: FlowNodeType.TransformData,
links: [],
},
}
expect(hasCycles(nodes)).toBe(true)
})
it('should return false for a correct flow with forEach', () => {
const nodes = {
trigger: {
type: FlowNodeType.ApiTrigger,
links: [{ key: 'forEach' }],
},
forEach: {
type: FlowNodeType.ForEachV2,
config: {
rootNodeKey: 'insideForEach',
},
links: [],
},
insideForEach: {
type: FlowNodeType.TransformData,
links: [],
},
}
expect(hasCycles(nodes)).toBe(false)
})
})
})

@@ -63,8 +63,27 @@ import { toHeaderCase } from 'js-convert-case'

*/
export function getRootNodeKeys(flow: Flow | FlowInstance): string[] {
const allNodeKeys = Object.keys(flow.nodes ?? {})
const allLinkKeys = Object.values(flow.nodes ?? {})
export function getRootNodeKeys({
nodes,
}: {
nodes?: Record<string, FlowNode>
}): string[] {
const allNodeKeys = Object.keys(nodes ?? {})
const allLinkKeys = Object.values(nodes ?? {})
.flatMap((n) => n.links?.map((l) => l.key) ?? [])
.filter(Boolean)
return allNodeKeys.filter((k) => !allLinkKeys.includes(k))
const allSubFlowRootNodeKeys: string[] = []
for (const nodeKey of allNodeKeys) {
const node = nodes?.[nodeKey]
if (node && FLOW_NODE_SPECS[node.type]?.getSubFlowRootNodeKey) {
const subFlowRootNodeKey =
FLOW_NODE_SPECS[node.type].getSubFlowRootNodeKey(node)
if (subFlowRootNodeKey) {
allSubFlowRootNodeKeys.push(subFlowRootNodeKey)
}
}
}
const allNonRootNodeKeys = allLinkKeys.concat(allSubFlowRootNodeKeys)
return allNodeKeys.filter((k) => !allNonRootNodeKeys.includes(k))
}

@@ -135,35 +154,2 @@

/**
* Returns keys of flow nodes in order of execution.
* If order of execution is not possible to determine (i.e. two triggers) - the returned order is arbitrary.
*
* This function allows executing operations on nodes that require upstream nodes to be processed first,
* such as node setup.
*/
export function getOrderedNodeKeys(flow: Flow | FlowInstance): string[] {
const rootNodeKeys = getRootNodeKeys(flow)
const orderedNodeKeys = rootNodeKeys
let moreIterations = true
// Going layer after layer and adding children
// but only if all of their parents are already in the list
while (moreIterations) {
moreIterations = false
for (const nodeKey of orderedNodeKeys) {
for (const childNodeKey of getChildNodeKeys(flow, nodeKey)) {
if (!orderedNodeKeys.includes(childNodeKey)) {
const parentNodeKeys = getParentNodeKeys(flow, childNodeKey)
if (parentNodeKeys.every((k) => orderedNodeKeys.includes(k))) {
orderedNodeKeys.push(childNodeKey)
moreIterations = true
}
}
}
}
}
return orderedNodeKeys
}
/**
* Detects cycles in the flow.

@@ -176,48 +162,58 @@ */

const visited = new Set<string>()
const stack = new Set<string>()
let hasCycles = false
const allVisited = new Set<string>()
for (const nodeKey in nodes) {
if (dfs(nodeKey, visited, stack, nodes)) {
return true
function visitNode(nodeKey: string, visited: string[]): string[] {
if (!nodeKey) return visited
if (visited.includes(nodeKey)) {
hasCycles = true
return visited
}
}
return false
}
const node = nodes?.[nodeKey]
if (!node) return visited
/**
* Depth-first search
*/
function dfs(
nodeKey: string,
visited: Set<string>,
stack: Set<string>,
nodes: Record<string, FlowNode>,
): boolean {
if (stack.has(nodeKey)) {
return true
}
visited = [...visited, nodeKey]
allVisited.add(nodeKey)
if (visited.has(nodeKey)) {
return false
}
if (FLOW_NODE_SPECS[node?.type]?.getSubFlowRootNodeKey) {
visited = [
...visited,
...visitNode(
FLOW_NODE_SPECS[node.type].getSubFlowRootNodeKey(node),
visited,
),
]
}
visited.add(nodeKey)
stack.add(nodeKey)
const node = nodes[nodeKey]
if (node && node.links) {
for (const link of node.links) {
/* FIXME: strictNullCheck temporary fix */
// @ts-expect-error TS(2345): Argument of type 'string | undefined' is not assig... Remove this comment to see the full error message
if (dfs(link.key, visited, stack, nodes)) {
return true
if (node && node.links) {
let visitedSubNodes: string[] = []
for (const link of node.links) {
if (link.key) {
visitedSubNodes = [
...visitedSubNodes,
...visitNode(link.key, visited),
]
}
}
visited = [...visited, ...Array.from(new Set(visitedSubNodes))]
}
return visited
}
stack.delete(nodeKey)
const rootNodeKeys = getRootNodeKeys({ nodes })
return false
for (const nodeKey of rootNodeKeys) {
visitNode(nodeKey, [])
}
if (allVisited.size !== Object.keys(nodes).length) {
// If we didn't visit all the nodes, it's because we couldn't find all the root nodes
// due to cycles.
hasCycles = true
}
return hasCycles
}

@@ -24,2 +24,6 @@ import { IntegrationAppApiClient } from '../api-client'

getUniqueIdentifier() {
return this.endpoint
}
async get(query: { autoCreate?: boolean } = {}): Promise<Element> {

@@ -26,0 +30,0 @@ return this.client.get(this.uri('', query))

@@ -15,2 +15,6 @@ import { IntegrationAppApiClient } from '../api-client'

getUniqueIdentifier() {
return this.endpoint
}
async get(): Promise<Element> {

@@ -17,0 +21,0 @@ return this.client.get(this.endpoint)

@@ -77,4 +77,2 @@ import { Connection } from '../connections'

hasUdm?: boolean
hasAuth?: boolean
}

@@ -81,0 +79,0 @@

@@ -23,2 +23,3 @@ import { structuredClone } from '../_helper'

import deals from './deals'
import dealStages from './deal-stages'
import documents from './documents'

@@ -68,2 +69,3 @@ import drives from './drives'

DEALS = 'deals',
DEAL_STAGES = 'deal-stages',
DOCUMENTS = 'documents',

@@ -112,2 +114,3 @@ DRIVES = 'drives',

[UDM.DEALS]: deals,
[UDM.DEAL_STAGES]: dealStages,
[UDM.DOCUMENTS]: documents,

@@ -114,0 +117,0 @@ [UDM.DRIVES]: drives,

@@ -85,3 +85,12 @@ import { CreateActionRequest } from '../actions'

}
export interface UserWorkspaceSettings {
id: string
userId: string
workspaceId: string
testCustomerId: string
}
export interface WorkspaceElements {

@@ -88,0 +97,0 @@ flows?: Record<string, CreateFlowRequest>

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc