@hypen-space/core 0.2.11 → 0.3.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.
Files changed (48) hide show
  1. package/README.md +182 -11
  2. package/dist/src/app.js +470 -44
  3. package/dist/src/app.js.map +7 -5
  4. package/dist/src/components/builtin.js +470 -44
  5. package/dist/src/components/builtin.js.map +7 -5
  6. package/dist/src/discovery.js +559 -65
  7. package/dist/src/discovery.js.map +8 -6
  8. package/dist/src/engine.browser.js +2 -2
  9. package/dist/src/engine.browser.js.map +2 -2
  10. package/dist/src/engine.js +18 -9
  11. package/dist/src/engine.js.map +3 -3
  12. package/dist/src/index.browser.js +863 -82
  13. package/dist/src/index.browser.js.map +11 -7
  14. package/dist/src/index.js +1591 -125
  15. package/dist/src/index.js.map +17 -10
  16. package/dist/src/remote/client.js +525 -35
  17. package/dist/src/remote/client.js.map +7 -4
  18. package/dist/src/remote/index.js +1796 -35
  19. package/dist/src/remote/index.js.map +13 -4
  20. package/dist/src/router.js +55 -29
  21. package/dist/src/router.js.map +3 -3
  22. package/dist/src/state.js +57 -29
  23. package/dist/src/state.js.map +3 -3
  24. package/package.json +8 -2
  25. package/src/app.ts +292 -13
  26. package/src/discovery.ts +123 -18
  27. package/src/disposable.ts +281 -0
  28. package/src/engine.browser.ts +1 -1
  29. package/src/engine.ts +29 -10
  30. package/src/hypen.ts +209 -0
  31. package/src/index.ts +147 -11
  32. package/src/logger.ts +338 -0
  33. package/src/remote/client.ts +263 -56
  34. package/src/remote/index.ts +25 -1
  35. package/src/remote/server.ts +652 -0
  36. package/src/remote/session.ts +256 -0
  37. package/src/remote/types.ts +68 -1
  38. package/src/result.ts +260 -0
  39. package/src/retry.ts +306 -0
  40. package/src/state.ts +103 -45
  41. package/wasm-browser/README.md +4 -0
  42. package/wasm-browser/hypen_engine_bg.wasm +0 -0
  43. package/wasm-browser/package.json +1 -1
  44. package/wasm-node/README.md +4 -0
  45. package/wasm-node/hypen_engine_bg.wasm +0 -0
  46. package/wasm-node/package.json +1 -1
  47. package/wasm-browser/hypen_engine_bg.js +0 -736
  48. package/wasm-node/hypen_engine_bg.js +0 -736
