Skip to content

Commit

Permalink
feature compelete & cleanup (#1)
Browse files Browse the repository at this point in the history
* feature compelete & cleanup

* fix

* fix
  • Loading branch information
rohit-kadhe authored Mar 21, 2024
1 parent fe39b2d commit eaccab5
Show file tree
Hide file tree
Showing 18 changed files with 111 additions and 46 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/prerequisites.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ on:
pull_request:
types: [synchronize, opened, edited, ready_for_review, reopened, unlocked]
branches: [main, development]
push:
branches: [main, development]

permissions:
checks: write
contents: write
pull-requests: write

jobs:
test:
Run-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down
8 changes: 5 additions & 3 deletions core/clickhouse_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ interface IClickhouseSchema {
GetCreateTableQueryAsList: () => string[]
}

export type ChSchemaDefinition = Record<string, SchemaValue>

/* This class is used to represent a clickhouse table schema */
export class ClickhouseSchema<ChSchema> implements IClickhouseSchema {
readonly schema: ChSchema
export class ClickhouseSchema<SchemaDefinition extends ChSchemaDefinition> implements IClickhouseSchema {
readonly schema: SchemaDefinition
private readonly options: ChSchemaOptions

constructor (schema: ChSchema, options: ChSchemaOptions) {
constructor (schema: SchemaDefinition, options: ChSchemaOptions) {
this.schema = schema
this.options = options
}
Expand Down
29 changes: 5 additions & 24 deletions core/infer_schema_type.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
import { type ClickhouseSchema } from '@clickhouse-schema-core/clickhouse_schema'
import { type ChDataType, type MapChSchemaTypes } from '@clickhouse-schema-data-types/index'
import { type ChArray } from '@clickhouse-schema-data-types/ch_array'
import { type ChJSON } from '@clickhouse-schema-data-types/ch_json'
import { type ExtractInnerType, type ExtractOuterType } from '@clickhouse-schema-utils/type_inference'
import { type ChEnum } from '@clickhouse-schema-data-types/ch_enum'
import { type ClickhouseSchema, type ChSchemaDefinition } from '@clickhouse-schema-core/clickhouse_schema'
import { type ChDataType } from '@clickhouse-schema-data-types/index'
import { type InferArray, type InferEnum, type InferJSON, type InferNullable, type InferTypeFromMap } from '@clickhouse-schema-utils/util'

/** InferSchemaClickhouseSchemaType is a type that takes a ClickhouseSchema and returns the typescript that it represents */
export type InferClickhouseSchemaType<T extends ClickhouseSchema<any>> = { [K in keyof T['schema']]: InferType<T['schema'][K]['type']> }

/** InferTypeFromMap is a type that takes a string and returns the typescript that it represents */
type InferTypeFromMap<T extends string> = ExtractInnerType<T> extends keyof MapChSchemaTypes
? MapChSchemaTypes[ExtractInnerType<T>]
: ExtractOuterType<T> extends keyof MapChSchemaTypes ?
MapChSchemaTypes[ExtractOuterType<T>]
: unknown
export type InferClickhouseSchemaType<T extends ClickhouseSchema<ChSchemaDefinition>> = { [K in keyof T['schema']]: InferType<T['schema'][K]['type']> }

/** InferType is a type that takes a ChDataType and returns the typescript that it represents */
type InferType<T extends ChDataType> =
T extends ChArray<infer ArrayType>
? Array<InferType<ArrayType>>
: T extends ChEnum<infer EnumType>
? keyof EnumType
: T extends ChJSON<infer Schema>
? { [K in keyof T['dataType']]: InferType<Schema[K]['type']> }
: T extends ChDataType
? InferTypeFromMap<T['typeStr']>
: unknown
type InferType<T extends ChDataType> = T['dataTypeMarker'] extends 'Array' ? InferArray<T> : T['dataTypeMarker'] extends 'Enum' ? InferEnum<T> : T['dataTypeMarker'] extends 'JSON' ? InferJSON<T> : T['dataTypeMarker'] extends 'Nullable' ? InferNullable<T> : InferTypeFromMap<T['typeStr']>
11 changes: 6 additions & 5 deletions data_types/ch_array.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChArray<T extends ChDataType | ChArray<ChDataType>> implements ChDataType {
readonly dataType: T
readonly innerType: T
readonly typeStr: string
readonly dataTypeMarker = 'Array' as const

constructor (t: T) {
if (t instanceof ChArray) {
this.dataType = new ChArray(t.dataType) as T
this.innerType = new ChArray(t.innerType) as T
} else {
this.dataType = t
this.innerType = t
}
this.typeStr = this.toString()
}

toString (): string {
if (this.dataType instanceof ChArray) return `Array(${this.dataType.toString()})`
return `Array(${this.dataType})`
if (this.innerType instanceof ChArray) return `Array(${this.innerType.toString()})`
return `Array(${this.innerType})`
}
}
1 change: 1 addition & 0 deletions data_types/ch_boolean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChBoolean implements ChDataType {
readonly typeStr: 'Boolean' = 'Boolean' as const
readonly dataTypeMarker = 'Boolean' as const

toString (): string {
return this.typeStr
Expand Down
7 changes: 7 additions & 0 deletions data_types/ch_date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChDate implements ChDataType {
readonly typeStr: 'Date' = 'Date' as const
readonly dataTypeMarker = 'Date' as const

toString (): string {
return this.typeStr
}
}

export class ChDate32 implements ChDataType {
readonly typeStr: 'Date32' = 'Date32' as const
readonly dataTypeMarker = 'Date32' as const

toString (): string {
return this.typeStr
Expand All @@ -17,6 +20,8 @@ export class ChDate32 implements ChDataType {

export class ChDateTime<T extends string> implements ChDataType {
readonly typeStr: `DateTime(${T})`
readonly dataTypeMarker = 'DateTime' as const

constructor (readonly timezone: T) {
this.typeStr = `DateTime(${timezone})`
}
Expand All @@ -28,6 +33,8 @@ export class ChDateTime<T extends string> implements ChDataType {

export class ChDateTime64<T extends number, V extends string> implements ChDataType {
readonly typeStr: `DateTime64(${T}, ${V})`
readonly dataTypeMarker = 'DateTime64' as const

constructor (readonly precision: T, readonly timezone: V) {
this.typeStr = `DateTime64(${precision}, ${timezone})`
}
Expand Down
7 changes: 4 additions & 3 deletions data_types/ch_enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChEnum<T extends Record<string, number>> implements ChDataType {
readonly typeStr: string
readonly dataType: T
readonly innerType: T
readonly dataTypeMarker = 'Enum' as const

constructor (enumObj: T) {
this.dataType = enumObj
this.innerType = enumObj
this.typeStr = this.toString()
}

toString (): string {
return `Enum(${Object.keys(this.dataType).map((key) => `'${key}' = ${this.dataType[key]}`).join(',')})`
return `Enum(${Object.keys(this.innerType).map((key) => `'${key}' = ${this.innerType[key]}`).join(',')})`
}
}
3 changes: 3 additions & 0 deletions data_types/ch_float.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChFloat32 implements ChDataType {
readonly typeStr: 'Float32' = 'Float32' as const
readonly dataTypeMarker = 'Float32' as const

toString (): string {
return this.typeStr
Expand All @@ -10,6 +11,8 @@ export class ChFloat32 implements ChDataType {

export class ChFloat64 implements ChDataType {
readonly typeStr: 'Float64' = 'Float64' as const
readonly dataTypeMarker = 'Float64' as const

toString (): string {
return this.typeStr
}
Expand Down
8 changes: 8 additions & 0 deletions data_types/ch_integer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChUInt8 implements ChDataType {
readonly typeStr: 'UInt8' = 'UInt8' as const
readonly dataTypeMarker = 'UInt8' as const
constructor () {
this.typeStr = 'UInt8'
}
Expand All @@ -13,6 +14,7 @@ export class ChUInt8 implements ChDataType {

export class ChUInt16 implements ChDataType {
readonly typeStr: 'UInt16' = 'UInt16' as const
readonly dataTypeMarker = 'UInt16' as const
constructor () {
this.typeStr = 'UInt16'
}
Expand All @@ -24,20 +26,25 @@ export class ChUInt16 implements ChDataType {

export class ChUInt32 implements ChDataType {
readonly typeStr: 'UInt32' = 'UInt32' as const
readonly dataTypeMarker = 'UInt32' as const

toString (): string {
return this.typeStr
}
}

export class ChUInt64 implements ChDataType {
readonly typeStr: 'UInt64' = 'UInt64' as const
readonly dataTypeMarker = 'UInt64' as const

toString (): string {
return this.typeStr
}
}

export class ChInt8 implements ChDataType {
readonly typeStr: 'Int8' = 'Int8' as const
readonly dataTypeMarker = 'Int8' as const

toString (): string {
return this.typeStr
Expand All @@ -46,6 +53,7 @@ export class ChInt8 implements ChDataType {

export class ChInt16 implements ChDataType {
readonly typeStr: 'Int16' = 'Int16' as const
readonly dataTypeMarker = 'Int16' as const

toString (): string {
return this.typeStr
Expand Down
5 changes: 4 additions & 1 deletion data_types/ch_json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChJSON<T extends Record<string, SchemaValue>> implements ChDataType {
readonly typeStr: 'JSON'
constructor (readonly dataType: T) {
readonly innerType: T
readonly dataTypeMarker = 'JSON' as const
constructor (innerType: T) {
this.typeStr = 'JSON'
this.innerType = innerType
}

toString (): string {
Expand Down
16 changes: 16 additions & 0 deletions data_types/ch_nullable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { type ChPrimitiveType, type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChNullable<T extends ChPrimitiveType> implements ChDataType {
readonly typeStr
readonly innerType: T
readonly dataTypeMarker = 'Nullable' as const

constructor (t: T) {
this.innerType = t
this.typeStr = `Nullable(${this.innerType})`
}

toString (): string {
return this.typeStr
}
}
2 changes: 2 additions & 0 deletions data_types/ch_string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChString implements ChDataType {
readonly typeStr: 'String' = 'String' as const
readonly dataTypeMarker = 'String' as const
toString (): string {
return this.typeStr
}
}

export class ChFixedString<T extends number> implements ChDataType {
readonly typeStr: `FixedString(${string})`
readonly dataTypeMarker = 'FixedString' as const
constructor (readonly length: T) {
this.typeStr = `FixedString(${length})`
}
Expand Down
1 change: 1 addition & 0 deletions data_types/ch_uuid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type ChDataType } from '@clickhouse-schema-data-types/index'

export class ChUUID implements ChDataType {
readonly typeStr: 'UUID' = 'UUID' as const
readonly dataTypeMarker = 'UUID' as const
toString (): string {
return this.typeStr
}
Expand Down
12 changes: 11 additions & 1 deletion data_types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import { ChUInt8, ChUInt16, ChUInt32, ChUInt64, ChInt8, ChInt16 } from '@clickho
import { ChJSON } from '@clickhouse-schema-data-types/ch_json'
import { ChString, ChFixedString } from '@clickhouse-schema-data-types/ch_string'
import { ChUUID } from '@clickhouse-schema-data-types/ch_uuid'
import { ChNullable } from '@clickhouse-schema-data-types/ch_nullable'

export interface ChDataType {
typeStr: string
dataTypeMarker: string
toString: () => string
}

Expand All @@ -33,7 +35,8 @@ export const ClickhouseTypes = {
FixedString: <T extends number>(length: T) => new ChFixedString(length),
JSON: <T extends Record<string, SchemaValue>>(schema: T) => new ChJSON(schema),
Array: <T extends ChDataType>(t: T) => new ChArray(t),
Enum: <T extends Record<string, number>>(enumObj: T) => new ChEnum(enumObj)
Enum: <T extends Record<string, number>>(enumObj: T) => new ChEnum(enumObj),
Nullable: <T extends ChPrimitiveType>(type: T) => new ChNullable(type)
}

export interface MapChSchemaTypes {
Expand All @@ -56,3 +59,10 @@ export interface MapChSchemaTypes {
DateTime64: Date
FixedString: string
}

export type ChPrimitiveType =
ChBoolean | ChUInt8 | ChUInt16 | ChUInt32 | ChUInt64 | ChInt8 | ChInt16 |
ChFloat32 | ChFloat64 | ChString | ChUUID | ChDate | ChDate32 | ChDateTime<string> |
ChDateTime64<number, string> | ChFixedString<number>

export type ChCompositeType = ChArray<ChArray<ChDataType> | ChDataType> | ChEnum<Record<string, number>> | ChNullable<ChPrimitiveType>
2 changes: 1 addition & 1 deletion examples/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const requestFieldsTable = new ClickhouseSchema({
status_code: { type: ClickhouseTypes.UInt32 },
url: { type: ClickhouseTypes.String },
request_method: { type: ClickhouseTypes.Enum({ GET: 0, POST: 1, PUT: 2, DELETE: 3 }) },
request_time: { type: ClickhouseTypes.DateTime('UTC') }
request_time: { type: ClickhouseTypes.Nullable(ClickhouseTypes.DateTime('UTC')) }
}, { table_name: 'request_data', primary_key: 'id' })

type RequestFields = InferClickhouseSchemaType<typeof requestFieldsTable>
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/data_types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,9 @@ describe('Data Types Tests', () => {
const enumType = new ChEnum({ POST: 1, PUT: 2, DELETE: 3, GET: 4 })
expect(enumType.toString()).toEqual('Enum(\'POST\' = 1,\'PUT\' = 2,\'DELETE\' = 3,\'GET\' = 4)')
})

it('should correctly create a nullable data types with the correct typeStr', () => {
const nullableString = ClickhouseTypes.Nullable(ClickhouseTypes.String)
expect(nullableString.toString()).toEqual('Nullable(String)')
})
})
7 changes: 0 additions & 7 deletions utils/type_inference.ts

This file was deleted.

28 changes: 28 additions & 0 deletions utils/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type ChArray } from '@clickhouse-schema-data-types/ch_array'
import { type ChEnum } from '@clickhouse-schema-data-types/ch_enum'
import { type ChJSON } from '@clickhouse-schema-data-types/ch_json'
import { type ChNullable } from '@clickhouse-schema-data-types/ch_nullable'
import { type MapChSchemaTypes, type ChDataType } from '@clickhouse-schema-data-types/index'

/* eslint-disable @typescript-eslint/no-unused-vars */
export type ExtractInnerType<T extends string> = T extends `${infer _BeforeBracket}(${infer Rest})`
? ExtractInnerType<Rest>
: T
export type ExtractOuterType<T extends string> = T extends `${infer BeforeBracket}(${infer _Rest})`
? BeforeBracket
: T

/** InferTypeFromMap is a type that takes a string and returns the typescript that it represents */
export type InferTypeFromMap<T extends string> = ExtractInnerType<T> extends keyof MapChSchemaTypes
? MapChSchemaTypes[ExtractInnerType<T>]
: ExtractOuterType<T> extends keyof MapChSchemaTypes ?
MapChSchemaTypes[ExtractOuterType<T>]
: unknown

export type InferArray<T extends ChDataType> = T extends ChArray<infer ArrayType> ? Array<InferArray<ArrayType>> : InferTypeFromMap<T['typeStr']>

export type InferEnum<T extends ChDataType> = T extends ChEnum<infer EnumType> ? keyof EnumType : InferTypeFromMap<T['typeStr']>

export type InferJSON<T extends ChDataType> = T extends ChJSON<infer Schema> ? { [K in keyof T['innerType']]: InferJSON<Schema[K]['type']> } : InferTypeFromMap<T['typeStr']>

export type InferNullable<T extends ChDataType> = T extends ChNullable<infer NullableType> ? InferTypeFromMap<NullableType['typeStr']> | null : InferTypeFromMap<T['typeStr']>

1 comment on commit eaccab5

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report

St.
Category Percentage Covered / Total
🟢 Statements 100% 129/129
🟢 Branches 100% 25/25
🟢 Functions 100% 54/54
🟢 Lines 100% 126/126

Test suite run success

20 tests passing in 2 suites.

Report generated by 🧪jest coverage report action from eaccab5

Please sign in to comment.