@abide/abide 0.102.0 → 0.103.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 (67) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/bin/abide.ts +31 -28
  3. package/docs/REGISTRY.md +30 -26
  4. package/docs/RULEBOOK.md +98 -83
  5. package/docs/abide.md +771 -522
  6. package/package.json +2 -1
  7. package/scaffold/AGENTS.md +13 -6
  8. package/src/compiler/TypeSession.ts +110 -35
  9. package/src/compiler/appMap.ts +96 -0
  10. package/src/compiler/argsSchemaOf.ts +1 -1
  11. package/src/compiler/checkApp.ts +35 -18
  12. package/src/compiler/checkedShadow.ts +40 -7
  13. package/src/compiler/compileApp.ts +228 -70
  14. package/src/compiler/compiledEntry.ts +10 -6
  15. package/src/compiler/componentGraph.ts +6 -7
  16. package/src/compiler/declaredExports.ts +3 -3
  17. package/src/compiler/emitClient.ts +3 -3
  18. package/src/compiler/emitComponent.ts +9 -9
  19. package/src/compiler/emitSource.ts +5 -9
  20. package/src/compiler/handlersUnder.ts +114 -73
  21. package/src/compiler/hooksCalled.ts +35 -0
  22. package/src/compiler/mountsOf.ts +30 -18
  23. package/src/compiler/parseAbide.ts +12 -12
  24. package/src/compiler/projectShadow.ts +70 -45
  25. package/src/compiler/readsIn.ts +2 -2
  26. package/src/compiler/scaffold.ts +24 -21
  27. package/src/compiler/serveLanguage.ts +0 -24
  28. package/src/compiler/sharedModuleWrites.ts +2 -2
  29. package/src/compiler/splitImports.ts +4 -4
  30. package/src/compiler/writeDefaultProject.ts +28 -1
  31. package/src/server/MODULE_QUERIES.ts +12 -3
  32. package/src/server/abideModules.ts +117 -51
  33. package/src/server/answerRequest.ts +9 -4
  34. package/src/server/answerRpc.ts +18 -16
  35. package/src/server/appTree.ts +83 -24
  36. package/src/server/commands.ts +5 -4
  37. package/src/server/componentModules.d.ts +1 -2
  38. package/src/server/createApp.ts +23 -11
  39. package/src/server/devWorker.ts +5 -1
  40. package/src/server/fenceServer.ts +36 -13
  41. package/src/server/hooks.ts +17 -4
  42. package/src/server/index.ts +1 -0
  43. package/src/server/installSourceMaps.ts +6 -1
  44. package/src/server/launcherOptions.ts +12 -13
  45. package/src/server/launcherPage.ts +2 -2
  46. package/src/server/nativeMenu.ts +3 -3
  47. package/src/server/preload.ts +13 -0
  48. package/src/server/runDesktop.ts +11 -16
  49. package/src/server/serveDev.ts +8 -2
  50. package/src/server/surfaceOf.ts +2 -0
  51. package/src/server/withAbideSources.ts +1 -1
  52. package/src/shared/ADDRESSES.ts +3 -0
  53. package/src/shared/LAUNCHER_FILES.ts +9 -0
  54. package/src/shared/RESERVED_DIRECTORIES.ts +13 -4
  55. package/src/shared/index.ts +2 -1
  56. package/src/{ui → shared}/menuBridge.ts +1 -1
  57. package/src/shared/menuItem.ts +2 -2
  58. package/src/shared/onMenu.ts +58 -0
  59. package/src/{ui → shared}/reportMenu.ts +7 -9
  60. package/src/shared/routePattern.ts +58 -20
  61. package/src/shared/rpc.ts +1 -1
  62. package/src/ui/Router.ts +0 -6
  63. package/src/compiler/syncTypes.ts +0 -32
  64. package/src/compiler/writeTypes.ts +0 -82
  65. package/src/server/LAUNCHER_FILES.ts +0 -9
  66. /package/scaffold/src/{page.abide → index.abide} +0 -0
  67. /package/src/{compiler → shared}/SPECIFIERS.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @abide/abide
2
2
 
