2.1.0 • Published 2 years ago

ts-entity-framework v2.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

ts-entity-framework

build MIT License

A package for creating data formats, relations, and postgresql data stores with strict Typescript type enforcement.

What and Why?

There has always been an inconvenient separation between Typescript types and the Javascript code that operates on them. Without repetition, coupling, constants, and/or otherwise cumbersome workarounds, one cannot easily attach metadata to type properties or iterate over them and perform particular operations on them.

Non-native solutions to this often use a type-to-Javascript approach to expose types to Javascript code, which typically involves either custom Typescript transformers or a new language with its own compiler down to Typescript.

ts-entity-framework takes a Javascript-to-type approach, allowing one to define Data Format Declarations in Javascript, with a one-liner ability to turn them into useful entity types. This approach requires only native JS and TS functionality.

Usage

Define Data Format Declarations:

import { createDataFormatDeclaration } from 'ts-entity-framework/dist/dataFormat'
import { DataType, NumberDataSubType, StringDataSubType } from 'ts-entity-framework/dist/dataFormat/types'

export const USER_DFD = createDataFormatDeclaration({
  name: 'user',
  fields: [
    { name: 'id', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.SERIAL },
    { name: 'name', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 50 },
  ],
} as const)

export const USER_GROUP_DFD = createDataFormatDeclaration({
  name: 'userGroup',
  fields: [
    { name: 'id', dataType: DataType.NUMBER, dataSubType: NumberDataSubType.SERIAL },
    { name: 'name', dataType: DataType.STRING, dataSubType: StringDataSubType.VARYING_LENGTH, maxLength: 50 },
  ],
} as const)

Create entity types from Data Format Declarations:

import { ToRecord, CreateRecordOptions } from 'ts-entity-framework/dist/dataFormat/types'

export type UserRecord = ToRecord<typeof USER_DFD>
// { id: number, name: string }

export type CreateUserRecordOptions = CreateRecordOptions<typeof USER_DFD>
// { name: string }

export type UserGroupRecord = ToRecord<typeof USER_GROUP_DFD>
// { id: number, name: string }

Load Data Format Declarations and Relations to create Entities:

import { createEntities } from 'ts-entity-framework'
import { RelationType } from 'ts-entity-framework/dist/relations/types'

const ENTITIES = createEntities()
  .loadDataFormats([
    USER_DFD,
    USER_GROUP_DFD
  ] as const)
  .loadRelations(dfs => [
    // Create many-to-many relation between user and userGroup entities, linked on id fields.
    {
      type: RelationType.MANY_TO_MANY,
      fieldRef1: dfs.user.fieldRefs.id,
      fieldRef2: dfs.userGroup.fieldRefs.id
    },
  ] as const)

Create and provision PostgreSQL entity stores:

import { DbService } from 'ts-entity-framework/dist/dataFormat/types'
// Define PostgreSql DB service, with query, queryGetFirstRow, and queryGetRows functions.
const dbService: DbService = { ... }
// Create and provision DB stores for entities
const stores = ENTITIES.sqldb.createAndProvisionStores(dbService, ['user', 'userGroup'])
// Create join table (a.k.a "junction table") for many-to-many relations, i.e. user_to_user_group
await ENTITIES.sqldb.createJoinTables(dbService)

Use types and stores throughout your application, all fully type-enforced:

// Perform CRUD operations on entities
const createUserOptions: CreateUserRecordOptions = { name: 'newUser' }
// Get entity record
const user: UserRecord = await stores.user.add(createUserOptions)
// Get related entity records
const userGroups = await stores.userGroups.getUserGroupsOfUser(user.id)
// Get entity record with all related entity records
const userWithUserGroups = await stores.user.getByIdWithAllRelations(user.id)
// Get entity record with some related entity records
const userWithUserGroups = await stores.userGroups.getByIdWithRelations(user.id, ['userGroups'])
// Use data format sql information to create custom type-enforced SQL statements
const userSqlInfo = ENTITIES.dataFormats.user.sql
const customUserSql = `select ${userSqlInfo.columnNames.name} from ${userSqlInfo.tableName}`
// select name from "user"

Examples

Examples can be found within ./src/examples, showing more complete and realistic usages of ts-entity-framework.

Article API

This is a simple single-endpoint api that has two entities - "User" and "UserArticle", with a single relation linking them.

Run npm run start-article-api to build and start the server (don't forget to run npm i first if you have not already). Once running, try sending a HTTP GET request to http://localhost:3000/userProfile/1 to see ts-entity-framework.

Development

ts-entity-framework is currently in an early state of development, primarily being used as a provider of PostgreSQL stores for data formats with simple data types (i.e. string, number, date, jsonb). More PostgreSQL data types or transformations to other SQL databases altogether could be added later as per need or request.

2.1.0

2 years ago

2.0.4

2 years ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago