@@ -23,7 +23,7 @@ import { SingleLineTextField } from './single-line-text.field';
2323import { SingleSelectField } from './single-select.field' ;
2424import { UserField } from './user.field' ;
2525
26- const FIELD_TYPES = new Set < string > ( Object . values ( FieldType ) ) ;
26+ const fieldTypes = new Set < string > ( Object . values ( FieldType ) ) ;
2727
2828const isRecordObject = ( value : unknown ) : value is Record < string , unknown > =>
2929 typeof value === 'object' && value !== null && ! Array . isArray ( value ) ;
@@ -32,7 +32,7 @@ const asRecordObject = (value: unknown): Record<string, unknown> | undefined =>
3232 isRecordObject ( value ) ? value : undefined ;
3333
3434const isKnownFieldType = ( value : unknown ) : value is FieldType =>
35- typeof value === 'string' && FIELD_TYPES . has ( value ) ;
35+ typeof value === 'string' && fieldTypes . has ( value ) ;
3636
3737const inferLookupInnerType = ( field : IFieldVo ) : FieldType => {
3838 switch ( field . cellValueType ) {
@@ -47,63 +47,148 @@ const inferLookupInnerType = (field: IFieldVo): FieldType => {
4747 }
4848} ;
4949
50- /**
51- * Translate v2 lookup DTO shape (type: lookup/conditionalLookup) to the v1-compatible shape
52- * consumed by the existing SDK field model.
53- */
54- const normalizeV2LookupField = ( field : IFieldVo ) : IFieldVo => {
55- const rawType = ( field as { type : string } ) . type ;
56- if ( rawType !== 'lookup' && rawType !== 'conditionalLookup' ) {
50+ const normalizeV2RollupField = ( field : IFieldVo ) : IFieldVo => {
51+ if ( field . type !== FieldType . Rollup ) {
5752 return field ;
5853 }
5954
6055 const raw = field as IFieldVo & {
61- type : string ;
62- innerType ?: unknown ;
63- innerOptions ?: unknown ;
56+ config ?: unknown ;
57+ lookupOptions ?: unknown ;
58+ } ;
59+ const config = asRecordObject ( raw . config ) ;
60+ if ( ! config ) {
61+ return field ;
62+ }
63+
64+ const lookupOptions = {
65+ ...( asRecordObject ( raw . lookupOptions ) ?? { } ) ,
66+ } as Record < string , unknown > ;
67+
68+ if ( config . linkFieldId != null ) lookupOptions . linkFieldId = config . linkFieldId ;
69+ if ( config . foreignTableId != null ) lookupOptions . foreignTableId = config . foreignTableId ;
70+ if ( config . lookupFieldId != null ) lookupOptions . lookupFieldId = config . lookupFieldId ;
71+
72+ return {
73+ ...field ,
74+ lookupOptions : lookupOptions as IFieldVo [ 'lookupOptions' ] ,
75+ } ;
76+ } ;
77+
78+ const normalizeV2ConditionalRollupField = ( field : IFieldVo ) : IFieldVo => {
79+ if ( field . type !== FieldType . ConditionalRollup ) {
80+ return field ;
81+ }
82+
83+ const raw = field as IFieldVo & {
84+ config ?: unknown ;
6485 options ?: unknown ;
6586 } ;
87+ const config = asRecordObject ( raw . config ) ;
88+ if ( ! config ) {
89+ return field ;
90+ }
6691
67- const rawOptions = asRecordObject ( raw . options as unknown ) ;
92+ const condition = asRecordObject ( config . condition ) ;
93+ const options = {
94+ ...( asRecordObject ( raw . options ) ?? { } ) ,
95+ } as Record < string , unknown > ;
96+
97+ if ( config . foreignTableId != null ) options . foreignTableId = config . foreignTableId ;
98+ if ( config . lookupFieldId != null ) options . lookupFieldId = config . lookupFieldId ;
99+ if ( condition ?. filter != null ) options . filter = condition . filter ;
100+ if ( condition ?. sort != null ) options . sort = condition . sort ;
101+ if ( condition ?. limit != null ) options . limit = condition . limit ;
102+
103+ return {
104+ ...field ,
105+ options : options as IFieldVo [ 'options' ] ,
106+ } ;
107+ } ;
108+
109+ const resolveLookupInnerType = (
110+ field : IFieldVo ,
111+ raw : IFieldVo & {
112+ innerType ?: unknown ;
113+ options ?: unknown ;
114+ } ,
115+ rawOptions : Record < string , unknown > | undefined
116+ ) : FieldType => {
68117 const innerTypeCandidate =
69118 ( typeof raw . innerType === 'string' ? raw . innerType : undefined ) ||
70119 ( typeof rawOptions ?. innerType === 'string' ? rawOptions . innerType : undefined ) ;
71- const innerType = isKnownFieldType ( innerTypeCandidate )
72- ? innerTypeCandidate
73- : inferLookupInnerType ( field ) ;
120+ return isKnownFieldType ( innerTypeCandidate ) ? innerTypeCandidate : inferLookupInnerType ( field ) ;
121+ } ;
74122
75- const innerOptions = ( raw . innerOptions ?? rawOptions ?. innerOptions ) as IFieldVo [ 'options' ] ;
76- const condition = asRecordObject ( rawOptions ?. condition ) ;
123+ const mergeLookupCondition = (
124+ lookupOptions : Record < string , unknown > ,
125+ condition : Record < string , unknown > | undefined
126+ ) => {
127+ if ( ! condition ) {
128+ return ;
129+ }
130+
131+ if ( condition . filter !== undefined ) lookupOptions . filter = condition . filter ;
132+ if ( condition . sort !== undefined ) lookupOptions . sort = condition . sort ;
133+ if ( condition . limit !== undefined ) lookupOptions . limit = condition . limit ;
134+ } ;
77135
136+ const buildLookupOptions = (
137+ field : IFieldVo ,
138+ rawOptions : Record < string , unknown > | undefined
139+ ) : IFieldVo [ 'lookupOptions' ] => {
78140 const lookupOptions : Record < string , unknown > = { } ;
141+
79142 if ( rawOptions ?. foreignTableId != null ) lookupOptions . foreignTableId = rawOptions . foreignTableId ;
80143 if ( rawOptions ?. lookupFieldId != null ) lookupOptions . lookupFieldId = rawOptions . lookupFieldId ;
81144 if ( rawOptions ?. linkFieldId != null ) lookupOptions . linkFieldId = rawOptions . linkFieldId ;
82145 if ( rawOptions ?. filter != null ) lookupOptions . filter = rawOptions . filter ;
83146 if ( rawOptions ?. sort != null ) lookupOptions . sort = rawOptions . sort ;
84147 if ( rawOptions ?. limit != null ) lookupOptions . limit = rawOptions . limit ;
85- if ( condition ) {
86- if ( condition . filter !== undefined ) lookupOptions . filter = condition . filter ;
87- if ( condition . sort !== undefined ) lookupOptions . sort = condition . sort ;
88- if ( condition . limit !== undefined ) lookupOptions . limit = condition . limit ;
148+
149+ mergeLookupCondition ( lookupOptions , asRecordObject ( rawOptions ?. condition ) ) ;
150+
151+ return Object . keys ( lookupOptions ) . length > 0
152+ ? ( lookupOptions as IFieldVo [ 'lookupOptions' ] )
153+ : field . lookupOptions ;
154+ } ;
155+
156+ /**
157+ * Translate v2 lookup DTO shape (type: lookup/conditionalLookup) to the v1-compatible shape
158+ * consumed by the existing SDK field model.
159+ */
160+ const normalizeV2LookupField = ( field : IFieldVo ) : IFieldVo => {
161+ const rawType = ( field as { type : string } ) . type ;
162+ if ( rawType !== 'lookup' && rawType !== 'conditionalLookup' ) {
163+ return field ;
89164 }
90165
166+ const raw = field as IFieldVo & {
167+ type : string ;
168+ innerType ?: unknown ;
169+ innerOptions ?: unknown ;
170+ options ?: unknown ;
171+ } ;
172+
173+ const rawOptions = asRecordObject ( raw . options as unknown ) ;
174+ const innerType = resolveLookupInnerType ( field , raw , rawOptions ) ;
175+ const innerOptions = ( raw . innerOptions ?? rawOptions ?. innerOptions ) as IFieldVo [ 'options' ] ;
176+
91177 return {
92178 ...field ,
93179 type : innerType ,
94180 isLookup : true ,
95181 isConditionalLookup :
96182 rawType === 'conditionalLookup' || field . isConditionalLookup ? true : undefined ,
97183 options : innerOptions ?? { } ,
98- lookupOptions :
99- Object . keys ( lookupOptions ) . length > 0
100- ? ( lookupOptions as IFieldVo [ 'lookupOptions' ] )
101- : field . lookupOptions ,
184+ lookupOptions : buildLookupOptions ( field , rawOptions ) ,
102185 } ;
103186} ;
104187
105188export function createFieldInstance ( field : IFieldVo , doc ?: Doc < IFieldVo > ) {
106- const normalizedField = normalizeV2LookupField ( field ) ;
189+ const normalizedField = normalizeV2ConditionalRollupField (
190+ normalizeV2RollupField ( normalizeV2LookupField ( field ) )
191+ ) ;
107192 const instance = ( ( ) => {
108193 switch ( normalizedField . type ) {
109194 case FieldType . SingleLineText :
0 commit comments