mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-28 15:20:58 -05:00
fix(backend): Use regex to parse version
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
69a7a1ae69
commit
7b2d541cac
2 changed files with 112 additions and 40 deletions
|
@ -5,23 +5,80 @@
|
||||||
*/
|
*/
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
|
|
||||||
import { getServerVersionFromPackageJson } from './serverVersion';
|
import {
|
||||||
|
clearCachedVersion,
|
||||||
|
getServerVersionFromPackageJson,
|
||||||
|
} from './serverVersion';
|
||||||
|
|
||||||
it('getServerVersionFromPackageJson works', async () => {
|
jest.mock('fs', () => ({
|
||||||
const major = 2;
|
promises: {
|
||||||
const minor = 0;
|
readFile: jest.fn(),
|
||||||
const patch = 0;
|
},
|
||||||
const preRelease = 'dev';
|
}));
|
||||||
/* eslint-disable @typescript-eslint/require-await*/
|
|
||||||
jest.spyOn(fs, 'readFile').mockImplementationOnce(async (_) => {
|
describe('getServerVersionFromPackageJson', () => {
|
||||||
return `{
|
afterEach(() => {
|
||||||
"version": "${major}.${minor}.${patch}"
|
clearCachedVersion();
|
||||||
}
|
});
|
||||||
`;
|
|
||||||
|
it('parses a complete version string', async () => {
|
||||||
|
const major = 2;
|
||||||
|
const minor = 0;
|
||||||
|
const patch = 0;
|
||||||
|
const preRelease = 'dev';
|
||||||
|
jest
|
||||||
|
.spyOn(fs, 'readFile')
|
||||||
|
.mockImplementationOnce(
|
||||||
|
async (_) =>
|
||||||
|
`{ "version": "${major}.${minor}.${patch}-${preRelease}" }`,
|
||||||
|
);
|
||||||
|
const serverVersion = await getServerVersionFromPackageJson();
|
||||||
|
expect(serverVersion.major).toEqual(major);
|
||||||
|
expect(serverVersion.minor).toEqual(minor);
|
||||||
|
expect(serverVersion.patch).toEqual(patch);
|
||||||
|
expect(serverVersion.preRelease).toEqual(preRelease);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parses a version string without pre release', async () => {
|
||||||
|
const major = 2;
|
||||||
|
const minor = 0;
|
||||||
|
const patch = 0;
|
||||||
|
jest
|
||||||
|
.spyOn(fs, 'readFile')
|
||||||
|
.mockImplementationOnce(
|
||||||
|
async (_) => `{ "version": "${major}.${minor}.${patch}" }`,
|
||||||
|
);
|
||||||
|
const serverVersion = await getServerVersionFromPackageJson();
|
||||||
|
expect(serverVersion.major).toEqual(major);
|
||||||
|
expect(serverVersion.minor).toEqual(minor);
|
||||||
|
expect(serverVersion.patch).toEqual(patch);
|
||||||
|
expect(serverVersion.preRelease).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if package.json can't be found", async () => {
|
||||||
|
jest.spyOn(fs, 'readFile').mockImplementationOnce(async (_) => {
|
||||||
|
throw new Error('package.json not found');
|
||||||
|
});
|
||||||
|
await expect(getServerVersionFromPackageJson()).rejects.toThrow(
|
||||||
|
'package.json not found',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if version isn't present in package.json", async () => {
|
||||||
|
jest.spyOn(fs, 'readFile').mockImplementationOnce(async (_) => `{ }`);
|
||||||
|
await expect(getServerVersionFromPackageJson()).rejects.toThrow(
|
||||||
|
'No version found in root package.json',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws an error if the version is malformed', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(fs, 'readFile')
|
||||||
|
.mockImplementationOnce(
|
||||||
|
async (_) => `{ "version": "TwoDotZeroDotZero" }`,
|
||||||
|
);
|
||||||
|
await expect(getServerVersionFromPackageJson()).rejects.toThrow(
|
||||||
|
'Version from package.json is malformed. Got TwoDotZeroDotZero',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
const serverVersion = await getServerVersionFromPackageJson();
|
|
||||||
expect(serverVersion.major).toEqual(major);
|
|
||||||
expect(serverVersion.minor).toEqual(minor);
|
|
||||||
expect(serverVersion.patch).toEqual(patch);
|
|
||||||
expect(serverVersion.preRelease).toEqual(preRelease);
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,36 +3,51 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
import { Optional } from '@mrdrogdrog/optional';
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { join as joinPath } from 'path';
|
import { join as joinPath } from 'path';
|
||||||
|
|
||||||
import { ServerVersion } from '../monitoring/server-status.dto';
|
import { ServerVersion } from '../monitoring/server-status.dto';
|
||||||
|
|
||||||
let versionCache: ServerVersion;
|
let versionCache: ServerVersion | undefined = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the HedgeDoc version from the root package.json. This is done only once per run.
|
||||||
|
*
|
||||||
|
* @return {Promise<ServerVersion>} A Promise that contains the parsed server version.
|
||||||
|
* @throws {Error} if the package.json couldn't be found or doesn't contain a correct version.
|
||||||
|
*/
|
||||||
export async function getServerVersionFromPackageJson(): Promise<ServerVersion> {
|
export async function getServerVersionFromPackageJson(): Promise<ServerVersion> {
|
||||||
if (versionCache === undefined) {
|
if (!versionCache) {
|
||||||
const rawFileContent: string = await fs.readFile(
|
versionCache = await parseVersionFromPackageJson();
|
||||||
joinPath(__dirname, '../../package.json'),
|
|
||||||
{ encoding: 'utf8' },
|
|
||||||
);
|
|
||||||
// TODO: Should this be validated in more detail?
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
||||||
const packageInfo: { version: string } = JSON.parse(rawFileContent);
|
|
||||||
const versionParts: number[] = packageInfo.version
|
|
||||||
.split('.')
|
|
||||||
.map((x) => parseInt(x, 10));
|
|
||||||
const preRelease = 'dev'; // TODO: Replace this?
|
|
||||||
versionCache = {
|
|
||||||
major: versionParts[0],
|
|
||||||
minor: versionParts[1],
|
|
||||||
patch: versionParts[2],
|
|
||||||
preRelease: preRelease,
|
|
||||||
fullString: `${versionParts[0]}.${versionParts[1]}.${versionParts[2]}${
|
|
||||||
preRelease ? '-' + preRelease : ''
|
|
||||||
}`,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return versionCache;
|
return versionCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function parseVersionFromPackageJson(): Promise<ServerVersion> {
|
||||||
|
const rawFileContent: string = await fs.readFile(
|
||||||
|
joinPath(__dirname, '../../../package.json'),
|
||||||
|
{ encoding: 'utf8' },
|
||||||
|
);
|
||||||
|
const packageInfo = JSON.parse(rawFileContent) as { version: string };
|
||||||
|
const versionParts = Optional.ofNullable(packageInfo.version)
|
||||||
|
.orThrow(() => new Error('No version found in root package.json'))
|
||||||
|
.map((version) => /^(\d+).(\d+).(\d+)(?:-(\w+))?$/g.exec(version))
|
||||||
|
.orElseThrow(
|
||||||
|
() =>
|
||||||
|
new Error(
|
||||||
|
`Version from package.json is malformed. Got ${packageInfo.version}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
major: parseInt(versionParts[1]),
|
||||||
|
minor: parseInt(versionParts[2]),
|
||||||
|
patch: parseInt(versionParts[3]),
|
||||||
|
preRelease: versionParts[4],
|
||||||
|
fullString: versionParts[0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearCachedVersion(): void {
|
||||||
|
versionCache = undefined;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue