diff --git a/.gitignore b/.gitignore index 435ab4d70..c960b2560 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ secrets.json tests.json tests.old.json .testtmp +feature-list.json diff --git a/scripts/add-new-bcd.ts b/scripts/add-new-bcd.ts index 680890e33..fc360df01 100644 --- a/scripts/add-new-bcd.ts +++ b/scripts/add-new-bcd.ts @@ -235,6 +235,7 @@ const main = async (): Promise => { {addNewFeatures: true}, bcd.browsers, overrides, + "", ); console.log("Injecting BCD..."); diff --git a/scripts/update-bcd.ts b/scripts/update-bcd.ts index af405f0d4..f35f56bc5 100644 --- a/scripts/update-bcd.ts +++ b/scripts/update-bcd.ts @@ -350,6 +350,12 @@ interface UpdateLog { reason: Reason; } +interface FeatureListLog { + browser: BrowserName; + path: string; + statements: SimpleSupportStatement[]; +} + /** Values available in operations. */ interface UpdateState extends UpdateLog { shared: UpdateShared; @@ -1008,6 +1014,27 @@ const pickLog = ({ }; }; +/** + * Picks specific properties from an object of type T and returns a new object of type FeatureListLog. + * @template T - The type of the input object. + * @param obj - The input object. + * @param obj.browser - The browser property of the input object. + * @param obj.path - The path property of the input object. + * @param obj.statements - The statements property of the input object. + * @returns - The new object of type FeatureListLog. + */ +const pickFeatureList = ({ + browser, + path, + statements, +}: T): FeatureListLog => { + return { + browser, + path, + statements, + }; +}; + /** * Generates a sequence of key-value pairs representing the entries in an object tree. * The keys are generated by concatenating the prefix with each nested key. @@ -1035,14 +1062,14 @@ export const walkEntries = function* ( * @param bcd - The BCD identifier. * @param supportMatrix - The support matrix. * @param options - Additional options for the update. - * @returns A boolean indicating whether any changes were made during the update. + * @returns An array of objects representing BCD paths that have been updated. */ export const update = ( bcd: Identifier, supportMatrix: SupportMatrix, options: any, -): boolean => { - const changes: UpdateLog[] = []; +): FeatureListLog[] => { + const results: UpdateLog[] = []; for (const state of compose( expand("entry", function* () { for (const [path, entry] of walkEntries("", bcd)) { @@ -1136,7 +1163,7 @@ export const update = ( } }), )()) { - changes.push(pickLog(state)); + results.push(pickLog(state)); if (state.statements) { state.shared.support[state.browser] = state.statements.length === 1 ? state.statements[0] : state.statements; @@ -1145,8 +1172,11 @@ export const update = ( logger.warn(state.reason.message); } } - // TODO: Serialize changes to a file - return changes.some(({statements}) => Boolean(statements)); + + const updates = results + .filter(({statements}) => Boolean(statements)) + .map((result) => pickFeatureList(result)); + return updates; }; /* c8 ignore start */ @@ -1191,6 +1221,7 @@ export const loadJsonFiles = async ( * @param filter - An object containing filter options. * @param browsers - An object representing the browsers to include in the update. * @param overrides - An object containing override options. + * @param outputPath - An string specifying filename and path for feature list output. Defaults to `feature-list.json`. * @returns A Promise that resolves when the update is complete. */ export const main = async ( @@ -1198,6 +1229,7 @@ export const main = async ( filter: any, browsers: Browsers, overrides: Overrides, + outputPath: string, ): Promise => { // Replace filter.path with a minimatch object. if (filter.path && filter.path.includes("*")) { @@ -1232,18 +1264,25 @@ export const main = async ( browsers, overrides.filter(Array.isArray as (item: unknown) => item is OverrideTuple), ); + let featureList: FeatureListLog[] = []; // Should match https://github.com/mdn/browser-compat-data/blob/f10bf2cc7d1b001a390e70b7854cab9435ffb443/test/linter/test-style.js#L63 // TODO: https://github.com/mdn/browser-compat-data/issues/3617 for (const [file, data] of Object.entries(bcdFiles)) { - const modified = update(data, supportMatrix, filter); - if (!modified) { + const updates = update(data, supportMatrix, filter); + if (!updates.length) { continue; } + featureList = featureList.concat(updates); logger.info(`Updating ${path.relative(BCD_DIR, file)}`); const json = JSON.stringify(data, null, " ") + "\n"; await fs.writeFile(file, json); } + + if (featureList.length) { + const featureListJSON = JSON.stringify(featureList, null, " ") + "\n"; + await fs.writeFile(outputPath, featureListJSON); + } }; if (esMain(import.meta)) { @@ -1292,10 +1331,17 @@ if (esMain(import.meta)) { 'Only update when versions are a specific number (or "false"), disallowing ranges', type: "boolean", default: false, + }) + .option("output", { + alias: "o", + describe: + 'Specify filename and output path for a json list of updated features. Defaults to "feature-list.json"', + type: "string", + default: "feature-list.json", }); }, ); - await main(argv.reports, argv, browsers, overrides); + await main(argv.reports, argv, browsers, overrides, argv.output); } /* c8 ignore stop */