@abide/abide 0.103.0 → 0.105.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 (88) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/bin/abide.ts +80 -173
  3. package/docs/REGISTRY.md +27 -27
  4. package/docs/RULEBOOK.md +68 -24
  5. package/docs/abide.md +31 -46
  6. package/package.json +1 -1
  7. package/src/compiler/Lowering.ts +15 -5
  8. package/src/compiler/Refusals.ts +57 -0
  9. package/src/compiler/TypeSession.ts +46 -89
  10. package/src/compiler/appLayout.ts +447 -0
  11. package/src/compiler/appMap.ts +21 -25
  12. package/src/compiler/checkApp.ts +61 -97
  13. package/src/compiler/checkedShadow.ts +12 -10
  14. package/src/compiler/classifyRead.ts +3 -6
  15. package/src/compiler/compileApp.ts +183 -478
  16. package/src/compiler/componentGraph.ts +2 -71
  17. package/src/compiler/declaredExports.ts +79 -60
  18. package/src/compiler/emitClient.ts +11 -13
  19. package/src/compiler/emitComponent.ts +21 -6
  20. package/src/compiler/emitSource.ts +20 -20
  21. package/src/compiler/handlersUnder.ts +46 -36
  22. package/src/compiler/hookCalls.ts +152 -0
  23. package/src/compiler/mountsOf.ts +31 -54
  24. package/src/compiler/projectShadow.ts +1 -1
  25. package/src/compiler/readSources.ts +27 -42
  26. package/src/compiler/readsIn.ts +5 -16
  27. package/src/compiler/resolverIn.ts +77 -0
  28. package/src/server/abideModules.ts +152 -146
  29. package/src/server/answerRequest.ts +18 -4
  30. package/src/server/answerSocket.ts +136 -76
  31. package/src/server/answerValue.ts +28 -15
  32. package/src/server/appTree.ts +59 -73
  33. package/src/server/claudeApi.ts +2 -5
  34. package/src/server/clientBundle.ts +198 -0
  35. package/src/server/coerceArgs.ts +1 -1
  36. package/src/server/commands.ts +93 -57
  37. package/src/server/createApp.ts +90 -16
  38. package/src/server/deferredBuilds.ts +175 -0
  39. package/src/server/devWorker.ts +107 -319
  40. package/src/server/faceOf.ts +120 -0
  41. package/src/server/fenceServer.ts +10 -18
  42. package/src/server/generatedSurfaces.ts +12 -53
  43. package/src/server/index.ts +3 -0
  44. package/src/server/placement.ts +167 -0
  45. package/src/server/remote.ts +14 -42
  46. package/src/server/render.ts +25 -17
  47. package/src/server/renderComponent.ts +9 -5
  48. package/src/server/requestScope.ts +10 -4
  49. package/src/server/responseRelay.ts +389 -0
  50. package/src/server/runCompiled.ts +9 -12
  51. package/src/server/runDesktop.ts +6 -9
  52. package/src/server/serveBuild.ts +26 -73
  53. package/src/server/serveDev.ts +19 -176
  54. package/src/server/streamEvent.ts +29 -0
  55. package/src/server/versionOf.ts +1 -2
  56. package/src/server/withAbideSources.ts +2 -1
  57. package/src/shared/HandlerRoute.ts +68 -0
  58. package/src/shared/REFUSAL_KEY.ts +5 -0
  59. package/src/shared/RESERVED_DIRECTORIES.ts +6 -0
  60. package/src/shared/answerOf.ts +105 -78
  61. package/src/shared/filledPath.ts +1 -9
  62. package/src/shared/framing.ts +127 -128
  63. package/src/shared/queryText.ts +15 -7
  64. package/src/shared/reactive/Cursor.ts +69 -124
  65. package/src/shared/reactive/Reactive.ts +296 -162
  66. package/src/shared/reactive/callLoad.ts +4 -18
  67. package/src/shared/reactive/index.ts +11 -8
  68. package/src/shared/reactive/pairReactive.ts +1 -1
  69. package/src/shared/reactive/scoped.ts +4 -3
  70. package/src/shared/reactive/share.ts +11 -1
  71. package/src/shared/routePattern.ts +0 -110
  72. package/src/shared/rpc.ts +17 -24
  73. package/src/shared/rpcRequest.ts +18 -47
  74. package/src/shared/takeEarlyCall.ts +12 -37
  75. package/src/shared/url.ts +1 -1
  76. package/src/ui/Level.ts +276 -0
  77. package/src/ui/List.ts +17 -17
  78. package/src/ui/Router.ts +20 -87
  79. package/src/ui/applyHead.ts +92 -79
  80. package/src/ui/index.ts +4 -2
  81. package/src/ui/reconcile.ts +4 -110
  82. package/src/ui/rows.ts +123 -2
  83. package/src/ui/wire.ts +12 -27
  84. package/src/compiler/hooksCalled.ts +0 -35
  85. package/src/server/clientBuildOptions.ts +0 -54
  86. package/src/server/refuseAddressCollision.ts +0 -37
  87. package/src/shared/reactive/chunksOfStream.ts +0 -57
  88. package/src/ui/MOUNTING_LEVEL.ts +0 -18
