Skip to content

Commit

Permalink
feat(core): update record
Browse files Browse the repository at this point in the history
fix #110 #93
  • Loading branch information
nichenqin committed Jan 4, 2023
1 parent b3c8389 commit 38d0f8c
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ICommandHandler } from '@egodb/domain'
import type { IRecordRepository } from '../../record/repository'
import type { IRecordRepository } from '../../record/record.repository'
import type { ITableRepository } from '../../table.repository'
import type { ICreateTableOutput } from '../create-table'
import type { CreateRecordCommand } from './create-record.comand'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ICommandHandler } from '@egodb/domain'
import type { IRecordRepository } from '../../record/repository'
import type { IRecordRepository } from '../../record/record.repository'
import type { ITableRepository } from '../../table.repository'
import type { UpdateRecordCommand } from './update-record.command'

Expand All @@ -8,7 +8,7 @@ export class UpdateRecordCommandHandler implements ICommandHandler<UpdateRecordC

async execute(command: UpdateRecordCommand): Promise<void> {
const table = (await this.tableRepo.findOneById(command.tableId)).unwrap()
const record = (await this.recordRepo.findOneById(command.id)).unwrap()
const record = (await this.recordRepo.findOneById(command.id, table.schema.toMap())).unwrap()

const spec = record.updateRecord(table.schema, command.value)
await this.recordRepo.updateOneById(command.id, spec)
Expand Down
3 changes: 2 additions & 1 deletion packages/core/record/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export * from './fixtures'
export * from './query-model'
export * from './record'
export * from './record.factory'
export * from './record.repository'
export * from './record.schema'
export * from './record.type'
export * from './repository'
export * from './specifications'
export * from './value-objects'
12 changes: 12 additions & 0 deletions packages/core/record/record.factory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { and } from '@egodb/domain'
import type { Result } from 'oxide.ts'
import type { TableSchemaMap } from '../value-objects'
import { Record } from './record'
import type { IQueryRecordSchema } from './record.type'
import { WithRecordCreatedAt, WithRecordId, WithRecordTableId, WithRecordValues } from './specifications'
import type { RecordCompositeSpecification } from './specifications/interface'

export class RecordFactory {
Expand All @@ -15,4 +18,13 @@ export class RecordFactory {
}
return spec.mutate(Record.create())
}

static fromQuery(r: IQueryRecordSchema, schema: TableSchemaMap): Result<Record, string> {
return this.create(
WithRecordId.fromString(r.id),
WithRecordTableId.fromString(r.tableId).unwrap(),
WithRecordCreatedAt.fromDate(r.createdAt),
WithRecordValues.fromObject(schema, r.values),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Option } from 'oxide.ts'
import type { TableSchemaMap } from '../value-objects'
import type { Record } from './record'
import type { IRecordSpec } from './specifications/interface'

export interface IRecordRepository {
insert(record: Record): Promise<void>
findOneById(id: string): Promise<Option<Record>>
findOneById(id: string, schema: TableSchemaMap): Promise<Option<Record>>

updateOneById(id: string, spec: IRecordSpec): Promise<void>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { CompositeSpecification } from '@egodb/domain'
import type { Result } from 'oxide.ts'
import { Ok } from 'oxide.ts'
import type { ICreateFieldsSchema_internal } from '../../field'
import type { TableSchemaMap } from '../../value-objects'
import type { Record } from '../record'
import type { IQueryRecordValues } from '../record.type'
import { RecordValues } from '../value-objects'
import type { IRecordVisitor } from './interface'

Expand All @@ -15,6 +17,10 @@ export class WithRecordValues extends CompositeSpecification<Record, IRecordVisi
return new this(RecordValues.fromArray(values))
}

static fromObject(schema: TableSchemaMap, values: IQueryRecordValues): WithRecordValues {
return new this(RecordValues.fromObject(schema, values))
}

isSatisfiedBy(t: Record): boolean {
return t.values.equals(this.values)
}
Expand Down
14 changes: 14 additions & 0 deletions packages/core/record/value-objects/record-values.vo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,27 @@ import type { FieldValue, ICreateFieldsSchema_internal, IFieldValue, UnpackedFie
import { DateRangeFieldValue } from '../../field/date-range-field-value'
import type { IDateRangeFieldValue } from '../../field/date-range-field.type'
import { SelectFieldValue } from '../../field/select-field-value'
import type { TableSchemaMap } from '../../value-objects'
import type { IQueryRecordValues } from '../record.type'

export class RecordValues extends ValueObject<Map<string, FieldValue>> {
static fromArray(inputs: ICreateFieldsSchema_internal): RecordValues {
const values = new Map(inputs.map((v) => [v.field.name.value, v.field.createValue(v.value as never)]))
return new RecordValues(values)
}

static fromObject(schema: TableSchemaMap, inputs: IQueryRecordValues): RecordValues {
const values = new Map(
Object.entries(inputs).map(([fieldName, fieldValue]) => [
fieldName,
// TODO: handler missing field
schema.get(fieldName)!.createValue(fieldValue as never),
]),
)

return new RecordValues(values)
}

static empty(): RecordValues {
return new RecordValues(new Map())
}
Expand Down
6 changes: 6 additions & 0 deletions packages/core/value-objects/table-schema.vo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export const createTableSchemaSchema = z

export type ICreateTableSchemaInput = z.infer<typeof createTableSchemaSchema>

export type TableSchemaMap = Map<string, Field>

/**
* Table Schema is a collection of fields
*/
Expand All @@ -36,6 +38,10 @@ export class TableSchema extends ValueObject<Field[]> {
return new TableSchema(fields)
}

public toMap(): TableSchemaMap {
return new Map(this.fields.map((f) => [f.name.value, f]))
}

public get fields(): Field[] {
return this.props
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
import type { IRecordRepository, IRecordSpec, Record } from '@egodb/core'
import type { IRecordRepository, IRecordSpec, Record, TableSchemaMap } from '@egodb/core'
import type { Option } from 'oxide.ts'
import { None, Some } from 'oxide.ts'
import { db } from '../db.js'
import { RecordInMemoryMapper } from './record-in-memory.mapper.js'
import { RecordInMemoryMutationVisitor } from './record-in-memory.mutation-visitor.js'

export class RecordInMemoryRepository implements IRecordRepository {
async findOneById(id: string): Promise<Option<Record>> {
async findOneById(id: string, schema: TableSchemaMap): Promise<Option<Record>> {
const r = db.data?.records.find((t) => t.id === id)
if (!r) return None

const record = RecordInMemoryMapper.toDomain(r).unwrap()
const record = RecordInMemoryMapper.toDomain(r, schema).unwrap()
return Some(record)
}

async findOne(spec: IRecordSpec): Promise<Option<Record>> {
throw new Error('unimplemented')
}

async find(spec: IRecordSpec): Promise<Record[]> {
throw new Error('unimplemented')
}

async insert(record: Record): Promise<void> {
db.data?.records.push(RecordInMemoryMapper.toInMemory(record))
}

async updateOneById(id: string, spec: IRecordSpec): Promise<void> {
throw new Error('Method not implemented.')
const record = db.data?.records.find((r) => r.id === id)
if (!record) return

const visitor = new RecordInMemoryMutationVisitor(record)
spec.accept(visitor)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { Record } from '@egodb/core'
import type { Record, TableSchemaMap } from '@egodb/core'
import { RecordFactory } from '@egodb/core'
import type { Result } from 'oxide.ts'
import type { RecordInMemory } from './record.type'

export class RecordInMemoryMapper {
static toDomain(t: RecordInMemory): Result<Record, Error> {
throw new Error('unimplemented')
static toDomain(t: RecordInMemory, schema: TableSchemaMap): Result<Record, string> {
return RecordFactory.fromQuery(t, schema)
}

static toInMemory(r: Record): RecordInMemory {
Expand Down

0 comments on commit 38d0f8c

Please sign in to comment.