@abide/abide 0.100.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 +31 -0
- package/bin/abide.ts +227 -163
- package/docs/REGISTRY.md +726 -0
- package/docs/RULEBOOK.md +2753 -0
- package/docs/abide.md +12878 -0
- package/package.json +10 -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 -56
- 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 +124 -39
- package/src/server/answerSocket.ts +141 -48
- 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 +48 -14
- 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 +144 -183
- 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 +81 -39
- 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/GLOBAL_GETS.ts +9 -3
- package/src/shared/RESERVED_DIRECTORIES.ts +15 -0
- package/src/shared/RPC_SERVER.ts +2 -2
- 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/Cursor.ts +3 -9
- package/src/shared/reactive/Keyed.ts +4 -3
- package/src/shared/reactive/NotLanded.ts +1 -1
- package/src/shared/reactive/Reactive.ts +81 -60
- 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 +155 -21
- package/src/shared/reactive/watch.ts +10 -6
- package/src/shared/refuse.ts +1 -1
- package/src/shared/routePattern.ts +82 -46
- package/src/shared/rpc.ts +47 -13
- 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
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import { tablePath } from '#server/abideModules.ts'
|
|
1
2
|
import type { AppPackage } from '#server/config.ts'
|
|
2
|
-
import type {
|
|
3
|
+
import type { SourceMaps } from '#server/installSourceMaps.ts'
|
|
4
|
+
import { SERVER_TABLE } from '#server/TABLES.ts'
|
|
3
5
|
import abidePackage from '../../package.json' with { type: 'json' }
|
|
4
6
|
|
|
5
|
-
// What the executable starts from: `abide compile`'s, and `abide bundle`'s window over it (38.
|
|
7
|
+
// What the executable starts from: `abide compile`'s, and `abide bundle`'s window over it (38.70).
|
|
8
|
+
const INSTALL_SOURCE_MAPS = Bun.fileURLToPath(
|
|
9
|
+
new URL('../server/installSourceMaps.ts', import.meta.url),
|
|
10
|
+
)
|
|
11
|
+
|
|
6
12
|
const RUNNERS = {
|
|
7
13
|
compiled: {
|
|
8
14
|
name: 'runCompiled',
|
|
@@ -22,7 +28,7 @@ const PACKAGE = Bun.fileURLToPath(new URL('../../', import.meta.url))
|
|
|
22
28
|
/**
|
|
23
29
|
* Abide's own package entries, by the specifier an app imports each with, to the module behind it.
|
|
24
30
|
*
|
|
25
|
-
* 38.
|
|
31
|
+
* 38.56 — the compiler is not among them: the executable does not hold it.
|
|
26
32
|
*/
|
|
27
33
|
function abideEntries(): Map<string, string> {
|
|
28
34
|
const specifiers = new Map<string, string>()
|
|
@@ -41,8 +47,8 @@ function abideEntries(): Map<string, string> {
|
|
|
41
47
|
/**
|
|
42
48
|
* The source of the module a compiled app starts from, written into the build beside `server.ts`.
|
|
43
49
|
*
|
|
44
|
-
* 38.
|
|
45
|
-
* the executable. 38.
|
|
50
|
+
* 38.10 — every part `runCompiled` boots over, named by a static import the bundler follows into
|
|
51
|
+
* the executable. 38.44 — NOTHING IN IT IS FOUND AT RUN TIME — a file this module does not name is
|
|
46
52
|
* a file the executable does not hold, which is what makes the artifact a property of the build
|
|
47
53
|
* rather than of the machine it lands on.
|
|
48
54
|
*
|
|
@@ -52,24 +58,25 @@ function abideEntries(): Map<string, string> {
|
|
|
52
58
|
*/
|
|
53
59
|
export function compiledEntry(app: {
|
|
54
60
|
/**
|
|
55
|
-
* 38.
|
|
56
|
-
* `
|
|
61
|
+
* 38.70 — what `abide bundle` read of the launcher's files: `launch` the path of its
|
|
62
|
+
* `launcher.abide`, and `custom` whether that file has markup of its own; `undefined` for
|
|
63
|
+
* `abide compile`.
|
|
57
64
|
*/
|
|
58
65
|
desktop:
|
|
59
66
|
| {
|
|
60
|
-
options: LauncherOptions
|
|
61
67
|
launch: string | undefined
|
|
62
|
-
|
|
68
|
+
custom: boolean
|
|
69
|
+
document: string
|
|
70
|
+
icon: string | undefined
|
|
71
|
+
accent: string | undefined
|
|
63
72
|
}
|
|
64
73
|
| undefined
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
/** The app's root, below which the server's table is served (`abideModules`). */
|
|
75
|
+
root: string
|
|
76
|
+
/** 38.97 — each server module's map, by the `.abide` it is served at. */
|
|
77
|
+
sourceMaps: SourceMaps
|
|
68
78
|
package: AppPackage
|
|
69
|
-
shell: string
|
|
70
79
|
manifest: unknown
|
|
71
|
-
/** 16.2 — each handler's source path as its row names it, to the file. */
|
|
72
|
-
handlerModules: Map<string, string>
|
|
73
80
|
/** Every file under the build's `client/`, by name to the file. */
|
|
74
81
|
client: Map<string, string>
|
|
75
82
|
/** Every file under the build's `public/`, by name to the file. */
|
|
@@ -77,8 +84,8 @@ export function compiledEntry(app: {
|
|
|
77
84
|
}): string {
|
|
78
85
|
const runner = RUNNERS[app.desktop === undefined ? 'compiled' : 'desktop']
|
|
79
86
|
let imports = `import { ${runner.name} } from ${JSON.stringify(runner.path)}
|
|
80
|
-
import
|
|
81
|
-
import
|
|
87
|
+
import { installSourceMaps } from ${JSON.stringify(INSTALL_SOURCE_MAPS)}
|
|
88
|
+
import * as table from ${JSON.stringify(tablePath(app.root, SERVER_TABLE))}
|
|
82
89
|
`
|
|
83
90
|
const files = (kind: string, paths: Map<string, string>): string => {
|
|
84
91
|
let entries = ''
|
|
@@ -92,49 +99,46 @@ import { handlers } from ${JSON.stringify(`${app.out}/rpc.ts`)}
|
|
|
92
99
|
}
|
|
93
100
|
const client = files('client', app.client)
|
|
94
101
|
const published = files('published', app.published)
|
|
95
|
-
let modules = ''
|
|
96
|
-
for (const [source, path] of app.handlerModules)
|
|
97
|
-
modules += `\n ${JSON.stringify(source)}: () => import(${JSON.stringify(path)}),`
|
|
98
|
-
// A handler module as a script names it: `#server/rpc/invoices`, with or without its extension.
|
|
99
102
|
let specifiers = ''
|
|
100
103
|
for (const [specifier, path] of abideEntries())
|
|
101
104
|
specifiers += `\n ${JSON.stringify(specifier)}: () => import(${JSON.stringify(path)}),`
|
|
102
|
-
for (const source of app.handlerModules.keys())
|
|
103
|
-
for (const specifier of [
|
|
104
|
-
`#${source}`,
|
|
105
|
-
`#${source.replace(/\.ts$/, '')}`,
|
|
106
|
-
])
|
|
107
|
-
specifiers += `\n ${JSON.stringify(specifier)}: handlerModules[${JSON.stringify(source)}],`
|
|
108
|
-
const hooks =
|
|
109
|
-
app.hooks === undefined
|
|
110
|
-
? 'undefined'
|
|
111
|
-
: `() => import(${JSON.stringify(app.hooks)})`
|
|
112
105
|
const desktop =
|
|
113
106
|
app.desktop === undefined
|
|
114
107
|
? ''
|
|
115
108
|
: `
|
|
116
109
|
{
|
|
117
|
-
|
|
110
|
+
custom: ${app.desktop.custom},
|
|
118
111
|
launch: ${app.desktop.launch === undefined ? 'undefined' : `() => import(${JSON.stringify(app.desktop.launch)})`},
|
|
119
|
-
|
|
112
|
+
document: ${JSON.stringify(app.desktop.document)},
|
|
113
|
+
icon: ${JSON.stringify(app.desktop.icon)},
|
|
114
|
+
accent: ${JSON.stringify(app.desktop.accent)},
|
|
120
115
|
},`
|
|
121
116
|
return `// Written by \`abide compile\`. The whole app, as what one executable holds.
|
|
122
117
|
${imports}
|
|
123
|
-
|
|
124
|
-
|
|
118
|
+
// 38.56 — a file declaring handlers as a script names it through the app's one alias:
|
|
119
|
+
// \`#src/invoices/page.abide\`, to the module its server block compiled into.
|
|
120
|
+
const declared = {}
|
|
121
|
+
for (const row of table.handlers) declared[\`#src/\${row.source}\`] = row.load
|
|
122
|
+
|
|
123
|
+
// 38.97 — before anything runs, a script \`run\` included: the executable's frames name each
|
|
124
|
+
// \`.abide\` as it was bundled.
|
|
125
|
+
installSourceMaps(${JSON.stringify(app.sourceMaps)}, undefined)
|
|
125
126
|
|
|
126
127
|
await ${runner.name}(
|
|
127
|
-
|
|
128
|
+
// 37.1 — every server block, imported before the boot.
|
|
129
|
+
{
|
|
130
|
+
hooks: () => Promise.all(table.servers.map((load) => load())),
|
|
131
|
+
package: ${JSON.stringify(app.package)},
|
|
132
|
+
},
|
|
128
133
|
{
|
|
129
134
|
table,
|
|
130
|
-
handlers,
|
|
131
|
-
handlerModule: (source) => handlerModules[source](),
|
|
132
|
-
shell: ${JSON.stringify(app.shell)},
|
|
135
|
+
handlers: table.handlers,
|
|
133
136
|
manifest: ${JSON.stringify(app.manifest)},
|
|
134
137
|
client: ${client},
|
|
135
138
|
published: ${published},
|
|
136
139
|
},
|
|
137
140
|
{${specifiers}
|
|
141
|
+
...declared,
|
|
138
142
|
},${desktop}
|
|
139
143
|
)
|
|
140
144
|
`
|
|
@@ -1,57 +1,40 @@
|
|
|
1
|
-
import { dirname,
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { dirname, relative as relativeTo } from 'node:path' // bun exposes no path helpers of its own
|
|
2
|
+
import {
|
|
3
|
+
type FileKind,
|
|
4
|
+
fileKind,
|
|
5
|
+
placeOf,
|
|
6
|
+
routeOf,
|
|
7
|
+
} from '#shared/routePattern.ts'
|
|
8
|
+
import { type AbideFile, scriptBodies } from './parseAbide.ts'
|
|
9
|
+
import { abideImports, attributedImports } from './splitImports.ts'
|
|
5
10
|
|
|
6
11
|
type Resolve = (specifier: string, from: string) => string | undefined
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
|
-
*
|
|
10
|
-
* `.abide` imports land in the output tree.
|
|
14
|
+
* Which files are invoked as components: every source path another file imports.
|
|
11
15
|
*
|
|
12
|
-
* 32.17 — off ONE reading of every file's imports
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `invoked` is every source path another file imports as a component (`emitClient`'s `selfFill`).
|
|
16
|
-
* By PATH, not by file name: two `Row.abide` in two directories are two components, and only the
|
|
17
|
-
* one somebody imports carries its own markup.
|
|
18
|
-
*
|
|
19
|
-
* `imports` is, per importing file, where each `.abide` specifier it wrote lands in the output
|
|
20
|
-
* tree, relative and without an extension (`splitImports`). The output mirrors the source, so
|
|
21
|
-
* the path between two sources IS the path between their modules — which is what turns a seam
|
|
22
|
-
* specifier (`#ui/components/Row.abide`) into one that resolves inside the build rather than into
|
|
23
|
-
* a source tree where the compiler wrote nothing.
|
|
16
|
+
* 32.17 — off ONE reading of every file's imports, each `.abide` specifier resolved once against
|
|
17
|
+
* the file that wrote it. By PATH, not by file name: two `Row.abide` in two directories are two
|
|
18
|
+
* components, and only the one somebody imports carries its own markup (`emitClient`'s `selfFill`).
|
|
24
19
|
*
|
|
25
20
|
* `resolve` is the app's: a build asks bun, and a harness that lays an app out by hand answers for
|
|
26
|
-
* its own seams. A specifier it cannot resolve, or that lands outside `files`,
|
|
21
|
+
* its own seams. A specifier it cannot resolve, or that lands outside `files`, invokes nothing.
|
|
27
22
|
*/
|
|
28
23
|
export function componentGraph(
|
|
29
24
|
files: readonly { path: string; file: AbideFile }[],
|
|
30
25
|
resolve: Resolve,
|
|
31
|
-
): {
|
|
32
|
-
invoked: Set<string>
|
|
33
|
-
imports: Map<string, Map<string, string>>
|
|
34
|
-
} {
|
|
26
|
+
): { invoked: Set<string> } {
|
|
35
27
|
const known = new Set<string>()
|
|
36
28
|
for (const entry of files) known.add(entry.path)
|
|
37
29
|
const invoked = new Set<string>()
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
const from = dirname(entry.path)
|
|
41
|
-
const landed = new Map<string, string>()
|
|
42
|
-
for (const [specifier, target] of abideImportsOf(
|
|
30
|
+
for (const entry of files)
|
|
31
|
+
for (const target of abideImportsOf(
|
|
43
32
|
entry.path,
|
|
44
33
|
entry.file,
|
|
45
34
|
resolve,
|
|
46
|
-
))
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
const path = relativePath(from, target.slice(0, -'.abide'.length))
|
|
50
|
-
landed.set(specifier, path.startsWith('.') ? path : `./${path}`)
|
|
51
|
-
}
|
|
52
|
-
imports.set(entry.path, landed)
|
|
53
|
-
}
|
|
54
|
-
return { invoked, imports }
|
|
35
|
+
).values())
|
|
36
|
+
if (known.has(target)) invoked.add(target)
|
|
37
|
+
return { invoked }
|
|
55
38
|
}
|
|
56
39
|
|
|
57
40
|
/**
|
|
@@ -69,7 +52,7 @@ export function abideImportsOf(
|
|
|
69
52
|
): Map<string, string> {
|
|
70
53
|
const from = dirname(path)
|
|
71
54
|
const resolved = new Map<string, string>()
|
|
72
|
-
for (const script of
|
|
55
|
+
for (const script of scriptBodies(file))
|
|
73
56
|
for (const { specifier } of abideImports(script)) {
|
|
74
57
|
if (resolved.has(specifier)) continue
|
|
75
58
|
const target = resolve(specifier, from)
|
|
@@ -81,6 +64,8 @@ export function abideImportsOf(
|
|
|
81
64
|
/** One source in the app graph: where it is below the root, what it is, and its address. */
|
|
82
65
|
export type AppNode<Source> = Source & {
|
|
83
66
|
relative: string
|
|
67
|
+
/** 23.19 — the path it answers by: its own below the root, or the one its mount gives it. */
|
|
68
|
+
position: string
|
|
84
69
|
kind: FileKind
|
|
85
70
|
/** 23.3 — the address of a page or an error page, and `undefined` for anything else. */
|
|
86
71
|
route: string | undefined
|
|
@@ -88,52 +73,54 @@ export type AppNode<Source> = Source & {
|
|
|
88
73
|
|
|
89
74
|
/**
|
|
90
75
|
* The app as one graph, built once per build or check: every source with its kind and address,
|
|
91
|
-
* which files are invoked as components
|
|
92
|
-
*
|
|
93
|
-
* `imports` is `componentGraph`'s with the relative specifiers landed beside the `.abide` ones —
|
|
94
|
-
* 34.14, A RELATIVE IMPORT RESOLVES FROM THE FILE THAT WROTE IT. The module that file compiles to
|
|
95
|
-
* is in the output tree, which holds compiled `.abide` files and nothing else, so a stylesheet or
|
|
96
|
-
* a `.ts` beside the source is reached by the path from the module back to it.
|
|
97
|
-
*
|
|
98
|
-
* `output` is where the modules are written, relative to `root`.
|
|
76
|
+
* and which files are invoked as components.
|
|
99
77
|
*/
|
|
100
|
-
export function appGraph<
|
|
78
|
+
export function appGraph<
|
|
79
|
+
Source extends {
|
|
80
|
+
path: string
|
|
81
|
+
file: AbideFile
|
|
82
|
+
position?: string | undefined
|
|
83
|
+
},
|
|
84
|
+
>(
|
|
101
85
|
root: string,
|
|
102
86
|
sources: readonly Source[],
|
|
103
|
-
output: string,
|
|
104
87
|
resolve: Resolve,
|
|
105
|
-
): {
|
|
106
|
-
nodes: AppNode<Source>[]
|
|
107
|
-
invoked: Set<string>
|
|
108
|
-
imports: Map<string, Map<string, string>>
|
|
109
|
-
} {
|
|
88
|
+
): { nodes: AppNode<Source>[]; invoked: Set<string> } {
|
|
110
89
|
const nodes: AppNode<Source>[] = []
|
|
111
90
|
for (const source of sources) {
|
|
112
|
-
|
|
113
|
-
|
|
91
|
+
// Below the root for the app's own files, and above it — `../node_modules/…` — for a
|
|
92
|
+
// dependency's (34.28).
|
|
93
|
+
const relative = relativeTo(root, source.path)
|
|
94
|
+
const position = source.position ?? relative
|
|
95
|
+
// 34.21 — a server block of the app's own under a `server` or `public` directory has no
|
|
96
|
+
// address: refused here, before anything reads one off it. A dependency's has none of its own
|
|
97
|
+
// (34.31); the app mounts what it declares where the app re-exports it.
|
|
98
|
+
const place = placeOf(position)
|
|
99
|
+
if (
|
|
100
|
+
source.file.servers.length > 0 &&
|
|
101
|
+
(place === 'server' || place === 'public')
|
|
102
|
+
)
|
|
103
|
+
throw new Error(
|
|
104
|
+
`abide: ${relative} has a <script server>, and it is under a ${place} directory, where nothing has an address. Move the file out of it, or the code into a module under a server directory. RULEBOOK 34.21.`,
|
|
105
|
+
)
|
|
106
|
+
// 34.25 — a file imported as text is found at build, not when its module first loads.
|
|
107
|
+
for (const script of scriptBodies(source.file))
|
|
108
|
+
for (const { specifier } of attributedImports(script, 'text'))
|
|
109
|
+
if (resolve(specifier, dirname(source.path)) === undefined)
|
|
110
|
+
throw new Error(
|
|
111
|
+
`abide: ${relative} imports ${specifier} as text, and there is no such file. RULEBOOK 34.25.`,
|
|
112
|
+
)
|
|
113
|
+
const kind = fileKind(position)
|
|
114
114
|
nodes.push({
|
|
115
115
|
...source,
|
|
116
116
|
relative,
|
|
117
|
+
position,
|
|
117
118
|
kind,
|
|
118
119
|
route:
|
|
119
120
|
kind === 'page' || kind === 'error'
|
|
120
|
-
? routeOf(
|
|
121
|
+
? routeOf(position)
|
|
121
122
|
: undefined,
|
|
122
123
|
})
|
|
123
124
|
}
|
|
124
|
-
|
|
125
|
-
for (const node of nodes) {
|
|
126
|
-
const landed = imports.get(node.path) as Map<string, string>
|
|
127
|
-
const written = dirname(node.path)
|
|
128
|
-
const emitted = posix.join(root, output, dirname(node.relative))
|
|
129
|
-
for (const script of [...node.file.modules, ...node.file.scripts])
|
|
130
|
-
for (const specifier of relativeSpecifiers(script)) {
|
|
131
|
-
const path = posix.relative(
|
|
132
|
-
emitted,
|
|
133
|
-
posix.join(written, specifier),
|
|
134
|
-
)
|
|
135
|
-
landed.set(specifier, path.startsWith('.') ? path : `./${path}`)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return { nodes, invoked, imports }
|
|
125
|
+
return { nodes, invoked: componentGraph(sources, resolve).invoked }
|
|
139
126
|
}
|
|
@@ -189,8 +189,8 @@ async function declaringMethod(
|
|
|
189
189
|
}
|
|
190
190
|
| undefined
|
|
191
191
|
> {
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
let declaration = await symbol.valueDeclaration?.resolve()
|
|
193
|
+
let call =
|
|
194
194
|
declaration === undefined
|
|
195
195
|
? undefined
|
|
196
196
|
: isVariableDeclaration(declaration)
|
|
@@ -198,6 +198,24 @@ async function declaringMethod(
|
|
|
198
198
|
: isExportAssignment(declaration)
|
|
199
199
|
? declaration.expression
|
|
200
200
|
: undefined
|
|
201
|
+
// 19.15 — A BINDING NAMING ANOTHER BINDING is the call that one was declared by: `export const
|
|
202
|
+
// named = drop` is `drop`'s handler under another name. Bounded, so a cycle the checker would
|
|
203
|
+
// refuse anyway cannot spin here.
|
|
204
|
+
for (
|
|
205
|
+
let hops = 0;
|
|
206
|
+
hops < 8 && call !== undefined && isIdentifier(call);
|
|
207
|
+
hops += 1
|
|
208
|
+
) {
|
|
209
|
+
const bound = await checker.getSymbolAtLocation(call)
|
|
210
|
+
if (bound === undefined) return undefined
|
|
211
|
+
declaration = await (
|
|
212
|
+
await aliasedSymbol(checker, bound)
|
|
213
|
+
).valueDeclaration?.resolve()
|
|
214
|
+
call =
|
|
215
|
+
declaration !== undefined && isVariableDeclaration(declaration)
|
|
216
|
+
? declaration.initializer
|
|
217
|
+
: undefined
|
|
218
|
+
}
|
|
201
219
|
if (call === undefined || !isCallExpression(call)) return undefined
|
|
202
220
|
const callee = isPropertyAccessExpression(call.expression)
|
|
203
221
|
? call.expression.name
|
|
@@ -520,11 +538,10 @@ function describedAs(
|
|
|
520
538
|
/**
|
|
521
539
|
* What a handler call's inline `clients` declares for `surface`, or `undefined` where it does not.
|
|
522
540
|
*
|
|
523
|
-
* 20.4, 38.
|
|
524
|
-
* `ui: false`
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
* that is not a literal, is not read.
|
|
541
|
+
* 20.4, 38.62 — written on the declaration, which is what the build can read without running it:
|
|
542
|
+
* `ui: false` gives the file's browser copy no stand-in for it; `cli: false` keeps it off the
|
|
543
|
+
* shell's listing, which reads the table the build wrote (38.7); and an explicit `true` overrides
|
|
544
|
+
* 16.37's default. An options object built elsewhere, or a value that is not a literal, is not read.
|
|
528
545
|
*/
|
|
529
546
|
function declaredFor(
|
|
530
547
|
call: Node & { arguments?: readonly Node[] },
|