@async/framework 0.11.19 → 0.11.23

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 CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.23 - 2026-06-21
4
+
5
+ - Added first-class JSX type profiles for runtime/no-build and
6
+ buildtime/build-required authoring, including profile-local automatic
7
+ `jsx-runtime` and `jsx-dev-runtime` package subpaths.
8
+ - Added TypeScript fixtures proving runtime JSX accepts protocol attributes,
9
+ strict buildtime JSX rejects protocol props, and both profiles avoid global
10
+ ambient JSX pollution.
11
+ - Added component registry mounting through `async:component` plus
12
+ `this.slot(...)` outlets for child component replacement from signal-derived
13
+ props.
14
+ - Added example README coverage and clarified benchmark smoke checks without
15
+ publishing an incomplete Vite optimizer setup as a public example.
16
+ - Bundle size from bundled TypeScript source: `browser.ts` raw 228,180 B (228.2 KB / 0.228 MB), gzip 43,390 B (43.4 KB / 0.043 MB), br 35,878 B (35.9 KB / 0.036 MB) -> `browser.min.js` raw 97,570 B (97.6 KB / 0.098 MB), gzip 29,015 B (29.0 KB / 0.029 MB), br 25,549 B (25.5 KB / 0.026 MB); delta raw -130,610 B (-130.6 KB / -0.131 MB), gzip -14,375 B (-14.4 KB / -0.014 MB), br -10,329 B (-10.3 KB / -0.010 MB).
17
+
18
+ ## 0.11.22 - 2026-06-19
19
+
20
+ - Updated framework release automation to consume `@async/pipeline@0.9.25`,
21
+ whose generated release workflow runs package-owned release evidence before
22
+ release plan/inspect/changelog/notes steps so `dist/` exists before package
23
+ inspection.
24
+ - Kept release-description sync checks on the released pipeline path after the
25
+ existing `v0.11.20` and `v0.11.21` GitHub Release description repairs.
26
+ - Bundle size from bundled TypeScript source: `browser.ts` raw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) -> `browser.min.js` raw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
27
+
28
+ ## 0.11.21 - 2026-06-19
29
+
30
+ - Updated framework release automation to consume `@async/pipeline@0.9.24`,
31
+ whose generated release helper steps use `pnpm dlx` for the pinned
32
+ `@async/release` package on Node 24/npm 11 runners.
33
+ - Kept release-description sync scripts and generated workflow entries on the
34
+ released pipeline path.
35
+ - Bundle size from bundled TypeScript source: `browser.ts` raw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) -> `browser.min.js` raw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
36
+
37
+ ## 0.11.20 - 2026-06-19
38
+
39
+ - Updated framework release automation to consume `@async/pipeline@0.9.22`
40
+ with the released `release sync-descriptions` command.
41
+ - Added framework package scripts for release-description sync checks and
42
+ generated matching `pipeline:release:sync-descriptions` entries.
43
+ - Synced existing semver GitHub Release descriptions from `CHANGELOG.md` so the
44
+ changelog remains the source of truth.
45
+ - Bundle size from bundled TypeScript source: `browser.ts` raw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) -> `browser.min.js` raw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
46
+
3
47
  ## 0.11.19 - 2026-06-19
4
48
 
5
49
  - Added the first build-required profile subpaths,
