Skip to content

Commit 1949cba

Browse files
committed
linting and small refactor
1 parent 25791bc commit 1949cba

File tree

1 file changed

+111
-102
lines changed

1 file changed

+111
-102
lines changed

protographic/src/operations/message-builder.ts

Lines changed: 111 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,97 @@ export function buildMessageFromSelectionSet(
203203
return message;
204204
}
205205

206+
/**
207+
* Gets or assigns a field number for a proto field
208+
*/
209+
function getOrAssignFieldNumber(
210+
message: protobuf.Type,
211+
protoFieldName: string,
212+
fieldNumberManager?: FieldNumberManager,
213+
): number {
214+
const existingFieldNumber = fieldNumberManager?.getFieldNumber(message.name, protoFieldName);
215+
216+
if (existingFieldNumber !== undefined) {
217+
return existingFieldNumber;
218+
}
219+
220+
if (fieldNumberManager) {
221+
const fieldNumber = fieldNumberManager.getNextFieldNumber(message.name);
222+
fieldNumberManager.assignFieldNumber(message.name, protoFieldName, fieldNumber);
223+
return fieldNumber;
224+
}
225+
226+
return message.fieldsArray.length + 1;
227+
}
228+
229+
/**
230+
* Resolves the final type name and repetition flag, handling nested list wrappers
231+
*/
232+
function resolveTypeNameAndRepetition(
233+
baseTypeName: string,
234+
protoTypeInfo: ProtoTypeInfo,
235+
fieldType: GraphQLOutputType,
236+
options?: MessageBuilderOptions,
237+
): { typeName: string; isRepeated: boolean } {
238+
let typeName = baseTypeName;
239+
let isRepeated = protoTypeInfo.isRepeated;
240+
241+
if (protoTypeInfo.requiresNestedWrapper && options?.ensureNestedListWrapper) {
242+
typeName = options.ensureNestedListWrapper(fieldType) as any;
243+
isRepeated = false; // Wrapper handles the repetition
244+
}
245+
246+
return { typeName, isRepeated };
247+
}
248+
249+
/**
250+
* Creates and configures a proto field with comments
251+
*/
252+
function createProtoField(
253+
protoFieldName: string,
254+
fieldNumber: number,
255+
typeName: string,
256+
isRepeated: boolean,
257+
fieldDef: any,
258+
options?: MessageBuilderOptions,
259+
): protobuf.Field {
260+
const protoField = new protobuf.Field(protoFieldName, fieldNumber, typeName);
261+
262+
if (isRepeated) {
263+
protoField.repeated = true;
264+
}
265+
266+
if (options?.includeComments && fieldDef.description) {
267+
protoField.comment = fieldDef.description;
268+
}
269+
270+
return protoField;
271+
}
272+
273+
/**
274+
* Ensures an enum type is created and added to the root
275+
*/
276+
function ensureEnumCreated(namedType: GraphQLEnumType, options: MessageBuilderOptions): void {
277+
if (!options.root) {
278+
return;
279+
}
280+
281+
const enumTypeName = namedType.name;
282+
283+
// Initialize createdEnums in options if missing to ensure persistence across calls
284+
if (!options.createdEnums) {
285+
options.createdEnums = new Set<string>();
286+
}
287+
288+
if (!options.createdEnums.has(enumTypeName)) {
289+
const protoEnum = buildEnumType(namedType, {
290+
includeComments: options.includeComments,
291+
});
292+
options.root.add(protoEnum);
293+
options.createdEnums.add(enumTypeName);
294+
}
295+
}
296+
206297
/**
207298
* Processes a field selection and adds it to the message
208299
*/
@@ -246,17 +337,15 @@ function processFieldSelection(
246337

247338
const fieldType = fieldDef.type;
248339

249-
// If the field has a selection set, we need a nested message
340+
// Determine the base type name based on whether we have a selection set
341+
let baseTypeName: string;
342+
250343
if (field.selectionSet) {
344+
// Build nested message for object types
251345
const namedType = getNamedType(fieldType);
252346
if (isObjectType(namedType) || isInterfaceType(namedType) || isUnionType(namedType)) {
253-
// Use simple name since message will be nested inside parent
254347
const nestedMessageName = upperFirst(camelCase(fieldName));
255348

256-
// For interfaces and unions, we use the type directly for processing
257-
// Union types will only work with inline fragments that specify concrete types
258-
const typeForSelection = namedType;
259-
260349
const nestedOptions = {
261350
...options,
262351
_depth: (options?._depth ?? 0) + 1,
@@ -265,122 +354,42 @@ function processFieldSelection(
265354
const nestedMessage = buildMessageFromSelectionSet(
266355
nestedMessageName,
267356
field.selectionSet,
268-
typeForSelection,
357+
namedType,
269358
typeInfo,
270359
nestedOptions,
271360
);
272361

273-
// Add nested message to the parent message
274362
message.add(nestedMessage);
275-
276-
// Get field number - check if already assigned from reconciliation
277-
const existingFieldNumber = fieldNumberManager?.getFieldNumber(message.name, protoFieldName);
278-
279-
let fieldNumber: number;
280-
if (existingFieldNumber !== undefined) {
281-
// Use existing field number from reconciliation
282-
fieldNumber = existingFieldNumber;
283-
} else if (fieldNumberManager) {
284-
// Get next field number and assign it
285-
fieldNumber = fieldNumberManager.getNextFieldNumber(message.name);
286-
fieldNumberManager.assignFieldNumber(message.name, protoFieldName, fieldNumber);
287-
} else {
288-
// No field number manager, use sequential numbering
289-
fieldNumber = message.fieldsArray.length + 1;
290-
}
291-
292-
// Determine if field should be repeated
293-
const protoTypeInfo = mapGraphQLTypeToProto(fieldType, {
294-
customScalarMappings: options?.customScalarMappings,
295-
});
296-
297-
// Handle nested list wrappers for nested messages
298-
let finalTypeName = nestedMessageName;
299-
let isRepeated = protoTypeInfo.isRepeated;
300-
301-
if (protoTypeInfo.requiresNestedWrapper && options?.ensureNestedListWrapper) {
302-
// Create wrapper message and use its name
303-
finalTypeName = options.ensureNestedListWrapper(fieldType) as any;
304-
isRepeated = false; // Wrapper handles the repetition
305-
}
306-
307-
const protoField = new protobuf.Field(protoFieldName, fieldNumber, finalTypeName);
308-
309-
if (isRepeated) {
310-
protoField.repeated = true;
311-
}
312-
313-
if (options?.includeComments && fieldDef.description) {
314-
protoField.comment = fieldDef.description;
315-
}
316-
317-
message.add(protoField);
363+
baseTypeName = nestedMessageName;
364+
} else {
365+
return; // Shouldn't happen with valid GraphQL
318366
}
319367
} else {
320-
// Scalar or enum field
368+
// Handle scalar/enum fields
321369
const namedType = getNamedType(fieldType);
322370

323-
// If this is an enum type, ensure it's added to the root
324371
if (isEnumType(namedType) && options?.root) {
325-
const enumTypeName = namedType.name;
326-
327-
// Initialize createdEnums in options if missing to ensure persistence across calls
328-
if (!options.createdEnums) {
329-
options.createdEnums = new Set<string>();
330-
}
331-
const createdEnums = options.createdEnums;
332-
333-
if (!createdEnums.has(enumTypeName)) {
334-
const protoEnum = buildEnumType(namedType as GraphQLEnumType, {
335-
includeComments: options.includeComments,
336-
});
337-
options.root.add(protoEnum);
338-
options.createdEnums.add(enumTypeName);
339-
}
372+
ensureEnumCreated(namedType as GraphQLEnumType, options);
340373
}
341374

342375
const protoTypeInfo = mapGraphQLTypeToProto(fieldType, {
343376
customScalarMappings: options?.customScalarMappings,
344377
});
378+
baseTypeName = protoTypeInfo.typeName;
379+
}
345380

346-
// Handle nested list wrappers
347-
let finalTypeName = protoTypeInfo.typeName;
348-
let isRepeated = protoTypeInfo.isRepeated;
349-
350-
if (protoTypeInfo.requiresNestedWrapper && options?.ensureNestedListWrapper) {
351-
// Create wrapper message and use its name
352-
finalTypeName = options.ensureNestedListWrapper(fieldType) as any;
353-
isRepeated = false; // Wrapper handles the repetition
354-
}
355-
356-
// Get field number - check if already assigned from reconciliation
357-
const existingFieldNumber = fieldNumberManager?.getFieldNumber(message.name, protoFieldName);
358-
359-
let fieldNumber: number;
360-
if (existingFieldNumber !== undefined) {
361-
// Use existing field number from reconciliation
362-
fieldNumber = existingFieldNumber;
363-
} else if (fieldNumberManager) {
364-
// Get next field number and assign it
365-
fieldNumber = fieldNumberManager.getNextFieldNumber(message.name);
366-
fieldNumberManager.assignFieldNumber(message.name, protoFieldName, fieldNumber);
367-
} else {
368-
// No field number manager, use sequential numbering
369-
fieldNumber = message.fieldsArray.length + 1;
370-
}
381+
// Common logic for both branches
382+
const protoTypeInfo = mapGraphQLTypeToProto(fieldType, {
383+
customScalarMappings: options?.customScalarMappings,
384+
});
371385

372-
const protoField = new protobuf.Field(protoFieldName, fieldNumber, finalTypeName);
386+
const { typeName, isRepeated } = resolveTypeNameAndRepetition(baseTypeName, protoTypeInfo, fieldType, options);
373387

374-
if (isRepeated) {
375-
protoField.repeated = true;
376-
}
388+
const fieldNumber = getOrAssignFieldNumber(message, protoFieldName, fieldNumberManager);
377389

378-
if (options?.includeComments && fieldDef.description) {
379-
protoField.comment = fieldDef.description;
380-
}
390+
const protoField = createProtoField(protoFieldName, fieldNumber, typeName, isRepeated, fieldDef, options);
381391

382-
message.add(protoField);
383-
}
392+
message.add(protoField);
384393
}
385394

386395
/**

0 commit comments

Comments
 (0)