@abide/abide 0.118.0 → 0.119.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 (149) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/bin/abide.ts +74 -11
  3. package/docs/REGISTRY.md +2 -1
  4. package/docs/RULEBOOK.md +22 -0
  5. package/docs/abide.md +338 -118
  6. package/package.json +1 -1
  7. package/scaffold/src/getGreeting.test.ts +1 -0
  8. package/scaffold/src/index.abide +4 -1
  9. package/scaffold/src/index.test.ts +2 -0
  10. package/scaffold/src/layout.abide +6 -6
  11. package/src/compiler/Lowering.ts +20 -2
  12. package/src/compiler/PositionTable.ts +1 -0
  13. package/src/compiler/Refusals.ts +1 -0
  14. package/src/compiler/TypeSession.ts +11 -8
  15. package/src/compiler/aliasedSymbol.ts +1 -1
  16. package/src/compiler/ambientReadsIn.ts +1 -0
  17. package/src/compiler/appLayout.ts +4 -2
  18. package/src/compiler/argsDefaultsIn.ts +1 -0
  19. package/src/compiler/argsSchemaOf.ts +1 -0
  20. package/src/compiler/checkApp.ts +3 -1
  21. package/src/compiler/checkedShadow.ts +2 -1
  22. package/src/compiler/classifyRead.ts +1 -0
  23. package/src/compiler/classifyTemplate.ts +1 -0
  24. package/src/compiler/compileApp.ts +4 -2
  25. package/src/compiler/compiledEntry.ts +1 -0
  26. package/src/compiler/componentGraph.ts +1 -0
  27. package/src/compiler/declaredExports.ts +4 -2
  28. package/src/compiler/emitClient.ts +19 -14
  29. package/src/compiler/emitComponent.ts +1 -0
  30. package/src/compiler/emitSource.ts +2 -1
  31. package/src/compiler/formatAbide.ts +857 -0
  32. package/src/compiler/formatDiagnosis.ts +1 -0
  33. package/src/compiler/handlersUnder.ts +2 -1
  34. package/src/compiler/hookCalls.ts +1 -0
  35. package/src/compiler/lineOf.ts +17 -0
  36. package/src/compiler/matchersOf.ts +13 -3
  37. package/src/compiler/mountsOf.ts +2 -0
  38. package/src/compiler/paramFile.ts +1 -0
  39. package/src/compiler/parseAbide.ts +48 -28
  40. package/src/compiler/projectShadow.ts +10 -3
  41. package/src/compiler/reactiveOptions.ts +1 -0
  42. package/src/compiler/reactiveTypes.ts +2 -1
  43. package/src/compiler/readsIn.ts +3 -2
  44. package/src/compiler/renderMarkup.ts +3 -2
  45. package/src/compiler/resolverIn.ts +2 -0
  46. package/src/compiler/sameTemplate.ts +150 -0
  47. package/src/compiler/scaffold.ts +4 -11
  48. package/src/compiler/serveLanguage.ts +46 -19
  49. package/src/compiler/sharedModuleWrites.ts +2 -1
  50. package/src/compiler/sourceMapOf.ts +1 -0
  51. package/src/compiler/splitImports.ts +2 -0
  52. package/src/compiler/templateWarnings.ts +2 -2
  53. package/src/compiler/trackingWarnings.ts +1 -0
  54. package/src/compiler/writeDefaultProject.ts +5 -1
  55. package/src/server/BRIDGE_VERSION.ts +1 -1
  56. package/src/server/abideModules.ts +2 -0
  57. package/src/server/answerFailure.ts +1 -0
  58. package/src/server/answerRequest.ts +15 -14
  59. package/src/server/answerRpc.ts +3 -2
  60. package/src/server/answerSocket.ts +2 -1
  61. package/src/server/answerValue.ts +1 -0
  62. package/src/server/answerWorker.ts +1 -0
  63. package/src/server/appTree.ts +3 -1
  64. package/src/server/argsFor.ts +1 -0
  65. package/src/server/assistant.ts +2 -1
  66. package/src/server/banner.ts +2 -0
  67. package/src/server/bridgeRelay.ts +1 -0
  68. package/src/server/callerOf.ts +1 -0
  69. package/src/server/claudeApi.ts +1 -0
  70. package/src/server/claudeCode.ts +1 -0
  71. package/src/server/clientBundle.ts +1 -0
  72. package/src/server/coerceArgs.ts +1 -2
  73. package/src/server/commands.ts +9 -0
  74. package/src/server/compressAnswer.ts +2 -1
  75. package/src/server/config.ts +2 -0
  76. package/src/server/createApp.ts +4 -2
  77. package/src/server/crossingOrigin.ts +1 -0
  78. package/src/server/csp.ts +1 -0
  79. package/src/server/deferredBuilds.ts +1 -0
  80. package/src/server/derivedArgs.ts +1 -0
  81. package/src/server/devWorker.ts +2 -1
  82. package/src/server/faceOf.ts +2 -7
  83. package/src/server/generatedSurfaces.ts +5 -1
  84. package/src/server/hooks.ts +1 -0
  85. package/src/server/iconAccent.ts +1 -1
  86. package/src/server/installServer.ts +1 -0
  87. package/src/server/installSourceMaps.ts +1 -0
  88. package/src/server/launcherPage.ts +2 -2
  89. package/src/server/manifestOf.ts +1 -0
  90. package/src/server/muxUpgrade.ts +1 -0
  91. package/src/server/nativeMenu.ts +2 -0
  92. package/src/server/principal.ts +2 -1
  93. package/src/server/remote.ts +1 -0
  94. package/src/server/render.ts +3 -3
  95. package/src/server/renderComponent.ts +1 -0
  96. package/src/server/reportHealth.ts +1 -0
  97. package/src/server/requestScope.ts +3 -1
  98. package/src/server/runDesktop.ts +3 -2
  99. package/src/server/seedBuffer.ts +1 -0
  100. package/src/server/serveDev.ts +3 -2
  101. package/src/server/shell.ts +2 -0
  102. package/src/server/streamEvent.ts +1 -0
  103. package/src/server/surfaceOf.ts +1 -0
  104. package/src/server/testBuild.ts +1 -0
  105. package/src/server/testMount.ts +1 -0
  106. package/src/server/trace.ts +2 -0
  107. package/src/server/withAbideSources.ts +1 -0
  108. package/src/shared/Attributes.ts +12 -8
  109. package/src/shared/cookies.ts +1 -1
  110. package/src/shared/escapeText.ts +1 -1
  111. package/src/shared/index.ts +1 -5
  112. package/src/shared/jsonSchema.ts +1 -3
  113. package/src/shared/menuBridge.ts +1 -2
  114. package/src/shared/outbox.ts +1 -1
  115. package/src/shared/reactive/Keyed.ts +2 -2
  116. package/src/shared/reactive/Reactive.ts +12 -16
  117. package/src/shared/reactive/index.ts +3 -4
  118. package/src/shared/reactive/isReactive.ts +1 -1
  119. package/src/shared/reactive/scoped.ts +2 -2
  120. package/src/shared/reactive/share.ts +1 -1
  121. package/src/shared/reactive/watch.ts +4 -4
  122. package/src/shared/refuse.ts +1 -1
  123. package/src/shared/rpc.ts +8 -11
  124. package/src/shared/url.ts +1 -1
  125. package/src/shared/validateJson.ts +1 -1
  126. package/src/ui/ArmRegion.ts +1 -0
  127. package/src/ui/Level.ts +1 -0
  128. package/src/ui/List.ts +1 -0
  129. package/src/ui/RawRun.ts +1 -0
  130. package/src/ui/Router.ts +1 -0
  131. package/src/ui/TryRegion.ts +1 -0
  132. package/src/ui/adoptWalk.ts +2 -1
  133. package/src/ui/bindElement.ts +1 -0
  134. package/src/ui/bindFiles.ts +1 -0
  135. package/src/ui/bindGroup.ts +1 -0
  136. package/src/ui/bindProperty.ts +1 -0
  137. package/src/ui/bindSpread.ts +1 -0
  138. package/src/ui/index.ts +1 -6
  139. package/src/ui/outboxQueue.ts +1 -1
  140. package/src/ui/parseMarkup.ts +2 -1
  141. package/src/ui/reconcile.ts +2 -1
  142. package/src/ui/reconcileHead.ts +1 -0
  143. package/src/ui/regions.ts +2 -1
  144. package/src/ui/registerWorker.ts +1 -0
  145. package/src/ui/rows.ts +1 -0
  146. package/src/ui/setMarkup.ts +1 -0
  147. package/src/ui/setText.ts +1 -0
  148. package/src/ui/socketWire.ts +4 -3
  149. package/src/ui/wire.ts +2 -1
