1const db = getDb("cache.sqlite");
2
3db.table(
4 "permissions",
5 /* SQL */ `
6 create table if not exists permissions (
7 prefix text primary key,
8 allow integer not null
9 );
10`,
11);
12export class FilePermissions {
13 prefix!: string;
14 /** Currently set to 1 always */
15 allow!: number;
16
17 // -- static ops --
18 static getByPrefix(filePath: string): number {
19 return getByPrefixQuery.get(filePath)?.allow ?? 0;
20 }
21
22 static getExact(filePath: string): number {
23 return getExactQuery.get(filePath)?.allow ?? 0;
24 }
25
26 static setPermissions(prefix: string, allow: number) {
27 if (allow) {
28 insertQuery.run({ prefix, allow });
29 } else {
30 deleteQuery.run(prefix);
31 }
32 }
33}
34
35// comparisons fold case to match the file store: a permission on
36// "/2026/friends" must also gate a request spelled "/2026/Friends"
37const getByPrefixQuery = db.prepare<
38 [prefix: string],
39 Pick<FilePermissions, "allow">
40>(/* SQL */ `
41 select allow
42 from permissions
43 where lower(?) glob lower(prefix) || '*'
44 order by length(prefix) desc
45 limit 1;
46`);
47const getExactQuery = db.prepare<
48 [file: string],
49 Pick<FilePermissions, "allow">
50>(/* SQL */ `
51 select allow from permissions where ? == prefix collate nocase
52`);
53
54const insertQuery = db.prepare<[{ prefix: string; allow: number }]>(/* SQL */ `
55 replace into permissions(prefix, allow) values($prefix, $allow);
56`);
57const deleteQuery = db.prepare<[file: string]>(/* SQL */ `
58 delete from permissions where prefix = ?;
59`);
60
61import { getDb } from "#sitegen/sqlite";