Merge branch 'main' into issue-553
This commit is contained in:
@@ -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;
|
||||
|
@@ -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;
|
||||
|
78
packages/backend/src/helpers/get-app.ts
Normal file
78
packages/backend/src/helpers/get-app.ts
Normal 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;
|
44
packages/backend/src/helpers/global-variable.ts
Normal file
44
packages/backend/src/helpers/global-variable.ts
Normal 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;
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user