diff --git a/.github/workflows/datasets.yml b/.github/workflows/datasets.yml index f93a1466..a7cd7748 100644 --- a/.github/workflows/datasets.yml +++ b/.github/workflows/datasets.yml @@ -5,6 +5,12 @@ on: # Every Monday at 09:00 America/Sao_Paulo (12:00 UTC), same day as Dependabot. - cron: "0 12 * * 1" workflow_dispatch: + inputs: + datasets: + description: "Datasets to rebuild, separated by spaces (e.g. `ncm cbo`). Empty rebuilds all of them." + required: false + default: "" + type: string permissions: contents: read @@ -29,7 +35,11 @@ jobs: uses: ./.github/actions/setup - name: Rebuild datasets - run: npm run build:data + env: + DATASETS: ${{ inputs.datasets }} + run: | + read -ra datasets <<< "$DATASETS" + npm run build:data -- "${datasets[@]}" - name: Validate the regenerated datasets run: npm run check && npx vp test --run diff --git a/package-lock.json b/package-lock.json index 0f742e16..8018067a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2194,9 +2194,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "peer": true, @@ -2857,9 +2857,9 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5147,9 +5147,9 @@ } }, "node_modules/@stryker-mutator/core/node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7208,9 +7208,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", "dev": true, "license": "MIT", "dependencies": { @@ -8373,9 +8373,9 @@ } }, "node_modules/eslint-plugin-sonarjs/node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8492,9 +8492,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "peer": true, @@ -8785,9 +8785,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz", - "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", + "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index 48684021..0b01a228 100644 --- a/package.json +++ b/package.json @@ -159,7 +159,7 @@ "overrides": { "@puppeteer/browsers@2": "^3.2.2", "basic-ftp@5": "^5.3.1", - "brace-expansion@2": "^2.1.2", + "brace-expansion@2": "^2.1.7", "eslint-plugin-sonarjs": { "typescript": "6.0.3", "ts-api-utils": { diff --git a/scripts/data.ts b/scripts/data.ts index ee3a7857..5bbed506 100644 --- a/scripts/data.ts +++ b/scripts/data.ts @@ -1,5 +1,15 @@ #!/usr/bin/env node +/** + * Rebuilds the embedded datasets from their official sources, then lints and formats the + * generated files. + * + * Usage: + * node scripts/data.ts [dataset...] + * Rebuild every dataset, or only the named ones (`ncm`, `cbo`, ..., the generator file names + * without `.ts`). A generator that fails is named on stderr and makes the script exit with 1. + */ + import { spawn } from "node:child_process"; import { resolve } from "node:path"; @@ -67,10 +77,30 @@ const generatedFiles = [ "./src/is-valid-ncm/constants.ts", ]; +const requested = process.argv.slice(2).map((name) => name.replace(/\.ts$/, "")); +const known = generators.map((generator) => generator.replace(/\.ts$/, "")); +const unknown = requested.filter((name) => !known.includes(name)); + +if (unknown.length > 0) { + console.error(`Unknown datasets: ${unknown.join(", ")}. Known: ${known.join(", ")}.`); + process.exit(1); +} + +const selected = + requested.length === 0 + ? generators + : generators.filter((_, index) => requested.includes(known[index])); + const results = await Promise.all( - generators.map((generator) => run("node", [resolve(scriptsDirectory, generator)])), + selected.map((generator) => run("node", [resolve(scriptsDirectory, generator)])), ); +const failed = selected.filter((_, index) => results[index] !== 0); + +if (failed.length > 0) { + console.error(`Failed to rebuild: ${failed.join(", ")}`); +} + // Lint and format before checking the generators, so a failing generator never leaves // unformatted files behind in the working tree. `vp fmt` runs last because `vp lint --fix` // rewrites code without reformatting it. diff --git a/src/is-valid-ncm/constants.ts b/src/is-valid-ncm/constants.ts index 5363a56a..cf7a186a 100644 --- a/src/is-valid-ncm/constants.ts +++ b/src/is-valid-ncm/constants.ts @@ -2,9 +2,9 @@ * NCM (Nomenclatura Comum do Mercosul) 8 digit codes in force on the generation date, in ascending * order, packed as base 36 differences by `packCodes` (scripts/lookup-table.ts) (one per source * line, joined by line continuations). A code is included when the generation date falls within its - * Siscomex `Data_Inicio`/`Data_Fim` range (both inclusive), which also keeps codes that are valid - * today but carry a scheduled future end date, not only the ones with no end date (`Data_Fim: - * "31/12/9999"`). + * Siscomex `Data_Inicio`/`Data_Fim` range (both inclusive), which also keeps codes that are + * valid today but carry a scheduled future end date, not only the ones with no end date + * (`Data_Fim: "31/12/9999"`). * * Generated by `node ./scripts/ncm.ts`. Do not edit by hand. * @@ -9213,7 +9213,8 @@ a,\ 1y,\ jq,\ 2ee,\ -28,\ +a,\ +1y,\ s2,\ 2s,\ jq,\