UNPKG

templates-mo

Version:

Templates is a scaffolding framework that makes code generation simple, dynamic, and reusable. Generate files, parts of your app, or whole project structures—without the repetitive copy-pasting

164 lines (141 loc) • 3.52 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ import * as is from 'is'; import path from 'path'; import paths from 'npm-paths'; import { CWD } from './constants'; export function hasProp(obj: Record<string, any>, prop: string): boolean { return Object.prototype.hasOwnProperty.call(obj, prop); } /** * Loop through a object property. Will break out of loop if `cb` returns false * @param obj - object to loop through * @param cb - Function to call on every property */ export function eachObj( obj: Record<string, any>, cb: (val: any, key: string) => void | boolean, ) { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; if (!(is as any).undef(obj[key])) { const val = obj[key]; if (cb(val, key) === false) { break; } } } } /** * Check to see if `obj` matches `matcher` * @param matcher * @param obj - object to match against `matcher` */ export function couldMatchObj( matcher: Record<string, any>, obj: Record<string, any>, ): boolean { let matched = true; eachObj(matcher, (val, key) => { switch (typeof val) { case 'function': matched = val(obj[key]); break; case 'object': if (val.not) { matched = val.not !== obj[key]; break; } // eslint-disable-next-line no-fallthrough default: matched = val === obj[key]; } // matched = val === obj[key]; return matched; }); return matched; } /** * Makes `options` inherit all properties it doesnt have from `default` * @param options * @param defaultObj - default properties that you want `options` to have * @returns - options with all default properties */ export function defaults<T extends object>( options: Partial<T>, defaultObj: T, ): T { const newObj: T = { ...options } as T; eachObj(defaultObj, (val, key) => { if (!hasProp(options, key) || is.undefined(options[key])) { newObj[key] = val; } }); return newObj; } export function cliLog(str: string): void { const string = str .split(/\n/) .map((s) => s.trim()) .join('\n') .trim(); // eslint-disable-next-line console.log(string); } /** * Get all npm paths */ export const getNpmPaths = (cwd: string = CWD): string[] => { return paths(cwd); }; /** * Get a list of all parent directories from a directory * * @example * getAllDirectoriesAndUp("/User/marcellinoornelas/Desktop/random") * // returns * [ * "/User/marcellinoornelas/Desktop/random", * "/User/marcellinoornelas/Desktop", * "/User/marcellinoornelas", * "/User", * "/", * ] */ export const getAllDirectoriesAndUp = (dir): string[] => { const parent = path.dirname(dir); if (dir === parent) return [dir]; return [dir, ...getAllDirectoriesAndUp(parent)]; }; /** * Unflatten an array */ export const flatten = <T>(arr: T[][]): T[] => { return arr.reduce((unflattened, subArr) => { unflattened.push(...subArr); return unflattened; }, []); }; export const unique = <T extends string | number>(array: T[]): T[] => { const tracker: Record<string, boolean> = {}; const uniqueArray: T[] = []; array.forEach((item) => { const string = item.toString(); if (tracker[string]) return; tracker[string] = true; uniqueArray.push(item); }); return uniqueArray; }; /** * strip the prefix from the provided string * * @example * stripPrefix("tps-app", "tps-"); // "app" */ export const stripPrefix = (str: string, prefix: string): string => { if (str.startsWith(prefix)) { return str.slice(prefix.length); } return str; };