feat: Serve static assets of apps

This commit is contained in:
Faruk AYDIN
2021-10-19 16:29:37 +02:00
committed by Ali BARIN
parent 5a2de1de9e
commit 672cc4c60c
17 changed files with 118 additions and 23 deletions

View File

@@ -6,6 +6,7 @@ import corsOptions from './config/cors-options';
import graphQLInstance from './helpers/graphql-instance';
import logger from './helpers/logger';
import morgan from './helpers/morgan';
import appAssetsHandler from './helpers/app-assets-handler';
import errorHandler from './helpers/error-handler';
import './config/database';
import authentication from './helpers/authentication';
@@ -13,6 +14,8 @@ import authentication from './helpers/authentication';
const app = express();
const port = appConfig.port;
appAssetsHandler(app)
app.use(morgan);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" aria-label="Flickr" role="img" viewBox="0 0 512 512">
<rect width="512" height="512" rx="15%" fill="#fff"/>
<circle cx="157" cy="256" fill="#0063dc" r="79"/>
<circle cx="355" cy="256" fill="#ff0084" r="79"/>
</svg>

After

Width:  |  Height:  |  Size: 261 B

View File

@@ -1,7 +1,10 @@
{
import appInfoType from '../../types/app-info';
import appConfig from '../../config/app';
const appInfo: appInfoType = {
"name": "Flickr",
"key": "flickr",
"iconUrl": "https://automatisch.io/apps/flickr.png",
"iconUrl": `${appConfig.baseUrl}/apps/flickr/assets/favicon.svg`,
"docUrl": "https://automatisch.io/docs/flickr",
"primaryColor": "000000",
"fields": [
@@ -113,3 +116,5 @@
}
]
}
export default appInfo;

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" aria-label="Twitch" role="img" viewBox="0 0 512 512">
<rect width="512" height="512" rx="15%" fill="#fff"/>
<path d="m115 101-22 56v228h78v42h44l41-42h63l85-85v-199zm260 185-48 48h-78l-42 42v-42h-65v-204h233zm-48-100v85h-30v-85zm-78 0v85h-29v-85z" fill="#6441a4"/>
</svg>

After

Width:  |  Height:  |  Size: 316 B

View File

@@ -1,7 +1,10 @@
{
import appInfoType from '../../types/app-info';
import appConfig from '../../config/app';
const appInfo: appInfoType = {
"name": "Twitch",
"key": "twitch",
"iconUrl": "https://automatisch.io/apps/twitch.png",
"iconUrl": `${appConfig.baseUrl}/apps/twitch/assets/favicon.svg`,
"docUrl": "https://automatisch.io/docs/twitch",
"primaryColor": "6441a5",
"fields": [
@@ -43,3 +46,5 @@
}
]
}
export default appInfo;

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" aria-label="Twitter" role="img" viewBox="0 0 512 512">
<rect width="512" height="512" rx="15%" fill="#1da1f2"/>
<path fill="#fff" d="M437 152a72 72 0 01-40 12a72 72 0 0032-40a72 72 0 01-45 17a72 72 0 00-122 65a200 200 0 01-145-74a72 72 0 0022 94a72 72 0 01-32-7a72 72 0 0056 69a72 72 0 01-32 1a72 72 0 0067 50a200 200 0 01-105 29a200 200 0 00309-179a200 200 0 0035-37"/>
</svg>

After

Width:  |  Height:  |  Size: 422 B

View File

@@ -1,7 +1,10 @@
{
import appInfoType from '../../types/app-info';
import appConfig from '../../config/app';
const appInfo: appInfoType = {
"name": "Twitter",
"key": "twitter",
"iconUrl": "https://automatisch.io/apps/twitter.png",
"iconUrl": `${appConfig.baseUrl}/apps/twitter/assets/favicon.svg`,
"docUrl": "https://automatisch.io/docs/twitter",
"primaryColor": "2DAAE1",
"fields": [
@@ -113,3 +116,5 @@
}
]
}
export default appInfo;

View File

