From 9782630e71bf75a2db71778b9951109095380b3e Mon Sep 17 00:00:00 2001 From: gchust Date: Fri, 10 Jul 2026 13:39:58 +0800 Subject: [PATCH] fix: can't resolve external datasource popup record var (#10048) --- ...ables.resolve.external-data-source.test.ts | 69 +++++++++++++++++++ .../src/server/variables/records.ts | 10 ++- 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 packages/plugins/@nocobase/plugin-flow-engine/src/server/__tests__/variables.resolve.external-data-source.test.ts diff --git a/packages/plugins/@nocobase/plugin-flow-engine/src/server/__tests__/variables.resolve.external-data-source.test.ts b/packages/plugins/@nocobase/plugin-flow-engine/src/server/__tests__/variables.resolve.external-data-source.test.ts new file mode 100644 index 00000000000..adeda2df4a6 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-flow-engine/src/server/__tests__/variables.resolve.external-data-source.test.ts @@ -0,0 +1,69 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import type { ResourcerContext } from '@nocobase/resourcer'; +import { beforeAll, describe, expect, it, vi } from 'vitest'; +import { resolveVariablesTemplate } from '../variables/resolve'; +import { resetVariablesRegistryForTest } from './test-utils'; + +describe('variables:resolve external data source records', () => { + beforeAll(() => { + resetVariablesRegistryForTest(); + }); + + it('resolves a popup record field when the repository returns plain JSON', async () => { + const findOne = vi.fn(async () => ({ id: 'lead-1', email: 'acme@example.test' })); + const repository = { findOne }; + const collection = { + filterTargetKey: 'id', + model: { + primaryKeyAttribute: 'id', + }, + }; + const getDataSource = vi.fn((key: string) => { + expect(key).toBe('crm_external'); + return { + collectionManager: { + db: { + getCollection: () => collection, + getRepository: () => repository, + }, + }, + }; + }); + const koaContext = { + app: { + dataSourceManager: { get: getDataSource }, + environment: { getVariables: () => ({}) }, + logger: { child: () => ({ debug: vi.fn(), warn: vi.fn() }) }, + }, + state: {}, + } as unknown as ResourcerContext; + + const result = await resolveVariablesTemplate( + koaContext, + { value: '{{ ctx.popup.record.email }}' }, + { + 'popup.record': { + dataSourceKey: 'crm_external', + collection: 'leads', + filterByTk: 'lead-1', + }, + }, + ); + + expect(result).toEqual({ value: 'acme@example.test' }); + expect(findOne).toHaveBeenCalledTimes(1); + expect(findOne).toHaveBeenCalledWith({ + filterByTk: 'lead-1', + fields: undefined, + appends: undefined, + }); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-flow-engine/src/server/variables/records.ts b/packages/plugins/@nocobase/plugin-flow-engine/src/server/variables/records.ts index 635ba3caf70..b9785054d5a 100644 --- a/packages/plugins/@nocobase/plugin-flow-engine/src/server/variables/records.ts +++ b/packages/plugins/@nocobase/plugin-flow-engine/src/server/variables/records.ts @@ -77,9 +77,15 @@ export function mergeFieldsWithExtras(fields?: string[], extras: string[] = []): return uniqStrings([...fields, ...extras]); } +function toJsonRecord(record: unknown): unknown { + if (!record || typeof record !== 'object') return record; + const toJSON = (record as { toJSON?: () => unknown }).toJSON; + return typeof toJSON === 'function' ? toJSON.call(record) : record; +} + function toJsonArray(rows: unknown): any[] { if (!Array.isArray(rows)) return []; - return rows.map((r: any) => (r?.toJSON ? r.toJSON() : r)); + return rows.map(toJsonRecord); } /** @@ -158,5 +164,5 @@ export async function fetchRecordOrRecordsJson( const rec = await repo.findOne( preferFullRecord ? { filterByTk: filterByTk as any } : { filterByTk: filterByTk as any, fields, appends }, ); - return rec ? rec.toJSON() : undefined; + return rec ? toJsonRecord(rec) : undefined; }