Skip to content

umuplus/dynamorph

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dynamorph

It's a minimalist toolkit for aws dynamodb for AWS SDK v3.

It's not an ORM. The main purpose is to make single table design smooth and easy with validators and converters through built-in types.

Development Status

It's a weekend-only project and still in development.

Supported Types

Dynamorph is going to support various data types for DynamoDB such as simple types like String, Number, Boolean and more complex types like List, Map, NumberSet, StringSet.

It will also support some advanced custom types like Timestamp, SoftDelete and UpdateToken. These custom types also provide functionalities to change the data automatically when certain conditions occurred.

Common Options

These options are available for most of the data types. Some of them are conditionally available and they might end up with errors in parser implementations in the data types.

enum KeyType {
    NUMBER = 'Number',
    STRING = 'String',
}

enum ComplexAttributeType {
    LIST = 'List',
    MAP = 'Map',
    NUMBER_SET = 'NumberSet',
    STRING_SET = 'StringSet',
}

enum CustomAttributeType {
    SOFT_DELETE = 'SoftDelete',
    TIMESTAMP = 'Timestamp',
    UPDATE_TOKEN = 'UpdateToken',
}

type AttributeType = KeyType | ComplexAttributeType | CustomAttributeType | 'Boolean'

interface Attribute {
    type: AttributeType
    fieldName?: string
    partitionKey?: boolean
    sortKey?: boolean
    ignore?: boolean
    required?: boolean
}
Parameter Type Required Description
type AttributeType true The name of the type of the attribute
fieldName string false Field's name to put the value into. If you don't provide, attribute's name will be used
partitionKey boolean false Flag to determine whether the attribute is the partition key or not
sortKey boolean false Flag to determine whether the attribute is the sort key or not
ignore boolean false Set true, if you want to skip the attribute while saving the data to database
required boolean false Flag to determine whether the attribute is required to fill or not

Boolean

This type is for defining attributes to store boolean values.

Options:

type BooleanBaseType = Omit<Attribute, 'type'>

interface BooleanOptions extends BooleanBaseType {
    validate?: (v: boolean | undefined) => string | undefined
    transform?: (v: boolean | undefined) => boolean | undefined
    default?: () => boolean
}
Parameter Type Required Description
validate Function false Custom validator function. You can return custom error string from your validator
transform Function false A custom function to overwrite the value
default Function false A custom function to set the default value

Usages:

const attribute = new BooleanType({
    validate: (v: boolean | undefined) => (!v ? 'value must be true always' : undefined),
    transform: (v: boolean | undefined) => !!v,
    default: () => true
})
attribute.value = true

Number

This type is for defining attributes to store numeric values.

Options:

type NumberBaseType = Omit<Attribute, 'type'>

interface NumberOptions extends NumberBaseType {
    lt?: number
    lte?: number
    gt?: number
    gte?: number
    float?: boolean
    int?: boolean
    validate?: (v: number | undefined) => string | undefined
    transform?: (v: number | undefined) => number | undefined
    default?: () => number
}
Parameter Type Required Description
lt number false Checks the value is less than the provided number
lte number false Checks the value is less than or equal to the provided number
gt number false Checks the value is greater than the provided number
gte number false Checks the value is greater than or equal to the provided number
float boolean false Flag to determine whether the attribute is a floating number or not
int boolean false Flag to determine whether the attribute is an integer or not
validate Function false Custom validator function. You can return custom error string from your validator
transform Function false A custom function to overwrite the value
default Function false A custom function to set the default value

Usages:

const attribute = new NumberType({
    lt: 5,
    lte: 5,
    gt: 15,
    gte: 15,
    float: false,
    int: true,
    validate: (v: number | undefined) => (v % 2 ? 'value must be a even number' : undefined),
    transform: (v: number | undefined) => v * v,
    default: () => Math.random(),
})
attribute.value = 10

String

This type is for defining attributes to store string values.

Options:

enum StringMode {
    EMAIL = 'email',
    ULID = 'ulid',
    URL = 'url',
}

type StringBaseType = Omit<Attribute, 'type'>

interface StringOptions extends StringBaseType {
    min?: number
    max?: number
    length?: number
    regex?: RegExp
    validate?: (v: string | undefined) => string | undefined
    transform?: (v: string | undefined) => string | undefined
    default?: () => string
    mode?: StringMode
    format?: string
}
Parameter Type Required Description
min number false Checks length of the value is not less than the provided number
max number false Checks length of the value is not greater than the provided number
length number false Checks length of the value is equal to the provided number
regex RegExp false Checks the value is matches with the provided regular expression
validate Function false Custom validator function. You can return custom error string from your validator
transform Function false A custom function to overwrite the value
default Function false A custom function to set the default value
mode StringMode false Checks the value matches with the pre-defined mode
format string false Determines the format of the value

Usages:

const attribute = new StringType({
    min: 5,
    max: 5,
    length: 5,
    regex: /TEST/gi,
    validate: (v: string | undefined) => (v.includes('forbidden') ? 'value cannot contain the word "forbidden"' : undefined),
    transform: (v: string | undefined) => v.toUpperCase(),
    default: () => '?'
})
attribute.value = 'test'

const attribute2 = new StringType({
    min: 10,
    max: 10,
    length: 10,
    mode: StringMode.EMAIL,
    format: '{username}@{domain}',
})
attribute2.value = { username: 'info', domain: 'example.com' }

List

This type is for defining attributes to store list values.

Options:

type ListBaseType = Omit<Attribute, 'type'>

