@loadbare/app 0.22.0 → 0.23.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/dist/build/build.d.ts +16 -0
- package/dist/build/build.d.ts.map +1 -1
- package/dist/build/build.js +77 -5
- package/dist/build/build.js.map +1 -1
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +12 -6
- package/dist/hub/lb-apply.js.map +1 -1
- package/docs/miswarts.md +3 -2
- package/docs/reference/data-binding.md +13 -9
- package/docs/reference/dev-server.md +10 -3
- package/docs/temp-proposals.md +251 -0
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +2 -1
- package/skills/loadbare-app/references/data-binding.md +13 -9
- package/skills/loadbare-app/references/dev-server.md +10 -3
- package/skills/loadbare-app/references/miswarts.md +3 -2
package/dist/build/build.d.ts
CHANGED
|
@@ -59,4 +59,20 @@ export interface AppWatcher {
|
|
|
59
59
|
* never overlap and never fall behind.
|
|
60
60
|
*/
|
|
61
61
|
export declare function watchApp(options?: WatchOptions): AppWatcher;
|
|
62
|
+
/**
|
|
63
|
+
* Watch every directory under `root`, and each one made later, and report
|
|
64
|
+
* each file an event names, relative to `root`. A directory `skip` answers
|
|
65
|
+
* true for, relative to `root`, is not watched, nor is anything under it.
|
|
66
|
+
*
|
|
67
|
+
* Directories rather than `recursive: true`: on Linux, Node's recursive
|
|
68
|
+
* watch follows each file, so a file saved by replacing it, as `sed -i` and
|
|
69
|
+
* many editors save, is never heard from again. A directory's watch outlives
|
|
70
|
+
* every file in it.
|
|
71
|
+
*
|
|
72
|
+
* A directory made after the watch began may hold files before its own
|
|
73
|
+
* watch starts, so each file found in it is reported.
|
|
74
|
+
*/
|
|
75
|
+
export declare function watchTree(root: string, onFile: (file: string) => void, skip?: (dir: string) => boolean): {
|
|
76
|
+
close(): void;
|
|
77
|
+
};
|
|
62
78
|
//# sourceMappingURL=build.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../build/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,KAAK;IACpB,kCAAkC;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,wBAAsB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAgEzE;AAED,sCAAsC;AACtC,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACtC,gFAAgF;IAChF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7B,uDAAuD;IACvD,KAAK,IAAI,IAAI,CAAC;CACf;AAYD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,UAAU,CA6D/D"}
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../build/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,KAAK;IACpB,kCAAkC;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,wBAAsB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAgEzE;AAED,sCAAsC;AACtC,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACtC,gFAAgF;IAChF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7B,uDAAuD;IACvD,KAAK,IAAI,IAAI,CAAC;CACf;AAYD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,UAAU,CA6D/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAC9B,IAAI,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAqB,GAC3C;IAAE,KAAK,IAAI,IAAI,CAAA;CAAE,CAqDnB"}
|
package/dist/build/build.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* leaves the last good build in place, so a server reading `dist/` keeps
|
|
11
11
|
* serving something coherent while the developer fixes the mistake.
|
|
12
12
|
*/
|
|
13
|
-
import { watch as
|
|
13
|
+
import { readdirSync, statSync, watch as watchDir } from "node:fs";
|
|
14
14
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import * as esbuild from "esbuild";
|
|
@@ -121,8 +121,8 @@ export function watchApp(options = {}) {
|
|
|
121
121
|
void drain();
|
|
122
122
|
return outcome;
|
|
123
123
|
});
|
|
124
|
-
const
|
|
125
|
-
if (closed || !
|
|
124
|
+
const tree = watchTree(src, (file) => {
|
|
125
|
+
if (closed || !BUILT_FROM.test(file) || inOut(file))
|
|
126
126
|
return;
|
|
127
127
|
pending.add(file.split(path.sep).join("/"));
|
|
128
128
|
if (running || timer)
|
|
@@ -135,14 +135,86 @@ export function watchApp(options = {}) {
|
|
|
135
135
|
void drain();
|
|
136
136
|
});
|
|
137
137
|
}, SETTLE_MS);
|
|
138
|
-
});
|
|
138
|
+
}, inOut);
|
|
139
139
|
return {
|
|
140
140
|
ready,
|
|
141
141
|
close() {
|
|
142
142
|
closed = true;
|
|
143
143
|
clearTimeout(timer);
|
|
144
|
-
|
|
144
|
+
tree.close();
|
|
145
145
|
},
|
|
146
146
|
};
|
|
147
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Watch every directory under `root`, and each one made later, and report
|
|
150
|
+
* each file an event names, relative to `root`. A directory `skip` answers
|
|
151
|
+
* true for, relative to `root`, is not watched, nor is anything under it.
|
|
152
|
+
*
|
|
153
|
+
* Directories rather than `recursive: true`: on Linux, Node's recursive
|
|
154
|
+
* watch follows each file, so a file saved by replacing it, as `sed -i` and
|
|
155
|
+
* many editors save, is never heard from again. A directory's watch outlives
|
|
156
|
+
* every file in it.
|
|
157
|
+
*
|
|
158
|
+
* A directory made after the watch began may hold files before its own
|
|
159
|
+
* watch starts, so each file found in it is reported.
|
|
160
|
+
*/
|
|
161
|
+
export function watchTree(root, onFile, skip = () => false) {
|
|
162
|
+
const watchers = new Map();
|
|
163
|
+
const drop = (dir) => {
|
|
164
|
+
for (const [watched, watcher] of watchers) {
|
|
165
|
+
if (dir === "" || watched === dir || watched.startsWith(dir + path.sep)) {
|
|
166
|
+
watcher.close();
|
|
167
|
+
watchers.delete(watched);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const changed = (file) => {
|
|
172
|
+
let isDir = false;
|
|
173
|
+
try {
|
|
174
|
+
isDir = statSync(path.join(root, file)).isDirectory();
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Gone: a deleted file is a change, and a deleted directory's watch ends.
|
|
178
|
+
}
|
|
179
|
+
if (isDir) {
|
|
180
|
+
if (!watchers.has(file))
|
|
181
|
+
add(file, true);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
drop(file);
|
|
185
|
+
onFile(file);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const add = (dir, report) => {
|
|
189
|
+
if (skip(dir))
|
|
190
|
+
return;
|
|
191
|
+
const full = path.join(root, dir);
|
|
192
|
+
let watcher;
|
|
193
|
+
let entries;
|
|
194
|
+
try {
|
|
195
|
+
watcher = watchDir(full, (_event, name) => {
|
|
196
|
+
if (name)
|
|
197
|
+
changed(path.join(dir, name.toString()));
|
|
198
|
+
});
|
|
199
|
+
entries = readdirSync(full, { withFileTypes: true });
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
// The root must exist; a directory below it may be gone already.
|
|
203
|
+
if (dir === "")
|
|
204
|
+
throw err;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
watcher.on("error", () => drop(dir));
|
|
208
|
+
watchers.set(dir, watcher);
|
|
209
|
+
for (const entry of entries) {
|
|
210
|
+
const child = path.join(dir, entry.name);
|
|
211
|
+
if (entry.isDirectory())
|
|
212
|
+
add(child, report);
|
|
213
|
+
else if (report)
|
|
214
|
+
onFile(child);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
add("", false);
|
|
218
|
+
return { close: () => drop("") };
|
|
219
|
+
}
|
|
148
220
|
//# sourceMappingURL=build.js.map
|
package/dist/build/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../build/build.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The build, as a library: one build, or a watch that rebuilds and says when\n * each build has ended. `loadbare-app-build` (build/cli.ts) is a thin\n * command over these, and `@loadbare/app/dev` runs the watch in process.\n *\n * Paths resolve against the working directory, as the command's do, so a\n * caller runs from the application's root.\n *\n * A build writes nothing until every output is in hand. One that fails\n * leaves the last good build in place, so a server reading `dist/` keeps\n * serving something coherent while the developer fixes the mistake.\n */\n\nimport { watch as watchFiles } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport * as esbuild from \"esbuild\";\nimport { assemble } from \"./assemble.js\";\nimport { loadDeclared } from \"./declared.js\";\nimport {\n checkReservedMethods,\n clientEntrySource,\n resolveElements,\n} from \"./elements.js\";\nimport { resolveLocations } from \"./locations.js\";\nimport { cssFrom, scanAll } from \"./origins.js\";\nimport { pagesSource } from \"./pages.js\";\nimport { stylesSource } from \"./styles.js\";\n\nexport interface BuildOptions {\n /** The application's source tree, `src` when absent. */\n src?: string;\n /** Where the output lands, `dist` when absent. */\n out?: string;\n /** Minify `client.js` and `app.css`. */\n minify?: boolean;\n}\n\nexport interface Built {\n /** Every file the build wrote. */\n files: string[];\n /** How many custom elements `client.js` registers. */\n elements: number;\n /** One line saying what was written, as the command prints it. */\n summary: string;\n}\n\n/** Build once. Throws, having written nothing, when the build fails. */\nexport async function buildApp(options: BuildOptions = {}): Promise<Built> {\n const src = options.src ?? \"src\";\n const minify = options.minify ?? false;\n const locations = await resolveLocations({ src, out: options.out ?? \"dist\" });\n const { outDir } = locations;\n const entryFile = path.join(outDir, \"client-entry.ts\");\n\n const scans = await scanAll(locations, src, locations.importsFile);\n await mkdir(outDir, { recursive: true });\n const declared = await loadDeclared(\n locations.pages,\n locations.pageSources,\n outDir,\n );\n const { html, usedTags } = await assemble({ ...locations, scans, declared });\n\n const { resolved } = resolveElements({ used: usedTags, scans });\n await checkReservedMethods(resolved);\n // The entry is read by the bundler and never served, so it is written now.\n await writeFile(entryFile, clientEntrySource(resolved, outDir), \"utf-8\");\n const bundle = await esbuild.build({\n entryPoints: [entryFile],\n bundle: true,\n format: \"iife\",\n outfile: path.join(outDir, \"client.js\"),\n minify,\n write: false,\n // esbuild keeps the directory it started in; the paths are the caller's.\n absWorkingDir: process.cwd(),\n });\n\n const outputs = new Map<string, string | Uint8Array>();\n outputs.set(path.join(outDir, \"app.html\"), html);\n for (const file of bundle.outputFiles) outputs.set(file.path, file.contents);\n\n const pages = pagesSource(\n locations.pages,\n locations.pageSources,\n outDir,\n locations.packageName,\n );\n if (pages) outputs.set(path.join(outDir, \"pages.ts\"), pages);\n\n const css = await stylesSource(cssFrom(scans));\n if (css) {\n const code = minify\n ? (await esbuild.transform(css, { loader: \"css\", minify: true })).code\n : css;\n outputs.set(path.join(outDir, \"app.css\"), code);\n }\n\n for (const [file, content] of outputs) await writeFile(file, content);\n\n const files = [...outputs.keys()].map((file) =>\n path.relative(process.cwd(), file),\n );\n const elements = resolved.size;\n return {\n files,\n elements,\n summary:\n `wrote ${files.join(\" and \")} ` +\n `(${elements} custom element${elements === 1 ? \"\" : \"s\"})`,\n };\n}\n\n/** How one build of a watch ended. */\nexport type BuildOutcome =\n | { ok: true; changed: string[]; built: Built }\n | { ok: false; changed: string[]; error: Error };\n\nexport interface WatchOptions extends BuildOptions {\n /**\n * A build is starting, for these changed files under `src`, relative to\n * it. Empty for the first build.\n */\n onStart?: (changed: string[]) => void;\n /** A build has ended, well or badly. A failed build does not stop the watch. */\n onBuilt?: (outcome: BuildOutcome) => void;\n}\n\nexport interface AppWatcher {\n /** How the first build ended. */\n ready: Promise<BuildOutcome>;\n /** Stop watching. A build already running finishes. */\n close(): void;\n}\n\n/** The files a build reads. A change to any other file starts no build. */\nconst BUILT_FROM = /\\.(html|ts|css)$/;\n\n/**\n * Edits arrive in bursts: an editor's save is often several events, and a\n * branch switch is hundreds. Waiting this long after the first lets the\n * burst finish, so it starts one build.\n */\nconst SETTLE_MS = 20;\n\n/**\n * Build, then build again whenever a file under `src` changes. Changes that\n * arrive while a build runs are gathered into one build after it, so builds\n * never overlap and never fall behind.\n */\nexport function watchApp(options: WatchOptions = {}): AppWatcher {\n const src = options.src ?? \"src\";\n // An output directory inside the source tree is written by every build,\n // and a change there must not start the next one.\n const out = path.relative(path.resolve(src), path.resolve(options.out ?? \"dist\"));\n const inOut = (file: string) =>\n out !== \"\" && !out.startsWith(\"..\") && (file === out || file.startsWith(out + path.sep));\n let pending = new Set<string>();\n let running = false;\n let timer: NodeJS.Timeout | undefined;\n let closed = false;\n\n const once = async (changed: string[]): Promise<BuildOutcome> => {\n options.onStart?.(changed);\n let outcome: BuildOutcome;\n try {\n outcome = { ok: true, changed, built: await buildApp(options) };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n outcome = { ok: false, changed, error };\n }\n options.onBuilt?.(outcome);\n return outcome;\n };\n\n const drain = async (): Promise<void> => {\n running = true;\n while (pending.size > 0 && !closed) {\n const changed = [...pending].sort();\n pending = new Set();\n await once(changed);\n }\n running = false;\n };\n\n const ready = once([]).then((outcome) => {\n if (pending.size > 0) void drain();\n return outcome;\n });\n\n const watcher = watchFiles(src, { recursive: true }, (_event, file) => {\n if (closed || !file || !BUILT_FROM.test(file) || inOut(file)) return;\n pending.add(file.split(path.sep).join(\"/\"));\n if (running || timer) return;\n timer = setTimeout(() => {\n timer = undefined;\n // The first build is still running: it starts the next when it ends.\n void ready.then(() => {\n if (!running) void drain();\n });\n }, SETTLE_MS);\n });\n\n return {\n ready,\n close() {\n closed = true;\n clearTimeout(timer);\n watcher.close();\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../build/build.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The build, as a library: one build, or a watch that rebuilds and says when\n * each build has ended. `loadbare-app-build` (build/cli.ts) is a thin\n * command over these, and `@loadbare/app/dev` runs the watch in process.\n *\n * Paths resolve against the working directory, as the command's do, so a\n * caller runs from the application's root.\n *\n * A build writes nothing until every output is in hand. One that fails\n * leaves the last good build in place, so a server reading `dist/` keeps\n * serving something coherent while the developer fixes the mistake.\n */\n\nimport { readdirSync, statSync, watch as watchDir, type FSWatcher } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport * as esbuild from \"esbuild\";\nimport { assemble } from \"./assemble.js\";\nimport { loadDeclared } from \"./declared.js\";\nimport {\n checkReservedMethods,\n clientEntrySource,\n resolveElements,\n} from \"./elements.js\";\nimport { resolveLocations } from \"./locations.js\";\nimport { cssFrom, scanAll } from \"./origins.js\";\nimport { pagesSource } from \"./pages.js\";\nimport { stylesSource } from \"./styles.js\";\n\nexport interface BuildOptions {\n /** The application's source tree, `src` when absent. */\n src?: string;\n /** Where the output lands, `dist` when absent. */\n out?: string;\n /** Minify `client.js` and `app.css`. */\n minify?: boolean;\n}\n\nexport interface Built {\n /** Every file the build wrote. */\n files: string[];\n /** How many custom elements `client.js` registers. */\n elements: number;\n /** One line saying what was written, as the command prints it. */\n summary: string;\n}\n\n/** Build once. Throws, having written nothing, when the build fails. */\nexport async function buildApp(options: BuildOptions = {}): Promise<Built> {\n const src = options.src ?? \"src\";\n const minify = options.minify ?? false;\n const locations = await resolveLocations({ src, out: options.out ?? \"dist\" });\n const { outDir } = locations;\n const entryFile = path.join(outDir, \"client-entry.ts\");\n\n const scans = await scanAll(locations, src, locations.importsFile);\n await mkdir(outDir, { recursive: true });\n const declared = await loadDeclared(\n locations.pages,\n locations.pageSources,\n outDir,\n );\n const { html, usedTags } = await assemble({ ...locations, scans, declared });\n\n const { resolved } = resolveElements({ used: usedTags, scans });\n await checkReservedMethods(resolved);\n // The entry is read by the bundler and never served, so it is written now.\n await writeFile(entryFile, clientEntrySource(resolved, outDir), \"utf-8\");\n const bundle = await esbuild.build({\n entryPoints: [entryFile],\n bundle: true,\n format: \"iife\",\n outfile: path.join(outDir, \"client.js\"),\n minify,\n write: false,\n // esbuild keeps the directory it started in; the paths are the caller's.\n absWorkingDir: process.cwd(),\n });\n\n const outputs = new Map<string, string | Uint8Array>();\n outputs.set(path.join(outDir, \"app.html\"), html);\n for (const file of bundle.outputFiles) outputs.set(file.path, file.contents);\n\n const pages = pagesSource(\n locations.pages,\n locations.pageSources,\n outDir,\n locations.packageName,\n );\n if (pages) outputs.set(path.join(outDir, \"pages.ts\"), pages);\n\n const css = await stylesSource(cssFrom(scans));\n if (css) {\n const code = minify\n ? (await esbuild.transform(css, { loader: \"css\", minify: true })).code\n : css;\n outputs.set(path.join(outDir, \"app.css\"), code);\n }\n\n for (const [file, content] of outputs) await writeFile(file, content);\n\n const files = [...outputs.keys()].map((file) =>\n path.relative(process.cwd(), file),\n );\n const elements = resolved.size;\n return {\n files,\n elements,\n summary:\n `wrote ${files.join(\" and \")} ` +\n `(${elements} custom element${elements === 1 ? \"\" : \"s\"})`,\n };\n}\n\n/** How one build of a watch ended. */\nexport type BuildOutcome =\n | { ok: true; changed: string[]; built: Built }\n | { ok: false; changed: string[]; error: Error };\n\nexport interface WatchOptions extends BuildOptions {\n /**\n * A build is starting, for these changed files under `src`, relative to\n * it. Empty for the first build.\n */\n onStart?: (changed: string[]) => void;\n /** A build has ended, well or badly. A failed build does not stop the watch. */\n onBuilt?: (outcome: BuildOutcome) => void;\n}\n\nexport interface AppWatcher {\n /** How the first build ended. */\n ready: Promise<BuildOutcome>;\n /** Stop watching. A build already running finishes. */\n close(): void;\n}\n\n/** The files a build reads. A change to any other file starts no build. */\nconst BUILT_FROM = /\\.(html|ts|css)$/;\n\n/**\n * Edits arrive in bursts: an editor's save is often several events, and a\n * branch switch is hundreds. Waiting this long after the first lets the\n * burst finish, so it starts one build.\n */\nconst SETTLE_MS = 20;\n\n/**\n * Build, then build again whenever a file under `src` changes. Changes that\n * arrive while a build runs are gathered into one build after it, so builds\n * never overlap and never fall behind.\n */\nexport function watchApp(options: WatchOptions = {}): AppWatcher {\n const src = options.src ?? \"src\";\n // An output directory inside the source tree is written by every build,\n // and a change there must not start the next one.\n const out = path.relative(path.resolve(src), path.resolve(options.out ?? \"dist\"));\n const inOut = (file: string) =>\n out !== \"\" && !out.startsWith(\"..\") && (file === out || file.startsWith(out + path.sep));\n let pending = new Set<string>();\n let running = false;\n let timer: NodeJS.Timeout | undefined;\n let closed = false;\n\n const once = async (changed: string[]): Promise<BuildOutcome> => {\n options.onStart?.(changed);\n let outcome: BuildOutcome;\n try {\n outcome = { ok: true, changed, built: await buildApp(options) };\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n outcome = { ok: false, changed, error };\n }\n options.onBuilt?.(outcome);\n return outcome;\n };\n\n const drain = async (): Promise<void> => {\n running = true;\n while (pending.size > 0 && !closed) {\n const changed = [...pending].sort();\n pending = new Set();\n await once(changed);\n }\n running = false;\n };\n\n const ready = once([]).then((outcome) => {\n if (pending.size > 0) void drain();\n return outcome;\n });\n\n const tree = watchTree(src, (file) => {\n if (closed || !BUILT_FROM.test(file) || inOut(file)) return;\n pending.add(file.split(path.sep).join(\"/\"));\n if (running || timer) return;\n timer = setTimeout(() => {\n timer = undefined;\n // The first build is still running: it starts the next when it ends.\n void ready.then(() => {\n if (!running) void drain();\n });\n }, SETTLE_MS);\n }, inOut);\n\n return {\n ready,\n close() {\n closed = true;\n clearTimeout(timer);\n tree.close();\n },\n };\n}\n\n/**\n * Watch every directory under `root`, and each one made later, and report\n * each file an event names, relative to `root`. A directory `skip` answers\n * true for, relative to `root`, is not watched, nor is anything under it.\n *\n * Directories rather than `recursive: true`: on Linux, Node's recursive\n * watch follows each file, so a file saved by replacing it, as `sed -i` and\n * many editors save, is never heard from again. A directory's watch outlives\n * every file in it.\n *\n * A directory made after the watch began may hold files before its own\n * watch starts, so each file found in it is reported.\n */\nexport function watchTree(\n root: string,\n onFile: (file: string) => void,\n skip: (dir: string) => boolean = () => false,\n): { close(): void } {\n const watchers = new Map<string, FSWatcher>();\n\n const drop = (dir: string) => {\n for (const [watched, watcher] of watchers) {\n if (dir === \"\" || watched === dir || watched.startsWith(dir + path.sep)) {\n watcher.close();\n watchers.delete(watched);\n }\n }\n };\n\n const changed = (file: string) => {\n let isDir = false;\n try {\n isDir = statSync(path.join(root, file)).isDirectory();\n } catch {\n // Gone: a deleted file is a change, and a deleted directory's watch ends.\n }\n if (isDir) {\n if (!watchers.has(file)) add(file, true);\n } else {\n drop(file);\n onFile(file);\n }\n };\n\n const add = (dir: string, report: boolean) => {\n if (skip(dir)) return;\n const full = path.join(root, dir);\n let watcher: FSWatcher;\n let entries;\n try {\n watcher = watchDir(full, (_event, name) => {\n if (name) changed(path.join(dir, name.toString()));\n });\n entries = readdirSync(full, { withFileTypes: true });\n } catch (err) {\n // The root must exist; a directory below it may be gone already.\n if (dir === \"\") throw err;\n return;\n }\n watcher.on(\"error\", () => drop(dir));\n watchers.set(dir, watcher);\n for (const entry of entries) {\n const child = path.join(dir, entry.name);\n if (entry.isDirectory()) add(child, report);\n else if (report) onFile(child);\n }\n };\n\n add(\"\", false);\n return { close: () => drop(\"\") };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"AAoFA,OAAO,EASL,KAAK,WAAW,EAKhB,KAAK,YAAY,EACjB,KAAK,GAAG,EACR,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AA0B7B,mEAAmE;AACnE,MAAM,WAAW,OAAQ,SAAQ,OAAO;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AA4BD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAE5C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAGrD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,OAAO,CAIpD;AAUD;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,OAAO,GACV,IAAI,CAMN;
|
|
1
|
+
{"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"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"}
|
package/dist/hub/lb-apply.js
CHANGED
|
@@ -141,9 +141,11 @@ function land(el, value) {
|
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
143
|
if (isCheckbox(el)) {
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
144
|
+
// Off for false, and for what an unchecked checkbox gathers or an absent
|
|
145
|
+
// query parm lands as, so a checkbox lands what it gathered even from a
|
|
146
|
+
// query whose values are strings, such as lb-url.
|
|
147
|
+
el.checked =
|
|
148
|
+
value !== false && value !== "false" && value !== "";
|
|
147
149
|
}
|
|
148
150
|
else if (isRadio(el)) {
|
|
149
151
|
el.checked =
|
|
@@ -1014,7 +1016,8 @@ function hide(el, hidden) {
|
|
|
1014
1016
|
}
|
|
1015
1017
|
/**
|
|
1016
1018
|
* Finish a group and everything under it, from the rows it shows: each
|
|
1017
|
-
* heading filled from the first, as it was when last placed by
|
|
1019
|
+
* heading filled and linked from the first, as it was when last placed by
|
|
1020
|
+
* the order,
|
|
1018
1021
|
* each aggregate set from all of them, and a group hidden when a filter hides
|
|
1019
1022
|
* every row in it. The rows it shows are returned.
|
|
1020
1023
|
*/
|
|
@@ -1032,9 +1035,12 @@ function finish(group, types) {
|
|
|
1032
1035
|
}
|
|
1033
1036
|
}
|
|
1034
1037
|
}
|
|
1035
|
-
if (shown[0])
|
|
1036
|
-
for (const head of group.heads)
|
|
1038
|
+
if (shown[0]) {
|
|
1039
|
+
for (const head of group.heads) {
|
|
1037
1040
|
fill(head, shown[0].placed);
|
|
1041
|
+
link(head, shown[0].placed);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1038
1044
|
aggregate(group.aggregates, rows, types);
|
|
1039
1045
|
return shown;
|
|
1040
1046
|
}
|