feat: save single html and update redis
This commit is contained in:
parent
c6539439e9
commit
e032c092d9
@ -66,6 +66,7 @@ app
|
|||||||
const newData = { ...app.data, ...data };
|
const newData = { ...app.data, ...data };
|
||||||
const newApp = await app.update({ data: newData, ...rest });
|
const newApp = await app.update({ data: newData, ...rest });
|
||||||
ctx.body = newApp;
|
ctx.body = newApp;
|
||||||
|
setExpire(newApp.id, tokenUser.username);
|
||||||
} else {
|
} else {
|
||||||
throw new CustomError('app not found');
|
throw new CustomError('app not found');
|
||||||
}
|
}
|
||||||
@ -177,7 +178,7 @@ app
|
|||||||
const dataFiles = app.data.files || [];
|
const dataFiles = app.data.files || [];
|
||||||
const newFiles = _.uniqBy([...dataFiles, ...files], 'name');
|
const newFiles = _.uniqBy([...dataFiles, ...files], 'name');
|
||||||
const res = await app.update({ data: { ...app.data, files: newFiles } });
|
const res = await app.update({ data: { ...app.data, files: newFiles } });
|
||||||
|
setExpire(app.id, 'test');
|
||||||
ctx.body = prefixFix(res, tokenUser.username);
|
ctx.body = prefixFix(res, tokenUser.username);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('update error', e);
|
console.log('update error', e);
|
||||||
|
@ -5,7 +5,7 @@ import { AppData, AppType, AppStatus } from './app.ts';
|
|||||||
export type AppList = Partial<InstanceType<typeof AppListModel>>;
|
export type AppList = Partial<InstanceType<typeof AppListModel>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* APP List 管理
|
* APP List 管理 历史版本管理
|
||||||
*/
|
*/
|
||||||
export class AppListModel extends Model {
|
export class AppListModel extends Model {
|
||||||
declare id: string;
|
declare id: string;
|
||||||
|
@ -46,28 +46,28 @@ const add = app.route({
|
|||||||
add.run = async (ctx) => {
|
add.run = async (ctx) => {
|
||||||
const tokenUser = ctx.state.tokenUser;
|
const tokenUser = ctx.state.tokenUser;
|
||||||
const data = ctx.query.data;
|
const data = ctx.query.data;
|
||||||
|
|
||||||
const _data: Container = {
|
|
||||||
title: '',
|
|
||||||
description: '',
|
|
||||||
code: '',
|
|
||||||
type: '',
|
|
||||||
};
|
|
||||||
const container = {
|
const container = {
|
||||||
..._data,
|
|
||||||
...data,
|
...data,
|
||||||
};
|
};
|
||||||
let containerModel: any = null;
|
let containerModel: any = null;
|
||||||
if (container.id) {
|
if (container.id) {
|
||||||
containerModel = await ContainerModel.findByPk(container.id);
|
containerModel = await ContainerModel.findByPk(container.id);
|
||||||
if (containerModel) {
|
if (containerModel) {
|
||||||
containerModel.update(container);
|
containerModel.update({
|
||||||
await containerModel.save();
|
...container,
|
||||||
ctx.emit?.('pageEdit', {
|
publish: {
|
||||||
source: 'container',
|
...containerModel.publish,
|
||||||
data: containerModel.toJSON(),
|
...container.publish,
|
||||||
operation: 'edit',
|
},
|
||||||
});
|
});
|
||||||
|
await containerModel.save();
|
||||||
|
if (containerModel.code || containerModel.source || containerModel.sourceType) {
|
||||||
|
ctx.emit?.('pageEdit', {
|
||||||
|
source: 'container',
|
||||||
|
data: containerModel.toJSON(),
|
||||||
|
operation: 'edit',
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -123,7 +123,7 @@ app
|
|||||||
}
|
}
|
||||||
container.publish = publish;
|
container.publish = publish;
|
||||||
await container.save();
|
await container.save();
|
||||||
const { title, description, key, version, fileName } = publish;
|
const { title, description, key, version, fileName, saveHTML } = publish;
|
||||||
ctx.body = container;
|
ctx.body = container;
|
||||||
if (!key || !version || !fileName) {
|
if (!key || !version || !fileName) {
|
||||||
return;
|
return;
|
||||||
@ -134,6 +134,7 @@ app
|
|||||||
version: version,
|
version: version,
|
||||||
code: container.code,
|
code: container.code,
|
||||||
filePath: fileName,
|
filePath: fileName,
|
||||||
|
saveHTML
|
||||||
});
|
});
|
||||||
await ctx.call({
|
await ctx.call({
|
||||||
path: 'app',
|
path: 'app',
|
||||||
@ -143,7 +144,7 @@ app
|
|||||||
data: {
|
data: {
|
||||||
appKey: key,
|
appKey: key,
|
||||||
version,
|
version,
|
||||||
files: [uploadResult],
|
files: uploadResult,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,7 @@ import { Op } from 'sequelize';
|
|||||||
import { getContainerData } from './get-container.ts';
|
import { getContainerData } from './get-container.ts';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { getHTML, getDataJs } from './file-template.ts';
|
import { getHTML, getDataJs, getOneHTML } from './file-template.ts';
|
||||||
import { minioClient } from '@/app.ts';
|
import { minioClient } from '@/app.ts';
|
||||||
import { bucketName } from '@/modules/minio.ts';
|
import { bucketName } from '@/modules/minio.ts';
|
||||||
import { getContentType } from '@/utils/get-content-type.ts';
|
import { getContentType } from '@/utils/get-content-type.ts';
|
||||||
@ -65,24 +65,43 @@ export const cachePage = async (page: PageModel, opts: { tokenUser: any; key; ve
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
export const uploadMinioContainer = async ({ tokenUser, key, version, code, filePath }) => {
|
export const uploadMinioContainer = async ({ tokenUser, key, version, code, filePath, saveHTML }) => {
|
||||||
if ((filePath as string).includes('..')) {
|
if ((filePath as string).includes('..')) {
|
||||||
throw new CustomError('file path is invalid');
|
throw new CustomError('file path is invalid');
|
||||||
}
|
}
|
||||||
|
const uploadFiles = [];
|
||||||
const minioKeyVersion = `${tokenUser.username}/${key}/${version}`;
|
const minioKeyVersion = `${tokenUser.username}/${key}/${version}`;
|
||||||
const minioPath = path.join(minioKeyVersion, filePath);
|
const minioPath = path.join(minioKeyVersion, filePath);
|
||||||
|
const minioFileName = path.basename(minioPath);
|
||||||
|
if (!minioFileName.endsWith('.js')) {
|
||||||
|
saveHTML = false;
|
||||||
|
}
|
||||||
console.log('minioPath', minioPath);
|
console.log('minioPath', minioPath);
|
||||||
// const isHTML = filePath.endsWith('.html');
|
// const isHTML = filePath.endsWith('.html');
|
||||||
const name = minioPath.replace(minioKeyVersion + '/', '');
|
const name = minioPath.replace(minioKeyVersion + '/', '');
|
||||||
await minioClient.putObject(bucketName, minioPath, code, code.length, {
|
await minioClient.putObject(bucketName, minioPath, code, code.length, {
|
||||||
'Content-Type': getContentType(filePath),
|
'Content-Type': getContentType(filePath),
|
||||||
'app-source': 'user-app',
|
'app-source': 'user-app',
|
||||||
'Cache-Control': 'no-cache', // 缓存一年
|
'Cache-Control': 'no-cache', // no-cache
|
||||||
});
|
});
|
||||||
return {
|
uploadFiles.push({
|
||||||
name,
|
name,
|
||||||
path: minioPath,
|
path: minioPath,
|
||||||
};
|
});
|
||||||
|
if (saveHTML) {
|
||||||
|
const htmlPath = minioPath.replace('.js', '.html');
|
||||||
|
const code = getOneHTML({ title: 'Kevisual', file: minioFileName.replace('.js', '') });
|
||||||
|
await minioClient.putObject(bucketName, htmlPath, code, code.length, {
|
||||||
|
'Content-Type': 'text/html',
|
||||||
|
'app-source': 'user-app',
|
||||||
|
'Cache-Control': 'max-age=31536000, immutable',
|
||||||
|
});
|
||||||
|
uploadFiles.push({
|
||||||
|
name: 'index.html',
|
||||||
|
path: htmlPath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return uploadFiles;
|
||||||
};
|
};
|
||||||
export const uploadMinio = async ({ tokenUser, key, version, path, filePath }) => {
|
export const uploadMinio = async ({ tokenUser, key, version, path, filePath }) => {
|
||||||
const minioPath = `${tokenUser.username}/${key}/${version}/${path}`;
|
const minioPath = `${tokenUser.username}/${key}/${version}/${path}`;
|
||||||
|
@ -3,6 +3,11 @@ type HTMLOptions = {
|
|||||||
rootId: string;
|
rootId: string;
|
||||||
dataKey?: string;
|
dataKey?: string;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* data list
|
||||||
|
* @param opts
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export const getHTML = (opts: HTMLOptions) => {
|
export const getHTML = (opts: HTMLOptions) => {
|
||||||
return `<!DOCTYPE html>
|
return `<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
@ -45,3 +50,51 @@ export const getHTML = (opts: HTMLOptions) => {
|
|||||||
export const getDataJs = (result: any) => {
|
export const getDataJs = (result: any) => {
|
||||||
return 'export const data=' + JSON.stringify(result);
|
return 'export const data=' + JSON.stringify(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type OneHTMLOptions = {
|
||||||
|
title?: string;
|
||||||
|
file: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* one data
|
||||||
|
* @param opts
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getOneHTML = (opts: OneHTMLOptions) => {
|
||||||
|
return `<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="icon" href="https://envision.xiongxiao.me/resources/root/avatar.png"/>
|
||||||
|
<title>${opts.title || 'Kevisual'}</title>
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module">
|
||||||
|
import { ContainerOne } from 'https://kevisual.xiongxiao.me/system/lib/container.js'
|
||||||
|
import { render, unmount } from './${opts.file}.js'
|
||||||
|
const container = new ContainerOne({
|
||||||
|
root: '#root',
|
||||||
|
});
|
||||||
|
container.renderOne({
|
||||||
|
code: {render, unmount}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>`;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user