Skip to content
Source
Sign inSign up
Open History to see the last commit

t3-sqlite-state.test.ts

93 lines3.5 KB

1import * as NodeServices from "@effect/platform-node/NodeServices";
2import { assert, it } from "@effect/vitest";
3import * as Effect from "effect/Effect";
4import * as FileSystem from "effect/FileSystem";
5import * as Path from "effect/Path";
6import * as SqlClient from "effect/sql/SqlClient";
7​
8import * as NodeSqliteClient from "@t3tools/shared/nodeSqliteClient";
9import { runSqliteState } from "./t3-sqlite-state.ts";
10import * as HostProcess from "@t3tools/shared/HostProcess";
11import { symlinksSupported } from "@t3tools/shared/testing/symlinks";
12​
13const createFixtureDatabase = Effect.fn("createSqliteStateFixtureDatabase")(function* (
14 baseDir: string,
15) {
16 const fs = yield* FileSystem.FileSystem;
17 const path = yield* Path.Path;
18 const stateDir = path.join(baseDir, "userdata");
19 const databasePath = path.join(stateDir, "statev2.sqlite");
20 yield* fs.makeDirectory(stateDir, { recursive: true });
21 yield* Effect.gen(function* () {
22 const sql = yield* SqlClient.SqlClient;
23 yield* sql`CREATE TABLE fixtures (id INTEGER PRIMARY KEY, label TEXT NOT NULL)`;
24 yield* sql`INSERT INTO fixtures (id, label) VALUES (1, 'existing')`;
25 }).pipe(Effect.provide(NodeSqliteClient.layer({ filename: databasePath })));
26});
27​
28it.layer(NodeServices.layer)("t3-sqlite-state", (it) => {
29 it.effect("enables checkpoint_fullfsync on its direct connection", () =>
30 Effect.gen(function* () {
31 const fs = yield* FileSystem.FileSystem;
32 const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-sqlite-state-fsync-" });
33 yield* createFixtureDatabase(baseDir);
34​
35 const result = yield* runSqliteState({
36 operation: "query",
37 baseDir,
38 sql: "PRAGMA checkpoint_fullfsync",
39 });
40​
41 assert.equal(result.operation, "query");
42 if (result.operation === "query") {
43 assert.deepStrictEqual(result.rows, [{ checkpoint_fullfsync: 1 }]);
44 }
45 }),
46 );
47​
48 it.effect.skipIf(!symlinksSupported)(
49 "backs up isolated state before writes and refuses the shared home",
50 () =>
51 Effect.gen(function* () {
52 const fs = yield* FileSystem.FileSystem;
53 const path = yield* Path.Path;
54 const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-sqlite-state-exec-" });
55 yield* createFixtureDatabase(baseDir);
56​
57 const mutation = yield* runSqliteState({
58 operation: "exec",
59 baseDir,
60 sql: "INSERT INTO fixtures (id, label) VALUES (2, 'seeded')",
61 });
62 assert.equal(mutation.operation, "exec");
63 if (mutation.operation === "exec" && (yield* HostProcess.Platform) !== "win32") {
64 assert.equal((yield* fs.stat(mutation.backup)).mode & 0o777, 0o600);
65 }
66​
67 const error = yield* runSqliteState(
68 {
69 operation: "exec",
70 baseDir,
71 sql: "DELETE FROM fixtures",
72 },
73 { sharedHome: baseDir },
74 ).pipe(Effect.flip);
75 assert.equal(error._tag, "SqliteStateSharedHomeMutationError");
76​
77 const aliasParent = yield* fs.makeTempDirectoryScoped({
78 prefix: "t3-sqlite-state-alias-",
79 });
80 const aliasBaseDir = path.join(aliasParent, "shared-home-alias");
81 yield* fs.symlink(baseDir, aliasBaseDir);
82 const aliasError = yield* runSqliteState(
83 {
84 operation: "exec",
85 baseDir: aliasBaseDir,
86 sql: "DELETE FROM fixtures",
87 },
88 { sharedHome: baseDir },
89 ).pipe(Effect.flip);
90 assert.equal(aliasError._tag, "SqliteStateSharedHomeMutationError");
91 }),
92 );
93});