ilha 0.12.0 → 0.12.1

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.
@@ -246,6 +246,9 @@ interface KeyedIsland<TInput> {
246
246
  }
247
247
  type AnyIsland = Island<any>;
248
248
  type ActionCall<P> = [P] extends [undefined] ? () => void : unknown extends P ? () => void : (payload: P) => void;
249
+ /** A bound action can back native events or component callback props.
250
+ * Runtime arguments are ignored when `.with()` binds a payload. */
251
+ type BoundActionHandler = (...runtimeArgs: unknown[]) => unknown;
249
252
  /**
250
253
  * Reactive operation with execution state. `pending`, `data`, and `error`
251
254
  * are reactive: reading them during render subscribes the island render.
@@ -255,10 +258,10 @@ type ActionAccessor<P = undefined, R = void> = ActionCall<P> & {
255
258
  readonly data: Awaited<R> | undefined;
256
259
  readonly error: Error | undefined;
257
260
  /** Bind an explicit serializable payload into an RPC-replayable action
258
- * reference for server-owned islands (`onclick={remove.withArgs(id)}`).
261
+ * reference for server-owned islands (`onclick={remove.with(id)}`).
259
262
  * Arguments are validated JSON-safe (≤ 8 KiB serialized) at bind time and
260
263
  * stored in the hydration manifest — never extracted by executing code. */
261
- withArgs: (...args: unknown[]) => NativeEventHandler;
264
+ with: (...args: unknown[]) => BoundActionHandler;
262
265
  };
