refactor: convert function expressions to declarations (#4926)
This commit is contained in:
committed by
GitHub
parent
c0236536dd
commit
141a2eba56
@ -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()],
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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' }));
|
||||
};
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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}`);
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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}`);
|
||||
};
|
||||
}
|
||||
|
@ -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),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -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());
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user