@abide/abide 0.101.0 → 0.102.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 (157) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/bin/abide.ts +223 -164
  3. package/docs/REGISTRY.md +726 -0
  4. package/docs/RULEBOOK.md +2753 -0
  5. package/docs/abide.md +12878 -0
  6. package/package.json +5 -3
  7. package/scaffold/AGENTS.md +31 -0
  8. package/scaffold/CLAUDE.md +1 -0
  9. package/scaffold/src/layout.abide +18 -0
  10. package/src/compiler/Lowering.ts +78 -9
  11. package/src/compiler/ShadowMap.ts +2 -2
  12. package/src/compiler/TypeSession.ts +262 -67
  13. package/src/compiler/argsSchemaOf.ts +1 -1
  14. package/src/compiler/checkApp.ts +43 -15
  15. package/src/compiler/checkedShadow.ts +39 -5
  16. package/src/compiler/classifyRead.ts +6 -4
  17. package/src/compiler/classifyTemplate.ts +1 -1
  18. package/src/compiler/compileApp.ts +433 -193
  19. package/src/compiler/compiledEntry.ts +43 -39
  20. package/src/compiler/componentGraph.ts +58 -71
  21. package/src/compiler/declaredExports.ts +24 -7
  22. package/src/compiler/emitClient.ts +141 -71
  23. package/src/compiler/emitComponent.ts +37 -8
  24. package/src/compiler/emitSource.ts +106 -13
  25. package/src/compiler/handlersUnder.ts +106 -59
  26. package/src/compiler/index.ts +7 -0
  27. package/src/compiler/mountsOf.ts +138 -0
  28. package/src/compiler/nearest.ts +14 -0
  29. package/src/compiler/parseAbide.ts +157 -20
  30. package/src/compiler/projectShadow.ts +213 -7
  31. package/src/compiler/reactiveTypes.ts +20 -7
  32. package/src/compiler/readSources.ts +15 -2
  33. package/src/compiler/readsIn.ts +61 -7
  34. package/src/compiler/renderMarkup.ts +3 -3
  35. package/src/compiler/scaffold.ts +30 -11
  36. package/src/compiler/serveLanguage.ts +125 -34
  37. package/src/compiler/sourceMapOf.ts +193 -0
  38. package/src/compiler/splitImports.ts +205 -83
  39. package/src/compiler/syncTypes.ts +32 -0
  40. package/src/compiler/tokenize.ts +14 -0
  41. package/src/compiler/writeDefaultProject.ts +1 -1
  42. package/src/compiler/writeTypes.ts +82 -0
  43. package/src/server/CLIENT_BUILD.ts +11 -13
  44. package/src/server/DEFAULT_PORT.ts +1 -1
  45. package/src/server/LAUNCHER_FILES.ts +9 -0
  46. package/src/server/MODULE_QUERIES.ts +18 -0
  47. package/src/server/TABLES.ts +7 -0
  48. package/src/server/VIRTUAL_DIRECTORY.ts +4 -5
  49. package/src/server/abideModules.ts +391 -0
  50. package/src/server/answerFailure.ts +16 -6
  51. package/src/server/answerRequest.ts +235 -106
  52. package/src/server/answerRpc.ts +102 -30
  53. package/src/server/answerSocket.ts +65 -20
  54. package/src/server/answerValue.ts +22 -9
  55. package/src/server/appDirectories.ts +1 -1
  56. package/src/server/appPlugins.ts +1 -1
  57. package/src/server/appTree.ts +179 -0
  58. package/src/server/argsFor.ts +2 -2
  59. package/src/server/assistant.ts +2 -2
  60. package/src/server/bridgeRelay.ts +6 -8
  61. package/src/server/claudeCode.ts +0 -6
  62. package/src/server/clientBuildOptions.ts +8 -3
  63. package/src/server/coerceArgs.ts +1 -1
  64. package/src/server/commands.ts +37 -37
  65. package/src/server/componentModules.d.ts +3 -1
  66. package/src/server/compressAnswer.ts +4 -4
  67. package/src/server/config.ts +25 -29
  68. package/src/server/configFields.ts +31 -25
  69. package/src/server/createApp.ts +59 -73
  70. package/src/server/devWorker.ts +114 -181
  71. package/src/server/executableName.ts +4 -0
  72. package/src/server/fenceServer.ts +37 -35
  73. package/src/server/generatedSurfaces.ts +99 -66
  74. package/src/server/hooks.ts +124 -52
  75. package/src/server/iconAccent.ts +191 -0
  76. package/src/server/index.ts +11 -7
  77. package/src/server/installSourceMaps.ts +88 -0
  78. package/src/server/launcherOptions.ts +34 -31
  79. package/src/server/launcherPage.ts +107 -64
  80. package/src/server/manifestOf.ts +16 -13
  81. package/src/server/namesUnder.ts +2 -2
  82. package/src/server/nativeMenu.ts +5 -5
  83. package/src/server/negotiateEncoding.ts +1 -1
  84. package/src/server/principal.ts +10 -5
  85. package/src/server/realOrAsGiven.ts +10 -0
  86. package/src/server/refuseAddressCollision.ts +21 -14
  87. package/src/server/remote.ts +49 -52
  88. package/src/server/render.ts +65 -94
  89. package/src/server/renderComponent.ts +5 -0
  90. package/src/server/reportHealth.ts +2 -2
  91. package/src/server/requestScope.ts +12 -1
  92. package/src/server/runBuild.ts +24 -0
  93. package/src/server/runCompiled.ts +5 -5
  94. package/src/server/runDesktop.ts +52 -27
  95. package/src/server/serveBuild.ts +43 -52
  96. package/src/server/serveDev.ts +73 -37
  97. package/src/server/shell.ts +7 -22
  98. package/src/server/sourceMappings.ts +139 -0
  99. package/src/server/surfaceOf.ts +18 -3
  100. package/src/server/testBuild.ts +1 -19
  101. package/src/server/withAbideSources.ts +117 -0
  102. package/src/shared/ADDRESSES.ts +7 -18
  103. package/src/shared/APP_META.ts +7 -0
  104. package/src/shared/CopyOptions.ts +1 -1
  105. package/src/shared/DEBUG_META.ts +1 -1
  106. package/src/shared/RESERVED_DIRECTORIES.ts +15 -0
  107. package/src/shared/cookies.ts +2 -2
  108. package/src/shared/csp.ts +1 -1
  109. package/src/shared/escapeText.ts +1 -1
  110. package/src/shared/filledPath.ts +85 -0
  111. package/src/shared/framing.ts +79 -6
  112. package/src/shared/headKeyOf.ts +2 -0
  113. package/src/shared/index.ts +1 -1
  114. package/src/shared/log.ts +27 -13
  115. package/src/shared/matchRoute.ts +23 -4
  116. package/src/shared/menuItem.ts +3 -3
  117. package/src/shared/reactive/Keyed.ts +2 -2
  118. package/src/shared/reactive/NotLanded.ts +1 -1
  119. package/src/shared/reactive/Reactive.ts +43 -43
  120. package/src/shared/reactive/argsContract.ts +4 -4
  121. package/src/shared/reactive/canonicalKey.ts +4 -4
  122. package/src/shared/reactive/chunksOfStream.ts +6 -0
  123. package/src/shared/reactive/index.ts +1 -1
  124. package/src/shared/reactive/recordWrites.ts +103 -5
  125. package/src/shared/reactive/structural.ts +1 -1
  126. package/src/shared/reactive/tracking.ts +1 -1
  127. package/src/shared/reactive/watch.ts +3 -3
  128. package/src/shared/refuse.ts +1 -1
  129. package/src/shared/routePattern.ts +82 -46
  130. package/src/shared/rpc.ts +37 -8
  131. package/src/shared/rpcRequest.ts +27 -3
  132. package/src/shared/url.ts +4 -44
  133. package/src/shared/writePath.ts +1 -1
  134. package/src/ui/LAYER_NAMES.ts +1 -1
  135. package/src/ui/List.ts +3 -3
  136. package/src/ui/MOUNTING_LEVEL.ts +18 -0
  137. package/src/ui/Mismatch.ts +1 -1
  138. package/src/ui/RawRun.ts +1 -1
  139. package/src/ui/Router.ts +38 -31
  140. package/src/ui/Scope.ts +1 -1
  141. package/src/ui/TryRegion.ts +2 -2
  142. package/src/ui/applyHead.ts +33 -0
  143. package/src/ui/index.ts +1 -1
  144. package/src/ui/menuBridge.ts +1 -1
  145. package/src/ui/moveNode.ts +1 -1
  146. package/src/ui/reconcile.ts +2 -2
  147. package/src/ui/reportMenu.ts +2 -2
  148. package/src/ui/routing.ts +2 -2
  149. package/src/ui/setAttribute.ts +1 -1
  150. package/src/ui/setText.ts +1 -1
  151. package/src/ui/socketWire.ts +9 -7
  152. package/src/ui/wire.ts +1 -1
  153. package/scaffold/src/server/app.ts +0 -6
  154. package/scaffold/src/shared/.gitkeep +0 -0
  155. package/scaffold/src/ui/app.html +0 -8
  156. package/src/server/componentImports.ts +0 -56
  157. /package/scaffold/src/{ui/pages/page.abide → page.abide} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abide/abide",
