utilful 2.5.2 → 3.0.0
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.
- package/README.md +207 -38
- package/dist/array.d.mts +4 -4
- package/dist/csv.d.mts +138 -148
- package/dist/csv.mjs +72 -88
- package/dist/defu.d.mts +12 -6
- package/dist/defu.mjs +3 -3
- package/dist/emitter.d.mts +5 -5
- package/dist/emitter.mjs +25 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +3 -3
- package/dist/json.d.mts +6 -13
- package/dist/json.mjs +3 -19
- package/dist/module.d.mts +5 -5
- package/dist/module.mjs +2 -1
- package/dist/object.d.mts +26 -22
- package/dist/object.mjs +13 -7
- package/dist/path.d.mts +24 -20
- package/dist/path.mjs +9 -4
- package/dist/result.d.mts +16 -8
- package/dist/result.mjs +6 -5
- package/dist/string.d.mts +17 -13
- package/dist/string.mjs +8 -2
- package/dist/types.d.mts +1 -1
- package/package.json +10 -16
package/dist/path.mjs
CHANGED
|
@@ -56,7 +56,7 @@ function joinURL(...paths) {
|
|
|
56
56
|
continue;
|
|
57
57
|
}
|
|
58
58
|
if (path === "/") continue;
|
|
59
|
-
const resultHasTrailing = result
|
|
59
|
+
const resultHasTrailing = result.at(-1) === "/";
|
|
60
60
|
const pathHasLeading = path[0] === "/";
|
|
61
61
|
if (resultHasTrailing && pathHasLeading) result += path.slice(1);
|
|
62
62
|
else if (!resultHasTrailing && !pathHasLeading) result += `/${path}`;
|
|
@@ -70,7 +70,7 @@ function joinURL(...paths) {
|
|
|
70
70
|
function withBase(input = "", base = "") {
|
|
71
71
|
if (!base || base === "/") return input;
|
|
72
72
|
const _base = withoutTrailingSlash(base);
|
|
73
|
-
if (input.startsWith(_base) && (input.length === _base.length || input[_base.length] === "/" || input[_base.length] === "?")) return input;
|
|
73
|
+
if (input.startsWith(_base) && (input.length === _base.length || input[_base.length] === "/" || input[_base.length] === "?" || input[_base.length] === "#")) return input;
|
|
74
74
|
return joinURL(_base, input);
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
@@ -79,15 +79,20 @@ function withBase(input = "", base = "") {
|
|
|
79
79
|
function withoutBase(input = "", base = "") {
|
|
80
80
|
if (!base || base === "/") return input;
|
|
81
81
|
const _base = withoutTrailingSlash(base);
|
|
82
|
-
if (!input.startsWith(_base) || input.length !== _base.length && input[_base.length] !== "/" && input[_base.length] !== "?") return input;
|
|
82
|
+
if (!input.startsWith(_base) || input.length !== _base.length && input[_base.length] !== "/" && input[_base.length] !== "?" && input[_base.length] !== "#") return input;
|
|
83
83
|
const trimmed = input.slice(_base.length);
|
|
84
84
|
return trimmed[0] === "/" ? trimmed : `/${trimmed}`;
|
|
85
85
|
}
|
|
86
|
+
const URL_SCHEME_RE = /^[a-z][\w+.-]*:\/\//i;
|
|
86
87
|
/**
|
|
87
88
|
* Returns the pathname of the given path, which is the path without the query string or hash.
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* Absolute URLs (with a scheme, e.g. `https://example.com/foo`) return the URL's pathname.
|
|
92
|
+
* All other inputs are returned unchanged with the query string and hash removed.
|
|
88
93
|
*/
|
|
89
94
|
function getPathname(path = "/") {
|
|
90
|
-
if (
|
|
95
|
+
if (URL_SCHEME_RE.test(path)) return new URL(path).pathname;
|
|
91
96
|
let pathEnd = path.length;
|
|
92
97
|
const queryIndex = path.indexOf("?");
|
|
93
98
|
const hashIndex = path.indexOf("#");
|
package/dist/result.d.mts
CHANGED
|
@@ -10,10 +10,10 @@ interface ErrData<E> {
|
|
|
10
10
|
}
|
|
11
11
|
type ResultData<T, E> = OkData<T> | ErrData<E>;
|
|
12
12
|
/**
|
|
13
|
-
* Successful result variant.
|
|
14
|
-
* @template T Success value type.
|
|
15
|
-
* @template E Error type (phantom - for type unification).
|
|
16
|
-
*/
|
|
13
|
+
* Successful result variant.
|
|
14
|
+
* @template T Success value type.
|
|
15
|
+
* @template E Error type (phantom - for type unification).
|
|
16
|
+
*/
|
|
17
17
|
declare class Ok<T, E = never> {
|
|
18
18
|
readonly value: T;
|
|
19
19
|
readonly ok = true;
|
|
@@ -35,10 +35,10 @@ declare class Ok<T, E = never> {
|
|
|
35
35
|
}): R;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* Error result variant.
|
|
39
|
-
* @template T Success type (phantom - for type unification).
|
|
40
|
-
* @template E Error value type.
|
|
41
|
-
*/
|
|
38
|
+
* Error result variant.
|
|
39
|
+
* @template T Success type (phantom - for type unification).
|
|
40
|
+
* @template E Error value type.
|
|
41
|
+
*/
|
|
42
42
|
declare class Err<T, E> {
|
|
43
43
|
readonly error: E;
|
|
44
44
|
readonly ok = false;
|
|
@@ -64,6 +64,14 @@ declare function err<T = never, E extends string = string>(error: E): Err<T, E>;
|
|
|
64
64
|
declare function err<T = never, E = unknown>(error: E): Err<T, E>;
|
|
65
65
|
declare function isOk<T, E>(result: Result<T, E>): result is Ok<T, E>;
|
|
66
66
|
declare function isErr<T, E>(result: Result<T, E>): result is Err<T, E>;
|
|
67
|
+
/**
|
|
68
|
+
* Wraps a function call or promise in a `Result`.
|
|
69
|
+
*
|
|
70
|
+
* @remarks
|
|
71
|
+
* The function overload must be synchronous. For asynchronous work, pass the
|
|
72
|
+
* promise itself (e.g. `toResult(fn())`) – a function returning a promise
|
|
73
|
+
* throws a `TypeError`, since its rejection could not be captured as `Err`.
|
|
74
|
+
*/
|
|
67
75
|
declare function toResult<T, E = unknown>(fn: () => T): Result<T, E>;
|
|
68
76
|
declare function toResult<T, E = unknown>(promise: Promise<T>): Promise<Result<T, E>>;
|
|
69
77
|
declare function unwrapResult<T, E>(result: Ok<T, E>): OkData<T>;
|
package/dist/result.mjs
CHANGED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
* @template E Error type (phantom - for type unification).
|
|
6
6
|
*/
|
|
7
7
|
var Ok = class Ok {
|
|
8
|
-
value;
|
|
9
|
-
ok = true;
|
|
10
8
|
constructor(value) {
|
|
9
|
+
this.ok = true;
|
|
11
10
|
this.value = value;
|
|
12
11
|
}
|
|
13
12
|
/** Transforms the success value. */
|
|
@@ -41,9 +40,8 @@ var Ok = class Ok {
|
|
|
41
40
|
* @template E Error value type.
|
|
42
41
|
*/
|
|
43
42
|
var Err = class Err {
|
|
44
|
-
error;
|
|
45
|
-
ok = false;
|
|
46
43
|
constructor(error) {
|
|
44
|
+
this.ok = false;
|
|
47
45
|
this.error = error;
|
|
48
46
|
}
|
|
49
47
|
/** No-op on Err, returns self with new value type. */
|
|
@@ -85,11 +83,14 @@ function isErr(result) {
|
|
|
85
83
|
}
|
|
86
84
|
function toResult(fnOrPromise) {
|
|
87
85
|
if (fnOrPromise instanceof Promise) return fnOrPromise.then(ok).catch(err);
|
|
86
|
+
let value;
|
|
88
87
|
try {
|
|
89
|
-
|
|
88
|
+
value = fnOrPromise();
|
|
90
89
|
} catch (error) {
|
|
91
90
|
return err(error);
|
|
92
91
|
}
|
|
92
|
+
if (value instanceof Promise) throw new TypeError("[toResult] The function returned a promise. Pass the promise itself instead, e.g. toResult(fn())");
|
|
93
|
+
return ok(value);
|
|
93
94
|
}
|
|
94
95
|
function unwrapResult(result) {
|
|
95
96
|
return result.ok ? {
|
package/dist/string.d.mts
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
//#region src/string.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Simple template engine to replace variables in a string.
|
|
4
|
-
*
|
|
5
|
-
* @
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
3
|
+
* Simple template engine to replace variables in a string.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Only own properties of `variables` are substituted, so placeholders like
|
|
7
|
+
* `{constructor}` cannot leak prototype members.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const str = 'Hello, {name}!'
|
|
11
|
+
* const variables = { name: 'world' }
|
|
12
|
+
*
|
|
13
|
+
* console.log(template(str, variables)) // Hello, world!
|
|
14
|
+
*/
|
|
11
15
|
declare function template(str: string, variables: Record<string | number, any>, fallback?: string | ((key: string) => string)): string;
|
|
12
16
|
/**
|
|
13
|
-
* Generates a random string.
|
|
14
|
-
*
|
|
15
|
-
* @remarks Ported from `nanoid`.
|
|
16
|
-
* @see https://github.com/ai/nanoid
|
|
17
|
-
*/
|
|
17
|
+
* Generates a random string.
|
|
18
|
+
*
|
|
19
|
+
* @remarks Ported from `nanoid`.
|
|
20
|
+
* @see https://github.com/ai/nanoid
|
|
21
|
+
*/
|
|
18
22
|
declare function generateRandomId(size?: number, dict?: string): string;
|
|
19
23
|
//#endregion
|
|
20
24
|
export { generateRandomId, template };
|
package/dist/string.mjs
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
//#region src/string.ts
|
|
2
2
|
const URL_ALPHABET = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
3
|
+
const TEMPLATE_PLACEHOLDER_RE = /\{(\w+)\}/g;
|
|
3
4
|
/**
|
|
4
5
|
* Simple template engine to replace variables in a string.
|
|
5
6
|
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Only own properties of `variables` are substituted, so placeholders like
|
|
9
|
+
* `{constructor}` cannot leak prototype members.
|
|
10
|
+
*
|
|
6
11
|
* @example
|
|
7
12
|
* const str = 'Hello, {name}!'
|
|
8
13
|
* const variables = { name: 'world' }
|
|
@@ -10,8 +15,9 @@ const URL_ALPHABET = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvw
|
|
|
10
15
|
* console.log(template(str, variables)) // Hello, world!
|
|
11
16
|
*/
|
|
12
17
|
function template(str, variables, fallback) {
|
|
13
|
-
return str.replace(
|
|
14
|
-
|
|
18
|
+
return str.replace(TEMPLATE_PLACEHOLDER_RE, (_, key) => {
|
|
19
|
+
const value = Object.hasOwn(variables, key) ? variables[key] : void 0;
|
|
20
|
+
return value != null ? String(value) : (typeof fallback === "function" ? fallback(key) : fallback) ?? key;
|
|
15
21
|
});
|
|
16
22
|
}
|
|
17
23
|
/**
|
package/dist/types.d.mts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
type AutocompletableString = string & {};
|
|
3
3
|
type LooseAutocomplete<T extends string> = T | AutocompletableString;
|
|
4
4
|
/** Also commonly referred to as `Prettify` */
|
|
5
|
-
type UnifyIntersection<T> = { [K in keyof T]: T[K] } & {};
|
|
5
|
+
type UnifyIntersection<T> = { [K in keyof T]: T[K]; } & {};
|
|
6
6
|
declare const brand: unique symbol;
|
|
7
7
|
type BrandedType<T, B> = T & {
|
|
8
8
|
[brand]: B;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "utilful",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
5
|
-
"packageManager": "pnpm@
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"packageManager": "pnpm@11.15.1",
|
|
6
6
|
"description": "A collection of TypeScript utilities",
|
|
7
7
|
"author": "Johann Schopplich <hello@johannschopplich.com>",
|
|
8
8
|
"license": "MIT",
|
|
@@ -78,19 +78,13 @@
|
|
|
78
78
|
"release": "bumpp"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@antfu/eslint-config": "^
|
|
82
|
-
"@types/node": "^
|
|
83
|
-
"bumpp": "^
|
|
84
|
-
"eslint": "^10.0
|
|
85
|
-
"eslint-flat-config-utils": "^3.0
|
|
86
|
-
"tsdown": "^0.
|
|
87
|
-
"typescript": "^
|
|
88
|
-
"vitest": "^4.
|
|
89
|
-
},
|
|
90
|
-
"pnpm": {
|
|
91
|
-
"onlyBuiltDependencies": [
|
|
92
|
-
"esbuild",
|
|
93
|
-
"unrs-resolver"
|
|
94
|
-
]
|
|
81
|
+
"@antfu/eslint-config": "^9.1.0",
|
|
82
|
+
"@types/node": "^26.1.1",
|
|
83
|
+
"bumpp": "^12.0.0",
|
|
84
|
+
"eslint": "^10.7.0",
|
|
85
|
+
"eslint-flat-config-utils": "^3.2.0",
|
|
86
|
+
"tsdown": "^0.22.13",
|
|
87
|
+
"typescript": "^6.0.3",
|
|
88
|
+
"vitest": "^4.1.10"
|
|
95
89
|
}
|
|
96
90
|
}
|