import { it, describe, expect } from 'vitest';
const itEffect = (name: string, fn: () => Effect.Effect) =>
it(name, () => Effect.runPromise(fn()));
import { Effect, Schema } from 'effect';
import { EntityESchema } from '../index.js';
import { ESchemaError } from '../index.js';
describe('ESchema', () => {
describe('Decoding', () => {
describe('Decode', () => {
itEffect('decodes v1 data without migration', () =>
Effect.gen(function* () {
const schema = EntityESchema.make('Test', 'id', {
name: Schema.String,
count: Schema.Number,
}).build();
const decoded = yield* schema.decode({
_v: 'v1',
id: 't1',
name: 'foo',
count: 10,
});
expect(decoded).toEqual({ id: 't1', name: 'foo', count: 10 });
}),
);
itEffect('decodes and migrates v1 to v2', () =>
Effect.gen(function* () {
const schema = EntityESchema.make('Test', 'id', {
a: Schema.Number,
})
.evolve('v2', { b: Schema.String }, (v) => ({ ...v, b: 'added' }))
.build();
const decoded = yield* schema.decode({ _v: 'v1', id: 't1', a: 42 });
expect(decoded).toEqual({ id: 't1', a: 42, b: 'added' });
}),
);
itEffect('decodes latest version without running migrations', () =>
Effect.gen(function* () {
const schema = EntityESchema.make('Test', 'id', {
a: Schema.String,
})
.evolve('v2', { b: Schema.String }, (v) => ({
...v,
b: 'should not appear',
}))
.build();
const decoded = yield* schema.decode({
_v: 'v2',
id: 't1',
a: 'hello',
b: 'world',
});
expect(decoded).toEqual({ id: 't1', a: 'hello', b: 'world' });
}),
);
itEffect('fails with ESchemaError on unknown version', () =>
Effect.gen(function* () {
const schema = EntityESchema.make('Test', 'id', {
a: Schema.String,
}).build();
const error = yield* Effect.flip(
schema.decode({ _v: 'v99', id: 't1', a: 'hello' }),
);
expect(error).toBeInstanceOf(ESchemaError);
expect(error.message).toBe('Unknown schema version: v99');
}),
);
itEffect('treats missing _v as the earliest version (v1)', () =>
Effect.gen(function* () {
const schema = EntityESchema.make('Test', 'id', {
a: Schema.String,
}).build();
const decoded = yield* schema.decode({ id: 't1', a: 'hello' });
expect(decoded).toEqual({ id: 't1', a: 'hello' });
}),
);
});
});
});