Skip to content

Instantly share code, notes, and snippets.

@smhmayboudi
Last active July 13, 2024 15:59
Show Gist options
  • Save smhmayboudi/6f76dcf36f0218dbd6565c71206a3d76 to your computer and use it in GitHub Desktop.
Save smhmayboudi/6f76dcf36f0218dbd6565c71206a3d76 to your computer and use it in GitHub Desktop.
import {Schema, Serializable} from '@effect/schema';
import {Brand, Console, Effect, HashMap, pipe, Ref} from 'effect';
export type Int = number & Brand.Brand<'Int'>;
export const Int = Brand.refined<Int>(
n => Number.isInteger(n),
n => Brand.error(`expected ${n} to be an integer.`)
);
export type Positive = number & Brand.Brand<'Positive'>;
export const Positive = Brand.refined<Positive>(
n => n >= 0,
n => Brand.error(`expected ${n} to be positive.`)
);
export const TodoId = Brand.all(Int, Positive);
export type TodoId = Brand.Brand.FromConstructor<typeof TodoId>;
export class TodoModelDAO extends Schema.Class<TodoModelDAO>('TodoModelDAO')({
id: pipe(Schema.Number, Schema.fromBrand(TodoId)),
title: Schema.String,
completed: Schema.Boolean,
}) {}
export class TodoModelBO extends Schema.Class<TodoModelBO>('TodoModelBO')({
id: pipe(Schema.Number, Schema.fromBrand(TodoId)),
title: Schema.String,
completed: Schema.Boolean,
}) {
static FromEncoded = Schema.transform(TodoModelDAO, TodoModelBO, {
decode: (
fromA: Schema.Schema.Encoded<typeof TodoModelDAO>
): Schema.Schema.Encoded<typeof TodoModelBO> => {
console.log('>TodoModelBO.FromEncoded.decode');
return {
id: fromA.id,
title: fromA.title,
completed: fromA.completed,
};
},
encode: (
toI: Schema.Schema.Encoded<typeof TodoModelBO>
): Schema.Schema.Type<typeof TodoModelDAO> => {
console.log('>TodoModelBO.FromEncoded.encode');
return {
id: TodoId(toI.id),
title: toI.title,
completed: toI.completed,
};
},
});
// get [Serializable.symbol]() {
// return TodoModelBO.FromEncoded;
// }
}
export class TodoModelDTO extends Schema.Class<TodoModelDTO>('TodoModelDTO')({
id: Schema.Number,
title: Schema.String,
completed: Schema.Number,
}) {
static FromEncoded = Schema.transform(TodoModelBO, TodoModelDTO, {
decode: (
fromA: Schema.Schema.Encoded<typeof TodoModelBO>
): Schema.Schema.Encoded<typeof TodoModelDTO> => {
console.log('>TodoModelDTO.FromEncoded.decode');
return {
id: fromA.id,
title: fromA.title,
completed: fromA.completed ? 1 : 0,
};
},
encode: (
toI: Schema.Schema.Encoded<typeof TodoModelDTO>
): Schema.Schema.Type<typeof TodoModelBO> => {
console.log('>TodoModelDTO.FromEncoded.encode');
return {
id: TodoId(toI.id),
title: toI.title,
completed: toI.completed === 1,
};
},
});
get [Serializable.symbol]() {
return TodoModelDTO.FromEncoded;
}
}
const dao = TodoModelDAO.make({
id: TodoId(1),
title: 'HI, WHY!?',
completed: true,
});
console.log('DAO >>>', dao);
const bo = Schema.decodeUnknownOption(TodoModelBO.FromEncoded, {
errors: 'all',
propertyOrder: 'original',
onExcessProperty: 'error',
exact: false,
})(dao);
console.log('BO >>>', bo);
const app = Effect.gen(function* () {
const nextIdRef = yield* Ref.make(TodoId(1));
const todosRef = yield* Ref.make(HashMap.empty<TodoId, TodoModelDAO>());
const createTodo = pipe(
Ref.getAndUpdate(nextIdRef, n => TodoId(n + 1)),
Effect.flatMap(id =>
Ref.modify(todosRef, map => {
const newTodo = new TodoModelDAO({
id: TodoId(1),
title: 'HI, WHY!?',
completed: true,
});
const updated = HashMap.set(map, newTodo.id, newTodo);
return [newTodo.id, updated];
})
)
);
createTodo.pipe(Effect.runSync);
const apple = pipe(
// Effect.succeed(
// TodoModelDAO.make({
// id: TodoId(1),
// title: 'HI, WHY!?',
// completed: true,
// })
// ),
Ref.get(todosRef),
Effect.map(HashMap.get(TodoId(1))),
Effect.tap(o => Console.log('>>>1', o)),
Effect.map(
Schema.decodeUnknownOption(TodoModelBO.FromEncoded, {
errors: 'all',
propertyOrder: 'original',
onExcessProperty: 'error',
exact: false,
})
),
Effect.tap(o => Console.log('>>>2', o))
);
apple.pipe(Effect.runSync);
});
pipe(app, Effect.runFork);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment