@computekit/core 0.1.3 → 0.2.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/src/index.ts CHANGED
@@ -11,6 +11,14 @@ import type {
11
11
  ComputeKitEvents,
12
12
  } from './types';
13
13
 
14
+ import type {
15
+ ComputeFunctionRegistry,
16
+ RegisteredFunctionName,
17
+ FunctionInput,
18
+ FunctionOutput,
19
+ ComputeFn,
20
+ } from './registry';
21
+
14
22
  import { WorkerPool } from './pool';
15
23
  import { EventEmitter, isWasmSupported, createLogger } from './utils';
16
24
 
@@ -60,48 +68,79 @@ export class ComputeKit extends EventEmitter<ComputeKitEvents> {
60
68
  /**
61
69
  * Register a compute function
62
70
  *
63
- * @param name - Unique name for the function
71
+ * @param name - Unique name for the function (autocompletes if registry is extended)
64
72
  * @param fn - The function to execute (will run in a Web Worker)
65
73
  *
66
74
  * @example
67
75
  * ```ts
76
+ * // Basic usage
68
77
  * kit.register('sum', (arr: number[]) => arr.reduce((a, b) => a + b, 0));
78
+ *
79
+ * // With typed registry (extend ComputeFunctionRegistry for autocomplete)
80
+ * // declare module '@computekit/core' {
81
+ * // interface ComputeFunctionRegistry {
82
+ * // sum: { input: number[]; output: number };
83
+ * // }
84
+ * // }
85
+ * // kit.register('sum', (arr) => arr.reduce((a, b) => a + b, 0));
69
86
  * ```
70
87
  */
71
- register<TInput, TOutput>(
72
- name: string,
73
- fn: (input: TInput) => TOutput | Promise<TOutput>
88
+ register<
89
+ TName extends RegisteredFunctionName,
90
+ TInput = FunctionInput<TName extends string ? TName : never>,
91
+ TOutput = FunctionOutput<TName extends string ? TName : never>,
92
+ >(
93
+ name: TName,
94
+ fn: TName extends keyof ComputeFunctionRegistry
95
+ ? ComputeFn<
96
+ ComputeFunctionRegistry[TName]['input'],
97
+ ComputeFunctionRegistry[TName]['output']
98
+ >
99
+ : ComputeFn<TInput, TOutput>
74
100
  ): this {
75
- this.pool.register(name, fn);
101
+ this.pool.register(name as string, fn as ComputeFn<unknown, unknown>);
76
102
  return this;
77
103
  }
78
104
 
79
105
  /**
80
106
  * Execute a registered compute function
81
107
  *
82
- * @param name - Name of the registered function
83
- * @param input - Input data for the function
108
+ * @param name - Name of the registered function (autocompletes if registry is extended)
109
+ * @param input - Input data for the function (type-safe if registry is extended)
84
110
  * @param options - Execution options
85
- * @returns Promise resolving to the function result
111
+ * @returns Promise resolving to the function result (type-safe if registry is extended)
86
112
  *
87
113
  * @example
88
114
  * ```ts
89
115
  * const sum = await kit.run('sum', [1, 2, 3, 4, 5]);
116
+ *
117
+ * // With typed registry, input/output types are inferred:
118
+ * // const result = await kit.run('fibonacci', 50); // result: number
90
119
  * ```
91
120
  */
92
- async run<TInput, TOutput>(
93
- name: string,
94
- input: TInput,
121
+ async run<
122
+ TName extends RegisteredFunctionName,
123
+ TInput = FunctionInput<TName extends string ? TName : never>,
124
+ TOutput = FunctionOutput<TName extends string ? TName : never>,
125
+ >(
126
+ name: TName,
127
+ input: TName extends keyof ComputeFunctionRegistry
128
+ ? ComputeFunctionRegistry[TName]['input']
129
+ : TInput,
95
130
  options?: ComputeOptions
96
- ): Promise<TOutput> {
97
- return this.pool.execute<TInput, TOutput>(name, input, options);
131
+ ): Promise<
132
+ TName extends keyof ComputeFunctionRegistry
133
+ ? ComputeFunctionRegistry[TName]['output']
134
+ : TOutput
135
+ > {
136
+ return this.pool.execute(name as string, input, options);
98
137
  }
99
138
 
100
139
  /**
101
140
  * Execute a registered compute function with full result metadata
102
141
  *
103
- * @param name - Name of the registered function
104
- * @param input - Input data for the function
142
+ * @param name - Name of the registered function (autocompletes if registry is extended)
143
+ * @param input - Input data for the function (type-safe if registry is extended)
105
144
  * @param options - Execution options
106
145
  * @returns Promise resolving to ComputeResult with metadata
107
146
  *
@@ -111,13 +150,33 @@ export class ComputeKit extends EventEmitter<ComputeKitEvents> {
111
150
  * console.log(`Took ${result.duration}ms`);
112
151
  * ```
113
152
  */
114
- async runWithMetadata<TInput, TOutput>(
115
- name: string,
116
- input: TInput,
153
+ async runWithMetadata<
154
+ TName extends RegisteredFunctionName,
155
+ TInput = FunctionInput<TName extends string ? TName : never>,
156
+ TOutput = FunctionOutput<TName extends string ? TName : never>,
157
+ >(
158
+ name: TName,
159
+ input: TName extends keyof ComputeFunctionRegistry
160
+ ? ComputeFunctionRegistry[TName]['input']
161
+ : TInput,
117
162
  options?: ComputeOptions
118
- ): Promise<ComputeResult<TOutput>> {
163
+ ): Promise<
164
+ ComputeResult<
165
+ TName extends keyof ComputeFunctionRegistry
166
+ ? ComputeFunctionRegistry[TName]['output']
167
+ : TOutput
168
+ >
169
+ > {
170
+ type ActualOutput = TName extends keyof ComputeFunctionRegistry
171
+ ? ComputeFunctionRegistry[TName]['output']
172
+ : TOutput;
173
+
119
174
  const startTime = performance.now();
120
- const data = await this.pool.execute<TInput, TOutput>(name, input, options);
175
+ const data = (await this.pool.execute(
176
+ name as string,
177
+ input,
178
+ options
179
+ )) as ActualOutput;
121
180
  const duration = performance.now() - startTime;
122
181
 
123
182
  return {
@@ -175,23 +234,64 @@ export function getDefaultInstance(): ComputeKit {
175
234
 
176
235
  /**
177
236
  * Register a function on the default instance
237
+ *
238
+ * @example
239
+ * ```ts
240
+ * import { register } from '@computekit/core';
241
+ *
242
+ * register('fibonacci', (n: number) => {
243
+ * if (n <= 1) return n;
244
+ * let a = 0, b = 1;
245
+ * for (let i = 2; i <= n; i++) {
246
+ * [a, b] = [b, a + b];
247
+ * }
248
+ * return b;
249
+ * });
250
+ * ```
178
251
  */
179
- export function register<TInput, TOutput>(
180
- name: string,
181
- fn: (input: TInput) => TOutput | Promise<TOutput>
252
+ export function register<
253
+ TName extends RegisteredFunctionName,
254
+ TInput = FunctionInput<TName extends string ? TName : never>,
255
+ TOutput = FunctionOutput<TName extends string ? TName : never>,
256
+ >(
257
+ name: TName,
258
+ fn: TName extends keyof ComputeFunctionRegistry
259
+ ? ComputeFn<
260
+ ComputeFunctionRegistry[TName]['input'],
261
+ ComputeFunctionRegistry[TName]['output']
262
+ >
263
+ : ComputeFn<TInput, TOutput>
182
264
  ): void {
183
265
  getDefaultInstance().register(name, fn);
184
266
  }
185
267
 
186
268
  /**
187
269
  * Run a function on the default instance
270
+ *
271
+ * @example
272
+ * ```ts
273
+ * import { run } from '@computekit/core';
274
+ *
275
+ * const result = await run('fibonacci', 50);
276
+ * console.log(result); // Type is inferred if registry is extended
277
+ * ```
188
278
  */
189
- export async function run<TInput, TOutput>(
190
- name: string,
191
- input: TInput,
279
+ export async function run<
280
+ TName extends RegisteredFunctionName,
281
+ TInput = FunctionInput<TName extends string ? TName : never>,
282
+ TOutput = FunctionOutput<TName extends string ? TName : never>,
283
+ >(
284
+ name: TName,
285
+ input: TName extends keyof ComputeFunctionRegistry
286
+ ? ComputeFunctionRegistry[TName]['input']
287
+ : TInput,
192
288
  options?: ComputeOptions
193
- ): Promise<TOutput> {
194
- return getDefaultInstance().run<TInput, TOutput>(name, input, options);
289
+ ): Promise<
290
+ TName extends keyof ComputeFunctionRegistry
291
+ ? ComputeFunctionRegistry[TName]['output']
292
+ : TOutput
293
+ > {
294
+ return getDefaultInstance().run(name, input, options);
195
295
  }
196
296
 
197
297
  // Re-export types
@@ -221,6 +321,18 @@ export type {
221
321
  ParallelBatchResult,
222
322
  } from './types';
223
323
 
324
+ // Re-export typed registry types
325
+ export type {
326
+ ComputeFunctionRegistry,
327
+ RegisteredFunctionName,
328
+ FunctionInput,
329
+ FunctionOutput,
330
+ ComputeFn,
331
+ InferComputeFn,
332
+ DefineFunction,
333
+ HasRegisteredFunctions,
334
+ } from './registry';
335
+
224
336
  // Re-export utilities
225
337
  export {
226
338
  isWasmSupported,
@@ -0,0 +1,132 @@
1
+ /**
2
+ * ComputeKit Typed Registry
3
+ *
4
+ * This module provides type-safe function registration and execution.
5
+ * Users can extend the ComputeFunctionRegistry interface to get autocomplete
6
+ * and type safety for their registered functions.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // Extend the registry interface (in a .d.ts file or at the top of your file)
11
+ * declare module '@computekit/core' {
12
+ * interface ComputeFunctionRegistry {
13
+ * fibonacci: { input: number; output: number };
14
+ * sum: { input: number[]; output: number };
15
+ * processData: { input: { items: string[] }; output: { count: number } };
16
+ * }
17
+ * }
18
+ *
19
+ * // Now you get autocomplete and type safety!
20
+ * const kit = new ComputeKit();
21
+ * kit.register('fibonacci', (n) => ...); // n is inferred as number
22
+ * const result = await kit.run('fibonacci', 42); // result is number
23
+ * ```
24
+ */
25
+
26
+ /**
27
+ * Registry interface for compute functions.
28
+ * Extend this interface using module augmentation to add your own functions.
29
+ *
30
+ * Each entry should be in the format:
31
+ * ```ts
32
+ * functionName: { input: InputType; output: OutputType }
33
+ * ```
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * declare module '@computekit/core' {
38
+ * interface ComputeFunctionRegistry {
39
+ * myFunction: { input: string; output: number };
40
+ * }
41
+ * }
42
+ * ```
43
+ */
44
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
45
+ export interface ComputeFunctionRegistry {}
46
+
47
+ /**
48
+ * Helper type to get all registered function names.
49
+ * If no functions are registered, falls back to string.
50
+ */
51
+ export type RegisteredFunctionName = keyof ComputeFunctionRegistry extends never
52
+ ? string
53
+ : keyof ComputeFunctionRegistry;
54
+
55
+ /**
56
+ * Helper type to check if the registry has any entries.
57
+ */
58
+ export type HasRegisteredFunctions = keyof ComputeFunctionRegistry extends never
59
+ ? false
60
+ : true;
61
+
62
+ /**
63
+ * Get the input type for a registered function.
64
+ * Falls back to TFallback if the function is not registered.
65
+ */
66
+ export type FunctionInput<
67
+ TName extends string,
68
+ TFallback = unknown,
69
+ > = TName extends keyof ComputeFunctionRegistry
70
+ ? ComputeFunctionRegistry[TName]['input']
71
+ : TFallback;
72
+
73
+ /**
74
+ * Get the output type for a registered function.
75
+ * Falls back to TFallback if the function is not registered.
76
+ */
77
+ export type FunctionOutput<
78
+ TName extends string,
79
+ TFallback = unknown,
80
+ > = TName extends keyof ComputeFunctionRegistry
81
+ ? ComputeFunctionRegistry[TName]['output']
82
+ : TFallback;
83
+
84
+ /**
85
+ * Type for a compute function based on registry or explicit types.
86
+ */
87
+ export type ComputeFn<TInput, TOutput> = (input: TInput) => TOutput | Promise<TOutput>;
88
+
89
+ /**
90
+ * Infer the compute function type for a registered function name.
91
+ */
92
+ export type InferComputeFn<TName extends string> =
93
+ TName extends keyof ComputeFunctionRegistry
94
+ ? ComputeFn<
95
+ ComputeFunctionRegistry[TName]['input'],
96
+ ComputeFunctionRegistry[TName]['output']
97
+ >
98
+ : ComputeFn<unknown, unknown>;
99
+
100
+ /**
101
+ * Type helper for creating registry entries.
102
+ * Use this to define your function types more easily.
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * declare module '@computekit/core' {
107
+ * interface ComputeFunctionRegistry {
108
+ * fibonacci: DefineFunction<number, number>;
109
+ * sum: DefineFunction<number[], number>;
110
+ * }
111
+ * }
112
+ * ```
113
+ */
114
+ export type DefineFunction<TInput, TOutput> = {
115
+ input: TInput;
116
+ output: TOutput;
117
+ };
118
+
119
+ /**
120
+ * Helper type for typing the register method.
121
+ * Provides proper type inference based on whether the function is in the registry.
122
+ */
123
+ export type RegisterFn<
124
+ TName extends string,
125
+ TInput,
126
+ TOutput,
127
+ > = TName extends keyof ComputeFunctionRegistry
128
+ ? ComputeFn<
129
+ ComputeFunctionRegistry[TName]['input'],
130
+ ComputeFunctionRegistry[TName]['output']
131
+ >
132
+ : ComputeFn<TInput, TOutput>;