package/README.md CHANGED
@@ -318,6 +318,7 @@ import {
318
318
  createLazyRegistry,
319
319
  component,
320
320
  computed,
321
+ component,
321
322
  createSignal,
322
323
  createHandlerRegistry,
323
324
  createPartialRegistry,
@@ -332,7 +333,6 @@ import {
332
333
  defineAttributeConfig,
333
334
  defineApp,
334
335
  defineCache,
335
- defineComponent,
336
336
  defineRegistrySnapshot,
337
337
  defineRoute,
338
338
  delay,
@@ -404,13 +404,13 @@ You can also create isolated app hubs and runtimes:
404
404
  ```js
405
405
  const app = defineApp();
406
406
  app.use("signal", { count: createSignal(0) });
407
-
408
- const runtime = createApp(app, { root: document }).start();
409
- runtime.use("handler", {
407
+ app.use("handler", {
410
408
  increment() {
411
409
  this.signals.update("count", (count) => count + 1);
412
410
  }
413
411
  });
412
+
413
+ const runtime = createApp(app, { root: document }).start();
414
414
  ```
415
415
 
416
416
  Naming rules:
@@ -472,6 +472,28 @@ runtime.registry.snapshot().entries.server;
472
472
  // {}
473
473
  ```
474
474
 
475
+ The singleton runtime is intentionally internal. Use app-level methods for
476
+ global lifecycle work, and use `inspectRuntime()` for diagnostics:
477
+
478
+ ```js
479
+ Async.attachRoot(document.body);
480
+ Async.applySnapshot(snapshot);
481
+
482
+ Async.inspectRuntime();
483
+ // {
484
+ // active: true,
485
+ // started: true,
486
+ // destroyed: false,
487
+ // target: "browser",
488
+ // roots: { count: 1, roots: [...] },
489
+ // loader: { ready: true, pending: 0, root: document.body },
490
+ // router: false
491
+ // }
492
+ ```
493
+
494
+ `Async.runtime` is not public API. If you need direct instance ownership, keep
495
+ the handle returned from `Async.start(...)` or `createApp(...).start()`.
496
+
475
497
  ### Signals
476
498
 
477
499
  ```js
@@ -1049,6 +1071,34 @@ If an `async:snapshot` script is present under the root or document,
1049
1071
  const snapshot = readSnapshot(document);
1050
1072
  ```
1051
1073
 
1074
+ ## Loader Bootstrap Queue
1075
+
1076
+ `Async.loader` is a promise-returning facade for script-friendly loader work
1077
+ that may run before the app has attached a root. Calls to `scan`, `swap`, and
1078
+ `mount` queue until `Async.start({ root })` or `Async.attachRoot(root)` creates
1079
+ the concrete runtime loader:
1080
+
1081
+ ```js
1082
+ Async.use("handler", {
1083
+ selectProduct() {
1084
+ this.signals.set("selected", true);
1085
+ }
1086
+ });
1087
+
1088
+ const swapped = Async.loader.swap(
1089
+ "route",
1090
+ `<button type="button" on:click="selectProduct">Select</button>`
1091
+ );
1092
+
1093
+ Async.start({ root: document, router: false });
1094
+ await swapped;
1095
+ ```
1096
+
1097
+ `Async.loader.ready()` resolves with the concrete `runtime.loader`.
1098
+ `Async.loader.inspect()` reports whether a loader is ready and how many loader
1099
+ operations are still pending. The concrete `runtime.loader` remains
1100
+ synchronous for routers, boundary receivers, and server-result application.
1101
+
1052
1102
  ## Components
1053
1103
 
1054
1104
  Components are scoped fragment functions. They return strings or `html`
@@ -1056,7 +1106,7 @@ templates; Loader inserts and scans the result. There is no virtual node
1056
1106
  type and no rerender loop.
1057
1107
 
1058
1108
  ```js
1059
- const Toggle = defineComponent(function Toggle() {
1109
+ const Toggle = component(function Toggle() {
1060
1110
  const selected = this.signal(false);
1061
1111
  const attach = this.handler("attach", function ({ element }) {
1062
1112
  element.dataset.attached = "true";
@@ -1086,8 +1136,6 @@ const loader = Loader({ root: document });
1086
1136
  loader.mount(document.querySelector("#app"), Toggle);
1087
1137
  ```
1088
1138
 
1089
- `component(...)` remains a compatibility alias for `defineComponent(...)`.
1090
-
1091
1139
  Component helpers:
1092
1140
 
1093
1141
  | Helper | Behavior |
@@ -1100,6 +1148,7 @@ Component helpers:
1100
1148
  | `this.handler(name, fn)` | Scoped named handler registry entry |
1101
1149
  | `this.handler(fn)` | Generated scoped handler registry entry |
1102
1150
  | `this.render(Component, props)` | Child fragment rendering |
1151
+ | `this.slot(Component, propsOrFn)` | Child component outlet using an `on:attach` target |
1103
1152
  | `this.suspense(signalRef, views)` | Async boundary template helper |
1104
1153
  | `this.on(event, fn)` | Fragment lifecycle fallback for `attach`, `visible`, and `destroy` |
1105
1154
  | `this.onMount(fn)` | Compatibility alias for `this.on("attach", fn)` |
@@ -1113,7 +1162,7 @@ caller owns the boundary element, and the loader chooses the loading, ready, or
1113
1162
  error template from the async signal status.
1114
1163
 
1115
1164
  ```js
1116
- const Product = defineComponent(function Product() {
1165
+ const Product = component(function Product() {
1117
1166
  const product = this.asyncSignal("product", async function () {
1118
1167
  return this.server.products.get("sku-1");
1119
1168
  });
@@ -1202,7 +1251,7 @@ Use `this.on("intersect", ...)` when a component needs continuous visibility
1202
1251
  state:
1203
1252
 
1204
1253
  ```js
1205
- const Card = defineComponent(function Card() {
1254
+ const Card = component(function Card() {
1206
1255
  const visible = this.signal(false);
1207
1256
 
1208
1257
  this.on("intersect", { threshold: 0.5 }, ({ isIntersecting }) => {
@@ -1217,7 +1266,7 @@ Use `this.intersect(...)` with a direct element when a parent owns scroll-spy or
1217
1266
  active-section state:
1218
1267
 
1219
1268
  ```js
1220
- const Section = defineComponent(function Section({ id, observeSection }) {
1269
+ const Section = component(function Section({ id, observeSection }) {
1221
1270
  const attach = this.handler("attach", function ({ element }) {
1222
1271
  return observeSection(id, element);
1223
1272
  });
@@ -1225,7 +1274,7 @@ const Section = defineComponent(function Section({ id, observeSection }) {
1225
1274
  return html`<section on:attach="${attach}"><h2>${id}</h2></section>`;
1226
1275
  });
1227
1276
 
1228
- const Page = defineComponent(function Page() {
1277
+ const Page = component(function Page() {
1229
1278
  const active = this.signal("intro");
1230
1279
  const ratios = new Map();
1231
1280
  const options = {
@@ -1309,6 +1358,9 @@ rerendering.
1309
1358
 
1310
1359
  ## Examples
1311
1360
 
1361
+ See [`examples/README.md`](./examples/README.md) for start commands and a short
1362
+ description of every example.
1363
+
1312
1364
  | Example | Shows |
1313
1365
  | --- | --- |
1314
1366
  | [`examples/counter`](./examples/counter) | Signal text binding and delegated handlers |
@@ -1320,6 +1372,7 @@ rerendering.
1320
1372
  | [`examples/partials`](./examples/partials) | Server-rendered partial fragments |
1321
1373
  | [`examples/cache`](./examples/cache) | Browser/server cache declarations |
1322
1374
  | [`examples/ssr`](./examples/ssr) | Server render output and browser activation snapshot |
1375
+ | [`examples/size`](./examples/size) | Scenario-size fixtures for bundle and runtime slices |
1323
1376
 
1324
1377
  ## Pipeline
1325
1378
 
package/browser.d.ts CHANGED
@@ -512,6 +512,21 @@ export interface LoaderInstance {
512
512
 
513
513
  export type AsyncLoaderOptions = LoaderOptions;
514
514
  export type AsyncLoaderInstance = LoaderInstance;
515
+ export interface AsyncLoaderFacadeInspection {
516
+ ready: boolean;
517
+ pending: number;
518
+ root?: Document | Element | DocumentFragment;
519
+ }
520
+
521
+ export interface AsyncLoaderFacade {
522
+ readonly current?: LoaderInstance;
523
+ ready(): Promise<LoaderInstance>;
524
+ scan(rootOrFragment?: Document | Element | DocumentFragment): Promise<LoaderInstance>;
525
+ swap(boundaryId: string, fragmentOrTemplate: TemplateLike): Promise<Element>;
526
+ mount<TProps extends Record<string, unknown> = Record<string, unknown>>(target: Element, Component: ComponentFunction<TProps>, props?: TProps): Promise<unknown>;
527
+ inspect(): AsyncLoaderFacadeInspection;
528
+ }
529
+
515
530
 
516
531
  export type AttributePatchValue = string | number | boolean | null | undefined;
517
532
  export type BuiltAttributePatchTriples = readonly AttributePatchValue[];
@@ -652,9 +667,19 @@ export interface RootInspection {
652
667
  roots: Array<{ root: Document | Element | DocumentFragment; loader: LoaderInstance; primary: boolean }>;
653
668
  }
654
669
 
670
+ export interface RuntimeInspection {
671
+ active: boolean;
672
+ started: boolean;
673
+ destroyed: boolean;
674
+ target?: RuntimeTarget;
675
+ roots: RootInspection;
676
+ loader: AsyncLoaderFacadeInspection;
677
+ router: boolean;
678
+ }
679
+
655
680
  export interface AppHub {
656
681
  registry: RegistryStore;
657
- runtime?: AppRuntime;
682
+ loader: AsyncLoaderFacade;
658
683
  use(type: "signal", entries: SignalMap): this;
659
684
  use(type: "handler", entries: Record<string, HandlerFunction | LazyDescriptor>): this;
660
685
  use(type: "server", entries: Record<string, ServerFunction>): this;
@@ -669,6 +694,7 @@ export interface AppHub {
669
694
  detachRoot(root?: Document | Element | DocumentFragment): this;
670
695
  applySnapshot(snapshot: RegistryRuntimeSnapshot, options?: { strict?: boolean }): this;
671
696
  inspectRoots(): RootInspection;
697
+ inspectRuntime(): RuntimeInspection;
672
698
  }
673
699
 
674
700
  export interface CreateAppOptions extends LoaderOptions {
@@ -734,6 +760,7 @@ export interface AsyncNamespace extends AppHub {
734
760
  detachRoot: AppHub["detachRoot"];
735
761
  applySnapshot: AppHub["applySnapshot"];
736
762
  inspectRoots: AppHub["inspectRoots"];
763
+ inspectRuntime: AppHub["inspectRuntime"];
737
764
  attributeName: typeof attributeName;
738
765
  defineAttributeConfig: typeof defineAttributeConfig;
739
766
  AsyncStream: AsyncStreamNamespace;