@@ -62,6 +62,12 @@ const argv = yargs
6262 'experimental' ,
6363 ] ,
6464 } ,
65+ cleanup : {
66+ describe : 'output flags by cleanup category.' ,
67+ requiresArg : false ,
68+ type : 'boolean' ,
69+ default : false ,
70+ } ,
6571 } ) . argv ;
6672
6773// Load ReactFeatureFlags with __NEXT_MAJOR__ replaced with 'next'.
@@ -375,53 +381,86 @@ const FLAG_CONFIG = {
375381
376382const FLAG_COLUMNS = Object . keys ( FLAG_CONFIG ) ;
377383
384+ const INTERNAL_VARIANTS = [ 'WWW Classic' , 'WWW Modern' , 'RN FB' ] ;
385+ const OSS_VARIANTS = [
386+ 'OSS Next Major' ,
387+ 'OSS Canary' ,
388+ 'OSS Experimental' ,
389+ 'RN OSS' ,
390+ 'RN Next Major' ,
391+ ] ;
392+
378393// Build the table with the value for each flag.
379- const isDiff = argv . diff != null && argv . diff . length > 1 ;
380- const table = { } ;
381- // eslint-disable-next-line no-for-of-loops/no-for-of-loops
382- for ( const flag of allFlagsUniqueFlags ) {
383- const values = FLAG_COLUMNS . reduce ( ( acc , key ) => {
384- acc [ key ] = FLAG_CONFIG [ key ] ( flag ) ;
385- return acc ;
386- } , { } ) ;
387-
388- if ( ! isDiff ) {
389- table [ flag ] = values ;
390- continue ;
391- }
394+ function buildTable ( filterFn ) {
395+ const isDiff = argv . diff != null && argv . diff . length > 1 ;
396+ const table = { } ;
397+ const filteredFlags = filterFn
398+ ? allFlagsUniqueFlags . filter ( filterFn )
399+ : allFlagsUniqueFlags ;
400+ // eslint-disable-next-line no-for-of-loops/no-for-of-loops
401+ for ( const flag of filteredFlags ) {
402+ const values = FLAG_COLUMNS . reduce ( ( acc , key ) => {
403+ acc [ key ] = FLAG_CONFIG [ key ] ( flag ) ;
404+ return acc ;
405+ } , { } ) ;
406+
407+ if ( ! isDiff ) {
408+ table [ flag ] = values ;
409+ continue ;
410+ }
411+
412+ const subset = argv . diff . map ( argToHeader ) . reduce ( ( acc , key ) => {
413+ if ( key in values ) {
414+ acc [ key ] = values [ key ] ;
415+ }
416+ return acc ;
417+ } , { } ) ;
392418
393- const subset = argv . diff . map ( argToHeader ) . reduce ( ( acc , key ) => {
394- if ( key in values ) {
395- acc [ key ] = values [ key ] ;
419+ if ( new Set ( Object . values ( subset ) ) . size !== 1 ) {
420+ table [ flag ] = subset ;
396421 }
397- return acc ;
398- } , { } ) ;
422+ }
399423
400- if ( new Set ( Object . values ( subset ) ) . size !== 1 ) {
401- table [ flag ] = subset ;
424+ // Sort the table
425+ let sorted = table ;
426+ if ( isDiff || argv . sort ) {
427+ const sortChannel = argToHeader ( isDiff ? argv . diff [ 0 ] : argv . sort ) ;
428+ const sortBy =
429+ sortChannel === 'flag'
430+ ? ( [ flagA ] , [ flagB ] ) => {
431+ return flagA . localeCompare ( flagB ) ;
432+ }
433+ : ( [ , rowA ] , [ , rowB ] ) => {
434+ return rowB [ sortChannel ]
435+ . toString ( )
436+ . localeCompare ( rowA [ sortChannel ] ) ;
437+ } ;
438+ sorted = Object . fromEntries ( Object . entries ( table ) . sort ( sortBy ) ) ;
402439 }
440+
441+ return sorted ;
403442}
404443
405- // Sort the table
406- let sorted = table ;
407- if ( isDiff || argv . sort ) {
408- const sortChannel = argToHeader ( isDiff ? argv . diff [ 0 ] : argv . sort ) ;
409- const sortBy =
410- sortChannel === 'flag'
411- ? ( [ flagA ] , [ flagB ] ) => {
412- return flagA . localeCompare ( flagB ) ;
413- }
414- : ( [ , rowA ] , [ , rowB ] ) => {
415- return rowB [ sortChannel ] . toString ( ) . localeCompare ( rowA [ sortChannel ] ) ;
416- } ;
417- sorted = Object . fromEntries ( Object . entries ( table ) . sort ( sortBy ) ) ;
444+ function formatTable ( tableData ) {
445+ // left align the flag names.
446+ const maxLength = Math . max (
447+ ...Object . keys ( tableData ) . map ( item => item . length )
448+ ) ;
449+ const padded = { } ;
450+ Object . keys ( tableData ) . forEach ( key => {
451+ const newKey = key . padEnd ( maxLength , ' ' ) ;
452+ padded [ newKey ] = tableData [ key ] ;
453+ } ) ;
454+
455+ return padded ;
418456}
419457
420458if ( argv . csv ) {
459+ const table = buildTable ( ) ;
421460 const csvRows = [
422461 `Flag name, ${ FLAG_COLUMNS . join ( ', ' ) } ` ,
423462 ...Object . keys ( table ) . map ( flag => {
424- const row = sorted [ flag ] ;
463+ const row = table [ flag ] ;
425464 return `${ flag } , ${ FLAG_COLUMNS . map ( col => row [ col ] ) . join ( ', ' ) } ` ;
426465 } ) ,
427466 ] ;
@@ -433,16 +472,108 @@ if (argv.csv) {
433472 } ) ;
434473}
435474
436- // left align the flag names.
437- const maxLength = Math . max ( ...Object . keys ( sorted ) . map ( item => item . length ) ) ;
438- const padded = { } ;
439- Object . keys ( sorted ) . forEach ( key => {
440- const newKey = key . padEnd ( maxLength , ' ' ) ;
441- padded [ newKey ] = sorted [ key ] ;
442- } ) ;
475+ if ( argv . cleanup ) {
476+ const allPassingFlags = [ ] ;
477+ const allFailingFlags = [ ] ;
478+ const needsShippedExperimentFlags = [ ] ;
479+ const earlyExperimentationFlags = [ ] ;
480+ const internalOnlyFlags = [ ] ;
481+
482+ const diffedFlagColumns =
483+ argv . diff [ 0 ] != null ? argv . diff . map ( argToHeader ) : FLAG_COLUMNS ;
484+
485+ // eslint-disable-next-line no-for-of-loops/no-for-of-loops
486+ for ( const flag of allFlagsUniqueFlags ) {
487+ const values = diffedFlagColumns . reduce ( ( acc , key ) => {
488+ acc [ key ] = FLAG_CONFIG [ key ] ( flag ) ;
489+ return acc ;
490+ } , { } ) ;
491+
492+ const uniqueValues = new Set ( Object . values ( values ) ) ;
493+
494+ if (
495+ uniqueValues . size === 1 &&
496+ ( uniqueValues . has ( '✅' ) ||
497+ typeof uniqueValues . values ( ) . next ( ) . value === 'number' )
498+ ) {
499+ allPassingFlags . push ( flag ) ;
500+ }
501+
502+ if ( uniqueValues . size === 1 && uniqueValues . has ( '❌' ) ) {
503+ allFailingFlags . push ( flag ) ;
504+ }
505+
506+ const internalVariantValues = INTERNAL_VARIANTS . filter ( value =>
507+ diffedFlagColumns . includes ( value )
508+ ) . map ( v => values [ v ] ) ;
509+ const ossVariantValues = OSS_VARIANTS . filter ( value =>
510+ diffedFlagColumns . includes ( value )
511+ ) . map ( v => values [ v ] ) ;
512+
513+ if (
514+ internalVariantValues . some ( v => v === '✅' ) &&
515+ ossVariantValues . every ( v => v === '❌' )
516+ ) {
517+ internalOnlyFlags . push ( flag ) ;
518+ }
519+
520+ if (
521+ internalVariantValues . some ( v => v === '🧪' ) &&
522+ ( ossVariantValues . every ( v => v === '❌' ) ||
523+ ( ossVariantValues . some ( v => v === '❌' ) &&
524+ values [ 'OSS Experimental' ] === '✅' ) )
525+ ) {
526+ earlyExperimentationFlags . push ( flag ) ;
527+ }
528+
529+ if (
530+ internalVariantValues . some ( v => v === '🧪' || v === '❌' ) &&
531+ ossVariantValues . every ( v => v === '✅' )
532+ ) {
533+ needsShippedExperimentFlags . push ( flag ) ;
534+ }
535+ }
536+
537+ if ( allPassingFlags . length > 0 ) {
538+ console . log ( 'ALL VARIANTS PASS (✅)' ) ;
539+ console . table (
540+ formatTable ( buildTable ( flag => allPassingFlags . includes ( flag ) ) )
541+ ) ;
542+ }
543+
544+ if ( allFailingFlags . length > 0 ) {
545+ console . log ( 'ALL VARIANTS FAIL (❌)' ) ;
546+ console . table (
547+ formatTable ( buildTable ( flag => allFailingFlags . includes ( flag ) ) )
548+ ) ;
549+ }
550+
551+ if ( internalOnlyFlags . length > 0 ) {
552+ console . log ( 'INTERNAL ONLY (✅)' ) ;
553+ console . table (
554+ formatTable ( buildTable ( flag => internalOnlyFlags . includes ( flag ) ) )
555+ ) ;
556+ }
557+
558+ if ( earlyExperimentationFlags . length > 0 ) {
559+ console . log ( 'WAITING ON RESULTS (🧪)' ) ;
560+ console . table (
561+ formatTable ( buildTable ( flag => earlyExperimentationFlags . includes ( flag ) ) )
562+ ) ;
563+ }
564+
565+ if ( needsShippedExperimentFlags . length > 0 ) {
566+ console . log ( 'WAITING ON ROLLOUT (🧪)' ) ;
567+ console . table (
568+ formatTable (
569+ buildTable ( flag => needsShippedExperimentFlags . includes ( flag ) )
570+ )
571+ ) ;
572+ }
573+ } else {
574+ console . table ( formatTable ( buildTable ( ) ) ) ;
575+ }
443576
444- // print table with formatting
445- console . table ( padded ) ;
446577console . log ( `
447578Legend:
448579 ✅ On
0 commit comments