@@ -23,17 +23,18 @@ const printDocASTReducer: ASTReducer<string> = {
23
23
// Document
24
24
25
25
Document : {
26
- leave : ( node ) => join ( node . definitions , '\n\n' ) ,
26
+ leave : ( node ) => truthyJoin ( node . definitions , '\n\n' ) ,
27
27
} ,
28
28
29
29
OperationDefinition : {
30
30
leave ( node ) {
31
- const varDefs = wrap ( '(' , join ( node . variableDefinitions , ', ' ) , ')' ) ;
31
+ const varDefs = wrap ( '(' , truthyJoin ( node . variableDefinitions , ', ' ) , ')' ) ;
32
32
const prefix = join (
33
33
[
34
34
node . operation ,
35
+ // TODO: optimize
35
36
join ( [ node . name , varDefs ] ) ,
36
- join ( node . directives , ' ' ) ,
37
+ truthyJoin ( node . directives , ' ' ) ,
37
38
] ,
38
39
' ' ,
39
40
) ;
@@ -50,20 +51,20 @@ const printDocASTReducer: ASTReducer<string> = {
50
51
': ' +
51
52
type +
52
53
wrap ( ' = ' , defaultValue ) +
53
- wrap ( ' ' , join ( directives , ' ' ) ) ,
54
+ wrap ( ' ' , truthyJoin ( directives , ' ' ) ) ,
54
55
} ,
55
56
SelectionSet : { leave : ( { selections } ) => block ( selections ) } ,
56
57
57
58
Field : {
58
59
leave ( { alias, name, arguments : args , directives, selectionSet } ) {
59
60
const prefix = wrap ( '' , alias , ': ' ) + name ;
60
- let argsLine = prefix + wrap ( '(' , join ( args , ', ' ) , ')' ) ;
61
+ let argsLine = prefix + wrap ( '(' , truthyJoin ( args , ', ' ) , ')' ) ;
61
62
62
63
if ( argsLine . length > MAX_LINE_LENGTH ) {
63
- argsLine = prefix + wrap ( '(\n' , indent ( join ( args , '\n' ) ) , '\n)' ) ;
64
+ argsLine = prefix + wrap ( '(\n' , indent ( truthyJoin ( args , '\n' ) ) , '\n)' ) ;
64
65
}
65
66
66
- return join ( [ argsLine , join ( directives , ' ' ) , selectionSet ] , ' ' ) ;
67
+ return join ( [ argsLine , truthyJoin ( directives , ' ' ) , selectionSet ] , ' ' ) ;
67
68
} ,
68
69
} ,
69
70
@@ -73,7 +74,7 @@ const printDocASTReducer: ASTReducer<string> = {
73
74
74
75
FragmentSpread : {
75
76
leave : ( { name, directives } ) =>
76
- '...' + name + wrap ( ' ' , join ( directives , ' ' ) ) ,
77
+ '...' + name + wrap ( ' ' , truthyJoin ( directives , ' ' ) ) ,
77
78
} ,
78
79
79
80
InlineFragment : {
@@ -82,7 +83,7 @@ const printDocASTReducer: ASTReducer<string> = {
82
83
[
83
84
'...' ,
84
85
wrap ( 'on ' , typeCondition ) ,
85
- join ( directives , ' ' ) ,
86
+ truthyJoin ( directives , ' ' ) ,
86
87
selectionSet ,
87
88
] ,
88
89
' ' ,
@@ -99,8 +100,8 @@ const printDocASTReducer: ASTReducer<string> = {
99
100
} ) =>
100
101
// Note: fragment variable definitions are experimental and may be changed
101
102
// or removed in the future.
102
- `fragment ${ name } ${ wrap ( '(' , join ( variableDefinitions , ', ' ) , ')' ) } ` +
103
- `on ${ typeCondition } ${ wrap ( '' , join ( directives , ' ' ) , ' ' ) } ` +
103
+ `fragment ${ name } ${ wrap ( '(' , truthyJoin ( variableDefinitions , ', ' ) , ')' ) } ` +
104
+ `on ${ typeCondition } ${ wrap ( '' , truthyJoin ( directives , ' ' ) , ' ' ) } ` +
104
105
selectionSet ,
105
106
} ,
106
107
@@ -115,15 +116,15 @@ const printDocASTReducer: ASTReducer<string> = {
115
116
BooleanValue : { leave : ( { value } ) => ( value ? 'true' : 'false' ) } ,
116
117
NullValue : { leave : ( ) => 'null' } ,
117
118
EnumValue : { leave : ( { value } ) => value } ,
118
- ListValue : { leave : ( { values } ) => '[' + join ( values , ', ' ) + ']' } ,
119
- ObjectValue : { leave : ( { fields } ) => '{' + join ( fields , ', ' ) + '}' } ,
119
+ ListValue : { leave : ( { values } ) => '[' + truthyJoin ( values , ', ' ) + ']' } ,
120
+ ObjectValue : { leave : ( { fields } ) => '{' + truthyJoin ( fields , ', ' ) + '}' } ,
120
121
ObjectField : { leave : ( { name, value } ) => name + ': ' + value } ,
121
122
122
123
// Directive
123
124
124
125
Directive : {
125
126
leave : ( { name, arguments : args } ) =>
126
- '@' + name + wrap ( '(' , join ( args , ', ' ) , ')' ) ,
127
+ '@' + name + wrap ( '(' , truthyJoin ( args , ', ' ) , ')' ) ,
127
128
} ,
128
129
129
130
// Type
@@ -147,7 +148,7 @@ const printDocASTReducer: ASTReducer<string> = {
147
148
ScalarTypeDefinition : {
148
149
leave : ( { description, name, directives } ) =>
149
150
wrap ( '' , description , '\n' ) +
150
- join ( [ 'scalar' , name , join ( directives , ' ' ) ] , ' ' ) ,
151
+ join ( [ 'scalar' , name , truthyJoin ( directives , ' ' ) ] , ' ' ) ,
151
152
} ,
152
153
153
154
ObjectTypeDefinition : {
@@ -157,8 +158,8 @@ const printDocASTReducer: ASTReducer<string> = {
157
158
[
158
159
'type' ,
159
160
name ,
160
- wrap ( 'implements ' , join ( interfaces , ' & ' ) ) ,
161
- join ( directives , ' ' ) ,
161
+ wrap ( 'implements ' , truthyJoin ( interfaces , ' & ' ) ) ,
162
+ truthyJoin ( directives , ' ' ) ,
162
163
block ( fields ) ,
163
164
] ,
164
165
' ' ,
@@ -170,18 +171,18 @@ const printDocASTReducer: ASTReducer<string> = {
170
171
wrap ( '' , description , '\n' ) +
171
172
name +
172
173
( hasMultilineItems ( args )
173
- ? wrap ( '(\n' , indent ( join ( args , '\n' ) ) , '\n)' )
174
- : wrap ( '(' , join ( args , ', ' ) , ')' ) ) +
174
+ ? wrap ( '(\n' , indent ( truthyJoin ( args , '\n' ) ) , '\n)' )
175
+ : wrap ( '(' , truthyJoin ( args , ', ' ) , ')' ) ) +
175
176
': ' +
176
177
type +
177
- wrap ( ' ' , join ( directives , ' ' ) ) ,
178
+ wrap ( ' ' , truthyJoin ( directives , ' ' ) ) ,
178
179
} ,
179
180
180
181
InputValueDefinition : {
181
182
leave : ( { description, name, type, defaultValue, directives } ) =>
182
183
wrap ( '' , description , '\n' ) +
183
184
join (
184
- [ name + ': ' + type , wrap ( '= ' , defaultValue ) , join ( directives , ' ' ) ] ,
185
+ [ name + ': ' + type , wrap ( '= ' , defaultValue ) , truthyJoin ( directives , ' ' ) ] ,
185
186
' ' ,
186
187
) ,
187
188
} ,
@@ -193,8 +194,8 @@ const printDocASTReducer: ASTReducer<string> = {
193
194
[
194
195
'interface' ,
195
196
name ,
196
- wrap ( 'implements ' , join ( interfaces , ' & ' ) ) ,
197
- join ( directives , ' ' ) ,
197
+ wrap ( 'implements ' , truthyJoin ( interfaces , ' & ' ) ) ,
198
+ truthyJoin ( directives , ' ' ) ,
198
199
block ( fields ) ,
199
200
] ,
200
201
' ' ,
@@ -205,26 +206,26 @@ const printDocASTReducer: ASTReducer<string> = {
205
206
leave : ( { description, name, directives, types } ) =>
206
207
wrap ( '' , description , '\n' ) +
207
208
join (
208
- [ 'union' , name , join ( directives , ' ' ) , wrap ( '= ' , join ( types , ' | ' ) ) ] ,
209
+ [ 'union' , name , truthyJoin ( directives , ' ' ) , wrap ( '= ' , truthyJoin ( types , ' | ' ) ) ] ,
209
210
' ' ,
210
211
) ,
211
212
} ,
212
213
213
214
EnumTypeDefinition : {
214
215
leave : ( { description, name, directives, values } ) =>
215
216
wrap ( '' , description , '\n' ) +
216
- join ( [ 'enum' , name , join ( directives , ' ' ) , block ( values ) ] , ' ' ) ,
217
+ join ( [ 'enum' , name , truthyJoin ( directives , ' ' ) , block ( values ) ] , ' ' ) ,
217
218
} ,
218
219
219
220
EnumValueDefinition : {
220
221
leave : ( { description, name, directives } ) =>
221
- wrap ( '' , description , '\n' ) + join ( [ name , join ( directives , ' ' ) ] , ' ' ) ,
222
+ wrap ( '' , description , '\n' ) + join ( [ name , truthyJoin ( directives , ' ' ) ] , ' ' ) ,
222
223
} ,
223
224
224
225
InputObjectTypeDefinition : {
225
226
leave : ( { description, name, directives, fields } ) =>
226
227
wrap ( '' , description , '\n' ) +
227
- join ( [ 'input' , name , join ( directives , ' ' ) , block ( fields ) ] , ' ' ) ,
228
+ join ( [ 'input' , name , truthyJoin ( directives , ' ' ) , block ( fields ) ] , ' ' ) ,
228
229
} ,
229
230
230
231
DirectiveDefinition : {
@@ -233,24 +234,24 @@ const printDocASTReducer: ASTReducer<string> = {
233
234
'directive @' +
234
235
name +
235
236
( hasMultilineItems ( args )
236
- ? wrap ( '(\n' , indent ( join ( args , '\n' ) ) , '\n)' )
237
- : wrap ( '(' , join ( args , ', ' ) , ')' ) ) +
237
+ ? wrap ( '(\n' , indent ( truthyJoin ( args , '\n' ) ) , '\n)' )
238
+ : wrap ( '(' , truthyJoin ( args , ', ' ) , ')' ) ) +
238
239
( repeatable ? ' repeatable' : '' ) +
239
240
' on ' +
240
- join ( locations , ' | ' ) ,
241
+ truthyJoin ( locations , ' | ' ) ,
241
242
} ,
242
243
243
244
SchemaExtension : {
244
245
leave : ( { directives, operationTypes } ) =>
245
246
join (
246
- [ 'extend schema' , join ( directives , ' ' ) , block ( operationTypes ) ] ,
247
+ [ 'extend schema' , truthyJoin ( directives , ' ' ) , block ( operationTypes ) ] ,
247
248
' ' ,
248
249
) ,
249
250
} ,
250
251
251
252
ScalarTypeExtension : {
252
253
leave : ( { name, directives } ) =>
253
- join ( [ 'extend scalar' , name , join ( directives , ' ' ) ] , ' ' ) ,
254
+ join ( [ 'extend scalar' , name , truthyJoin ( directives , ' ' ) ] , ' ' ) ,
254
255
} ,
255
256
256
257
ObjectTypeExtension : {
@@ -259,8 +260,8 @@ const printDocASTReducer: ASTReducer<string> = {
259
260
[
260
261
'extend type' ,
261
262
name ,
262
- wrap ( 'implements ' , join ( interfaces , ' & ' ) ) ,
263
- join ( directives , ' ' ) ,
263
+ wrap ( 'implements ' , truthyJoin ( interfaces , ' & ' ) ) ,
264
+ truthyJoin ( directives , ' ' ) ,
264
265
block ( fields ) ,
265
266
] ,
266
267
' ' ,
@@ -273,8 +274,8 @@ const printDocASTReducer: ASTReducer<string> = {
273
274
[
274
275
'extend interface' ,
275
276
name ,
276
- wrap ( 'implements ' , join ( interfaces , ' & ' ) ) ,
277
- join ( directives , ' ' ) ,
277
+ wrap ( 'implements ' , truthyJoin ( interfaces , ' & ' ) ) ,
278
+ truthyJoin ( directives , ' ' ) ,
278
279
block ( fields ) ,
279
280
] ,
280
281
' ' ,
@@ -287,21 +288,21 @@ const printDocASTReducer: ASTReducer<string> = {
287
288
[
288
289
'extend union' ,
289
290
name ,
290
- join ( directives , ' ' ) ,
291
- wrap ( '= ' , join ( types , ' | ' ) ) ,
291
+ truthyJoin ( directives , ' ' ) ,
292
+ wrap ( '= ' , truthyJoin ( types , ' | ' ) ) ,
292
293
] ,
293
294
' ' ,
294
295
) ,
295
296
} ,
296
297
297
298
EnumTypeExtension : {
298
299
leave : ( { name, directives, values } ) =>
299
- join ( [ 'extend enum' , name , join ( directives , ' ' ) , block ( values ) ] , ' ' ) ,
300
+ join ( [ 'extend enum' , name , truthyJoin ( directives , ' ' ) , block ( values ) ] , ' ' ) ,
300
301
} ,
301
302
302
303
InputObjectTypeExtension : {
303
304
leave : ( { name, directives, fields } ) =>
304
- join ( [ 'extend input' , name , join ( directives , ' ' ) , block ( fields ) ] , ' ' ) ,
305
+ join ( [ 'extend input' , name , truthyJoin ( directives , ' ' ) , block ( fields ) ] , ' ' ) ,
305
306
} ,
306
307
} ;
307
308
@@ -313,7 +314,30 @@ function join(
313
314
maybeArray : Maybe < ReadonlyArray < string | undefined > > ,
314
315
separator = '' ,
315
316
) : string {
316
- return maybeArray ?. filter ( ( x ) => x ) . join ( separator ) ?? '' ;
317
+ if ( ! maybeArray ) return ''
318
+
319
+ const list = maybeArray . filter ( ( x ) => x ) ;
320
+ const listLength = list . length ;
321
+ let result = '' ;
322
+ for ( let i = 0 ; i < listLength ; i ++ ) {
323
+ if ( i === listLength - 1 ) return result + list [ i ] ;
324
+ else result += list [ i ] + separator ;
325
+ }
326
+ return result
327
+ }
328
+
329
+ function truthyJoin (
330
+ list : ReadonlyArray < string > | undefined ,
331
+ separator : string ,
332
+ ) : string {
333
+ if ( ! list ) return ''
334
+ const listLength = list . length ;
335
+ let result = '' ;
336
+ for ( let i = 0 ; i < listLength ; i ++ ) {
337
+ if ( i === listLength - 1 ) return result + list [ i ] ;
338
+ else result += list [ i ] + separator ;
339
+ }
340
+ return result
317
341
}
318
342
319
343
/**
0 commit comments