export interface ListOptions extends ListBaseType {
    min?: number
    max?: number
    size?: number
    validate?: (v: any[] | undefined) => string | undefined
    transform?: (v: any[] | undefined) => any[] | undefined
    default?: () => any[]
}
Parameter Type Required Description
min number false Checks length of the value is not less than the provided number
max number false Checks length of the value is not greater than the provided number
size number false Checks length of the value is equal to the provided number
validate Function false Custom validator function. You can return custom error string from your validator
transform Function false A custom function to overwrite the value
default Function false A custom function to set the default value

Usages:

const attribute = new ListType({
    min: 1,
    max: 5,
    size: 3,
    validate: (v: any[] | undefined) => (v.length % 2 ? 'number of items in the value must be even' : undefined),
    transform: (v: any[] | undefined) => v.map(k => k?.toUpperCase() || k),
    default: () => [],
})
attribute.value = ['a', 'b', 'c']

Map

This type is for defining attributes to store map (object) values.

Options:

type MapBaseType = Omit<Attribute, 'type'>

export interface MapOptions extends MapBaseType {
    validate?: (v: Record<string, any> | undefined) => string | undefined
    transform?: (v: Record<string, any> | undefined) => Record<string, any> | undefined
    default?: () => Record<string, any>
}
Parameter Type Required Description
validate Function false Custom validator function. You can return custom error string from your validator
transform Function false A custom function to overwrite the value
default Function false A custom function to set the default value

Usages:

const attribute = new MapType({
    validate: (v: Record<string, any> | undefined) => (!v.type ? 'type must exist' : undefined),
    transform: (v: Record<string, any> | undefined) => {
        Object.keys(v).map(k => v[k].toUpperCase())
        return v
    }),
    default: () => {},
})
attribute.value = { type: 'x', a: 'a', b: 'b' }

NumberSet

This type is for defining attributes to store a set of numbers.

Options:

type NumberSetBaseType = Omit<Attribute, 'type'>

export interface NumberSetOptions extends NumberSetBaseType {
    min?: number
    max?: number
    size?: number
    validate?: (v: Set<number> | undefined) => string | undefined
    transform?: (v: Set<number> | undefined) => Set<number> | undefined
    default?: () => Set<number>
}
Parameter Type Required Description
min number false Checks length of the value is not less than the provided number
max number false Checks length of the value is not greater than the provided number
size number false Checks length of the value is equal to the provided number
validate Function false Custom validator function. You can return custom error string from your validator
transform Function false A custom function to overwrite the value
default Function false A custom function to set the default value

Usages:

const attribute = new NumberSetType({
    min: 1,
    max: 5,
    size: 3,
    validate: (v: Set<number> | undefined) => (v.size % 2 ? 'number of items in the value must be even' : undefined),
    transform: (v: Set<number> | undefined) => new Set(Array.from(v).map(k => k * 2)),
    default: () => new Set<number>(),
})
attribute.value = new Set([1, 2])
attribute.plain() // [2, 4]

StringSet

This type is for defining attributes to store a set of strings.

Options:

type StringSetBaseType = Omit<Attribute, 'type'>

export interface StringSetOptions extends StringSetBaseType {
    min?: number
    max?: number
    size?: number
    validate?: (v: Set<string> | undefined) => string | undefined
    transform?: (v: Set<string> | undefined) => Set<string> | undefined
    default?: () => Set<string>
}
Parameter Type Required Description
min number false Checks length of the value is not less than the provided number
max number false Checks length of the value is not greater than the provided number
size number false Checks length of the value is equal to the provided number
validate Function false Custom validator function. You can return custom error string from your validator
transform Function false A custom function to overwrite the value
default Function false A custom function to set the default value

Usages:

const attribute = new StringSetType({
    min: 1,
    max: 5,
    size: 3,
    validate: (v: Set<string> | undefined) => (v.size % 2 ? 'number of items in the value must be even' : undefined),
    transform: (v: Set<string> | undefined) => new Set(Array.from(v).map(k => k.toUpperCase())),
    default: () => new Set<string>(),
})
attribute.value = new Set(['a', 'b'])
attribute.plain() // ['A', 'B']

Soft Delete

This type is for marking attributes as deleted. It supports only common options except partitionKey, sortKey or ignore. It's default value is false and you can assign only a boolean value.

Options:

type SoftDeleteBaseType = Omit<Attribute, 'type'>

interface SoftDeleteOptions extends SoftDeleteBaseType {}

Usages:

const attribute = new SoftDelete({})
attribute.value = true

Update Token

This type is for making atomic changes possible. It doesn't support options like partitionKey, sortKey or ignore.

Options:

type UpdateTokenBaseType = Omit<Attribute, 'type'>

export interface UpdateTokenOptions extends UpdateTokenBaseType {
    length?: number
}
Parameter Type Required Description
length number false Defines length of update token and the default is 4

Usages:

const attribute = new UpdateTokenType({ length: 6 })
attribute.reset()

Timestamp

This type is for managing timestamps on create, update or delete. It doesn't support options like partitionKey, sortKey or ignore.

Options:

export enum TimestampMode {
    ISO_STRING = 'iso',
    MILLISECONDS = 'ms',
    SECONDS = 's',
}

export enum TimestampOn {
    CREATE = 'c',
    DELETE = 'd',
    UPDATE = 'u',
}

type TimestampBaseType = Omit<Attribute, 'type'>

export interface TimestampOptions extends TimestampBaseType {
    on: TimestampOn
    mode: TimestampMode
}
Parameter Type Required Description
on TimestampOn true Defines when to change the value
mode TimestampMode true Defines type of the timestamp

Usages:

const attribute = new TimestampType({ on: TimestampOn.CREATE, mode: TimestampMode.ISO_STRING })
attribute.stamp()

About

a minimalist toolkit for aws dynamodb for AWS SDK v3.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published