/** * Imports and generates the '@smogon/sets' package. * Pokemon Showdown - http://pokemonshowdown.com/ * * Run with `node tools/set-import [version]`. If version is not specified, * the 'patch' version of the existing package will be bumped. If version is * 'minor' or 'monthly', the minor version will be bumped. In general, every * month after usage stats are processed this script should be run to update * the sets package and bump the minor version. If this script is run in * between usage stats updates, the patch version should be bumped. If a * breaking change occurs to the output format, the major version must be * bumped (with 'major' or 'breaking' as the version argument). The exact * version string (eg. '1.2.3') can also be provided. After creating the set * import, provided there are no serious errors, the package can be released * by running `npm publish` in the `sets/` directory. * * @license MIT */ 'use strict'; const child_process = require('child_process'); const path = require('path'); const fs = require('fs'); const shell = cmd => child_process.execSync(cmd, { stdio: 'inherit', cwd: path.resolve(__dirname, '../..') }); shell('node build'); function missing(dep) { try { require.resolve(dep); return false; } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') throw err; return true; } } // We depend on smogon as a devDependency in order to get the typing information if (missing('smogon')) shell(`npm install --no-save smogon`); // Rather obnoxiously, the TeamValidator used by the importer refers to // rulesets which rely on Chat.plural to be set up, so we do so here. global.Chat = {}; Chat.plural = function (num, plural = 's', singular = '') { if (num && typeof num.length === 'number') { num = num.length; } else if (num && typeof num.size === 'number') { num = num.size; } else { num = Number(num); } return (num !== 1 ? plural : singular); }; const importer = require('../../dist/tools/set-import/importer.js'); const SETS = path.resolve(__dirname, 'sets'); (async () => { // Clean up old artifacts for (const file of fs.readdirSync(SETS)) { if (file.startsWith('gen') && file.endsWith('json')) { fs.unlinkSync(path.join(SETS, file)); } } const imports = []; for (const [i, generationData] of (await importer.importAll()).entries()) { fs.writeFileSync(path.resolve(SETS, `gen${i + 1}.json`), JSON.stringify(generationData)); imports.push(`gen${i + 1}`); for (const format in generationData) { fs.writeFileSync(path.resolve(SETS, `${format}.json`), JSON.stringify(generationData[format])); imports.push(format); } } let version = process.argv[2]; if (!version || version.match(/^[^\d]/)) { try { const current = require('./sets/package.json').version; const [major, minor, patch] = current.split('.'); if (version === 'major' || version === 'breaking') { version = `${Number(major) + 1}.0.0`; } else if (version === 'minor' || version === 'monthly') { version = `${major}.${Number(minor) + 1}.0`; } else { version = `${major}.${minor}.${Number(patch) + 1}`; } } catch { console.error("Version required to create '@smogon/sets' package"); process.exit(1); } } const packagejson = { "name": "@smogon/sets", version, "description": "Set data imported from Smogon.com and used on Pokémon Showdown", "main": "index.js", "unpkg": "index.js", "types": "index.d.ts", "repository": "github:smogon/sets", "publishConfig": { "access": "public", }, "license": "UNLICENSED", // The code/typings are MIT, but not all sources of data fall under MIT }; fs.writeFileSync(path.resolve(SETS, 'package.json'), JSON.stringify(packagejson, null, 2)); const indexjs = [ '"use strict";', 'var JSON;', // This hack allows us to require this package in Node and in the browser // and have the Node code which uses `require` get stripped on web. 'if (typeof window === "undefined") {', ' JSON = {', imports.map(n => ` "${n}": load("./${n}.json")`).join(',\n'), ' };', '} else {', ' JSON = {', imports.map(n => ` "${n}": import("./${n}.json")`).join(',\n'), ' };', '}', 'function load(path) {', ' return Promise.resolve(require(path));', '}', 'function forGen(gen) {', // eslint-disable-next-line no-template-curly-in-string ' return JSON[`gen${typeof gen === "number" ? gen : gen.num}`];', '}', 'exports.forGen = forGen;', 'function forFormat(format) {', ' return JSON[format];', '}', 'exports.forFormat = forFormat;', ].join('\n'); fs.writeFileSync(path.resolve(SETS, 'index.js'), indexjs); })().catch(err => console.error(err));