UNPKG

3.7 kBJavaScriptView Raw
1import path from 'path';
2import { promisify } from 'util';
3import fs from 'fs';
4const readFile = promisify(fs.readFile);
5/**
6 * Send a string to lowercase
7 * @param str the string to lowercase
8 * @returns the lowercased string
9 */
10export const toLowerCase = (str) => str.toLowerCase();
11/**
12 * Convert a string using dash-case to PascalCase
13 * @param str the string to convert to PascalCase
14 * @returns the PascalCased string
15 */
16export const dashToPascalCase = (str) => toLowerCase(str)
17 .split('-')
18 .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
19 .join('');
20/**
21 * Sorts a provided array by a property belonging to an item that exists on each item in the array
22 * @param array the array to sort
23 * @param prop a function to look up a field on an entry in the provided array
24 * @returns a shallow copy of the array, sorted by the property resolved by `prop`
25 */
26export function sortBy(array, prop) {
27 return array.slice().sort((a, b) => {
28 const nameA = prop(a);
29 const nameB = prop(b);
30 if (nameA < nameB)
31 return -1;
32 if (nameA > nameB)
33 return 1;
34 return 0;
35 });
36}
37/**
38 * Normalize a path
39 * @param str the path to normalize
40 * @returns the normalized path
41 */
42export function normalizePath(str) {
43 // Convert Windows backslash paths to slash paths: foo\\bar ➔ foo/bar
44 // https://github.com/sindresorhus/slash MIT
45 // By Sindre Sorhus
46 if (typeof str !== 'string') {
47 throw new Error(`invalid path to normalize`);
48 }
49 str = str.trim();
50 if (EXTENDED_PATH_REGEX.test(str) || NON_ASCII_REGEX.test(str)) {
51 return str;
52 }
53 str = str.replace(SLASH_REGEX, '/');
54 // always remove the trailing /
55 // this makes our file cache look ups consistent
56 if (str.charAt(str.length - 1) === '/') {
57 const colonIndex = str.indexOf(':');
58 if (colonIndex > -1) {
59 if (colonIndex < str.length - 2) {
60 str = str.substring(0, str.length - 1);
61 }
62 }
63 else if (str.length > 1) {
64 str = str.substring(0, str.length - 1);
65 }
66 }
67 return str;
68}
69/**
70 * Generate the relative import from `pathFrom` to `pathTo`
71 * @param pathFrom the path that shall be used as the origin in determining the relative path
72 * @param pathTo the path that shall be used as the destination in determining the relative path
73 * @param ext an extension to remove from the final path
74 * @returns the derived relative import
75 */
76export function relativeImport(pathFrom, pathTo, ext) {
77 let relativePath = path.relative(path.dirname(pathFrom), path.dirname(pathTo));
78 if (relativePath === '') {
79 relativePath = '.';
80 }
81 else if (relativePath[0] !== '.') {
82 relativePath = './' + relativePath;
83 }
84 return normalizePath(`${relativePath}/${path.basename(pathTo, ext)}`);
85}
86/**
87 * Attempts to read a `package.json` file at the provided directory.
88 * @param rootDir the directory to search for the `package.json` file to read
89 * @returns the read and parsed `package.json` file
90 */
91export async function readPackageJson(rootDir) {
92 const pkgJsonPath = path.join(rootDir, 'package.json');
93 let pkgJson;
94 try {
95 pkgJson = await readFile(pkgJsonPath, 'utf8');
96 }
97 catch (e) {
98 throw new Error(`Missing "package.json" file for distribution: ${pkgJsonPath}`);
99 }
100 let pkgData;
101 try {
102 pkgData = JSON.parse(pkgJson);
103 }
104 catch (e) {
105 throw new Error(`Error parsing package.json: ${pkgJsonPath}, ${e}`);
106 }
107 return pkgData;
108}
109const EXTENDED_PATH_REGEX = /^\\\\\?\\/;
110const NON_ASCII_REGEX = /[^\x00-\x80]+/;
111const SLASH_REGEX = /\\/g;