@abide/abide 0.117.2 → 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 (156) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/bin/abide.ts +74 -11
  3. package/docs/REGISTRY.md +18 -15
  4. package/docs/RULEBOOK.md +71 -10
  5. package/docs/abide.md +584 -274
  6. package/package.json +1 -1
  7. package/scaffold/AGENTS.md +1 -1
  8. package/scaffold/src/getGreeting.test.ts +2 -1
  9. package/scaffold/src/index.abide +5 -2
  10. package/scaffold/src/index.test.ts +2 -0
  11. package/scaffold/src/layout.abide +6 -6
  12. package/src/compiler/Lowering.ts +20 -2
  13. package/src/compiler/PositionTable.ts +1 -0
  14. package/src/compiler/Refusals.ts +1 -0
  15. package/src/compiler/TypeSession.ts +49 -13
  16. package/src/compiler/aliasedSymbol.ts +1 -1
  17. package/src/compiler/ambientReadsIn.ts +1 -0
  18. package/src/compiler/appLayout.ts +55 -3
  19. package/src/compiler/appMap.ts +15 -0
  20. package/src/compiler/argsDefaultsIn.ts +1 -0
  21. package/src/compiler/argsSchemaOf.ts +1 -0
  22. package/src/compiler/checkApp.ts +3 -1
  23. package/src/compiler/checkedShadow.ts +2 -1
  24. package/src/compiler/classifyRead.ts +1 -0
  25. package/src/compiler/classifyTemplate.ts +1 -0
  26. package/src/compiler/compileApp.ts +5 -3
  27. package/src/compiler/compiledEntry.ts +2 -1
  28. package/src/compiler/componentGraph.ts +1 -0
  29. package/src/compiler/declaredExports.ts +4 -2
  30. package/src/compiler/emitClient.ts +19 -14
  31. package/src/compiler/emitComponent.ts +1 -0
  32. package/src/compiler/emitSource.ts +2 -1
  33. package/src/compiler/formatAbide.ts +857 -0
  34. package/src/compiler/formatDiagnosis.ts +1 -0
  35. package/src/compiler/handlersUnder.ts +7 -3
  36. package/src/compiler/hookCalls.ts +1 -0
  37. package/src/compiler/lineOf.ts +17 -0
  38. package/src/compiler/matchersOf.ts +157 -0
  39. package/src/compiler/mountsOf.ts +5 -0
  40. package/src/compiler/paramFile.ts +125 -0
  41. package/src/compiler/parseAbide.ts +48 -28
  42. package/src/compiler/projectShadow.ts +11 -4
  43. package/src/compiler/reactiveOptions.ts +1 -0
  44. package/src/compiler/reactiveTypes.ts +2 -1
  45. package/src/compiler/readsIn.ts +3 -2
  46. package/src/compiler/renderMarkup.ts +3 -2
  47. package/src/compiler/resolverIn.ts +2 -0
  48. package/src/compiler/sameTemplate.ts +150 -0
  49. package/src/compiler/scaffold.ts +4 -11
  50. package/src/compiler/serveLanguage.ts +48 -21
  51. package/src/compiler/sharedModuleWrites.ts +2 -1
  52. package/src/compiler/sourceMapOf.ts +1 -0
  53. package/src/compiler/splitImports.ts +2 -0
  54. package/src/compiler/templateWarnings.ts +2 -2
  55. package/src/compiler/trackingWarnings.ts +1 -0
  56. package/src/compiler/writeDefaultProject.ts +5 -1
  57. package/src/server/BRIDGE_VERSION.ts +1 -1
  58. package/src/server/abideModules.ts +2 -0
  59. package/src/server/answerFailure.ts +1 -0
  60. package/src/server/answerRequest.ts +57 -19
  61. package/src/server/answerRpc.ts +6 -2
  62. package/src/server/answerSocket.ts +2 -1
  63. package/src/server/answerValue.ts +1 -0
  64. package/src/server/answerWorker.ts +1 -0
  65. package/src/server/appTree.ts +18 -9
  66. package/src/server/argsFor.ts +1 -0
  67. package/src/server/assistant.ts +2 -1
  68. package/src/server/banner.ts +2 -0
  69. package/src/server/bridgeRelay.ts +1 -0
  70. package/src/server/callerOf.ts +1 -0
  71. package/src/server/claudeApi.ts +1 -0
  72. package/src/server/claudeCode.ts +1 -0
  73. package/src/server/clientBundle.ts +1 -0
  74. package/src/server/coerceArgs.ts +1 -2
  75. package/src/server/commands.ts +9 -0
  76. package/src/server/compressAnswer.ts +2 -1
  77. package/src/server/config.ts +2 -0
  78. package/src/server/createApp.ts +4 -2
  79. package/src/server/crossingOrigin.ts +1 -0
  80. package/src/server/csp.ts +1 -0
  81. package/src/server/deferredBuilds.ts +1 -0
  82. package/src/server/derivedArgs.ts +1 -0
  83. package/src/server/devWorker.ts +2 -1
  84. package/src/server/faceOf.ts +2 -7
  85. package/src/server/generatedSurfaces.ts +79 -7
  86. package/src/server/hooks.ts +1 -0
  87. package/src/server/iconAccent.ts +1 -1
  88. package/src/server/installServer.ts +1 -0
  89. package/src/server/installSourceMaps.ts +1 -0
  90. package/src/server/launcherPage.ts +2 -2
  91. package/src/server/manifestOf.ts +1 -0
  92. package/src/server/muxUpgrade.ts +1 -0
  93. package/src/server/nativeMenu.ts +2 -0
  94. package/src/server/placement.ts +12 -2
  95. package/src/server/principal.ts +2 -1
  96. package/src/server/remote.ts +7 -2
  97. package/src/server/render.ts +3 -3
  98. package/src/server/renderComponent.ts +1 -0
  99. package/src/server/reportHealth.ts +1 -0
  100. package/src/server/requestScope.ts +3 -1
  101. package/src/server/runDesktop.ts +3 -2
  102. package/src/server/seedBuffer.ts +1 -0
  103. package/src/server/serveDev.ts +3 -2
  104. package/src/server/shell.ts +2 -0
  105. package/src/server/streamEvent.ts +1 -0
  106. package/src/server/surfaceOf.ts +6 -1
  107. package/src/server/testBuild.ts +1 -0
  108. package/src/server/testMount.ts +1 -0
  109. package/src/server/trace.ts +2 -0
  110. package/src/server/withAbideSources.ts +1 -0
  111. package/src/shared/Attributes.ts +12 -8
  112. package/src/shared/cookies.ts +1 -1
  113. package/src/shared/escapeText.ts +1 -1
  114. package/src/shared/filledPath.ts +16 -10
  115. package/src/shared/index.ts +1 -5
  116. package/src/shared/jsonSchema.ts +1 -3
  117. package/src/shared/matchRoute.ts +16 -4
  118. package/src/shared/menuBridge.ts +1 -2
  119. package/src/shared/outbox.ts +1 -1
  120. package/src/shared/reactive/Keyed.ts +2 -2
  121. package/src/shared/reactive/Reactive.ts +12 -16
  122. package/src/shared/reactive/index.ts +3 -4
  123. package/src/shared/reactive/isReactive.ts +1 -1
  124. package/src/shared/reactive/scoped.ts +2 -2
  125. package/src/shared/reactive/share.ts +1 -1
  126. package/src/shared/reactive/watch.ts +4 -4
  127. package/src/shared/refuse.ts +1 -1
  128. package/src/shared/routePattern.ts +66 -14
  129. package/src/shared/rpc.ts +8 -11
  130. package/src/shared/url.ts +24 -7
  131. package/src/shared/validateJson.ts +1 -1
  132. package/src/ui/ArmRegion.ts +1 -0
  133. package/src/ui/Level.ts +1 -0
  134. package/src/ui/List.ts +1 -0
  135. package/src/ui/RawRun.ts +1 -0
  136. package/src/ui/Router.ts +1 -0
  137. package/src/ui/TryRegion.ts +1 -0
  138. package/src/ui/adoptWalk.ts +2 -1
  139. package/src/ui/bindElement.ts +1 -0
  140. package/src/ui/bindFiles.ts +1 -0
  141. package/src/ui/bindGroup.ts +1 -0
  142. package/src/ui/bindProperty.ts +1 -0
  143. package/src/ui/bindSpread.ts +1 -0
  144. package/src/ui/index.ts +1 -6
  145. package/src/ui/outboxQueue.ts +1 -1
  146. package/src/ui/parseMarkup.ts +2 -1
  147. package/src/ui/reconcile.ts +2 -1
  148. package/src/ui/reconcileHead.ts +1 -0
  149. package/src/ui/regions.ts +2 -1
  150. package/src/ui/registerWorker.ts +1 -0
  151. package/src/ui/rows.ts +1 -0
  152. package/src/ui/setMarkup.ts +1 -0
  153. package/src/ui/setText.ts +1 -0
  154. package/src/ui/socketWire.ts +4 -3
  155. package/src/ui/wire.ts +2 -1
  156. /package/scaffold/src/{getGreeting.ts → getGreeting.handler.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @abide/abide
2
2
 
3
+ ## 0.119.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a9f8ad1: abide format formats every .abide — its scripts, styles and expressions by bun fmt, its markup by its nesting — and leaves one as written where the template would change (RULEBOOK 38.125-38.130) ([`fb0b837`](https://github.com/briancray/abide/commit/fb0b837b1264a4193371388a61fb64ec81f16638))
8
+
9
+ ### Patch Changes
10
+
11
+ - a9f8ad1: bun fmt replaces biome, and an unused local or parameter is a type error ([`259f9b1`](https://github.com/briancray/abide/commit/259f9b18b9c2bd12b6ab5c9d9784adb2b8d2edd1))
12
+ - a9f8ad1: format the repo with abide format and bun fmt ([`d7cd46d`](https://github.com/briancray/abide/commit/d7cd46da1e0cd523631d38d923f8bb08d1f0716f))
13
+
14
+ ## 0.118.0
15
+
16
+ ### Minor Changes
17
+
18
+ - 1613343: Breaking: a handler file is named <name>.handler.ts (RULEBOOK 23.14, 23.22) ([`5f64c1b`](https://github.com/briancray/abide/commit/5f64c1b02dec18c6e8574a88ee46e2f7477bee71))
19
+ - 1613343: Breaking: a route param names a matcher in a <NAME>.param.ts, and one naming none takes no part carrying a period (RULEBOOK 23.24-23.27, 30.34-30.37, 20.23) ([`db7b00d`](https://github.com/briancray/abide/commit/db7b00d07bbb8f47bc73a757356675555b276b51))
20
+
21
+ ### Patch Changes
22
+
23
+ - 1613343: a page answers 404 to a request that cannot display it, before its setup runs (RULEBOOK 35.19) ([`7276d7c`](https://github.com/briancray/abide/commit/7276d7c41a44b5602b9dd4a779f85b3a05aa260f))
24
+
3
25
  ## 0.117.2
4
26
 
5
27
  ### Patch Changes
package/bin/abide.ts CHANGED
@@ -4,17 +4,19 @@
4
4
 
5
5
  import { existsSync, realpathSync } from 'node:fs' // bun exposes no sync existence check or realpath of its own
6
6
  import { mkdir, rename, rm } from 'node:fs/promises' // bun exposes no directory creation, rename or recursive directory removal of its own
7
- import { dirname, resolve } from 'node:path' // bun exposes no path helpers of its own
7
+ import { dirname, relative, resolve } from 'node:path' // bun exposes no path helpers of its own
8
8
  import { brotliCompress, constants } from 'node:zlib' // bun's brotli is `CompressionStream`, which compresses on the main thread — 1390 ms against this pool's 300 ms over the docs bundle
9
+
9
10
  import { paints } from '#compiler/appLayout.ts'
10
11
  import { appMap, mapText } from '#compiler/appMap.ts'
11
12
  import { checkApp } from '#compiler/checkApp.ts'
12
13
  import {
13
- type CompiledApp,
14
14
  compilationOf,
15
15
  compileApp,
16
+ type CompiledApp,
16
17
  } from '#compiler/compileApp.ts'
17
18
  import { compiledEntry } from '#compiler/compiledEntry.ts'
19
+ import { formatAbide } from '#compiler/formatAbide.ts'
18
20
  import { formatDiagnosis } from '#compiler/formatDiagnosis.ts'
19
21
  import { parseAbide } from '#compiler/parseAbide.ts'
20
22
  import { scaffold } from '#compiler/scaffold.ts'
@@ -40,18 +42,23 @@ import { appOnDisk, appRoot, noAppHere } from '#server/createApp.ts'
40
42
  import { executableName } from '#server/executableName.ts'
41
43
  import { iconAccent } from '#server/iconAccent.ts'
42
44
  import { namesUnder } from '#server/namesUnder.ts'
45
+ import { skipped } from '#server/placement.ts'
43
46
  import { DEFAULT_DOCUMENT, intoHead } from '#server/render.ts'
44
47
  import { runtimeRefusal } from '#server/runtimeRefusal.ts'
45
48
  import { pathsUnder, serveBuild } from '#server/serveBuild.ts'
46
49
  import { serveDev } from '#server/serveDev.ts'
47
50
  import { escapeText } from '#shared/escapeText.ts'
48
51
  import { ICON_ADDRESSES, LAUNCHER_PAGE } from '#shared/LAUNCHER_FILES.ts'
52
+
49
53
  import abidePackage from '../package.json' with { type: 'json' }
50
54
 
51
55
  // 38.123 — the bun this process runs on, held to abide's `engines.bun` before anything is built or
52
56
  // booted. A compiled app carries the bun `abide compile` ran on, which this held already.
53
57
  const RUNTIME_REFUSAL = runtimeRefusal(Bun.version, abidePackage.engines.bun)
54
58
 
59
+ /** How many files `abide format` formats at once, each spawning `bun fmt` for its pieces. */
60
+ const FILES_AT_ONCE = 8
61
+
55
62
  /** Where the app a command builds or serves is, and where its build goes — both absolute. */
56
63
  type AppDirectories = { root: string; out: string }
57
64
 
@@ -81,6 +88,10 @@ const DISK: Host = {
81
88
  dev: inApp(dev),
82
89
  build: inApp(build),
83
90
  check: inApp(check),
91
+ format: (given) =>
92
+ given.positionals.length > 1
93
+ ? format(namedDirectories(given.positionals), given)
94
+ : inApp(({ root }) => format([root], given))(given),
84
95
  routes: inApp(routes),
85
96
  compile: inApp(compile),
86
97
  bundle: inApp(bundle),
@@ -699,9 +710,9 @@ async function scaffoldCommand({
699
710
  return 1
700
711
  }
701
712
  const into = resolve(name)
702
- const { written, skipped } = await scaffold(name, into)
713
+ const { written, skipped: kept } = await scaffold(name, into)
703
714
  for (const path of written) console.log(` wrote ${path}`)
704
- for (const path of skipped) console.log(` kept ${path}`)
715
+ for (const path of kept) console.log(` kept ${path}`)
705
716
  console.log(
706
717
  // The starter's own script: `abide` alone is on no PATH until it is installed globally.
707
718
  `\nabide scaffold: ${into}\n\n cd ${name}\n bun install\n bun run dev`,
@@ -729,13 +740,7 @@ async function check(
729
740
  { root }: AppDirectories,
730
741
  { positionals }: Given,
731
742
  ): Promise<number> {
732
- const within: string[] = []
733
- for (const directory of positionals.slice(1))
734
- within.push(
735
- existsSync(directory)
736
- ? realpathSync(resolve(directory))
737
- : resolve(directory),
738
- )
743
+ const within = namedDirectories(positionals)
739
744
  const found = await checkApp(root)
740
745
  let errors = 0
741
746
  let warnings = 0
@@ -760,6 +765,64 @@ async function check(
760
765
  return errors > 0 ? 1 : 0
761
766
  }
762
767
 
768
+ /** The directories a command's `[dir…]` names, each as the real path a finding is filed under. */
769
+ function namedDirectories(positionals: string[]): string[] {
770
+ const named: string[] = []
771
+ for (const directory of positionals.slice(1))
772
+ named.push(
773
+ existsSync(directory)
774
+ ? realpathSync(resolve(directory))
775
+ : resolve(directory),
776
+ )
777
+ return named
778
+ }
779
+
780
+ /**
781
+ * `abide format`: formats every `.abide` under `within` — the directories named, or the app where
782
+ * none are — and fails where any file was left as written. 38.125, 38.128.
783
+ *
784
+ * `--check` writes nothing, and fails where a file would change. 38.129.
785
+ *
786
+ * NAMED DIRECTORIES NEED NO APP, unlike `check`'s: a formatter reads one file at a time, so a
787
+ * monorepo formats every app under it in one run.
788
+ */
789
+ async function format(within: string[], { values }: Given): Promise<number> {
790
+ const paths: string[] = []
791
+ for (const directory of within)
792
+ for (const name of namesUnder(directory, '**/*.abide'))
793
+ if (!name.split('/').some(skipped))
794
+ paths.push(`${directory}/${name}`)
795
+ let changed = 0
796
+ let errors = 0
797
+ // A file's pieces are formatted in parallel already, so files are taken a few at a time.
798
+ let next = 0
799
+ const take = async (): Promise<void> => {
800
+ while (next < paths.length) {
801
+ const path = paths[next] as string
802
+ next += 1
803
+ const text = await Bun.file(path).text()
804
+ const formatted = await formatAbide(path, text)
805
+ for (const finding of formatted.findings) {
806
+ errors += 1
807
+ console.log(formatDiagnosis(finding, process.cwd()))
808
+ }
809
+ if (formatted.text === text) continue
810
+ changed += 1
811
+ if (values.check)
812
+ console.log(
813
+ `${relative(process.cwd(), path)} - needs formatting`,
814
+ )
815
+ else await Bun.write(path, formatted.text)
816
+ }
817
+ }
818
+ await Promise.all(Array.from({ length: FILES_AT_ONCE }, take))
819
+ const files = `${changed} file${changed === 1 ? '' : 's'}`
820
+ console.log(
821
+ `abide format: ${values.check ? `${files} to format` : `${files} formatted`} of ${paths.length}, ${errors} error${errors === 1 ? '' : 's'}`,
822
+ )
823
+ return errors > 0 || (values.check && changed > 0) ? 1 : 0
824
+ }
825
+
763
826
  /**
764
827
  * `abide lsp`: the language server over stdio.
765
828
  *
package/docs/REGISTRY.md CHANGED
@@ -264,9 +264,9 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
264
264
 
265
265
  | File | Declares | Served at | Rules |
266
266
  | --- | --- | --- | --- |
267
- | `users/getUser.ts` | `export default GET(…)` | `/users/getUser` | 16.2, 16.73, 19.1, 19.20, 23.14 |
268
- | `health.ts` | `export default GET(…)` | `/health` | 16.2, 23.14 |
269
- | `media/[id]/save.ts` | `export default POST(…)` | `/media/[id]/save`, `id` reaching its `Args` | 16.2, 16.65, 16.66, 16.67, 16.69 |
267
+ | `users/getUser.handler.ts` | `export default GET(…)` | `/users/getUser` | 16.2, 16.73, 19.1, 19.20, 23.14 |
268
+ | `health.handler.ts` | `export default GET(…)` | `/health` | 16.2, 23.14 |
269
+ | `media/[id]/save.handler.ts` | `export default POST(…)` | `/media/[id]/save`, `id` reaching its `Args` | 16.2, 16.65, 16.66, 16.67, 16.69 |
270
270
  | `media/[id]/lib/Comments.abide` | `const addComment = POST(…)` in its `<script server>` | `/__abide/handlers/media/id/lib/Comments/addComment` | 16.70, 16.71, 16.72 |
271
271
 
272
272
  ## Schemas
@@ -315,14 +315,14 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
315
315
 
316
316
  | Name | Signature | Meaning | Rules |
317
317
  | --- | --- | --- | --- |
318
- | `/__abide/openapi.json` | `GET` | The generated OpenAPI document. | 19.21, 19.22, 20.5, 20.6, 20.7, 20.8, 20.11, 20.13, 20.15, 36.7 |
318
+ | `/__abide/openapi.json` | `GET` | The generated OpenAPI document. | 19.21, 19.22, 20.5, 20.6, 20.7, 20.8, 20.11, 20.13, 20.15, 20.23, 36.7 |
319
319
  | `OpenApiDocument` | `JsonValue` | OpenAPI 3.1, whose schema dialect is `JsonSchema`. | 20.6 |
320
320
 
321
321
  ## MCP
322
322
 
323
323
  | Name | Signature | Meaning | Rules |
324
324
  | --- | --- | --- | --- |
325
- | `/__abide/mcp` | `POST` | The streamable-http MCP endpoint. | 19.21, 19.22, 20.5, 20.7, 20.8, 20.9, 20.10, 20.12, 20.13, 20.14, 20.16, 20.17, 20.19, 20.20, 20.21, 20.22, 36.7, 16.78 |
325
+ | `/__abide/mcp` | `POST` | The streamable-http MCP endpoint. | 19.21, 19.22, 20.5, 20.7, 20.8, 20.9, 20.10, 20.12, 20.13, 20.14, 20.16, 20.17, 20.19, 20.20, 20.21, 20.22, 20.23, 36.7, 16.78 |
326
326
 
327
327
  # Assistant
328
328
 
@@ -513,8 +513,8 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
513
513
  | `OptionalNames<P>` | `string` | The optional segment names. | 30.4 |
514
514
  | `RestNames<P>` | `string` | The rest segment names. | 30.5 |
515
515
  | `Query` | `Record<string, unknown> \| URLSearchParams` | The query half. | 30.6, 30.28 |
516
- | `ParamsOf<P>` | `& { [K in RequiredNames<P>]: string \| number } & { [K in OptionalNames<P>]?: string \| number } & { [K in RestNames<P>]?: string \| number \| (string \| number)[] }` | What a route literal's segments accept. | 30.3, 30.4, 30.5 |
517
- | `RouteParams<P>` | `{ [K in RequiredNames<P>]: string } & { [K in OptionalNames<P>]?: string } & { [K in RestNames<P>]: string[] }` | What a page filed under `P` reads its params as. | 23.9 |
516
+ | `ParamsOf<P>` | `& { [K in RequiredNames<P>]: string \| number } & { [K in OptionalNames<P>]?: string \| number } & { [K in RestNames<P>]?: string \| number \| (string \| number)[] }` | What a route literal's segments accept, narrowed where `abide check` declares a matcher's literals. | 30.3, 30.4, 30.5 |
517
+ | `RouteParams<P>` | `{ [K in RequiredNames<P>]: string } & { [K in OptionalNames<P>]?: string } & { [K in RestNames<P>]: string[] }` | What a page filed under `P` reads its params as, narrowed where `abide check` declares a matcher's literals. | 23.9 |
518
518
  | `Routes` | `interface Routes {}` | The app's route literals and public file addresses, which `abide check` declares. | 30.26 |
519
519
  | `RouteLiteral` | `[keyof Routes] extends [never] ? string : Extract<keyof Routes, string>` | What `url` takes. | 30.26 |
520
520
 
@@ -619,9 +619,10 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
619
619
  | --- | --- | --- |
620
620
  | `<head>` | A page's, layout's or component's contribution to the document head. | 39.1, 39.2, 39.3, 39.4, 39.5, 39.6, 39.11, 39.12, 39.13, 39.14, 39.15, 39.16, 39.17 |
621
621
  | `view-transition-name` | What turns view transitions on, in the app's own stylesheet. | 39.7, 39.8, 39.9, 39.10, 39.18, 39.19 |
622
- | `[name]` | A required dynamic segment. | 16.65, 23.5, 30.3 |
623
- | `[[name]]` | An optional segment. | 23.5, 30.4 |
624
- | `[...name]` | A rest segment, terminal. | 23.5, 30.5 |
622
+ | `[name]` | A required dynamic segment. | 16.65, 23.5, 30.3, 30.34, 30.36 |
623
+ | `[[name]]` | An optional segment. | 23.5, 30.4, 30.34, 30.36 |
624
+ | `[...name]` | A rest segment, terminal. | 23.5, 30.5, 30.34, 30.36 |
625
+ | `[name=NAME]` · `[[name=NAME]]` · `[...name=NAME]` | A dynamic segment a param file's matcher decides. | 19.1, 23.26, 23.27, 30.19, 30.35, 30.36, 30.37 |
625
626
  | `/__abide/**` | Every endpoint abide controls. | 20.8 |
626
627
 
627
628
  ## `render`
@@ -684,9 +685,10 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
684
685
  | `src/public/robots.txt` | The file answered at `/robots.txt`. | 36.11 |
685
686
  | `src/public/icon.png` · `src/public/icon.icns` | The files answered at `/icon.png` and `/icon.icns`, and the desktop app's icon. | 36.11, 38.79, 45.15 |
686
687
  | `src/**/` | A directory of the app's, a segment of the route of every file directly in it. | 23.14, 23.17, 23.22 |
687
- | `**/index.abide` | The page at its directory's route. | 19.1, 23.3, 23.4, 23.14, 23.18 |
688
- | `**/<name>.abide` | The page at its directory's route and then `<name>`. | 19.1, 23.3, 23.4, 23.14, 23.21 |
689
- | `**/<name>.ts` | A handler file: the handler its default export declares, at its directory's route and then `<name>`. | 16.2, 16.28, 16.73, 16.74, 19.1, 23.14, 23.22 |
688
+ | `**/index.abide` | The page at its directory's route. | 19.1, 23.3, 23.4, 23.14, 23.18, 35.19 |
689
+ | `**/<name>.abide` | The page at its directory's route and then `<name>`. | 19.1, 23.3, 23.4, 23.14, 23.21, 35.19 |
690
+ | `**/<NAME>.param.ts` | A param file: the matcher a segment naming `NAME` matches by. | 23.22, 23.24, 23.25, 23.26 |
691
+ | `**/<name>.handler.ts` | A handler file: the handler its default export declares, at its directory's route and then `<name>`. | 16.2, 16.28, 16.73, 16.74, 19.1, 23.14, 23.22 |
690
692
  | `**/layout.abide` | A layout, rendering every page below its route through a slot, and the hooks over that route. | 35.1, 35.12, 35.13, 37.2, 41.11, 41.19, 41.23 |
691
693
  | `src/launcher.abide` | The desktop launcher, beside the root layout: the `onLauncher` it calls, and its page in place of the launcher's own where it has markup. | 38.80, 38.82, 38.84, 38.85, 38.107 |
692
694
  | `src/layout.abide` | The root layout, whose `<script server>` is the app's own, and whose `<html>` is the document its pages are served in. | 35.15, 35.16, 35.17, 37.1, 37.3, 39.4 |
@@ -859,7 +861,8 @@ rows a runner prints, and an adapter for an abide app.
859
861
  | `abide scaffold <name>` | Writes a starter project. | 38.1, 38.42, 38.103, 38.104, 38.106, 38.112, 38.122, 38.124 |
860
862
  | `abide run <file> [args…]` | Runs a script under the abide runtime. | 38.2, 38.57 |
861
863
  | `abide check [dir…]` | The type-checker over a `.abide` tree. | 38.3, 38.31, 38.32, 38.33, 38.40, 38.105, 38.123 |
862
- | `abide routes [--json]` | Every address the app answers, the file answering it, and where each hook is filed. | 38.108, 38.123 |
864
+ | `abide format [--check] [dir…]` | The formatter over a `.abide` tree. | 38.25, 38.125, 38.126, 38.127, 38.128, 38.129 |
865
+ | `abide routes [--json]` | Every address the app answers, the file answering it, what each matcher takes, and where each hook is filed. | 38.108, 38.123 |
863
866
  | `abide dev [--port <n>]` | Watches the project and keeps the app up. | 16.23, 16.56, 37.8, 37.9, 38.4, 38.14, 38.15, 38.16, 38.17, 38.19, 38.24, 38.25, 38.26, 38.28, 38.30, 38.35, 38.36, 38.37, 38.38, 38.41, 38.43, 38.58, 38.63, 38.64, 38.65, 38.94, 38.96, 38.97, 38.123 |
864
867
  | `abide build` | Builds the client into content-hashed chunks and a manifest. | 38.43, 38.5, 38.18, 38.25, 38.26, 38.27, 38.30, 38.66, 38.94, 38.123 |
865
868
  | `abide start [--port <n>]` | Boots the built app. | 37.8, 37.10, 37.11, 37.12, 38.6, 38.100, 38.20, 38.21, 38.22, 38.23, 38.25, 38.26, 38.27, 38.28, 38.29, 38.58, 38.67, 38.68, 38.95, 38.97, 38.110, 38.123 |
@@ -870,6 +873,6 @@ rows a runner prints, and an adapter for an abide app.
870
873
  | `abide watch <address> [args]` | A live subscription to one of the app's followed `GET`s. | 38.69 |
871
874
  | `abide compile [--target] [--out] [--platforms]` | One standalone executable. | 37.8, 37.10, 37.11, 37.12, 38.10, 38.25, 38.26, 38.44, 38.45, 38.46, 38.47, 38.48, 38.49, 38.50, 38.51, 38.52, 38.56, 38.93, 38.97, 38.123 |
872
875
  | `abide bundle [--out]` | A desktop app for the host platform, with a window on the app. | 38.10, 38.25, 38.26, 38.70, 38.71, 38.72, 38.73, 38.74, 38.75, 38.76, 38.77, 38.78, 38.79, 38.80, 38.81, 38.82, 38.83, 38.84, 38.85, 38.86, 38.87, 38.88, 38.89, 38.90, 38.91, 38.92, 38.101, 38.102, 38.123 |
873
- | `abide lsp` | The `.abide` language server, over stdio. | 38.11, 38.34, 38.39, 38.98, 38.116, 38.117, 38.118 |
876
+ | `abide lsp` | The `.abide` language server, over stdio. | 38.11, 38.34, 38.39, 38.98, 38.116, 38.117, 38.118, 38.130 |
874
877
  | `--help` · `-h` · `abide help` | Usage, generated from the command list. | 38.12, 38.113, 38.114 |
875
878
  | `--version` · `-v` | The version of abide, or of the app a compiled executable holds. | 38.115 |
package/docs/RULEBOOK.md CHANGED
@@ -121,7 +121,9 @@ REGISTRY.md because none of them is a name an app author writes.
121
121
  | server file | A file named `<name>.server.<extension>`. |
122
122
  | test file | A `.test.ts` file. |
123
123
  | declaration file | A `.d.ts` file. |
124
- | handler file | A `.ts` of the app's own, neither a declaration file, a test file nor a server file, directly in a directory under no fence. |
124
+ | handler file | A file of the app's own named `<name>.handler.ts`, directly in a directory under no fence. |
125
+ | param file | A file of the app's own named `<NAME>.param.ts`, directly in a directory under no fence. |
126
+ | matcher | What a param file declares, and what a segment naming it matches by. |
125
127
  | private handler | A handler a `<script server>` declares. |
126
128
  | chapter app | The app the documentation's story has built by the end of one chapter, kept whole so a reader can download it and run it. |
127
129
 
@@ -1266,7 +1268,7 @@ while `outbox` holds a call not yet delivered, and MUST read the value again onc
1266
1268
 
1267
1269
  19.1 A route MUST be answered for each method by one file at most, a page answering `GET` and `HEAD`
1268
1270
  at its own, and a second MUST be a build error naming both files, two routes differing only in
1269
- their parameters' names being one route.
1271
+ their parameters' names or matchers being one route.
1270
1272
 
1271
1273
  19.2 A `Schema` MUST return what it accepts.
1272
1274
 
@@ -1405,6 +1407,10 @@ text, and MUST carry no `structuredContent`.
1405
1407
  20.22 A call to a tool declaring an `outputSchema` that is answered with an `image/*` body MUST be
1406
1408
  refused, its text naming the tool and the image's type, and MUST be logged per 20.18 as a 500.
1407
1409
 
1410
+ 20.23 A path parameter `/__abide/openapi.json` publishes, save a rest's, and a route parameter an MCP
1411
+ tool's input declares, a rest's on each of its items, MUST carry the pattern its segment takes a part
1412
+ by, anchored, and a matcher's name MUST be no part of the path, the operation or the tool.
1413
+
1408
1414
  # 21. Generated headers
1409
1415
 
1410
1416
  21.1 Every response MUST carry `x-content-type-options: nosniff`.
@@ -1517,7 +1523,8 @@ composite.
1517
1523
 
1518
1524
  23.9 In a page or a layout, `route.params()` MUST be typed by that file's own route: a required
1519
1525
  segment as text, an optional one as text that may be absent, a rest as a list, and in a layout any
1520
- segment a page below it adds.
1526
+ segment a page below it adds — under `abide check`, a page's required or optional segment whose
1527
+ matcher is an alternation of literals as the union of those literals.
1521
1528
 
1522
1529
  23.10 `reachable` MUST be true where the host answered a request, whatever the status it answered.
1523
1530
 
@@ -1527,8 +1534,9 @@ segment a page below it adds.
1527
1534
 
1528
1535
  23.13 `reachable` MUST ask a host that names no scheme over https, and an origin as written.
1529
1536
 
1530
- 23.14 A route MUST be the path of its file below the app's `--root` without its extension, and an
1531
- `index.abide`'s, a `layout.abide`'s and an `error.abide`'s MUST be its directory's.
1537
+ 23.14 A route MUST be the path of its file below the app's `--root` without its extension, a handler
1538
+ file's being `.handler.ts`, and an `index.abide`'s, a `layout.abide`'s and an `error.abide`'s MUST be
1539
+ its directory's.
1532
1540
 
1533
1541
  23.15 A file under a fence MUST NOT have a route.
1534
1542
 
@@ -1549,12 +1557,26 @@ error naming the mount.
1549
1557
  `layout.abide`, an `error.abide` and the root's `launcher.abide`.
1550
1558
 
1551
1559
  23.22 A file of the app's own directly in a directory under no fence that is neither a `.abide`, a
1552
- handler file, a test file, a bench file nor a declaration file MUST be a build error naming the file and a `lib` directory, save one
1560
+ handler file, a param file, a test file, a bench file nor a declaration file MUST be a build error naming the file and a `lib` directory, save one
1553
1561
  beside the `package.json` of a root that holds it, nor a `.ts`.
1554
1562
 
1555
1563
  23.23 A server file of the app's own under no `lib` directory MUST be a build error naming the file
1556
1564
  and a `lib` directory.
1557
1565
 
1566
+ 23.24 A param file MUST hold one `export const`, of the name it is filed under, whose value is a
1567
+ regular expression literal carrying no flag, and anything else, an import included, MUST be a build
1568
+ error naming the file.
1569
+
1570
+ 23.25 A matcher repeating, with `*`, `+` or `{n,}`, a group that itself holds such a repetition, or
1571
+ carrying a backreference, MUST be a build error naming its file.
1572
+
1573
+ 23.26 A segment `[name=NAME]`, `[[name=NAME]]` or `[...name=NAME]` MUST name the param file `NAME.param.ts`
1574
+ in the directory holding that segment or the nearest directory above it below the root it is filed
1575
+ under, and one naming none MUST be a build error naming the segment's file and `NAME`.
1576
+
1577
+ 23.27 Two routes naming different matchers, or a matcher and none, at one parameter position after
1578
+ one static prefix MUST be a build error naming both files.
1579
+
1558
1580
  # 24. Tracing
1559
1581
 
1560
1582
  24.1 `trace` MUST be built on first ask and held for the request.
@@ -1741,7 +1763,8 @@ MUST NOT consume `csp.nonce`.
1741
1763
  30.2 `url` MUST require a params argument where the literal carries a required segment, and MUST
1742
1764
  make it optional otherwise.
1743
1765
 
1744
- 30.3 A required segment MUST map to a required key of `ParamsOf<P>`.
1766
+ 30.3 A required segment MUST map to a required key of `ParamsOf<P>`, typed under `abide check` as
1767
+ 23.9 types it where its matcher is an alternation of literals.
1745
1768
 
1746
1769
  30.4 An `OptionalNames<P>` segment MUST map to an optional key, and leaving one out MUST omit that
1747
1770
  segment.
@@ -1783,7 +1806,8 @@ on.
1783
1806
 
1784
1807
  30.18 `navigate` MUST leave an answer other than 204 to the document.
1785
1808
 
1786
- 30.19 `url` MUST throw where a param, or a member of a rest param, is `.` or `..`.
1809
+ 30.19 `url` MUST throw where a param, or a member of a rest param, of a segment naming no matcher
1810
+ carries a `.`, and where any param or member is `.` or `..`.
1787
1811
 
1788
1812
  30.20 A history step to an address that differs from the page shown only in its fragment MUST NOT
1789
1813
  pass through `middleware`, and MUST NOT remount the page.
@@ -1828,6 +1852,17 @@ MUST leave the page and the address where they stand, save where 45.12 holds.
1828
1852
  30.33 A history step under 30.20, and a `navigate` under 30.21, MUST move `route.url` to the address
1829
1853
  it steps to.
1830
1854
 
1855
+ 30.34 A `[param]` or an `[[optional]]` segment naming no matcher MUST NOT match a part carrying a
1856
+ `.`, and such a `[...rest]` MUST NOT take one.
1857
+
1858
+ 30.35 A segment naming a matcher MUST match a part only where the whole part, percent-decoded,
1859
+ matches it, and a `[...rest]` naming one MUST take a part only where it does.
1860
+
1861
+ 30.36 No dynamic segment MUST match a part that is `.` or `..`.
1862
+
1863
+ 30.37 An address whose part a segment refuses, by its matcher or by 30.34, MUST be matched against
1864
+ the routes 30.9 ranks after that route.
1865
+
1831
1866
  # 31. Reading and writing by name
1832
1867
 
1833
1868
  31.1 Inside a `.abide` file a name bound to a `Reactive` MUST be read wherever 31.3 does not hold it.
@@ -2322,6 +2357,9 @@ on any element is.
2322
2357
  35.18 A document an `error.abide` answers MUST NOT be hydrated as the page its address names, and a
2323
2358
  navigation from it MUST load the document it asks for.
2324
2359
 
2360
+ 35.19 A page route MUST answer a request whose `sec-fetch-dest` names neither a destination fetch
2361
+ calls a navigation request's nor `empty` with a bodiless 404, and MUST NOT set up its page.
2362
+
2325
2363
  # 36. Environment and files
2326
2364
 
2327
2365
  36.1 `PORT` MUST default to 3000, and a command's own port flag MUST override it by declaring it.
@@ -2729,8 +2767,9 @@ as one markdown file, in reading order.
2729
2767
  38.107 `onLauncher` called anywhere but `src/launcher.abide` MUST be a build error naming that file.
2730
2768
 
2731
2769
  38.108 `abide routes` MUST print every route with each method it answers and the file answering
2732
- it, every private handler with its address and its file, and every hook with the file that filed it;
2733
- with `--json` it MUST print the same as one JSON document.
2770
+ it, every private handler with its address and its file, every matcher a route names with the
2771
+ pattern it takes a part by, and every hook with the file that filed it; with `--json` it MUST print
2772
+ the same as one JSON document.
2734
2773
 
2735
2774
  38.109 Under `bun test` with `@abide/abide/test` preloaded, a test MUST import a `.abide` of the app as
2736
2775
  the module it compiles to, whether or not `createApp` has run.
@@ -2786,6 +2825,28 @@ the range.
2786
2825
 
2787
2826
  38.124 The project `abide scaffold` writes MUST carry a `bench` script that runs `harness-bench`.
2788
2827
 
2828
+ 38.125 `abide format` MUST hand each `<script>` block and each `<style>` of every `.abide` under the
2829
+ directories named, or under the app where none are, to `bun fmt` as TypeScript and as CSS, under the
2830
+ options `bun fmt` reads for that file, and MUST leave as written a file those options'
2831
+ `ignorePatterns` name.
2832
+
2833
+ 38.126 `abide format` MUST hand each expression a slot, an attribute, a spread, a `{#if}`, a
2834
+ `{:else if}` or a `{#for}` holds to `bun fmt` as an expression, and MUST keep one as written where
2835
+ the printed expression would end the attribute value it stands in.
2836
+
2837
+ 38.127 `abide format` MUST indent the markup by its element and block nesting, and MUST NOT change
2838
+ the template the file parses to: a run 33.17 drops between two nodes MUST NOT gain indentation, and
2839
+ the body of a `<pre>`, a `<textarea>` and a markup `<script>` MUST stay as written.
2840
+
2841
+ 38.128 `abide format` MUST leave as written a file the parser refuses, a file whose formatted text
2842
+ would parse to a different template (38.127), and a piece `bun fmt` refuses, MUST report each on its
2843
+ line, MUST go on formatting the rest, and MUST exit non-zero where it reports one.
2844
+
2845
+ 38.129 `abide format --check` MUST write nothing, and MUST exit non-zero where a file would change.
2846
+
2847
+ 38.130 `abide lsp` MUST answer a formatting request with what `abide format` makes of the text the
2848
+ editor holds.
2849
+
2789
2850
  # 39. Head and view transitions
2790
2851
 
2791
2852
  39.1 A `<head>` element in a `.abide` file MUST contribute its children to the document head.