Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: prepare new release #34

Merged
merged 6 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bin/smoke
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/usr/bin/env node
require('../smoke-cli.js')(process.argv.slice(2));
import { run } from '../smoke-cli.js';
await run(process.argv.slice(2));
3 changes: 2 additions & 1 deletion bin/smoke-conv
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/usr/bin/env node
require('../smoke-conv-cli.js')(process.argv.slice(2));
import { run } from '../smoke-conv-cli.js';
await run(process.argv.slice(2));
31 changes: 15 additions & 16 deletions lib/convert.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
const {getMockFiles, getMocksFromCollections, getMock, getMockContent} = require('./mock');
const {mockCollectionExt, writeMock, writeMockCollection} = require('./recorder');
import process from 'node:process';
import {getMockFiles, getMocksFromCollections, getMock, getMockContent} from './mock.js';
import {mockCollectionExt, writeMock, writeMockCollection} from './recorder.js';

async function convert(input, output, ignore = null, depth = null) {
function isMockCollection(file) {
return file.endsWith(mockCollectionExt) || file.endsWith(mockCollectionExt.replace('js', 'cjs'));
}

export async function convert(input, output, ignore = null, depth = null) {
depth = typeof depth === 'number' ? depth : 1;

const files = await getMockFiles(process.cwd(), ignore ? [ignore] : [], [input]);
const mockCollectionFiles = files.filter((file) => file.endsWith(mockCollectionExt));
const mockFiles = files.filter((file) => !file.endsWith(mockCollectionExt));
const mockCollectionFiles = files.filter((file) => isMockCollection(file));
const mockFiles = files.filter((file) => !isMockCollection(file));

if (files.length === 0) {
return console.error('No files to convert');
Expand All @@ -25,26 +30,26 @@ async function convert(input, output, ignore = null, depth = null) {
return convertMocks(mockFiles, output);
}

function convertMockCollection(file, outputFolder, depth) {
export async function convertMockCollection(file, outputFolder, depth) {
return Promise.all(
getMocksFromCollections(process.cwd(), [file]).map(async (mock) => {
(await getMocksFromCollections(process.cwd(), [file])).map(async (mock) => {
try {
await writeMock(mock, outputFolder, depth);
} catch (error) {
console.error(`Error while converting "${file}"`, error.message);
}
})
}),
);
}

async function convertMocks(files, outputFile) {
export async function convertMocks(files, outputFile) {
try {
const mocks = await Promise.all(
files.map(async (file) => {
const mock = getMock(process.cwd(), file);
mock.data = await getMockContent(mock);
return mock;
})
}),
);
mocks.sort((a, b) => a.file.localeCompare(b.file));

Expand All @@ -53,9 +58,3 @@ async function convertMocks(files, outputFile) {
console.error(`Error during conversion`, error);
}
}

module.exports = {
convert,
convertMockCollection,
convertMocks
};
83 changes: 37 additions & 46 deletions lib/mock.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
const path = require('path');
const fs = require('fs-extra');
const globby = require('globby');
const {pathToRegexp} = require('path-to-regexp');
const importFresh = require('import-fresh');
import process from 'node:process';
import path from 'node:path';
import fs from 'node:fs/promises';
import globby from 'globby';
import {pathToRegexp} from 'path-to-regexp';

const methodRegExp = /^([a-z+]+?)_/i;
const paramsRegExp = /[$?]([^.\s]+$)/;
const setRegExp = /__([\w-]+?)$/;
const defaultType = 'application/octet-stream';

class MockContentError extends Error {
const importFresh = async (moduleName) => import(`${moduleName}?${Date.now()}`);

export class MockContentError extends Error {
constructor(message, error) {
super(message);
this.innerError = error;
Expand All @@ -20,7 +22,7 @@ class MockContentError extends Error {
}
}

function getMock(basePath, file, data = undefined) {
export function getMock(basePath, file, data = undefined) {
let ext = path.extname(file);
const isTemplate = ext.endsWith('_');
let basename = path.basename(file, ext);
Expand Down Expand Up @@ -58,28 +60,22 @@ function getMock(basePath, file, data = undefined) {
.dirname(file)
.split(path.delimiter)
.filter((c) => c && c !== '.');
const fileComponents = basename.split('#').filter((c) => c);
const fileComponents = basename.split('#').filter(Boolean);
let methods = null;
const matchMethods = fileComponents[0].match(methodRegExp);

if (matchMethods) {
methods = matchMethods[1];
fileComponents[0] = fileComponents[0].slice(Math.max(0, methods.length + 1));

if (methods) {
methods = methods
.split('+')
.filter((m) => m)
.map((m) => m.toLowerCase());
}
methods &&= methods
.split('+')
.filter(Boolean)
.map((m) => m.toLowerCase());
}

const reqPath = dirComponents
.concat(fileComponents)
.filter((c) => c)
.join('/')
.replace(/@/g, ':');
const keys = [];
const reqPath = [...dirComponents, ...fileComponents].filter(Boolean).join('/').replaceAll('@', ':');
const {regexp, keys} = pathToRegexp(reqPath);

return {
file: path.join(basePath, file),
Expand All @@ -89,18 +85,18 @@ function getMock(basePath, file, data = undefined) {
isTemplate,
methods,
reqPath,
regexp: pathToRegexp(reqPath, keys),
regexp,
keys,
params,
data
data,
};
}

async function getMocks(basePath, ignoreGlobs, globs = ['**/*']) {
export async function getMocks(basePath, ignoreGlobs, globs = ['**/*']) {
let mockFiles = await getMockFiles(basePath, ignoreGlobs, globs);
const mockCollectionFiles = [];
mockFiles = mockFiles.filter((mock) => {
if (mock.endsWith('.mocks.js')) {
if (mock.endsWith('.mocks.js') || mock.endsWith('.mocks.cjs')) {
mockCollectionFiles.push(mock);
return false;
}
Expand All @@ -110,10 +106,10 @@ async function getMocks(basePath, ignoreGlobs, globs = ['**/*']) {

return mockFiles
.map((file) => getMock(basePath, file))
.concat(getMocksFromCollections(basePath, mockCollectionFiles));
.concat(await getMocksFromCollections(basePath, mockCollectionFiles));
}

function getMockFiles(basePath, ignoreGlobs, globs) {
export function getMockFiles(basePath, ignoreGlobs, globs) {
if (!basePath) {
globs.push('!node_modules');
}
Expand All @@ -123,35 +119,39 @@ function getMockFiles(basePath, ignoreGlobs, globs) {
return globby(globs.concat(ignoreGlobs), {cwd: basePath});
}

function getMocksFromCollections(basePath, mockCollectionFiles) {
return mockCollectionFiles.reduce((mocks, file) => {
export async function getMocksFromCollections(basePath, mockCollectionFiles) {
let mocks = [];
basePath = path.isAbsolute(basePath) ? basePath : path.join(process.cwd(), basePath);

for (const file of mockCollectionFiles) {
try {
basePath = path.isAbsolute(basePath) ? basePath : path.join(process.cwd(), basePath);
const collection = importFresh(path.join(basePath, file));
// eslint-disable-next-line no-await-in-loop
const collection = (await importFresh(path.join(basePath, file))).default;
const newMocks = Object.entries(collection).map(([route, data]) => getMock(basePath, route, data));
return mocks.concat(newMocks);
mocks = mocks.concat(newMocks);
} catch (error) {
console.error(`Error while loading collection "${file}"`, error);
return mocks;
}
}, []);
}

return mocks;
}

async function getMockContent(mock) {
export async function getMockContent(mock) {
let content;

if (mock.data !== undefined) {
content = mock.data;
} else if (mock.isTemplate || mock.ext === 'json') {
try {
content = await fs.readFile(mock.file, 'utf-8');
content = await fs.readFile(mock.file, 'utf8');
} catch (error) {
throw new MockContentError(`Error while reading mock file "${mock.file}"`, error);
}
} else if (mock.ext === 'js') {
} else if (mock.ext === 'js' || mock.ext === 'cjs') {
try {
const filePath = path.isAbsolute(mock.file) ? mock.file : path.join(process.cwd(), mock.file);
content = importFresh(filePath);
content = (await importFresh(filePath)).default;
} catch {
throw new MockContentError(`Error while evaluating JS for mock "${mock.file}"`);
}
Expand All @@ -166,12 +166,3 @@ async function getMockContent(mock) {

return content;
}

module.exports = {
MockContentError,
getMock,
getMocks,
getMockFiles,
getMocksFromCollections,
getMockContent
};
Loading
Loading