@@ -20,6 +20,7 @@ import { mounted } from '#shared/mount.ts'
20
20
  import { type Reactive, reactive } from '#shared/reactive/index.ts'
21
21
  import { parseRoutePattern, type Segment } from '#shared/routePattern.ts'
22
22
  import { argsInURL, rpcRequest } from '#shared/rpcRequest.ts'
23
+
23
24
  import { answered } from './answerFailure.ts'
24
25
  import { bodyWithin, type Mounted } from './answerRpc.ts'
25
26
  import type { ToolAnswer, ToolDefinition } from './assistant.ts'
@@ -146,7 +147,10 @@ function openApiOf(handlers: Map<string, Mounted>): {
146
147
  schema:
147
148
  segment.kind === 'rest'
148
149
  ? declared
149
- : patterned(declared, patternOf(segment, each.matchers)),
150
+ : patterned(
151
+ declared,
152
+ patternOf(segment, each.matchers),
153
+ ),
150
154
  }
151
155
  if (segment.kind === 'optional')
152
156
  parameter.description = 'May be left out, with its segment.'
@@ -21,6 +21,7 @@ import {
21
21
  type Segment,
22
22
  } from '#shared/routePattern.ts'
23
23
  import type { Schema } from '#shared/Schema.ts'
24
+
24
25
  import { config } from './config.ts'
