refineable 1.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 +60 -0
- package/bun.lock +26 -0
- package/index.ts +13 -0
- package/package.json +12 -0
- package/tsconfig.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# refineable
|
|
2
|
+
|
|
3
|
+
A tiny TypeScript utility for chaining transformations over a value in a readable, functional style.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install refineable
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Wrap any value with `r()`, then chain `.refine()` calls to transform it step by step. Unwrap the final result with `.value`.
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { r } from 'refineable';
|
|
17
|
+
|
|
18
|
+
const result = r(42)
|
|
19
|
+
.refine(n => n * 2) // 84
|
|
20
|
+
.refine(n => `${n}!`) // "84!"
|
|
21
|
+
.refine(s => s.length) // 3
|
|
22
|
+
.value;
|
|
23
|
+
|
|
24
|
+
console.log(result); // 3
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
TypeScript infers the type at every step — no annotations needed.
|
|
28
|
+
|
|
29
|
+
## Async
|
|
30
|
+
|
|
31
|
+
Use `.refineAsync()` when your transformation returns a Promise. It resolves the value and keeps the chain going.
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
const result = await r("hello")
|
|
35
|
+
.refineAsync(async s => s.toUpperCase()) // "HELLO"
|
|
36
|
+
.then(v => v.refine(s => s + "!")) // "HELLO!"
|
|
37
|
+
|
|
38
|
+
console.log(result.value); // "HELLO!"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Why?
|
|
42
|
+
|
|
43
|
+
It's just a cleaner alternative to deeply nested function calls or intermediate variables:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// instead of this:
|
|
47
|
+
const doubled = n * 2;
|
|
48
|
+
const labeled = `${doubled}!`;
|
|
49
|
+
const len = labeled.length;
|
|
50
|
+
|
|
51
|
+
// or this:
|
|
52
|
+
const len = getLength(label(double(n)));
|
|
53
|
+
|
|
54
|
+
// do this:
|
|
55
|
+
const len = r(n)
|
|
56
|
+
.refine(n => n * 2)
|
|
57
|
+
.refine(n => `${n}!`)
|
|
58
|
+
.refine(s => s.length)
|
|
59
|
+
.value;
|
|
60
|
+
```
|
package/bun.lock
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 1,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "refineable",
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"@types/bun": "latest",
|
|
9
|
+
},
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"typescript": "^5",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
"packages": {
|
|
16
|
+
"@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="],
|
|
17
|
+
|
|
18
|
+
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
|
|
19
|
+
|
|
20
|
+
"bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="],
|
|
21
|
+
|
|
22
|
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
23
|
+
|
|
24
|
+
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
|
25
|
+
}
|
|
26
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Refineable<T> = {
|
|
2
|
+
value: T;
|
|
3
|
+
refine: <U>(f: (value: T) => U) => Refineable<U>;
|
|
4
|
+
refineAsync: <U>(f: (value: T) => Promise<U>) => Promise<Refineable<U>>;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const r = <T>(value: T): Refineable<T> => ({
|
|
8
|
+
value,
|
|
9
|
+
refine: <U>(f: (v: T) => U) => r(f(value)),
|
|
10
|
+
refineAsync: async <U>(f: (v: T) => Promise<U>) => r(await f(value)),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export { r, Refineable };
|
package/package.json
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
"noImplicitOverride": true,
|
|
23
|
+
|
|
24
|
+
// Some stricter flags (disabled by default)
|
|
25
|
+
"noUnusedLocals": false,
|
|
26
|
+
"noUnusedParameters": false,
|
|
27
|
+
"noPropertyAccessFromIndexSignature": false
|
|
28
|
+
}
|
|
29
|
+
}
|