@goodbyenjn/utils 26.3.0 → 26.4.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 +53 -31
- package/dist/chunks/chunk-3c6f28c7.d.ts +39 -0
- package/dist/chunks/{chunk-5ed3bc8a.js → chunk-486f65b0.js} +190 -324
- package/dist/chunks/chunk-704a1835.d.ts +174 -0
- package/dist/chunks/chunk-7ffde8d4.js +43 -0
- package/dist/chunks/chunk-b61db0a7.js +27 -0
- package/dist/common.d.ts +8 -16
- package/dist/common.js +1 -1
- package/dist/fs.d.ts +2 -5
- package/dist/fs.js +239 -588
- package/dist/global-types.d.ts +89 -59
- package/dist/remeda.d.ts +10 -12288
- package/dist/remeda.js +2 -2
- package/dist/result.d.ts +2 -2
- package/dist/result.js +2 -2
- package/dist/shell.d.ts +4 -14
- package/dist/shell.js +290 -290
- package/dist/types.d.ts +3 -2
- package/package.json +14 -11
- package/dist/chunks/chunk-b970a8d0.js +0 -2782
- package/dist/chunks/chunk-d1860346.d.ts +0 -154
- package/dist/chunks/chunk-e931fe39.d.ts +0 -11978
package/README.md
CHANGED
|
@@ -116,6 +116,10 @@ const parts = split("-", "hello-world-js"); // ["hello", "world", "js"]
|
|
|
116
116
|
// Split string by line breaks (handles both \n and \r\n)
|
|
117
117
|
const lines = splitByLineBreak("line1\nline2\r\nline3");
|
|
118
118
|
console.log(lines); // ["line1", "line2", "line3"]
|
|
119
|
+
|
|
120
|
+
// Parse boolean value with custom default
|
|
121
|
+
const isEnabled = parseValueToBoolean("yes", false); // true
|
|
122
|
+
const debugMode = parseValueToBoolean("invalid", "auto"); // "auto"
|
|
119
123
|
```
|
|
120
124
|
|
|
121
125
|
#### Promise Utilities
|
|
@@ -307,7 +311,7 @@ const pattern = convertPathToPattern("/home/user/project");
|
|
|
307
311
|
### Result Pattern - Functional Error Handling
|
|
308
312
|
|
|
309
313
|
```typescript
|
|
310
|
-
import { err, ok, Result
|
|
314
|
+
import { err, ok, Result } from "@goodbyenjn/utils/result";
|
|
311
315
|
|
|
312
316
|
// Create results explicitly
|
|
313
317
|
const success = ok(42);
|
|
@@ -315,7 +319,7 @@ const failure = err("Something went wrong");
|
|
|
315
319
|
|
|
316
320
|
// Handle results with chainable methods
|
|
317
321
|
const doubled = success
|
|
318
|
-
.map(value => value * 2)
|
|
322
|
+
.map(value => value * 2) // Supports async: .map(async v => v * 2) returns Promise<Result>
|
|
319
323
|
.mapErr(err => `Error: ${err}`)
|
|
320
324
|
.unwrapOr(0); // 84
|
|
321
325
|
|
|
@@ -323,28 +327,36 @@ const doubled = success
|
|
|
323
327
|
const result: Result<string, Error> = ok("value");
|
|
324
328
|
const transformed = result.mapErr(() => new Error("Custom error"));
|
|
325
329
|
|
|
326
|
-
// Convert throwing functions to Result
|
|
330
|
+
// Convert throwing functions or promises to Result
|
|
327
331
|
async function fetchUser(id: string) {
|
|
328
|
-
//
|
|
329
|
-
const user = await Result.
|
|
332
|
+
// Result.try catches thrown errors
|
|
333
|
+
const user = await Result.try(() => JSON.parse(userJson));
|
|
334
|
+
// Or handle promise rejections
|
|
335
|
+
const user = await Result.try(fetch(`/api/users/${id}`));
|
|
330
336
|
|
|
331
337
|
return user.map(u => u.name).mapErr(err => new Error(`Failed to parse user: ${err.message}`));
|
|
332
338
|
}
|
|
333
339
|
|
|
340
|
+
// Wrap a function to always return a Result
|
|
341
|
+
const safeParse = Result.wrap(JSON.parse, Error);
|
|
342
|
+
const data = safeParse('{"valid": true}'); // Result<any, Error>
|
|
343
|
+
|
|
334
344
|
// Combine multiple Results
|
|
335
345
|
const results = [ok(1), ok(2), err("oops"), ok(4)];
|
|
336
346
|
const combined = Result.all(...results); // Err("oops")
|
|
337
347
|
|
|
338
|
-
//
|
|
339
|
-
const
|
|
340
|
-
|
|
348
|
+
// Generator-based "do" notation for flattening Results
|
|
349
|
+
const finalResult = Result.gen(function* () {
|
|
350
|
+
const a = yield* ok(10);
|
|
351
|
+
const b = yield* ok(20);
|
|
352
|
+
return a + b;
|
|
353
|
+
}); // ok(30)
|
|
354
|
+
|
|
355
|
+
// Supports async generators
|
|
356
|
+
const asyncFinal = await Result.gen(async function* () {
|
|
357
|
+
const user = yield* await fetchUser("1");
|
|
358
|
+
return user.name;
|
|
341
359
|
});
|
|
342
|
-
|
|
343
|
-
if (safeTryExample.isOk()) {
|
|
344
|
-
console.log("Data:", safeTryExample.unwrap());
|
|
345
|
-
} else {
|
|
346
|
-
console.error("Failed:", safeTryExample.unwrapErr());
|
|
347
|
-
}
|
|
348
360
|
```
|
|
349
361
|
|
|
350
362
|
### Type Utilities
|
|
@@ -356,46 +368,56 @@ import type {
|
|
|
356
368
|
YieldType,
|
|
357
369
|
OmitByKey,
|
|
358
370
|
SetNullable,
|
|
371
|
+
TemplateFn,
|
|
359
372
|
} from "@goodbyenjn/utils/types";
|
|
360
373
|
|
|
374
|
+
// ... (other types)
|
|
375
|
+
|
|
376
|
+
// Template string function type
|
|
377
|
+
const myTag: TemplateFn<string> = (strings, ...values) => {
|
|
378
|
+
return strings[0] + values[0];
|
|
379
|
+
};
|
|
380
|
+
```
|
|
381
|
+
|
|
361
382
|
// Nullable type for values that can be null or undefined
|
|
362
383
|
type User = {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
384
|
+
id: string;
|
|
385
|
+
name: string;
|
|
386
|
+
email: Nullable<string>; // string | null | undefined
|
|
366
387
|
};
|
|
367
388
|
|
|
368
389
|
// Optional type (undefined but not null)
|
|
369
390
|
type Profile = {
|
|
370
|
-
|
|
391
|
+
bio: Optional<string>; // string | undefined
|
|
371
392
|
};
|
|
372
393
|
|
|
373
394
|
// Extract yield type from generators
|
|
374
|
-
function
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
395
|
+
function\* numberGenerator() {
|
|
396
|
+
yield 1;
|
|
397
|
+
yield 2;
|
|
398
|
+
yield 3;
|
|
378
399
|
}
|
|
379
400
|
|
|
380
401
|
type NumberType = YieldType<typeof numberGenerator>; // number
|
|
381
402
|
|
|
382
403
|
// Omit properties by their value type
|
|
383
404
|
type Config = {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
405
|
+
name: string;
|
|
406
|
+
debug: boolean;
|
|
407
|
+
verbose: boolean;
|
|
408
|
+
timeout: number;
|
|
388
409
|
};
|
|
389
410
|
type WithoutBooleans = OmitByKey<Config, boolean>; // { name: string; timeout: number }
|
|
390
411
|
|
|
391
412
|
// Set specific properties to nullable
|
|
392
413
|
type APIResponse = {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
414
|
+
id: number;
|
|
415
|
+
name: string;
|
|
416
|
+
email: string;
|
|
396
417
|
};
|
|
397
418
|
type PartialResponse = SetNullable<APIResponse, "email" | "name">; // email and name become nullable
|
|
398
|
-
|
|
419
|
+
|
|
420
|
+
````
|
|
399
421
|
|
|
400
422
|
### Extended Remeda Utilities
|
|
401
423
|
|
|
@@ -492,7 +514,7 @@ const totalAge = sumBy(
|
|
|
492
514
|
// Chunk array into groups
|
|
493
515
|
const chunked = chunk(users, 2);
|
|
494
516
|
// [[user1, user2], [user3]]
|
|
495
|
-
|
|
517
|
+
````
|
|
496
518
|
|
|
497
519
|
## API Reference
|
|
498
520
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Except, IterableElement } from "type-fest";
|
|
2
|
+
|
|
3
|
+
//#region src/types/fn.d.ts
|
|
4
|
+
type Fn<Return = any, Args extends readonly any[] = any[]> = (...args: Args) => Return;
|
|
5
|
+
type FnWithThis<Return = any, Args extends readonly any[] = any[], This = unknown> = ((this: This, ...args: Args) => Return) & {
|
|
6
|
+
prototype: This;
|
|
7
|
+
};
|
|
8
|
+
type AsyncFn<Return = any, Args extends readonly any[] = any[]> = (...args: Args) => PromiseLike<Return>;
|
|
9
|
+
type AsyncFnWithThis<Return = any, Args extends readonly any[] = any[], This = unknown> = ((this: This, ...args: Args) => PromiseLike<Return>) & {
|
|
10
|
+
prototype: This;
|
|
11
|
+
};
|
|
12
|
+
type SyncFn<Return = any, Args extends readonly any[] = any[]> = (...args: Args) => Return extends PromiseLike<any> ? never : Return;
|
|
13
|
+
type SyncFnWithThis<Return = any, Args extends readonly any[] = any[], This = unknown> = ((this: This, ...args: Args) => Return extends PromiseLike<any> ? never : Return) & {
|
|
14
|
+
prototype: This;
|
|
15
|
+
};
|
|
16
|
+
type TemplateFn<Return = any> = (template: TemplateStringsArray, ...values: any[]) => Return;
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/types/nullable.d.ts
|
|
19
|
+
type Nullable<T> = T | null | undefined;
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/types/omit-by-key.d.ts
|
|
22
|
+
type OmitByKey<ObjectType, KeysType extends keyof ObjectType> = Except<ObjectType, KeysType, {
|
|
23
|
+
requireExactProps: true;
|
|
24
|
+
}>;
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/types/optional.d.ts
|
|
27
|
+
type Optional<T> = T | undefined;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/types/set-nullable.d.ts
|
|
30
|
+
type SetNullable<BaseType, Keys extends keyof BaseType = keyof BaseType> = { [Key in keyof BaseType]: Key extends Keys ? Nullable<BaseType[Key]> : BaseType[Key] };
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/types/yield-type.d.ts
|
|
33
|
+
type YieldType<TargetGeneratorFn extends Fn<Generator | AsyncGenerator>> = IterableElement<ReturnType<TargetGeneratorFn>>;
|
|
34
|
+
declare namespace index_d_exports {
|
|
35
|
+
export { AsyncFn, AsyncFnWithThis, Fn, FnWithThis, Nullable, OmitByKey, Optional, SetNullable, SyncFn, SyncFnWithThis, TemplateFn, YieldType };
|
|
36
|
+
}
|
|
37
|
+
import * as import_type_fest from "type-fest";
|
|
38
|
+
//#endregion
|
|
39
|
+
export { OmitByKey as a, AsyncFnWithThis as c, SyncFn as d, SyncFnWithThis as f, Optional as i, Fn as l, YieldType as n, Nullable as o, TemplateFn as p, SetNullable as r, AsyncFn as s, index_d_exports as t, FnWithThis as u };
|