263
266
  interface EffectContext {
264
267
  /**
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as action, B as isSafeUrl, C as PersistOptions, D as SignalSetter, E as SignalAccessor, F as each, G as mount, H as isUrlAttributeName, I as effect, J as persist, K as onError, L as html, M as context, N as css, O as SignalWriter, P as derived, Q as untrack, R as ilha, S as NativeEventModifier, T as RawHtml, U as json, V as isSafeUrlAttrValue, W as morph, X as serializeStyle, Y as raw, Z as state, _ as KeyedIsland, a as EachKeyedBuilder, b as NativeEventContext, c as EffectFn, d as ErrorContext, f as ErrorSource, g as IslandComponent, h as Island, i as EachBuilder, j as batch, k as StateAccessor, l as EffectOnceContext, m as HydratableOptions, n as DerivedAccessor, o as EachResult, p as ExternalSignal, q as onUncaughtError, r as DerivedValue, s as EffectContext, t as ActionAccessor, u as EffectOnceFn, v as MountOptions, w as PersistStorage, x as NativeEventHandler, y as MountResult, z as ilhaSignal } from "./index-DZI0fEmR.js";
1
+ import { A as action, B as isSafeUrl, C as PersistOptions, D as SignalSetter, E as SignalAccessor, F as each, G as mount, H as isUrlAttributeName, I as effect, J as persist, K as onError, L as html, M as context, N as css, O as SignalWriter, P as derived, Q as untrack, R as ilha, S as NativeEventModifier, T as RawHtml, U as json, V as isSafeUrlAttrValue, W as morph, X as serializeStyle, Y as raw, Z as state, _ as KeyedIsland, a as EachKeyedBuilder, b as NativeEventContext, c as EffectFn, d as ErrorContext, f as ErrorSource, g as IslandComponent, h as Island, i as EachBuilder, j as batch, k as StateAccessor, l as EffectOnceContext, m as HydratableOptions, n as DerivedAccessor, o as EachResult, p as ExternalSignal, q as onUncaughtError, r as DerivedValue, s as EffectContext, t as ActionAccessor, u as EffectOnceFn, v as MountOptions, w as PersistStorage, x as NativeEventHandler, y as MountResult, z as ilhaSignal } from "./index-BETRqz-0.js";
2
2
  export { ActionAccessor, DerivedAccessor, DerivedValue, EachBuilder, EachKeyedBuilder, EachResult, EffectContext, EffectFn, EffectOnceContext, EffectOnceFn, ErrorContext, ErrorSource, ExternalSignal, HydratableOptions, Island, IslandComponent, KeyedIsland, MountOptions, MountResult, NativeEventContext, NativeEventHandler, NativeEventModifier, PersistOptions, PersistStorage, RawHtml, SignalAccessor, SignalSetter, SignalWriter, StateAccessor, action, batch, context, css, derived, each, effect, html, ilha, ilhaSignal, isSafeUrl, isSafeUrlAttrValue, isUrlAttributeName, json, morph, mount, onError, onUncaughtError, persist, raw, serializeStyle, state, untrack };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, serializeServerManifest, setJsxRuntimeBridge } from "./internal.js";
1
+ import { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, serializeServerManifest, setJsxRuntimeBridge, setServerActionBinder } from "./internal.js";
2
2
  import { effect as effect$1, endBatch, setActiveSub, signal, startBatch } from "alien-signals";
3
3
 
4
4
  //#region src/index.ts
@@ -592,7 +592,7 @@ function each(items) {
592
592
  const SSR_ACTION_STUB = Symbol.for("ilha.ssrActionStub");
593
593
  const ACTION_MANIFEST_ID = Symbol.for("ilha.actionManifestId");
594
594
  const ACTION_BOUND_ARGS = Symbol.for("ilha.actionBoundArgs");
595
- /** Serialized size ceiling for `.withArgs()` payloads (JSON chars). */
595
+ /** Serialized size ceiling for `.with()` payloads (JSON chars). */
596
596
  const MAX_BOUND_ARGS_CHARS = 8192;
597
597
  /** Manifest id for a brand-recognized action reference, else undefined.
598
598
  * Anything that isn't a branded action stub is rejected outright — event
@@ -601,13 +601,13 @@ function actionManifestId(fn) {
601
601
  if (typeof fn !== "function" || !(SSR_ACTION_STUB in fn)) return void 0;
602
602
  return fn[ACTION_MANIFEST_ID];
603
603
  }
604
- /** Bound args recorded by `.withArgs()` on an action reference, else undefined. */
604
+ /** Bound args recorded by `.with()` on an action reference, else undefined. */
605
605
  function actionBoundArgs(fn) {
606
606
  if (typeof fn !== "function" || !(ACTION_BOUND_ARGS in fn)) return void 0;
607
607
  const args = fn[ACTION_BOUND_ARGS];
608
608
  return Array.isArray(args) ? args : void 0;
609
609
  }
610
- /** Attach `.withArgs(...args)` to an action accessor. Returns an explicit,
610
+ /** Attach `.with(...args)` to an action accessor. Returns an explicit,
611
611
  * serializable action REFERENCE — never a closure to inspect or probe.
612
612
  * Arguments are validated JSON-safe at bind time; the hydration manifest
613
613
  * stores `{ actionId, args }` directly and the client RPC path sends them
@@ -631,19 +631,19 @@ function assertJsonSafe(value, seen = /* @__PURE__ */ new WeakSet()) {
631
631
  case "boolean": return;
632
632
  case "number":
633
633
  if (Number.isFinite(value)) return;
634
- throw new TypeError("withArgs() rejects non-finite numbers.");
634
+ throw new TypeError("with() rejects non-finite numbers.");
635
635
  case "object": break;
636
- default: throw new TypeError(`withArgs() rejects ${typeof value} values.`);
636
+ default: throw new TypeError(`with() rejects ${typeof value} values.`);
637
637
  }
638
- if (seen.has(value)) throw new TypeError("withArgs() rejects circular values.");
638
+ if (seen.has(value)) throw new TypeError("with() rejects circular values.");
639
639
  seen.add(value);
640
640
  if (Array.isArray(value)) {
641
641
  for (const item of value) assertJsonSafe(item, seen);
642
642
  return;
643
643
  }
644
- if (Object.getPrototypeOf(value) !== Object.prototype) throw new TypeError("withArgs() accepts plain objects only.");
644
+ if (Object.getPrototypeOf(value) !== Object.prototype) throw new TypeError("with() accepts plain objects only.");
645
645
  for (const [key, child] of Object.entries(value)) {
646
- if (UNSAFE_KEYS.has(key)) throw new TypeError(`withArgs() rejects unsafe key "${key}".`);
646
+ if (UNSAFE_KEYS.has(key)) throw new TypeError(`with() rejects unsafe key "${key}".`);
647
647
  assertJsonSafe(child, seen);
648
648
  }
649
649
  }
