From 09eda5ffdc6fe2c3e6b8259e54423c4b41c405b0 Mon Sep 17 00:00:00 2001 From: aaaaaajie Date: Sun, 30 Mar 2025 19:24:28 +0800 Subject: [PATCH] feat: mock server access to plugin mssql import static and compatible mssql function --- .../src/query-interface/query-interface.ts | 3 ++- packages/core/database/src/sync-runner.ts | 2 +- packages/core/test/src/server/mock-server.ts | 17 ++++++++++++----- .../src/server/server.ts | 3 ++- .../src/server/repository.ts | 14 ++++++++++---- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/core/database/src/query-interface/query-interface.ts b/packages/core/database/src/query-interface/query-interface.ts index 3e73cc7d6b..a2b774a997 100644 --- a/packages/core/database/src/query-interface/query-interface.ts +++ b/packages/core/database/src/query-interface/query-interface.ts @@ -11,6 +11,7 @@ import { ColumnDescription, ModelStatic, QueryInterface as SequelizeQueryInterface, + TableName, Transaction, Transactionable, } from 'sequelize'; @@ -23,7 +24,7 @@ export type TableInfo = { }; export interface ChangeColumnOptions { - tableName: string; + tableName: TableName; schema?: string; columnName: string; columnDescription: ColumnDescription; diff --git a/packages/core/database/src/sync-runner.ts b/packages/core/database/src/sync-runner.ts index e7530391de..fa6ae6b268 100644 --- a/packages/core/database/src/sync-runner.ts +++ b/packages/core/database/src/sync-runner.ts @@ -255,7 +255,7 @@ export class SyncRunner { } else { await this.database.queryInterface.changeColumn({ actions: ['setDefaultValue'], - tableName: this.tableName as string, + tableName: this.tableName, columnDescription: changeAttribute, columnName: columnName, model: this.model, diff --git a/packages/core/test/src/server/mock-server.ts b/packages/core/test/src/server/mock-server.ts index ab535ff548..9f5b3317c4 100644 --- a/packages/core/test/src/server/mock-server.ts +++ b/packages/core/test/src/server/mock-server.ts @@ -8,7 +8,14 @@ */ import { mockDatabase } from '@nocobase/database'; -import { Application, ApplicationOptions, AppSupervisor, Gateway, PluginManager } from '@nocobase/server'; +import { + Application, + ApplicationOptions, + AppSupervisor, + Gateway, + PluginManager, + runPluginStaticImports, +} from '@nocobase/server'; import { uid } from '@nocobase/utils'; import jwt from 'jsonwebtoken'; import qs from 'qs'; @@ -223,7 +230,7 @@ export class MockServer extends Application { } } -export function mockServer(options: ApplicationOptions = {}) { +export async function mockServer(options: ApplicationOptions = {}) { if (typeof TextEncoder === 'undefined') { global.TextEncoder = require('util').TextEncoder; } @@ -231,7 +238,7 @@ export function mockServer(options: ApplicationOptions = {}) { if (typeof TextDecoder === 'undefined') { global.TextDecoder = require('util').TextDecoder; } - + await runPluginStaticImports(); Gateway.getInstance().reset(); // AppSupervisor.getInstance().reset(); @@ -271,7 +278,7 @@ export function mockServer(options: ApplicationOptions = {}) { } export async function startMockServer(options: ApplicationOptions = {}) { - const app = mockServer(options); + const app = await mockServer(options); await app.runCommand('start'); return app; } @@ -347,7 +354,7 @@ export async function createMockServer(options: MockServerOptions = {}): Promise // ignore errors } const { version, beforeInstall, skipInstall, skipStart, ...others } = options; - const app: MockServer = mockServer(others); + const app: MockServer = await mockServer(others); if (!skipInstall) { if (beforeInstall) { await beforeInstall(app); diff --git a/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts b/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts index e94bb7c180..47d4c0b30d 100644 --- a/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-data-source-main/src/server/server.ts @@ -92,7 +92,8 @@ export class PluginDataSourceMainServer extends Plugin { this.app.db.on('collections.beforeCreate', beforeCreateForViewCollection(this.db)); this.app.db.on('collections.beforeCreate', async (model: CollectionModel, options) => { - if (this.app.db.getCollection(model.get('name')) && model.get('from') !== 'db2cm' && !model.get('isThrough')) { + const isDB2cm = model.get('from') === 'db2cm' || options.values?.from === 'db2cm'; + if (this.app.db.getCollection(model.get('name')) && !isDB2cm && !model.get('isThrough')) { throw new Error(`Collection named ${model.get('name')} already exists`); } }); diff --git a/packages/plugins/@nocobase/plugin-ui-schema-storage/src/server/repository.ts b/packages/plugins/@nocobase/plugin-ui-schema-storage/src/server/repository.ts index f13461d128..997201704d 100644 --- a/packages/plugins/@nocobase/plugin-ui-schema-storage/src/server/repository.ts +++ b/packages/plugins/@nocobase/plugin-ui-schema-storage/src/server/repository.ts @@ -731,10 +731,15 @@ export class UiSchemaRepository extends Repository { } if (nodePosition === 'last') { + let isNull = 'ifnull'; + const dialect = this.database.sequelize.getDialect(); + if (dialect === 'postgres') { + isNull = 'coalesce'; + } else if (dialect === 'mssql') { + isNull = 'ISNULL'; + } const maxSort = await db.sequelize.query( - `SELECT ${ - this.database.sequelize.getDialect() === 'postgres' ? 'coalesce' : 'ifnull' - }(MAX(TreeTable.sort), 0) as maxsort FROM ${treeTable} as TreeTable + `SELECT ${isNull}(MAX(TreeTable.sort), 0) as maxsort FROM ${treeTable} as TreeTable LEFT JOIN ${treeTable} as NodeInfo ON NodeInfo.descendant = TreeTable.descendant and NodeInfo.depth = 0 WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and NodeInfo.type = :type`, @@ -1085,6 +1090,7 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort const db = this.database; const treeTable = this.uiSchemaTreePathTableName; + const isNotTrue = this.database.options.dialect === 'mssql' ? '1' : 'true'; const rawSql = ` SELECT "SchemaTable"."x-uid" as "x-uid", "SchemaTable"."name" as name, "SchemaTable"."schema" as "schema" , @@ -1095,7 +1101,7 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort LEFT JOIN ${treeTable} as NodeInfo ON NodeInfo.descendant = "SchemaTable"."x-uid" and NodeInfo.descendant = NodeInfo.ancestor and NodeInfo.depth = 0 LEFT JOIN ${treeTable} as ParentPath ON (ParentPath.descendant = "SchemaTable"."x-uid" AND ParentPath.depth = 1) WHERE TreePath.ancestor = :ancestor ${ - options?.includeAsyncNode ? '' : 'AND (NodeInfo.async != true or TreePath.depth = 0)' + options?.includeAsyncNode ? '' : `AND (NodeInfo.async != ${isNotTrue} or TreePath.depth = 0)` } `;