import { GenericId } from "../values/index.js"; import { test } from "vitest"; import { assert, assertFalse, Equals } from "../test/type_testing.js"; import { GenericDatabaseWriter } from "./database.js"; import { SystemTableNames } from "./schema.js"; type CreateDataModel = { tableName: { document: Document; fieldPaths: "body" | "_id"; indexes: {}; searchIndexes: {}; vectorIndexes: {}; }; }; test("DatabaseWriter has the right types for a simple data model", () => { type Document = { body: string; _id: GenericId<"tableName">; _creationTime: number; }; type DB = GenericDatabaseWriter>; type InsertType = Parameters; type ExpectedInsertType = [table: "tableName", value: { body: string }]; assert>(); type PatchType = Parameters; type ExpectedPatchType = [ id: GenericId<"tableName">, value: { body?: string; _id?: GenericId<"tableName">; _creationTime?: number; }, ]; assert>(); type ReplaceType = Parameters; type ExpectedReplaceType = [ id: GenericId<"tableName">, value: { body: string; _id?: GenericId<"tableName">; _creationTime?: number; }, ]; assert>(); }); test("DatabaseWriter has the right types for a union", () => { // This data model discriminates on `type`. It only has a `body` field if // the type is "text". type Document = | { type: "text"; body: string; _id: GenericId<"tableName">; _creationTime: number; } | { type: "giphy"; _id: GenericId<"tableName">; _creationTime: number; }; type DB = GenericDatabaseWriter>; type InsertType = Parameters; type Expected = [ "tableName", { type: "text"; body: string } | { type: "giphy" }, ]; assert>(); type PatchType = Parameters; type ExpectedPatchType = [ id: GenericId<"tableName">, value: | { type?: "text"; body?: string; _id?: GenericId<"tableName">; _creationTime?: number; } | { type?: "giphy"; _id?: GenericId<"tableName">; _creationTime?: number; }, ]; assert>(); type ReplaceType = Parameters; type ExpectedReplaceType = [ id: GenericId<"tableName">, value: | { type: "text"; body: string; _id?: GenericId<"tableName">; _creationTime?: number; } | { type: "giphy"; _id?: GenericId<"tableName">; _creationTime?: number }, ]; assert>(); }); test("DatabaseWriter has the right types with loose data model", () => { // Use a document with an index signature to simulate `strict: false` type Document = { body: string; _id: GenericId<"tableName">; _creationTime: number; [propertyName: string]: any; }; type DB = GenericDatabaseWriter>; type InsertType = Parameters; type ExpectedInsertType = [ table: "tableName", value: { body: string; [propertyName: string]: any }, ]; assert>(); type PatchType = Parameters; type ExpectedPatchType = [ id: GenericId<"tableName">, value: { body?: string; _id?: GenericId<"tableName">; _creationTime?: number; [propertyName: string]: any; }, ]; assert>(); type ReplaceType = Parameters; type ExpectedReplaceType = [ id: GenericId<"tableName">, value: { body: string; _id?: GenericId<"tableName">; _creationTime?: number; [propertyName: string]: any; }, ]; assert>(); }); test("DatabaseWriter can only access system tables through system", () => { // Even with this system Document is in the data model, it is inaccessible from SystemDB type Document = { body: string; _id: GenericId<"tableName">; _creationTime: number; }; type DB = GenericDatabaseWriter>; type SystemDB = DB["system"]; type QueryType = Parameters; type ExpectedQueryType = [table: SystemTableNames]; // check that we can only pass in SystemTableNames assert>(); }); test("System Tables are readonly", () => { type Document = { body: string; _id: GenericId<"tableName">; _creationTime: number; }; type DB = GenericDatabaseWriter>; type SystemDB = DB["system"]; type PropertyExists = K extends keyof T ? true : false; assert>; assert>; assertFalse>; assertFalse>; assertFalse>; assertFalse>; });