@@ -651,13 +651,13 @@ function assertJsonSafe(value, seen = /* @__PURE__ */ new WeakSet()) {
651
651
  function cloneJsonSafe(value) {
652
652
  return structuredClone(value);
653
653
  }
654
- function attachWithArgs(accessor) {
655
- Object.defineProperty(accessor, "withArgs", {
654
+ function attachWith(accessor) {
655
+ Object.defineProperty(accessor, "with", {
656
656
  enumerable: false,
657
657
  value: (...args) => {
658
658
  for (const arg of args) assertJsonSafe(arg);
659
659
  const serialized = cloneJsonSafe(args);
660
- if (JSON.stringify(serialized).length > MAX_BOUND_ARGS_CHARS) throw new RangeError(`withArgs() payload exceeds ${MAX_BOUND_ARGS_CHARS} JSON characters.`);
660
+ if (JSON.stringify(serialized).length > MAX_BOUND_ARGS_CHARS) throw new RangeError(`with() payload exceeds ${MAX_BOUND_ARGS_CHARS} JSON characters.`);
661
661
  const manifestId = actionManifestId(accessor);
662
662
  const bound = (...runtimeArgs) => {
663
663
  return accessor(serialized.length > 0 ? serialized.length === 1 ? serialized[0] : serialized : runtimeArgs.length === 1 ? runtimeArgs[0] : runtimeArgs);
@@ -670,6 +670,13 @@ function attachWithArgs(accessor) {
670
670
  }
671
671
  });
672
672
  }
673
+ setServerActionBinder(function bindExternalAction(fn, manifestId) {
674
+ const action = fn;
675
+ action[SSR_ACTION_STUB] = true;
676
+ action[ACTION_MANIFEST_ID] = manifestId;
677
+ attachWith(action);
678
+ return action;
679
+ });
673
680
  const RENDER_CTX_STACK = Symbol.for("ilha.renderCtxStack");
674
681
  function renderCtxStack() {
675
682
  const g = globalThis;
@@ -1871,7 +1878,7 @@ function action(fn) {
1871
1878
  data: { get: () => void 0 },
1872
1879
  error: { get: () => void 0 }
1873
1880
  });
1874
- attachWithArgs(noop);
1881
+ attachWith(noop);
1875
1882
  return noop;
1876
1883
  }
1877
1884
  const manifestId = `a${f.actionIndex++}`;
@@ -1900,7 +1907,7 @@ function action(fn) {
1900
1907
  fn
1901
1908
  };
1902
1909
  const ssrAccessor = invoke;
1903
- attachWithArgs(ssrAccessor);
1910
+ attachWith(ssrAccessor);
1904
1911
  return ssrAccessor;
1905
1912
  }
1906
1913
  const instance = f.instance;
@@ -1997,7 +2004,7 @@ function action(fn) {
1997
2004
  instance.actionIds.set(slot.acc, manifestId);
1998
2005
  const clientAccessor = invoke;
1999
2006
  clientAccessor[ACTION_MANIFEST_ID] = manifestId;
2000
- attachWithArgs(clientAccessor);
2007
+ attachWith(clientAccessor);
2001
2008
  return clientAccessor;
2002
2009
  }
2003
2010
  /**
@@ -2824,7 +2831,7 @@ const ilha = ((...args) => {
2824
2831
  if (snapshot !== false) {
2825
2832
  const doState = snapshot === true || snapshot.state !== false;
2826
2833
  const doDerived = snapshot === true || snapshot.derived !== false;
2827
- const doSkipOnMount = explicitSkipOnMount ?? (doState || doDerived);
2834
+ const doSkipOnMount = explicitSkipOnMount ?? false;
2828
2835
  const snapshotData = { v: 2 };
2829
2836
  const input = resolveInput(resolvedProps);
2830
2837
  const probeFrame = freshFrame({ ssr: true });
@@ -1,5 +1,13 @@
1
- import { S as NativeEventModifier, T as RawHtml, x as NativeEventHandler } from "./index-DZI0fEmR.js";
1
+ import { S as NativeEventModifier, T as RawHtml, x as NativeEventHandler } from "./index-BETRqz-0.js";
2
2
  //#region src/internal.d.ts
3
+ type ServerAction<A extends unknown[] = unknown[], R = unknown> = ((...args: A) => R) & {
4
+ with: (...args: unknown[]) => (...runtimeArgs: unknown[]) => unknown;
5
+ };
6
+ type ServerActionBinder = <A extends unknown[], R>(fn: (...args: A) => R, manifestId?: string) => ServerAction<A, R>;
7
+ /** @internal Register core's action branding implementation. */
8
+ declare function setServerActionBinder(binder: ServerActionBinder): void;
9
+ /** @internal Brand an external server action for hydration-manifest replay. */
10
+ declare function bindServerAction<A extends unknown[], R>(fn: (...args: A) => R, manifestId?: string): ServerAction<A, R>;
3
11
  /** Registry of live island mount handles keyed by host element. */
4
12
  declare const ISLAND_MOUNT_HANDLES: WeakMap<Element, {
5
13
  unmount: () => void | Promise<void>;
@@ -58,4 +66,4 @@ declare function setServerManifestSerializer(serializer: ServerManifestSerialize
58
66
  /** @internal Used by island rendering to serialize nested child manifests. */
59
67
  declare function serializeServerManifest(manifest: Map<string, ManifestEntry>): string;
60
68
  //#endregion
61
- export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, JsxEventRegistration, JsxRuntimeBridge, ManifestEntry, ServerManifestSerializer, __ilhaJsxEvent, __ilhaJsxSlot, serializeServerManifest, setJsxRuntimeBridge, setServerManifestSerializer };
69
+ export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, JsxEventRegistration, JsxRuntimeBridge, ManifestEntry, ServerAction, ServerManifestSerializer, __ilhaJsxEvent, __ilhaJsxSlot, bindServerAction, serializeServerManifest, setJsxRuntimeBridge, setServerActionBinder, setServerManifestSerializer };
package/dist/internal.js CHANGED
@@ -1,4 +1,14 @@
1
1
  //#region src/internal.ts
2
+ let serverActionBinder;
3
+ /** @internal Register core's action branding implementation. */
4
+ function setServerActionBinder(binder) {
5
+ serverActionBinder = binder;
6
+ }
7
+ /** @internal Brand an external server action for hydration-manifest replay. */
8
+ function bindServerAction(fn, manifestId) {
9
+ if (!serverActionBinder) throw new Error("ilha: server action binder is unavailable");
10
+ return serverActionBinder(fn, manifestId);
11
+ }
2
12
  /** Registry of live island mount handles keyed by host element. */
3
13
  const ISLAND_MOUNT_HANDLES = /* @__PURE__ */ new WeakMap();
4
14
  /** Hook a parent's mountSlots uses to mount a child island and keep a handle
@@ -36,4 +46,4 @@ function serializeServerManifest(manifest) {
36
46
  }
37
47
 
38
48
  //#endregion
39
- export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, __ilhaJsxEvent, __ilhaJsxSlot, serializeServerManifest, setJsxRuntimeBridge, setServerManifestSerializer };
49
+ export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, __ilhaJsxEvent, __ilhaJsxSlot, bindServerAction, serializeServerManifest, setJsxRuntimeBridge, setServerActionBinder, setServerManifestSerializer };
@@ -1,2 +1,2 @@
1
- import { a as JSX, r as jsxDEV, t as Fragment } from "./jsx-runtime-BCGuHwTg.js";
1
+ import { a as JSX, r as jsxDEV, t as Fragment } from "./jsx-runtime-qnxoD2YJ.js";
2
2
  export { Fragment, type JSX, jsxDEV };
@@ -1,4 +1,4 @@
1
- import { E as SignalAccessor, O as SignalWriter, S as NativeEventModifier, T as RawHtml, x as NativeEventHandler } from "./index-DZI0fEmR.js";
1
+ import { E as SignalAccessor, O as SignalWriter, S as NativeEventModifier, T as RawHtml, x as NativeEventHandler } from "./index-BETRqz-0.js";
2
2
  //#region src/jsx-types.d.ts
3
3
  declare namespace JSX {
4
4
  export type Child = unknown;
@@ -1,2 +1,2 @@
1
- import { a as JSX, i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-BCGuHwTg.js";
1
+ import { a as JSX, i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-qnxoD2YJ.js";
2
2
  export { Fragment, type JSX, jsx, jsxDEV, jsxs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilha",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "A tiny, framework-free island architecture library",
5
5
  "keywords": [
6
6
  "framework-free",