@fluixi/core 1.0.0-alpha.100
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/LICENSE +21 -0
- package/README.md +334 -0
- package/dist/cdn/core.global.js +2 -0
- package/dist/cli/generate.cjs +5639 -0
- package/dist/cli/generate.d.ts +7 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +2580 -0
- package/dist/cli/generate.mjs +5644 -0
- package/dist/cli/index.cjs +5639 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +2580 -0
- package/dist/cli/index.mjs +5644 -0
- package/dist/cli/run.cjs +64 -0
- package/dist/cli/run.d.ts +3 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +62 -0
- package/dist/cli/run.mjs +40 -0
- package/dist/fluixi.d.ts +5 -0
- package/dist/src/cdn/chunk-RKBFEFZP.mjs +987 -0
- package/dist/src/cdn/core.cjs +1592 -0
- package/dist/src/cdn/core.d.ts +16 -0
- package/dist/src/cdn/core.d.ts.map +1 -0
- package/dist/src/cdn/core.js +15 -0
- package/dist/src/cdn/core.mjs +714 -0
- package/dist/src/cdn/router-V2THK27H.mjs +74 -0
- package/dist/src/index.cjs +1711 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +11 -0
- package/dist/src/index.mjs +1833 -0
- package/dist/src/jsx-dev-runtime.cjs +26 -0
- package/dist/src/jsx-dev-runtime.d.ts +2 -0
- package/dist/src/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/src/jsx-dev-runtime.js +1 -0
- package/dist/src/jsx-dev-runtime.mjs +24 -0
- package/dist/src/jsx-runtime.cjs +26 -0
- package/dist/src/jsx-runtime.d.ts +7 -0
- package/dist/src/jsx-runtime.d.ts.map +1 -0
- package/dist/src/jsx-runtime.js +8 -0
- package/dist/src/jsx-runtime.mjs +24 -0
- package/dist/src/lib/client/chunk-FDOPDB6Z.mjs +53 -0
- package/dist/src/lib/client/index.cjs +1210 -0
- package/dist/src/lib/client/index.d.ts +51 -0
- package/dist/src/lib/client/index.d.ts.map +1 -0
- package/dist/src/lib/client/index.js +174 -0
- package/dist/src/lib/client/index.mjs +293 -0
- package/dist/src/lib/client/router-4PTBPZLQ.mjs +891 -0
- package/dist/src/lib/context/context.cjs +81 -0
- package/dist/src/lib/context/context.d.ts +73 -0
- package/dist/src/lib/context/context.d.ts.map +1 -0
- package/dist/src/lib/context/context.js +93 -0
- package/dist/src/lib/context/context.mjs +64 -0
- package/dist/src/lib/context/index.cjs +83 -0
- package/dist/src/lib/context/index.d.ts +3 -0
- package/dist/src/lib/context/index.d.ts.map +1 -0
- package/dist/src/lib/context/index.js +1 -0
- package/dist/src/lib/context/index.mjs +64 -0
- package/dist/src/lib/control-flow.cjs +35 -0
- package/dist/src/lib/control-flow.d.ts +4 -0
- package/dist/src/lib/control-flow.d.ts.map +1 -0
- package/dist/src/lib/control-flow.js +1 -0
- package/dist/src/lib/control-flow.mjs +25 -0
- package/dist/src/lib/core.cjs +1710 -0
- package/dist/src/lib/core.d.ts +91 -0
- package/dist/src/lib/core.d.ts.map +1 -0
- package/dist/src/lib/core.js +158 -0
- package/dist/src/lib/core.mjs +1833 -0
- package/dist/src/lib/env/index.cjs +44 -0
- package/dist/src/lib/env/index.d.ts +26 -0
- package/dist/src/lib/env/index.d.ts.map +1 -0
- package/dist/src/lib/env/index.js +31 -0
- package/dist/src/lib/env/index.mjs +23 -0
- package/dist/src/lib/i18n/index.cjs +123 -0
- package/dist/src/lib/i18n/index.d.ts +110 -0
- package/dist/src/lib/i18n/index.d.ts.map +1 -0
- package/dist/src/lib/i18n/index.js +164 -0
- package/dist/src/lib/i18n/index.mjs +103 -0
- package/dist/src/lib/index.cjs +598 -0
- package/dist/src/lib/index.d.ts +81 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +130 -0
- package/dist/src/lib/index.mjs +688 -0
- package/dist/src/lib/isomorphic.cjs +90 -0
- package/dist/src/lib/isomorphic.d.ts +114 -0
- package/dist/src/lib/isomorphic.d.ts.map +1 -0
- package/dist/src/lib/isomorphic.js +132 -0
- package/dist/src/lib/isomorphic.mjs +69 -0
- package/dist/src/lib/jsx-runtime/index.cjs +21 -0
- package/dist/src/lib/jsx-runtime/index.d.ts +13 -0
- package/dist/src/lib/jsx-runtime/index.d.ts.map +1 -0
- package/dist/src/lib/jsx-runtime/index.js +13 -0
- package/dist/src/lib/jsx-runtime/index.mjs +4 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +21 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts +2 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.js +1 -0
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +4 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.cjs +302 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts +35 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.d.ts.map +1 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.js +118 -0
- package/dist/src/lib/plugins/fluixi-routes-plugin.mjs +271 -0
- package/dist/src/lib/plugins/index.cjs +311 -0
- package/dist/src/lib/plugins/index.d.ts +6 -0
- package/dist/src/lib/plugins/index.d.ts.map +1 -0
- package/dist/src/lib/plugins/index.js +7 -0
- package/dist/src/lib/plugins/index.mjs +279 -0
- package/dist/src/lib/plugins/route-codegen.cjs +73 -0
- package/dist/src/lib/plugins/route-codegen.d.ts +12 -0
- package/dist/src/lib/plugins/route-codegen.d.ts.map +1 -0
- package/dist/src/lib/plugins/route-codegen.js +80 -0
- package/dist/src/lib/plugins/route-codegen.mjs +52 -0
- package/dist/src/lib/plugins/route-scanner.cjs +189 -0
- package/dist/src/lib/plugins/route-scanner.d.ts +38 -0
- package/dist/src/lib/plugins/route-scanner.d.ts.map +1 -0
- package/dist/src/lib/plugins/route-scanner.js +215 -0
- package/dist/src/lib/plugins/route-scanner.mjs +158 -0
- package/dist/src/lib/plugins/vite.cjs +27 -0
- package/dist/src/lib/plugins/vite.d.ts +3 -0
- package/dist/src/lib/plugins/vite.d.ts.map +1 -0
- package/dist/src/lib/plugins/vite.js +1 -0
- package/dist/src/lib/plugins/vite.mjs +6 -0
- package/dist/src/lib/render/await.cjs +38 -0
- package/dist/src/lib/render/await.d.ts +26 -0
- package/dist/src/lib/render/await.d.ts.map +1 -0
- package/dist/src/lib/render/await.js +45 -0
- package/dist/src/lib/render/await.mjs +17 -0
- package/dist/src/lib/render/component.cjs +221 -0
- package/dist/src/lib/render/component.d.ts +296 -0
- package/dist/src/lib/render/component.d.ts.map +1 -0
- package/dist/src/lib/render/component.js +514 -0
- package/dist/src/lib/render/component.mjs +214 -0
- package/dist/src/lib/render/deferred.cjs +175 -0
- package/dist/src/lib/render/deferred.d.ts +36 -0
- package/dist/src/lib/render/deferred.d.ts.map +1 -0
- package/dist/src/lib/render/deferred.js +141 -0
- package/dist/src/lib/render/deferred.mjs +158 -0
- package/dist/src/lib/render/index.cjs +573 -0
- package/dist/src/lib/render/index.d.ts +98 -0
- package/dist/src/lib/render/index.d.ts.map +1 -0
- package/dist/src/lib/render/index.js +180 -0
- package/dist/src/lib/render/index.mjs +590 -0
- package/dist/src/lib/render/lazy.cjs +67 -0
- package/dist/src/lib/render/lazy.d.ts +49 -0
- package/dist/src/lib/render/lazy.d.ts.map +1 -0
- package/dist/src/lib/render/lazy.js +105 -0
- package/dist/src/lib/render/lazy.mjs +50 -0
- package/dist/src/lib/render/suspense.cjs +141 -0
- package/dist/src/lib/render/suspense.d.ts +65 -0
- package/dist/src/lib/render/suspense.d.ts.map +1 -0
- package/dist/src/lib/render/suspense.js +196 -0
- package/dist/src/lib/render/suspense.mjs +136 -0
- package/dist/src/lib/render/versions.cjs +35 -0
- package/dist/src/lib/render/versions.d.ts +2 -0
- package/dist/src/lib/render/versions.d.ts.map +1 -0
- package/dist/src/lib/render/versions.js +21 -0
- package/dist/src/lib/render/versions.mjs +14 -0
- package/dist/src/lib/router/data.cjs +228 -0
- package/dist/src/lib/router/data.d.ts +142 -0
- package/dist/src/lib/router/data.d.ts.map +1 -0
- package/dist/src/lib/router/data.js +258 -0
- package/dist/src/lib/router/data.mjs +214 -0
- package/dist/src/lib/router/index.cjs +921 -0
- package/dist/src/lib/router/index.d.ts +274 -0
- package/dist/src/lib/router/index.d.ts.map +1 -0
- package/dist/src/lib/router/index.js +904 -0
- package/dist/src/lib/router/index.mjs +938 -0
- package/dist/src/lib/router/scroll.cjs +79 -0
- package/dist/src/lib/router/scroll.d.ts +19 -0
- package/dist/src/lib/router/scroll.d.ts.map +1 -0
- package/dist/src/lib/router/scroll.js +68 -0
- package/dist/src/lib/router/scroll.mjs +58 -0
- package/dist/src/lib/router/transition.cjs +75 -0
- package/dist/src/lib/router/transition.d.ts +81 -0
- package/dist/src/lib/router/transition.d.ts.map +1 -0
- package/dist/src/lib/router/transition.js +136 -0
- package/dist/src/lib/router/transition.mjs +54 -0
- package/dist/src/lib/server/hydration.cjs +169 -0
- package/dist/src/lib/server/hydration.d.ts +198 -0
- package/dist/src/lib/server/hydration.d.ts.map +1 -0
- package/dist/src/lib/server/hydration.js +345 -0
- package/dist/src/lib/server/hydration.mjs +148 -0
- package/dist/src/lib/server/index.cjs +406 -0
- package/dist/src/lib/server/index.d.ts +115 -0
- package/dist/src/lib/server/index.d.ts.map +1 -0
- package/dist/src/lib/server/index.js +164 -0
- package/dist/src/lib/server/index.mjs +384 -0
- package/dist/src/lib/server/reactive.cjs +197 -0
- package/dist/src/lib/server/reactive.d.ts +239 -0
- package/dist/src/lib/server/reactive.d.ts.map +1 -0
- package/dist/src/lib/server/reactive.js +413 -0
- package/dist/src/lib/server/reactive.mjs +176 -0
- package/dist/src/lib/storage/cache.cjs +51 -0
- package/dist/src/lib/storage/cache.d.ts +18 -0
- package/dist/src/lib/storage/cache.d.ts.map +1 -0
- package/dist/src/lib/storage/cache.js +42 -0
- package/dist/src/lib/storage/cache.mjs +30 -0
- package/dist/src/lib/storage/index.cjs +246 -0
- package/dist/src/lib/storage/index.d.ts +83 -0
- package/dist/src/lib/storage/index.d.ts.map +1 -0
- package/dist/src/lib/storage/index.js +179 -0
- package/dist/src/lib/storage/index.mjs +231 -0
- package/dist/src/lib/storage/persisted.cjs +91 -0
- package/dist/src/lib/storage/persisted.d.ts +53 -0
- package/dist/src/lib/storage/persisted.d.ts.map +1 -0
- package/dist/src/lib/storage/persisted.js +75 -0
- package/dist/src/lib/storage/persisted.mjs +70 -0
- package/dist/src/lib/theme/color-scheme.cjs +281 -0
- package/dist/src/lib/theme/color-scheme.d.ts +61 -0
- package/dist/src/lib/theme/color-scheme.d.ts.map +1 -0
- package/dist/src/lib/theme/color-scheme.js +120 -0
- package/dist/src/lib/theme/color-scheme.mjs +265 -0
- package/dist/src/lib/theme/index.cjs +267 -0
- package/dist/src/lib/theme/index.d.ts +78 -0
- package/dist/src/lib/theme/index.d.ts.map +1 -0
- package/dist/src/lib/theme/index.js +135 -0
- package/dist/src/lib/theme/index.mjs +251 -0
- package/dist/src/lib/theme/provider.cjs +346 -0
- package/dist/src/lib/theme/provider.d.ts +34 -0
- package/dist/src/lib/theme/provider.d.ts.map +1 -0
- package/dist/src/lib/theme/provider.js +60 -0
- package/dist/src/lib/theme/provider.mjs +332 -0
- package/dist/src/lib/utils/index.cjs +209 -0
- package/dist/src/lib/utils/index.d.ts +286 -0
- package/dist/src/lib/utils/index.d.ts.map +1 -0
- package/dist/src/lib/utils/index.js +434 -0
- package/dist/src/lib/utils/index.mjs +188 -0
- package/dist/src/routes.cjs +37 -0
- package/dist/src/routes.d.ts +22 -0
- package/dist/src/routes.d.ts.map +1 -0
- package/dist/src/routes.js +20 -0
- package/dist/src/routes.mjs +17 -0
- package/dist/src/server.cjs +405 -0
- package/dist/src/server.d.ts +63 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +62 -0
- package/dist/src/server.mjs +382 -0
- package/dist/src/utils.cjs +21 -0
- package/dist/src/utils.d.ts +10 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +9 -0
- package/dist/src/utils.mjs +4 -0
- package/dist/src/version.generated.cjs +26 -0
- package/dist/src/version.generated.d.ts +3 -0
- package/dist/src/version.generated.d.ts.map +1 -0
- package/dist/src/version.generated.js +3 -0
- package/dist/src/version.generated.mjs +5 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +164 -0
- package/src/index.ts +19 -0
- package/types/fluixi.d.ts +5 -0
- package/types/vinxi.d.ts +50 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @fluixi/core/utils
|
|
3
|
+
*
|
|
4
|
+
* This module provides general utility functions for common operations.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Debounces a function call
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { debounce } from '@fluixi/core/utils';
|
|
12
|
+
*
|
|
13
|
+
* const handleInput = debounce((value: string) => {
|
|
14
|
+
* console.log('Input:', value);
|
|
15
|
+
* }, 300);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function debounce<T extends (...args: any[]) => any>(fn: T, delay: number): (...args: Parameters<T>) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Throttles a function call
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { throttle } from '@fluixi/core/utils';
|
|
25
|
+
*
|
|
26
|
+
* const handleScroll = throttle(() => {
|
|
27
|
+
* console.log('Scrolled');
|
|
28
|
+
* }, 100);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function throttle<T extends (...args: any[]) => any>(fn: T, limit: number): (...args: Parameters<T>) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a memoized version of a function
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* import { memoize } from '@fluixi/core/utils';
|
|
38
|
+
*
|
|
39
|
+
* const expensiveCalc = memoize((n: number) => {
|
|
40
|
+
* return n * n;
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function memoize<T extends (...args: any[]) => any>(fn: T): T;
|
|
45
|
+
/**
|
|
46
|
+
* Deep clones an object
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { deepClone } from '@fluixi/core/utils';
|
|
51
|
+
*
|
|
52
|
+
* const original = { a: 1, b: { c: 2 } };
|
|
53
|
+
* const copy = deepClone(original);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function deepClone<T>(obj: T): T;
|
|
57
|
+
/**
|
|
58
|
+
* Deep merges multiple objects
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* import { deepMerge } from '@fluixi/core/utils';
|
|
63
|
+
*
|
|
64
|
+
* const result = deepMerge(
|
|
65
|
+
* { a: 1, b: { c: 2 } },
|
|
66
|
+
* { b: { d: 3 } }
|
|
67
|
+
* );
|
|
68
|
+
* // { a: 1, b: { c: 2, d: 3 } }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function deepMerge<T extends Record<string, any>>(...objects: Partial<T>[]): T;
|
|
72
|
+
/**
|
|
73
|
+
* Generates a unique ID
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* import { uniqueId } from '@fluixi/core/utils';
|
|
78
|
+
*
|
|
79
|
+
* const id = uniqueId('component-');
|
|
80
|
+
* // 'component-abc123def456'
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function uniqueId(prefix?: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* Formats a number with commas
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* import { formatNumber } from '@fluixi/core/utils';
|
|
90
|
+
*
|
|
91
|
+
* formatNumber(1234567); // '1,234,567'
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function formatNumber(num: number): string;
|
|
95
|
+
/**
|
|
96
|
+
* Formats bytes to human readable string
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* import { formatBytes } from '@fluixi/core/utils';
|
|
101
|
+
*
|
|
102
|
+
* formatBytes(1024); // '1 KB'
|
|
103
|
+
* formatBytes(1048576); // '1 MB'
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare function formatBytes(bytes: number, decimals?: number): string;
|
|
107
|
+
/**
|
|
108
|
+
* Capitalizes first letter of a string
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* import { capitalize } from '@fluixi/core/utils';
|
|
113
|
+
*
|
|
114
|
+
* capitalize('hello'); // 'Hello'
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare function capitalize(str: string): string;
|
|
118
|
+
/**
|
|
119
|
+
* Converts string to kebab-case
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* import { kebabCase } from '@fluixi/core/utils';
|
|
124
|
+
*
|
|
125
|
+
* kebabCase('HelloWorld'); // 'hello-world'
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export declare function kebabCase(str: string): string;
|
|
129
|
+
/**
|
|
130
|
+
* Converts string to camelCase
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* import { camelCase } from '@fluixi/core/utils';
|
|
135
|
+
*
|
|
136
|
+
* camelCase('hello-world'); // 'helloWorld'
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function camelCase(str: string): string;
|
|
140
|
+
/**
|
|
141
|
+
* Clamps a number between min and max
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* import { clamp } from '@fluixi/core/utils';
|
|
146
|
+
*
|
|
147
|
+
* clamp(5, 0, 10); // 5
|
|
148
|
+
* clamp(-5, 0, 10); // 0
|
|
149
|
+
* clamp(15, 0, 10); // 10
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export declare function clamp(value: number, min: number, max: number): number;
|
|
153
|
+
/**
|
|
154
|
+
* Generates a random number between min and max
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { random } from '@fluixi/core/utils';
|
|
159
|
+
*
|
|
160
|
+
* const num = random(1, 100);
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export declare function random(min: number, max: number): number;
|
|
164
|
+
/**
|
|
165
|
+
* Checks if a value is empty
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* import { isEmpty } from '@fluixi/core/utils';
|
|
170
|
+
*
|
|
171
|
+
* isEmpty(''); // true
|
|
172
|
+
* isEmpty([]); // true
|
|
173
|
+
* isEmpty({}); // true
|
|
174
|
+
* isEmpty(null); // true
|
|
175
|
+
* isEmpty('text'); // false
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export declare function isEmpty(value: any): boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Picks specific keys from an object
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* import { pick } from '@fluixi/core/utils';
|
|
185
|
+
*
|
|
186
|
+
* const obj = { a: 1, b: 2, c: 3 };
|
|
187
|
+
* pick(obj, 'a', 'c'); // { a: 1, c: 3 }
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export declare function pick<T extends object, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;
|
|
191
|
+
/**
|
|
192
|
+
* Omits specific keys from an object
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* import { omit } from '@fluixi/core/utils';
|
|
197
|
+
*
|
|
198
|
+
* const obj = { a: 1, b: 2, c: 3 };
|
|
199
|
+
* omit(obj, 'b'); // { a: 1, c: 3 }
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
export declare function omit<T extends object, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K>;
|
|
203
|
+
/**
|
|
204
|
+
* Groups array items by a key
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```typescript
|
|
208
|
+
* import { groupBy } from '@fluixi/core/utils';
|
|
209
|
+
*
|
|
210
|
+
* const users = [
|
|
211
|
+
* { name: 'Alice', role: 'admin' },
|
|
212
|
+
* { name: 'Bob', role: 'user' },
|
|
213
|
+
* { name: 'Charlie', role: 'admin' }
|
|
214
|
+
* ];
|
|
215
|
+
* const grouped = groupBy(users, u => u.role);
|
|
216
|
+
* // Map { 'admin' => [...], 'user' => [...] }
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
export declare function groupBy<T, K>(array: T[], fn: (item: T) => K): Map<K, T[]>;
|
|
220
|
+
/**
|
|
221
|
+
* Creates an array of numbers from start to end
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* import { range } from '@fluixi/core/utils';
|
|
226
|
+
*
|
|
227
|
+
* range(0, 5); // [0, 1, 2, 3, 4, 5]
|
|
228
|
+
* range(0, 10, 2); // [0, 2, 4, 6, 8, 10]
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
export declare function range(start: number, end: number, step?: number): number[];
|
|
232
|
+
/**
|
|
233
|
+
* Retries an async function
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```typescript
|
|
237
|
+
* import { retry } from '@fluixi/core/utils';
|
|
238
|
+
*
|
|
239
|
+
* const data = await retry(
|
|
240
|
+
* () => fetch('/api/data').then(r => r.json()),
|
|
241
|
+
* 3,
|
|
242
|
+
* 1000
|
|
243
|
+
* );
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
export declare function retry<T>(fn: () => Promise<T>, retries?: number, delay?: number): Promise<T>;
|
|
247
|
+
/**
|
|
248
|
+
* Sleep for specified milliseconds
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```typescript
|
|
252
|
+
* import { sleep } from '@fluixi/core/utils';
|
|
253
|
+
*
|
|
254
|
+
* await sleep(1000); // Wait 1 second
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
258
|
+
/**
|
|
259
|
+
* Type guard to check if value is defined
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```typescript
|
|
263
|
+
* import { isDefined } from '@fluixi/core/utils';
|
|
264
|
+
*
|
|
265
|
+
* const values = [1, null, 2, undefined, 3];
|
|
266
|
+
* const defined = values.filter(isDefined); // [1, 2, 3]
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
export declare function isDefined<T>(value: T | null | undefined): value is T;
|
|
270
|
+
/**
|
|
271
|
+
* Creates a chainable pipe function
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* import { pipe } from '@fluixi/core/utils';
|
|
276
|
+
*
|
|
277
|
+
* const transform = pipe(
|
|
278
|
+
* (x: number) => x * 2,
|
|
279
|
+
* (x: number) => x + 1,
|
|
280
|
+
* (x: number) => x.toString()
|
|
281
|
+
* );
|
|
282
|
+
* transform(5); // '11'
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
export declare function pipe<T>(...fns: Array<(arg: any) => any>): (arg: T) => any;
|
|
286
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/utils/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @fluixi/core/utils
|
|
3
|
+
*
|
|
4
|
+
* This module provides general utility functions for common operations.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Debounces a function call
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { debounce } from '@fluixi/core/utils';
|
|
12
|
+
*
|
|
13
|
+
* const handleInput = debounce((value: string) => {
|
|
14
|
+
* console.log('Input:', value);
|
|
15
|
+
* }, 300);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function debounce(fn, delay) {
|
|
19
|
+
let timeoutId;
|
|
20
|
+
return (...args) => {
|
|
21
|
+
clearTimeout(timeoutId);
|
|
22
|
+
timeoutId = setTimeout(() => fn(...args), delay);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Throttles a function call
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { throttle } from '@fluixi/core/utils';
|
|
31
|
+
*
|
|
32
|
+
* const handleScroll = throttle(() => {
|
|
33
|
+
* console.log('Scrolled');
|
|
34
|
+
* }, 100);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function throttle(fn, limit) {
|
|
38
|
+
let inThrottle;
|
|
39
|
+
return (...args) => {
|
|
40
|
+
if (!inThrottle) {
|
|
41
|
+
fn(...args);
|
|
42
|
+
inThrottle = true;
|
|
43
|
+
setTimeout(() => (inThrottle = false), limit);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a memoized version of a function
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { memoize } from '@fluixi/core/utils';
|
|
53
|
+
*
|
|
54
|
+
* const expensiveCalc = memoize((n: number) => {
|
|
55
|
+
* return n * n;
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export function memoize(fn) {
|
|
60
|
+
const cache = new Map();
|
|
61
|
+
return ((...args) => {
|
|
62
|
+
const key = JSON.stringify(args);
|
|
63
|
+
if (cache.has(key)) {
|
|
64
|
+
return cache.get(key);
|
|
65
|
+
}
|
|
66
|
+
const result = fn(...args);
|
|
67
|
+
cache.set(key, result);
|
|
68
|
+
return result;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Deep clones an object
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* import { deepClone } from '@fluixi/core/utils';
|
|
77
|
+
*
|
|
78
|
+
* const original = { a: 1, b: { c: 2 } };
|
|
79
|
+
* const copy = deepClone(original);
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function deepClone(obj) {
|
|
83
|
+
if (obj === null || typeof obj !== 'object') {
|
|
84
|
+
return obj;
|
|
85
|
+
}
|
|
86
|
+
if (obj instanceof Date) {
|
|
87
|
+
return new Date(obj.getTime());
|
|
88
|
+
}
|
|
89
|
+
if (obj instanceof Array) {
|
|
90
|
+
return Array.from(obj).map((item) => deepClone(item));
|
|
91
|
+
}
|
|
92
|
+
if (obj instanceof Set) {
|
|
93
|
+
return new Set(Array.from(obj).map((item) => deepClone(item)));
|
|
94
|
+
}
|
|
95
|
+
if (obj instanceof Map) {
|
|
96
|
+
return new Map(Array.from(obj.entries()).map(([key, value]) => [
|
|
97
|
+
deepClone(key),
|
|
98
|
+
deepClone(value),
|
|
99
|
+
]));
|
|
100
|
+
}
|
|
101
|
+
const clonedObj = {};
|
|
102
|
+
for (const key in obj) {
|
|
103
|
+
if (obj.hasOwnProperty(key)) {
|
|
104
|
+
clonedObj[key] = deepClone(obj[key]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return clonedObj;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Deep merges multiple objects
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* import { deepMerge } from '@fluixi/core/utils';
|
|
115
|
+
*
|
|
116
|
+
* const result = deepMerge(
|
|
117
|
+
* { a: 1, b: { c: 2 } },
|
|
118
|
+
* { b: { d: 3 } }
|
|
119
|
+
* );
|
|
120
|
+
* // { a: 1, b: { c: 2, d: 3 } }
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export function deepMerge(...objects) {
|
|
124
|
+
const result = {};
|
|
125
|
+
for (const obj of objects) {
|
|
126
|
+
for (const key in obj) {
|
|
127
|
+
if (obj.hasOwnProperty(key)) {
|
|
128
|
+
const value = obj[key];
|
|
129
|
+
if (value !== null &&
|
|
130
|
+
typeof value === 'object' &&
|
|
131
|
+
!Array.isArray(value)) {
|
|
132
|
+
result[key] = deepMerge(result[key] || {}, value);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
result[key] = value;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Generates a unique ID
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* import { uniqueId } from '@fluixi/core/utils';
|
|
148
|
+
*
|
|
149
|
+
* const id = uniqueId('component-');
|
|
150
|
+
* // 'component-abc123def456'
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export function uniqueId(prefix = '') {
|
|
154
|
+
return prefix + Math.random().toString(36).substr(2, 9);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Formats a number with commas
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```typescript
|
|
161
|
+
* import { formatNumber } from '@fluixi/core/utils';
|
|
162
|
+
*
|
|
163
|
+
* formatNumber(1234567); // '1,234,567'
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export function formatNumber(num) {
|
|
167
|
+
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Formats bytes to human readable string
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* import { formatBytes } from '@fluixi/core/utils';
|
|
175
|
+
*
|
|
176
|
+
* formatBytes(1024); // '1 KB'
|
|
177
|
+
* formatBytes(1048576); // '1 MB'
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
export function formatBytes(bytes, decimals = 2) {
|
|
181
|
+
if (bytes === 0)
|
|
182
|
+
return '0 Bytes';
|
|
183
|
+
const k = 1024;
|
|
184
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
185
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
186
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
187
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Capitalizes first letter of a string
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* import { capitalize } from '@fluixi/core/utils';
|
|
195
|
+
*
|
|
196
|
+
* capitalize('hello'); // 'Hello'
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export function capitalize(str) {
|
|
200
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Converts string to kebab-case
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* import { kebabCase } from '@fluixi/core/utils';
|
|
208
|
+
*
|
|
209
|
+
* kebabCase('HelloWorld'); // 'hello-world'
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export function kebabCase(str) {
|
|
213
|
+
return str
|
|
214
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
215
|
+
.replace(/[\s_]+/g, '-')
|
|
216
|
+
.toLowerCase();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Converts string to camelCase
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```typescript
|
|
223
|
+
* import { camelCase } from '@fluixi/core/utils';
|
|
224
|
+
*
|
|
225
|
+
* camelCase('hello-world'); // 'helloWorld'
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
export function camelCase(str) {
|
|
229
|
+
return str.replace(/[-_\s](.)/g, (_, char) => char.toUpperCase());
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Clamps a number between min and max
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* import { clamp } from '@fluixi/core/utils';
|
|
237
|
+
*
|
|
238
|
+
* clamp(5, 0, 10); // 5
|
|
239
|
+
* clamp(-5, 0, 10); // 0
|
|
240
|
+
* clamp(15, 0, 10); // 10
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
243
|
+
export function clamp(value, min, max) {
|
|
244
|
+
return Math.min(Math.max(value, min), max);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Generates a random number between min and max
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* import { random } from '@fluixi/core/utils';
|
|
252
|
+
*
|
|
253
|
+
* const num = random(1, 100);
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
export function random(min, max) {
|
|
257
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Checks if a value is empty
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```typescript
|
|
264
|
+
* import { isEmpty } from '@fluixi/core/utils';
|
|
265
|
+
*
|
|
266
|
+
* isEmpty(''); // true
|
|
267
|
+
* isEmpty([]); // true
|
|
268
|
+
* isEmpty({}); // true
|
|
269
|
+
* isEmpty(null); // true
|
|
270
|
+
* isEmpty('text'); // false
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
export function isEmpty(value) {
|
|
274
|
+
if (value === null || value === undefined)
|
|
275
|
+
return true;
|
|
276
|
+
if (typeof value === 'string')
|
|
277
|
+
return value.trim().length === 0;
|
|
278
|
+
if (Array.isArray(value))
|
|
279
|
+
return value.length === 0;
|
|
280
|
+
if (typeof value === 'object')
|
|
281
|
+
return Object.keys(value).length === 0;
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Picks specific keys from an object
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* ```typescript
|
|
289
|
+
* import { pick } from '@fluixi/core/utils';
|
|
290
|
+
*
|
|
291
|
+
* const obj = { a: 1, b: 2, c: 3 };
|
|
292
|
+
* pick(obj, 'a', 'c'); // { a: 1, c: 3 }
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
export function pick(obj, ...keys) {
|
|
296
|
+
const result = {};
|
|
297
|
+
keys.forEach((key) => {
|
|
298
|
+
if (key in obj) {
|
|
299
|
+
result[key] = obj[key];
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
return result;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Omits specific keys from an object
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* import { omit } from '@fluixi/core/utils';
|
|
310
|
+
*
|
|
311
|
+
* const obj = { a: 1, b: 2, c: 3 };
|
|
312
|
+
* omit(obj, 'b'); // { a: 1, c: 3 }
|
|
313
|
+
* ```
|
|
314
|
+
*/
|
|
315
|
+
export function omit(obj, ...keys) {
|
|
316
|
+
const result = { ...obj };
|
|
317
|
+
keys.forEach((key) => {
|
|
318
|
+
delete result[key];
|
|
319
|
+
});
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Groups array items by a key
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```typescript
|
|
327
|
+
* import { groupBy } from '@fluixi/core/utils';
|
|
328
|
+
*
|
|
329
|
+
* const users = [
|
|
330
|
+
* { name: 'Alice', role: 'admin' },
|
|
331
|
+
* { name: 'Bob', role: 'user' },
|
|
332
|
+
* { name: 'Charlie', role: 'admin' }
|
|
333
|
+
* ];
|
|
334
|
+
* const grouped = groupBy(users, u => u.role);
|
|
335
|
+
* // Map { 'admin' => [...], 'user' => [...] }
|
|
336
|
+
* ```
|
|
337
|
+
*/
|
|
338
|
+
export function groupBy(array, fn) {
|
|
339
|
+
return array.reduce((acc, item) => {
|
|
340
|
+
const key = fn(item);
|
|
341
|
+
const group = acc.get(key) || [];
|
|
342
|
+
group.push(item);
|
|
343
|
+
acc.set(key, group);
|
|
344
|
+
return acc;
|
|
345
|
+
}, new Map());
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Creates an array of numbers from start to end
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```typescript
|
|
352
|
+
* import { range } from '@fluixi/core/utils';
|
|
353
|
+
*
|
|
354
|
+
* range(0, 5); // [0, 1, 2, 3, 4, 5]
|
|
355
|
+
* range(0, 10, 2); // [0, 2, 4, 6, 8, 10]
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
export function range(start, end, step = 1) {
|
|
359
|
+
const result = [];
|
|
360
|
+
for (let i = start; i <= end; i += step) {
|
|
361
|
+
result.push(i);
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Retries an async function
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```typescript
|
|
370
|
+
* import { retry } from '@fluixi/core/utils';
|
|
371
|
+
*
|
|
372
|
+
* const data = await retry(
|
|
373
|
+
* () => fetch('/api/data').then(r => r.json()),
|
|
374
|
+
* 3,
|
|
375
|
+
* 1000
|
|
376
|
+
* );
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
export async function retry(fn, retries = 3, delay = 1000) {
|
|
380
|
+
try {
|
|
381
|
+
return await fn();
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
if (retries <= 0)
|
|
385
|
+
throw error;
|
|
386
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
387
|
+
return retry(fn, retries - 1, delay);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Sleep for specified milliseconds
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* ```typescript
|
|
395
|
+
* import { sleep } from '@fluixi/core/utils';
|
|
396
|
+
*
|
|
397
|
+
* await sleep(1000); // Wait 1 second
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
export function sleep(ms) {
|
|
401
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Type guard to check if value is defined
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* ```typescript
|
|
408
|
+
* import { isDefined } from '@fluixi/core/utils';
|
|
409
|
+
*
|
|
410
|
+
* const values = [1, null, 2, undefined, 3];
|
|
411
|
+
* const defined = values.filter(isDefined); // [1, 2, 3]
|
|
412
|
+
* ```
|
|
413
|
+
*/
|
|
414
|
+
export function isDefined(value) {
|
|
415
|
+
return value !== null && value !== undefined;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Creates a chainable pipe function
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```typescript
|
|
422
|
+
* import { pipe } from '@fluixi/core/utils';
|
|
423
|
+
*
|
|
424
|
+
* const transform = pipe(
|
|
425
|
+
* (x: number) => x * 2,
|
|
426
|
+
* (x: number) => x + 1,
|
|
427
|
+
* (x: number) => x.toString()
|
|
428
|
+
* );
|
|
429
|
+
* transform(5); // '11'
|
|
430
|
+
* ```
|
|
431
|
+
*/
|
|
432
|
+
export function pipe(...fns) {
|
|
433
|
+
return (arg) => fns.reduce((acc, fn) => fn(acc), arg);
|
|
434
|
+
}
|