import { resolve } from "node:path"; import ts from "typescript"; import { expect, it } from "vitest"; it("checks property references and schedule variants in user code", () => { const cases = [ { name: "property", valid: true, expression: "events.notionPageUpdated({ dataSource: tasks.dataSource, properties: [tasks.dataSource.properties.Status] })", }, { name: "content", valid: true, expression: "events.notionPageUpdated({ dataSource: tasks.dataSource, includePageContent: true })", }, { name: "typo", valid: false, expression: "events.notionPageUpdated({ dataSource: tasks.dataSource, properties: [tasks.dataSource.properties.Statuz] })", }, { name: "string", valid: false, expression: 'events.notionPageUpdated({ dataSource: tasks.dataSource, properties: ["Status"] })', }, { name: "other_source", valid: false, expression: "events.notionPageUpdated({ dataSource: tasks.dataSource, properties: [other.dataSource.properties.Name] })", }, { name: "unsupported_property", valid: false, expression: "events.notionPageUpdated({ dataSource: tasks.dataSource, properties: [tasks.dataSource.properties.Files] })", }, { name: "empty", valid: false, expression: "events.notionPageUpdated({ dataSource: tasks.dataSource, properties: [] })", }, { name: "no_watch", valid: false, expression: "events.notionPageUpdated({ dataSource: tasks.dataSource })", }, { name: "weekly", valid: true, expression: 'events.scheduled({ frequency: "week", interval: 1, weekdays: { MO: true }, start: "2026-09-23", timeZone: "UTC" })', }, { name: "no_weekday", valid: false, expression: 'events.scheduled({ frequency: "week", interval: 1, weekdays: {}, start: "2026-09-23", timeZone: "UTC" })', }, ]; const fixtures = new Map( cases.map((testCase) => [ resolve("src", `__events_${testCase.name}.ts`), ` import { database, events } from "./index.js"; const tasks = database("tasks", { name: "Tasks", dataSourceResourceId: "tasks-source", schema: { Name: { type: "title", resourceId: "name" }, Status: { type: "select", resourceId: "status", options: [] }, Files: { type: "file", resourceId: "files" } } }); const other = database("other", { name: "Other", dataSourceResourceId: "other-source", schema: { Name: { type: "title", resourceId: "other-name" } } }); ${testCase.expression}; `, ]), ); const config = ts.readConfigFile(resolve("tsconfig.json"), ts.sys.readFile); const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys, process.cwd()); const host = ts.createCompilerHost(parsed.options); const getSourceFile = host.getSourceFile.bind(host); host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => { const fixture = fixtures.get(fileName); return fixture === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts.createSourceFile(fileName, fixture, languageVersion, true); }; const program = ts.createProgram( [...fixtures.keys()], { ...parsed.options, noEmit: true }, host, ); const diagnostics = ts.getPreEmitDiagnostics(program); expect( diagnostics.filter( (diagnostic) => !diagnostic.file || !fixtures.has(diagnostic.file.fileName), ), ).toEqual([]); for (const testCase of cases) { const errors = diagnostics.filter( (diagnostic) => diagnostic.file?.fileName === resolve("src", `__events_${testCase.name}.ts`), ); expect(errors.length === 0, testCase.name).toBe(testCase.valid); } });