Compare commits
	
		
			1 Commits
		
	
	
		
			dependabot
			...
			AUT-1252
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 06e8f5bfdc | 
							
								
								
									
										1
									
								
								.github/workflows/playwright.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/playwright.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,6 +23,7 @@ env: | |||||||
|   REDIS_HOST: localhost |   REDIS_HOST: localhost | ||||||
|   APP_ENV: production |   APP_ENV: production | ||||||
|   LICENSE_KEY: dummy_license_key |   LICENSE_KEY: dummy_license_key | ||||||
|  |   BACKEND_APP_URL: http://localhost:3000 | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   test: |   test: | ||||||
|   | |||||||
| @@ -1,11 +1,15 @@ | |||||||
| // Converted mutations | // Converted mutations | ||||||
|  | import executeFlow from './mutations/execute-flow.js'; | ||||||
| import verifyConnection from './mutations/verify-connection.js'; | import verifyConnection from './mutations/verify-connection.js'; | ||||||
| import updateCurrentUser from './mutations/update-current-user.js'; | import updateCurrentUser from './mutations/update-current-user.js'; | ||||||
| import generateAuthUrl from './mutations/generate-auth-url.js'; | import generateAuthUrl from './mutations/generate-auth-url.js'; | ||||||
|  | import createConnection from './mutations/create-connection.js'; | ||||||
| import resetConnection from './mutations/reset-connection.js'; | import resetConnection from './mutations/reset-connection.js'; | ||||||
| import updateConnection from './mutations/update-connection.js'; | import updateConnection from './mutations/update-connection.js'; | ||||||
|  |  | ||||||
| const mutationResolvers = { | const mutationResolvers = { | ||||||
|  |   createConnection, | ||||||
|  |   executeFlow, | ||||||
|   generateAuthUrl, |   generateAuthUrl, | ||||||
|   resetConnection, |   resetConnection, | ||||||
|   updateConnection, |   updateConnection, | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								packages/backend/src/graphql/mutations/create-connection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								packages/backend/src/graphql/mutations/create-connection.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | import App from '../../models/app.js'; | ||||||
|  | import AppConfig from '../../models/app-config.js'; | ||||||
|  |  | ||||||
|  | const createConnection = async (_parent, params, context) => { | ||||||
|  |   context.currentUser.can('create', 'Connection'); | ||||||
|  |  | ||||||
|  |   const { key, appAuthClientId } = params.input; | ||||||
|  |  | ||||||
|  |   const app = await App.findOneByKey(key); | ||||||
|  |  | ||||||
|  |   const appConfig = await AppConfig.query().findOne({ key }); | ||||||
|  |  | ||||||
|  |   let formattedData = params.input.formattedData; | ||||||
|  |   if (appConfig) { | ||||||
|  |     if (appConfig.disabled) | ||||||
|  |       throw new Error( | ||||||
|  |         'This application has been disabled for new connections!' | ||||||
|  |       ); | ||||||
|  |  | ||||||
|  |     if (!appConfig.allowCustomConnection && formattedData) | ||||||
|  |       throw new Error(`Custom connections cannot be created for ${app.name}!`); | ||||||
|  |  | ||||||
|  |     if (appConfig.shared && !formattedData) { | ||||||
|  |       const authClient = await appConfig | ||||||
|  |         .$relatedQuery('appAuthClients') | ||||||
|  |         .findById(appAuthClientId) | ||||||
|  |         .where({ | ||||||
|  |           active: true, | ||||||
|  |         }) | ||||||
|  |         .throwIfNotFound(); | ||||||
|  |  | ||||||
|  |       formattedData = authClient.formattedAuthDefaults; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const createdConnection = await context.currentUser | ||||||
|  |     .$relatedQuery('connections') | ||||||
|  |     .insert({ | ||||||
|  |       key, | ||||||
|  |       appAuthClientId, | ||||||
|  |       formattedData, | ||||||
|  |       verified: false, | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |   return createdConnection; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default createConnection; | ||||||
							
								
								
									
										28
									
								
								packages/backend/src/graphql/mutations/execute-flow.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								packages/backend/src/graphql/mutations/execute-flow.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | import testRun from '../../services/test-run.js'; | ||||||
|  | import Step from '../../models/step.js'; | ||||||
|  |  | ||||||
|  | const executeFlow = async (_parent, params, context) => { | ||||||
|  |   const conditions = context.currentUser.can('update', 'Flow'); | ||||||
|  |   const isCreator = conditions.isCreator; | ||||||
|  |   const allSteps = Step.query(); | ||||||
|  |   const userSteps = context.currentUser.$relatedQuery('steps'); | ||||||
|  |   const baseQuery = isCreator ? userSteps : allSteps; | ||||||
|  |  | ||||||
|  |   const { stepId } = params.input; | ||||||
|  |  | ||||||
|  |   const untilStep = await baseQuery.clone().findById(stepId).throwIfNotFound(); | ||||||
|  |  | ||||||
|  |   const { executionStep } = await testRun({ stepId }); | ||||||
|  |  | ||||||
|  |   if (executionStep.isFailed) { | ||||||
|  |     throw new Error(JSON.stringify(executionStep.errorDetails)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   await untilStep.$query().patch({ | ||||||
|  |     status: 'completed', | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   return { data: executionStep.dataOut, step: untilStep }; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default executeFlow; | ||||||
| @@ -2,6 +2,8 @@ type Query { | |||||||
|   placeholderQuery(name: String): Boolean |   placeholderQuery(name: String): Boolean | ||||||
| } | } | ||||||
| type Mutation { | type Mutation { | ||||||
|  |   createConnection(input: CreateConnectionInput): Connection | ||||||
|  |   executeFlow(input: ExecuteFlowInput): executeFlowType | ||||||
|   generateAuthUrl(input: GenerateAuthUrlInput): AuthLink |   generateAuthUrl(input: GenerateAuthUrlInput): AuthLink | ||||||
|   resetConnection(input: ResetConnectionInput): Connection |   resetConnection(input: ResetConnectionInput): Connection | ||||||
|   updateConnection(input: UpdateConnectionInput): Connection |   updateConnection(input: UpdateConnectionInput): Connection | ||||||
| @@ -151,6 +153,11 @@ type ConnectionData { | |||||||
|   screenName: String |   screenName: String | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type executeFlowType { | ||||||
|  |   data: JSONObject | ||||||
|  |   step: Step | ||||||
|  | } | ||||||
|  |  | ||||||
| type ExecutionStep { | type ExecutionStep { | ||||||
|   id: String |   id: String | ||||||
|   executionId: String |   executionId: String | ||||||
| @@ -201,6 +208,12 @@ type SamlAuthProvidersRoleMapping { | |||||||
|   remoteRoleName: String |   remoteRoleName: String | ||||||
| } | } | ||||||
|  |  | ||||||
|  | input CreateConnectionInput { | ||||||
|  |   key: String! | ||||||
|  |   appAuthClientId: String | ||||||
|  |   formattedData: JSONObject | ||||||
|  | } | ||||||
|  |  | ||||||
| input GenerateAuthUrlInput { | input GenerateAuthUrlInput { | ||||||
|   id: String! |   id: String! | ||||||
| } | } | ||||||
| @@ -219,6 +232,10 @@ input VerifyConnectionInput { | |||||||
|   id: String! |   id: String! | ||||||
| } | } | ||||||
|  |  | ||||||
|  | input ExecuteFlowInput { | ||||||
|  |   stepId: String! | ||||||
|  | } | ||||||
|  |  | ||||||
| input UserRoleInput { | input UserRoleInput { | ||||||
|   id: String |   id: String | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ export class AuthenticatedPage extends BasePage { | |||||||
|     super(page); |     super(page); | ||||||
|  |  | ||||||
|     this.profileMenuButton = this.page.getByTestId('profile-menu-button'); |     this.profileMenuButton = this.page.getByTestId('profile-menu-button'); | ||||||
|     this.logoutMenuItem = this.page.getByTestId('logout-item'); |  | ||||||
|     this.adminMenuItem = this.page.getByRole('menuitem', { name: 'Admin' }); |     this.adminMenuItem = this.page.getByRole('menuitem', { name: 'Admin' }); | ||||||
|     this.userInterfaceDrawerItem = this.page.getByTestId( |     this.userInterfaceDrawerItem = this.page.getByTestId( | ||||||
|       'user-interface-drawer-link' |       'user-interface-drawer-link' | ||||||
| @@ -19,9 +18,4 @@ export class AuthenticatedPage extends BasePage { | |||||||
|     this.typographyLogo = this.page.getByTestId('typography-logo'); |     this.typographyLogo = this.page.getByTestId('typography-logo'); | ||||||
|     this.customLogo = this.page.getByTestId('custom-logo'); |     this.customLogo = this.page.getByTestId('custom-logo'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async logout() { |  | ||||||
|     await this.profileMenuButton.click(); |  | ||||||
|     await this.logoutMenuItem.click(); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								packages/e2e-tests/fixtures/bullmq-helper.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								packages/e2e-tests/fixtures/bullmq-helper.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | const { expect } = require('../fixtures/index'); | ||||||
|  |  | ||||||
|  | export const expectNoDelayedJobForFlow = async (flowId, request) => { | ||||||
|  |   const token = btoa(`${process.env.BULLMQ_DASHBOARD_USERNAME}:${process.env.BULLMQ_DASHBOARD_PASSWORD}`); | ||||||
|  |   const queues = await request.get(`${process.env.BACKEND_APP_URL}/admin/queues/api/queues?activeQueue=flow&status=delayed&page=1`, { | ||||||
|  |     headers: {'Authorization': `Basic ${token}`} | ||||||
|  |   }); | ||||||
|  |   const queuesJsonResponse = await queues.json(); | ||||||
|  |   const flowQueue = queuesJsonResponse.queues.find(queue => queue.name === "flow"); | ||||||
|  |   await expect(flowQueue.jobs.find(job => job.name === `flow-${flowId}`)).toBeUndefined(); | ||||||
|  | }; | ||||||
| @@ -24,6 +24,7 @@ export class FlowEditorPage extends AuthenticatedPage { | |||||||
|     this.unpublishFlowButton = this.page.getByTestId('unpublish-flow-button'); |     this.unpublishFlowButton = this.page.getByTestId('unpublish-flow-button'); | ||||||
|     this.publishFlowButton = this.page.getByTestId('publish-flow-button'); |     this.publishFlowButton = this.page.getByTestId('publish-flow-button'); | ||||||
|     this.infoSnackbar = this.page.getByTestId('flow-cannot-edit-info-snackbar'); |     this.infoSnackbar = this.page.getByTestId('flow-cannot-edit-info-snackbar'); | ||||||
|  |     this.errorSnackbar = this.page.getByTestId('snackbar-error'); | ||||||
|     this.trigger = this.page.getByLabel('Trigger on weekends?'); |     this.trigger = this.page.getByLabel('Trigger on weekends?'); | ||||||
|     this.stepCircularLoader = this.page.getByTestId('step-circular-loader'); |     this.stepCircularLoader = this.page.getByTestId('step-circular-loader'); | ||||||
|     this.flowName = this.page.getByTestId('editableTypography'); |     this.flowName = this.page.getByTestId('editableTypography'); | ||||||
| @@ -32,16 +33,12 @@ export class FlowEditorPage extends AuthenticatedPage { | |||||||
|       .locator('input'); |       .locator('input'); | ||||||
|  |  | ||||||
|     this.flowStep = this.page.getByTestId('flow-step'); |     this.flowStep = this.page.getByTestId('flow-step'); | ||||||
|  |     this.rssFeedUrl = this.page.getByTestId('parameters.feedUrl-text'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async createWebhookTrigger(workSynchronously) { |   async createWebhookTrigger(workSynchronously) { | ||||||
|     await this.appAutocomplete.click(); |     this.chooseAppAndTrigger('Webhook', 'Catch raw webhook'); | ||||||
|     await this.page.getByRole('option', { name: 'Webhook' }).click(); |  | ||||||
|  |  | ||||||
|     await expect(this.eventAutocomplete).toBeVisible(); |  | ||||||
|     await this.eventAutocomplete.click(); |  | ||||||
|     await this.page.getByRole('option', { name: 'Catch raw webhook' }).click(); |  | ||||||
|     await this.continueButton.click(); |  | ||||||
|     await this.page |     await this.page | ||||||
|       .getByTestId('parameters.workSynchronously-autocomplete') |       .getByTestId('parameters.workSynchronously-autocomplete') | ||||||
|       .click(); |       .click(); | ||||||
| @@ -69,6 +66,19 @@ export class FlowEditorPage extends AuthenticatedPage { | |||||||
|     return await webhookUrl.inputValue(); |     return await webhookUrl.inputValue(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   async chooseAppAndTrigger(appName, triggerEvent) { | ||||||
|  |     await expect(this.appAutocomplete).toHaveCount(1); | ||||||
|  |     await this.appAutocomplete.click(); | ||||||
|  |     await this.page.getByRole('option', { name: appName }).click(); | ||||||
|  |     await expect(this.eventAutocomplete).toBeVisible(); | ||||||
|  |     await this.eventAutocomplete.click(); | ||||||
|  |     await Promise.all([ | ||||||
|  |       this.page.waitForResponse(resp => /(apps\/.*\/triggers\/.*\/substeps)/.test(resp.url()) && resp.status() === 200), | ||||||
|  |       this.page.getByRole('option', { name: triggerEvent }).click(), | ||||||
|  |     ]); | ||||||
|  |     await this.continueButton.click(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   async chooseAppAndEvent(appName, eventName) { |   async chooseAppAndEvent(appName, eventName) { | ||||||
|     await expect(this.appAutocomplete).toHaveCount(1); |     await expect(this.appAutocomplete).toHaveCount(1); | ||||||
|     await this.appAutocomplete.click(); |     await this.appAutocomplete.click(); | ||||||
| @@ -88,4 +98,10 @@ export class FlowEditorPage extends AuthenticatedPage { | |||||||
|     await expect(this.testOutput).toBeVisible(); |     await expect(this.testOutput).toBeVisible(); | ||||||
|     await this.continueButton.click(); |     await this.continueButton.click(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   async dismissErrorSnackbar() { | ||||||
|  |     await expect(this.errorSnackbar).toBeVisible(); | ||||||
|  |     await this.errorSnackbar.click(); | ||||||
|  |     await expect(this.errorSnackbar).toHaveCount(0); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ exports.test = test.extend({ | |||||||
|   userInterfacePage: async ({ page }, use) => { |   userInterfacePage: async ({ page }, use) => { | ||||||
|     await use(new UserInterfacePage(page)); |     await use(new UserInterfacePage(page)); | ||||||
|   }, |   }, | ||||||
|   ...adminFixtures, |   ...adminFixtures | ||||||
| }); | }); | ||||||
|  |  | ||||||
| exports.publicTest = test.extend({ | exports.publicTest = test.extend({ | ||||||
| @@ -49,18 +49,21 @@ exports.publicTest = test.extend({ | |||||||
|  |  | ||||||
|     await use(loginPage); |     await use(loginPage); | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   acceptInvitationPage: async ({ page }, use) => { |   acceptInvitationPage: async ({ page }, use) => { | ||||||
|     const acceptInvitationPage = new AcceptInvitation(page); |     const acceptInvitationPage = new AcceptInvitation(page); | ||||||
|     await use(acceptInvitationPage); |     await use(acceptInvitationPage); | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   adminSetupPage: async ({ page }, use) => { |   adminSetupPage: async ({ page }, use) => { | ||||||
|     const adminSetupPage = new AdminSetupPage(page); |     const adminSetupPage = new AdminSetupPage(page); | ||||||
|     await use(adminSetupPage); |     await use(adminSetupPage); | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   adminCreateUserPage: async ({page}, use) => { |   adminCreateUserPage: async ({page}, use) => { | ||||||
|     const adminCreateUserPage = new AdminCreateUserPage(page); |     const adminCreateUserPage = new AdminCreateUserPage(page); | ||||||
|     await use(adminCreateUserPage); |     await use(adminCreateUserPage); | ||||||
|   }, |   } | ||||||
| }); | }); | ||||||
|  |  | ||||||
| expect.extend({ | expect.extend({ | ||||||
|   | |||||||
| @@ -1,21 +0,0 @@ | |||||||
| const { AuthenticatedPage } = require('./authenticated-page'); |  | ||||||
|  |  | ||||||
| export class MyProfilePage extends AuthenticatedPage { |  | ||||||
|   constructor(page) { |  | ||||||
|     super(page); |  | ||||||
|  |  | ||||||
|     this.fullName = this.page.locator('[name="fullName"]'); |  | ||||||
|     this.email = this.page.locator('[name="email"]'); |  | ||||||
|     this.newPassword = this.page.locator('[name="password"]'); |  | ||||||
|     this.passwordConfirmation = this.page.locator('[name="confirmPassword"]'); |  | ||||||
|     this.updateProfileButton = this.page.getByTestId('update-profile-button'); |  | ||||||
|     this.settingsMenuItem = this.page.getByRole('menuitem', { |  | ||||||
|       name: 'Settings', |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   async navigateTo() { |  | ||||||
|     await this.profileMenuButton.click(); |  | ||||||
|     await this.settingsMenuItem.click(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										18
									
								
								packages/e2e-tests/fixtures/postgres/postgres-helper.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								packages/e2e-tests/fixtures/postgres/postgres-helper.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | const { pgPool } = require('./postgres-config'); | ||||||
|  | const { expect } = require('../../fixtures/index'); | ||||||
|  |  | ||||||
|  | export const flowShouldNotHavePublishedAtDateFilled = async (flowId) => { | ||||||
|  |   const queryFlow = { | ||||||
|  |     text: 'SELECT * FROM flows WHERE id = $1', | ||||||
|  |     values: [flowId] | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   try { | ||||||
|  |     const queryFlowResult = await pgPool.query(queryFlow); | ||||||
|  |     expect(queryFlowResult.rowCount).toEqual(1); | ||||||
|  |     expect(queryFlowResult.rows[0].published_at).toBeNull(); | ||||||
|  |   } catch (err) { | ||||||
|  |     console.error(err.message); | ||||||
|  |     throw err; | ||||||
|  |   } | ||||||
|  | }; | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| const { test, expect } = require('../../fixtures/index'); | const { test, expect } = require('../../fixtures/index'); | ||||||
| const { pgPool } = require('../../fixtures/postgres-config'); | const { pgPool } = require('../../fixtures/postgres/postgres-config'); | ||||||
|  |  | ||||||
| test.describe('Admin Applications', () => { | test.describe('Admin Applications', () => { | ||||||
|   test.beforeAll(async () => { |   test.beforeAll(async () => { | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								packages/e2e-tests/tests/flow-editor/flow-validation.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								packages/e2e-tests/tests/flow-editor/flow-validation.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | const { test, expect } = require('../../fixtures/index'); | ||||||
|  | const { expectNoDelayedJobForFlow } = require('../../fixtures/bullmq-helper'); | ||||||
|  | const { flowShouldNotHavePublishedAtDateFilled } = require('../../fixtures/postgres/postgres-helper'); | ||||||
|  |  | ||||||
|  | test.describe('Flow Validation', () => { | ||||||
|  |   test.beforeEach(async ({ page }) => { | ||||||
|  |     await page.getByTestId('create-flow-button').click(); | ||||||
|  |     await page.waitForURL( | ||||||
|  |       /\/editor\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/ | ||||||
|  |     ); | ||||||
|  |     await expect(page.getByTestId('flow-step')).toHaveCount(2); | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   test('Should not be able to publish flow without trigger', async ({ | ||||||
|  |     flowEditorPage, | ||||||
|  |     page, | ||||||
|  |     request | ||||||
|  |   }) => { | ||||||
|  |     const flowId = await page.url().split('editor/').pop(); | ||||||
|  |  | ||||||
|  |     await flowEditorPage.flowName.click(); | ||||||
|  |     await flowEditorPage.flowNameInput.fill('incompleteFlow'); | ||||||
|  |     await flowEditorPage.chooseAppAndTrigger('RSS', 'New items in feed'); | ||||||
|  |  | ||||||
|  |     await flowEditorPage.publishFlowButton.click(); | ||||||
|  |     await flowEditorPage.dismissErrorSnackbar(); | ||||||
|  |  | ||||||
|  |     await flowShouldNotHavePublishedAtDateFilled(flowId); | ||||||
|  |     await expectNoDelayedJobForFlow(flowId, request); | ||||||
|  |  | ||||||
|  |     await flowEditorPage.rssFeedUrl.fill('http://rss.cnn.com/rss/money_mostpopular.rss'); | ||||||
|  |     await expect(flowEditorPage.continueButton).toHaveCount(1); | ||||||
|  |     await flowEditorPage.continueButton.click(); | ||||||
|  |  | ||||||
|  |     await flowEditorPage.publishFlowButton.click(); | ||||||
|  |     await flowEditorPage.dismissErrorSnackbar(); | ||||||
|  |  | ||||||
|  |     await flowShouldNotHavePublishedAtDateFilled(flowId); | ||||||
|  |     await expectNoDelayedJobForFlow(flowId, request); | ||||||
|  |  | ||||||
|  |     await expect(flowEditorPage.testOutput).not.toBeVisible(); | ||||||
|  |     await flowEditorPage.testAndContinueButton.click(); | ||||||
|  |     await expect(flowEditorPage.testOutput).toBeVisible(); | ||||||
|  |     await expect(flowEditorPage.hasNoOutput).not.toBeVisible(); | ||||||
|  |     await flowEditorPage.continueButton.click(); | ||||||
|  |  | ||||||
|  |     await flowEditorPage.publishFlowButton.click(); | ||||||
|  |     await expect(page.getByTestId('snackbar-error')).toBeVisible(); | ||||||
|  |  | ||||||
|  |     await flowShouldNotHavePublishedAtDateFilled(flowId); | ||||||
|  |     await expectNoDelayedJobForFlow(flowId, request); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
| @@ -1,95 +0,0 @@ | |||||||
| const { publicTest, expect } = require('../../fixtures/index'); |  | ||||||
| const { AdminUsersPage } = require('../../fixtures/admin/users-page'); |  | ||||||
| const { MyProfilePage } = require('../../fixtures/my-profile-page'); |  | ||||||
|  |  | ||||||
| publicTest.describe('My Profile', () => { |  | ||||||
|   publicTest( |  | ||||||
|     'user should be able to change own data', |  | ||||||
|     async ({ acceptInvitationPage, adminCreateUserPage, loginPage, page }) => { |  | ||||||
|       let acceptInvitationLink; |  | ||||||
|  |  | ||||||
|       adminCreateUserPage.seed( |  | ||||||
|         Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER) |  | ||||||
|       ); |  | ||||||
|       const testUser = adminCreateUserPage.generateUser(); |  | ||||||
|  |  | ||||||
|       const adminUsersPage = new AdminUsersPage(page); |  | ||||||
|       const myProfilePage = new MyProfilePage(page); |  | ||||||
|  |  | ||||||
|       await publicTest.step('login as Admin', async () => { |  | ||||||
|         await loginPage.login(); |  | ||||||
|         await expect(loginPage.page).toHaveURL('/flows'); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('create new user', async () => { |  | ||||||
|         await adminUsersPage.navigateTo(); |  | ||||||
|         await adminUsersPage.createUserButton.click(); |  | ||||||
|         await adminCreateUserPage.fullNameInput.fill(testUser.fullName); |  | ||||||
|         await adminCreateUserPage.emailInput.fill(testUser.email); |  | ||||||
|         await adminCreateUserPage.roleInput.click(); |  | ||||||
|         await adminCreateUserPage.page |  | ||||||
|           .getByRole('option', { name: 'Admin' }) |  | ||||||
|           .click(); |  | ||||||
|         await adminCreateUserPage.createButton.click(); |  | ||||||
|         const snackbar = await adminUsersPage.getSnackbarData( |  | ||||||
|           'snackbar-create-user-success' |  | ||||||
|         ); |  | ||||||
|         await expect(snackbar.variant).toBe('success'); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('copy invitation link', async () => { |  | ||||||
|         const invitationMessage = |  | ||||||
|           await adminCreateUserPage.acceptInvitationLink; |  | ||||||
|         acceptInvitationLink = await invitationMessage.getAttribute('href'); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('logout', async () => { |  | ||||||
|         await myProfilePage.logout(); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('accept invitation', async () => { |  | ||||||
|         await page.goto(acceptInvitationLink); |  | ||||||
|         await acceptInvitationPage.acceptInvitation(process.env.LOGIN_PASSWORD); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('login as new Admin', async () => { |  | ||||||
|         await loginPage.login(testUser.email, process.env.LOGIN_PASSWORD); |  | ||||||
|         await expect(loginPage.loginButton).not.toBeVisible(); |  | ||||||
|         await expect(page).toHaveURL('/flows'); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('change own data', async () => { |  | ||||||
|         await myProfilePage.navigateTo(); |  | ||||||
|  |  | ||||||
|         await myProfilePage.fullName.fill('abecadło'); |  | ||||||
|         await myProfilePage.email.fill('a' + testUser.email); |  | ||||||
|         await myProfilePage.newPassword.fill( |  | ||||||
|           process.env.LOGIN_PASSWORD + process.env.LOGIN_PASSWORD |  | ||||||
|         ); |  | ||||||
|         await myProfilePage.passwordConfirmation.fill( |  | ||||||
|           process.env.LOGIN_PASSWORD + process.env.LOGIN_PASSWORD |  | ||||||
|         ); |  | ||||||
|         await myProfilePage.updateProfileButton.click(); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('logout', async () => { |  | ||||||
|         await myProfilePage.logout(); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('login with new credentials', async () => { |  | ||||||
|         await loginPage.login( |  | ||||||
|           'a' + testUser.email, |  | ||||||
|           process.env.LOGIN_PASSWORD + process.env.LOGIN_PASSWORD |  | ||||||
|         ); |  | ||||||
|         await expect(loginPage.loginButton).not.toBeVisible(); |  | ||||||
|         await expect(page).toHaveURL('/flows'); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       await publicTest.step('verify changed data', async () => { |  | ||||||
|         await myProfilePage.navigateTo(); |  | ||||||
|         await expect(myProfilePage.fullName).toHaveValue('abecadło'); |  | ||||||
|         await expect(myProfilePage.email).toHaveValue('a' + testUser.email); |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| }); |  | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| const { publicTest, expect } = require('../../fixtures/index'); | const { publicTest, expect } = require('../../fixtures/index'); | ||||||
| const { pgPool } = require('../../fixtures/postgres-config'); | const { pgPool } = require('../../fixtures/postgres/postgres-config'); | ||||||
| const { DateTime } = require('luxon'); | const { DateTime } = require('luxon'); | ||||||
|  |  | ||||||
| publicTest.describe('Accept invitation page', () => { | publicTest.describe('Accept invitation page', () => { | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import * as React from 'react'; | import * as React from 'react'; | ||||||
|  | import { useMutation } from '@apollo/client'; | ||||||
| import Box from '@mui/material/Box'; | import Box from '@mui/material/Box'; | ||||||
| import Collapse from '@mui/material/Collapse'; | import Collapse from '@mui/material/Collapse'; | ||||||
| import ListItem from '@mui/material/ListItem'; | import ListItem from '@mui/material/ListItem'; | ||||||
| @@ -9,19 +10,37 @@ import LoadingButton from '@mui/lab/LoadingButton'; | |||||||
|  |  | ||||||
| import { EditorContext } from 'contexts/Editor'; | import { EditorContext } from 'contexts/Editor'; | ||||||
| import useFormatMessage from 'hooks/useFormatMessage'; | import useFormatMessage from 'hooks/useFormatMessage'; | ||||||
| import useTestStep from 'hooks/useTestStep'; | import { EXECUTE_FLOW } from 'graphql/mutations/execute-flow'; | ||||||
| import JSONViewer from 'components/JSONViewer'; | import JSONViewer from 'components/JSONViewer'; | ||||||
| import WebhookUrlInfo from 'components/WebhookUrlInfo'; | import WebhookUrlInfo from 'components/WebhookUrlInfo'; | ||||||
| import FlowSubstepTitle from 'components/FlowSubstepTitle'; | import FlowSubstepTitle from 'components/FlowSubstepTitle'; | ||||||
| import { useQueryClient } from '@tanstack/react-query'; | import { useQueryClient } from '@tanstack/react-query'; | ||||||
| import { StepPropType, SubstepPropType } from 'propTypes/propTypes'; | import { StepPropType, SubstepPropType } from 'propTypes/propTypes'; | ||||||
|  |  | ||||||
|  | function serializeErrors(graphQLErrors) { | ||||||
|  |   return graphQLErrors?.map((error) => { | ||||||
|  |     try { | ||||||
|  |       return { | ||||||
|  |         ...error, | ||||||
|  |         message: ( | ||||||
|  |           <pre style={{ margin: 0, whiteSpace: 'pre-wrap' }}> | ||||||
|  |             {JSON.stringify(JSON.parse(error.message), null, 2)} | ||||||
|  |           </pre> | ||||||
|  |         ), | ||||||
|  |       }; | ||||||
|  |     } catch { | ||||||
|  |       return error; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
| function TestSubstep(props) { | function TestSubstep(props) { | ||||||
|   const { |   const { | ||||||
|     substep, |     substep, | ||||||
|     expanded = false, |     expanded = false, | ||||||
|     onExpand, |     onExpand, | ||||||
|     onCollapse, |     onCollapse, | ||||||
|  |     onSubmit, | ||||||
|     onContinue, |     onContinue, | ||||||
|     step, |     step, | ||||||
|     showWebhookUrl = false, |     showWebhookUrl = false, | ||||||
| @@ -29,21 +48,15 @@ function TestSubstep(props) { | |||||||
|   } = props; |   } = props; | ||||||
|   const formatMessage = useFormatMessage(); |   const formatMessage = useFormatMessage(); | ||||||
|   const editorContext = React.useContext(EditorContext); |   const editorContext = React.useContext(EditorContext); | ||||||
|   const { |   const [executeFlow, { data, error, loading, called, reset }] = useMutation( | ||||||
|     mutateAsync: testStep, |     EXECUTE_FLOW, | ||||||
|     isPending: isTestStepPending, |     { | ||||||
|     data, |       context: { autoSnackbar: false }, | ||||||
|     isSuccess: isCompleted, |     }, | ||||||
|     reset, |   ); | ||||||
|   } = useTestStep(step.id); |   const response = data?.executeFlow?.data; | ||||||
|   const loading = isTestStepPending; |   const isCompleted = !error && called && !loading; | ||||||
|   const lastExecutionStep = data?.data.lastExecutionStep; |   const hasNoOutput = !response && isCompleted; | ||||||
|   const dataOut = lastExecutionStep?.dataOut; |  | ||||||
|   const errorDetails = lastExecutionStep?.errorDetails; |  | ||||||
|   const hasError = errorDetails && Object.values(errorDetails).length > 0; |  | ||||||
|   const hasNoOutput = !hasError && isCompleted && !dataOut; |  | ||||||
|   const hasOutput = |  | ||||||
|     !hasError && isCompleted && dataOut && Object.values(dataOut).length > 0; |  | ||||||
|   const { name } = substep; |   const { name } = substep; | ||||||
|   const queryClient = useQueryClient(); |   const queryClient = useQueryClient(); | ||||||
|  |  | ||||||
| @@ -62,12 +75,18 @@ function TestSubstep(props) { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     await testStep(); |     await executeFlow({ | ||||||
|  |       variables: { | ||||||
|  |         input: { | ||||||
|  |           stepId: step.id, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     await queryClient.invalidateQueries({ |     await queryClient.invalidateQueries({ | ||||||
|       queryKey: ['flows', flowId], |       queryKey: ['flows', flowId], | ||||||
|     }); |     }); | ||||||
|   }, [testStep, onContinue, isCompleted, queryClient, flowId]); |   }, [onSubmit, onContinue, isCompleted, queryClient, flowId]); | ||||||
|  |  | ||||||
|   const onToggle = expanded ? onCollapse : onExpand; |   const onToggle = expanded ? onCollapse : onExpand; | ||||||
|  |  | ||||||
| @@ -83,14 +102,14 @@ function TestSubstep(props) { | |||||||
|             alignItems: 'flex-start', |             alignItems: 'flex-start', | ||||||
|           }} |           }} | ||||||
|         > |         > | ||||||
|           {hasError && ( |           {!!error?.graphQLErrors?.length && ( | ||||||
|             <Alert |             <Alert | ||||||
|               severity="error" |               severity="error" | ||||||
|               sx={{ mb: 2, fontWeight: 500, width: '100%' }} |               sx={{ mb: 2, fontWeight: 500, width: '100%' }} | ||||||
|             > |             > | ||||||
|               <pre style={{ margin: 0, whiteSpace: 'pre-wrap' }}> |               {serializeErrors(error.graphQLErrors).map((error, i) => ( | ||||||
|                 {JSON.stringify(errorDetails, null, 2)} |                 <div key={i}>{error.message}</div> | ||||||
|               </pre> |               ))} | ||||||
|             </Alert> |             </Alert> | ||||||
|           )} |           )} | ||||||
|  |  | ||||||
| @@ -114,12 +133,12 @@ function TestSubstep(props) { | |||||||
|             </Alert> |             </Alert> | ||||||
|           )} |           )} | ||||||
|  |  | ||||||
|           {hasOutput && ( |           {response && ( | ||||||
|             <Box |             <Box | ||||||
|               sx={{ maxHeight: 400, overflowY: 'auto', width: '100%' }} |               sx={{ maxHeight: 400, overflowY: 'auto', width: '100%' }} | ||||||
|               data-test="flow-test-substep-output" |               data-test="flow-test-substep-output" | ||||||
|             > |             > | ||||||
|               <JSONViewer data={dataOut} /> |               <JSONViewer data={response} /> | ||||||
|             </Box> |             </Box> | ||||||
|           )} |           )} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								packages/web/src/graphql/mutations/create-connection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								packages/web/src/graphql/mutations/create-connection.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | import { gql } from '@apollo/client'; | ||||||
|  | export const CREATE_CONNECTION = gql` | ||||||
|  |   mutation CreateConnection($input: CreateConnectionInput) { | ||||||
|  |     createConnection(input: $input) { | ||||||
|  |       id | ||||||
|  |       key | ||||||
|  |       verified | ||||||
|  |       formattedData { | ||||||
|  |         screenName | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | `; | ||||||
							
								
								
									
										12
									
								
								packages/web/src/graphql/mutations/execute-flow.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								packages/web/src/graphql/mutations/execute-flow.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | import { gql } from '@apollo/client'; | ||||||
|  | export const EXECUTE_FLOW = gql` | ||||||
|  |   mutation ExecuteFlow($input: ExecuteFlowInput) { | ||||||
|  |     executeFlow(input: $input) { | ||||||
|  |       step { | ||||||
|  |         id | ||||||
|  |         status | ||||||
|  |       } | ||||||
|  |       data | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | `; | ||||||
| @@ -1,9 +1,10 @@ | |||||||
|  | import { CREATE_CONNECTION } from './create-connection'; | ||||||
| import { UPDATE_CONNECTION } from './update-connection'; | import { UPDATE_CONNECTION } from './update-connection'; | ||||||
| import { VERIFY_CONNECTION } from './verify-connection'; | import { VERIFY_CONNECTION } from './verify-connection'; | ||||||
| import { RESET_CONNECTION } from './reset-connection'; | import { RESET_CONNECTION } from './reset-connection'; | ||||||
| import { GENERATE_AUTH_URL } from './generate-auth-url'; | import { GENERATE_AUTH_URL } from './generate-auth-url'; | ||||||
|  |  | ||||||
| const mutations = { | const mutations = { | ||||||
|  |   createConnection: CREATE_CONNECTION, | ||||||
|   updateConnection: UPDATE_CONNECTION, |   updateConnection: UPDATE_CONNECTION, | ||||||
|   verifyConnection: VERIFY_CONNECTION, |   verifyConnection: VERIFY_CONNECTION, | ||||||
|   resetConnection: RESET_CONNECTION, |   resetConnection: RESET_CONNECTION, | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ import { | |||||||
| } from 'helpers/authenticationSteps'; | } from 'helpers/authenticationSteps'; | ||||||
| import computeAuthStepVariables from 'helpers/computeAuthStepVariables'; | import computeAuthStepVariables from 'helpers/computeAuthStepVariables'; | ||||||
| import useAppAuth from './useAppAuth'; | import useAppAuth from './useAppAuth'; | ||||||
| import useCreateConnection from './useCreateConnection'; |  | ||||||
| import useFormatMessage from './useFormatMessage'; | import useFormatMessage from './useFormatMessage'; | ||||||
|  |  | ||||||
| function getSteps(auth, hasConnection, useShared) { | function getSteps(auth, hasConnection, useShared) { | ||||||
| @@ -28,7 +27,6 @@ function getSteps(auth, hasConnection, useShared) { | |||||||
| export default function useAuthenticateApp(payload) { | export default function useAuthenticateApp(payload) { | ||||||
|   const { appKey, appAuthClientId, connectionId, useShared = false } = payload; |   const { appKey, appAuthClientId, connectionId, useShared = false } = payload; | ||||||
|   const { data: auth } = useAppAuth(appKey); |   const { data: auth } = useAppAuth(appKey); | ||||||
|   const { mutateAsync: createConnection } = useCreateConnection(appKey); |  | ||||||
|   const [authenticationInProgress, setAuthenticationInProgress] = |   const [authenticationInProgress, setAuthenticationInProgress] = | ||||||
|     React.useState(false); |     React.useState(false); | ||||||
|   const formatMessage = useFormatMessage(); |   const formatMessage = useFormatMessage(); | ||||||
| @@ -67,13 +65,8 @@ export default function useAuthenticateApp(payload) { | |||||||
|           } |           } | ||||||
|  |  | ||||||
|           if (step.type === 'mutation') { |           if (step.type === 'mutation') { | ||||||
|             if (step.name === 'createConnection') { |  | ||||||
|               const stepResponse = await createConnection(variables); |  | ||||||
|               response[step.name] = stepResponse?.data; |  | ||||||
|             } else { |  | ||||||
|             const stepResponse = await processMutation(step.name, variables); |             const stepResponse = await processMutation(step.name, variables); | ||||||
|             response[step.name] = stepResponse; |             response[step.name] = stepResponse; | ||||||
|             } |  | ||||||
|           } else if (step.type === 'openWithPopup') { |           } else if (step.type === 'openWithPopup') { | ||||||
|             const stepResponse = await processPopupMessage(popup); |             const stepResponse = await processPopupMessage(popup); | ||||||
|             response[step.name] = stepResponse; |             response[step.name] = stepResponse; | ||||||
|   | |||||||
| @@ -1,26 +0,0 @@ | |||||||
| import { useMutation, useQueryClient } from '@tanstack/react-query'; |  | ||||||
|  |  | ||||||
| import api from 'helpers/api'; |  | ||||||
|  |  | ||||||
| export default function useCreateConnection(appKey) { |  | ||||||
|   const queryClient = useQueryClient(); |  | ||||||
|  |  | ||||||
|   const query = useMutation({ |  | ||||||
|     mutationFn: async ({ appAuthClientId, formattedData }) => { |  | ||||||
|       const { data } = await api.post(`/v1/apps/${appKey}/connections`, { |  | ||||||
|         appAuthClientId, |  | ||||||
|         formattedData, |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       return data; |  | ||||||
|     }, |  | ||||||
|  |  | ||||||
|     onSuccess: () => { |  | ||||||
|       queryClient.invalidateQueries({ |  | ||||||
|         queryKey: ['apps', appKey, 'connections'], |  | ||||||
|       }); |  | ||||||
|     }, |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   return query; |  | ||||||
| } |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| import { useMutation } from '@tanstack/react-query'; |  | ||||||
| import api from 'helpers/api'; |  | ||||||
|  |  | ||||||
| export default function useTestStep(stepId) { |  | ||||||
|   const query = useMutation({ |  | ||||||
|     mutationFn: async () => { |  | ||||||
|       const { data } = await api.post(`/v1/steps/${stepId}/test`); |  | ||||||
|  |  | ||||||
|       return data; |  | ||||||
|     }, |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   return query; |  | ||||||
| } |  | ||||||
| @@ -160,7 +160,6 @@ function ProfileSettings() { | |||||||
|                   variant="contained" |                   variant="contained" | ||||||
|                   type="submit" |                   type="submit" | ||||||
|                   disabled={!isDirty || !isValid || isSubmitting} |                   disabled={!isDirty || !isValid || isSubmitting} | ||||||
|                   data-test="update-profile-button" |  | ||||||
|                 > |                 > | ||||||
|                   {formatMessage('profileSettings.updateProfile')} |                   {formatMessage('profileSettings.updateProfile')} | ||||||
|                 </Button> |                 </Button> | ||||||
|   | |||||||
							
								
								
									
										177
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										177
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -3459,85 +3459,80 @@ | |||||||
|     estree-walker "^1.0.1" |     estree-walker "^1.0.1" | ||||||
|     picomatch "^2.2.2" |     picomatch "^2.2.2" | ||||||
|  |  | ||||||
| "@rollup/rollup-android-arm-eabi@4.22.4": | "@rollup/rollup-android-arm-eabi@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz#8b613b9725e8f9479d142970b106b6ae878610d5" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz#57936f50d0335e2e7bfac496d209606fa516add4" | ||||||
|   integrity sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w== |   integrity sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w== | ||||||
|  |  | ||||||
| "@rollup/rollup-android-arm64@4.22.4": | "@rollup/rollup-android-arm64@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz#654ca1049189132ff602bfcf8df14c18da1f15fb" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz#81bba83b37382a2d0e30ceced06c8d3d85138054" | ||||||
|   integrity sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA== |   integrity sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q== | ||||||
|  |  | ||||||
| "@rollup/rollup-darwin-arm64@4.22.4": | "@rollup/rollup-darwin-arm64@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz#6d241d099d1518ef0c2205d96b3fa52e0fe1954b" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz#a371bd723a5c4c4a33376da72abfc3938066842b" | ||||||
|   integrity sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q== |   integrity sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA== | ||||||
|  |  | ||||||
| "@rollup/rollup-darwin-x64@4.22.4": | "@rollup/rollup-darwin-x64@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz#42bd19d292a57ee11734c980c4650de26b457791" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz#8baf2fda277c9729125017c65651296282412886" | ||||||
|   integrity sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw== |   integrity sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-arm-gnueabihf@4.22.4": | "@rollup/rollup-linux-arm-gnueabihf@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz#f23555ee3d8fe941c5c5fd458cd22b65eb1c2232" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz#822830a8f7388d5b81d04c69415408d3bab1079b" | ||||||
|   integrity sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ== |   integrity sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-arm-musleabihf@4.22.4": | "@rollup/rollup-linux-arm64-gnu@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz#f3bbd1ae2420f5539d40ac1fde2b38da67779baa" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz#e20fbe1bd4414c7119f9e0bba8ad17a6666c8365" | ||||||
|   integrity sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg== |   integrity sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-arm64-gnu@4.22.4": | "@rollup/rollup-linux-arm64-musl@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz#7abe900120113e08a1f90afb84c7c28774054d15" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz#13f475596a62e1924f13fe1c8cf2c40e09a99b47" | ||||||
|   integrity sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw== |   integrity sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-arm64-musl@4.22.4": | "@rollup/rollup-linux-powerpc64le-gnu@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz#9e655285c8175cd44f57d6a1e8e5dedfbba1d820" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz#6a431c441420d1c510a205e08c6673355a0a2ea9" | ||||||
|   integrity sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA== |   integrity sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-powerpc64le-gnu@4.22.4": | "@rollup/rollup-linux-riscv64-gnu@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz#9a79ae6c9e9d8fe83d49e2712ecf4302db5bef5e" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz#53d9448962c3f9ed7a1672269655476ea2d67567" | ||||||
|   integrity sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg== |   integrity sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-riscv64-gnu@4.22.4": | "@rollup/rollup-linux-s390x-gnu@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz#67ac70eca4ace8e2942fabca95164e8874ab8128" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz#95f0c133b324da3e7e5c7d12855e0eb71d21a946" | ||||||
|   integrity sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA== |   integrity sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-s390x-gnu@4.22.4": | "@rollup/rollup-linux-x64-gnu@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz#9f883a7440f51a22ed7f99e1d070bd84ea5005fc" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz#820ada75c68ead1acc486e41238ca0d8f8531478" | ||||||
|   integrity sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q== |   integrity sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-x64-gnu@4.22.4": | "@rollup/rollup-linux-x64-musl@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz#70116ae6c577fe367f58559e2cffb5641a1dd9d0" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz#ca74f22e125efbe94c1148d989ef93329b464443" | ||||||
|   integrity sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg== |   integrity sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg== | ||||||
|  |  | ||||||
| "@rollup/rollup-linux-x64-musl@4.22.4": | "@rollup/rollup-win32-arm64-msvc@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz#f473f88219feb07b0b98b53a7923be716d1d182f" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz#269023332297051d037a9593dcba92c10fef726b" | ||||||
|   integrity sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g== |   integrity sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ== | ||||||
|  |  | ||||||
| "@rollup/rollup-win32-arm64-msvc@4.22.4": | "@rollup/rollup-win32-ia32-msvc@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz#4349482d17f5d1c58604d1c8900540d676f420e0" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz#d7701438daf964011fd7ca33e3f13f3ff5129e7b" | ||||||
|   integrity sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw== |   integrity sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw== | ||||||
|  |  | ||||||
| "@rollup/rollup-win32-ia32-msvc@4.22.4": | "@rollup/rollup-win32-x64-msvc@4.14.0": | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz#a6fc39a15db618040ec3c2a24c1e26cb5f4d7422" |   resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz#0bb7ac3cd1c3292db1f39afdabfd03ccea3a3d34" | ||||||
|   integrity sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g== |   integrity sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag== | ||||||
|  |  | ||||||
| "@rollup/rollup-win32-x64-msvc@4.22.4": |  | ||||||
|   version "4.22.4" |  | ||||||
|   resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz#3dd5d53e900df2a40841882c02e56f866c04d202" |  | ||||||
|   integrity sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q== |  | ||||||
|  |  | ||||||
| "@rudderstack/rudder-sdk-node@^1.1.2": | "@rudderstack/rudder-sdk-node@^1.1.2": | ||||||
|   version "1.1.2" |   version "1.1.2" | ||||||
| @@ -14754,36 +14749,42 @@ rollup-plugin-terser@^7.0.0: | |||||||
|     serialize-javascript "^4.0.0" |     serialize-javascript "^4.0.0" | ||||||
|     terser "^5.0.0" |     terser "^5.0.0" | ||||||
|  |  | ||||||
| rollup@^2.43.1, rollup@^2.79.1: | rollup@^2.43.1: | ||||||
|   version "2.79.2" |   version "2.66.0" | ||||||
|   resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.2.tgz#f150e4a5db4b121a21a747d762f701e5e9f49090" |   resolved "https://registry.npmjs.org/rollup/-/rollup-2.66.0.tgz" | ||||||
|   integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ== |   integrity sha512-L6mKOkdyP8HK5kKJXaiWG7KZDumPJjuo1P+cfyHOJPNNTK3Moe7zCH5+fy7v8pVmHXtlxorzaBjvkBMB23s98g== | ||||||
|  |   optionalDependencies: | ||||||
|  |     fsevents "~2.3.2" | ||||||
|  |  | ||||||
|  | rollup@^2.79.1: | ||||||
|  |   version "2.79.1" | ||||||
|  |   resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz" | ||||||
|  |   integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== | ||||||
|   optionalDependencies: |   optionalDependencies: | ||||||
|     fsevents "~2.3.2" |     fsevents "~2.3.2" | ||||||
|  |  | ||||||
| rollup@^4.13.0: | rollup@^4.13.0: | ||||||
|   version "4.22.4" |   version "4.14.0" | ||||||
|   resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.22.4.tgz#4135a6446671cd2a2453e1ad42a45d5973ec3a0f" |   resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.14.0.tgz#c3e2cd479f1b2358b65c1f810fa05b51603d7be8" | ||||||
|   integrity sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A== |   integrity sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@types/estree" "1.0.5" |     "@types/estree" "1.0.5" | ||||||
|   optionalDependencies: |   optionalDependencies: | ||||||
|     "@rollup/rollup-android-arm-eabi" "4.22.4" |     "@rollup/rollup-android-arm-eabi" "4.14.0" | ||||||
|     "@rollup/rollup-android-arm64" "4.22.4" |     "@rollup/rollup-android-arm64" "4.14.0" | ||||||
|     "@rollup/rollup-darwin-arm64" "4.22.4" |     "@rollup/rollup-darwin-arm64" "4.14.0" | ||||||
|     "@rollup/rollup-darwin-x64" "4.22.4" |     "@rollup/rollup-darwin-x64" "4.14.0" | ||||||
|     "@rollup/rollup-linux-arm-gnueabihf" "4.22.4" |     "@rollup/rollup-linux-arm-gnueabihf" "4.14.0" | ||||||
|     "@rollup/rollup-linux-arm-musleabihf" "4.22.4" |     "@rollup/rollup-linux-arm64-gnu" "4.14.0" | ||||||
|     "@rollup/rollup-linux-arm64-gnu" "4.22.4" |     "@rollup/rollup-linux-arm64-musl" "4.14.0" | ||||||
|     "@rollup/rollup-linux-arm64-musl" "4.22.4" |     "@rollup/rollup-linux-powerpc64le-gnu" "4.14.0" | ||||||
|     "@rollup/rollup-linux-powerpc64le-gnu" "4.22.4" |     "@rollup/rollup-linux-riscv64-gnu" "4.14.0" | ||||||
|     "@rollup/rollup-linux-riscv64-gnu" "4.22.4" |     "@rollup/rollup-linux-s390x-gnu" "4.14.0" | ||||||
|     "@rollup/rollup-linux-s390x-gnu" "4.22.4" |     "@rollup/rollup-linux-x64-gnu" "4.14.0" | ||||||
|     "@rollup/rollup-linux-x64-gnu" "4.22.4" |     "@rollup/rollup-linux-x64-musl" "4.14.0" | ||||||
|     "@rollup/rollup-linux-x64-musl" "4.22.4" |     "@rollup/rollup-win32-arm64-msvc" "4.14.0" | ||||||
|     "@rollup/rollup-win32-arm64-msvc" "4.22.4" |     "@rollup/rollup-win32-ia32-msvc" "4.14.0" | ||||||
|     "@rollup/rollup-win32-ia32-msvc" "4.22.4" |     "@rollup/rollup-win32-x64-msvc" "4.14.0" | ||||||
|     "@rollup/rollup-win32-x64-msvc" "4.22.4" |  | ||||||
|     fsevents "~2.3.2" |     fsevents "~2.3.2" | ||||||
|  |  | ||||||
| run-async@^2.4.0: | run-async@^2.4.0: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user