refactor: convert function expressions to declarations (#4926)

This commit is contained in:
Vladislav Shkodin
2021-02-08 20:01:21 +02:00
committed by GitHub
parent c0236536dd
commit 141a2eba56
241 changed files with 3444 additions and 2933 deletions

View File

@ -6,10 +6,10 @@ type LogOptions = {
level: string;
};
export const createLogger = ({ level }: LogOptions) => {
export function createLogger({ level }: LogOptions) {
return winston.createLogger({
level,
format: combine(colorize(), simple()),
transports: [new winston.transports.Console()],
});
};
}

View File

@ -8,20 +8,20 @@ type Options = {
logLevel?: string;
};
const createOptions = (options: Options) => {
function createOptions(options: Options) {
return {
logger: createLogger({ level: options.logLevel || 'info' }),
};
};
}
export const registerLocalGit = async (app: express.Express, options: Options = {}) => {
export async function registerLocalGit(app: express.Express, options: Options = {}) {
const opts = createOptions(options);
registerCommonMiddlewares(app, opts);
await localGit(app, opts);
};
}
export const registerLocalFs = async (app: express.Express, options: Options = {}) => {
export async function registerLocalFs(app: express.Express, options: Options = {}) {
const opts = createOptions(options);
registerCommonMiddlewares(app, opts);
await localFs(app, opts);
};
}

View File

@ -7,7 +7,7 @@ export type Options = {
logger: winston.Logger;
};
export const registerCommonMiddlewares = (app: express.Express, options: Options) => {
export function registerCommonMiddlewares(app: express.Express, options: Options) {
const { logger } = options;
const stream = {
write: (message: string) => {
@ -17,4 +17,4 @@ export const registerCommonMiddlewares = (app: express.Express, options: Options
app.use(morgan('combined', { stream }));
app.use(cors());
app.use(express.json({ limit: '50mb' }));
};
}

View File

@ -1,8 +1,8 @@
import Joi from '@hapi/joi';
import path from 'path';
export const pathTraversal = (repoPath: string) =>
Joi.extend({
export function pathTraversal(repoPath: string) {
return Joi.extend({
type: 'path',
base: Joi.string().required(),
messages: {
@ -15,3 +15,4 @@ export const pathTraversal = (repoPath: string) =>
}
},
}).path();
}

View File

@ -2,13 +2,13 @@ import { defaultSchema, joi } from '.';
import express from 'express';
import Joi from '@hapi/joi';
const assetFailure = (result: Joi.ValidationResult, expectedMessage: string) => {
function assetFailure(result: Joi.ValidationResult, expectedMessage: string) {
const { error } = result;
expect(error).not.toBeNull();
expect(error!.details).toHaveLength(1);
const message = error!.details.map(({ message }) => message)[0];
expect(message).toBe(expectedMessage);
};
}
const defaultParams = {
branch: 'master',

View File

@ -29,7 +29,7 @@ const requiredBool = Joi.bool().required();
const collection = requiredString;
const slug = requiredString;
export const defaultSchema = ({ path = requiredString } = {}) => {
export function defaultSchema({ path = requiredString } = {}) {
const defaultParams = Joi.object({
branch: requiredString,
});
@ -234,19 +234,17 @@ export const defaultSchema = ({ path = requiredString } = {}) => {
action: Joi.valid(...allowedActions).required(),
params,
});
};
}
export const joi = (schema: Joi.Schema) => (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
const { error } = schema.validate(req.body, { allowUnknown: true });
if (error) {
const { details } = error;
const message = details.map(i => i.message).join(',');
res.status(422).json({ error: message });
} else {
next();
}
};
export function joi(schema: Joi.Schema) {
return (req: express.Request, res: express.Response, next: express.NextFunction) => {
const { error } = schema.validate(req.body, { allowUnknown: true });
if (error) {
const { details } = error;
const message = details.map(i => i.message).join(',');
res.status(422).json({ error: message });
} else {
next();
}
};
}

View File

@ -2,13 +2,13 @@
import Joi from '@hapi/joi';
import { getSchema } from '.';
const assetFailure = (result: Joi.ValidationResult, expectedMessage: string) => {
function assetFailure(result: Joi.ValidationResult, expectedMessage: string) {
const { error } = result;
expect(error).not.toBeNull();
expect(error!.details).toHaveLength(1);
const message = error!.details.map(({ message }) => message)[0];
expect(message).toBe(expectedMessage);
};
}
const defaultParams = {
branch: 'master',

View File

@ -23,7 +23,7 @@ type FsOptions = {
logger: winston.Logger;
};
export const localFsMiddleware = ({ repoPath, logger }: FsOptions) => {
export function localFsMiddleware({ repoPath, logger }: FsOptions) {
return async function(req: express.Request, res: express.Response) {
try {
const { body } = req;
@ -138,21 +138,21 @@ export const localFsMiddleware = ({ repoPath, logger }: FsOptions) => {
res.status(500).json({ error: 'Unknown error' });
}
};
};
}
export const getSchema = ({ repoPath }: { repoPath: string }) => {
export function getSchema({ repoPath }: { repoPath: string }) {
const schema = defaultSchema({ path: pathTraversal(repoPath) });
return schema;
};
}
type Options = {
logger: winston.Logger;
};
export const registerMiddleware = async (app: express.Express, options: Options) => {
export async function registerMiddleware(app: express.Express, options: Options) {
const { logger } = options;
const repoPath = path.resolve(process.env.GIT_REPO_DIRECTORY || process.cwd());
app.post('/api/v1', joi(getSchema({ repoPath })));
app.post('/api/v1', localFsMiddleware({ repoPath, logger }));
logger.info(`Netlify CMS File System Proxy Server configured with ${repoPath}`);
};
}

View File

@ -1,18 +1,19 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import Joi from '@hapi/joi';
import express from 'express';
import winston from 'winston';
import { validateRepo, getSchema, localGitMiddleware } from '.';
jest.mock('netlify-cms-lib-util', () => jest.fn());
jest.mock('simple-git/promise');
const assetFailure = (result: Joi.ValidationResult, expectedMessage: string) => {
function assetFailure(result: Joi.ValidationResult, expectedMessage: string) {
const { error } = result;
expect(error).not.toBeNull();
expect(error!.details).toHaveLength(1);
const message = error!.details.map(({ message }) => message)[0];
expect(message).toBe(expectedMessage);
};
}
const defaultParams = {
branch: 'master',
@ -139,7 +140,7 @@ describe('localGitMiddleware', () => {
},
} as express.Request;
await localGitMiddleware({ repoPath })(req, res);
await localGitMiddleware({ repoPath, logger: winston.createLogger() })(req, res);
expect(status).toHaveBeenCalledTimes(1);
expect(status).toHaveBeenCalledWith(422);

View File

@ -40,7 +40,7 @@ import { pathTraversal } from '../joi/customValidators';
import { listRepoFiles, writeFile, move, deleteFile, getUpdateDate } from '../utils/fs';
import { entriesFromFiles, readMediaFile } from '../utils/entries';
const commit = async (git: simpleGit.SimpleGit, commitMessage: string) => {
async function commit(git: simpleGit.SimpleGit, commitMessage: string) {
await git.add('.');
await git.commit(commitMessage, undefined, {
// setting the value to a string passes name=value
@ -48,14 +48,14 @@ const commit = async (git: simpleGit.SimpleGit, commitMessage: string) => {
'--no-verify': null,
'--no-gpg-sign': null,
});
};
}
const getCurrentBranch = async (git: simpleGit.SimpleGit) => {
async function getCurrentBranch(git: simpleGit.SimpleGit) {
const currentBranch = await git.branchLocal().then(summary => summary.current);
return currentBranch;
};
}
const runOnBranch = async <T>(git: simpleGit.SimpleGit, branch: string, func: () => Promise<T>) => {
async function runOnBranch<T>(git: simpleGit.SimpleGit, branch: string, func: () => Promise<T>) {
const currentBranch = await getCurrentBranch(git);
try {
if (currentBranch !== branch) {
@ -66,22 +66,24 @@ const runOnBranch = async <T>(git: simpleGit.SimpleGit, branch: string, func: ()
} finally {
await git.checkout(currentBranch);
}
};
}
const branchDescription = (branch: string) => `branch.${branch}.description`;
function branchDescription(branch: string) {
return `branch.${branch}.description`;
}
type GitOptions = {
repoPath: string;
logger: winston.Logger;
};
const commitEntry = async (
async function commitEntry(
git: simpleGit.SimpleGit,
repoPath: string,
dataFiles: DataFile[],
assets: Asset[],
commitMessage: string,
) => {
) {
// save entry content
await Promise.all(
dataFiles.map(dataFile => writeFile(path.join(repoPath, dataFile.path), dataFile.raw)),
@ -98,9 +100,9 @@ const commitEntry = async (
// commits files
await commit(git, commitMessage);
};
}
const rebase = async (git: simpleGit.SimpleGit, branch: string) => {
async function rebase(git: simpleGit.SimpleGit, branch: string) {
const gpgSign = await git.raw(['config', 'commit.gpgsign']);
try {
if (gpgSign === 'true') {
@ -112,9 +114,9 @@ const rebase = async (git: simpleGit.SimpleGit, branch: string) => {
await git.addConfig('commit.gpgsign', gpgSign);
}
}
};
}
const merge = async (git: simpleGit.SimpleGit, from: string, to: string) => {
async function merge(git: simpleGit.SimpleGit, from: string, to: string) {
const gpgSign = await git.raw(['config', 'commit.gpgsign']);
try {
if (gpgSign === 'true') {
@ -126,14 +128,14 @@ const merge = async (git: simpleGit.SimpleGit, from: string, to: string) => {
await git.addConfig('commit.gpgsign', gpgSign);
}
}
};
}
const isBranchExists = async (git: simpleGit.SimpleGit, branch: string) => {
async function isBranchExists(git: simpleGit.SimpleGit, branch: string) {
const branchExists = await git.branchLocal().then(({ all }) => all.includes(branch));
return branchExists;
};
}
const getDiffs = async (git: simpleGit.SimpleGit, source: string, dest: string) => {
async function getDiffs(git: simpleGit.SimpleGit, source: string, dest: string) {
const rawDiff = await git.diff([source, dest]);
const diffs = parse(rawDiff).map(d => {
const oldPath = d.oldPath?.replace(/b\//, '') || '';
@ -150,22 +152,22 @@ const getDiffs = async (git: simpleGit.SimpleGit, source: string, dest: string)
};
});
return diffs;
};
}
export const validateRepo = async ({ repoPath }: { repoPath: string }) => {
export async function validateRepo({ repoPath }: { repoPath: string }) {
const git = simpleGit(repoPath).silent(false);
const isRepo = await git.checkIsRepo();
if (!isRepo) {
throw Error(`${repoPath} is not a valid git repository`);
}
};
}
export const getSchema = ({ repoPath }: { repoPath: string }) => {
export function getSchema({ repoPath }: { repoPath: string }) {
const schema = defaultSchema({ path: pathTraversal(repoPath) });
return schema;
};
}
export const localGitMiddleware = ({ repoPath, logger }: GitOptions) => {
export function localGitMiddleware({ repoPath, logger }: GitOptions) {
const git = simpleGit(repoPath).silent(false);
// we can only perform a single git operation at any given time
@ -443,17 +445,17 @@ export const localGitMiddleware = ({ repoPath, logger }: GitOptions) => {
release && release();
}
};
};
}
type Options = {
logger: winston.Logger;
};
export const registerMiddleware = async (app: express.Express, options: Options) => {
export async function registerMiddleware(app: express.Express, options: Options) {
const { logger } = options;
const repoPath = path.resolve(process.env.GIT_REPO_DIRECTORY || process.cwd());
await validateRepo({ repoPath });
app.post('/api/v1', joi(getSchema({ repoPath })));
app.post('/api/v1', localGitMiddleware({ repoPath, logger }));
logger.info(`Netlify CMS Git Proxy Server configured with ${repoPath}`);
};
}

View File

@ -2,20 +2,22 @@ import crypto from 'crypto';
import path from 'path';
import { promises as fs } from 'fs';
const sha256 = (buffer: Buffer) => {
function sha256(buffer: Buffer) {
return crypto
.createHash('sha256')
.update(buffer)
.digest('hex');
};
}
// normalize windows os path format
const normalizePath = (path: string) => path.replace(/\\/g, '/');
function normalizePath(path: string) {
return path.replace(/\\/g, '/');
}
export const entriesFromFiles = async (
export async function entriesFromFiles(
repoPath: string,
files: { path: string; label?: string }[],
) => {
) {
return Promise.all(
files.map(async file => {
try {
@ -32,9 +34,9 @@ export const entriesFromFiles = async (
}
}),
);
};
}
export const readMediaFile = async (repoPath: string, file: string) => {
export async function readMediaFile(repoPath: string, file: string) {
const encoding = 'base64';
const buffer = await fs.readFile(path.join(repoPath, file));
const id = sha256(buffer);
@ -46,4 +48,4 @@ export const readMediaFile = async (repoPath: string, file: string) => {
path: normalizePath(file),
name: path.basename(file),
};
};
}

View File

@ -1,7 +1,7 @@
import path from 'path';
import { promises as fs } from 'fs';
const listFiles = async (dir: string, extension: string, depth: number): Promise<string[]> => {
async function listFiles(dir: string, extension: string, depth: number): Promise<string[]> {
if (depth <= 0) {
return [];
}
@ -20,33 +20,33 @@ const listFiles = async (dir: string, extension: string, depth: number): Promise
} catch (e) {
return [];
}
};
}
export const listRepoFiles = async (
export async function listRepoFiles(
repoPath: string,
folder: string,
extension: string,
depth: number,
) => {
) {
const files = await listFiles(path.join(repoPath, folder), extension, depth);
return files.map(f => f.substr(repoPath.length + 1));
};
}
export const writeFile = async (filePath: string, content: Buffer | string) => {
export async function writeFile(filePath: string, content: Buffer | string) {
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, content);
};
}
export const deleteFile = async (repoPath: string, filePath: string) => {
export async function deleteFile(repoPath: string, filePath: string) {
await fs.unlink(path.join(repoPath, filePath)).catch(() => undefined);
};
}
const moveFile = async (from: string, to: string) => {
async function moveFile(from: string, to: string) {
await fs.mkdir(path.dirname(to), { recursive: true });
await fs.rename(from, to);
};
}
export const move = async (from: string, to: string) => {
export async function move(from: string, to: string) {
// move file
await moveFile(from, to);
@ -55,11 +55,11 @@ export const move = async (from: string, to: string) => {
const destDir = path.dirname(to);
const allFiles = await listFiles(sourceDir, '', 100);
await Promise.all(allFiles.map(file => moveFile(file, file.replace(sourceDir, destDir))));
};
}
export const getUpdateDate = async (repoPath: string, filePath: string) => {
export async function getUpdateDate(repoPath: string, filePath: string) {
return fs
.stat(path.join(repoPath, filePath))
.then(stat => stat.mtime)
.catch(() => new Date());
};
}