@serwist/utils 10.0.0-preview.1 → 10.0.0-preview.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ import { nonNullable } from "./nonNullable.js";
2
+ import { parallel } from "./parallel.js";
3
+ export { nonNullable, parallel };
4
+ export { slash, toUnix, resolveBasePath, isAbsolute } from "./paths.js";
5
+ export type * from "./types.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxE,mBAAmB,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -26,8 +26,18 @@ const parallel = async (limit, array, func)=>{
26
26
  return results;
27
27
  };
28
28
 
29
+ const slash = (str)=>{
30
+ return str.replace(/\\/g, "/");
31
+ };
29
32
  const toUnix = (p)=>{
30
- return p.replace(/\\/g, "/").replace(/(?<!^)\/+/g, "/");
33
+ return slash(p).replace(/(?<!^)\/+/g, "/");
34
+ };
35
+ const resolveBasePath = (base)=>{
36
+ if (isAbsolute(base)) return base;
37
+ return !base.startsWith("/") && !base.startsWith("./") ? `/${base}` : base;
38
+ };
39
+ const isAbsolute = (url)=>{
40
+ return url.match(/^(?:[a-z]+:)?\/\//i);
31
41
  };
32
42
 
33
- export { nonNullable, parallel, toUnix };
43
+ export { isAbsolute, nonNullable, parallel, resolveBasePath, slash, toUnix };
@@ -0,0 +1,4 @@
1
+ export { createLogger } from "./node/log.js";
2
+ export type { LogType, LogLevel, LoggerOptions, Logger } from "./node/log.js";
3
+ export { resolveEntry } from "./node/paths.js";
4
+ //# sourceMappingURL=index.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../src/index.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,70 @@
1
+ import fs, { readFileSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import { red, yellow, cyan } from 'kolorist';
4
+ import path from 'node:path';
5
+
6
+ const LogLevels = {
7
+ silent: 0,
8
+ error: 1,
9
+ warn: 2,
10
+ info: 3
11
+ };
12
+ const require = createRequire(import.meta.url);
13
+ const createLogger = (level = "info", options = {})=>{
14
+ const { prefix: _prefix = "serwist", showVersion = true, allowClearScreen = true } = options;
15
+ const packageJson = showVersion ? JSON.parse(readFileSync(require.resolve("@serwist/utils/package.json"), "utf-8")) : null;
16
+ const prefix = `${_prefix}${showVersion ? ` v${packageJson.version}` : ""}`;
17
+ const thresh = LogLevels[level];
18
+ const canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI;
19
+ const clear = canClearScreen ? console.clear : ()=>{};
20
+ const output = (type, msg, options = {})=>{
21
+ if (thresh >= LogLevels[type]) {
22
+ const method = type === "info" ? "log" : type;
23
+ if (options.clear) clear();
24
+ let tag = type === "error" ? red(prefix) : type === "warn" ? yellow(prefix) : cyan(prefix);
25
+ console[method](`${options.skipLine ? "\n" : ""}${tag} ${msg}`);
26
+ }
27
+ };
28
+ const warnedMessages = new Set();
29
+ return {
30
+ info (msg, opts) {
31
+ output("info", msg, opts);
32
+ },
33
+ warn (msg, opts) {
34
+ output("warn", msg, opts);
35
+ },
36
+ warnOnce (msg, opts) {
37
+ if (warnedMessages.has(msg)) return;
38
+ output("warn", msg, opts);
39
+ warnedMessages.add(msg);
40
+ },
41
+ error (msg, opts) {
42
+ output("error", msg, opts);
43
+ },
44
+ clearScreen (type) {
45
+ if (thresh >= LogLevels[type]) {
46
+ clear();
47
+ }
48
+ }
49
+ };
50
+ };
51
+
52
+ const resolveEntry = (entry)=>{
53
+ if (fs.existsSync(entry)) {
54
+ const stats = fs.statSync(entry);
55
+ if (stats.isDirectory()) {
56
+ return resolveEntry(path.join(entry, "index"));
57
+ }
58
+ return entry;
59
+ }
60
+ const dir = path.dirname(entry);
61
+ if (fs.existsSync(dir)) {
62
+ const base = path.basename(entry);
63
+ const files = fs.readdirSync(dir);
64
+ const found = files.find((file)=>file.replace(/\.[^.]+$/, "") === base);
65
+ if (found) return path.join(dir, found);
66
+ }
67
+ return null;
68
+ };
69
+
70
+ export { createLogger, resolveEntry };
@@ -0,0 +1,21 @@
1
+ export type LogType = "error" | "warn" | "info";
2
+ export type LogLevel = LogType | "silent";
3
+ export interface LogOptions {
4
+ clear?: boolean;
5
+ skipLine?: boolean;
6
+ }
7
+ export declare const LogLevels: Record<LogLevel, number>;
8
+ export interface LoggerOptions {
9
+ prefix?: string;
10
+ showVersion?: boolean;
11
+ allowClearScreen?: boolean;
12
+ }
13
+ export interface Logger {
14
+ info(msg: string, options?: LogOptions): void;
15
+ warn(msg: string, options?: LogOptions): void;
16
+ warnOnce(msg: string, options?: LogOptions): void;
17
+ error(msg: string, options?: LogOptions): void;
18
+ clearScreen(type: LogType): void;
19
+ }
20
+ export declare const createLogger: (level?: LogLevel, options?: LoggerOptions) => Logger;
21
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/node/log.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAChD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC1C,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAK9C,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/C,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAClC;AAID,eAAO,MAAM,YAAY,GAAI,QAAO,QAAiB,EAAE,UAAS,aAAkB,KAAG,MAqCpF,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolves a file path without extension. Also handles `/index` if the path
3
+ * actually points to a directory.
4
+ * @param ctx
5
+ * @param api
6
+ * @returns
7
+ */
8
+ export declare const resolveEntry: (entry: string) => string | null;
9
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/node/paths.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAAM,GAAG,IAqBrD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const nonNullable: <T>(value: T) => value is NonNullable<T>;
2
+ //# sourceMappingURL=nonNullable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nonNullable.d.ts","sourceRoot":"","sources":["../src/nonNullable.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,KAAK,IAAI,WAAW,CAAC,CAAC,CAA0C,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Executes many async functions in parallel. Returns the
3
+ * results from all functions as an array. Does not handle
4
+ * any error.
5
+ */
6
+ export declare const parallel: <T, K>(limit: number, array: readonly T[], func: (item: T) => Promise<K>) => Promise<K[]>;
7
+ //# sourceMappingURL=parallel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAU,CAAC,EAAE,CAAC,EAAE,OAAO,MAAM,EAAE,OAAO,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,EAAE,CA4BnH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const slash: (str: string) => string;
2
+ export declare const toUnix: (p: string) => string;
3
+ export declare const resolveBasePath: (base: string) => string;
4
+ export declare const isAbsolute: (url: string) => RegExpMatchArray | null;
5
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,WAEhC,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,WAE/B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,WAG3C,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,4BAErC,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Makes certain fields in a object type required
3
+ *
4
+ * @example
5
+ * interface A {
6
+ * a?: string;
7
+ * b?: string;
8
+ * c?: string;
9
+ * }
10
+ * type B = RequiredFields<A, "b" | "c">;
11
+ * const b: B = {
12
+ * b: "hehe",
13
+ * c: "hehe",
14
+ * }; //valid
15
+ * const b: B = { a: "hehe" }; //invalid
16
+ * const c: B = { a: "hehe", b: "hehe" }; //invalid
17
+ */
18
+ export type Require<T, U extends keyof T> = T & Required<Pick<T, U>>;
19
+ /**
20
+ * Makes certain fields in a object type optional
21
+ *
22
+ * @example
23
+ * interface A {
24
+ * a: string;
25
+ * b: string;
26
+ * c: string;
27
+ * }
28
+ * type B = Optional<A, "b" | "c">;
29
+ * const b: B = { a: "hehe" }; //valid
30
+ * const b: B = {}; //invalid
31
+ */
32
+ export type Optional<T, U extends keyof T> = Omit<T, U> & Partial<Pick<T, U>>;
33
+ /**
34
+ * Makes an object type's hover overlay more readable
35
+ *
36
+ * @example
37
+ *
38
+ * interface A {
39
+ * b: string;
40
+ * c: boolean;
41
+ * }
42
+ *
43
+ * interface B {
44
+ * c: number;
45
+ * }
46
+ *
47
+ * type D = A | B; // Displayed as is written
48
+ *
49
+ * type C = Prettify<A | B>; // { b: string; c: boolean; } | { c: number; }
50
+ */
51
+ export type Prettify<T> = {
52
+ [K in keyof T]: T[K];
53
+ } & {};
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAErE;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAE9E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;KACvB,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACrB,GAAG,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@serwist/utils",
3
- "version": "10.0.0-preview.1",
3
+ "version": "10.0.0-preview.3",
4
4
  "type": "module",
5
5
  "description": "This module contains internal utilities used by Serwist packages.",
6
6
  "files": [
7
- "src"
7
+ "src",
8
+ "dist"
8
9
  ],
9
10
  "keywords": [
10
11
  "serwist",
@@ -19,22 +20,37 @@
19
20
  "homepage": "https://serwist.pages.dev",
20
21
  "main": "./dist/index.js",
21
22
  "types": "./dist/index.d.ts",
23
+ "typesVersions": {
24
+ "node": {
25
+ "*": [
26
+ "./dist/index.node.d.ts"
27
+ ]
28
+ }
29
+ },
22
30
  "exports": {
23
31
  ".": {
24
32
  "types": "./dist/index.d.ts",
25
33
  "default": "./dist/index.js"
26
34
  },
35
+ "./node": {
36
+ "types": "./dist/index.node.d.ts",
37
+ "default": "./dist/index.node.js"
38
+ },
27
39
  "./package.json": "./package.json"
28
40
  },
41
+ "dependencies": {
42
+ "kolorist": "1.8.0"
43
+ },
29
44
  "devDependencies": {
30
- "rollup": "4.34.8",
31
- "typescript": "5.7.3",
32
- "@serwist/configs": "10.0.0-preview.1"
45
+ "rollup": "4.40.0",
46
+ "typescript": "5.8.3",
47
+ "@serwist/configs": "10.0.0-preview.3"
33
48
  },
34
49
  "scripts": {
35
50
  "build": "rimraf dist && NODE_ENV=production rollup --config rollup.config.js",
36
51
  "dev": "rollup --config rollup.config.js --watch",
37
52
  "lint": "biome lint ./src",
53
+ "qcheck": "biome check ./src",
38
54
  "typecheck": "tsc"
39
55
  }
40
56
  }
@@ -0,0 +1,3 @@
1
+ export { createLogger } from "./node/log.js";
2
+ export type { LogType, LogLevel, LoggerOptions, Logger } from "./node/log.js";
3
+ export { resolveEntry } from "./node/paths.js";
package/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { nonNullable } from "./nonNullable.js";
2
2
  import { parallel } from "./parallel.js";
3
- import { toUnix } from "./toUnix.js";
4
-
5
- export { nonNullable, parallel, toUnix };
6
3
 
4
+ export { nonNullable, parallel };
5
+ export { slash, toUnix, resolveBasePath, isAbsolute } from "./paths.js";
7
6
  export type * from "./types.js";
@@ -0,0 +1,71 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { cyan, yellow, red } from "kolorist";
4
+
5
+ export type LogType = "error" | "warn" | "info";
6
+ export type LogLevel = LogType | "silent";
7
+ export interface LogOptions {
8
+ clear?: boolean;
9
+ skipLine?: boolean;
10
+ }
11
+ export const LogLevels: Record<LogLevel, number> = {
12
+ silent: 0,
13
+ error: 1,
14
+ warn: 2,
15
+ info: 3,
16
+ };
17
+
18
+ export interface LoggerOptions {
19
+ prefix?: string;
20
+ showVersion?: boolean;
21
+ allowClearScreen?: boolean;
22
+ }
23
+
24
+ export interface Logger {
25
+ info(msg: string, options?: LogOptions): void;
26
+ warn(msg: string, options?: LogOptions): void;
27
+ warnOnce(msg: string, options?: LogOptions): void;
28
+ error(msg: string, options?: LogOptions): void;
29
+ clearScreen(type: LogType): void;
30
+ }
31
+
32
+ const require = createRequire(import.meta.url);
33
+
34
+ export const createLogger = (level: LogLevel = "info", options: LoggerOptions = {}): Logger => {
35
+ const { prefix: _prefix = "serwist", showVersion = true, allowClearScreen = true } = options;
36
+ const packageJson = showVersion ? JSON.parse(readFileSync(require.resolve("@serwist/utils/package.json"), "utf-8")) : null;
37
+ const prefix = `${_prefix}${showVersion ? ` v${packageJson.version}` : ""}`;
38
+ const thresh = LogLevels[level];
39
+ const canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI;
40
+ const clear = canClearScreen ? console.clear : () => {};
41
+ const output = (type: LogType, msg: string, options: LogOptions = {}) => {
42
+ if (thresh >= LogLevels[type]) {
43
+ const method = type === "info" ? "log" : type;
44
+ if (options.clear) clear();
45
+ let tag = type === "error" ? red(prefix) : type === "warn" ? yellow(prefix) : cyan(prefix);
46
+ console[method](`${options.skipLine ? "\n" : ""}${tag} ${msg}`);
47
+ }
48
+ };
49
+ const warnedMessages = new Set<string>();
50
+ return {
51
+ info(msg, opts) {
52
+ output("info", msg, opts);
53
+ },
54
+ warn(msg, opts) {
55
+ output("warn", msg, opts);
56
+ },
57
+ warnOnce(msg, opts) {
58
+ if (warnedMessages.has(msg)) return;
59
+ output("warn", msg, opts);
60
+ warnedMessages.add(msg);
61
+ },
62
+ error(msg, opts) {
63
+ output("error", msg, opts);
64
+ },
65
+ clearScreen(type) {
66
+ if (thresh >= LogLevels[type]) {
67
+ clear();
68
+ }
69
+ },
70
+ } satisfies Logger;
71
+ };
@@ -0,0 +1,34 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ // Source: https://github.com/sveltejs/kit/blob/6419d3eaa7bf1b0a756b28f06a73f71fe042de0a/packages/kit/src/utils/filesystem.js
5
+ // License: MIT
6
+ /**
7
+ * Resolves a file path without extension. Also handles `/index` if the path
8
+ * actually points to a directory.
9
+ * @param ctx
10
+ * @param api
11
+ * @returns
12
+ */
13
+ export const resolveEntry = (entry: string): string | null => {
14
+ if (fs.existsSync(entry)) {
15
+ const stats = fs.statSync(entry);
16
+ if (stats.isDirectory()) {
17
+ return resolveEntry(path.join(entry, "index"));
18
+ }
19
+
20
+ return entry;
21
+ }
22
+ const dir = path.dirname(entry);
23
+
24
+ if (fs.existsSync(dir)) {
25
+ const base = path.basename(entry);
26
+ const files = fs.readdirSync(dir);
27
+
28
+ const found = files.find((file) => file.replace(/\.[^.]+$/, "") === base);
29
+
30
+ if (found) return path.join(dir, found);
31
+ }
32
+
33
+ return null;
34
+ };
package/src/paths.ts ADDED
@@ -0,0 +1,16 @@
1
+ export const slash = (str: string) => {
2
+ return str.replace(/\\/g, "/");
3
+ };
4
+
5
+ export const toUnix = (p: string) => {
6
+ return slash(p).replace(/(?<!^)\/+/g, "/");
7
+ };
8
+
9
+ export const resolveBasePath = (base: string) => {
10
+ if (isAbsolute(base)) return base;
11
+ return !base.startsWith("/") && !base.startsWith("./") ? `/${base}` : base;
12
+ };
13
+
14
+ export const isAbsolute = (url: string) => {
15
+ return url.match(/^(?:[a-z]+:)?\/\//i);
16
+ };
package/src/toUnix.ts DELETED
@@ -1,3 +0,0 @@
1
- export const toUnix = (p: string) => {
2
- return p.replace(/\\/g, "/").replace(/(?<!^)\/+/g, "/");
3
- };