package/README.md CHANGED
@@ -124,34 +124,34 @@ interface UserState {
124
124
  const userModule = app
125
125
  .defineState<UserState>({ user: null, loading: false })
126
126
 
127
- // Called when module is created
128
- .onCreated(async ({ state, next }) => {
127
+ // Lifecycle handler: receives (state, context?)
128
+ .onCreated(async (state, context) => {
129
129
  state.loading = true;
130
- next(); // Sync state changes to engine
130
+ // State changes are auto-synced via Proxy
131
131
  })
132
132
 
133
- // Handle actions dispatched from UI
134
- .onAction("loadUser", async ({ state, action, next }) => {
133
+ // Action handler: receives context object { action, state, next, context }
134
+ .onAction("loadUser", async ({ state, action, next, context }) => {
135
135
  const userId = action.payload?.id;
136
136
  state.user = await fetchUser(userId);
137
137
  state.loading = false;
138
- next();
138
+ // State changes are auto-synced via Proxy
139
+ // next.router is available for programmatic navigation
139
140
  })
140
141
 
141
- .onAction("logout", ({ state, next }) => {
142
+ .onAction("logout", ({ state }) => {
142
143
  state.user = null;
143
- next();
144
144
  })
145
145
 
146
- // Called when module is destroyed
147
- .onDestroyed(({ state }) => {
146
+ // Lifecycle handler: receives (state, context?)
147
+ .onDestroyed((state, context) => {
148
148
  console.log("Cleanup");
149
149
  })
150
150
 
151
151
  .build();
152
152
  ```
153
153
 
154
- The `next()` callback synchronizes state changes with the engine after async operations.
154
+ State mutations are automatically tracked via Proxy and synced to the engine.
155
155
 
156
156
  ## State
157
157
 
@@ -346,6 +346,171 @@ const engine = new BrowserEngine();
346
346
  await engine.init({ wasmPath: "/hypen_engine_bg.wasm" });
347
347
  ```
348
348
 
349
+ ## Single-File Components
350
+
351
+ Use template literals with the `hypen`, `state`, `item`, and `index` helpers:
352
+
353
+ ```typescript
354
+ import { app, hypen, state, item, index } from "@hypen-space/core";
355
+
356
+ export default app
357
+ .defineState({ items: ["A", "B", "C"] })
358
+ .ui(hypen`
359
+ Column {
360
+ ForEach(items: ${state.items}) {
361
+ Text("${index}: ${item}")
362
+ }
363
+ }
364
+ `);
365
+ ```
366
+
367
+ ## Error Handling
368
+
369
+ ### Result Type
370
+
371
+ Type-safe error handling without exceptions:
372
+
373
+ ```typescript
374
+ import { Ok, Err, fromPromise, match, all, isOk, isErr } from "@hypen-space/core";
375
+
376
+ // Create results
377
+ const success = Ok(42);
378
+ const failure = Err(new Error("failed"));
379
+
380
+ // Pattern matching
381
+ const message = match(result, {
382
+ ok: (value) => `Got ${value}`,
383
+ err: (error) => `Failed: ${error.message}`,
384
+ });
385
+
386
+ // Convert promises to Result
387
+ const result = await fromPromise(fetch("/api/data"));
388
+
389
+ // Combine multiple results
390
+ const combined = all([result1, result2, result3]);
391
+ ```
392
+
393
+ ### Module Error Handler
394
+
395
+ Handle errors in module actions:
396
+
397
+ ```typescript
398
+ app
399
+ .defineState({ error: null })
400
+ .onError(({ error, action, state }) => {
401
+ console.error(`Action ${action.name} failed:`, error);
402
+ state.error = error.message;
403
+ return { handled: true }; // Prevent error from propagating
404
+ })
405
+ .onAction("riskyAction", async ({ state }) => {
406
+ throw new Error("Something went wrong");
407
+ });
408
+ ```
409
+
410
+ ## Session Lifecycle
411
+
412
+ Handle connection state for remote UI:
413
+
414
+ ```typescript
415
+ app
416
+ .defineState({ connected: true })
417
+ .onDisconnect(({ state, reason }) => {
418
+ state.connected = false;
419
+ console.log("Disconnected:", reason);
420
+ })
421
+ .onReconnect(({ state, wasExpired }) => {
422
+ state.connected = true;
423
+ if (wasExpired) {
424
+ // Session was restored from server
425
+ }
426
+ })
427
+ .onExpire(({ state, reason }) => {
428
+ // Session expired, need to re-authenticate
429
+ state.connected = false;
430
+ });
431
+ ```
432
+
433
+ ## Disposable Pattern
434
+
435
+ Resource management with automatic cleanup:
436
+
437
+ ```typescript
438
+ import { DisposableStack, using, disposableListener } from "@hypen-space/core";
439
+
440
+ // Automatic cleanup with using()
441
+ await using(new DisposableStack(), async (stack) => {
442
+ const listener = stack.use(
443
+ disposableListener(window, "resize", handleResize)
444
+ );
445
+ // listener is automatically removed when scope exits
446
+ });
447
+
448
+ // Manual stack management
449
+ const stack = new DisposableStack();
450
+ stack.use(disposableTimeout(() => {}, 1000));
451
+ stack.use(disposableInterval(() => {}, 100));
452
+ stack.dispose(); // Cleans up everything
453
+ ```
454
+
455
+ ## Retry Utilities
456
+
457
+ Retry failed operations with backoff:
458
+
459
+ ```typescript
460
+ import { retry, retryResult, RetryPresets } from "@hypen-space/core";
461
+
462
+ // Simple retry with exponential backoff
463
+ const data = await retry(
464
+ () => fetch("/api/data"),
465
+ { maxAttempts: 3, backoff: "exponential" }
466
+ );
467
+
468
+ // Retry returning Result type
469
+ const result = await retryResult(
470
+ () => fetchData(),
471
+ RetryPresets.network // Pre-configured for network errors
472
+ );
473
+ ```
474
+
475
+ ## Logger
476
+
477
+ Structured logging with levels:
478
+
479
+ ```typescript
480
+ import { createLogger, setLogLevel, Logger } from "@hypen-space/core";
481
+
482
+ const log = createLogger("MyModule");
483
+
484
+ log.debug("Detailed info");
485
+ log.info("Normal operation");
486
+ log.warn("Something unexpected");
487
+ log.error("Something failed", error);
488
+
489
+ // Configure globally
490
+ setLogLevel("warn"); // Only warn and error
491
+ ```
492
+
493
+ ## Typed Events
494
+
495
+ Type-safe event emitter:
496
+
497
+ ```typescript
498
+ import { TypedEventEmitter, createEventEmitter } from "@hypen-space/core";
499
+
500
+ interface MyEvents {
501
+ userLogin: { userId: string };
502
+ dataLoaded: { items: string[] };
503
+ }
504
+
505
+ const events = createEventEmitter<MyEvents>();
506
+
507
+ events.on("userLogin", ({ userId }) => {
508
+ console.log("User logged in:", userId);
509
+ });
510
+
511
+ events.emit("userLogin", { userId: "123" });
512
+ ```
513
+
349
514
  ## Package Exports
350
515
 
351
516
  | Export | Description |
@@ -362,6 +527,12 @@ await engine.init({ wasmPath: "/hypen_engine_bg.wasm" });
362
527
  | `@hypen-space/core/loader` | Component loader |
363
528
  | `@hypen-space/core/discovery` | Component discovery |
364
529
  | `@hypen-space/core/components` | Built-in Router, Route, Link |
530
+ | `@hypen-space/core/result` | Result type for error handling |
531
+ | `@hypen-space/core/disposable` | Disposable pattern utilities |
532
+ | `@hypen-space/core/retry` | Retry with backoff |
533
+ | `@hypen-space/core/logger` | Structured logging |
534
+ | `@hypen-space/core/events` | Typed event emitter |
535
+ | `@hypen-space/core/hypen` | Template helpers (hypen, state, item, index) |
365
536
 
366
537
  ## Requirements
367
538