UNPKG

6.93 kBTypeScriptView Raw
1import { Logger } from "@lbu/insight";
2import { ExecOptions, SpawnOptions } from "child_process";
3
4interface UuidFunc {
5 /**
6 * Return a new uuid v4
7 */ (): string;
8
9 /**
10 * Returns true if value conforms a basic uuid structure.
11 * This check is case-insensitive.
12 */
13 isValid(value: any): boolean;
14}
15
16/**
17 * Return a new uuid v4
18 * @example
19 * ```js
20 * uuid();
21 * // => f3283b08-08c4-43fc-9fa6-e36c0ab2b61a
22 * ```
23 */
24export declare const uuid: UuidFunc;
25
26/**
27 * AppErrors represent errors, that should immediately stop the request and return a
28 * status and other meta data directly
29 * @example
30 * ```js
31 * new AppError(401, "error.server.unauthorized");
32 * AppError.validationError("validation.string.length", { message: "String should have at
33 * least 3 characters" }); AppError.serverError({}, new Error("Oopsie"));
34 * ```
35 */
36export class AppError<T extends any> extends Error {
37 /**
38 * Key is preferred to be in the following format
39 * ```
40 * "foo.bar"
41 * "error.server.notImplemented"
42 * ```
43 */
44 public key: string;
45
46 /**
47 * Status number to send to the api client
48 */
49 public status: number;
50
51 /**
52 * Extra information in the form of an object for the client to use
53 */
54 public info: T;
55
56 /**
57 * Optional original error that was thrown
58 */
59 public originalError?: Error;
60
61 /**
62 * Create a new AppError
63 */
64 constructor(key: string, status: number, info?: T, originalError?: Error);
65
66 /**
67 * Check if value contains the properties to at least act like a valid AppError
68 */
69 static instanceOf(value: unknown): value is AppError<unknown>;
70
71 /**
72 * Create a new 404 not found error
73 */
74 static notFound<T extends any>(info?: T, error?: Error): AppError<T>;
75
76 /**
77 * Create a new 405 not implemented error
78 */
79 static notImplemented<T extends any>(info?: T, error?: Error): AppError<T>;
80
81 /**
82 * Create a new 500 internal server error
83 */
84 static serverError<T extends any>(info?: T, error?: Error): AppError<T>;
85
86 /**
87 * Create a new 400 validation error
88 */
89 static validationError<T extends any>(
90 key: string,
91 info?: T,
92 error?: Error,
93 ): AppError<T>;
94
95 /**
96 * Format errors recursively
97 */
98 static format<T extends any>(
99 e: AppError<T> | Error,
100 skipStack?: boolean,
101 ):
102 | {
103 key: string;
104 status: number;
105 info: T;
106 originalError: any;
107 stack: string[];
108 }
109 | { name: string; message: string; stack: string[] };
110}
111
112/**
113 * Check if item is null or undefined
114 * @example
115 * ```js
116 * isNil(null);
117 * // => true
118 * isNil(undefined);
119 * // => true
120 * isNil({});
121 * // => false
122 * ```
123 */
124export function isNil<T>(
125 value: T | null | undefined,
126): value is null | undefined;
127
128/**
129 * Check if item is a plain javascript object
130 * Not completely bullet proof
131 * @example
132 * ```js
133 * isPlainObject("foo");
134 * // => false
135 * isPlainObject(new (class Foo {}));
136 * // => false
137 * isPlainObject([]);
138 * // => false
139 * isPlainObject({});
140 * // => true
141 * ```
142 */
143export function isPlainObject(obj: any): boolean;
144
145/**
146 * Re expose lodash.merge
147 * TODO: Note that lodash.merge is deprecated although it doesnt say so when installing
148 * **Note:** This method mutates `object`.
149 * @example
150 * ```js
151 * merge({}, {});
152 * // => {}
153 * merge({}, { foo: true});
154 * // => { foo: true }
155 * merge({ bar: 1 }, { bar: 2 });
156 * // => { bar: 2 }
157 * ```
158 */
159export function merge(object: any, ...sources: any[]): any;
160
161/**
162 * Flattens the given nested object, skipping anything that is not a plain object
163 * @example
164 * ```js
165 * flatten({ foo: { bar: 2 } });
166 * // => { "foo.bar": 2 }
167 * ```
168 */
169export function flatten(
170 object: any,
171 result?: any,
172 path?: string,
173): { [key: string]: any };
174
175/**
176 * Opposite of flatten
177 * @example
178 * ```js
179 * unFlatten({ "foo.bar": 2});
180 * // => { foo: { bar: 2 } }
181 * ```
182 */
183export function unFlatten(data?: { [keys: string]: any }): any;
184
185/**
186 * Convert a camelCase string to a snake_case string
187 *
188 * @example
189 * ```js
190 * camelToSnakeCase("fooBBar");
191 * // => "foo_b_bar"
192 * ```
193 */
194export function camelToSnakeCase(input: string): string;
195
196/**
197 * Promisify version of child_process#exec
198 * @example
199 * ```js
200 * exec("uname -m");
201 * // => Promise<{ stdout: "x86_64\n", stderr: "", exitCode: 0 }>
202 * ```
203 */
204export function exec(
205 command: string,
206 opts?: ExecOptions,
207): Promise<{ stdout: string; stderr: string; exitCode: number }>;
208
209/**
210 * A promise wrapper around child_process#spawn
211 * @example
212 * ```js
213 * spawn("ls", ["-al"], { cwd: "/home" });
214 * // => Promise<{ exitCode: 0 }>
215 * ```
216 */
217export function spawn(
218 command: string,
219 args: string[],
220 opts?: SpawnOptions,
221): Promise<{ exitCode: number }>;
222
223/**
224 * Read a readable stream completely, and return as Buffer
225 */
226export function streamToBuffer(stream: ReadableStream): Promise<Buffer>;
227
228/**
229 * Options for processDirectoryRecursive and processDirectoryRecursiveSync
230 */
231export interface ProcessDirectoryOptions {
232 /**
233 * Skip node_modules directory, true by default
234 */
235 skipNodeModules?: boolean;
236
237 /**
238 * Skip files and directories starting with a '.', true
239 * by default
240 */
241 skipDotFiles?: boolean;
242}
243
244/**
245 * Recursively walks directory async and calls cb on all files
246 *
247 */
248export function processDirectoryRecursive(
249 dir: string,
250 cb: (file: string) => Promise<void> | void,
251 opts?: ProcessDirectoryOptions,
252): Promise<void>;
253
254/**
255 * Recursively walks directory synchronous and calls cb on all files
256 */
257export function processDirectoryRecursiveSync(
258 dir: string,
259 cb: (file: string) => void,
260 opts?: ProcessDirectoryOptions,
261): void;
262
263/**
264 * Reexport of path#join
265 * @example
266 * ```js
267 * pathJoin("/foo", "bar");
268 * // => "/foo/bar"
269 * ```
270 */
271export function pathJoin(...parts: string[]): string;
272
273/**
274 * Return seconds since unix epoch
275 */
276export function getSecondsSinceEpoch(): number;
277
278/**
279 * An empty function, doing exactly nothing but returning undefined.
280 */
281export function noop(): void;
282
283/**
284 * HACKY
285 * Let V8 know to please run the garbage collector.
286 */
287export function gc(): void;
288
289export interface MainFnCallback {
290 (logger: Logger): void | Promise<void>;
291}
292
293/**
294 * Run the provided cb if this file is the process entrypoint
295 * Will also load dotenv before executing the provided callback.
296 * Another side effect is that a process listener is added for warnings
297 */
298export function mainFn(meta: ImportMeta, cb: MainFnCallback): void;
299
300/**
301 * Return filename for ES Module
302 * Alternative to CommonJS __filename
303 */
304export function filenameForModule(meta: ImportMeta): string;
305
306/**
307 * Return dirname for ES Module
308 * Alternative to CommonJS __dirname
309 */
310export function dirnameForModule(meta: ImportMeta): string;
311
312/**
313 * Returns whether NODE_ENV === "production"
314 */
315export function isProduction(): boolean;
316
317/**
318 * Returns whether NODE_ENV !== "production" OR IS_STAGING === "true"
319 */
320export function isStaging(): boolean;