3
- "version": "0.101.0",
3
+ "version": "0.102.0",
4
4
  "type": "module",
5
5
  "description": "Isomorphic type-safe framework for reactive async interfaces for humans and machines",
6
6
  "license": "MIT",
@@ -25,7 +25,7 @@
25
25
  "cli"
26
26
  ],
27
27
  "engines": {
28
- "bun": ">=1.3.0"
28
+ "bun": ">=1.4.3"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public",
@@ -62,12 +62,14 @@
62
62
  "typescript": "^7.0.2"
63
63
  },
64
64
  "scripts": {
65
- "typecheck": "tsc -p tsconfig.json"
65
+ "typecheck": "bun check",
66
+ "prepack": "bun ../../scripts/packDocs.ts"
66
67
  },
67
68
  "files": [
68
69
  "src",
69
70
  "bin",
70
71
  "scaffold",
72
+ "docs",
71
73
  "CHANGELOG.md"
72
74
  ]
73
75
  }
@@ -0,0 +1,31 @@
1
+ # Working on this app
2
+
3
+ This is an abide app. abide is newer than any model's training data, so read its documentation
4
+ before writing code, rather than guessing from Svelte, Vue or React. It installs with the package:
5
+
6
+ - `node_modules/@abide/abide/docs/abide.md` — every documentation page in reading order, with a
7
+ working example for each task. It is long: read its Contents, then search for the page's
8
+ address, which heads each page as a comment — `<!-- values/show-a-value-that-changes.md -->`.
9
+ - `node_modules/@abide/abide/docs/REGISTRY.md` — every name an app can import or write, with its
10
+ signature and the rules that govern it.
11
+ - `node_modules/@abide/abide/docs/RULEBOOK.md` — every rule, numbered. A compiler or server
12
+ message that ends in `RULEBOOK 23.16.` names a clause in this file — search it for `23.16`.
13
+
14
+ ## Checking your work
15
+
16
+ - `bun run check` — runs `abide check`, the type checker over `.abide` files. `tsc` and an editor's
17
+ TypeScript service do not read `.abide` files, so a clean `tsc` says nothing about them. Run
18
+ `bun run check` after every change, and treat its warnings as bugs: several of them name a read
19
+ that will not update when its value changes.
20
+ - `bun run dev` — serves the app on a local port and rebuilds when a file changes.
21
+ - `bun run build` then `bun run start` — the production build, and the app served from it.
22
+
23
+ ## Layout
24
+
25
+ - Every directory under `src/` is an address: `src/invoices/page.abide` answers `/invoices`.
26
+ `layout.abide` wraps the pages below it, and the outermost one writes `<html>`.
27
+ - A module under a `server` directory runs on the server only, and importing one from browser
28
+ code is a compile error. A file under a `public` directory is served as it is:
29
+ `src/blog/public/cover.png` answers `/blog/cover.png`.
30
+ - Handlers and hooks go in a `<script server>` block of a `.abide` file.
31
+ - Import the app's own modules as `#src/…` (see `imports` in `package.json`).
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -0,0 +1,18 @@
1
+ <script server>
2
+ import { log, onStart } from '@abide/abide/server'
3
+
4
+ onStart(async (start) => {
5
+ await start()
6
+ log('started')
7
+ })
8
+ </script>
9
+
10
+ <html lang="en">
11
+ <head>
12
+ <meta charset="utf-8" />
13
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
14
+ </head>
15
+ <body>
16
+ <slot/>
17
+ </body>
18
+ </html>
@@ -42,6 +42,9 @@ const SHORT_CIRCUIT: ReadonlySet<string> = new Set(['||', '&&', '??'])
42
42
  * so the import goes with the call; left to the callers it is one `used.add` per call site and a
