@logosdx/hooks 1.0.0-beta.0 → 1.0.0-beta.2
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/CHANGELOG.md +7 -0
- package/dist/browser/bundle.js +1 -1
- package/dist/browser/bundle.js.map +1 -1
- package/dist/cjs/index.js +415 -305
- package/dist/esm/index.mjs +427 -347
- package/dist/types/index.d.ts +196 -132
- package/package.json +15 -8
- package/readme.md +1 -5
- package/src/index.ts +385 -260
package/dist/types/index.d.ts
CHANGED
|
@@ -1,228 +1,292 @@
|
|
|
1
1
|
import { AsyncFunc, FunctionProps } from '@logosdx/utils';
|
|
2
2
|
/**
|
|
3
|
-
* Error thrown when a hook
|
|
3
|
+
* Error thrown when a hook calls `ctx.fail()`.
|
|
4
|
+
*
|
|
5
|
+
* This error is only created when using the default `handleFail` behavior.
|
|
6
|
+
* If a custom `handleFail` is provided, that error type is thrown instead.
|
|
4
7
|
*
|
|
5
8
|
* @example
|
|
6
|
-
*
|
|
9
|
+
* hooks.on('validate', async (ctx) => {
|
|
7
10
|
* if (!ctx.args[0].isValid) {
|
|
8
11
|
* ctx.fail('Validation failed');
|
|
9
12
|
* }
|
|
10
13
|
* });
|
|
11
14
|
*
|
|
12
|
-
* const [, err] = await attempt(() =>
|
|
15
|
+
* const [, err] = await attempt(() => engine.emit('validate', data));
|
|
13
16
|
* if (isHookError(err)) {
|
|
14
|
-
* console.log(err.hookName); // '
|
|
15
|
-
* console.log(err.extPoint); // 'before'
|
|
17
|
+
* console.log(err.hookName); // 'validate'
|
|
16
18
|
* }
|
|
17
19
|
*/
|
|
18
20
|
export declare class HookError extends Error {
|
|
19
21
|
/** Name of the hook where the error occurred */
|
|
20
22
|
hookName?: string;
|
|
21
|
-
/** Extension point where the error occurred: 'before', 'after', or 'error' */
|
|
22
|
-
extPoint?: string;
|
|
23
23
|
/** Original error if `fail()` was called with an Error instance */
|
|
24
24
|
originalError?: Error;
|
|
25
|
-
/** Whether the hook was explicitly aborted via `fail()` */
|
|
26
|
-
aborted: boolean;
|
|
27
25
|
constructor(message: string);
|
|
28
26
|
}
|
|
29
27
|
/**
|
|
30
28
|
* Type guard to check if an error is a HookError.
|
|
31
29
|
*
|
|
32
30
|
* @example
|
|
33
|
-
* const
|
|
34
|
-
* if (isHookError(
|
|
35
|
-
* console.log(`Hook "${
|
|
31
|
+
* const { error } = await engine.emit('validate', data);
|
|
32
|
+
* if (isHookError(error)) {
|
|
33
|
+
* console.log(`Hook "${error.hookName}" failed`);
|
|
36
34
|
* }
|
|
37
35
|
*/
|
|
38
36
|
export declare const isHookError: (error: unknown) => error is HookError;
|
|
39
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Result returned from `emit()` after running all hook callbacks.
|
|
39
|
+
*/
|
|
40
|
+
export interface EmitResult<F extends AsyncFunc> {
|
|
41
|
+
/** Current arguments (possibly modified by callbacks) */
|
|
40
42
|
args: Parameters<F>;
|
|
41
|
-
|
|
43
|
+
/** Result value (if set by a callback) */
|
|
44
|
+
result?: Awaited<ReturnType<F>> | undefined;
|
|
45
|
+
/** Whether a callback called `returnEarly()` */
|
|
46
|
+
earlyReturn: boolean;
|
|
42
47
|
}
|
|
43
48
|
/**
|
|
44
|
-
* Context object passed to hook
|
|
49
|
+
* Context object passed to hook callbacks.
|
|
45
50
|
* Provides access to arguments, results, and control methods.
|
|
46
51
|
*
|
|
47
52
|
* @example
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* const
|
|
53
|
+
* hooks.on('cacheCheck', async (ctx) => {
|
|
54
|
+
* const [url] = ctx.args;
|
|
55
|
+
* const cached = cache.get(url);
|
|
51
56
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* // Or skip the original function entirely
|
|
56
|
-
* if (isCached(url)) {
|
|
57
|
-
* ctx.setResult(getCached(url));
|
|
57
|
+
* if (cached) {
|
|
58
|
+
* ctx.setResult(cached);
|
|
58
59
|
* ctx.returnEarly();
|
|
59
60
|
* }
|
|
60
61
|
* });
|
|
61
62
|
*/
|
|
62
|
-
export interface HookContext<F extends AsyncFunc
|
|
63
|
-
/** Current
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
|
|
67
|
-
/** Abort hook execution with an error.
|
|
68
|
-
fail: (
|
|
69
|
-
/** Replace the arguments
|
|
63
|
+
export interface HookContext<F extends AsyncFunc, FailArgs extends unknown[] = [string]> {
|
|
64
|
+
/** Current arguments passed to emit() */
|
|
65
|
+
args: Parameters<F>;
|
|
66
|
+
/** Result value (can be set by callbacks) */
|
|
67
|
+
result?: Awaited<ReturnType<F>>;
|
|
68
|
+
/** Abort hook execution with an error. */
|
|
69
|
+
fail: (...args: FailArgs) => never;
|
|
70
|
+
/** Replace the arguments for subsequent callbacks */
|
|
70
71
|
setArgs: (next: Parameters<F>) => void;
|
|
71
|
-
/**
|
|
72
|
+
/** Set the result value */
|
|
72
73
|
setResult: (next: Awaited<ReturnType<F>>) => void;
|
|
73
|
-
/**
|
|
74
|
+
/** Stop processing remaining callbacks and return early */
|
|
74
75
|
returnEarly: () => void;
|
|
75
|
-
/** Remove this
|
|
76
|
+
/** Remove this callback from the hook */
|
|
76
77
|
removeHook: () => void;
|
|
77
78
|
}
|
|
78
|
-
export type HookFn<F extends AsyncFunc> = (ctx: HookContext<F>) => Promise<void>;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
after: Set<HookFn<F>>;
|
|
82
|
-
error: Set<HookFn<F>>;
|
|
83
|
-
}
|
|
84
|
-
type HookExtOptions<F extends AsyncFunc> = {
|
|
85
|
-
callback: HookFn<F>;
|
|
79
|
+
export type HookFn<F extends AsyncFunc, FailArgs extends unknown[] = [string]> = (ctx: HookContext<F, FailArgs>) => Promise<void>;
|
|
80
|
+
type HookOptions<F extends AsyncFunc, FailArgs extends unknown[] = [string]> = {
|
|
81
|
+
callback: HookFn<F, FailArgs>;
|
|
86
82
|
once?: true;
|
|
87
83
|
ignoreOnFail?: true;
|
|
88
84
|
};
|
|
89
|
-
type
|
|
90
|
-
type MakeHookOptions = {
|
|
91
|
-
bindTo?: any;
|
|
92
|
-
};
|
|
85
|
+
type HookOrOptions<F extends AsyncFunc, FailArgs extends unknown[] = [string]> = HookFn<F, FailArgs> | HookOptions<F, FailArgs>;
|
|
93
86
|
type FuncOrNever<T> = T extends AsyncFunc ? T : never;
|
|
94
87
|
/**
|
|
95
|
-
*
|
|
88
|
+
* Custom error handler for `ctx.fail()`.
|
|
89
|
+
* Can be an Error constructor or a function that throws.
|
|
90
|
+
*/
|
|
91
|
+
export type HandleFail<Args extends unknown[] = [string]> = (new (...args: Args) => Error) | ((...args: Args) => never);
|
|
92
|
+
/**
|
|
93
|
+
* Options for HookEngine constructor.
|
|
94
|
+
*/
|
|
95
|
+
export interface HookEngineOptions<FailArgs extends unknown[] = [string]> {
|
|
96
|
+
/**
|
|
97
|
+
* Custom handler for `ctx.fail()`.
|
|
98
|
+
* Can be an Error constructor or a function that throws.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* // Use Firebase HttpsError
|
|
102
|
+
* new HookEngine({ handleFail: HttpsError });
|
|
103
|
+
*
|
|
104
|
+
* // Use custom function
|
|
105
|
+
* new HookEngine({
|
|
106
|
+
* handleFail: (msg, data) => { throw Boom.badRequest(msg, data); }
|
|
107
|
+
* });
|
|
108
|
+
*/
|
|
109
|
+
handleFail?: HandleFail<FailArgs>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* A lightweight, type-safe lifecycle hook system.
|
|
96
113
|
*
|
|
97
|
-
* HookEngine allows you to
|
|
98
|
-
*
|
|
99
|
-
* results, or abort execution entirely.
|
|
114
|
+
* HookEngine allows you to define lifecycle events and subscribe to them.
|
|
115
|
+
* Callbacks can modify arguments, set results, or abort execution.
|
|
100
116
|
*
|
|
101
117
|
* @example
|
|
102
|
-
* interface
|
|
103
|
-
*
|
|
104
|
-
*
|
|
118
|
+
* interface FetchLifecycle {
|
|
119
|
+
* preRequest(url: string, options: RequestInit): Promise<Response>;
|
|
120
|
+
* rateLimit(error: Error, attempt: number): Promise<void>;
|
|
121
|
+
* cacheHit(url: string, data: unknown): Promise<unknown>;
|
|
105
122
|
* }
|
|
106
123
|
*
|
|
107
|
-
* const
|
|
108
|
-
* const hooks = new HookEngine<MyApp>();
|
|
124
|
+
* const hooks = new HookEngine<FetchLifecycle>();
|
|
109
125
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* hooks.extend('save', 'before', async (ctx) => {
|
|
115
|
-
* if (!ctx.args[0].isValid) {
|
|
116
|
-
* ctx.fail('Validation failed');
|
|
117
|
-
* }
|
|
126
|
+
* hooks.on('rateLimit', async (ctx) => {
|
|
127
|
+
* const [error, attempt] = ctx.args;
|
|
128
|
+
* if (attempt > 3) ctx.fail('Max retries exceeded');
|
|
129
|
+
* await sleep(error.retryAfter * 1000);
|
|
118
130
|
* });
|
|
119
131
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* console.log('Saved:', ctx.results);
|
|
132
|
+
* hooks.on('cacheHit', async (ctx) => {
|
|
133
|
+
* console.log('Cache hit for:', ctx.args[0]);
|
|
123
134
|
* });
|
|
124
135
|
*
|
|
125
|
-
*
|
|
136
|
+
* // In your implementation
|
|
137
|
+
* const result = await hooks.emit('cacheHit', url, cachedData);
|
|
138
|
+
*
|
|
139
|
+
* @typeParam Lifecycle - Interface defining the lifecycle hooks
|
|
140
|
+
* @typeParam FailArgs - Arguments type for ctx.fail() (default: [string])
|
|
141
|
+
*/
|
|
142
|
+
/**
|
|
143
|
+
* Default permissive lifecycle type when no type parameter is provided.
|
|
126
144
|
*/
|
|
127
|
-
|
|
128
|
-
|
|
145
|
+
type DefaultLifecycle = Record<string, AsyncFunc>;
|
|
146
|
+
/**
|
|
147
|
+
* Extract only function property keys from a type.
|
|
148
|
+
* This ensures only methods are available as hook names, not data properties.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* interface Doc {
|
|
152
|
+
* id: string;
|
|
153
|
+
* save(): Promise<void>;
|
|
154
|
+
* delete(): Promise<void>;
|
|
155
|
+
* }
|
|
156
|
+
*
|
|
157
|
+
* type DocHooks = HookName<Doc>; // 'save' | 'delete' (excludes 'id')
|
|
158
|
+
*/
|
|
159
|
+
export type HookName<T> = FunctionProps<T>;
|
|
160
|
+
export declare class HookEngine<Lifecycle = DefaultLifecycle, FailArgs extends unknown[] = [string]> {
|
|
161
|
+
constructor(options?: HookEngineOptions<FailArgs>);
|
|
129
162
|
/**
|
|
130
|
-
*
|
|
163
|
+
* Register hook names for runtime validation.
|
|
164
|
+
* Once any hooks are registered, all hooks must be registered before use.
|
|
165
|
+
*
|
|
166
|
+
* @param names - Hook names to register
|
|
167
|
+
* @returns this (for chaining)
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* const hooks = new HookEngine<FetchLifecycle>()
|
|
171
|
+
* .register('preRequest', 'postRequest', 'rateLimit');
|
|
131
172
|
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
|
|
135
|
-
|
|
173
|
+
* hooks.on('preRequest', cb); // OK
|
|
174
|
+
* hooks.on('preRequset', cb); // Error: not registered (typo caught!)
|
|
175
|
+
*/
|
|
176
|
+
register(...names: HookName<Lifecycle>[]): this;
|
|
177
|
+
/**
|
|
178
|
+
* Subscribe to a lifecycle hook.
|
|
136
179
|
*
|
|
137
|
-
* @param name - Name of the
|
|
138
|
-
* @param
|
|
139
|
-
* @
|
|
140
|
-
* @returns Cleanup function to remove the extension
|
|
180
|
+
* @param name - Name of the lifecycle hook
|
|
181
|
+
* @param cbOrOpts - Callback function or options object
|
|
182
|
+
* @returns Cleanup function to remove the subscription
|
|
141
183
|
*
|
|
142
184
|
* @example
|
|
143
185
|
* // Simple callback
|
|
144
|
-
* const cleanup = hooks.
|
|
145
|
-
* console.log('
|
|
186
|
+
* const cleanup = hooks.on('preRequest', async (ctx) => {
|
|
187
|
+
* console.log('Request:', ctx.args[0]);
|
|
146
188
|
* });
|
|
147
189
|
*
|
|
148
190
|
* // With options
|
|
149
|
-
* hooks.
|
|
150
|
-
* callback: async (ctx) => {
|
|
191
|
+
* hooks.on('analytics', {
|
|
192
|
+
* callback: async (ctx) => { track(ctx.args); },
|
|
151
193
|
* once: true, // Remove after first run
|
|
152
|
-
* ignoreOnFail: true // Don't throw if
|
|
194
|
+
* ignoreOnFail: true // Don't throw if callback fails
|
|
153
195
|
* });
|
|
154
196
|
*
|
|
155
|
-
* //
|
|
197
|
+
* // Remove subscription
|
|
156
198
|
* cleanup();
|
|
157
199
|
*/
|
|
158
|
-
|
|
200
|
+
on<K extends HookName<Lifecycle>>(name: K, cbOrOpts: HookOrOptions<FuncOrNever<Lifecycle[K]>, FailArgs>): () => void;
|
|
159
201
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* The wrapped function behaves identically to the original but allows
|
|
163
|
-
* extensions to be added via `extend()`. Use `wrap()` for a simpler API
|
|
164
|
-
* when working with object methods.
|
|
202
|
+
* Subscribe to a lifecycle hook that fires only once.
|
|
203
|
+
* Sugar for `on(name, { callback, once: true })`.
|
|
165
204
|
*
|
|
166
|
-
* @param name -
|
|
167
|
-
* @param
|
|
168
|
-
* @
|
|
169
|
-
* @returns Wrapped function with hook support
|
|
205
|
+
* @param name - Name of the lifecycle hook
|
|
206
|
+
* @param callback - Callback function
|
|
207
|
+
* @returns Cleanup function to remove the subscription
|
|
170
208
|
*
|
|
171
209
|
* @example
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* hooks.extend('fetch', 'before', async (ctx) => {
|
|
177
|
-
* console.log('Fetching:', ctx.args[0]);
|
|
210
|
+
* // Log only the first request
|
|
211
|
+
* hooks.once('preRequest', async (ctx) => {
|
|
212
|
+
* console.log('First request:', ctx.args[0]);
|
|
178
213
|
* });
|
|
179
|
-
*
|
|
180
|
-
* await hookedFetch('/api/data');
|
|
181
214
|
*/
|
|
182
|
-
|
|
215
|
+
once<K extends HookName<Lifecycle>>(name: K, callback: HookFn<FuncOrNever<Lifecycle[K]>, FailArgs>): () => void;
|
|
183
216
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* This is a convenience method that combines `make()` with automatic
|
|
187
|
-
* binding and reassignment. The method is replaced on the instance
|
|
188
|
-
* with the wrapped version.
|
|
217
|
+
* Emit a lifecycle hook, running all subscribed callbacks.
|
|
189
218
|
*
|
|
190
|
-
* @param
|
|
191
|
-
* @param
|
|
192
|
-
* @
|
|
219
|
+
* @param name - Name of the lifecycle hook to emit
|
|
220
|
+
* @param args - Arguments to pass to callbacks
|
|
221
|
+
* @returns EmitResult with final args, result, and earlyReturn flag
|
|
193
222
|
*
|
|
194
223
|
* @example
|
|
195
|
-
*
|
|
196
|
-
*
|
|
224
|
+
* const result = await hooks.emit('cacheCheck', url);
|
|
225
|
+
*
|
|
226
|
+
* if (result.earlyReturn && result.result) {
|
|
227
|
+
* return result.result; // Use cached value
|
|
197
228
|
* }
|
|
198
229
|
*
|
|
199
|
-
*
|
|
200
|
-
* const
|
|
230
|
+
* // Continue with modified args
|
|
231
|
+
* const [modifiedUrl] = result.args;
|
|
232
|
+
*/
|
|
233
|
+
emit<K extends HookName<Lifecycle>>(name: K, ...args: Parameters<FuncOrNever<Lifecycle[K]>>): Promise<EmitResult<FuncOrNever<Lifecycle[K]>>>;
|
|
234
|
+
/**
|
|
235
|
+
* Clear all registered hooks.
|
|
201
236
|
*
|
|
202
|
-
*
|
|
237
|
+
* @example
|
|
238
|
+
* hooks.on('preRequest', validator);
|
|
239
|
+
* hooks.on('postRequest', logger);
|
|
203
240
|
*
|
|
204
|
-
* //
|
|
205
|
-
* hooks.
|
|
206
|
-
* console.log('Saving user:', ctx.args[0]);
|
|
207
|
-
* });
|
|
241
|
+
* // Reset for testing
|
|
242
|
+
* hooks.clear();
|
|
208
243
|
*/
|
|
209
|
-
|
|
244
|
+
clear(): void;
|
|
210
245
|
/**
|
|
211
|
-
*
|
|
246
|
+
* Wrap a function with pre/post lifecycle hooks.
|
|
247
|
+
*
|
|
248
|
+
* - Pre hook: emitted with function args, can modify args or returnEarly with result
|
|
249
|
+
* - Post hook: emitted with [result, ...args], can modify result
|
|
212
250
|
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
251
|
+
* @param fn - The async function to wrap
|
|
252
|
+
* @param hooks - Object with optional pre and post hook names
|
|
253
|
+
* @returns Wrapped function with same signature
|
|
216
254
|
*
|
|
217
255
|
* @example
|
|
218
|
-
*
|
|
219
|
-
*
|
|
256
|
+
* interface Lifecycle {
|
|
257
|
+
* preRequest(url: string, opts: RequestInit): Promise<Response>;
|
|
258
|
+
* postRequest(result: Response, url: string, opts: RequestInit): Promise<Response>;
|
|
259
|
+
* }
|
|
220
260
|
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
261
|
+
* const hooks = new HookEngine<Lifecycle>();
|
|
262
|
+
*
|
|
263
|
+
* // Add cache check in pre hook
|
|
264
|
+
* hooks.on('preRequest', async (ctx) => {
|
|
265
|
+
* const cached = cache.get(ctx.args[0]);
|
|
266
|
+
* if (cached) {
|
|
267
|
+
* ctx.setResult(cached);
|
|
268
|
+
* ctx.returnEarly();
|
|
269
|
+
* }
|
|
270
|
+
* });
|
|
223
271
|
*
|
|
224
|
-
* //
|
|
272
|
+
* // Log result in post hook
|
|
273
|
+
* hooks.on('postRequest', async (ctx) => {
|
|
274
|
+
* const [result, url] = ctx.args;
|
|
275
|
+
* console.log(`Fetched ${url}:`, result.status);
|
|
276
|
+
* });
|
|
277
|
+
*
|
|
278
|
+
* // Wrap the fetch function
|
|
279
|
+
* const wrappedFetch = hooks.wrap(
|
|
280
|
+
* async (url: string, opts: RequestInit) => fetch(url, opts),
|
|
281
|
+
* { pre: 'preRequest', post: 'postRequest' }
|
|
282
|
+
* );
|
|
225
283
|
*/
|
|
226
|
-
|
|
284
|
+
wrap<F extends AsyncFunc>(fn: F, hooks: {
|
|
285
|
+
pre: HookName<Lifecycle>;
|
|
286
|
+
post?: HookName<Lifecycle>;
|
|
287
|
+
} | {
|
|
288
|
+
pre?: HookName<Lifecycle>;
|
|
289
|
+
post: HookName<Lifecycle>;
|
|
290
|
+
}): (...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>>;
|
|
227
291
|
}
|
|
228
292
|
export {};
|
package/package.json
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
+
"name": "@logosdx/hooks",
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
|
+
"description": "A lightweight, type-safe hook system for extending function behavior",
|
|
2
5
|
"license": "BSD-3-Clause",
|
|
3
6
|
"homepage": "https://logosdx.dev/",
|
|
4
7
|
"bugs": {
|
|
@@ -6,11 +9,10 @@
|
|
|
6
9
|
"email": "danilo@alonso.network"
|
|
7
10
|
},
|
|
8
11
|
"author": "Danilo Alonso <danilo@alonso.network>",
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"@logosdx/utils": "^5.0.0"
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/logosdx/monorepo",
|
|
15
|
+
"directory": "packages/hooks"
|
|
14
16
|
},
|
|
15
17
|
"keywords": [
|
|
16
18
|
"hooks",
|
|
@@ -18,6 +20,7 @@
|
|
|
18
20
|
"extensions",
|
|
19
21
|
"before after"
|
|
20
22
|
],
|
|
23
|
+
"sideEffects": false,
|
|
21
24
|
"files": [
|
|
22
25
|
"dist",
|
|
23
26
|
"src",
|
|
@@ -27,10 +30,14 @@
|
|
|
27
30
|
],
|
|
28
31
|
"exports": {
|
|
29
32
|
".": {
|
|
30
|
-
"require": "./dist/cjs/index.js",
|
|
31
|
-
"import": "./dist/esm/index.mjs",
|
|
32
33
|
"types": "./dist/types/index.d.ts",
|
|
33
|
-
"
|
|
34
|
+
"require": "./dist/cjs/index.js",
|
|
35
|
+
"import": "./dist/esm/index.mjs"
|
|
34
36
|
}
|
|
37
|
+
},
|
|
38
|
+
"unpkg": "./dist/browser/bundle.js",
|
|
39
|
+
"jsdelivr": "./dist/browser/bundle.js",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@logosdx/utils": "^6.1.0-beta.0"
|
|
35
42
|
}
|
|
36
43
|
}
|
package/readme.md
CHANGED
|
@@ -38,15 +38,11 @@
|
|
|
38
38
|
- `@logosdx/storage`: One API for your many key-value stores.
|
|
39
39
|
- `@logosdx/localize`: Localization utilities for everything from languages to customer-specific strings.
|
|
40
40
|
- `@logosdx/dom`: For those who like to raw-dawg the DOM.
|
|
41
|
+
- `@logosdx/react`: The above, but for React. Use it in Next.js, React Native, or anywhere else.
|
|
41
42
|
|
|
42
43
|
## Under-construction
|
|
43
44
|
|
|
44
45
|
- `@logosdx/state-machine`: State management as streams, not stores.
|
|
45
|
-
- `@logosdx/kit`: Bootstrap your app. Type-safe from day one. All the packages in one place.
|
|
46
|
-
|
|
47
|
-
## Roadmap
|
|
48
|
-
|
|
49
|
-
- `@logosdx/react`: All of the above, but for React. Use it in Next.js, React Native, or anywhere else.
|
|
50
46
|
|
|
51
47
|
## LLM Helpers
|
|
52
48
|
|