3
+ ## 0.103.0
4
+
5
+ ### Minor Changes
6
+
7
+ - dc5611c: BREAKING: a file is its segment. A page is the `index.abide` in its directory, and `src/invoices/index.abide` answers `/invoices` — `page.abide` is gone. A `.ts` beside the pages is a handler file, its handler its default export (`export default GET(…)`), answering at its own path: `src/invoices/getInvoice.ts` is `/invoices/getInvoice`. A `.abide` no longer exports: a handler a page alone calls is a `const` in its `<script server>`, private, answered below `/__abide/handlers/`, and listed nowhere. Code that is no address lives under a `lib` directory and tests under a `tests` directory, beside the pages they serve; a `.abide` under either is a component whatever it is called, and anything else directly in an address directory fails the build. The desktop launcher's options come from `onLauncher(…)` in `src/launcher.abide`, and a layout's or a page's menus from `onMenu(…)` in its `<script>`, in place of the `launcher` and `menu` exports. `abide sync`, `.abide/types` and the `rootDirs` the scaffold wrote are gone. New: `abide routes` prints every address and hook with the file behind it, and `@abide/abide/test`, preloaded by the scaffold's `bunfig.toml`, lets a test import the app's `.abide` and handler files as modules with nothing booted first.
8
+
9
+ ### Patch Changes
10
+
11
+ - dc5611c: `abide check` reports an export or a top-level `await` in a `.abide` another one imports at that file, rather than stopping, and reports every refusal the whole app raises — a handler file's, two files at one route, a stray `onLauncher` — at the file that raised it. A mounted package's `server` directory is fenced from the browser's bundle as the app's own is. `abide routes` lists a hook called as a member (`server.onStart(…)`). The language server walks the app once per change rather than on every check, and a build no longer reloads the checker's project for each of the app's own handler files. `abide scaffold` writes the test preload's `bunfig.toml` and the `.gitignore` itself, so a packed release cannot drop them, and adds a `routes` script.
12
+
3
13
  ## 0.102.0
4
14
 
5
15
  ### Minor Changes
package/bin/abide.ts CHANGED
@@ -6,14 +6,19 @@ import { existsSync, realpathSync } from 'node:fs' // bun exposes no sync existe
6
6
  import { mkdir, rename, rm } from 'node:fs/promises' // bun exposes no directory creation, rename or recursive directory removal of its own
