Skip to content

Commit dfd72d9

Browse files
authored
Add DB schema validation (#111)
* Add DB schema validation Closes #105 * Remove redundant .string()
1 parent e190626 commit dfd72d9

File tree

9 files changed

+96241
-95271
lines changed

9 files changed

+96241
-95271
lines changed

build/main.js

Lines changed: 96197 additions & 95267 deletions
Large diffs are not rendered by default.

deno.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"npm:@hapi/inert": "npm:@hapi/[email protected]",
5555
"npm:chalk": "npm:[email protected]",
5656
"npm:ws": "npm:[email protected]",
57+
"npm:zod": "npm:[email protected]",
5758
"npm:@types/ws": "npm:@types/[email protected]",
5859
"npm:joi": "npm:[email protected]",
5960
"npm:bottleneck": "npm:[email protected]",

deno.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/migrate.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@ export async function migrate (args: ArgumentsCamelCase<Params>): Promise<void>
2929
nconf.set(`database:backendOptions:${backend}`, fromConfigOpts)
3030
}
3131

32-
await initDB({ skipDbPreloading: true })
32+
try {
33+
await initDB({ skipDbPreloading: true })
34+
} catch (e) {
35+
console.error('Error setting up database')
36+
exit(e)
37+
throw e
38+
}
3339

3440
let backendTo: DatabaseBackend
3541
try {

src/serve/database-fs.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
import { Buffer } from 'node:buffer'
1+
import type { Buffer } from 'node:buffer'
22
import { mkdir, readdir, readFile, rm, unlink, writeFile } from 'node:fs/promises'
33
import { basename, dirname, join, normalize, resolve } from 'node:path'
44
import { checkKey } from 'npm:@chelonia/lib/db'
5+
import * as z from 'npm:zod'
56
import DatabaseBackend from './DatabaseBackend.ts'
67

8+
const ConfigSchema = z.strictObject({
9+
dirname: z.optional(z.string()),
10+
depth: z.optional(z.number()),
11+
keyChunkLength: z.optional(z.number()),
12+
skipFsCaseSensitivityCheck: z.optional(z.boolean()),
13+
})
14+
715
// Some operating systems (such as macOS and Windows) use case-insensitive
816
// filesystems by default. This can be problematic for Chelonia / Group Income,
917
// as we rely on keys being case-sensitive. This is especially relevant for CIDs,
@@ -48,6 +56,7 @@ export default class FsBackend extends DatabaseBackend {
4856

4957
constructor (options: { dirname?: string; depth?: number; keyChunkLength?: number, skipFsCaseSensitivityCheck?: boolean } = {}) {
5058
super()
59+
ConfigSchema.parse(options)
5160
if (options.dirname) this.dataFolder = resolve(options.dirname)
5261
if (options.depth) this.depth = options.depth
5362
if (options.keyChunkLength) this.keyChunkLength = options.keyChunkLength

src/serve/database-redis.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
import { Buffer } from 'node:buffer'
22
import { RESP_TYPES, createClient, type RedisClientType } from 'npm:redis'
3+
import * as z from 'npm:zod'
34
import DatabaseBackend from './DatabaseBackend.ts'
45

6+
const ConfigSchema = z.strictObject({
7+
url: z.optional(z.url({ protocol: /^rediss?$/ })),
8+
})
9+
510
export default class RedisBackend extends DatabaseBackend {
611
db: RedisClientType | null = null
712
url: string | undefined
813

914
constructor (options: { url?: string } = {}) {
1015
super()
16+
ConfigSchema.parse(options)
1117
this.url = options.url
1218
}
1319

src/serve/database-router.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import type { Buffer } from 'node:buffer'
2+
import * as z from 'npm:zod'
23
import DatabaseBackend from './DatabaseBackend.ts'
34

5+
const ConfigEntrySchema = z.strictObject({
6+
name: z.string(),
7+
options: z.object()
8+
})
9+
const ConfigSchema = z.intersection(
10+
z.object({ '*': ConfigEntrySchema }),
11+
z.record(z.string(), ConfigEntrySchema)
12+
)
13+
414
type ConfigEntry = { name: string; options: Record<string, unknown> }
515
type Config = {
616
[key: string]: ConfigEntry
@@ -13,6 +23,7 @@ export default class RouterBackend extends DatabaseBackend {
1323
constructor (config: Config = {}) {
1424
super()
1525
// Return a sorted copy where entries with longer keys come first.
26+
ConfigSchema.parse(config)
1627
const configCopy = Object.fromEntries(Object.entries(config).sort((a, b) => b[0].length - a[0].length)) as Config
1728
const errors = this.validateConfig(configCopy)
1829
if (errors.length) {

src/serve/database-sqlite.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ import * as sqlite from 'jsr:@db/sqlite'
33
import { Buffer } from 'node:buffer'
44
import { mkdir } from 'node:fs/promises'
55
import { basename, dirname, join, resolve } from 'node:path'
6+
import * as z from 'npm:zod'
67
import DatabaseBackend from './DatabaseBackend.ts'
78

9+
const ConfigSchema = z.strictObject({
10+
filepath: z.optional(z.string()),
11+
})
12+
813
export default class SqliteBackend extends DatabaseBackend {
914
dataFolder: string = 'data'
1015
db: SQLiteDB | null = null
@@ -17,6 +22,7 @@ export default class SqliteBackend extends DatabaseBackend {
1722

1823
constructor (options: { filepath?: string } = {}) {
1924
super()
25+
ConfigSchema.parse(options)
2026
const { filepath } = options
2127
if (!filepath) return
2228
const resolvedPath = resolve(filepath)

src/serve/database.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Buffer } from 'node:buffer'
1+
import type { Buffer } from 'node:buffer'
22
import process from 'node:process'
33
import { Readable } from 'node:stream'
44
import 'npm:@chelonia/lib/chelonia'

0 commit comments

Comments
 (0)