25
26
  import type { LauncherOptions } from './launcherOptions.ts'
26
27
  import { currentRequestScope } from './requestScope.ts'
@@ -82,7 +82,7 @@ function decoded(
82
82
  let channels = 0
83
83
  const compressed: Uint8Array[] = []
84
84
  let length = 0
85
- for (let at = 8; at + 8 <= png.length; ) {
85
+ for (let at = 8; at + 8 <= png.length;) {
86
86
  const size = view.getUint32(at)
87
87
  const type = String.fromCharCode(...png.subarray(at + 4, at + 8))
88
88
  const body = png.subarray(at + 8, at + 8 + size)
@@ -14,6 +14,7 @@ import { MOUNT } from '#shared/mount.ts'
14
14
  import { PRINCIPAL } from '#shared/principal.ts'
15
15
  import { RPC_SERVER } from '#shared/RPC_SERVER.ts'
16
16
  import { UNEXPECTED } from '#shared/UNEXPECTED.ts'
17
+
17
18
  import { reachedInRender } from './answerRequest.ts'
18
19
  import { environmentTimeout } from './answerRpc.ts'
19
20
  import { broadcast, feedFromServed, swept } from './answerSocket.ts'
@@ -7,6 +7,7 @@
7
7
  // rebuild, and a test boots several apps in one process.
8
8
 
9
9
  import { resolve } from 'node:path' // bun exposes no path helpers of its own
10
+
10
11
  import { HANDLER_FACE } from './MODULE_QUERIES.ts'
11
12
  import { decodeMappings, placeAt, type Segment } from './sourceMappings.ts'
12
13
 
@@ -7,6 +7,7 @@
7
7
  // asks something first, so a Start with no configuration to ask for has none and starts at once.
8
8
 
9
9
  import { escapeAttribute, escapeText } from '#shared/escapeText.ts'
10
+
10
11
  import type { ConfigField } from './configFields.ts'
11
12
  import { inkOn } from './iconAccent.ts'
12
13
 
@@ -77,8 +78,7 @@ export function launcherPage(page: Launch): string {
77
78
  // field shows them.
78
79
  const failureLine = (
79
80
  failure:
80
- | { message: string; issues: Record<string, string[]> }
81
- | undefined,
81
+ { message: string; issues: Record<string, string[]> } | undefined,
82
82
  ): string => {
83
83
  if (failure === undefined) return ''
84
84
  let line = `<p class="failure" role="alert">${escapeText(failure.message)}</p>`
@@ -16,6 +16,7 @@
16
16
  // a preload of the same address is a second request line for bytes already on their way.
17
17
 
18
18
  import { resolve } from 'node:path' // bun exposes no path helpers of its own
19
+
19
20
  import { CLIENT_ENTRY } from './CLIENT_BUILD.ts'
20
21
  import { VIRTUAL_DIRECTORY } from './VIRTUAL_DIRECTORY.ts'
21
22
 
@@ -10,6 +10,7 @@
10
10
 
11
11
  import { SOCKET_ADDRESS } from '#shared/ADDRESSES.ts'
12
12
  import { unmounted } from '#shared/mount.ts'
13
+
13
14
  import { positiveSetting } from './config.ts'
14
15
  import { plainAnswer } from './plainAnswer.ts'
15
16
 
@@ -2,7 +2,9 @@
2
2
  // with `onMenu`, built as an `NSMenu`.
3
3
 
4
4
  import { FFIType } from 'bun:ffi'
5
+
5
6
  import type { MenuRole } from '#shared/menuItem.ts'
7
+
6
8
  import {
7
9
  definedClass,
8
10
  type Id,
@@ -9,14 +9,15 @@ import { cookies } from '#shared/cookies.ts'
9
9
  import { isFailed } from '#shared/Failed.ts'
10
10
  import { isRecord } from '#shared/isRecord.ts'
11
11
  import { namedLogger } from '#shared/log.ts'
12
- import { PRINCIPAL_HEADER } from '#shared/PRINCIPAL_HEADER.ts'
13
12
  import {
14
13
  type PRINCIPAL,
15
14
  type Principal,
16
15
  principalMembers,
17
16
  } from '#shared/principal.ts'
17
+ import { PRINCIPAL_HEADER } from '#shared/PRINCIPAL_HEADER.ts'
18
18
  import { refuse } from '#shared/refuse.ts'
19
19
  import { declare } from '#shared/rpc.ts'
20
+
20
21
  import { mountedOwn } from './answerRpc.ts'
21
22
  import { signedInAt } from './bridgeRelay.ts'
22
23
  import { callerOf, callerOrMint, mintCaller } from './callerOf.ts'
@@ -11,6 +11,7 @@ import type { PatchOp } from '#shared/reactive/PATCH_SINKS.ts'
11
11
  import { rankRoutes } from '#shared/routePattern.ts'
12
12
  import type { Method } from '#shared/rpc.ts'
13
13
  import { argsInURL, rpcRequest } from '#shared/rpcRequest.ts'
14
+
14
15
  import type { Mount } from './answerRpc.ts'
15
16
  import { DEFAULT_PORT } from './DEFAULT_PORT.ts'
16
17
  import { withoutTrailingSlash } from './withoutTrailingSlash.ts'
@@ -9,6 +9,7 @@ import { headKeyOf } from '#shared/headKeyOf.ts'
9
9
  import { isThenable } from '#shared/reactive/isThenable.ts'
10
10
  import type { ShareScope } from '#shared/reactive/share.ts'
11
11
  import { setUpLevels } from '#shared/setUpLevels.ts'
12
+
12
13
  import { buildDeferred, markPainted } from './deferredBuilds.ts'
13
14
  import { currentRequestScope, type PageCall } from './requestScope.ts'
14
15
 
@@ -23,7 +24,7 @@ import { currentRequestScope, type PageCall } from './requestScope.ts'
23
24
  * satisfy the linter would put the code and the registry row out of step, which is the drift
24
25
  * the documents exist to stop.
25
26
  */
26
- // biome-ignore lint/suspicious/noEmptyInterface: REGISTRY declares `interface Component {}`.
27
+ // REGISTRY declares `interface Component {}`.
27
28
  export interface Component {}
28
29
 
29
30
  /**
@@ -364,8 +365,7 @@ export async function renderDocument(
364
365
  */
365
366
  function earlyCallScript(calls: PageCall[]): string {
366
367
  const rows: (
367
- | [string, string, RequestInit]
368
- | [string, string, RequestInit, 1]
368
+ [string, string, RequestInit] | [string, string, RequestInit, 1]
369
369
  )[] = []
370
370
  for (const { request, painted } of calls)
371
371
  rows.push(
@@ -1,4 +1,5 @@
1
1
  import { regionMarkup } from '#shared/anchorMarkup.ts'
2
+
2
3
  import { callsMadeSoFar, deferBuild, refuseDocument } from './deferredBuilds.ts'
3
4
  import type { Component, Rendered } from './render.ts'
4
5
 
@@ -7,6 +7,7 @@
7
7
  import type { Health } from '#shared/health.ts'
8
8
  import { isRecord } from '#shared/isRecord.ts'
9
9
  import { namedLogger } from '#shared/log.ts'
10
+
10
11
  import abidePackage from '../../package.json' with { type: 'json' }
11
12
  import { appIdentity, config } from './config.ts'
12
13
  import { HOOKS, inOrder } from './hooks.ts'
@@ -10,12 +10,14 @@
10
10
  // values forwarders rather than process-wide.
11
11
 
12
12
  import { AsyncLocalStorage } from 'node:async_hooks' // bun implements AsyncLocalStorage and has no context-carrying api of its own
13
+
13
14
  import { Cookies } from '#shared/cookies.ts'
14
15
  import type { Framed } from '#shared/framing.ts'
15
16
  import type { Params } from '#shared/matchRoute.ts'
16
17
  import type { Principal } from '#shared/principal.ts'
17
- import { SCOPING, type Scope } from '#shared/reactive/scoping.ts'
18
+ import { type Scope, SCOPING } from '#shared/reactive/scoping.ts'
18
19
  import type { RpcRequest } from '#shared/rpcRequest.ts'
20
+
19
21
  import type { McpSurface } from './generatedSurfaces.ts'
20
22
  import { IDLE_TIMEOUT_SECONDS } from './IDLE_TIMEOUT_SECONDS.ts'
21
23
 
@@ -8,7 +8,9 @@
8
8
 
9
9
  import { FFIType } from 'bun:ffi'
10
10
  import { mkdir } from 'node:fs/promises' // bun exposes no directory creation of its own
11
+
11
12
  import { isFailed } from '#shared/Failed.ts'
13
+
12
14
  import {
13
15
  callBlock,
14
16
  created,
@@ -54,8 +56,7 @@ type Failure = {
54
56
  export type Desktop = {
55
57
  /** 38.82 — `src/launcher.abide`'s page, where the app has one that paints. */
56
58
  launch:
57
- | (() => Promise<{ default: (props: Launch) => Component }>)
58
- | undefined
59
+ (() => Promise<{ default: (props: Launch) => Component }>) | undefined
59
60
  /** The document the launch page renders into, its stylesheet already in its head (38.84). */
60
61
  document: string
61
62
  /** 38.101 — the app's icon as a data URL, and the accent taken from it. */
@@ -30,6 +30,7 @@ import {
30
30
  STREAMING,
31
31
  streamingOrSettled,
32
32
  } from '#shared/reactive/index.ts'
33
+
33
34
  import { positiveSetting } from './config.ts'
34
35
  import {
35
36
  currentRequestScope,
@@ -20,6 +20,7 @@
20
20
 
21
21
  import { watch } from 'node:fs' // bun exposes no file watcher of its own
22
22
  import { dirname, resolve } from 'node:path' // bun exposes no path helpers of its own
23
+
23
24
  import {
24
25
  type AppChecker,
25
26
  compilationOf,
@@ -28,6 +29,7 @@ import {
28
29
  } from '#compiler/compileApp.ts'
29
30
  import { formatDiagnosis } from '#compiler/formatDiagnosis.ts'
30
31
  import { DEV_ADDRESS } from '#shared/ADDRESSES.ts'
32
+
31
33
  import type { Compilation } from './abideModules.ts'
32
34
  import { DEFAULT_PORT } from './DEFAULT_PORT.ts'
33
35
  import type { FromWorker, ToWorker } from './devWorker.ts'
@@ -66,8 +68,7 @@ const LAST_DEV_PORT = 3099
66
68
  // An app-mux socket's data: the id the worker knows its connection by, and what `Mux.connect` reads
67
69
  // off the upgrade. `undefined` on the reload client's.
68
70
  type Carried =
69
- | { connection: number; url: string; headers: [string, string][] }
70
- | undefined
71
+ { connection: number; url: string; headers: [string, string][] } | undefined
71
72
 
72
73
  /**
73
74
  * `abide dev`'s listener, compiling the app here and serving it from a child process.
@@ -4,9 +4,11 @@
4
4
  // is the only part that needs a terminal. A call goes over http through `remote.ts`, as any client's.
5
5
 
6
6
  import { createInterface } from 'node:readline' // bun exposes no line editor of its own
7
+
7
8
  import { isRecord } from '#shared/isRecord.ts'
8
9
  import { useColor } from '#shared/log.ts'
9
10
  import { paint as painted } from '#shared/paint.ts'
11
+
10
12
  import type { Mount } from './answerRpc.ts'
11
13
  import { LogPanel } from './LogPanel.ts'
12
14
  import { callHandler, watch } from './remote.ts'
@@ -5,6 +5,7 @@
5
5
  import type { Problem } from '#shared/Failed.ts'
6
6
  import type { Framed } from '#shared/framing.ts'
7
7
  import { REFUSAL_KEY } from '#shared/REFUSAL_KEY.ts'
8
+
8
9
  import { HEARTBEAT_MILLISECONDS } from './HEARTBEAT_MILLISECONDS.ts'
9
10
 
10
11
  /** AN EVENT STREAM OPENS ON A COMMENT, so a proxy has bytes to pass before the first event. */
@@ -1,4 +1,5 @@
1
1
  import type { Method } from '#shared/rpc.ts'
2
+
2
3
  import type { Mount, Mounted } from './answerRpc.ts'
3
4
 
4
5
  /** A generated surface a handler may be listed on, besides the browser's (20.4 is the build's). */
@@ -6,6 +6,7 @@
6
6
 
7
7
  import { mkdir, rename, rm, utimes, writeFile } from 'node:fs/promises' // bun exposes no directory creation, rename, removal, mtime write or exclusive create of its own
8
8
  import { dirname } from 'node:path' // bun exposes no path helpers of its own
9
+
9
10
  import { namesUnder } from './namesUnder.ts'
10
11
  import { runBuild } from './runBuild.ts'
11
12
 
@@ -3,6 +3,7 @@
3
3
  // same two halves a page load runs, in one process, so a test can click it and read the work.
4
4
 
5
5
  import { flushSync } from '#shared/reactive/Reactive.ts'
6
+
6
7
  import { MOUNTABLE } from './MOUNTABLE.ts'
7
8
  import { type Component, render } from './render.ts'
8
9
 
@@ -7,7 +7,9 @@
7
7
  // (24.5) while a sibling running concurrently names its own.
8
8
 
9
9
  import { AsyncLocalStorage } from 'node:async_hooks' // bun implements AsyncLocalStorage and has no context-carrying api of its own
10
+
10
11
  import { writeSpan } from '#shared/log.ts'
12
+
11
13
  import { randomToken } from './randomToken.ts'
12
14
  import {
13
15
  currentRequestScope,
@@ -1,4 +1,5 @@
1
1
  import { relative, resolve } from 'node:path' // bun exposes no path helpers of its own
2
+
2
3
  import type { Compilation } from './abideModules.ts'
3
4
  import { COMPONENT_NAMESPACE } from './faceOf.ts'
4
5
  import { COMPONENT_QUERY } from './MODULE_QUERIES.ts'
@@ -47,11 +47,13 @@ type Reflected<Element> = {
47
47
 
48
48
  /** `Element`'s keys without its index signatures. */
49
49
  type Named<Element> = keyof {
50
- [Key in keyof Element as string extends Key
51
- ? never
52
- : number extends Key
53
- ? never
54
- : Key]: Element[Key]
50
+ [
51
+ Key in keyof Element as string extends Key
52
+ ? never
53
+ : number extends Key
54
+ ? never
55
+ : Key
56
+ ]: Element[Key]
55
57
  }
56
58
 
57
59
  /** The properties whose attribute is not their name lowercased. */
@@ -119,9 +121,11 @@ export type Attributes<
119
121
 
120
122
  /** An HTML element's attributes, derived from what its DOM type reflects. */
121
123
  type HtmlAttributes<Tag extends keyof HTMLElementTagNameMap> = {
122
- [Key in Reflected<HTMLElementTagNameMap[Tag]> as Key extends `on${string}`
123
- ? never
124
- : AttributeName<Key>]?: Written<
124
+ [
125
+ Key in Reflected<
126
+ HTMLElementTagNameMap[Tag]
127
+ > as Key extends `on${string}` ? never : AttributeName<Key>
128
+ ]?: Written<
125
129
  AttributeName<Key>,
126
130
  NonNullable<HTMLElementTagNameMap[Tag][Key]>
127
131
  > | null
@@ -238,7 +238,7 @@ export function browserCookies(): Cookies {
238
238
  const jar = new Cookies(
239
239
  document.cookie,
240
240
  (serialized) => {
241
- // biome-ignore lint/suspicious/noDocumentCookie: the Cookie Store API is asynchronous and missing from some browsers, and a read of the jar is synchronous.
241
+ // The Cookie Store API is asynchronous and missing from some browsers, and a read of the jar is synchronous.
242
242
  document.cookie = serialized
243
243
  },
244
244
  true,
@@ -4,7 +4,7 @@
4
4
  // `escapeless` in #ui is that path, and the two sitting apart is what keeps them from being
5
5
  // confused for one another.
6
6
 
7
- import { RAW_WRITES, Raw, textOf } from './Raw.ts'
7
+ import { Raw, RAW_WRITES, textOf } from './Raw.ts'
8
8
 
9
9
  // The common slot holds nothing to escape, so the scan is the fast path and the rewrite is
10
10
  // the fallback: a clean string is returned as it arrived, with no allocation.
@@ -23,11 +23,7 @@ export {
23
23
  } from './boundValue.ts'
24
24
  export { type Cookies, cookies } from './cookies.ts'
25
25
  export { csp } from './csp.ts'
26
- export {
27
- escapeAttribute,
28
- escapeStyleValue,
29
- escapeText,
30
- } from './escapeText.ts'
26
+ export { escapeAttribute, escapeStyleValue, escapeText } from './escapeText.ts'
31
27
  export { type Failed, isFailed } from './Failed.ts'
32
28
  // 25 — the account of the app.
33
29
  export { type Health, health } from './health.ts'
@@ -31,9 +31,7 @@ export function jsonSchema<T = Untyped>(
31
31
  vendor: 'abide',
32
32
  validate(value: unknown) {
33
33
  const found = validateJson(document, value) as
34
- | Record<string, string[]>
35
- | string[]
36
- | null
34
+ Record<string, string[]> | string[] | null
37
35
  if (found === null) return { value: value as T }
38
36
  const issues: { message: string; path: string[] }[] = []
39
37
  // A value that is not an object came back as the bare list, every issue on `''`.
@@ -5,8 +5,7 @@
5
5
  * page inside a desktop app loads. 38.88.
6
6
  */
7
7
  export function menuBridge():
8
- | { postMessage(message: string): void }
9
- | undefined {
8
+ { postMessage(message: string): void } | undefined {
10
9
  return (
11
10
  globalThis as {
12
11
  webkit?: {
@@ -9,9 +9,9 @@
9
9
 
10
10
  import type { Failed } from './Failed.ts'
11
11
  import type { JsonValue } from './JsonValue.ts'
12
+ import { OUTBOX_SENDING } from './OUTBOX_SENDING.ts'
12
13
  import { ambient, type Reactive, type Selection } from './reactive/index.ts'
13
14
  import { matchesPattern } from './reactive/matchesPattern.ts'
14
- import { OUTBOX_SENDING } from './OUTBOX_SENDING.ts'
15
15
  import type { Method } from './rpc.ts'
16
16
 
17
17
  /** One call `outbox` holds: what it sends, when it was queued, how often it was sent, and its value. */
@@ -15,8 +15,8 @@ import {
15
15
  normalized,
16
16
  PARAMETER_DEFAULTS,
17
17
  } from './argsContract.ts'
18
- import { CELL } from './CELL.ts'
19
18
  import { canonicalKey } from './canonicalKey.ts'
19
+ import { CELL } from './CELL.ts'
20
20
  import { ENTRY_LIVES } from './ENTRY_LIVES.ts'
21
21
  import { armTimer } from './Expiry.ts'
22
22
  import { KEYED_BRAND } from './KEYED_BRAND.ts'
@@ -43,8 +43,8 @@ import {
43
43
  newSubscriber,
44
44
  newTracked,
45
45
  type Subscriber,
46
- TRACKING,
47
46
  type Tracked,
47
+ TRACKING,
48
48
  trackProbe,
49
49
  } from './tracking.ts'
50
50
  import { owned, owning } from './watch.ts'
@@ -31,23 +31,23 @@ import { NotLanded } from './NotLanded.ts'
31
31
  import { PATCH_SINKS, type PatchOp } from './PATCH_SINKS.ts'
32
32
  import { REACTIVE_BRAND } from './REACTIVE_BRAND.ts'
33
33
  import { recordWrites } from './recordWrites.ts'
34
- import { STREAMING } from './STREAMING.ts'
35
34
  import { currentScope, runInScope, type Scope } from './scoping.ts'
35
+ import { STREAMING } from './STREAMING.ts'
36
36
  import {
37
37
  CHECK,
38
38
  CLEAN,
39
- DIRTY,
40
39
  detach,
40
+ DIRTY,
41
41
  dropProbeReader,
42
42
  newSubscriber,
43
43
  newTracked,
44
44
  RELEASING,
45
45
  revive,
46
46
  type Subscriber,
47
- TRACKING,
48
- type Tracked,
49
47
  tombstone,
50
48
  track,
49
+ type Tracked,
50
+ TRACKING,
51
51
  trackProbe,
52
52
  truncate,
53
53
  truncateProbes,
@@ -252,12 +252,12 @@ export type Reactive<
252
252
  | Accepted
253
253
  | PromiseLike<Accepted>
254
254
  | Reactive<Accepted, unknown, Failures, unknown>,
255
- // biome-ignore lint/suspicious/noConfusingVoidType: same reason as `watch` below — a `set` that returns nothing infers `void`, and 4.18's refusal is the other arm.
255
+ // Same reason as `watch` below — a `set` that returns nothing infers `void`, and 4.18's refusal is the other arm.
256
256
  ): void | Failures
257
257
  patch(mutate: (value: Stored) => void): void
258
258
  refresh(): void
259
259
  invalidate(): void
260
- // biome-ignore lint/suspicious/noConfusingVoidType: `void` is the RETURN POSITION of an author's effect, and it is load-bearing. `undefined` there refuses `(v) => { read(v) }` — a block body returning nothing infers `void`, which is not assignable to `undefined` — so the rule's fix would reject the ordinary effect.
260
+ // `void`, not `undefined`: see `Effect` in `watch.ts` — `(v) => { read(v) }` infers `void`.
261
261
  watch(effect: (value: Stored) => void | (() => void)): () => void
262
262
  /** What one run produced: the settled value once, or a stream's chunks to its close (2.5, 2.6). */
263
263
  [Symbol.asyncIterator](): AsyncIterator<Produced>
@@ -658,8 +658,7 @@ class Cell {
658
658
  * keyed on `.id` read every number as the same `undefined` and never woke again.
659
659
  */
660
660
  declare declaredIdentityFn:
661
- | ((next: unknown, previous: unknown) => boolean)
662
- | null
661
+ ((next: unknown, previous: unknown) => boolean) | null
663
662
  declare transform: ((value: unknown) => unknown) | null
664
663
  /**
665
664
  * `null` on every value that declares no `schema`, which keeps the gate off the write
@@ -859,8 +858,7 @@ class Cell {
859
858
  )
860
859
  this.declaredIdentityFn = this.identityFn
861
860
  this.transform = (options?.transform ?? null) as
862
- | ((value: unknown) => unknown)
863
- | null
861
+ ((value: unknown) => unknown) | null
864
862
  this.schema = (options?.schema ?? null) as Schema<unknown> | null
865
863
  this.ring = EMPTY_RING
866
864
  this.ringBase = 0
@@ -906,9 +904,7 @@ class Cell {
906
904
  unwatch: null,
907
905
  }
908
906
  this.by = (options?.by ?? null) as
909
- | string
910
- | ((element: unknown) => unknown)
911
- | null
907
+ string | ((element: unknown) => unknown) | null
912
908
  this.probePass = 0
913
909
  this.owes = OWES_NOTHING
914
910
  this.isEffect = false
@@ -3502,7 +3498,7 @@ function settled(cell: Cell, untilStreaming = false): Promise<unknown> {
3502
3498
  */
3503
3499
  function watchCell(
3504
3500
  cell: Cell,
3505
- // biome-ignore lint/suspicious/noConfusingVoidType: `void` is an EFFECT'S RETURN POSITION and is load-bearing. `undefined` there refuses the ordinary effect — a block body that returns nothing infers `void`, which is not assignable to `undefined` — so the rule's own fix would reject every caller that does not return a disposer.
3501
+ // `void`, not `undefined`: see `Effect` in `watch.ts`.
3506
3502
  effect: (value: unknown) => void | (() => void),
3507
3503
  ): () => void {
3508
3504
  return owned(
@@ -4459,7 +4455,7 @@ const MEMBERS = {
4459
4455
  },
4460
4456
  watch(
4461
4457
  this: Callable,
4462
- // biome-ignore lint/suspicious/noConfusingVoidType: `void` is an EFFECT'S RETURN POSITION and is load-bearing. `undefined` there refuses the ordinary effect — a block body that returns nothing infers `void`, which is not assignable to `undefined` — so the rule's own fix would reject every caller that does not return a disposer.
4458
+ // `void`, not `undefined`: see `Effect` in `watch.ts`.
4463
4459
  effect: (value: unknown) => void | (() => void),
4464
4460
  ): () => void {
4465
4461
  return watchCell(this[CELL], effect)
@@ -4467,7 +4463,7 @@ const MEMBERS = {
4467
4463
  [Symbol.asyncIterator](this: Callable): AsyncIterator<unknown> {
4468
4464
  return producedRun(this[CELL])
4469
4465
  },
4470
- // biome-ignore lint/suspicious/noThenProperty: RULEBOOK 1.4 — a `Reactive` MUST be thenable, which is what this rule warns about. Banning it buys a discrimination rather than a semantics, and 16.4's in-process `Rpc` arm is what that discrimination would have cost. 1.6 is the guard that makes thenability safe — the brand is read before `then`.
4466
+ // RULEBOOK 1.4 — a `Reactive` MUST be thenable. Banning it buys a discrimination rather than a semantics, and 16.4's in-process `Rpc` arm is what that discrimination would have cost. 1.6 is the guard that makes thenability safe — the brand is read before `then`.
4471
4467
  then(
4472
4468
  this: Callable,
4473
4469
  onSettled?: (value: unknown) => unknown,
@@ -231,7 +231,7 @@ export function reactive<
231
231
  */
232
232
  export function reactive<
233
233
  Body extends (args?: never) => unknown,
234
- Optional extends OptionalParameter<Body>,
234
+ _Optional extends OptionalParameter<Body>,
235
235
  Shaped = ChunkOf<Body>[],
236
236
  Gate = Schema<ChunkOf<Body>[]>,
237
237
  ArgsGate = Schema<Parameters<Body>[0]>,
@@ -291,7 +291,7 @@ export function reactive<
291
291
  */
292
292
  export function reactive<
293
293
  Body extends (args?: never) => unknown,
294
- Optional extends OptionalParameter<Body>,
294
+ _Optional extends OptionalParameter<Body>,
295
295
  Shaped = Awaited<ReturnType<Body>>,
296
296
  Gate = Schema<Awaited<ReturnType<Body>>>,
297
297
  ArgsGate = Schema<Parameters<Body>[0]>,
@@ -388,8 +388,7 @@ export function reactive(
388
388
  // `store`, built where it is first reached (11.71). `global` is what keeps a value process-wide
389
389
  // (11.34).
390
390
  const options = given[1] as
391
- | { global?: boolean; store?: unknown }
392
- | undefined
391
+ { global?: boolean; store?: unknown } | undefined
393
392
  if (outsideScope(options?.global === true))
394
393
  return scoped(
395
394
  () => build(given, keyed),
@@ -1,3 +1,4 @@
1
+ import type { Reactive } from './Reactive.ts'
1
2
  // 1.6 — THE BRAND, READ ON ITS OWN. A `Reactive` is callable AND thenable, so every guard that
2
3
  // can meet one reads this before `typeof value === 'function'` or an `isThenable` probe.
3
4
  //
@@ -9,7 +10,6 @@
9
10
  // 2,348 bytes without it. The `Reactive` import is TYPE-ONLY and erased, which is what lets the
10
11
  // predicate keep its exact shape at no cost.
11
12
  import { REACTIVE_BRAND } from './REACTIVE_BRAND.ts'
12
- import type { Reactive } from './Reactive.ts'
13
13
 
14
14
  export function isReactive(value: unknown): value is Reactive<unknown> {
15
15
  return (
@@ -16,9 +16,9 @@ import { contractOf, type Gated } from './argsContract.ts'
16
16
  import { CELL } from './CELL.ts'
17
17
  import { KEYED_BRAND } from './KEYED_BRAND.ts'
18
18
  import { brandedPrototype, MEMBER_KEYS, signalMoved } from './Reactive.ts'
19
- import { SELECTION_MEMBERS } from './SELECTION_MEMBERS.ts'
20
19
  import { currentScope, runInScope, SCOPING } from './scoping.ts'
21
- import { newTracked, TRACKING, type Tracked, trackProbe } from './tracking.ts'
20
+ import { SELECTION_MEMBERS } from './SELECTION_MEMBERS.ts'
21
+ import { newTracked, type Tracked, TRACKING, trackProbe } from './tracking.ts'
22
22
 
23
23
  const UNBUILT: unique symbol = Symbol('abide.unbuilt')
24
24
 
@@ -35,7 +35,7 @@ let CURRENT: ShareScope | null = null
35
35
  * Empty here: an app widens it, and a key it declares is checked against it where a key it does
36
36
  * not is inferred from the thunk.
37
37
  */
38
- // biome-ignore lint/suspicious/noEmptyInterface: 10.3 — an app merges its own keys into this.
38
+ // 10.3 — an app merges its own keys into this.
39
39
  export interface Shared {}
40
40
 
41
41
  /** The value held under `key` by this component or its nearest ancestor, or one created here. */