import { PartitionAndSortKey, PartitionKeyAndSortKeyPrefix } from "./keys" import { Table } from "./Table" import { TaggedModel } from "./types" export class Model { constructor( private table: Table, private partitionKeyPrefix: string, private partitionKeyFields: U[], private sortKeyPrefix: string, private sortKeyFields: V[], readonly modelTag: string ) {} key(params: { [X in U]: string } & { [Y in V]: string }): PartitionAndSortKey { const { partitionKeyPrefix, sortKeyPrefix, partitionKeyFields, sortKeyFields } = this const pkComponents = partitionKeyFields.map((_) => params[_]) const skComponents = sortKeyFields.map((_) => params[_]) return new PartitionAndSortKey( this.table.partitionKeyName, this.buildKey(partitionKeyPrefix, ...pkComponents), this.table.sortKeyName, this.buildKey(sortKeyPrefix, ...skComponents), this.modelTag ) } partitionKey(params: { [X in U]: string }): PartitionKeyAndSortKeyPrefix { const { partitionKeyPrefix, partitionKeyFields } = this const pkComponents = partitionKeyFields.map((_) => params[_]) return new PartitionKeyAndSortKeyPrefix( this.table.partitionKeyName, this.buildKey(partitionKeyPrefix, ...pkComponents), this.table.sortKeyName, this.sortKeyPrefix, this.modelTag ) } create(fields: Omit) { const { partitionKeyPrefix, sortKeyPrefix, partitionKeyFields, sortKeyFields, modelTag } = this const fieldsWithTag = { ...fields, model: modelTag } as T const pkComponents = partitionKeyFields.map((_) => fieldsWithTag[_]) const skComponents = sortKeyFields.map((_) => fieldsWithTag[_]) const pk = this.buildKey(partitionKeyPrefix, ...pkComponents) const sk = this.buildKey(sortKeyPrefix, ...skComponents) return { ...fieldsWithTag, [this.table.partitionKeyName]: pk, [this.table.sortKeyName]: sk } } private buildKey(...components: string[]): string { return components.join(this.table.delimiter) } } export class PartitionKeyBuilder { constructor(private table: Table, private modelTag: string) {} partitionKey(prefix: string, ...partitionKeyFields: U[]): SortKeyBuilder { return new SortKeyBuilder(this.table, prefix, partitionKeyFields, this.modelTag) } } export class SortKeyBuilder { constructor( private table: Table, private partitionKeyPrefix: string, private partitionKeyFields: U[], private modelTag: string ) {} sortKey(prefix: string, ...sortKeyFields: V[]): Model { return new Model(this.table, this.partitionKeyPrefix, this.partitionKeyFields, prefix, sortKeyFields, this.modelTag) } }