1
1
import glob from 'fast-glob' ;
2
- import { cyan } from 'kleur/colors' ;
2
+ import { bold , cyan } from 'kleur/colors' ;
3
3
import type fsMod from 'node:fs' ;
4
4
import * as path from 'node:path' ;
5
5
import { fileURLToPath , pathToFileURL } from 'node:url' ;
@@ -56,13 +56,6 @@ type CreateContentGeneratorParams = {
56
56
fs : typeof fsMod ;
57
57
} ;
58
58
59
- type EventOpts = { logLevel : 'info' | 'warn' } ;
60
-
61
- type EventWithOptions = {
62
- type : ContentEvent ;
63
- opts : EventOpts | undefined ;
64
- } ;
65
-
66
59
class UnsupportedFileTypeError extends Error { }
67
60
68
61
export async function createContentTypesGenerator ( {
@@ -78,7 +71,7 @@ export async function createContentTypesGenerator({
78
71
const contentEntryExts = [ ...contentEntryConfigByExt . keys ( ) ] ;
79
72
const dataEntryExts = getDataEntryExts ( settings ) ;
80
73
81
- let events : EventWithOptions [ ] = [ ] ;
74
+ let events : ContentEvent [ ] = [ ] ;
82
75
let debounceTimeout : NodeJS . Timeout | undefined ;
83
76
84
77
const typeTemplateContent = await fs . promises . readFile ( contentPaths . typesTemplate , 'utf-8' ) ;
@@ -90,10 +83,7 @@ export async function createContentTypesGenerator({
90
83
return { typesGenerated : false , reason : 'no-content-dir' } ;
91
84
}
92
85
93
- events . push ( {
94
- type : { name : 'add' , entry : contentPaths . config . url } ,
95
- opts : { logLevel : 'warn' } ,
96
- } ) ;
86
+ events . push ( { name : 'add' , entry : contentPaths . config . url } ) ;
97
87
98
88
const globResult = await glob ( '**' , {
99
89
cwd : fileURLToPath ( contentPaths . contentDir ) ,
@@ -110,24 +100,18 @@ export async function createContentTypesGenerator({
110
100
const entryURL = pathToFileURL ( fullPath ) ;
111
101
if ( entryURL . href . startsWith ( contentPaths . config . url . href ) ) continue ;
112
102
if ( entry . dirent . isFile ( ) ) {
113
- events . push ( {
114
- type : { name : 'add' , entry : entryURL } ,
115
- opts : { logLevel : 'warn' } ,
116
- } ) ;
103
+ events . push ( { name : 'add' , entry : entryURL } ) ;
117
104
} else if ( entry . dirent . isDirectory ( ) ) {
118
- events . push ( { type : { name : 'addDir' , entry : entryURL } , opts : { logLevel : 'warn' } } ) ;
105
+ events . push ( { name : 'addDir' , entry : entryURL } ) ;
119
106
}
120
107
}
121
108
await runEvents ( ) ;
122
109
return { typesGenerated : true } ;
123
110
}
124
111
125
112
async function handleEvent (
126
- event : ContentEvent ,
127
- opts ?: EventOpts
113
+ event : ContentEvent
128
114
) : Promise < { shouldGenerateTypes : boolean ; error ?: Error } > {
129
- const logLevel = opts ?. logLevel ?? 'info' ;
130
-
131
115
if ( event . name === 'addDir' || event . name === 'unlinkDir' ) {
132
116
const collection = normalizePath (
133
117
path . relative ( fileURLToPath ( contentPaths . contentDir ) , fileURLToPath ( event . entry ) )
@@ -140,9 +124,7 @@ export async function createContentTypesGenerator({
140
124
switch ( event . name ) {
141
125
case 'addDir' :
142
126
collectionEntryMap [ JSON . stringify ( collection ) ] = { type : 'unknown' , entries : { } } ;
143
- if ( logLevel === 'info' ) {
144
- logger . info ( 'content' , `${ cyan ( collection ) } collection added` ) ;
145
- }
127
+ logger . debug ( 'content' , `${ cyan ( collection ) } collection added` ) ;
146
128
break ;
147
129
case 'unlinkDir' :
148
130
if ( collectionKey in collectionEntryMap ) {
@@ -186,16 +168,14 @@ export async function createContentTypesGenerator({
186
168
187
169
const collection = getEntryCollectionName ( { entry, contentDir } ) ;
188
170
if ( collection === undefined ) {
189
- if ( [ 'info' , 'warn' ] . includes ( logLevel ) ) {
190
- logger . warn (
191
- 'content' ,
192
- `${ cyan (
193
- normalizePath (
194
- path . relative ( fileURLToPath ( contentPaths . contentDir ) , fileURLToPath ( event . entry ) )
195
- )
196
- ) } must be nested in a collection directory. Skipping.`
197
- ) ;
198
- }
171
+ logger . warn (
172
+ 'content' ,
173
+ `${ bold (
174
+ normalizePath (
175
+ path . relative ( fileURLToPath ( contentPaths . contentDir ) , fileURLToPath ( event . entry ) )
176
+ )
177
+ ) } must live in a ${ bold ( 'content/...' ) } collection subdirectory.`
178
+ ) ;
199
179
return { shouldGenerateTypes : false } ;
200
180
}
201
181
@@ -308,22 +288,19 @@ export async function createContentTypesGenerator({
308
288
}
309
289
}
310
290
311
- function queueEvent ( rawEvent : RawContentEvent , opts ?: EventOpts ) {
291
+ function queueEvent ( rawEvent : RawContentEvent ) {
312
292
const event = {
313
- type : {
314
- entry : pathToFileURL ( rawEvent . entry ) ,
315
- name : rawEvent . name ,
316
- } ,
317
- opts,
293
+ entry : pathToFileURL ( rawEvent . entry ) ,
294
+ name : rawEvent . name ,
318
295
} ;
319
- if ( ! event . type . entry . pathname . startsWith ( contentPaths . contentDir . pathname ) ) return ;
296
+ if ( ! event . entry . pathname . startsWith ( contentPaths . contentDir . pathname ) ) return ;
320
297
321
298
events . push ( event ) ;
322
299
323
300
debounceTimeout && clearTimeout ( debounceTimeout ) ;
324
301
const runEventsSafe = async ( ) => {
325
302
try {
326
- await runEvents ( opts ) ;
303
+ await runEvents ( ) ;
327
304
} catch {
328
305
// Prevent frontmatter errors from crashing the server. The errors
329
306
// are still reported on page reflects as desired.
@@ -333,30 +310,25 @@ export async function createContentTypesGenerator({
333
310
debounceTimeout = setTimeout ( runEventsSafe , 50 /* debounce to batch chokidar events */ ) ;
334
311
}
335
312
336
- async function runEvents ( opts ?: EventOpts ) {
337
- const logLevel = opts ?. logLevel ?? 'info' ;
313
+ async function runEvents ( ) {
338
314
const eventResponses = [ ] ;
339
315
340
316
for ( const event of events ) {
341
- const response = await handleEvent ( event . type , event . opts ) ;
317
+ const response = await handleEvent ( event ) ;
342
318
eventResponses . push ( response ) ;
343
319
}
344
320
345
321
events = [ ] ;
346
- let unsupportedFiles = [ ] ;
347
322
for ( const response of eventResponses ) {
348
323
if ( response . error instanceof UnsupportedFileTypeError ) {
349
- unsupportedFiles . push ( response . error . message ) ;
324
+ logger . warn (
325
+ 'content' ,
326
+ `Unsupported file type ${ bold (
327
+ response . error . message
328
+ ) } found. Prefix filename with an underscore (\`_\`) to ignore.`
329
+ ) ;
350
330
}
351
331
}
352
- if ( unsupportedFiles . length > 0 && [ 'info' , 'warn' ] . includes ( logLevel ) ) {
353
- logger . warn (
354
- 'content' ,
355
- `Unsupported file types found. Prefix with an underscore (\`_\`) to ignore:\n- ${ unsupportedFiles . join (
356
- '\n'
357
- ) } `
358
- ) ;
359
- }
360
332
const observable = contentConfigObserver . get ( ) ;
361
333
if ( eventResponses . some ( ( r ) => r . shouldGenerateTypes ) ) {
362
334
await writeContentFiles ( {
@@ -369,7 +341,7 @@ export async function createContentTypesGenerator({
369
341
viteServer,
370
342
} ) ;
371
343
invalidateVirtualMod ( viteServer ) ;
372
- if ( observable . status === 'loaded' && [ 'info' , 'warn' ] . includes ( logLevel ) ) {
344
+ if ( observable . status === 'loaded' ) {
373
345
warnNonexistentCollections ( {
374
346
logger,
375
347
contentConfig : observable . config ,
@@ -475,6 +447,7 @@ async function writeContentFiles({
475
447
let configPathRelativeToCacheDir = normalizePath (
476
448
path . relative ( contentPaths . cacheDir . pathname , contentPaths . config . url . pathname )
477
449
) ;
450
+
478
451
if ( ! isRelativePath ( configPathRelativeToCacheDir ) )
479
452
configPathRelativeToCacheDir = './' + configPathRelativeToCacheDir ;
480
453
@@ -514,9 +487,9 @@ function warnNonexistentCollections({
514
487
if ( ! collectionEntryMap [ JSON . stringify ( configuredCollection ) ] ) {
515
488
logger . warn (
516
489
'content' ,
517
- `The ${ JSON . stringify (
518
- configuredCollection
519
- ) } collection does not have an associated folder in your \` content\` directory. Make sure the folder exists , or check your content config for typos.`
490
+ `The ${ bold ( configuredCollection ) } collection is defined but no ${ bold (
491
+ 'content/' + configuredCollection
492
+ ) } folder exists in the content directory. Create a new folder for the collection , or check your content configuration file for typos.`
520
493
) ;
521
494
}
522
495
}
0 commit comments