diff --git a/package.json b/package.json index 34ec7550..3d7e38dd 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "nohoist": [ "**/babel-loader", "**/webpack", - "**/@automatisch/web" + "**/@automatisch/web", + "**/@automatisch/types" ] }, "devDependencies": { diff --git a/packages/backend/package.json b/packages/backend/package.json index f8100e48..5893599b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -18,7 +18,6 @@ "dependencies": { "@automatisch/web": "0.1.0", "@octokit/oauth-methods": "^1.2.6", - "@types/lodash.get": "^4.4.6", "axios": "0.24.0", "bcrypt": "^5.0.1", "cors": "^2.8.5", @@ -66,11 +65,13 @@ "url": "https://github.com/automatisch/automatisch/issues" }, "devDependencies": { + "@automatisch/types": "0.1.0", "@types/bcrypt": "^5.0.0", "@types/cors": "^2.8.12", "@types/crypto-js": "^4.0.2", "@types/express": "^4.17.13", "@types/http-errors": "^1.8.1", + "@types/lodash.get": "^4.4.6", "@types/morgan": "^1.9.3", "@types/node": "^16.10.2", "@types/nodemailer": "^6.4.4", diff --git a/packages/backend/src/apps/discord/authentication.ts b/packages/backend/src/apps/discord/authentication.ts index 12d39d2f..4a842a29 100644 --- a/packages/backend/src/apps/discord/authentication.ts +++ b/packages/backend/src/apps/discord/authentication.ts @@ -1,6 +1,6 @@ +import type { IField } from '@automatisch/types'; import { URLSearchParams } from 'url'; import axios, { AxiosInstance } from 'axios'; -import Field from '../../types/field'; export default class Authentication { appData: any; @@ -18,7 +18,7 @@ export default class Authentication { get oauthRedirectUrl() { return this.appData.fields.find( - (field: Field) => field.key == 'oAuthRedirectUrl' + (field: IField) => field.key == 'oAuthRedirectUrl' ).value; } diff --git a/packages/backend/src/apps/firebase/authentication.ts b/packages/backend/src/apps/firebase/authentication.ts index 31a872ea..921598ac 100644 --- a/packages/backend/src/apps/firebase/authentication.ts +++ b/packages/backend/src/apps/firebase/authentication.ts @@ -1,13 +1,15 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IField, + IJSONObject, +} from '@automatisch/types'; import { google as GoogleApi } from 'googleapis'; import { OAuth2Client } from 'google-auth-library'; -import Field from '../../types/field'; -import AppInfo from '../../types/app-info'; -import JSONObject from '../../types/interfaces/json-object'; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: OAuth2Client; scopes: string[] = [ @@ -17,7 +19,7 @@ export default class Authentication implements AuthenticationInterface { 'profile', ]; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.appData = appData; this.connectionData = connectionData; @@ -32,7 +34,7 @@ export default class Authentication implements AuthenticationInterface { get oauthRedirectUrl() { return this.appData.fields.find( - (field: Field) => field.key == 'oAuthRedirectUrl' + (field: IField) => field.key == 'oAuthRedirectUrl' ).value; } diff --git a/packages/backend/src/apps/flickr/authentication.ts b/packages/backend/src/apps/flickr/authentication.ts index 890d5d31..dbb095ac 100644 --- a/packages/backend/src/apps/flickr/authentication.ts +++ b/packages/backend/src/apps/flickr/authentication.ts @@ -1,16 +1,18 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IField, + IJSONObject, +} from '@automatisch/types'; import FlickrApi from 'flickr-sdk'; -import AppInfo from '../../types/app-info'; -import Field from '../../types/field'; -import JSONObject from '../../types/interfaces/json-object'; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: typeof FlickrApi; oauthClient: typeof FlickrApi; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.oauthClient = new FlickrApi.OAuth( connectionData.consumerKey, connectionData.consumerSecret @@ -33,7 +35,7 @@ export default class Authentication implements AuthenticationInterface { async createAuthData() { const appFields = this.appData.fields.find( - (field: Field) => field.key == 'oAuthRedirectUrl' + (field: IField) => field.key == 'oAuthRedirectUrl' ); const callbackUrl = appFields.value; diff --git a/packages/backend/src/apps/github/authentication.ts b/packages/backend/src/apps/github/authentication.ts index 23a417b8..190e54ed 100644 --- a/packages/backend/src/apps/github/authentication.ts +++ b/packages/backend/src/apps/github/authentication.ts @@ -1,16 +1,18 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IField, + IJSONObject, +} from '@automatisch/types'; import { getWebFlowAuthorizationUrl, exchangeWebFlowCode, checkToken, } from '@octokit/oauth-methods'; -import AppInfo from '../../types/app-info'; -import Field from '../../types/field'; -import JSONObject from '../../types/interfaces/json-object'; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; scopes: string[] = ['repo']; client: { getWebFlowAuthorizationUrl: typeof getWebFlowAuthorizationUrl; @@ -18,7 +20,7 @@ export default class Authentication implements AuthenticationInterface { checkToken: typeof checkToken; }; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.connectionData = connectionData; this.appData = appData; @@ -31,7 +33,7 @@ export default class Authentication implements AuthenticationInterface { get oauthRedirectUrl(): string { return this.appData.fields.find( - (field: Field) => field.key == 'oAuthRedirectUrl' + (field: IField) => field.key == 'oAuthRedirectUrl' ).value; } diff --git a/packages/backend/src/apps/postgresql/authentication.ts b/packages/backend/src/apps/postgresql/authentication.ts index a45e3543..96aab484 100644 --- a/packages/backend/src/apps/postgresql/authentication.ts +++ b/packages/backend/src/apps/postgresql/authentication.ts @@ -1,14 +1,17 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IField, + IJSONObject, +} from '@automatisch/types'; import { Client } from 'pg'; -import AppInfo from '../../types/app-info'; -import JSONObject from '../../types/interfaces/json-object'; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: Client; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.client = new Client({ host: connectionData.host as string, port: connectionData.port as number, diff --git a/packages/backend/src/apps/smtp/authentication.ts b/packages/backend/src/apps/smtp/authentication.ts index 5ade97b6..65dfd609 100644 --- a/packages/backend/src/apps/smtp/authentication.ts +++ b/packages/backend/src/apps/smtp/authentication.ts @@ -1,13 +1,16 @@ import nodemailer, { Transporter, TransportOptions } from 'nodemailer'; -import AppInfo from '../../types/app-info'; -import JSONObject from '../../types/interfaces/json-object'; +import type { + IAuthentication, + IApp, + IJSONObject, +} from '@automatisch/types'; -export default class Authentication { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: Transporter; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.client = nodemailer.createTransport({ host: connectionData.host, port: connectionData.port, diff --git a/packages/backend/src/apps/twilio/authentication.ts b/packages/backend/src/apps/twilio/authentication.ts index bff16c3a..a2b1d8ca 100644 --- a/packages/backend/src/apps/twilio/authentication.ts +++ b/packages/backend/src/apps/twilio/authentication.ts @@ -1,14 +1,16 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IJSONObject, +} from '@automatisch/types'; import TwilioApi from 'twilio'; -import AppInfo from '../../types/app-info'; -import JSONObject from '../../types/interfaces/json-object'; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: TwilioApi.Twilio; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.client = TwilioApi( connectionData.accountSid as string, connectionData.authToken as string diff --git a/packages/backend/src/apps/twitch/authentication.ts b/packages/backend/src/apps/twitch/authentication.ts index 862724b4..26780bc9 100644 --- a/packages/backend/src/apps/twitch/authentication.ts +++ b/packages/backend/src/apps/twitch/authentication.ts @@ -1,9 +1,11 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IField, + IJSONObject, +} from '@automatisch/types'; import TwitchApi, { TwitchJsOptions } from 'twitch-js'; import fetchUtil from 'twitch-js/lib/utils/fetch'; -import AppInfo from '../../types/app-info'; -import Field from '../../types/field'; -import JSONObject from '../../types/interfaces/json-object'; type TwitchTokenResponse = { accessToken: string; @@ -12,12 +14,12 @@ type TwitchTokenResponse = { tokenType: string; }; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: TwitchApi; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.connectionData = connectionData; this.appData = appData; @@ -36,7 +38,7 @@ export default class Authentication implements AuthenticationInterface { get oauthRedirectUrl() { return this.appData.fields.find( - (field: Field) => field.key == 'oAuthRedirectUrl' + (field: IField) => field.key == 'oAuthRedirectUrl' ).value; } diff --git a/packages/backend/src/apps/twitter/authentication.ts b/packages/backend/src/apps/twitter/authentication.ts index 54bab8ce..8d35ee01 100644 --- a/packages/backend/src/apps/twitter/authentication.ts +++ b/packages/backend/src/apps/twitter/authentication.ts @@ -1,15 +1,17 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IField, + IJSONObject, +} from '@automatisch/types'; import TwitterApi, { TwitterApiTokens } from 'twitter-api-v2'; -import AppInfo from '../../types/app-info'; -import Field from '../../types/field'; -import JSONObject from '../../types/interfaces/json-object'; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: TwitterApi; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.appData = appData; this.connectionData = connectionData; @@ -25,7 +27,7 @@ export default class Authentication implements AuthenticationInterface { async createAuthData() { const appFields = this.appData.fields.find( - (field: Field) => field.key == 'oAuthRedirectUrl' + (field: IField) => field.key == 'oAuthRedirectUrl' ); const callbackUrl = appFields.value; diff --git a/packages/backend/src/apps/typeform/authentication.ts b/packages/backend/src/apps/typeform/authentication.ts index f644a55d..bd0a5ee0 100644 --- a/packages/backend/src/apps/typeform/authentication.ts +++ b/packages/backend/src/apps/typeform/authentication.ts @@ -1,13 +1,15 @@ -import AuthenticationInterface from '../../types/interfaces/authentication-interface'; +import type { + IAuthentication, + IApp, + IField, + IJSONObject, +} from '@automatisch/types'; import { URLSearchParams } from 'url'; import axios, { AxiosInstance } from 'axios'; -import AppInfo from '../../types/app-info'; -import Field from '../../types/field'; -import JSONObject from '../../types/interfaces/json-object'; -export default class Authentication implements AuthenticationInterface { - appData: AppInfo; - connectionData: JSONObject; +export default class Authentication implements IAuthentication { + appData: IApp; + connectionData: IJSONObject; client: AxiosInstance = axios.create({ baseURL: 'https://api.typeform.com', }); @@ -22,14 +24,14 @@ export default class Authentication implements AuthenticationInterface { 'workspaces:read', ]; - constructor(appData: AppInfo, connectionData: JSONObject) { + constructor(appData: IApp, connectionData: IJSONObject) { this.connectionData = connectionData; this.appData = appData; } get oauthRedirectUrl() { return this.appData.fields.find( - (field: Field) => field.key == 'oAuthRedirectUrl' + (field: IField) => field.key == 'oAuthRedirectUrl' ).value; } diff --git a/packages/backend/src/graphql/mutations/create-flow.ts b/packages/backend/src/graphql/mutations/create-flow.ts index a28ac11d..81e89fc4 100644 --- a/packages/backend/src/graphql/mutations/create-flow.ts +++ b/packages/backend/src/graphql/mutations/create-flow.ts @@ -1,7 +1,6 @@ import Step from '../../models/step'; import flowType, { flowInputType } from '../types/flow'; import RequestWithCurrentUser from '../../types/express/request-with-current-user'; -import { StepType } from '../../types/step'; type Params = { input: { @@ -21,7 +20,7 @@ const createFlowResolver = async ( await Step.query().insert({ flowId: flow.id, - type: StepType.Trigger, + type: 'trigger', position: 1, appKey, }); diff --git a/packages/backend/src/graphql/mutations/create-step.ts b/packages/backend/src/graphql/mutations/create-step.ts index b00512b3..89e2a48b 100644 --- a/packages/backend/src/graphql/mutations/create-step.ts +++ b/packages/backend/src/graphql/mutations/create-step.ts @@ -1,7 +1,6 @@ import { GraphQLNonNull } from 'graphql'; import stepType, { stepInputType } from '../types/step'; import RequestWithCurrentUser from '../../types/express/request-with-current-user'; -import { StepType } from '../../types/step'; type Params = { input: { @@ -42,7 +41,7 @@ const createStepResolver = async ( const step = await flow.$relatedQuery('steps').insertAndFetch({ key: input.key, appKey: input.appKey, - type: StepType.Action, + type: 'action', position: previousStep.position + 1, parameters: {}, }); diff --git a/packages/backend/src/graphql/types/available-apps-enum-type.ts b/packages/backend/src/graphql/types/available-apps-enum-type.ts index ab21e194..a4d41361 100644 --- a/packages/backend/src/graphql/types/available-apps-enum-type.ts +++ b/packages/backend/src/graphql/types/available-apps-enum-type.ts @@ -1,11 +1,11 @@ +import type { IApp } from '@automatisch/types'; import { GraphQLEnumType } from 'graphql'; import App from '../../models/app'; -import appInfoType from '../../types/app-info' const apps = App.findAll(); const availableAppEnumValues: any = {} -apps.forEach((app: appInfoType) => { +apps.forEach((app: IApp) => { availableAppEnumValues[app.key] = { value: app.key } }) diff --git a/packages/backend/src/helpers/app-info-converter.ts b/packages/backend/src/helpers/app-info-converter.ts index e5f0806a..df736006 100644 --- a/packages/backend/src/helpers/app-info-converter.ts +++ b/packages/backend/src/helpers/app-info-converter.ts @@ -1,11 +1,11 @@ -import AppInfoType from '../types/app-info'; +import type { IApp } from '@automatisch/types'; import appConfig from '../config/app'; const appInfoConverter = (rawAppData: string) => { let computedRawData = rawAppData.replace('{BASE_URL}', appConfig.baseUrl); computedRawData = computedRawData.replace('{WEB_APP_URL}', appConfig.webAppUrl); - const computedJSONData: AppInfoType = JSON.parse(computedRawData) + const computedJSONData: IApp = JSON.parse(computedRawData) return computedJSONData; } diff --git a/packages/backend/src/models/connection.ts b/packages/backend/src/models/connection.ts index 6c1e92e4..866fd1b6 100644 --- a/packages/backend/src/models/connection.ts +++ b/packages/backend/src/models/connection.ts @@ -6,10 +6,10 @@ import User from './user'; import appConfig from '../config/app'; class Connection extends Base { - id!: number; + id!: string; key!: string; data!: any; - userId!: number; + userId!: string; verified: boolean; count: number; diff --git a/packages/backend/src/models/execution-step.ts b/packages/backend/src/models/execution-step.ts index 312c1c43..3f696c31 100644 --- a/packages/backend/src/models/execution-step.ts +++ b/packages/backend/src/models/execution-step.ts @@ -4,8 +4,8 @@ import Step from './step'; class ExecutionStep extends Base { id!: string; - executionId!: number; - stepId!: number; + executionId!: string; + stepId!: string; dataIn!: any; dataOut!: any; status: string; @@ -17,8 +17,8 @@ class ExecutionStep extends Base { properties: { id: { type: 'string' }, - executionId: { type: 'integer' }, - stepId: { type: 'integer' }, + executionId: { type: 'string' }, + stepId: { type: 'string' }, dataIn: { type: 'object' }, dataOut: { type: 'object' }, status: { type: 'string', enum: ['success', 'failure'] }, diff --git a/packages/backend/src/models/flow.ts b/packages/backend/src/models/flow.ts index 8af98b35..ee84a915 100644 --- a/packages/backend/src/models/flow.ts +++ b/packages/backend/src/models/flow.ts @@ -1,11 +1,11 @@ -import { ModelOptions, QueryContext, ValidationError } from 'objection'; +import { ValidationError } from 'objection'; import Base from './base'; import Step from './step'; class Flow extends Base { id!: string; name: string; - userId!: number; + userId!: string; active: boolean; steps?: [Step]; @@ -17,7 +17,7 @@ class Flow extends Base { properties: { id: { type: 'string' }, name: { type: 'string' }, - userId: { type: 'integer' }, + userId: { type: 'string' }, active: { type: 'boolean' }, }, }; diff --git a/packages/backend/src/models/step.ts b/packages/backend/src/models/step.ts index 0f6ea058..c8ca29e3 100644 --- a/packages/backend/src/models/step.ts +++ b/packages/backend/src/models/step.ts @@ -2,14 +2,14 @@ import Base from './base'; import Flow from './flow'; import Connection from './connection'; import ExecutionStep from './execution-step'; -import { StepType } from '../types/step'; +import type { IStep } from '@automatisch/types'; class Step extends Base { - id!: number; + id!: string; flowId!: string; key: string; appKey: string; - type!: StepType; + type!: IStep["type"]; connectionId?: string; status: string; position: number; @@ -25,7 +25,7 @@ class Step extends Base { required: ['type'], properties: { - id: { type: 'integer' }, + id: { type: 'string' }, flowId: { type: 'string' }, key: { type: ['string', 'null'] }, appKey: { type: ['string', 'null'], minLength: 1, maxLength: 255 }, diff --git a/packages/backend/src/models/user.ts b/packages/backend/src/models/user.ts index 0cfefe9b..a2c11952 100644 --- a/packages/backend/src/models/user.ts +++ b/packages/backend/src/models/user.ts @@ -6,7 +6,7 @@ import Step from './step'; import bcrypt from 'bcrypt'; class User extends Base { - id!: number; + id!: string; email!: string; password!: string; connections?: [Connection]; @@ -20,7 +20,7 @@ class User extends Base { required: ['email', 'password'], properties: { - id: { type: 'integer' }, + id: { type: 'string' }, email: { type: 'string', format: 'email', minLength: 1, maxLength: 255 }, password: { type: 'string', minLength: 1, maxLength: 255 }, }, diff --git a/packages/backend/src/services/processor.ts b/packages/backend/src/services/processor.ts index 46646563..f203ef88 100644 --- a/packages/backend/src/services/processor.ts +++ b/packages/backend/src/services/processor.ts @@ -4,7 +4,6 @@ import Flow from '../models/flow'; import Step from '../models/step'; import Execution from '../models/execution'; import ExecutionStep from '../models/execution-step'; -import { StepType } from '../types/step'; type ExecutionSteps = Record; @@ -44,7 +43,7 @@ class Processor { parameters: rawParameters = {}, id } = step; - const isTrigger = type === StepType.Trigger; + const isTrigger = type === 'trigger'; const AppClass = (await import(`../apps/${appKey}`)).default; const computedParameters = Processor.computeParameters(rawParameters, priorExecutionSteps); const appInstance = new AppClass(appData, connection.data, computedParameters); diff --git a/packages/backend/src/types/authentication-step.ts b/packages/backend/src/types/authentication-step.ts index 824405ee..d4bb9b8b 100644 --- a/packages/backend/src/types/authentication-step.ts +++ b/packages/backend/src/types/authentication-step.ts @@ -1,10 +1,10 @@ -import AuthenticationStepField from '../types/authentication-step-field'; +import type { IAuthenticationStepField } from '@automatisch/types'; type AuthenticationStep = { step: number, type: string, name: string, - fields: AuthenticationStepField[]; + fields: IAuthenticationStepField[]; } export default AuthenticationStep; diff --git a/packages/backend/src/types/interfaces/authentication-interface.ts b/packages/backend/src/types/interfaces/authentication-interface.ts index 61c75f37..092cf15e 100644 --- a/packages/backend/src/types/interfaces/authentication-interface.ts +++ b/packages/backend/src/types/interfaces/authentication-interface.ts @@ -1,9 +1,9 @@ -import appInfoType from '../../types/app-info'; +import type { IApp } from '@automatisch/types'; import JSONObject from './json-object'; export default interface AuthenticationInterface { - appData: appInfoType; - connectionData: JSONObject; + appData: IApp; + connectionData: IJSONObject; client: unknown; verifyCredentials(): Promise; isStillVerified(): Promise; diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json index 158a30ba..f6a5944d 100644 --- a/packages/backend/tsconfig.json +++ b/packages/backend/tsconfig.json @@ -9,9 +9,18 @@ "outDir": "dist", "baseUrl": ".", "paths": { - "*": ["node_modules/*", "src/types/*"] + "*": [ + "node_modules/*", + "src/types/*" + ] }, - "typeRoots": ["node_modules/@types", "./src/types", "./src/apps/*/types"] + "typeRoots": [ + "node_modules/@types", + "./src/types", + "./src/apps/*/types" + ] }, - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/packages/types/README.md b/packages/types/README.md new file mode 100644 index 00000000..0d99c26c --- /dev/null +++ b/packages/types/README.md @@ -0,0 +1,11 @@ +# `@automatisch/types` + +> TODO: description + +## Usage + +``` +const types = require('@automatisch/types'); + +// TODO: DEMONSTRATE API +``` diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts new file mode 100644 index 00000000..39a358d8 --- /dev/null +++ b/packages/types/index.d.ts @@ -0,0 +1,127 @@ +// Type definitions for automatisch + +export type IJSONValue = string | number | boolean | JSONObject | JSONArray; +export type IJSONArray = Array; +export interface IJSONObject { + [x: string]: JSONValue; +} + +export interface IConnection { + id: string; + key: string; + data: D; + userId: string; + verified: boolean; + count: number; + createdAt: string; +} + +export interface IExecutionStep { + id: string; + executionId: string; + stepId: string; + dataIn: IJSONObject; + dataOut: IJSONObject; + status: string; +} + +export interface IExecution { + id: string; + flowId: string; + testRun: boolean; + executionSteps: IExecutionStep[]; +} + +export interface IStep { + id: string; + name: string; + flowId: string; + key: string; + appKey: string; + type: 'action' | 'trigger'; + connectionId: string; + status: string; + position: number; + parameters: Record; + connection: IConnection; + flow: IFlow; + executionSteps: IExecutionStep[]; + // FIXME: remove this property once execution steps are properly exposed via queries + output: IJSONObject; +} + +export interface IFlow { + id: string; + name: string; + userId: string; + active: boolean; + steps: IStep[]; +} + +export interface IUser { + id: string; + email: string; + password: string; + connections: IConnection[]; + flows: IFlow[]; + steps: IStep[]; +} + +export interface IField { + key: string; + label: string; + type: string; + required: boolean; + readOnly: boolean; + value: string; + placeholder: string | null; + description: string; + docUrl: string; + clickToCopy: boolean; + name: string; + variables: boolean; +} + +export interface IAuthenticationStepField { + name: string; + value: string | null; + properties: { + name: string; + value: string; + }[]; +} + +export interface IAuthenticationStep { + step: number; + type: 'mutation' | 'openWithPopup'; + name: string; + arguments: IAuthenticationStepField[]; +} + +export interface IApp { + name: string; + key: string; + iconUrl: string; + docUrl: string; + primaryColor: string; + fields: IField[]; + authenticationSteps: IAuthenticationStep[]; + reconnectionSteps: IAuthenticationStep[]; + connectionCount: number; + triggers: any[]; + actions: any[]; + connections: IConnection[]; +} + +export interface IAuthentication { + appData: IApp; + connectionData: IJSONObject; + client: unknown; + verifyCredentials(): Promise; + isStillVerified(): Promise; +} + +export interface ISubstep { + name: string; + arguments: IField[]; +} diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 00000000..5d4811eb --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,17 @@ +{ + "name": "@automatisch/types", + "version": "0.1.0", + "description": "Type definitions for automatisch", + "homepage": "https://github.com/automatisch/automatisch", + "types": "./index.d.ts", + "scripts": {}, + "dependencies": {}, + "typeScriptVersion": "4.1", + "repository": { + "type": "git", + "url": "git+https://github.com/automatisch/automatisch.git" + }, + "bugs": { + "url": "https://github.com/automatisch/automatisch/issues" + } +} diff --git a/packages/web/package.json b/packages/web/package.json index 93cde33e..296709ed 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -4,6 +4,7 @@ "description": "> TODO: description", "dependencies": { "@apollo/client": "^3.4.15", + "@automatisch/types": "0.1.0", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "@mui/icons-material": "^5.0.1", diff --git a/packages/web/src/components/AddAppConnection/index.tsx b/packages/web/src/components/AddAppConnection/index.tsx index 7f2a24bc..b4be1361 100644 --- a/packages/web/src/components/AddAppConnection/index.tsx +++ b/packages/web/src/components/AddAppConnection/index.tsx @@ -10,12 +10,12 @@ import useFormatMessage from 'hooks/useFormatMessage'; import computeAuthStepVariables from 'helpers/computeAuthStepVariables'; import { processStep } from 'helpers/authenticationSteps'; import InputCreator from 'components/InputCreator'; -import type { App } from 'types/app'; +import type { IApp, IField } from '@automatisch/types'; import { Form } from './style'; type AddAppConnectionProps = { onClose: () => void; - application: App; + application: IApp; connectionId?: string; }; @@ -73,7 +73,7 @@ export default function AddAppConnection(props: AddAppConnectionProps): React.Re
- {fields?.map(field => ())} + {fields?.map((field: IField) => ())} - {data?.getApps?.map((app: App) => ( + {data?.getApps?.map((app: IApp) => ( diff --git a/packages/web/src/components/AppFlows/index.tsx b/packages/web/src/components/AppFlows/index.tsx index 6ab5884f..53057c7a 100644 --- a/packages/web/src/components/AppFlows/index.tsx +++ b/packages/web/src/components/AppFlows/index.tsx @@ -2,15 +2,15 @@ import { useQuery } from '@apollo/client'; import { GET_FLOWS } from 'graphql/queries/get-flows'; import AppFlowRow from 'components/AppFlowRow'; -import type { Flow } from 'types/flow'; +import type { IFlow } from '@automatisch/types'; export default function AppFlows(): React.ReactElement { const { data } = useQuery(GET_FLOWS); - const appFlows: Flow[] = data?.getFlows || []; + const appFlows: IFlow[] = data?.getFlows || []; return ( <> - {appFlows.map((appFlow: Flow) => ( + {appFlows.map((appFlow: IFlow) => ( ))} diff --git a/packages/web/src/components/AppRow/index.tsx b/packages/web/src/components/AppRow/index.tsx index 6a5864cf..f04f9c35 100644 --- a/packages/web/src/components/AppRow/index.tsx +++ b/packages/web/src/components/AppRow/index.tsx @@ -8,11 +8,12 @@ import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; import useFormatMessage from 'hooks/useFormatMessage'; import AppIcon from 'components/AppIcon'; import * as URLS from 'config/urls'; -import type { App } from 'types/app'; +import type { IApp } from '@automatisch/types'; + import { CardContent, Typography } from './style'; type AppRowProps = { - application: App; + application: IApp; } const countTranslation = (value: React.ReactNode) => ( diff --git a/packages/web/src/components/ChooseAccountSubstep/index.tsx b/packages/web/src/components/ChooseAccountSubstep/index.tsx index 397257e2..6453ceac 100644 --- a/packages/web/src/components/ChooseAccountSubstep/index.tsx +++ b/packages/web/src/components/ChooseAccountSubstep/index.tsx @@ -7,22 +7,21 @@ import ListItem from '@mui/material/ListItem'; import Autocomplete from '@mui/material/Autocomplete'; import FlowSubstepTitle from 'components/FlowSubstepTitle'; -import type { App, AppConnection } from 'types/app'; -import type { Step, Substep } from 'types/step'; +import type { IApp, IConnection, IStep, ISubstep, IJSONObject } from '@automatisch/types'; import { GET_APP_CONNECTIONS } from 'graphql/queries/get-app-connections'; import { TEST_CONNECTION } from 'graphql/queries/test-connection'; type ChooseAccountSubstepProps = { - substep: Substep, + substep: ISubstep, expanded?: boolean; onExpand: () => void; onCollapse: () => void; - onChange: ({ step }: { step: Step}) => void; + onChange: ({ step }: { step: IStep }) => void; onSubmit: () => void; - step: Step; + step: IStep; }; -const optionGenerator = (connection: AppConnection): { label: string; value: string; } => ({ +const optionGenerator = (connection: IConnection): { label: string; value: string; } => ({ label: connection?.data?.screenName as string ?? 'Unnamed', value: connection?.id as string, }); @@ -62,7 +61,7 @@ function ChooseAccountSubstep(props: ChooseAccountSubstepProps): React.ReactElem // intentionally no dependencies for initial test }, []); - const connectionOptions = React.useMemo(() => (data?.getApp as App)?.connections?.map((connection) => optionGenerator(connection)) || [], [data]); + const connectionOptions = React.useMemo(() => (data?.getApp as IApp)?.connections?.map((connection) => optionGenerator(connection)) || [], [data]); const { name } = substep; diff --git a/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx b/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx index 1113c5b8..6b53a0b7 100644 --- a/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx +++ b/packages/web/src/components/ChooseAppAndEventSubstep/index.tsx @@ -10,26 +10,24 @@ import Autocomplete from '@mui/material/Autocomplete'; import { GET_APPS } from 'graphql/queries/get-apps'; import FlowSubstepTitle from 'components/FlowSubstepTitle'; -import type { App } from 'types/app'; -import type { Step, Substep } from 'types/step'; -import { StepType } from 'types/step'; +import type { IApp, IStep, ISubstep } from '@automatisch/types'; type ChooseAppAndEventSubstepProps = { - substep: Substep, + substep: ISubstep, expanded?: boolean; onExpand: () => void; onCollapse: () => void; - onChange: ({ step }: { step: Step}) => void; + onChange: ({ step }: { step: IStep }) => void; onSubmit: () => void; - step: Step; + step: IStep; }; -const optionGenerator = (app: Record): { label: string; value: string; } => ({ +const optionGenerator = (app: IApp): { label: string; value: string; } => ({ label: app.name as string, value: app.key as string, }); -const getOption = (options: Record[], appKey: unknown) => options.find(app => app.value === appKey as string) || null; +const getOption = (options: Record[], appKey: IApp["key"]) => options.find(option => option.value === appKey as string) || null; function ChooseAppAndEventSubstep(props: ChooseAppAndEventSubstepProps): React.ReactElement { const { @@ -42,11 +40,11 @@ function ChooseAppAndEventSubstep(props: ChooseAppAndEventSubstepProps): React.R onChange, } = props; - const isTrigger = step.type === StepType.Trigger; + const isTrigger = step.type === 'trigger'; const { data } = useQuery(GET_APPS, { variables: { onlyWithTriggers: isTrigger }}); - const apps: App[] = data?.getApps; - const app = apps?.find((currentApp: App) => currentApp.key === step.appKey); + const apps: IApp[] = data?.getApps; + const app = apps?.find((currentApp: IApp) => currentApp.key === step.appKey); const appOptions = React.useMemo(() => apps?.map((app) => optionGenerator(app)), [apps]); const actionsOrTriggers = isTrigger ? app?.triggers : app?.actions; @@ -88,7 +86,7 @@ function ChooseAppAndEventSubstep(props: ChooseAppAndEventSubstepProps): React.R onChange({ step: { ...step, - key: null, + key: '', appKey, }, }); diff --git a/packages/web/src/components/Editor/index.tsx b/packages/web/src/components/Editor/index.tsx index d0c31dfe..2b6c242f 100644 --- a/packages/web/src/components/Editor/index.tsx +++ b/packages/web/src/components/Editor/index.tsx @@ -8,10 +8,10 @@ import { GET_FLOW } from 'graphql/queries/get-flow'; import { CREATE_STEP } from 'graphql/mutations/create-step'; import { UPDATE_STEP } from 'graphql/mutations/update-step'; import FlowStep from 'components/FlowStep'; -import type { Flow } from 'types/flow'; +import type { IFlow } from '@automatisch/types'; type EditorProps = { - flow: Flow; + flow: IFlow; }; function updateHandlerFactory(flowId: string, previousStepId: string) { diff --git a/packages/web/src/components/EditorLayout/index.tsx b/packages/web/src/components/EditorLayout/index.tsx index 43d2f664..42e08a8d 100644 --- a/packages/web/src/components/EditorLayout/index.tsx +++ b/packages/web/src/components/EditorLayout/index.tsx @@ -14,7 +14,7 @@ import Editor from 'components/Editor'; import useFormatMessage from 'hooks/useFormatMessage'; import { UPDATE_FLOW } from 'graphql/mutations/update-flow'; import { GET_FLOW } from 'graphql/queries/get-flow'; -import type { Flow } from 'types/flow'; +import type { IFlow } from '@automatisch/types'; import * as URLS from 'config/urls'; export default function EditorLayout(): React.ReactElement { @@ -22,7 +22,7 @@ export default function EditorLayout(): React.ReactElement { const formatMessage = useFormatMessage(); const [updateFlow] = useMutation(UPDATE_FLOW); const { data, loading } = useQuery(GET_FLOW, { variables: { id: flowId }}); - const flow: Flow = data?.getFlow; + const flow: IFlow = data?.getFlow; const onFlowNameUpdate = React.useCallback(async (name: string) => { await updateFlow({ diff --git a/packages/web/src/components/FlowRow/index.tsx b/packages/web/src/components/FlowRow/index.tsx index 8bc3c42a..fcfe73ee 100644 --- a/packages/web/src/components/FlowRow/index.tsx +++ b/packages/web/src/components/FlowRow/index.tsx @@ -5,12 +5,12 @@ import Box from '@mui/material/Box'; import CardActionArea from '@mui/material/CardActionArea'; import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; -import type { Flow } from 'types/flow'; +import type { IFlow } from '@automatisch/types'; import * as URLS from 'config/urls'; import { CardContent, Typography } from './style'; type FlowRowProps = { - flow: Flow; + flow: IFlow; } export default function FlowRow(props: FlowRowProps): React.ReactElement { diff --git a/packages/web/src/components/FlowStep/index.tsx b/packages/web/src/components/FlowStep/index.tsx index c4a7b856..c8f99295 100644 --- a/packages/web/src/components/FlowStep/index.tsx +++ b/packages/web/src/components/FlowStep/index.tsx @@ -10,6 +10,7 @@ import MoreHorizIcon from '@mui/icons-material/MoreHoriz'; import IconButton from '@mui/material/IconButton'; import ErrorIcon from '@mui/icons-material/Error'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import type { IApp, IField, IStep } from '@automatisch/types'; import { StepExecutionsProvider } from 'contexts/StepExecutions'; import TestSubstep from 'components/TestSubstep'; @@ -22,18 +23,15 @@ import AppIcon from 'components/AppIcon'; import { GET_APPS } from 'graphql/queries/get-apps'; import { GET_STEP_WITH_TEST_EXECUTIONS } from 'graphql/queries/get-step-with-test-executions'; import useFormatMessage from 'hooks/useFormatMessage'; -import type { App, AppFields } from 'types/app'; -import type { Step } from 'types/step'; -import { StepType } from 'types/step'; import { AppIconWrapper, AppIconStatusIconWrapper, Content, Header, Wrapper } from './style'; type FlowStepProps = { collapsed?: boolean; - step: Step; + step: IStep; index?: number; onOpen?: () => void; onClose?: () => void; - onChange: (step: Step) => void; + onChange: (step: IStep) => void; } const validIcon = ; @@ -42,9 +40,9 @@ const errorIcon = ; export default function FlowStep(props: FlowStepProps): React.ReactElement | null { const { collapsed, index, onChange } = props; const contextButtonRef = React.useRef(null); - const step: Step = props.step; + const step: IStep = props.step; const [anchorEl, setAnchorEl] = React.useState(null); - const isTrigger = step.type === StepType.Trigger; + const isTrigger = step.type === 'trigger'; const formatMessage = useFormatMessage(); const [currentSubstep, setCurrentSubstep] = React.useState(2); const { data } = useQuery(GET_APPS, { variables: { onlyWithTriggers: isTrigger }}); @@ -70,13 +68,13 @@ export default function FlowStep(props: FlowStepProps): React.ReactElement | nul } }, [collapsed, stepWithTestExecutionsCalled, getStepWithTestExecutions, step.id, isTrigger]); - const apps: App[] = data?.getApps; - const app = apps?.find((currentApp: App) => currentApp.key === step.appKey); + const apps: IApp[] = data?.getApps; + const app = apps?.find((currentApp: IApp) => currentApp.key === step.appKey); const actionsOrTriggers = isTrigger ? app?.triggers : app?.actions; const substeps = React.useMemo(() => actionsOrTriggers?.find(({ key }) => key === step.key)?.subSteps || [], [actionsOrTriggers, step?.key]); - const handleChange = React.useCallback(({ step }: { step: Step }) => { + const handleChange = React.useCallback(({ step }: { step: IStep }) => { onChange(step); }, []) @@ -85,7 +83,7 @@ export default function FlowStep(props: FlowStepProps): React.ReactElement | nul }, []); const handleSubmit = (val: any) => { - handleChange({ step: val as Step }); + handleChange({ step: val as IStep }); } if (!apps) return null; @@ -143,7 +141,7 @@ export default function FlowStep(props: FlowStepProps): React.ReactElement | nul - + - {substeps?.length > 0 && substeps.map((substep: { name: string, key: string, arguments: AppFields[] }, index: number) => ( + {substeps?.length > 0 && substeps.map((substep: { name: string, key: string, arguments: IField[] }, index: number) => ( {substep.key === 'chooseAccount' && ( void; onCollapse: () => void; - onChange: ({ step }: { step: Step }) => void; + onChange: ({ step }: { step: IStep }) => void; onSubmit: () => void; - step: Step; + step: IStep; }; -const validateSubstep = (substep: Substep, step: Step) => { +const validateSubstep = (substep: ISubstep, step: IStep) => { if (!substep) return true; - const args: AppFields[] = substep.arguments || []; + const args: IField[] = substep.arguments || []; return args.every(arg => { if (arg.required === false) { return true; } @@ -50,7 +49,7 @@ function FlowSubstep(props: FlowSubstepProps): React.ReactElement { } = substep; const formContext = useFormContext(); - const [validationStatus, setValidationStatus] = React.useState(validateSubstep(substep, formContext.getValues() as Step)); + const [validationStatus, setValidationStatus] = React.useState(validateSubstep(substep, formContext.getValues() as IStep)); const handleChangeOnBlur = React.useCallback((key: string) => { @@ -73,7 +72,7 @@ function FlowSubstep(props: FlowSubstepProps): React.ReactElement { React.useEffect(() => { function validate (step: unknown) { - const validationResult = validateSubstep(substep, step as Step); + const validationResult = validateSubstep(substep, step as IStep); setValidationStatus(validationResult); }; const subscription = formContext.watch(validate); diff --git a/packages/web/src/components/InputCreator/index.tsx b/packages/web/src/components/InputCreator/index.tsx index defaebc6..f14370d3 100644 --- a/packages/web/src/components/InputCreator/index.tsx +++ b/packages/web/src/components/InputCreator/index.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { useFormContext } from 'react-hook-form'; -import type { AppFields } from 'types/app'; +import type { IField } from '@automatisch/types'; import PowerInput from 'components/PowerInput'; import TextField from 'components/TextField'; @@ -8,7 +8,7 @@ import TextField from 'components/TextField'; type InputCreatorProps = { onChange?: React.ChangeEventHandler; onBlur?: React.FocusEventHandler; - schema: AppFields; + schema: IField; namePrefix?: string; }; diff --git a/packages/web/src/components/PowerInput/Suggestions.tsx b/packages/web/src/components/PowerInput/Suggestions.tsx index 028dd826..451344ef 100644 --- a/packages/web/src/components/PowerInput/Suggestions.tsx +++ b/packages/web/src/components/PowerInput/Suggestions.tsx @@ -10,7 +10,7 @@ import Collapse from '@mui/material/Collapse'; import Typography from '@mui/material/Typography'; import ExpandLess from '@mui/icons-material/ExpandLess'; import ExpandMore from '@mui/icons-material/ExpandMore'; -import { Step } from 'types/step'; +import type { IStep } from '@automatisch/types'; const ListItemText = styled(MuiListItemText)``; @@ -61,7 +61,7 @@ const Suggestions = (props: SuggestionsProps) => { - {data.map((option: Step, index: number) => ( + {data.map((option: IStep, index: number) => ( <> args.filter(Boolean).join(delimiter); @@ -32,10 +32,10 @@ const process = (data: any, parentKey?: any, index?: number): any[] => { }); }; -export const processStepWithExecutions = (steps: Step[]): any[] => { +export const processStepWithExecutions = (steps: IStep[]): any[] => { if (!steps) return []; - return steps.map((step: Step, index: number) => ({ + return steps.map((step: IStep, index: number) => ({ id: step.id, // TODO: replace with step.name once introduced name: `${index + 1}. ${step.appKey}`, diff --git a/packages/web/src/components/TestSubstep/index.tsx b/packages/web/src/components/TestSubstep/index.tsx index b57d9c78..d9cec8cd 100644 --- a/packages/web/src/components/TestSubstep/index.tsx +++ b/packages/web/src/components/TestSubstep/index.tsx @@ -6,17 +6,16 @@ import Button from '@mui/material/Button'; import { EXECUTE_FLOW } from 'graphql/mutations/execute-flow'; import FlowSubstepTitle from 'components/FlowSubstepTitle'; -import type { Step, Substep } from 'types/step'; -import type { AppFields } from 'types/app'; +import type { IStep, ISubstep } from '@automatisch/types'; type TestSubstepProps = { - substep: Substep, + substep: ISubstep, expanded?: boolean; onExpand: () => void; onCollapse: () => void; - onChange?: ({ step }: { step: Step }) => void; + onChange?: ({ step }: { step: IStep }) => void; onSubmit?: () => void; - step: Step; + step: IStep; }; function TestSubstep(props: TestSubstepProps): React.ReactElement { diff --git a/packages/web/src/contexts/StepExecutions.tsx b/packages/web/src/contexts/StepExecutions.tsx index 587c074d..c1ff2cb5 100644 --- a/packages/web/src/contexts/StepExecutions.tsx +++ b/packages/web/src/contexts/StepExecutions.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; -import { Step } from 'types/step'; +import type { IStep } from '@automatisch/types'; -export const StepExecutionsContext = React.createContext([]); +export const StepExecutionsContext = React.createContext([]); type StepExecutionsProviderProps = { children: React.ReactNode; - value: Step[]; + value: IStep[]; } export const StepExecutionsProvider = (props: StepExecutionsProviderProps): React.ReactElement => { diff --git a/packages/web/src/graphql/mutations/create-step.ts b/packages/web/src/graphql/mutations/create-step.ts index 5dedcb5f..88e0969b 100644 --- a/packages/web/src/graphql/mutations/create-step.ts +++ b/packages/web/src/graphql/mutations/create-step.ts @@ -8,6 +8,7 @@ export const CREATE_STEP = gql` key appKey parameters + status connection { id } diff --git a/packages/web/src/helpers/authenticationSteps.ts b/packages/web/src/helpers/authenticationSteps.ts index 28d0b762..d18ab4f4 100644 --- a/packages/web/src/helpers/authenticationSteps.ts +++ b/packages/web/src/helpers/authenticationSteps.ts @@ -1,3 +1,4 @@ +import type { IAuthenticationStep } from '@automatisch/types'; import apolloClient from 'graphql/client'; import MUTATIONS from 'graphql/mutations'; import appConfig from 'config/app'; @@ -7,14 +8,7 @@ enum AuthenticationSteps { OpenWithPopup = 'openWithPopup', } -type Step = { - name: string; - variables: Record; - process: (step: any, variables: Record) => Promise; - type: AuthenticationSteps.Mutation | AuthenticationSteps.OpenWithPopup; -}; - -const processMutation = async (step: Step, variables: Record) => { +const processMutation = async (step: IAuthenticationStep, variables: Record) => { const mutation = MUTATIONS[step.name]; const mutationResponse = await apolloClient.mutate({ mutation, variables }); const responseData = mutationResponse.data[step.name]; @@ -38,7 +32,7 @@ function getObjectOfEntries(iterator: any) { return result; } -const processOpenWithPopup = (step: Step, variables: Record) => { +const processOpenWithPopup = (step: IAuthenticationStep, variables: Record) => { return new Promise((resolve) => { const windowFeatures = 'toolbar=no, titlebar=no, menubar=no, width=500, height=700, top=100, left=100'; const url = variables.url; @@ -62,7 +56,7 @@ const processOpenWithPopup = (step: Step, variables: Record) => }); }; -export const processStep = async (step: Step, variables: Record): Promise => { +export const processStep = async (step: IAuthenticationStep, variables: Record): Promise => { if (step.type === AuthenticationSteps.Mutation) { return processMutation(step, variables); } else if (step.type === AuthenticationSteps.OpenWithPopup) { diff --git a/packages/web/src/helpers/computeAuthStepVariables.ts b/packages/web/src/helpers/computeAuthStepVariables.ts index 4d9f500d..9d572e21 100644 --- a/packages/web/src/helpers/computeAuthStepVariables.ts +++ b/packages/web/src/helpers/computeAuthStepVariables.ts @@ -1,4 +1,5 @@ import template from 'lodash.template'; +import type { IAuthenticationStepField, IJSONObject } from '@automatisch/types'; const interpolate = /{([\s\S]+?)}/g; @@ -6,18 +7,9 @@ type Variables = { [key: string]: any } -type VariableSchema = { - properties: VariableSchema[]; - name: string; - type: 'string' | 'integer'; - value: string; -} +type IVariable = Omit & Partial>; -type AggregatedData = { - [key: string]: Record | string; -} - -const computeAuthStepVariables = (variableSchema: VariableSchema[], aggregatedData: AggregatedData): Variables => { +const computeAuthStepVariables = (variableSchema: IVariable[], aggregatedData: IJSONObject): IJSONObject => { const variables: Variables = {}; for (const variable of variableSchema) { @@ -27,11 +19,9 @@ const computeAuthStepVariables = (variableSchema: VariableSchema[], aggregatedDa continue; } - const computedVariable = template(variable.value, { interpolate })(aggregatedData); + if (variable.value) { + const computedVariable = template(variable.value, { interpolate })(aggregatedData); - if (variable.type === 'integer') { - variables[variable.name] = parseInt(computedVariable, 10); - } else { variables[variable.name] = computedVariable; } } diff --git a/packages/web/src/pages/Applications/index.tsx b/packages/web/src/pages/Applications/index.tsx index 96c9cd9f..a30fd32d 100644 --- a/packages/web/src/pages/Applications/index.tsx +++ b/packages/web/src/pages/Applications/index.tsx @@ -5,6 +5,7 @@ import { useQuery } from '@apollo/client'; import Box from '@mui/material/Box'; import Grid from '@mui/material/Grid'; import AddIcon from '@mui/icons-material/Add'; +import type { IApp } from '@automatisch/types'; import ConditionalIconButton from 'components/ConditionalIconButton'; import Container from 'components/Container'; @@ -15,7 +16,6 @@ import SearchInput from 'components/SearchInput'; import useFormatMessage from 'hooks/useFormatMessage' import { GET_CONNECTED_APPS } from 'graphql/queries/get-connected-apps'; import * as URLS from 'config/urls'; -import type { App } from 'types/app'; export default function Applications(): React.ReactElement { const navigate = useNavigate(); @@ -69,7 +69,7 @@ export default function Applications(): React.ReactElement { - {data?.getConnectedApps?.map((app: App) => ( + {data?.getConnectedApps?.map((app: IApp) => ( ))} diff --git a/packages/web/src/pages/Flows/index.tsx b/packages/web/src/pages/Flows/index.tsx index 35ae2039..75bbc56e 100644 --- a/packages/web/src/pages/Flows/index.tsx +++ b/packages/web/src/pages/Flows/index.tsx @@ -5,6 +5,7 @@ import { useQuery } from '@apollo/client'; import Box from '@mui/material/Box'; import Grid from '@mui/material/Grid'; import AddIcon from '@mui/icons-material/Add'; +import type { IFlow } from '@automatisch/types'; import FlowRow from 'components/FlowRow'; import ConditionalIconButton from 'components/ConditionalIconButton'; @@ -14,14 +15,13 @@ import SearchInput from 'components/SearchInput'; import useFormatMessage from 'hooks/useFormatMessage' import { GET_FLOWS } from 'graphql/queries/get-flows'; import * as URLS from 'config/urls'; -import type { Flow } from 'types/flow'; export default function Flows(): React.ReactElement { const formatMessage = useFormatMessage(); const [flowName, setFlowName] = React.useState(''); const { data } = useQuery(GET_FLOWS); - const flows: Flow[] = data?.getFlows?.filter((flow: Flow) => flow.name?.toLowerCase().includes(flowName.toLowerCase())); + const flows: IFlow[] = data?.getFlows?.filter((flow: IFlow) => flow.name?.toLowerCase().includes(flowName.toLowerCase())); const onSearchChange = React.useCallback((event) => { setFlowName(event.target.value); diff --git a/packages/web/src/types/app.ts b/packages/web/src/types/app.ts deleted file mode 100644 index 98a3a88f..00000000 --- a/packages/web/src/types/app.ts +++ /dev/null @@ -1,40 +0,0 @@ -type AppFields = { - key: string; - name: string; - label: string; - type: string; - required: boolean; - readOnly: boolean; - value: string; - description: string; - docUrl: string; - clickToCopy: boolean; - variables?: boolean; -}; - -type AppConnection = { - id: string; - key: string; - verified: boolean; - createdAt: string; - data: { - [key: string]: any; - }; -}; - -type App = { - key: string; - name: string; - connectionCount: number; - iconUrl: string; - docUrl: string; - primaryColor: string; - fields: AppFields[]; - authenticationSteps: any[]; - reconnectionSteps: any[]; - triggers: any[]; - actions: any[]; - connections: AppConnection[]; -}; - -export type { App, AppFields, AppConnection }; diff --git a/packages/web/src/types/connection.ts b/packages/web/src/types/connection.ts index 4114f58b..a2c12e54 100644 --- a/packages/web/src/types/connection.ts +++ b/packages/web/src/types/connection.ts @@ -1,13 +1,3 @@ -type ConnectionData = { - screenName: string; -} +import type { IConnection, IJSONObject } from '@automatisch/types'; -type Connection = { - id: string; - key: string; - data: ConnectionData; - verified?: boolean; - createdAt: string; -}; - -export type { Connection, ConnectionData }; +export type Connection = IConnection; diff --git a/packages/web/src/types/flow.ts b/packages/web/src/types/flow.ts deleted file mode 100644 index 32d6770c..00000000 --- a/packages/web/src/types/flow.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Step } from './step'; - -export type Flow = { - id: string; - name: string; - steps: Step[]; - active: boolean; -}; diff --git a/packages/web/src/types/step.ts b/packages/web/src/types/step.ts deleted file mode 100644 index a0921326..00000000 --- a/packages/web/src/types/step.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { AppFields } from './app'; -import type { Connection } from './connection'; - -export enum StepType { - Trigger = 'trigger', - Action = 'action', -} - -export type Step = { - id: string; - key: string | null; - name: string; - appKey: string | null; - type: StepType; - previousStepId: string | null; - parameters: Record; - connection: Pick; - status: 'completed' | 'incomplete'; - output: Record; -}; - -export type Substep = { - name: string; - arguments: AppFields[]; -};