Merge commit '36c66dd290d3ce6eb1ccd310d0c658d4a32bb8eb' as 'repos/effect'
This commit is contained in:
227
repos/effect/packages/sql/mysql2/test/Model.test.ts
Normal file
227
repos/effect/packages/sql/mysql2/test/Model.test.ts
Normal file
@@ -0,0 +1,227 @@
|
||||
import { assert, describe, it } from "@effect/vitest"
|
||||
import { Cause, Effect, Schema } from "effect"
|
||||
import { Model } from "effect/unstable/schema"
|
||||
import { SqlClient, SqlModel, SqlResolver } from "effect/unstable/sql"
|
||||
import { MysqlContainer } from "./utils.ts"
|
||||
|
||||
class User extends Model.Class<User>("User")({
|
||||
id: Schema.Int.pipe(
|
||||
Model.FieldExcept(["insert"])
|
||||
),
|
||||
name: Schema.String,
|
||||
age: Schema.Int
|
||||
}) {}
|
||||
|
||||
class SoftDeleteUser extends Model.Class<SoftDeleteUser>("SoftDeleteUser")({
|
||||
id: Schema.Int.pipe(
|
||||
Model.FieldExcept(["insert"])
|
||||
),
|
||||
name: Schema.String,
|
||||
deletedAt: Schema.NullOr(Schema.String).pipe(
|
||||
Model.FieldOnly(["select", "update"])
|
||||
)
|
||||
}) {}
|
||||
|
||||
describe("SqlModel", () => {
|
||||
it.effect("insert returns result", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeRepository(User, {
|
||||
tableName: "users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "UserRepository"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), age INT)`
|
||||
|
||||
const result = yield* repo.insert(User.insert.make({ name: "Alice", age: 30 }))
|
||||
assert.deepStrictEqual(result, new User({ id: 1, name: "Alice", age: 30 }))
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClient),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.effect("insert returns result with transforms", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeRepository(User, {
|
||||
tableName: "users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "UserRepository"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), age INT)`
|
||||
|
||||
const result = yield* repo.insert(User.insert.make({ name: "Alice", age: 30 }))
|
||||
assert.deepStrictEqual(result, new User({ id: 1, name: "Alice", age: 30 }))
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClientWithTransforms),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.effect("insertVoid", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeRepository(User, {
|
||||
tableName: "users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "UserRepository"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), age INT)`
|
||||
|
||||
const result = yield* repo.insertVoid(User.insert.make({ name: "Alice", age: 30 }))
|
||||
assert.strictEqual(result, void 0)
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClient),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.live("insert data loader returns result", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeResolvers(User, {
|
||||
tableName: "users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "UserRepository"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), age INT)`
|
||||
|
||||
const [alice, john] = yield* Effect.all([
|
||||
SqlResolver.request(User.insert.make({ name: "Alice", age: 30 }), repo.insert),
|
||||
SqlResolver.request(User.insert.make({ name: "John", age: 30 }), repo.insert)
|
||||
], { concurrency: "unbounded" })
|
||||
assert.deepStrictEqual(alice.name, "Alice")
|
||||
assert.deepStrictEqual(john.name, "John")
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClient),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.live("findById data loader", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeResolvers(User, {
|
||||
tableName: "users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "UserRepository"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), age INT)`
|
||||
const alice = yield* SqlResolver.request(User.insert.make({ name: "Alice", age: 30 }), repo.insert)
|
||||
const john = yield* SqlResolver.request(User.insert.make({ name: "John", age: 30 }), repo.insert)
|
||||
|
||||
const [alice2, john2] = yield* Effect.all([
|
||||
SqlResolver.request(alice.id, repo.findById),
|
||||
SqlResolver.request(john.id, repo.findById)
|
||||
], { concurrency: "unbounded" })
|
||||
|
||||
assert.deepStrictEqual(alice2.name, "Alice")
|
||||
assert.deepStrictEqual(john2.name, "John")
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClient),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.effect("findById ignores soft deleted rows", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeRepository(SoftDeleteUser, {
|
||||
tableName: "soft_delete_users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "SoftDeleteUserRepository",
|
||||
softDeleteColumn: "deletedAt"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE soft_delete_users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), deletedAt VARCHAR(255) NULL)`
|
||||
|
||||
const alice = yield* repo.insert(SoftDeleteUser.insert.make({ name: "Alice" }))
|
||||
const bob = yield* repo.insert(SoftDeleteUser.insert.make({ name: "Bob" }))
|
||||
yield* sql`UPDATE soft_delete_users SET deletedAt = CURRENT_TIMESTAMP WHERE id = ${bob.id}`
|
||||
|
||||
const aliceResult = yield* repo.findById(alice.id)
|
||||
assert.deepStrictEqual(aliceResult, new SoftDeleteUser({ id: alice.id, name: "Alice", deletedAt: null }))
|
||||
|
||||
const error = yield* Effect.flip(repo.findById(bob.id))
|
||||
assert.isTrue(Cause.isNoSuchElementError(error))
|
||||
|
||||
yield* repo.delete(alice.id)
|
||||
const rows = yield* sql<
|
||||
{ deletedAt: string | null }
|
||||
>`SELECT deletedAt FROM soft_delete_users WHERE id = ${alice.id}`
|
||||
assert.strictEqual(rows.length, 1)
|
||||
assert.isNotNull(rows[0]!.deletedAt)
|
||||
|
||||
const deletedError = yield* Effect.flip(repo.findById(alice.id))
|
||||
assert.isTrue(Cause.isNoSuchElementError(deletedError))
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClient),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.live("findById data loader ignores soft deleted rows", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeResolvers(SoftDeleteUser, {
|
||||
tableName: "soft_delete_user_resolvers",
|
||||
idColumn: "id",
|
||||
spanPrefix: "SoftDeleteUserRepository",
|
||||
softDeleteColumn: "deletedAt"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE soft_delete_user_resolvers (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), deletedAt VARCHAR(255) NULL)`
|
||||
|
||||
const alice = yield* SqlResolver.request(SoftDeleteUser.insert.make({ name: "Alice" }), repo.insert)
|
||||
const bob = yield* SqlResolver.request(SoftDeleteUser.insert.make({ name: "Bob" }), repo.insert)
|
||||
yield* sql`UPDATE soft_delete_user_resolvers SET deletedAt = CURRENT_TIMESTAMP WHERE id = ${bob.id}`
|
||||
|
||||
const aliceResult = yield* SqlResolver.request(alice.id, repo.findById)
|
||||
assert.deepStrictEqual(aliceResult, new SoftDeleteUser({ id: alice.id, name: "Alice", deletedAt: null }))
|
||||
|
||||
const error = yield* Effect.flip(SqlResolver.request(bob.id, repo.findById))
|
||||
assert.isTrue(Cause.isNoSuchElementError(error))
|
||||
|
||||
yield* SqlResolver.request(alice.id, repo.delete)
|
||||
const rows = yield* sql<
|
||||
{ deletedAt: string | null }
|
||||
>`SELECT deletedAt FROM soft_delete_user_resolvers WHERE id = ${alice.id}`
|
||||
assert.strictEqual(rows.length, 1)
|
||||
assert.isNotNull(rows[0]!.deletedAt)
|
||||
|
||||
const deletedError = yield* Effect.flip(SqlResolver.request(alice.id, repo.findById))
|
||||
assert.isTrue(Cause.isNoSuchElementError(deletedError))
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClient),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.effect("update returns result", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeRepository(User, {
|
||||
tableName: "users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "UserRepository"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), age INT)`
|
||||
|
||||
let result = yield* repo.insert(User.insert.make({ name: "Alice", age: 30 }))
|
||||
result = yield* repo.update(User.update.make({ ...result, name: "Bob" }))
|
||||
assert.deepStrictEqual(result, new User({ id: 1, name: "Bob", age: 30 }))
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClient),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
|
||||
it.effect("update returns result with transforms", () =>
|
||||
Effect.gen(function*() {
|
||||
const repo = yield* SqlModel.makeRepository(User, {
|
||||
tableName: "users",
|
||||
idColumn: "id",
|
||||
spanPrefix: "UserRepository"
|
||||
})
|
||||
const sql = yield* SqlClient.SqlClient
|
||||
yield* sql`CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), age INT)`
|
||||
|
||||
let result = yield* repo.insert(User.insert.make({ name: "Alice", age: 30 }))
|
||||
result = yield* repo.update(User.update.make({ ...result, name: "Bob" }))
|
||||
assert.deepStrictEqual(result, new User({ id: 1, name: "Bob", age: 30 }))
|
||||
}).pipe(
|
||||
Effect.provide(MysqlContainer.layerClientWithTransforms),
|
||||
Effect.catchTag("ContainerError", () => Effect.void)
|
||||
), { timeout: 60_000 })
|
||||
})
|
||||
Reference in New Issue
Block a user