'use strict'; const { hasOwn, toInt, parsePagination, ensureCreatedBy } = require('./helpers'); const dataease = require('./dataease'); const { getDataSourceTables: getDataSourceTablesPayload, getDataSourceTableColumns: getDataSourceTableColumnsPayload, previewDataSourceQuery: previewDataSourceQueryPayload, } = require('./dataSourceQuery'); const normalizeDataSourceType = value => String(value || '').trim().toLowerCase(); module.exports.getDataSources = async (ctx, next) => { try { const { models, ORM: { Op } } = ctx.app.fs.dc; const { offset, limit } = parsePagination(ctx.request.query); const where = {}; const { type } = ctx.request.query; const createdBy = String(ctx.request.query.createdBy || '').trim(); const name = String(ctx.request.query.name || '').trim(); if (type) where.type = type; if (createdBy) where.createdBy = createdBy; if (name) where.name = { [Op.like]: `%${name}%` }; const list = await models.ReportDataSource.findAndCountAll({ where, order: [['id', 'DESC']], offset, limit, raw: true, }); ctx.body = { count: list.count, rows: list.rows }; ctx.status = 200; } catch (error) { ctx.logger.log(error); ctx.status = 400; ctx.body = { message: typeof error === 'string' ? error : '获取数据源列表失败' }; } }; module.exports.createDataSource = async (ctx, next) => { try { const { models } = ctx.app.fs.dc; const { name, type, connectionConfig } = ctx.request.body || {}; const createdBy = ensureCreatedBy(ctx.request.body || {}); if (!String(name || '').trim()) throw '缺少参数: name'; const normalizedType = normalizeDataSourceType(type); if (!normalizedType) throw '缺少参数: type'; if (connectionConfig === null || connectionConfig === undefined) throw '缺少参数: connectionConfig'; const normalizedConnectionConfig = normalizedType === 'dataease' ? await dataease.normalizeDataEaseConnectionConfig(ctx, connectionConfig) : connectionConfig; const created = await models.ReportDataSource.create({ name: String(name).trim(), type: normalizedType, connectionConfig: normalizedConnectionConfig, createdBy, }, { returning: true }); ctx.body = created; ctx.status = 200; } catch (error) { ctx.logger.log(error); ctx.status = 400; ctx.body = { message: typeof error === 'string' ? error : '创建数据源失败' }; } }; module.exports.updateDataSource = async (ctx, next) => { try { const { models } = ctx.app.fs.dc; const dataSourceId = toInt(ctx.params.dataSourceId); if (!dataSourceId) throw '缺少参数: dataSourceId'; const exist = await models.ReportDataSource.findByPk(dataSourceId, { raw: true }); if (!exist) throw '数据源不存在'; const body = ctx.request.body || {}; const updateData = {}; const nextType = hasOwn(body, 'type') ? normalizeDataSourceType(body.type) : normalizeDataSourceType(exist.type); const nextConnectionConfig = hasOwn(body, 'connectionConfig') ? body.connectionConfig : exist.connectionConfig; if (hasOwn(body, 'name')) updateData.name = body.name ? String(body.name).trim() : ''; if (hasOwn(body, 'type')) updateData.type = nextType; if (nextType === 'dataease' && (hasOwn(body, 'type') || hasOwn(body, 'connectionConfig'))) { updateData.connectionConfig = await dataease.normalizeDataEaseConnectionConfig(ctx, nextConnectionConfig); } else if (hasOwn(body, 'connectionConfig')) { updateData.connectionConfig = nextConnectionConfig; } await models.ReportDataSource.update(updateData, { where: { id: dataSourceId } }); ctx.status = 204; } catch (error) { ctx.logger.log(error); ctx.status = 400; ctx.body = { message: typeof error === 'string' ? error : '更新数据源失败' }; } }; module.exports.deleteDataSource = async (ctx, next) => { try { const { models } = ctx.app.fs.dc; const dataSourceId = toInt(ctx.params.dataSourceId); if (!dataSourceId) throw '缺少参数: dataSourceId'; const exist = await models.ReportDataSource.findByPk(dataSourceId, { raw: true }); if (!exist) throw '数据源不存在'; await models.ReportDataSource.destroy({ where: { id: dataSourceId } }); ctx.status = 204; } catch (error) { ctx.logger.log(error); ctx.status = 400; ctx.body = { message: typeof error === 'string' ? error : '删除数据源失败' }; } }; module.exports.getDataSourceTables = async (ctx, next) => { try { const dataSourceId = toInt(ctx.params.dataSourceId); if (!dataSourceId) throw 'missing param: dataSourceId'; ctx.body = await getDataSourceTablesPayload(ctx, dataSourceId); ctx.status = 200; } catch (error) { ctx.logger.log(error); ctx.status = 400; ctx.body = { message: typeof error === 'string' ? error : 'failed to list datasource datasets/tables' }; } }; module.exports.getDataSourceTableColumns = async (ctx, next) => { try { const dataSourceId = toInt(ctx.params.dataSourceId); if (!dataSourceId) throw 'missing param: dataSourceId'; ctx.body = await getDataSourceTableColumnsPayload(ctx, dataSourceId, ctx.params.tableId); ctx.status = 200; } catch (error) { ctx.logger.log(error); ctx.status = 400; ctx.body = { message: typeof error === 'string' ? error : 'failed to list datasource columns' }; } }; module.exports.previewDataSourceQuery = async (ctx, next) => { try { const dataSourceId = toInt(ctx.params.dataSourceId); if (!dataSourceId) throw 'missing param: dataSourceId'; ctx.body = await previewDataSourceQueryPayload(ctx, dataSourceId, ctx.request.body || {}); ctx.status = 200; } catch (error) { ctx.logger.log(error); ctx.status = 400; ctx.body = { message: typeof error === 'string' ? error : 'failed to preview query' }; } };