@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.
- package/CHANGELOG.md +16 -0
- package/bin/abide.ts +223 -164
- package/docs/REGISTRY.md +726 -0
- package/docs/RULEBOOK.md +2753 -0
- package/docs/abide.md +12878 -0
- package/package.json +5 -3
- package/scaffold/AGENTS.md +31 -0
- package/scaffold/CLAUDE.md +1 -0
- package/scaffold/src/layout.abide +18 -0
- package/src/compiler/Lowering.ts +78 -9
- package/src/compiler/ShadowMap.ts +2 -2
- package/src/compiler/TypeSession.ts +262 -67
- package/src/compiler/argsSchemaOf.ts +1 -1
- package/src/compiler/checkApp.ts +43 -15
- package/src/compiler/checkedShadow.ts +39 -5
- package/src/compiler/classifyRead.ts +6 -4
- package/src/compiler/classifyTemplate.ts +1 -1
- package/src/compiler/compileApp.ts +433 -193
- package/src/compiler/compiledEntry.ts +43 -39
- package/src/compiler/componentGraph.ts +58 -71
- package/src/compiler/declaredExports.ts +24 -7
- package/src/compiler/emitClient.ts +141 -71
- package/src/compiler/emitComponent.ts +37 -8
- package/src/compiler/emitSource.ts +106 -13
- package/src/compiler/handlersUnder.ts +106 -59
- package/src/compiler/index.ts +7 -0
- package/src/compiler/mountsOf.ts +138 -0
- package/src/compiler/nearest.ts +14 -0
- package/src/compiler/parseAbide.ts +157 -20
- package/src/compiler/projectShadow.ts +213 -7
- package/src/compiler/reactiveTypes.ts +20 -7
- package/src/compiler/readSources.ts +15 -2
- package/src/compiler/readsIn.ts +61 -7
- package/src/compiler/renderMarkup.ts +3 -3
- package/src/compiler/scaffold.ts +30 -11
- package/src/compiler/serveLanguage.ts +125 -34
- package/src/compiler/sourceMapOf.ts +193 -0
- package/src/compiler/splitImports.ts +205 -83
- package/src/compiler/syncTypes.ts +32 -0
- package/src/compiler/tokenize.ts +14 -0
- package/src/compiler/writeDefaultProject.ts +1 -1
- package/src/compiler/writeTypes.ts +82 -0
- package/src/server/CLIENT_BUILD.ts +11 -13
- package/src/server/DEFAULT_PORT.ts +1 -1
- package/src/server/LAUNCHER_FILES.ts +9 -0
- package/src/server/MODULE_QUERIES.ts +18 -0
- package/src/server/TABLES.ts +7 -0
- package/src/server/VIRTUAL_DIRECTORY.ts +4 -5
- package/src/server/abideModules.ts +391 -0
- package/src/server/answerFailure.ts +16 -6
- package/src/server/answerRequest.ts +235 -106
- package/src/server/answerRpc.ts +102 -30
- package/src/server/answerSocket.ts +65 -20
- package/src/server/answerValue.ts +22 -9
- package/src/server/appDirectories.ts +1 -1
- package/src/server/appPlugins.ts +1 -1
- package/src/server/appTree.ts +179 -0
- package/src/server/argsFor.ts +2 -2
- package/src/server/assistant.ts +2 -2
- package/src/server/bridgeRelay.ts +6 -8
- package/src/server/claudeCode.ts +0 -6
- package/src/server/clientBuildOptions.ts +8 -3
- package/src/server/coerceArgs.ts +1 -1
- package/src/server/commands.ts +37 -37
- package/src/server/componentModules.d.ts +3 -1
- package/src/server/compressAnswer.ts +4 -4
- package/src/server/config.ts +25 -29
- package/src/server/configFields.ts +31 -25
- package/src/server/createApp.ts +59 -73
- package/src/server/devWorker.ts +114 -181
- package/src/server/executableName.ts +4 -0
- package/src/server/fenceServer.ts +37 -35
- package/src/server/generatedSurfaces.ts +99 -66
- package/src/server/hooks.ts +124 -52
- package/src/server/iconAccent.ts +191 -0
- package/src/server/index.ts +11 -7
- package/src/server/installSourceMaps.ts +88 -0
- package/src/server/launcherOptions.ts +34 -31
- package/src/server/launcherPage.ts +107 -64
- package/src/server/manifestOf.ts +16 -13
- package/src/server/namesUnder.ts +2 -2
- package/src/server/nativeMenu.ts +5 -5
- package/src/server/negotiateEncoding.ts +1 -1
- package/src/server/principal.ts +10 -5
- package/src/server/realOrAsGiven.ts +10 -0
- package/src/server/refuseAddressCollision.ts +21 -14
- package/src/server/remote.ts +49 -52
- package/src/server/render.ts +65 -94
- package/src/server/renderComponent.ts +5 -0
- package/src/server/reportHealth.ts +2 -2
- package/src/server/requestScope.ts +12 -1
- package/src/server/runBuild.ts +24 -0
- package/src/server/runCompiled.ts +5 -5
- package/src/server/runDesktop.ts +52 -27
- package/src/server/serveBuild.ts +43 -52
- package/src/server/serveDev.ts +73 -37
- package/src/server/shell.ts +7 -22
- package/src/server/sourceMappings.ts +139 -0
- package/src/server/surfaceOf.ts +18 -3
- package/src/server/testBuild.ts +1 -19
- package/src/server/withAbideSources.ts +117 -0
- package/src/shared/ADDRESSES.ts +7 -18
- package/src/shared/APP_META.ts +7 -0
- package/src/shared/CopyOptions.ts +1 -1
- package/src/shared/DEBUG_META.ts +1 -1
- package/src/shared/RESERVED_DIRECTORIES.ts +15 -0
- package/src/shared/cookies.ts +2 -2
- package/src/shared/csp.ts +1 -1
- package/src/shared/escapeText.ts +1 -1
- package/src/shared/filledPath.ts +85 -0
- package/src/shared/framing.ts +79 -6
- package/src/shared/headKeyOf.ts +2 -0
- package/src/shared/index.ts +1 -1
- package/src/shared/log.ts +27 -13
- package/src/shared/matchRoute.ts +23 -4
- package/src/shared/menuItem.ts +3 -3
- package/src/shared/reactive/Keyed.ts +2 -2
- package/src/shared/reactive/NotLanded.ts +1 -1
- package/src/shared/reactive/Reactive.ts +43 -43
- package/src/shared/reactive/argsContract.ts +4 -4
- package/src/shared/reactive/canonicalKey.ts +4 -4
- package/src/shared/reactive/chunksOfStream.ts +6 -0
- package/src/shared/reactive/index.ts +1 -1
- package/src/shared/reactive/recordWrites.ts +103 -5
- package/src/shared/reactive/structural.ts +1 -1
- package/src/shared/reactive/tracking.ts +1 -1
- package/src/shared/reactive/watch.ts +3 -3
- package/src/shared/refuse.ts +1 -1
- package/src/shared/routePattern.ts +82 -46
- package/src/shared/rpc.ts +37 -8
- package/src/shared/rpcRequest.ts +27 -3
- package/src/shared/url.ts +4 -44
- package/src/shared/writePath.ts +1 -1
- package/src/ui/LAYER_NAMES.ts +1 -1
- package/src/ui/List.ts +3 -3
- package/src/ui/MOUNTING_LEVEL.ts +18 -0
- package/src/ui/Mismatch.ts +1 -1
- package/src/ui/RawRun.ts +1 -1
- package/src/ui/Router.ts +38 -31
- package/src/ui/Scope.ts +1 -1
- package/src/ui/TryRegion.ts +2 -2
- package/src/ui/applyHead.ts +33 -0
- package/src/ui/index.ts +1 -1
- package/src/ui/menuBridge.ts +1 -1
- package/src/ui/moveNode.ts +1 -1
- package/src/ui/reconcile.ts +2 -2
- package/src/ui/reportMenu.ts +2 -2
- package/src/ui/routing.ts +2 -2
- package/src/ui/setAttribute.ts +1 -1
- package/src/ui/setText.ts +1 -1
- package/src/ui/socketWire.ts +9 -7
- package/src/ui/wire.ts +1 -1
- package/scaffold/src/server/app.ts +0 -6
- package/scaffold/src/shared/.gitkeep +0 -0
- package/scaffold/src/ui/app.html +0 -8
- package/src/server/componentImports.ts +0 -56
- /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.
|
|
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
|
|
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": "
|
|
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>
|
package/src/compiler/Lowering.ts
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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) {
|