Merge branch 'main' into issue-553

This commit is contained in:
Ali BARIN
2022-10-08 15:03:51 +02:00
committed by GitHub
122 changed files with 14036 additions and 3174 deletions

View File

@@ -1,11 +1,9 @@
import express, { Application } from 'express';
import App from '../models/app';
const appAssetsHandler = async (app: Application) => {
const appNames = App.list;
appNames.forEach(appName => {
const svgPath = `${__dirname}/../apps/${appName}/assets/favicon.svg`;
app.use('/apps/:appKey/assets/favicon.svg', (req, res, next) => {
const { appKey } = req.params;
const svgPath = `${__dirname}/../apps/${appKey}/assets/favicon.svg`;
const staticFileHandlerOptions = {
/**
* Disabling fallthrough is important to respond with HTTP 404.
@@ -15,11 +13,8 @@ const appAssetsHandler = async (app: Application) => {
};
const staticFileHandler = express.static(svgPath, staticFileHandlerOptions);
app.use(
`/apps/${appName}/assets/favicon.svg`,
staticFileHandler
)
})
}
return staticFileHandler(req, res, next);
});
};
export default appAssetsHandler;

View File

@@ -1,12 +1,22 @@
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 appInfoConverter = (rawAppData: IApp) => {
rawAppData.iconUrl = rawAppData.iconUrl.replace(
'{BASE_URL}',
appConfig.baseUrl
);
const computedJSONData: IApp = JSON.parse(computedRawData)
return computedJSONData;
}
if (rawAppData.auth?.fields) {
rawAppData.auth.fields = rawAppData.auth.fields.map((field) => {
return {
...field,
value: field.value?.replace('{WEB_APP_URL}', appConfig.webAppUrl),
};
});
}
return rawAppData;
};
export default appInfoConverter;

View File

@@ -0,0 +1,78 @@
import fs from 'fs';
import { join } from 'path';
import { IApp, IAuth, IAction, ITrigger, IData } from '@automatisch/types';
const appsPath = join(__dirname, '../apps');
async function getDefaultExport(path: string) {
return (await import(path)).default;
}
function stripFunctions<C>(data: C): C {
return JSON.parse(JSON.stringify(data));
}
async function getFileContent<C>(
path: string,
stripFuncs: boolean
): Promise<C> {
try {
const fileContent = await getDefaultExport(path);
if (stripFuncs) {
return stripFunctions(fileContent);
}
return fileContent;
} catch (err) {
return null;
}
}
async function getChildrenContentInDirectory<C>(
path: string,
stripFuncs: boolean
): Promise<C[]> {
const appSubdirectory = join(appsPath, path);
const childrenContent = [];
if (fs.existsSync(appSubdirectory)) {
const filesInSubdirectory = fs.readdirSync(appSubdirectory);
for (const filename of filesInSubdirectory) {
const filePath = join(appSubdirectory, filename);
const fileContent = await getFileContent<C>(filePath, stripFuncs);
childrenContent.push(fileContent);
}
return childrenContent;
}
return [];
}
const getApp = async (appKey: string, stripFuncs = true) => {
const appData: IApp = await getDefaultExport(`../apps/${appKey}`);
appData.auth = await getFileContent<IAuth>(
`../apps/${appKey}/auth`,
stripFuncs
);
appData.triggers = await getChildrenContentInDirectory<ITrigger>(
`${appKey}/triggers`,
stripFuncs
);
appData.actions = await getChildrenContentInDirectory<IAction>(
`${appKey}/actions`,
stripFuncs
);
appData.data = await getChildrenContentInDirectory<IData>(
`${appKey}/data`,
stripFuncs
);
return appData;
};
export default getApp;

View File

@@ -0,0 +1,44 @@
import createHttpClient from './http-client';
import Connection from '../models/connection';
import Flow from '../models/flow';
import Step from '../models/step';
import { IJSONObject, IApp, IGlobalVariable } from '@automatisch/types';
const globalVariable = async (
connection: Connection,
appData: IApp,
flow?: Flow,
currentStep?: Step
): Promise<IGlobalVariable> => {
const lastInternalId = await flow?.lastInternalId();
return {
auth: {
set: async (args: IJSONObject) => {
if (connection) {
await connection.$query().patchAndFetch({
formattedData: {
...connection.formattedData,
...args,
},
});
}
return null;
},
data: connection?.formattedData,
},
app: appData,
http: createHttpClient({ baseURL: appData.baseUrl }),
db: {
flow: {
lastInternalId,
},
step: {
parameters: currentStep?.parameters || {},
},
},
};
};
export default globalVariable;

View File

@@ -1,34 +1,19 @@
import axios, { AxiosInstance, AxiosResponse } from 'axios';
import { IJSONObject, IHttpClientParams } from '@automatisch/types';
import axios from 'axios';
export { AxiosInstance as IHttpClient } from 'axios';
import { IHttpClientParams } from '@automatisch/types';
type ExtendedAxiosResponse = AxiosResponse & { integrationError: IJSONObject };
export default function createHttpClient({ baseURL }: IHttpClientParams) {
const instance = axios.create({
baseURL,
});
export default class HttpClient {
instance: AxiosInstance;
instance.interceptors.response.use(
(response) => response,
(error) => {
error.response.integrationError = error.response.data;
return error.response;
}
);
constructor(params: IHttpClientParams) {
this.instance = axios.create({
baseURL: params.baseURL,
});
this.instance.interceptors.response.use(
(response) => response,
(error) => {
error.response.integrationError = error.response.data;
return error.response;
}
);
}
async get(path: string, options?: IJSONObject) {
return (await this.instance.get(path, options)) as ExtendedAxiosResponse;
}
async post(path: string, body: IJSONObject | string, options?: IJSONObject) {
return (await this.instance.post(
path,
body,
options
)) as ExtendedAxiosResponse;
}
return instance;
}