@@ -11,7 +11,9 @@ type AppConfig = {
postgresPort: number,
postgresHost: string,
postgresUsername: string,
postgresPassword: string
postgresPassword: string,
baseUrl?: string
webAppUrl?: string
}
const appConfig: AppConfig = {
@@ -27,4 +29,10 @@ const appConfig: AppConfig = {
postgresPassword: process.env.POSTGRESS_PASSWORD,
}
const webAppUrl = `${appConfig.protocol}://${appConfig.host}:${appConfig.corsPort}`;
appConfig.webAppUrl = webAppUrl;
const baseUrl = `${appConfig.protocol}://${appConfig.host}:${appConfig.port}`;
appConfig.baseUrl = baseUrl;
export default appConfig;

View File

@@ -1,7 +1,7 @@
import appConfig from './app'
const corsOptions = {
origin: `${appConfig.protocol}://${appConfig.host}:${appConfig.corsPort}`,
origin: appConfig.webAppUrl,
methods: 'POST',
credentials: true,
optionsSuccessStatus: 200,

View File

@@ -9,7 +9,7 @@ type Params = {
}
const getConnectedAppsResolver = async (params: Params, req: RequestWithCurrentUser) => {
let apps = App.findAll(params.name)
let apps = await App.findAll(params.name)
const connections = await Connection.query()
.select('connections.key')

View File

@@ -0,0 +1,15 @@
import express, { Application } from 'express';
import App from '../models/app';
const appAssetsHandler = async (app: Application) => {
const appNames = App.list;
appNames.forEach(appName => {
app.use(
`/apps/${appName}/assets/favicon.svg`,
express.static(`src/apps/${appName}/assets/favicon.svg`)
)
})
}
export default appAssetsHandler;

View File

@@ -4,22 +4,28 @@ class App {
static folderPath = __dirname + '/../apps';
static list = fs.readdirSync(this.folderPath);
static findAll(name?: string): object[] {
if(!name) return this.list.map((name) => this.findOneByName(name));
static async findAll(name?: string): Promise<object[]> {
let appList;
return this.list
.filter((app) => app.includes(name.toLowerCase()))
.map((name) => this.findOneByName(name));
if(!name) {
appList = this.list.map(async (name) => await this.findOneByName(name));
} else {
appList = this.list
.filter((app) => app.includes(name.toLowerCase()))
.map(async (name) => await this.findOneByName(name));
}
return Promise.all(appList)
}
static findOneByName(name: string): object {
const rawAppData = fs.readFileSync(this.folderPath + `/${name}/info.json`, 'utf-8');
return JSON.parse(rawAppData);
static async findOneByName(name: string): Promise<object> {
const rawAppData = (await import(`../apps/${name}/info`)).default;
return rawAppData;
}
static findOneByKey(key: string): object {
const rawAppData = fs.readFileSync(this.folderPath + `/${key}/info.json`, 'utf-8');
return JSON.parse(rawAppData);
static async findOneByKey(key: string): Promise<object> {
const rawAppData = (await import(`../apps/${key}/info`)).default;
return rawAppData;
}
}

View File

@@ -0,0 +1,14 @@
import FieldType from './field';
import AuthenticationStepType from './authentication-step';
type AppInfo = {
name: string,
key: string,
iconUrl: string,
docUrl: string,
primaryColor: string,
fields: FieldType[],
authenticationSteps?: AuthenticationStepType[]
}
export default AppInfo;

View File

@@ -0,0 +1,10 @@
type AuthenticationStepField = {
name: string,
value: string | null,
fields?: {
name: string,
value: string | null
}[]
}
export default AuthenticationStepField;

View File

@@ -0,0 +1,10 @@
import AuthenticationStepField from '../types/authentication-step-field';
type AuthenticationStep = {
step: number,
type: string,
name: string,
fields: AuthenticationStepField[];
}
export default AuthenticationStep;

View File

@@ -5,7 +5,7 @@ type Field = {
required: boolean,
readOnly: boolean,
value: string,
placeholder: string,
placeholder: string | null,
description: string,
docUrl: string,
clickToCopy: boolean

View File

@@ -7,8 +7,9 @@ type AppIconProps = {
};
export default function AppIcon(props: AppIconProps) {
const { color, name, url } = props;
const { name, url } = props;
const color = url ? 'white' : props.color
return (
<Avatar component="span" variant="square" sx={{ bgcolor: `#${color}` }} src={url} alt={name} />
);