7
7
  import { dirname, 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
+ import { appMap, mapText } from '#compiler/appMap.ts'
9
10
  import { checkApp } from '#compiler/checkApp.ts'
10
- import { type CompiledApp, compileApp, paints } from '#compiler/compileApp.ts'
11
+ import {
12
+ type CompiledApp,
13
+ compilationOf,
14
+ compileApp,
15
+ paints,
16
+ } from '#compiler/compileApp.ts'
11
17
  import { compiledEntry } from '#compiler/compiledEntry.ts'
12
18
  import { formatDiagnosis } from '#compiler/formatDiagnosis.ts'
13
19
  import { parseAbide } from '#compiler/parseAbide.ts'
14
20
  import { scaffold } from '#compiler/scaffold.ts'
15
21
  import { serveLanguage } from '#compiler/serveLanguage.ts'
16
- import { syncTypes } from '#compiler/syncTypes.ts'
17
22
  import {
18
23
  abideModules,
19
24
  type Compilation,
@@ -40,7 +45,6 @@ import { appRoot, createApp, originUnder } from '#server/createApp.ts'
40
45
  import { executableName } from '#server/executableName.ts'
41
46
  import { fenceServer } from '#server/fenceServer.ts'
42
47
  import { iconAccent } from '#server/iconAccent.ts'
43
- import { ICON_ADDRESSES, LAUNCHER_PAGE } from '#server/LAUNCHER_FILES.ts'
44
48
  import { manifestOf, NO_MANIFEST } from '#server/manifestOf.ts'
45
49
  import { namesUnder } from '#server/namesUnder.ts'
46
50
  import { refuseAddressCollision } from '#server/refuseAddressCollision.ts'
@@ -53,6 +57,7 @@ import {
53
57
  } from '#server/serveBuild.ts'
54
58
  import { serveDev } from '#server/serveDev.ts'
55
59
  import { escapeText } from '#shared/escapeText.ts'
60
+ import { ICON_ADDRESSES, LAUNCHER_PAGE } from '#shared/LAUNCHER_FILES.ts'
56
61
 
57
62
  /** Where the app a command builds or serves is, and where its build goes — both absolute. */
58
63
  type AppDirectories = { root: string; out: string }
@@ -92,7 +97,7 @@ const DISK: Host = {
92
97
  dev: inApp(dev),
93
98
  build: inApp(build),
94
99
  check: inApp(check),
95
- sync: inApp(sync),
100
+ routes: inApp(routes),
96
101
  compile: inApp(compile),
97
102
  bundle: inApp(bundle),
98
103
  lsp,
@@ -127,13 +132,16 @@ async function writeBuild({
127
132
  const app = await compileApp(root)
128
133
  for (const warning of app.warnings)
129
134
  console.warn(formatDiagnosis(warning, process.cwd()))
130
- if (Object.keys(app.files).length === 0) {
135
+ if (
136
+ Object.keys(app.files).length === 0 &&
137
+ Object.keys(app.handlers).length === 0
138
+ ) {
131
139
  console.log(`abide build: no .abide sources or handlers under ${root}`)
132
140
  return undefined
133
141
  }
134
142
  // 38.6 — THE COMPILATION, KEPT WHOLE: `abide start` serves every `.abide` out of it at the
135
143
  // file's own path, with no compiler, and a module's imports resolve from the source they name.
136
- const compilation: Compilation = { files: app.files, tables: app.tables }
144
+ const compilation = compilationOf(app)
137
145
  // 36.11 — the directories above `public` and the path below it ARE the address.
138
146
  // `src/public/favicon.ico` answers at `/favicon.ico`, and nothing declares that anywhere.
139
147
  const publicAddresses = [...app.published.values()]
@@ -145,7 +153,7 @@ async function writeBuild({
145
153
  root,
146
154
  out,
147
155
  [
148
- fenceServer(root),
156
+ fenceServer(root, compilation.mounted),
149
157
  abideModules(root, compilation),
150
158
  ...(await appPlugins(root)),
151
159
  ],
@@ -249,12 +257,13 @@ async function bundle(
249
257
  const hasLauncher = app.files[LAUNCHER_PAGE] !== undefined
250
258
  const art = await launcherIcon(root)
251
259
  return {
252
- // 34.32 — its `launcher` export is read when the app launches, off the module.
253
- launch: hasLauncher ? launcherPath : undefined,
254
- // 38.82 — a `launcher.abide` of its script blocks alone keeps the built-in page.
255
- custom:
260
+ // 38.82 — the page, where it paints: a `launcher.abide` of its script blocks alone keeps
261
+ // the built-in page, and what its `onLauncher` answers is filed by the boot (37.1).
262
+ launch:
256
263
  hasLauncher &&
257
- paints(parseAbide(await Bun.file(launcherPath).text())),
264
+ paints(parseAbide(await Bun.file(launcherPath).text()))
265
+ ? launcherPath
266
+ : undefined,
258
267
  document: launchDocument(app),
259
268
  icon: art?.icon,
260
269
  accent: art?.accent,
@@ -777,6 +786,16 @@ async function scaffoldCommand({
777
786
  return 0
778
787
  }
779
788
 
789
+ /** `abide routes`: the app's map, as text or with `--json` as one document. 38.108. */
790
+ async function routes(
791
+ { root }: AppDirectories,
792
+ { values }: Given,
793
+ ): Promise<number> {
794
+ const map = await appMap(root)
795
+ console.log(values.json ? JSON.stringify(map, null, 4) : mapText(map))
796
+ return 0
797
+ }
798
+
780
799
  /**
781
800
  * `abide check`: prints every finding, and fails on any error.
782
801
  *
@@ -818,22 +837,6 @@ async function check(
818
837
  return errors > 0 ? 1 : 0
819
838
  }
820
839
 
821
- /**
822
- * `abide sync`: writes the types a plain `.ts` reads the app's `.abide` files by.
823
- *
824
- * 34.24 — parse and projection alone, so it is fast enough to run on every install (the scaffold's
825
- * `prepare`), where no checker and no build has run.
826
- */
827
- async function sync({ root }: AppDirectories): Promise<number> {
828
- const { typed, refused } = await syncTypes(root)
829
- for (const diagnosis of refused)
830
- console.error(formatDiagnosis(diagnosis, process.cwd()))
831
- console.log(
832
- `abide sync: ${typed} .abide file${typed === 1 ? '' : 's'} typed`,
833
- )
834
- return refused.length === 0 ? 0 : 1
835
- }
836
-
837
840
  /**
838
841
  * `abide lsp`: the language server over stdio.
839
842
  *
package/docs/REGISTRY.md CHANGED
@@ -57,7 +57,7 @@ Accepted, Failures>` is the inner value's own `Accepted`. Then `Failures`, then
57
57
  | `Failures` | union of `Failed` | What a read hands back in place of a value. | 1.3 |
58
58
  | `Shaped` | `unknown` | What a `transform` hands back: the value to store, or a refusal. | 4.6, 4.9 |
59
59
  | `Produced` | `unknown` | What a production carries, where that differs from what is stored. | 1.2, 9.3 |
60
- | `Args` | `Record<string, JsonValue> \| undefined` | The key of a keyed value. | 9.4, 11.24, 11.25, 11.26, 11.27, 11.29, 11.31, 11.64, 19.16 |
60
+ | `Args` | `Record<string, JsonValue> \| undefined` | The key of a keyed value. | 9.4, 11.24, 11.25, 11.26, 11.27, 11.29, 11.31, 11.64, 19.15 |
61
61
  | `reactive` | `<Computed, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>>(body: () => Computed, options?: Omit<ReactiveOptions<Awaited<Computed>, Kept<Shaped>, never>, 'schema'> & { transform?: (value: Awaited<Computed>) => Shaped; schema?: Gate & Schema<Awaited<Computed>> }) => Reactive<Kept<Shaped>, Awaited<Computed>, AdoptedFailures<Computed> \| Refused<Shaped> \| Gated<Gate, Awaited<Computed>>, AdoptedProduced<Computed, Kept<Shaped>>>` | The unkeyed body overload. | 3.9, 11.1, 11.3, 11.5, 11.7, 11.8, 11.9, 11.10, 11.11, 11.12, 11.13, 11.14, 11.15, 11.16, 11.17, 11.18, 11.19, 11.20, 11.21, 11.22, 11.32, 11.33, 11.50, 11.51, 11.52, 11.53, 11.54, 11.57, 11.58, 41.6, 11.62, 11.63, 11.65, 11.66, 12.14 |
62
62
  | `reactive` | `<Chunk, Shaped = Chunk[], Gate = Schema<Chunk[]>>(body: () => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Omit<ReactiveOptions<Chunk[], Kept<Shaped>, never>, 'schema'> & { transform?: (value: Chunk[]) => Shaped; schema?: Gate & Schema<Chunk[]> }) => Reactive<Kept<Shaped>, Chunk[], Refused<Shaped> \| Gated<Gate, Chunk[]>, Chunk>` | The streaming body overload. | 3.7, 3.8, 4.8, 9.1, 9.2, 9.6, 9.7, 9.8, 9.9 |
63
63
  | `reactive` | `<Chunk, Args, Shaped = Chunk[], Gate = Schema<Chunk[]>, ArgsGate = Schema<Args>>(body: (args: Args) => AsyncGenerator<Chunk> \| Promise<AsyncGenerator<Chunk>>, options?: Omit<ReactiveOptions<Chunk[], Kept<Shaped>, never, Args>, 'schema' \| 'args'> & { transform?: (value: Chunk[]) => Shaped; schema?: Gate & Schema<Chunk[]>; args?: ArgsGate & Schema<Args> }) => Keyed<Kept<Shaped>, Args, Chunk[], Refused<Shaped> \| Gated<Gate, Chunk[]> \| Gated<ArgsGate, Args>, Chunk>` | The keyed streaming body overload. | 9.6, 9.9 |
@@ -212,7 +212,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
212
212
  | `Rpc` | `<Value, Args, Failures, Produced = Value>(args?: Args, options?: { signal?: AbortSignal }) => Reactive<Value, Value, Failures \| Failed<'HttpError', undefined>, Produced>` | A handler reached over http, or in process on a server. | 16.3, 16.4, 16.8, 16.11, 16.25, 16.26, 16.27, 16.28, 16.29, 16.33, 16.43, 16.48, 16.49, 16.62, 41.5, 41.7, 41.12, 41.21, 41.22, 41.25, 41.26, 41.27 |
213
213
  | `Value` | `unknown` | What the addressed `Reactive` holds. | 16.3, 16.30 |
214
214
  | `Produced` | `unknown` | What it yields, per the unit rule. | 1.2, 16.3 |
215
- | `Args` | `Record<string, JsonValue> \| undefined` | The arguments, in the body on a mutation and in the URL on a `GET` or `DELETE`. | 11.24, 16.18, 19.16 |
215
+ | `Args` | `Record<string, JsonValue> \| undefined` | The arguments, in the body on a mutation and in the URL on a `GET` or `DELETE`. | 11.24, 16.18, 19.15 |
216
216
  | `Middleware` | `<Ctx, Result>(next: (ctx?: Ctx) => Promise<Result>, ctx: Ctx) => Result \| Promise<Result>` | One rung of `middleware`. | 16.14, 16.15, 16.16, 16.21 |
217
217
  | `GET` | `<Value, Args, Failures, RungFailures, Produced = Value>(handler: Reactive<Value, Value, Failures, Produced> \| Keyed<Value, Args, Value, Failures, Produced>, options?: RpcOptions<Args, RungFailures>) => Rpc<Value, Args, Failures \| RungFailures, Produced>` | Declares a read any surface may call. | 16.1, 16.2, 16.5, 16.6, 16.30, 16.31, 16.32, 16.68, 16.34, 16.35, 16.36, 16.37, 16.39, 16.44, 16.45, 16.46, 16.47, 16.50, 16.51, 16.52, 16.64, 18.1, 18.3, 18.6, 18.8, 18.10, 18.12, 18.21, 18.24 |
218
218
  | `GET` | `<Value, Args, Failures, RungFailures, Produced = Value>(handler: (args?: Args) => Value, options?: RpcOptions<Args, RungFailures> & ReactiveOptions<Value, Value, Failures, Args>) => Rpc<Value, Args, Failures \| RungFailures, Produced>` | The plain-function overload, whose options build the value it becomes beside its address. | 16.1, 16.6, 16.7 |
@@ -256,21 +256,20 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
256
256
 
257
257
  ## Mount paths
258
258
 
259
- | File | Export | Served at | Rules |
259
+ | File | Declares | Served at | Rules |
260
260
  | --- | --- | --- | --- |
261
- | `users/page.abide` | `getUser` | `/users/getUser` | 16.2, 19.1, 19.21, 23.14 |
262
- | `layout.abide` | `health` | `/health` | 16.2, 23.14 |
263
- | `admin/page.abide` | `recent` | `/admin/recent` | 16.2, 23.14 |
264
- | `media/[id]/page.abide` | `save` | `/media/[id]/save`, `id` reaching its `Args` | 16.2, 16.65, 16.66, 16.67, 16.69 |
265
- | `media/[id]/comments.abide` | `addComment` | `/media/[id]/addComment` | 16.2, 19.1, 23.14 |
261
+ | `users/getUser.ts` | `export default GET(…)` | `/users/getUser` | 16.2, 16.73, 19.1, 19.20, 23.14 |
262
+ | `health.ts` | `export default GET(…)` | `/health` | 16.2, 23.14 |
263
+ | `media/[id]/save.ts` | `export default POST(…)` | `/media/[id]/save`, `id` reaching its `Args` | 16.2, 16.65, 16.66, 16.67, 16.69 |
264
+ | `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 |
266
265
 
267
266
  ## Schemas
268
267
 
269
268
  | Name | Signature | Meaning | Rules |
270
269
  | --- | --- | --- | --- |
271
- | `Schema<T>` | `((value: unknown) => T) \| StandardSchemaV1<T>` | The two forms a shape may be declared in. | 19.2, 19.3, 19.4, 19.6, 19.8, 19.9, 19.10, 19.19, 19.11, 19.12 |
270
+ | `Schema<T>` | `((value: unknown) => T) \| StandardSchemaV1<T>` | The two forms a shape may be declared in. | 19.2, 19.3, 19.4, 19.6, 19.8, 19.9, 19.10, 19.18, 19.11, 19.12 |
272
271
  | `JsonValue` | `null \| boolean \| number \| string \| JsonValue[] \| { [k: string]: JsonValue }` | What an `Args` may hold. | — |
273
- | `Issues<T>` | `T extends object ? Partial<Record<Paths<T> \| '', string[]>> : string[]` | What was wrong, keyed by where. | 19.4, 19.20 |
272
+ | `Issues<T>` | `T extends object ? Partial<Record<Paths<T> \| '', string[]>> : string[]` | What was wrong, keyed by where. | 19.4, 19.19 |
274
273
  | `Paths<T>` | `string` | The dot-joined leaf paths of a type. | 19.5 |
275
274
  | `JsonSchema` | `JsonValue` | A JSON Schema document, the native form. | 19.7, 19.14 |
276
275
  | `jsonSchema` | `<T>(document: JsonSchema) => StandardSchemaV1<T>` | A JSON Schema document as a `Schema`, carrying its validator. | 19.13, 19.14, 20.11 |
@@ -370,7 +369,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
370
369
 
371
370
  | Name | Signature | Meaning | Rules |
372
371
  | --- | --- | --- | --- |
373
- | `route.url` | `Reactive<URL>` | Where we are. | 23.1, 23.2, 23.3, 23.4, 30.23, 19.17, 31.16 |
372
+ | `route.url` | `Reactive<URL>` | Where we are. | 23.1, 23.2, 23.3, 23.4, 30.23, 19.16, 31.16 |
374
373
  | `route.params` | `Reactive<Params>` | The matched route's segments. | 23.1, 23.5, 23.9, 30.23, 31.16 |
375
374
  | `Params` | `Record<string, string \| string[]>` | What a matched route's segments are. | 23.5 |
376
375
  | `route.name` | `Reactive<string>` | The resolution path. | 23.1, 23.6, 31.16 |
@@ -582,9 +581,9 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
582
581
 
583
582
  | Spelling | Meaning | Rules |
584
583
  | --- | --- | --- |
585
- | `<script>` | Per-instance component setup. | 14.7, 34.1, 34.3, 34.12, 34.13, 34.14, 34.15, 34.18, 34.34, 34.35 |
586
- | `<script module>` | Module scope. | 34.2, 34.3, 34.12, 34.14, 34.15, 34.17, 34.19, 34.24, 34.25, 34.35 |
587
- | `<script server>` | Module scope on a server alone, exporting the file's handlers. | 16.28, 19.15, 19.22, 34.3, 34.12, 34.20, 34.21, 34.22, 34.23, 34.24, 34.26, 34.33, 34.34, 34.35, 37.1 |
584
+ | `<script>` | Per-instance component setup. | 14.7, 34.1, 34.3, 34.12, 34.13, 34.14, 34.15, 34.17, 34.29, 34.30 |
585
+ | `<script module>` | Module scope. | 34.2, 34.3, 34.12, 34.14, 34.15, 34.17, 34.18, 34.21, 34.30 |
586
+ | `<script server>` | Module scope on a server alone, declaring its file's private handlers and filing its hooks. | 16.28, 16.70, 34.3, 34.12, 34.17, 34.19, 34.20, 34.22, 34.28, 34.29, 34.30, 37.1 |
588
587
  | `<style>` | Component-scoped styles. | 34.4, 34.5, 34.10, 34.11 |
589
588
  | `import './app.css'` | A stylesheet the component depends on. | 34.6 |
590
589
  | `:global(…)` | The per-selector escape from scoping. | 34.5 |
@@ -625,7 +624,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
625
624
  | Name | Type | Meaning | Rules |
626
625
  | --- | --- | --- | --- |
627
626
  | `PORT` | `number` | The listen port. | 36.1, 38.63, 38.64 |
628
- | `APP_URL` | `string \| null` | The app's public URL. | 36.2, 19.18 |
627
+ | `APP_URL` | `string \| null` | The app's public URL. | 36.2, 19.17 |
629
628
  | `NODE_ENV` | `string` | The environment name, verbatim. | 36.3, 36.16 |
630
629
  | `APP_NAME` | `string` | The app's name, and `log`'s default namespace. | 27.3, 28.4 |
631
630
  | `APP_VERSION` | `string` | The version beside that name. | 27.3 |
@@ -649,19 +648,24 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
649
648
  | --- | --- | --- |
650
649
  | `src/**` | The app's source. | 36.10, 38.25 |
651
650
  | `**/server/**` | Source the browser never loads. | 16.29, 23.15, 23.16, 23.18, 36.10 |
651
+ | `**/lib/**` | The app's code that is no address: components and modules, on both sides. | 23.15, 23.16, 23.18, 23.22, 37.1 |
652
+ | `**/tests/**` | The app's tests. | 23.15, 23.16, 23.18, 23.22, 37.1, 38.109 |
652
653
  | `**/public/**` | The files answered as authored, at their path below that directory. | 23.15, 23.16, 23.18, 36.11, 36.12, 36.13, 36.14, 36.15, 36.17, 21.12, 21.13, 21.14, 38.18, 38.19 |
653
654
  | `src/public/favicon.ico` | The file answered at `/favicon.ico`. | 36.11 |
654
655
  | `src/public/robots.txt` | The file answered at `/robots.txt`. | 36.11 |
655
656
  | `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 |
656
- | `src/**/` | A directory of the app's, a segment of the route its `page.abide`, `layout.abide` and `error.abide` answer at. | 23.14, 23.17 |
657
- | `**/page.abide` | A route: its page, and the handlers its `<script server>` exports. | 16.2, 19.1, 23.3, 23.4 |
657
+ | `src/**/` | A directory of the app's, a segment of the route of every file directly in it. | 23.14, 23.17, 23.22 |
658
+ | `**/index.abide` | The page at its directory's route. | 19.1, 23.3, 23.4, 23.14, 23.18 |
659
+ | `**/<name>.abide` | The page at its directory's route and then `<name>`. | 19.1, 23.3, 23.4, 23.14, 23.21 |
660
+ | `**/<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 |
658
661
  | `**/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 |
659
- | `src/launcher.abide` | The desktop launcher, beside the root layout: the `launcher` options its `<script module>` exports, and its page in place of the launcher's own where it has markup. | 38.80, 38.82, 38.84, 38.85 |
662
+ | `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 |
660
663
  | `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 |
661
664
  | `**/error.abide` | The page a refusal renders in. | 35.2, 35.3, 35.14 |
662
- | `**/node_modules/**/*.abide` | A component a dependency ships as source, compiled with the app that imports it. | 34.27, 34.28, 34.29, 34.30, 34.31, 38.99 |
663
- | `import '…' with { type: 'routes' }` | A package's directory mounted at the importing file's directory, its pages, layouts, error pages and handlers answering below it. | 23.19, 23.20 |
665
+ | `**/node_modules/**/*.abide` | A component a dependency ships as source, compiled with the app that imports it. | 34.23, 34.24, 34.25, 34.26, 34.27, 38.99 |
666
+ | `import '…' with { type: 'routes' }` | A package's directory mounted at the importing file's directory, its pages, layouts, error pages and handler files answering below it. | 23.19, 23.20 |
664
667
  | `bunfig.toml` | The file whose `[serve.static] plugins` the client is built with. | 38.43 |
668
+ | `preload = ["@abide/abide/test"]` | The `[test]` preload a test imports the app's `.abide` files through. | 38.109 |
665
669
 
666
670
  ## Lifecycle hooks
667
671
 
@@ -674,17 +678,17 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
674
678
  | `onConfig` | `(fn: ConfigDefaults \| null, options?: ConfigOptions) => () => void` | The app's config defaults. | 27.6, 37.7 |
675
679
  | `onHealth` | `(report: () => unknown \| Promise<unknown>) => () => void` | The app's health reporter. | 25.2, 37.7 |
676
680
  | `onPrincipal` | `(resolve: (claims: unknown) => unknown \| Promise<unknown>) => () => void` | Turns claims into the app's half of a principal. | 26.4, 37.7 |
681
+ | `onLauncher` | `(options: () => LauncherOptions) => () => void` | The window the desktop app opens and the forms its launcher offers. | 38.80, 38.81, 38.83, 38.86, 38.102, 38.107 |
677
682
 
678
683
  ## The desktop app
679
684
 
680
685
  | Name | Signature | Meaning | Rules |
681
686
  | --- | --- | --- | --- |
682
- | `launcher` | `LauncherOptions` | The window the desktop app opens and the forms its launcher offers, exported from `src/launcher.abide`'s `<script module>`. | 34.32, 38.80, 38.83, 38.86 |
683
- | `LauncherOptions` | `{ width?: number; height?: number; minWidth?: number; minHeight?: number } & ({ start?: true; connect?: boolean } \| { start: false; connect?: true })` | What the `launcher` export may set. | 38.80, 38.81 |
684
- | `menu` | `MenuItem[]` | The menus a layout or a page adds to the desktop app's menu bar, exported from its `<script module>`. | 34.32, 38.88, 38.92 |
687
+ | `LauncherOptions` | `{ width?: number; height?: number; minWidth?: number; minHeight?: number } & ({ start?: true; connect?: boolean } \| { start: false; connect?: true })` | What an `onLauncher` may answer. | 38.80, 38.81 |
688
+ | `onMenu` | `(read: () => readonly MenuItem[]) => () => void` | The menus a layout or a page adds to the desktop app's menu bar while it stands. | 38.88, 38.92 |
685
689
  | `MenuItem` | `'separator' \| MenuEntry \| { label: string; key?: string; role?: MenuRole; href?: string; items?: MenuItem[] }` | One entry in the menu bar or in a menu under it. | 38.89, 38.90 |
686
690
  | `MenuRole` | `'about' \| 'hide' \| 'hideOthers' \| 'showAll' \| 'quit' \| 'connect' \| 'disconnect' \| 'close' \| 'undo' \| 'redo' \| 'cut' \| 'copy' \| 'paste' \| 'selectAll' \| 'reload' \| 'fullscreen' \| 'minimize' \| 'zoom' \| 'front'` | What a menu item does natively. | 38.74, 38.89 |
687
- | `menuItem` | `(item: { label: string; key?: string; href?: string }) => MenuEntry` | A menu item the page that exports it answers. | 38.91 |
691
+ | `menuItem` | `(item: { label: string; key?: string; href?: string }) => MenuEntry` | A menu item the page that files it answers. | 38.91 |
688
692
  | `MenuEntry` | `class MenuEntry { label: string; key: string \| undefined; href: string \| undefined }` | What `menuItem` makes. | 38.91 |
689
693
  | `MenuEntry.on` | `(answer: () => unknown) => () => void` | Files a function run each time the item is picked. | 38.91 |
690
694
  | `Launch` | `{ name: string; start: string \| undefined; connect: string \| undefined; fields: ConfigField[]; url: string; failure: { form: 'start' \| 'connect'; message: string; issues: Record<string, string[]> } \| undefined; focus: 'start' \| 'connect' \| undefined; icon: string \| undefined; accent: string \| undefined }` | The props a launch page is rendered with. | 38.82, 38.83, 38.87, 38.101 |
@@ -710,8 +714,8 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
710
714
  | --- | --- | --- |
711
715
  | `abide scaffold <name>` | Writes a starter project. | 38.1, 38.42, 38.103, 38.104, 38.106 |
712
716
  | `abide run <file> [args…]` | Runs a script under the abide runtime. | 38.2, 38.57 |
713
- | `abide check [dir…]` | The type-checker over a `.abide` tree. | 38.3, 38.31, 38.32, 38.33, 38.40, 34.24, 38.105 |
714
- | `abide sync` | Writes the types a `.ts` reads a `.abide` by. | 34.24 |
717
+ | `abide check [dir…]` | The type-checker over a `.abide` tree. | 38.3, 38.31, 38.32, 38.33, 38.40, 38.105 |
718
+ | `abide routes [--json]` | Every address the app answers, the file answering it, and where each hook is filed. | 38.108 |
715
719
  | `abide dev [--port <n>]` | Watches the project and keeps the app up. | 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 |
716
720
  | `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 |
717
721
  | `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 |