diff --git a/package.json b/package.json index 085a9fbf19..fc85c84802 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "check": "flow check", "check-cover": "flow batch-coverage --quiet --strip-root --show-all src/ && flow stop --quiet", "build": "node resources/build.js", - "preversion": ". ./resources/checkgit.sh && npm test", + "preversion": ". ./resources/checkgit.sh", + "version": "node resources/gen-version.js && npm test", "prepublishOnly": ". ./resources/prepublish.sh", "gitpublish": ". ./resources/gitpublish.sh" }, diff --git a/resources/build.js b/resources/build.js index 4d480809e4..93f78d80d5 100644 --- a/resources/build.js +++ b/resources/build.js @@ -18,6 +18,7 @@ const { rmdirRecursive, mkdirRecursive, readdirRecursive, + parseSemver, } = require('./utils'); if (require.main === module) { @@ -26,7 +27,6 @@ if (require.main === module) { copyFile('./LICENSE', './dist/LICENSE'); copyFile('./README.md', './dist/README.md'); - writeFile('./dist/package.json', buildPackageJSON()); const srcFiles = readdirRecursive('./src', { ignoreDir: /^__.*__$/ }); for (const filepath of srcFiles) { @@ -34,6 +34,14 @@ if (require.main === module) { buildJSFile(filepath); } } + + const packageJSON = buildPackageJSON(); + assert( + packageJSON.version === require('../dist/version').version, + 'Version in package.json and version.js should match', + ); + + writeFile('./dist/package.json', packageJSON); } function buildJSFile(filepath) { @@ -52,13 +60,14 @@ function buildPackageJSON() { delete packageJSON.scripts; delete packageJSON.devDependencies; - const { version } = packageJSON; - const match = /^[0-9]+\.[0-9]+\.[0-9]+-?([^.]*)/.exec(version); - assert(match, 'Version does not match semver spec.'); - const tag = match[1]; - assert(!tag || tag === 'rc', 'Only "rc" tag is supported.'); + const { preReleaseTag } = parseSemver(packageJSON.version); + if (preReleaseTag != null) { + const [tag] = preReleaseTag.split('.'); + assert(tag === 'rc', 'Only "rc" tag is supported.'); + + assert(!packageJSON.publishConfig, 'Can not override "publishConfig".'); + packageJSON.publishConfig = { tag: tag || 'latest' }; + } - assert(!packageJSON.publishConfig, 'Can not override "publishConfig".'); - packageJSON.publishConfig = { tag: tag || 'latest' }; return JSON.stringify(packageJSON, null, 2); } diff --git a/resources/gen-version.js b/resources/gen-version.js new file mode 100644 index 0000000000..2b72131627 --- /dev/null +++ b/resources/gen-version.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @noflow + */ + +'use strict'; + +const { version } = require('../package.json'); +const { writeFile, parseSemver } = require('./utils'); + +const versionInfo = parseSemver(version); +const body = `/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +/** + * Note: This file is autogenerated using "resources/gen-version.js" script and + * automatically updated by "yarn version" command. + */ + +/** + * A string containing the version of the GraphQL.js library + */ +export const version = '${version}'; + +/** + * An object containing the components of the GraphQL.js version string + */ +export const versionInfo = Object.freeze({ + major: ${versionInfo.major}, + minor: ${versionInfo.minor}, + patch: ${versionInfo.patch}, + preReleaseTag: ${JSON.stringify(versionInfo.preReleaseTag || null)}, +}); +`; + +if (require.main === module) { + writeFile('./src/version.js', body); +} diff --git a/resources/utils.js b/resources/utils.js index 653bdd8db4..cf53d7dd12 100644 --- a/resources/utils.js +++ b/resources/utils.js @@ -61,10 +61,21 @@ function copyFile(srcPath, destPath) { fs.copyFileSync(srcPath, destPath); } +function parseSemver(version) { + const match = /^(\d+)\.(\d+)\.(\d+)-?(.*)?$/.exec(version); + if (!match) { + throw new Error('Version does not match semver spec: ' + version); + } + + const [, major, minor, patch, preReleaseTag] = match; + return { major, minor, patch, preReleaseTag }; +} + module.exports = { copyFile, writeFile, rmdirRecursive, mkdirRecursive, readdirRecursive, + parseSemver, }; diff --git a/src/__tests__/version-test.js b/src/__tests__/version-test.js new file mode 100644 index 0000000000..5b6eccf682 --- /dev/null +++ b/src/__tests__/version-test.js @@ -0,0 +1,43 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { version, versionInfo } from '../version'; + +describe('Version', () => { + it('version', () => { + expect(version).to.be.a('string'); + expect(version).to.match(/^\d+\.\d+\.\d(-rc.\d+)?$/); + }); + + it('versionInfo', () => { + expect(versionInfo).to.be.an('object'); + expect(versionInfo).to.have.all.keys( + 'major', + 'minor', + 'patch', + 'preReleaseTag', + ); + + const { major, minor, patch, preReleaseTag } = versionInfo; + + expect(major).to.be.a('number'); + expect(minor).to.be.a('number'); + expect(patch).to.be.a('number'); + if (preReleaseTag !== null) { + expect(preReleaseTag).to.be.a('string'); + } + + expect( + `${major}.${minor}.${patch}` + + (preReleaseTag !== null ? '-' + preReleaseTag : ''), + ).to.equal(version); + }); +}); diff --git a/src/index.js b/src/index.js index e52bd6a186..a84745e0f4 100644 --- a/src/index.js +++ b/src/index.js @@ -31,6 +31,9 @@ * import { parse } from 'graphql/language'; */ +// The GraphQL.js version info. +export { version, versionInfo } from './version'; + // The primary entry point into fulfilling a GraphQL request. export type { GraphQLArgs } from './graphql'; export { graphql, graphqlSync } from './graphql'; diff --git a/src/version.js b/src/version.js new file mode 100644 index 0000000000..e8dea7a83f --- /dev/null +++ b/src/version.js @@ -0,0 +1,28 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + */ + +/** + * Note: This file is autogenerated using "resources/gen-version.js" script and + * automatically updated by "yarn version" command. + */ + +/** + * A string containing the version of the GraphQL.js library + */ +export const version = '14.3.0'; + +/** + * An object containing the components of the GraphQL.js version string + */ +export const versionInfo = Object.freeze({ + major: 14, + minor: 3, + patch: 0, + preReleaseTag: null, +});