43
43
  * missed one emits a module calling a name it never imported.
44
44
  */
45
+ /** A run of emitted code a `Lowering` wrote, and where each of its runs stood in the projection. */
46
+ export type LoweredChunk = { text: string; origins: Origin[] }
47
+
45
48
  export class Lowering {
46
49
  readonly projection: Projection
47
50
  readonly used = new Set<string>()
@@ -77,12 +80,23 @@ export class Lowering {
77
80
  * still checked.
78
81
  */
79
82
  readonly refusals: Finding[] = []
80
-
81
- constructor(file: AbideFile, answer: CheckerAnswer, checking = false) {
83
+ /**
84
+ * 38.97 — where given, each chunk this lowering hands an emitter, with where its runs stood in
85
+ * the projection: what `sourceMapOf` finds in the module the emitter writes.
86
+ */
87
+ private readonly chunks: LoweredChunk[] | undefined
88
+
89
+ constructor(
90
+ file: AbideFile,
91
+ answer: CheckerAnswer,
92
+ checking = false,
93
+ chunks?: LoweredChunk[],
94
+ ) {
82
95
  this.projection = projectShadow(file)
83
96
  this.answer = answer
84
97
  this.holdsSlot = holdsSlot(file.template)
85
98
  this.checking = checking
99
+ this.chunks = chunks
86
100
  }
87
101
 
88
102
  /**
@@ -160,17 +174,22 @@ export class Lowering {
160
174
 
161
175
  /** The `<script module>` blocks, joined as the file wrote them and lowered. */
162
176
  modules(): string {
163
- return this.lower(this.projection.modules)
177
+ return this.lowerChunk(this.projection.modules)
178
+ }
179
+
180
+ /** The `<script server>` blocks, joined as the file wrote them and lowered. */
181
+ servers(): string {
182
+ return this.lowerChunk(this.projection.servers)
164
183
  }
165
184
 
166
185
  /** The `<script>` blocks, joined as the file wrote them and lowered. */
167
186
  scripts(): string {
168
- return this.lower(this.projection.scripts)
187
+ return this.lowerChunk(this.projection.scripts)
169
188
  }
170
189
 
171
190
  /** A template expression, lowered. */
172
191
  expression(holder: object): string {
173
- return grouped(this.lower(this.spanOf(holder)))
192
+ return grouped(this.lowerChunk(this.spanOf(holder)))
174
193
  }
175
194
 
176
195
  /**
@@ -180,7 +199,7 @@ export class Lowering {
180
199
  * lowers to its own record as a file's does to the file's.
181
200
  */
182
201
  setup(holder: Setup | InlineComponent): string {
183
- return this.lower(this.spanOf(holder))
202
+ return this.lowerChunk(this.spanOf(holder))
184
203
  }
185
204
 
186
205
  /**
@@ -196,7 +215,36 @@ export class Lowering {
196
215
  * passed through.
197
216
  */
198
217
  reference(holder: object): string {
199
- return grouped(this.lower(this.spanOf(holder), true))
218
+ const span = this.spanOf(holder)
219
+ return this.boundPath(span) ?? grouped(this.lowerChunk(span, true))
220
+ }
221
+
222
+ /**
223
+ * 32.5, 31.8 — A `bind:` OPERAND THAT IS A PATH INTO A VALUE, `contact.address.city`, as the
224
+ * `{ get, set }` pair a binding writes through: the read for its get, and the write 31.8 lowers
225
+ * `contact.address.city = v` to for its set. Lowered as a read, the binding was handed the city
226
+ * as a string and had nothing to write the typed text back into.
227
+ *
228
+ * A STATIC PATH ONLY — names and dots, which carry no read of their own. `undefined` for any
229
+ * other operand, which `reference` lowers as it stands.
230
+ */
231
+ private boundPath(span: Span): string | undefined {
232
+ if (this.checking) return undefined
233
+ const source = this.projection.text
234
+ const text = source.slice(span.start, span.end)
235
+ const from = span.start + (text.length - text.trimStart().length)
236
+ const to = span.start + text.trimEnd().length
237
+ const reads = this.answer.reads
238
+ const read = reads[this.answer.firstRead(from)]
239
+ if (read === undefined || read.from !== from || read.shape !== 'value')
240
+ return undefined
241
+ const path = source.slice(read.to, to)
242
+ if (!/^(\s*\.\s*[A-Za-z_$][\w$]*)+$/.test(path)) return undefined
243
+ const name = this.nameOf(read)
244
+ const segments: string[] = []
245
+ for (const [, segment] of path.matchAll(/\.\s*([A-Za-z_$][\w$]*)/g))
246
+ segments.push(JSON.stringify(segment))
247
+ return `{ get: () => ${this.lowerChunk({ start: from, end: to })}, set: (${STORED}) => ${name}.set(${this.use('writePath')}(${name}(), [${segments.join(', ')}], ${STORED})) }`
200
248
  }
201
249
 
202
250
  /**
@@ -209,7 +257,7 @@ export class Lowering {
209
257
  chosenTag(node: object): string | undefined {
210
258
  const span = this.projection.tags.get(node)
211
259
  if (span === undefined || !this.answer.holdsRead(span)) return undefined
212
- return this.lower(span)
260
+ return this.lowerChunk(span)
213
261
  }
214
262
 
215
263
  /** A `{#for}` block's key expression, lowered. */
@@ -217,7 +265,7 @@ export class Lowering {
217
265
  const span = this.projection.keys.get(block)
218
266
  if (span === undefined)
219
267
  throw new Error('abide: a {#for} key was never projected.')
220
- return grouped(this.lower(span))
268
+ return grouped(this.lowerChunk(span))
221
269
  }
222
270
 
223
271
  /**
@@ -283,6 +331,15 @@ export class Lowering {
283
331
  return span
284
332
  }
285
333
 
334
+ /** `lower`, the chunk recorded where `chunks` was given. */
335
+ private lowerChunk(span: Span, holds = false): string {
336
+ if (this.chunks === undefined) return this.lower(span, holds)
337
+ const origins: Origin[] = []
338
+ const text = this.lower(span, holds, origins)
339
+ this.chunks.push({ text, origins })
340
+ return text
341
+ }
342
+
286
343
  /**
287
344
  * The source of `span`, every read in it rewritten.
288
345
  *
@@ -484,6 +541,11 @@ export class Lowering {
484
541
  // the call (`expressionFacts`), so a `<script>`'s `raw` stays the file's.
485
542
  case 'raw':
486
543
  return this.use('raw')
544
+ // 27.13 — the call bound to a name, for the checker to read the defaults' type off.
545
+ case 'config':
546
+ return this.checking
547
+ ? `const ${CHECKED_CONFIG}${read.start} = ${CHECKED_CONFIG_OF}(${spelled})`
548
+ : undefined
487
549
  }
488
550
  const value =
489
551
  read.value === undefined ? '1' : this.lower(read.value).trim()
@@ -611,6 +673,13 @@ export const PROPS = '__props'
611
673
  /** The record a checked lowering reads each value through (`Lowering.values`). */
612
674
  export const CHECKED_VALUES = '__values'
613
675
 
676
+ /**
677
+ * 27.13 — what a checked lowering binds an `onConfig(…)` statement to, suffixed by where the call
678
+ * stands, and the declared function that hands that call back typed as what its defaults return.
679
+ */
680
+ export const CHECKED_CONFIG = '__config'
681
+ export const CHECKED_CONFIG_OF = '__configOf'
682
+
614
683
  /**
615
684
  * The checked lowering's write guard: holds a written value to what `set` takes.
616
685
  *
@@ -3,7 +3,7 @@ import type { Origin, Span } from './projectShadow.ts'
3
3
  /** What a `.abide`'s checked module is registered with the checker as, beside the `.abide`. */
4
4
  export const CHECKED_SUFFIX = '.check.ts'
5
5
  /** What a `.abide`'s projection is registered with the checker as, beside the `.abide`. */
6
- const SHADOW_SUFFIX = '.shadow.ts'
6
+ export const SHADOW_SUFFIX = '.shadow.ts'
7
7
 
8
8
  /**
9
9
  * The two files the checker reads for one `.abide`, and how a position in either is one in it.
@@ -101,7 +101,7 @@ export class ShadowMap {
101
101
  }
102
102
 
103
103
  /** The start of the run holding `position`, plus how far in; scaffolding is the run before's end. */
104
- function mapBack(origins: readonly Origin[], position: number): number {
104
+ export function mapBack(origins: readonly Origin[], position: number): number {
105
105
  let low = 0
106
106
  let high = origins.length
107
107
  while (low < high) {