@@ -1,54 +0,0 @@
1
- import { CLIENT_ADDRESS } from '#shared/ADDRESSES.ts'
2
- import { tablePath } from './abideModules.ts'
3
- import { CLIENT_ENTRY } from './CLIENT_BUILD.ts'
4
-
5
- /**
6
- * The `Bun.build` options for the client bundle both lanes build.
7
- *
8
- * `abide build` builds it to disk and `abide dev` in memory. 30.8 says dev resolves an address the
9
- * way the built app does, so what decides resolution is written once here and each lane adds only
10
- * where the output goes and how it is named.
11
- */
12
- export function clientBuildOptions(
13
- root: string,
14
- plugins: Bun.BunPlugin[],
15
- publicAddresses: string[],
16
- ) {
17
- return {
18
- // The entry is a table the plugin serves (`abideModules`), below the root.
19
- entrypoints: [tablePath(root, `${CLIENT_ENTRY}.ts`)] as string[],
20
- // The app's own root, because `Bun.build` opens the entry's directory otherwise, and the
21
- // tables' is not on disk to open.
22
- root,
23
- // 16.28, 16.29 — a `<script server>` is its stand-ins here, and a `server/` module refuses.
24
- plugins,
25
- target: 'browser',
26
- format: 'esm',
27
- splitting: true,
28
- metafile: true,
29
- // 36.15 — a stylesheet's `url('/fonts/…')` is the public file's address, not a path here,
30
- // and `Bun.build` reads a leading `/` as a path on this disk and fails on it not being
31
- // there. The list is the files that exist rather than every `/…`: a URL naming nothing the
32
- // app serves is still worth a build error.
33
- external: publicAddresses,
34
- } as const
35
- }
36
-
37
- // From the bundle's own directory up to the app's root: `../../` below `/__abide/client`.
38
- const UP_TO_ROOT = '../'.repeat(CLIENT_ADDRESS.split('/').length - 1)
39
-
40
- /**
41
- * A built stylesheet with every root-absolute `url()` written relative to the bundle's directory.
42
- *
43
- * 16.10, 36.15 — THE SAME MECHANISM AS THE HANDLER WRAPPERS: the address is written relative to
44
- * where the bundle is served and the browser resolves it against the sheet, so one build serves
45
- * at the root and below a mount. What survives the build as `url(/…)` is a public file's address
46
- * (the `external` list above), and the browser would resolve it against the origin. `//` is
47
- * another host's.
48
- */
49
- export function stylesheetUnderMount(css: string): string {
50
- return css.replace(
51
- /url\((["']?)\/(?!\/)/g,
52
- (_whole, quote: string) => `url(${quote}${UP_TO_ROOT}`,
53
- )
54
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * Throws, naming both, when a public file claims a route's address or another public file's.
3
- *
4
- * 36.13 — the walks that find routes and public files cannot see each other's collisions from
5
- * inside either one; this is the one place they meet, and naming BOTH is the clause — naming one
6
- * leaves the reader to find the other. Two `public` directories can claim one address too, since
7
- * each mounts at the path above it (36.11).
8
- *
9
- * THE BUILD AND DEV, and `abide start` trusts the build: `answerRequest` answers a public file
10
- * AHEAD of any route on the ground that 36.13 makes a collision impossible at run time, and 30.8
11
- * says dev must resolve an address the way the built app does.
12
- *
13
- * `published` is each public file's source path to its address, as `appTree` reads them.
14
- */
15
- export function refuseAddressCollision(
16
- pages: readonly { pattern: string }[],
17
- handlers: readonly { address: string }[],
18
- published: Map<string, string>,
19
- command: string,
20
- ): void {
21
- const patterns = new Set<string>()
22
- for (const page of pages) patterns.add(page.pattern)
23
- for (const handler of handlers) patterns.add(handler.address)
24
- const claimed = new Map<string, string>()
25
- for (const [source, address] of published) {
26
- if (patterns.has(address))
27
- throw new Error(
28
- `${command}: ${source} and the route ${address} claim the same address. RULEBOOK 36.13.`,
29
- )
30
- const other = claimed.get(address)
31
- if (other !== undefined)
32
- throw new Error(
33
- `${command}: ${other} and ${source} are both answered at ${address}. RULEBOOK 36.13.`,
34
- )
35
- claimed.set(address, source)
36
- }
37
- }
@@ -1,57 +0,0 @@
1
- import { isFailed } from '../Failed.ts'
2
- import { chunksFrom } from './Reactive.ts'
3
-
4
- /**
5
- * The chunks of a streaming value, as they land, ending when its run closes.
6
- *
7
- * The live cursor is the wake and not the source: a cursor outlives the run (it waits on the next
8
- * one), and a chunk landing in the same turn as the close could be lost to whichever settled first
9
- * — so each wake sends what the accumulation holds past what has already gone, and the close sends
10
- * the rest.
11
- */
12
- export async function* chunksOfStream(value: unknown): AsyncGenerator<unknown> {
13
- const stream = value as PromiseLike<unknown> & AsyncIterable<unknown>
14
- let closed = false
15
- let failure: unknown
16
- // ONE REACTION ON THE CLOSE FOR THE WHOLE STREAM, which wakes whichever wait is current. A
17
- // `Promise.race` against the close per chunk left one reaction per chunk on it, held until the
18
- // stream ended.
19
- let wake: () => void = () => {}
20
- void Promise.resolve(stream).then(
21
- () => {
22
- closed = true
23
- wake()
24
- },
25
- (error: unknown) => {
26
- closed = true
27
- failure = error
28
- wake()
29
- },
30
- )
31
- const cursor = stream[Symbol.asyncIterator]()
32
- let sent = 0
33
- let woken = cursor.next()
34
- try {
35
- for (;;) {
36
- if (!closed)
37
- await new Promise<void>((resolve, reject) => {
38
- wake = resolve
39
- woken.then(() => resolve(), reject)
40
- })
41
- for (const chunk of chunksFrom(value, sent)) {
42
- sent += 1
43
- yield chunk
44
- }
45
- if (closed) break
46
- woken = cursor.next()
47
- }
48
- } finally {
49
- void cursor.return?.(undefined)
50
- }
51
- if (failure !== undefined) throw failure
52
- // 16.59, 16.60 — A RUN ENDED BY ITS TIMEOUT SETTLES with the chunks it had and holds its refusal
53
- // rather than rejecting, so the refusal is read off the value and thrown after them: a stream
54
- // answered over http then ends on it (16.68) rather than as though it had finished.
55
- const held = (value as { error?: () => unknown }).error?.()
56
- if (isFailed(held)) throw held
57
- }
@@ -1,18 +0,0 @@
1
- // 39.1, 39.6 — THE ROUTER'S LEVEL BEING MOUNTED, set by the router around a page's or a layout's
2
- // setup and markup: a component mounted inside one adds its `<head>` to that level's
3
- // (`contributeHead`), and one mounted later — a row a list grew by — finds none and leaves the
4
- // document's head alone. `unapplied` is the head the components built on the client contributed
5
- // while it was set, which the router applies once it is unset rather than once a component.
6
- export const MOUNTING_LEVEL: {
7
- current:
8
- | {
9
- head: (() => string) | undefined
10
- /** Every component head joined to the level's own, in the order they mounted. */
11
- contributed: (() => string)[] | undefined
12
- }
13
- | undefined
14
- unapplied: string
15
- } = {
16
- current: undefined,
17
- unapplied: '',
18
- }