@syntropix/database 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +1 -1
- package/.vscode/settings.json +1 -8
- package/dist/core/client.d.ts +0 -1
- package/dist/core/client.js +2 -6
- package/dist/core/config.d.ts +0 -1
- package/dist/core/config.js +5 -6
- package/dist/core/dataClient.d.ts +0 -1
- package/dist/core/dataClient.js +4 -13
- package/dist/core/syntropix.d.ts +0 -1
- package/dist/core/syntropix.js +8 -10
- package/dist/core/tableClient.d.ts +2 -2
- package/dist/core/tableClient.js +4 -8
- package/dist/index.d.ts +0 -1
- package/dist/index.js +9 -33
- package/dist/types/basemodel.d.ts +2 -2
- package/dist/types/basemodel.js +32 -39
- package/dist/types/common.d.ts +1 -2
- package/dist/types/common.js +4 -8
- package/dist/types/data-type.d.ts +0 -1
- package/dist/types/data-type.js +18 -23
- package/dist/types/dto/base.d.ts +4 -0
- package/dist/types/dto/base.js +1 -0
- package/dist/types/dto/table.d.ts +22 -0
- package/dist/types/dto/table.js +1 -0
- package/dist/types/field.d.ts +0 -1
- package/dist/types/field.js +47 -62
- package/dist/types/filter.d.ts +0 -1
- package/dist/types/filter.js +35 -70
- package/dist/types/requests.d.ts +0 -1
- package/dist/types/requests.js +1 -3
- package/eslint.config.mjs +23 -23
- package/examples/tsconfig.json +13 -0
- package/examples/usage.ts +73 -52
- package/jest.config.ts +9 -0
- package/package.json +6 -5
- package/src/core/dataClient.ts +1 -6
- package/src/core/tableClient.ts +3 -2
- package/src/types/basemodel.ts +3 -2
- package/src/types/common.ts +83 -83
- package/src/types/dto/base.ts +4 -0
- package/src/types/dto/table.ts +21 -0
- package/src/types/filter.ts +28 -1
- package/src/types/requests.ts +2 -52
- package/tests/basic.test.ts +130 -62
- package/tests/tsconfig.json +8 -0
- package/tsconfig.json +18 -50
- package/dist/core/client.d.ts.map +0 -1
- package/dist/core/client.js.map +0 -1
- package/dist/core/config.d.ts.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/dataClient.d.ts.map +0 -1
- package/dist/core/dataClient.js.map +0 -1
- package/dist/core/syntropix.d.ts.map +0 -1
- package/dist/core/syntropix.js.map +0 -1
- package/dist/core/tableClient.d.ts.map +0 -1
- package/dist/core/tableClient.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types/basemodel.d.ts.map +0 -1
- package/dist/types/basemodel.js.map +0 -1
- package/dist/types/common.d.ts.map +0 -1
- package/dist/types/common.js.map +0 -1
- package/dist/types/data-type.d.ts.map +0 -1
- package/dist/types/data-type.js.map +0 -1
- package/dist/types/field.d.ts.map +0 -1
- package/dist/types/field.js.map +0 -1
- package/dist/types/filter.d.ts.map +0 -1
- package/dist/types/filter.js.map +0 -1
- package/dist/types/requests.d.ts.map +0 -1
- package/dist/types/requests.js.map +0 -1
- package/examples/advanced-usage.d.ts +0 -42
- package/examples/advanced-usage.d.ts.map +0 -1
- package/examples/advanced-usage.js +0 -257
- package/examples/advanced-usage.js.map +0 -1
- package/examples/usage.d.ts +0 -11
- package/examples/usage.d.ts.map +0 -1
- package/examples/usage.js +0 -91
- package/examples/usage.js.map +0 -1
- package/jest.config.js +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syntropix/database",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "TypeScript SDK for database operations with ORM support",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
@@ -12,9 +13,9 @@
|
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "tsc",
|
|
14
15
|
"dev": "tsc --watch",
|
|
15
|
-
"test": "jest",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
16
|
+
"test": "node --experimental-vm-modules $(yarn bin jest)",
|
|
17
|
+
"publish": "npm publish --access public",
|
|
18
|
+
"example": "tsx --tsconfig examples/tsconfig.json examples/usage.ts",
|
|
18
19
|
"lint": "eslint",
|
|
19
20
|
"lint:fix": "eslint --fix",
|
|
20
21
|
"format": "prettier --write .",
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
"typescript",
|
|
27
28
|
"sdk"
|
|
28
29
|
],
|
|
29
|
-
"author": "Syntropix",
|
|
30
|
+
"author": "Syntropix, Inc.",
|
|
30
31
|
"license": "MIT",
|
|
31
32
|
"dependencies": {
|
|
32
33
|
"dotenv": "^17.2.3",
|
package/src/core/dataClient.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { ClientConfig } from './config';
|
|
|
5
5
|
export class DataClient {
|
|
6
6
|
private client: Client;
|
|
7
7
|
|
|
8
|
-
constructor(config: ClientConfig) {
|
|
8
|
+
constructor(config: ClientConfig = new ClientConfig()) {
|
|
9
9
|
this.client = new Client(config);
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -26,8 +26,6 @@ export class DataClient {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
async updateByPrimaryKey(pk: string, data: Update): Promise<any> {
|
|
29
|
-
console.log(pk);
|
|
30
|
-
console.log(data);
|
|
31
29
|
const response = await this.client.post(`/update/${pk}`, data);
|
|
32
30
|
if (response.status === 'success') {
|
|
33
31
|
return response.data;
|
|
@@ -40,9 +38,6 @@ export class DataClient {
|
|
|
40
38
|
if (response.status === 'success') {
|
|
41
39
|
const responseData = response.data;
|
|
42
40
|
if (model !== undefined) {
|
|
43
|
-
// In TypeScript, we would typically use a validation library or manual validation
|
|
44
|
-
// For now, we'll return the data as-is, but in a real implementation you might want to use
|
|
45
|
-
// a library like class-validator or zod for validation
|
|
46
41
|
return new model(responseData);
|
|
47
42
|
}
|
|
48
43
|
return responseData;
|
package/src/core/tableClient.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TableCreateResponse } from '@/types/dto/table';
|
|
1
2
|
import { SyntropixDBTable } from '../types/common';
|
|
2
3
|
import {
|
|
3
4
|
TableAddColumn,
|
|
@@ -15,11 +16,11 @@ import { ClientConfig } from './config';
|
|
|
15
16
|
export class TableClient {
|
|
16
17
|
private client: Client;
|
|
17
18
|
|
|
18
|
-
constructor(config: ClientConfig) {
|
|
19
|
+
constructor(config: ClientConfig = new ClientConfig()) {
|
|
19
20
|
this.client = new Client(config);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
async createTable(data: TableCreate): Promise<
|
|
23
|
+
async createTable(data: TableCreate): Promise<TableCreateResponse> {
|
|
23
24
|
const response = await this.client.post('/table/create', data);
|
|
24
25
|
if (response.status === 'success') {
|
|
25
26
|
return response.data;
|
package/src/types/basemodel.ts
CHANGED
|
@@ -3,6 +3,7 @@ import 'reflect-metadata';
|
|
|
3
3
|
import { ClientConfig } from '../core/config';
|
|
4
4
|
import { SyntropixClient } from '../core/syntropix';
|
|
5
5
|
import { Aggregate, AggregateFunction, ForeignKey, GroupBy, Index, Join, Sort } from './common';
|
|
6
|
+
import { TableCreateResponse } from './dto/table';
|
|
6
7
|
import { Field, ForeignKeyField, IntegerField } from './field';
|
|
7
8
|
import { AND, EQ, Filter, GTE, OR, Value } from './filter';
|
|
8
9
|
|
|
@@ -218,7 +219,7 @@ export class BaseModel {
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
// Table operations
|
|
221
|
-
static async createTable(_client?: SyntropixClient | null): Promise<
|
|
222
|
+
static async createTable(_client?: SyntropixClient | null): Promise<TableCreateResponse> {
|
|
222
223
|
const fields = this.getFields();
|
|
223
224
|
const columns = Object.values(fields).map((f) => f.into());
|
|
224
225
|
const foreignKeys: ForeignKey[] = this.getAssociations().map((f) => ({
|
|
@@ -465,7 +466,7 @@ export class BaseModel {
|
|
|
465
466
|
this: new (data?: any) => T,
|
|
466
467
|
options: {
|
|
467
468
|
filter: Filter;
|
|
468
|
-
sort?: Sort;
|
|
469
|
+
sort?: Sort[];
|
|
469
470
|
aggregate?: Aggregate[];
|
|
470
471
|
join?: Join;
|
|
471
472
|
limit?: number;
|
package/src/types/common.ts
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
// Common types used across the SDK
|
|
2
|
-
|
|
3
|
-
export enum ForeignKeyAction {
|
|
4
|
-
CASCADE = 'Cascade',
|
|
5
|
-
RESTRICT = 'Restrict',
|
|
6
|
-
SET_NULL = 'SetNull',
|
|
7
|
-
NO_ACTION = 'NoAction',
|
|
8
|
-
SET_DEFAULT = 'SetDefault',
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export enum AggregateFunction {
|
|
12
|
-
COUNT = 'Count',
|
|
13
|
-
SUM = 'Sum',
|
|
14
|
-
AVG = 'AVG',
|
|
15
|
-
MIN = 'Min',
|
|
16
|
-
MAX = 'Max',
|
|
17
|
-
COUNT_DISTINCT = 'CountDistinct',
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface Sort {
|
|
21
|
-
column: string;
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface Join {
|
|
26
|
-
type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
|
|
27
|
-
table: string;
|
|
28
|
-
on: any;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface Aggregate {
|
|
32
|
-
column: string;
|
|
33
|
-
function: AggregateFunction;
|
|
34
|
-
alias: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface GroupBy {
|
|
38
|
-
columns: string[];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export interface ForeignKey {
|
|
42
|
-
from_table: string;
|
|
43
|
-
from_column: string;
|
|
44
|
-
to_table: string;
|
|
45
|
-
to_column: string;
|
|
46
|
-
on_delete?: ForeignKeyAction;
|
|
47
|
-
on_update?: ForeignKeyAction;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface Column {
|
|
51
|
-
name: string;
|
|
52
|
-
column_type: string | Record<string, any>;
|
|
53
|
-
description?: string;
|
|
54
|
-
is_primary_key?: boolean;
|
|
55
|
-
is_nullable?: boolean;
|
|
56
|
-
auto_increment?: boolean;
|
|
57
|
-
default?: any;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface Index {
|
|
61
|
-
name: string;
|
|
62
|
-
columns: string[];
|
|
63
|
-
unique?: boolean;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface SyntropixDBColumn {
|
|
67
|
-
id: string; // UUID as string in TypeScript
|
|
68
|
-
name: string;
|
|
69
|
-
description: string;
|
|
70
|
-
column_type: string | Record<string, any>;
|
|
71
|
-
is_nullable: boolean;
|
|
72
|
-
is_primary_key: boolean;
|
|
73
|
-
auto_increment: boolean;
|
|
74
|
-
default?: any; // Optional field
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface SyntropixDBTable {
|
|
78
|
-
id: string; // UUID as string in TypeScript
|
|
79
|
-
name: string;
|
|
80
|
-
description: string;
|
|
81
|
-
created_at: Date;
|
|
82
|
-
columns: SyntropixDBColumn[];
|
|
83
|
-
}
|
|
1
|
+
// Common types used across the SDK
|
|
2
|
+
|
|
3
|
+
export enum ForeignKeyAction {
|
|
4
|
+
CASCADE = 'Cascade',
|
|
5
|
+
RESTRICT = 'Restrict',
|
|
6
|
+
SET_NULL = 'SetNull',
|
|
7
|
+
NO_ACTION = 'NoAction',
|
|
8
|
+
SET_DEFAULT = 'SetDefault',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export enum AggregateFunction {
|
|
12
|
+
COUNT = 'Count',
|
|
13
|
+
SUM = 'Sum',
|
|
14
|
+
AVG = 'AVG',
|
|
15
|
+
MIN = 'Min',
|
|
16
|
+
MAX = 'Max',
|
|
17
|
+
COUNT_DISTINCT = 'CountDistinct',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface Sort {
|
|
21
|
+
column: string;
|
|
22
|
+
direction: 'ASCENDING' | 'DESCENDING';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Join {
|
|
26
|
+
type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
|
|
27
|
+
table: string;
|
|
28
|
+
on: any;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface Aggregate {
|
|
32
|
+
column: string;
|
|
33
|
+
function: AggregateFunction;
|
|
34
|
+
alias: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface GroupBy {
|
|
38
|
+
columns: string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ForeignKey {
|
|
42
|
+
from_table: string;
|
|
43
|
+
from_column: string;
|
|
44
|
+
to_table: string;
|
|
45
|
+
to_column: string;
|
|
46
|
+
on_delete?: ForeignKeyAction;
|
|
47
|
+
on_update?: ForeignKeyAction;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Column {
|
|
51
|
+
name: string;
|
|
52
|
+
column_type: string | Record<string, any>;
|
|
53
|
+
description?: string;
|
|
54
|
+
is_primary_key?: boolean;
|
|
55
|
+
is_nullable?: boolean;
|
|
56
|
+
auto_increment?: boolean;
|
|
57
|
+
default?: any;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface Index {
|
|
61
|
+
name: string;
|
|
62
|
+
columns: string[];
|
|
63
|
+
unique?: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface SyntropixDBColumn {
|
|
67
|
+
id: string; // UUID as string in TypeScript
|
|
68
|
+
name: string;
|
|
69
|
+
description: string;
|
|
70
|
+
column_type: string | Record<string, any>;
|
|
71
|
+
is_nullable: boolean;
|
|
72
|
+
is_primary_key: boolean;
|
|
73
|
+
auto_increment: boolean;
|
|
74
|
+
default?: any; // Optional field
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface SyntropixDBTable {
|
|
78
|
+
id: string; // UUID as string in TypeScript
|
|
79
|
+
name: string;
|
|
80
|
+
description: string;
|
|
81
|
+
created_at: Date;
|
|
82
|
+
columns: SyntropixDBColumn[];
|
|
83
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Column, ForeignKey, Index } from '../common';
|
|
2
|
+
|
|
3
|
+
export interface TableCreateResponse {
|
|
4
|
+
_id: { $oid: string };
|
|
5
|
+
table: {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
created_at: any;
|
|
10
|
+
columns: Column[];
|
|
11
|
+
foreign_keys: ForeignKey[];
|
|
12
|
+
indexes: Index[];
|
|
13
|
+
schema: string;
|
|
14
|
+
default_access: string | null;
|
|
15
|
+
};
|
|
16
|
+
created_at: any;
|
|
17
|
+
updated_at: any;
|
|
18
|
+
created_by: string;
|
|
19
|
+
metadata: Record<string, any>;
|
|
20
|
+
triggers: any[];
|
|
21
|
+
}
|
package/src/types/filter.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// Filter types for database queries
|
|
2
|
-
|
|
3
2
|
export enum SortType {
|
|
4
3
|
DESCENDING = 'DESCENDING',
|
|
5
4
|
ASCENDING = 'ASCENDING',
|
|
@@ -20,9 +19,13 @@ export enum FilterOperation {
|
|
|
20
19
|
NEQ = 'NEQ',
|
|
21
20
|
Between = 'Between',
|
|
22
21
|
In = 'In',
|
|
22
|
+
Contains = 'Contains',
|
|
23
|
+
Overlap = 'Overlap',
|
|
23
24
|
NotIn = 'NotIn',
|
|
24
25
|
Like = 'Like',
|
|
25
26
|
NotLike = 'NotLike',
|
|
27
|
+
ILike = 'ILike',
|
|
28
|
+
NotILike = 'NotILike',
|
|
26
29
|
IsNull = 'IsNull',
|
|
27
30
|
IsNotNull = 'IsNotNull',
|
|
28
31
|
Similarity = 'Similarity',
|
|
@@ -99,6 +102,30 @@ export const IN = (field: string, values: any[]): SyntropixDBFilterItem => ({
|
|
|
99
102
|
static_value: values,
|
|
100
103
|
});
|
|
101
104
|
|
|
105
|
+
export const CONTAINS = (field: string, value: any): SyntropixDBFilterItem => ({
|
|
106
|
+
column: field,
|
|
107
|
+
operator: FilterOperation.Contains,
|
|
108
|
+
static_value: value,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
export const OVERLAP = (field: string, value: any): SyntropixDBFilterItem => ({
|
|
112
|
+
column: field,
|
|
113
|
+
operator: FilterOperation.Overlap,
|
|
114
|
+
static_value: value,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
export const I_LIKE = (field: string, pattern: string): SyntropixDBFilterItem => ({
|
|
118
|
+
column: field,
|
|
119
|
+
operator: FilterOperation.ILike,
|
|
120
|
+
static_value: pattern,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export const NOT_I_LIKE = (field: string, pattern: string): SyntropixDBFilterItem => ({
|
|
124
|
+
column: field,
|
|
125
|
+
operator: FilterOperation.NotILike,
|
|
126
|
+
static_value: pattern,
|
|
127
|
+
});
|
|
128
|
+
|
|
102
129
|
export const NOT_IN = (field: string, values: any[]): SyntropixDBFilterItem => ({
|
|
103
130
|
column: field,
|
|
104
131
|
operator: FilterOperation.NotIn,
|
package/src/types/requests.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Request types for database operations
|
|
2
2
|
import { Aggregate, Column, ForeignKey, GroupBy, Index, Join, Sort } from './common';
|
|
3
|
-
import { Filter
|
|
3
|
+
import { Filter } from './filter';
|
|
4
4
|
|
|
5
5
|
// Table operations
|
|
6
6
|
export interface TableCreate {
|
|
@@ -76,7 +76,7 @@ export interface DeleteData {
|
|
|
76
76
|
|
|
77
77
|
export interface QueryPayload {
|
|
78
78
|
filter?: Filter;
|
|
79
|
-
sort?: Sort;
|
|
79
|
+
sort?: Sort[];
|
|
80
80
|
aggregate?: Aggregate[];
|
|
81
81
|
join?: Join[];
|
|
82
82
|
limit?: number;
|
|
@@ -89,53 +89,3 @@ export interface Query {
|
|
|
89
89
|
table_name: string;
|
|
90
90
|
query: QueryPayload;
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
// Rust-compatible type definitions
|
|
94
|
-
export interface SyntropixDBSortItem {
|
|
95
|
-
column: string;
|
|
96
|
-
direction: SortType;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export type SyntropixDBSort = SyntropixDBSortItem[];
|
|
100
|
-
|
|
101
|
-
export interface SyntropixDBJoin {
|
|
102
|
-
table: string;
|
|
103
|
-
on: string;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export interface SyntropixDBAggregate {
|
|
107
|
-
function: string;
|
|
108
|
-
column: string;
|
|
109
|
-
alias: string;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export type SyntropixDBGroupBy = string[];
|
|
113
|
-
|
|
114
|
-
export type SyntropixDBDistinct = string[];
|
|
115
|
-
|
|
116
|
-
export interface SyntropixDBQuery {
|
|
117
|
-
filter: SyntropixDBFilter;
|
|
118
|
-
sort?: SyntropixDBSort;
|
|
119
|
-
limit?: number;
|
|
120
|
-
offset?: number;
|
|
121
|
-
select?: string[];
|
|
122
|
-
join?: SyntropixDBJoin[];
|
|
123
|
-
aggregate?: SyntropixDBAggregate[];
|
|
124
|
-
group_by?: SyntropixDBGroupBy;
|
|
125
|
-
distinct?: SyntropixDBDistinct;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export interface SyntropixDBInsert {
|
|
129
|
-
columns: string[];
|
|
130
|
-
values: any[][];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export interface SyntropixDBUpdate {
|
|
134
|
-
filter: SyntropixDBFilter;
|
|
135
|
-
columns: string[];
|
|
136
|
-
values: any[];
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export interface SyntropixDBDelete {
|
|
140
|
-
filter: SyntropixDBFilter;
|
|
141
|
-
}
|
package/tests/basic.test.ts
CHANGED
|
@@ -1,73 +1,141 @@
|
|
|
1
|
-
|
|
1
|
+
import { BaseModel, Column } from '@/types/basemodel';
|
|
2
|
+
import { AND, EQ, OR } from '@/types/filter';
|
|
3
|
+
|
|
2
4
|
import 'dotenv/config';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@Column(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@Column(
|
|
5
|
+
|
|
6
|
+
const getRandomString = () => {
|
|
7
|
+
return Math.random().toString(36).substring(2, 15);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
class User extends BaseModel {
|
|
11
|
+
static tableName = `test_users_${getRandomString()}`;
|
|
12
|
+
|
|
13
|
+
@Column({ type: 'Integer', primary: true, auto_increment: true })
|
|
14
|
+
declare id: number;
|
|
15
|
+
|
|
16
|
+
@Column()
|
|
17
|
+
declare email: string;
|
|
18
|
+
|
|
19
|
+
@Column({ name: 'full_name' })
|
|
20
|
+
declare fullName: string;
|
|
21
|
+
|
|
22
|
+
@Column({ type: 'Json', nullable: true })
|
|
23
|
+
declare profile: any;
|
|
24
|
+
|
|
25
|
+
@Column({ type: 'Boolean', name: 'is_active' })
|
|
26
|
+
declare isActive: boolean;
|
|
15
27
|
}
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
async
|
|
19
|
-
|
|
20
|
-
await User.createTable();
|
|
21
|
-
|
|
22
|
-
// Create a new user
|
|
23
|
-
const newUser = await User.create({
|
|
24
|
-
id: 1,
|
|
25
|
-
email: 'user@example.com',
|
|
26
|
-
fullName: 'John Doe',
|
|
27
|
-
isActive: true,
|
|
29
|
+
describe('BaseModel ORM', () => {
|
|
30
|
+
beforeAll(async () => {
|
|
31
|
+
await User.createTable();
|
|
28
32
|
});
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
describe('User CRUD Operations', () => {
|
|
35
|
+
let userId: number;
|
|
36
|
+
let userEmail: string;
|
|
37
|
+
let userFullName: string;
|
|
38
|
+
|
|
39
|
+
test('should create a user', async () => {
|
|
40
|
+
const randomValue = getRandomString();
|
|
41
|
+
userEmail = `user${randomValue}@example.com`;
|
|
42
|
+
userFullName = `User ${randomValue}`;
|
|
43
|
+
const userCreateResp = await User.create({
|
|
44
|
+
email: userEmail,
|
|
45
|
+
fullName: userFullName,
|
|
46
|
+
isActive: true,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
expect(userCreateResp).toBeDefined();
|
|
50
|
+
expect(userCreateResp.pk).toBeDefined();
|
|
51
|
+
userId = userCreateResp.pk;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('should retrieve the created user by id', async () => {
|
|
55
|
+
const user = await User.get(OR(AND(EQ('id', userId))));
|
|
56
|
+
expect(user).toBeDefined();
|
|
57
|
+
expect(user.email).toBe(userEmail);
|
|
58
|
+
expect(user.fullName).toBe(userFullName);
|
|
59
|
+
expect(user.isActive).toBe(true);
|
|
60
|
+
expect(user.profile).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('should update a user', async () => {
|
|
64
|
+
const user = await User.get(OR(AND(EQ('id', userId))));
|
|
65
|
+
userFullName = `User ${getRandomString()}`;
|
|
66
|
+
user.fullName = userFullName;
|
|
67
|
+
await user.save();
|
|
33
68
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
69
|
+
const updatedUser = await User.get(OR(AND(EQ('id', userId))));
|
|
70
|
+
expect(updatedUser.fullName).toBe(userFullName);
|
|
71
|
+
});
|
|
37
72
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
73
|
+
test('should filter users by active status', async () => {
|
|
74
|
+
const activeUsers = await User.filter({
|
|
75
|
+
filter: OR(AND(EQ('is_active', true))),
|
|
76
|
+
limit: 10,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(activeUsers).toBeDefined();
|
|
80
|
+
expect(Array.isArray(activeUsers)).toBe(true);
|
|
81
|
+
activeUsers.forEach((user) => {
|
|
82
|
+
expect(user.isActive).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('should count users by active status', async () => {
|
|
87
|
+
const userCount = await User.count({
|
|
88
|
+
filter: OR(AND(EQ('is_active', true))),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(userCount).toBeDefined();
|
|
92
|
+
expect(typeof userCount).toBe('number');
|
|
93
|
+
expect(userCount).toBeGreaterThanOrEqual(0);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('should delete a user', async () => {
|
|
97
|
+
const user = await User.get(OR(AND(EQ('id', userId))));
|
|
98
|
+
await user.remove();
|
|
99
|
+
|
|
100
|
+
// Verify user is deleted (this might throw or return null depending on implementation)
|
|
101
|
+
await expect(User.get(OR(AND(EQ('id', userId))))).rejects.toThrow();
|
|
102
|
+
});
|
|
42
103
|
});
|
|
43
104
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
105
|
+
describe('Bulk Operations', () => {
|
|
106
|
+
test('should bulk create multiple users', async () => {
|
|
107
|
+
const users = await User.bulkCreate([
|
|
108
|
+
{
|
|
109
|
+
email: 'user2@example.com',
|
|
110
|
+
fullName: 'User 2',
|
|
111
|
+
isActive: true,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
email: 'user3@example.com',
|
|
115
|
+
fullName: 'User 3',
|
|
116
|
+
isActive: false,
|
|
117
|
+
},
|
|
118
|
+
]);
|
|
119
|
+
|
|
120
|
+
expect(users).toBeDefined();
|
|
121
|
+
expect(users).toBe(2);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('should retrieve bulk created users', async () => {
|
|
125
|
+
const user2 = await User.get(OR(AND(EQ('email', 'user2@example.com'))));
|
|
126
|
+
const user3 = await User.get(OR(AND(EQ('email', 'user3@example.com'))));
|
|
127
|
+
|
|
128
|
+
expect(user2).toBeDefined();
|
|
129
|
+
expect(user2.fullName).toBe('User 2');
|
|
130
|
+
expect(user2.isActive).toBe(true);
|
|
131
|
+
|
|
132
|
+
expect(user3).toBeDefined();
|
|
133
|
+
expect(user3.fullName).toBe('User 3');
|
|
134
|
+
expect(user3.isActive).toBe(false);
|
|
135
|
+
});
|
|
47
136
|
});
|
|
48
|
-
console.log(activeUsers);
|
|
49
|
-
console.log(userCount);
|
|
50
|
-
// // Delete user
|
|
51
|
-
await user.remove();
|
|
52
|
-
|
|
53
|
-
// // Bulk create
|
|
54
|
-
await User.bulkCreate([
|
|
55
|
-
{
|
|
56
|
-
id: 2,
|
|
57
|
-
email: 'user2@example.com',
|
|
58
|
-
fullName: 'User 2',
|
|
59
|
-
isActive: true,
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
id: 3,
|
|
63
|
-
email: 'user3@example.com',
|
|
64
|
-
fullName: 'User 3',
|
|
65
|
-
isActive: false,
|
|
66
|
-
},
|
|
67
|
-
]);
|
|
68
|
-
|
|
69
|
-
// console.log('All operations completed successfully!');
|
|
70
|
-
}
|
|
71
137
|
|
|
72
|
-
|
|
73
|
-
|
|
138
|
+
afterAll(async () => {
|
|
139
|
+
await User.dropTable();
|
|
140
|
+
});
|
|
141
|
+
});
|