@@ -0,0 +1,81 @@
|
||||
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
||||
// A write never reloads to show itself (AGENTS.md, "The recipe for a module", steps 5 and 9).
|
||||
//
|
||||
// - No module reloads the document: `location.reload()` throws the page's state away and reads every
|
||||
// loader again, where a live read changes only what changed.
|
||||
// - A module that declares a live collection writes through `useWrite`, which resolves once the
|
||||
// organization's live stream has seen the write, so every live read on the page already shows it.
|
||||
// Its UI re-runs no loader after a write (`usePageNavigation().refresh()`, `router.invalidate()`):
|
||||
// a page of it reads through `useLive` or a `useRead` kept live by the module's entities.
|
||||
//
|
||||
// Which modules declare a collection comes from their own manifests, every module whose source is
|
||||
// here, selected or not: a module that is switched on later is held to the same rule.
|
||||
|
||||
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"
|
||||
import { join, relative } from "node:path"
|
||||
import type { ModuleManifest } from "@conusai-kit/core"
|
||||
import { describe, expect, it } from "vitest"
|
||||
|
||||
const root = new URL("..", import.meta.url).pathname
|
||||
const modulesDir = join(root, "modules")
|
||||
|
||||
const RELOAD = /\blocation\s*(?:\.\s*reload\b|\[\s*["'`]reload["'`]\s*\])/
|
||||
const LOADER_RERUN = /\.\s*refresh\s*\(|\brouter\s*\.\s*invalidate\s*\(/
|
||||
|
||||
function sources(dir: string): string[] {
|
||||
if (!existsSync(dir)) return []
|
||||
return readdirSync(dir).flatMap((name) => {
|
||||
const path = join(dir, name)
|
||||
if (statSync(path).isDirectory()) return name === "node_modules" || name === "dist" ? [] : sources(path)
|
||||
return /\.(?:ts|tsx|mts)$/.test(name) ? [path] : []
|
||||
})
|
||||
}
|
||||
|
||||
const moduleIds = readdirSync(modulesDir).filter((name) => existsSync(join(modulesDir, name, "index.ts")))
|
||||
|
||||
const isManifest = (value: unknown): value is ModuleManifest =>
|
||||
typeof value === "object" && value !== null && "id" in value && "procedures" in value
|
||||
|
||||
/** The ids of the source modules whose manifests declare at least one live collection. */
|
||||
async function modulesWithCollections(): Promise<string[]> {
|
||||
const found = new Set<string>()
|
||||
for (const id of moduleIds) {
|
||||
const exports = (await import(join(modulesDir, id, "index.ts"))) as Record<string, unknown>
|
||||
for (const value of Object.values(exports)) {
|
||||
if (isManifest(value) && (value.collections?.length ?? 0) > 0) found.add(id)
|
||||
}
|
||||
}
|
||||
return [...found].sort()
|
||||
}
|
||||
|
||||
/** `file:line: text` for each line of `files` that matches `pattern`, outside comments. */
|
||||
function offending(files: readonly string[], pattern: RegExp): string[] {
|
||||
return files.flatMap((file) =>
|
||||
readFileSync(file, "utf8")
|
||||
.split("\n")
|
||||
.flatMap((line, index) => {
|
||||
const code = line.replace(/\/\/.*$/, "")
|
||||
return pattern.test(code) ? [`${relative(root, file)}:${index + 1}: ${line.trim()}`] : []
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
describe("a write never reloads to show itself", () => {
|
||||
it("no module reloads the document", () => {
|
||||
expect(offending(sources(modulesDir), RELOAD)).toEqual([])
|
||||
})
|
||||
|
||||
// kit:notes:begin
|
||||
it("finds the modules that declare live collections from their manifests", async () => {
|
||||
// notes is the worked example; if it stops declaring one, the next test proves nothing about it.
|
||||
expect(await modulesWithCollections()).toContain("notes")
|
||||
})
|
||||
// kit:notes:end
|
||||
|
||||
it("a module with a live collection re-runs no loader after a write", async () => {
|
||||
const problems = (await modulesWithCollections()).flatMap((id) =>
|
||||
offending(sources(join(modulesDir, id, "ui")), LOADER_RERUN),
|
||||
)
|
||||
expect(problems, "write with useWrite and read with useLive or a live useRead").toEqual([])
|
||||
}, 120_000)
|
||||
})
|
||||
Reference in New Issue
Block a user