@abide/abide 0.109.0 → 0.110.1
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 +12 -0
- package/docs/REGISTRY.md +6 -5
- package/docs/RULEBOOK.md +24 -13
- package/docs/abide.md +163 -159
- package/package.json +1 -1
- package/scaffold/AGENTS.md +12 -6
- package/scaffold/src/{tests/getGreeting.test.ts → getGreeting.test.ts} +1 -1
- package/scaffold/src/{tests/index.test.ts → index.test.ts} +1 -1
- package/src/compiler/appLayout.ts +5 -15
- package/src/compiler/compileApp.ts +0 -2
- package/src/compiler/handlersUnder.ts +1 -1
- package/src/compiler/scaffold.ts +5 -5
- package/src/server/abideModules.ts +0 -5
- package/src/server/appTree.ts +38 -34
- package/src/server/clientBundle.ts +2 -2
- package/src/server/fenceServer.ts +25 -31
- package/src/server/generatedSurfaces.ts +35 -1
- package/src/server/placement.ts +27 -51
- package/src/server/serveDev.ts +0 -1
- package/src/shared/RESERVED_DIRECTORIES.ts +7 -20
package/src/server/placement.ts
CHANGED
|
@@ -3,23 +3,11 @@
|
|
|
3
3
|
// each. The route GRAMMAR is `routePattern`'s, which the browser's router reads too; this half is the
|
|
4
4
|
// build's and the server's alone, so it stays out of the client's closure.
|
|
5
5
|
|
|
6
|
-
import { resolve } from 'node:path' // bun exposes no path helpers of its own
|
|
7
6
|
import { LAUNCHER_PAGE } from '#shared/LAUNCHER_FILES.ts'
|
|
8
|
-
import {
|
|
9
|
-
HOLDS_SERVER,
|
|
10
|
-
RESERVED_DIRECTORIES,
|
|
11
|
-
SERVER_DIRECTORY,
|
|
12
|
-
} from '#shared/RESERVED_DIRECTORIES.ts'
|
|
7
|
+
import { RESERVED_DIRECTORIES } from '#shared/RESERVED_DIRECTORIES.ts'
|
|
13
8
|
|
|
14
9
|
/** Where a file sits in an app, which is what it is to every reader (`placeOf`). */
|
|
15
|
-
export type Place =
|
|
16
|
-
| 'address'
|
|
17
|
-
| 'server'
|
|
18
|
-
| 'public'
|
|
19
|
-
| 'lib'
|
|
20
|
-
| 'tests'
|
|
21
|
-
| 'dependency'
|
|
22
|
-
| 'skipped'
|
|
10
|
+
export type Place = 'address' | 'public' | 'lib' | 'dependency' | 'skipped'
|
|
23
11
|
|
|
24
12
|
/** Whether a `.abide` is a page, a layout, an error page or a component. */
|
|
25
13
|
type FileKind = 'page' | 'layout' | 'error' | 'component'
|
|
@@ -50,9 +38,9 @@ export type Placement = {
|
|
|
50
38
|
* 23.21 — WHERE IT SITS, THEN ITS NAME. Every `.abide` directly in an address directory is a page
|
|
51
39
|
* but a `layout.abide`, an `error.abide` and the root's `launcher.abide`; one under a fence is a
|
|
52
40
|
* component whatever it is called. 37.1 — its hooks are filed at an address's own route; under a
|
|
53
|
-
* `lib`
|
|
54
|
-
*
|
|
55
|
-
*
|
|
41
|
+
* `lib` directory, at the route of the directory holding it, so a component an admin page renders
|
|
42
|
+
* runs under the admin route's rungs; under a `public` directory, for a dependency's file, and for
|
|
43
|
+
* the launcher (38.82), at the root's.
|
|
56
44
|
*
|
|
57
45
|
* `position` is RELATIVE TO THE APP'S ROOT: its directories are its route, so an absolute path would
|
|
58
46
|
* read the machine's directories as the app's.
|
|
@@ -70,7 +58,7 @@ export function placement(relative: string, position = relative): Placement {
|
|
|
70
58
|
? 'error'
|
|
71
59
|
: 'page'
|
|
72
60
|
scope = routeOf(position)
|
|
73
|
-
} else if (place === 'lib'
|
|
61
|
+
} else if (place === 'lib') {
|
|
74
62
|
const parts = position.split('/')
|
|
75
63
|
// The fence `placeOf` named is the first one, and its name is its place.
|
|
76
64
|
scope = `/${parts.slice(0, parts.indexOf(place)).join('/')}`
|
|
@@ -92,9 +80,7 @@ export function placement(relative: string, position = relative): Placement {
|
|
|
92
80
|
* - `dependency` — 34.24: a package's, outside the root or under `node_modules`, whose directories
|
|
93
81
|
* are its package's layout and none of the app's;
|
|
94
82
|
* - `skipped` — under a dot directory, which no walk of the app enters;
|
|
95
|
-
* - `
|
|
96
|
-
* save a `server` under a `lib` or a `tests`, which is `server` — the fence the browser's bundle
|
|
97
|
-
* is checked against (16.29) is never hidden by one above it (23.16);
|
|
83
|
+
* - `public` or `lib` — 23.15: under that fence, the nearest to the root deciding;
|
|
98
84
|
* - `address` — 23.14: everywhere else, its directories the segments of its route.
|
|
99
85
|
*
|
|
100
86
|
* The last part is the file itself, so a path ending in `/` is a directory and every part is read.
|
|
@@ -102,20 +88,30 @@ export function placement(relative: string, position = relative): Placement {
|
|
|
102
88
|
export function placeOf(path: string): Place {
|
|
103
89
|
if (path.startsWith('../') || path.startsWith('/')) return 'dependency'
|
|
104
90
|
const parts = path.split('/')
|
|
105
|
-
// A `lib` or a `tests` met first, which a `server` below it still overrides.
|
|
106
|
-
let fence: Place | undefined
|
|
107
91
|
for (let index = 0; index < parts.length - 1; index += 1) {
|
|
108
92
|
const part = parts[index] as string
|
|
109
93
|
if (skipped(part))
|
|
110
|
-
return
|
|
111
|
-
if (
|
|
112
|
-
if (part === SERVER_DIRECTORY) return 'server'
|
|
113
|
-
} else if (RESERVED_DIRECTORIES.has(part)) {
|
|
114
|
-
if (!HOLDS_SERVER.has(part)) return part as Place
|
|
115
|
-
fence = part as Place
|
|
116
|
-
}
|
|
94
|
+
return part === 'node_modules' ? 'dependency' : 'skipped'
|
|
95
|
+
if (RESERVED_DIRECTORIES.has(part)) return part as Place
|
|
117
96
|
}
|
|
118
|
-
return
|
|
97
|
+
return 'address'
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** 16.29 — whether `path` names a server file, `<name>.server.<extension>`, which only the server loads. */
|
|
101
|
+
export function isServerFile(path: string): boolean {
|
|
102
|
+
return SERVER_FILE.test(path)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const SERVER_FILE = /[^/]\.server\.[^./]+$/
|
|
106
|
+
|
|
107
|
+
/** Whether `path` names a test file, which is never an address nor a module the app runs. */
|
|
108
|
+
export function isTestFile(path: string): boolean {
|
|
109
|
+
return path.endsWith('.test.ts')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Whether `path` names a declaration file, which the checker reads and nothing runs. */
|
|
113
|
+
export function isDeclarationFile(path: string): boolean {
|
|
114
|
+
return path.endsWith('.d.ts')
|
|
119
115
|
}
|
|
120
116
|
|
|
121
117
|
/** Whether a walk of the app passes over the entry `name`: a dot file or directory, or `node_modules`. */
|
|
@@ -145,23 +141,3 @@ export const DIRECTORY_FILES = new Set([
|
|
|
145
141
|
'layout.abide',
|
|
146
142
|
'error.abide',
|
|
147
143
|
])
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* The position of the file at the absolute `path`: the one a mount gives it where a directory in
|
|
151
|
-
* `mounted` holds it (23.19), its own below `root` where the root does, `undefined` otherwise.
|
|
152
|
-
*
|
|
153
|
-
* `mounted` is `Compilation.mounted`, a directory below the root to the position its files take —
|
|
154
|
-
* directory-shaped, because a module under a mounted `server` directory is placed by it too.
|
|
155
|
-
*/
|
|
156
|
-
export function positionOf(
|
|
157
|
-
root: string,
|
|
158
|
-
mounted: Readonly<Record<string, string>>,
|
|
159
|
-
path: string,
|
|
160
|
-
): string | undefined {
|
|
161
|
-
for (const directory in mounted) {
|
|
162
|
-
const prefix = `${resolve(root, directory)}/`
|
|
163
|
-
if (path.startsWith(prefix))
|
|
164
|
-
return `${mounted[directory]}${path.slice(prefix.length)}`
|
|
165
|
-
}
|
|
166
|
-
return path.startsWith(`${root}/`) ? path.slice(root.length + 1) : undefined
|
|
167
|
-
}
|
package/src/server/serveDev.ts
CHANGED
|
@@ -1,30 +1,17 @@
|
|
|
1
|
-
// THE FENCES: the
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// the
|
|
5
|
-
|
|
6
|
-
/** A module under one only the server loads. */
|
|
7
|
-
export const SERVER_DIRECTORY = 'server'
|
|
1
|
+
// THE FENCES: the two directory names that are never an address (23.15). `public` is answered as
|
|
2
|
+
// authored (36.11), and `lib` holds what is neither an address nor that. Every other directory under
|
|
3
|
+
// the root is a segment of the routes of the files directly in it (23.14), and holds nothing else
|
|
4
|
+
// (23.22). What only the server loads is a file's NAME rather than a directory's (16.29), and so is a
|
|
5
|
+
// test — `placement.ts` reads both.
|
|
8
6
|
|
|
9
7
|
/** A file under one is answered as authored, at the path above it. */
|
|
10
8
|
export const PUBLIC_DIRECTORY = 'public'
|
|
11
9
|
|
|
12
|
-
/** The app's own code that is no address: components
|
|
10
|
+
/** The app's own code that is no address: components and modules, both sides. */
|
|
13
11
|
export const LIB_DIRECTORY = 'lib'
|
|
14
12
|
|
|
15
|
-
/**
|
|
16
|
-
export const TESTS_DIRECTORY = 'tests'
|
|
17
|
-
|
|
18
|
-
/** All four, as the walk of the app tests a directory against them. */
|
|
13
|
+
/** Both, as the walk of the app tests a directory against them. */
|
|
19
14
|
export const RESERVED_DIRECTORIES: ReadonlySet<string> = new Set([
|
|
20
|
-
SERVER_DIRECTORY,
|
|
21
15
|
PUBLIC_DIRECTORY,
|
|
22
16
|
LIB_DIRECTORY,
|
|
23
|
-
TESTS_DIRECTORY,
|
|
24
|
-
])
|
|
25
|
-
|
|
26
|
-
/** 23.16 — the fences a `server` directory nests in: it fences a graph rather than an address. */
|
|
27
|
-
export const HOLDS_SERVER: ReadonlySet<string> = new Set([
|
|
28
|
-
LIB_DIRECTORY,
|
|
29
|
-
TESTS_DIRECTORY,
|
|
30
17
|
])
|