tachybase_todo/packages/plugins/@nocobase/plugin-collection-manager/src/server/resourcers/sql.ts
YANG QIA 8633ec3735
refactor(logger): improve logger format (#2664)
* refactor(logger): improve logger format

* chore: improve log format

* feat(logger): plugin-logger

* feat: allow to download log files, close T-1917

* chore: update yarn.lock

* chore: improve log format

* fix: add maxsize params

* chore: add userId field to request

* chore: remove userId from request

* chore: change userId in response

* chore: change action in response

* chore: add database logger

* fix: build

* fix: test

* chore: solve conflicts

* fix: escape delimiter in message

* refactor: improve create logger api

* chore: update app logger options

* chore: remove colorize for json

* fix: bug of data2tree

* fix: test

* chore: log

* chore: remove GITHUB_ACTION check

* fix: bug

* chore: change version

* fix: transports

* fix: mockServer

* chore: use new plugin settings api

* fix: version

* fix: build

* feat: support logfmt

* fix: build

* fix: build

* fix: test

* chore: update config

* fix: test

* fix: bug

* fix: test

* fix: format

* chore: update path

* fix: build

* fix: bug

* chore: update comment

* fix: allow to custom format

* fix: package.json

* fix: version

* fix: bug
2023-12-27 13:56:13 +08:00

97 lines
3.1 KiB
TypeScript

import { Context, Next } from '@nocobase/actions';
import { SQLModel, SqlCollection } from '@nocobase/database';
import { CollectionModel } from '../models';
const updateCollection = async (ctx: Context, transaction: any) => {
const { filterByTk, values } = ctx.action.params;
const repo = ctx.db.getRepository('collections');
const collection: CollectionModel = await repo.findOne({
filter: {
name: filterByTk,
},
transaction,
});
const existFields = await collection.getFields({ transaction });
const deletedFields = existFields.filter((field: any) => !values.fields?.find((f: any) => f.name === field.name));
for (const field of deletedFields) {
await field.destroy({ transaction });
}
const upRes = await repo.update({
filterByTk,
values,
updateAssociationValues: ['fields'],
transaction,
});
return { collection, upRes };
};
export default {
name: 'sqlCollection',
actions: {
execute: async (ctx: Context, next: Next) => {
let {
values: { sql },
} = ctx.action.params;
sql = sql.trim().split(';').shift();
if (!sql) {
ctx.throw(400, ctx.t('SQL is empty'));
}
if (!/^select/i.test(sql) && !/^with([\s\S]+)select([\s\S]+)/i.test(sql)) {
ctx.throw(400, ctx.t('Only select query allowed'));
}
const tmpCollection = new SqlCollection({ name: 'tmp', sql }, { database: ctx.db });
const model = tmpCollection.model as typeof SQLModel;
// The result is for preview only, add limit clause to avoid too many results
const data = await model.findAll({ attributes: ['*'], limit: 5, raw: true });
let fields: {
[field: string]: {
type: string;
source: string;
collection: string;
interface: string;
};
} = {};
try {
fields = model.inferFields();
} catch (err) {
ctx.logger.warn(`resource: sql-collection, action: execute, error: ${err}`);
fields = {};
}
const sources = Array.from(new Set(Object.values(fields).map((field) => field.collection)));
ctx.body = { data, fields, sources };
await next();
},
setFields: async (ctx: Context, next: Next) => {
const transaction = await ctx.app.db.sequelize.transaction();
try {
const {
upRes: [collection],
} = await updateCollection(ctx, transaction);
await collection.loadFields({
transaction,
});
await transaction.commit();
} catch (e) {
await transaction.rollback();
throw e;
}
await next();
},
update: async (ctx: Context, next: Next) => {
const transaction = await ctx.app.db.sequelize.transaction();
try {
const { upRes } = await updateCollection(ctx, transaction);
const [collection] = upRes;
await (collection as CollectionModel).load({ transaction, resetFields: true });
await transaction.commit();
ctx.body = upRes;
} catch (e) {
await transaction.rollback();
throw e;
}
await next();
},
},
};