@syntropix/database 0.0.2 → 0.0.4

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.
@@ -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
- 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
- }
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,4 @@
1
+ export interface ApiResponse<T> {
2
+ status: string;
3
+ data: T;
4
+ }
@@ -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
+ }
@@ -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,
@@ -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, SortType, SyntropixDBFilter } from './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
- }
@@ -1,57 +1,73 @@
1
- // Jest tests for BaseModel ORM
2
1
  import { BaseModel, Column } from '@/types/basemodel';
3
2
  import { AND, EQ, OR } from '@/types/filter';
3
+
4
4
  import 'dotenv/config';
5
5
 
6
- // User model for testing
6
+ const getRandomString = () => {
7
+ return Math.random().toString(36).substring(2, 15);
8
+ };
9
+
7
10
  class User extends BaseModel {
8
- static tableName = 'users';
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;
9
21
 
10
- @Column({ type: 'Integer', primary: true, auto_increment: true }) id!: number;
11
- @Column() email!: string;
12
- @Column({ name: 'full_name' }) fullName!: string;
13
- @Column({ type: 'Json', nullable: true }) profile?: any;
14
- @Column({ type: 'Boolean', name: 'is_active' }) isActive!: boolean;
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
29
  describe('BaseModel ORM', () => {
18
30
  beforeAll(async () => {
19
- // Create table before running tests
20
31
  await User.createTable();
21
32
  });
22
33
 
23
34
  describe('User CRUD Operations', () => {
24
- let createdUser: User;
25
-
26
- test('should create a new user', async () => {
27
- createdUser = await User.create({
28
- id: 1,
29
- email: 'user@example.com',
30
- fullName: 'John Doe',
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,
31
46
  isActive: true,
32
47
  });
33
48
 
34
- expect(createdUser).toBeDefined();
35
- expect(createdUser.email).toBe('user@example.com');
36
- expect(createdUser.fullName).toBe('John Doe');
37
- expect(createdUser.isActive).toBe(true);
49
+ expect(userCreateResp).toBeDefined();
50
+ expect(userCreateResp.pk).toBeDefined();
51
+ userId = userCreateResp.pk;
38
52
  });
39
53
 
40
- test('should retrieve a user by email', async () => {
41
- const user = await User.get(OR(AND(EQ('email', 'user@example.com'))));
42
-
54
+ test('should retrieve the created user by id', async () => {
55
+ const user = await User.get(OR(AND(EQ('id', userId))));
43
56
  expect(user).toBeDefined();
44
- expect(user.email).toBe('user@example.com');
45
- expect(user.fullName).toBe('John Doe');
57
+ expect(user.email).toBe(userEmail);
58
+ expect(user.fullName).toBe(userFullName);
59
+ expect(user.isActive).toBe(true);
60
+ expect(user.profile).toBeNull();
46
61
  });
47
62
 
48
63
  test('should update a user', async () => {
49
- const user = await User.get(OR(AND(EQ('email', 'user@example.com'))));
50
- user.fullName = 'Jane Doe';
64
+ const user = await User.get(OR(AND(EQ('id', userId))));
65
+ userFullName = `User ${getRandomString()}`;
66
+ user.fullName = userFullName;
51
67
  await user.save();
52
68
 
53
- const updatedUser = await User.get(OR(AND(EQ('email', 'user@example.com'))));
54
- expect(updatedUser.fullName).toBe('Jane Doe');
69
+ const updatedUser = await User.get(OR(AND(EQ('id', userId))));
70
+ expect(updatedUser.fullName).toBe(userFullName);
55
71
  });
56
72
 
57
73
  test('should filter users by active status', async () => {
@@ -78,11 +94,11 @@ describe('BaseModel ORM', () => {
78
94
  });
79
95
 
80
96
  test('should delete a user', async () => {
81
- const user = await User.get(OR(AND(EQ('email', 'user@example.com'))));
97
+ const user = await User.get(OR(AND(EQ('id', userId))));
82
98
  await user.remove();
83
99
 
84
100
  // Verify user is deleted (this might throw or return null depending on implementation)
85
- await expect(User.get(OR(AND(EQ('email', 'user@example.com'))))).rejects.toThrow();
101
+ await expect(User.get(OR(AND(EQ('id', userId))))).rejects.toThrow();
86
102
  });
87
103
  });
88
104
 
@@ -90,13 +106,11 @@ describe('BaseModel ORM', () => {
90
106
  test('should bulk create multiple users', async () => {
91
107
  const users = await User.bulkCreate([
92
108
  {
93
- id: 2,
94
109
  email: 'user2@example.com',
95
110
  fullName: 'User 2',
96
111
  isActive: true,
97
112
  },
98
113
  {
99
- id: 3,
100
114
  email: 'user3@example.com',
101
115
  fullName: 'User 3',
102
116
  isActive: false,
@@ -104,7 +118,7 @@ describe('BaseModel ORM', () => {
104
118
  ]);
105
119
 
106
120
  expect(users).toBeDefined();
107
- expect(Array.isArray(users)).toBe(true);
121
+ expect(users).toBe(2);
108
122
  });
109
123
 
110
124
  test('should retrieve bulk created users', async () => {
@@ -120,4 +134,8 @@ describe('BaseModel ORM', () => {
120
134
  expect(user3.isActive).toBe(false);
121
135
  });
122
136
  });
137
+
138
+ afterAll(async () => {
139
+ await User.dropTable();
140
+ });
123
141
  });
@@ -0,0 +1,8 @@
1
+ // This file is used to let VSCode respect the tsconfig.json for this test folder
2
+ {
3
+ "extends": "../tsconfig.json",
4
+ "include": [".", "../src"],
5
+ "compilerOptions": {
6
+ "noEmit": true
7
+ }
8
+ }
package/tsconfig.json CHANGED
@@ -1,21 +1,18 @@
1
- {
2
- "extends": "./tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "declaration": true
6
- },
7
- "include": [
8
- "src"
9
- ],
10
- "exclude": [
11
- "tests",
12
- "examples",
13
- "dist",
14
- "node_modules"
15
- ],
16
- "references": [
17
- {
18
- "path": "./tsconfig.test.json"
19
- }
20
- ]
21
- }
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "experimentalDecorators": true,
9
+ "emitDecoratorMetadata": true,
10
+ "baseUrl": ".",
11
+ "paths": {
12
+ "@/*": ["src/*"]
13
+ },
14
+ "outDir": "dist",
15
+ "declaration": true
16
+ },
17
+ "include": ["src"]
18
+ }
@@ -1,42 +0,0 @@
1
- import 'dotenv/config';
2
- import { BaseModel } from '../src/types/basemodel';
3
- export declare class CompanyGroup extends BaseModel {
4
- static tableName: string;
5
- static description: string;
6
- id: number;
7
- name: string;
8
- description: string;
9
- }
10
- export declare class CompanyGroupMember extends BaseModel {
11
- static tableName: string;
12
- static description: string;
13
- id: number;
14
- groupId: number;
15
- memberId: number;
16
- }
17
- export declare class CompanyMember extends BaseModel {
18
- static tableName: string;
19
- static description: string;
20
- id: number;
21
- userId: string;
22
- firstName: string;
23
- lastName: string;
24
- middleName: string | null;
25
- email: string;
26
- avatar: string | null;
27
- bio: string;
28
- role: 'admin' | 'user';
29
- personalKey: string;
30
- }
31
- export declare class CompanyApiKey extends BaseModel {
32
- static tableName: string;
33
- static description: string;
34
- id: number;
35
- name: string;
36
- description: string | null;
37
- key: string;
38
- createdAt: Date | string;
39
- isPersonal: boolean;
40
- createdBy: number;
41
- }
42
- //# sourceMappingURL=advanced-usage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"advanced-usage.d.ts","sourceRoot":"","sources":["advanced-usage.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAGvB,OAAO,EAAE,SAAS,EAAsB,MAAM,wBAAwB,CAAC;AAGvE,qBAAa,YAAa,SAAQ,SAAS;IACzC,MAAM,CAAC,SAAS,SAA8B;IAC9C,MAAM,CAAC,WAAW,SAAoB;IAQtC,EAAE,EAAG,MAAM,CAAC;IAGZ,IAAI,EAAG,MAAM,CAAC;IAGd,WAAW,EAAG,MAAM,CAAC;CACtB;AAED,qBAAa,kBAAmB,SAAQ,SAAS;IAC/C,MAAM,CAAC,SAAS,SAAqC;IACrD,MAAM,CAAC,WAAW,SAA2B;IAQ7C,EAAE,EAAG,MAAM,CAAC;IAGZ,OAAO,EAAG,MAAM,CAAC;IAGjB,QAAQ,EAAG,MAAM,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,SAAS;IAC1C,MAAM,CAAC,SAAS,SAA+B;IAC/C,MAAM,CAAC,WAAW,SAAqB;IAQvC,EAAE,EAAG,MAAM,CAAC;IAQZ,MAAM,EAAG,MAAM,CAAC;IAQhB,SAAS,EAAG,MAAM,CAAC;IAOnB,QAAQ,EAAG,MAAM,CAAC;IAOlB,UAAU,EAAG,MAAM,GAAG,IAAI,CAAC;IAO3B,KAAK,EAAG,MAAM,CAAC;IAOf,MAAM,EAAG,MAAM,GAAG,IAAI,CAAC;IAEvB,GAAG,EAAG,MAAM,CAAC;IAOb,IAAI,EAAG,OAAO,GAAG,MAAM,CAAC;IAOxB,WAAW,EAAG,MAAM,CAAC;CACtB;AAED,qBAAa,aAAc,SAAQ,SAAS;IAC1C,MAAM,CAAC,SAAS,SAAgC;IAChD,MAAM,CAAC,WAAW,SAAsB;IAQxC,EAAE,EAAG,MAAM,CAAC;IAOZ,IAAI,EAAG,MAAM,CAAC;IAOd,WAAW,EAAG,MAAM,GAAG,IAAI,CAAC;IAO5B,GAAG,EAAG,MAAM,CAAC;IAOb,SAAS,EAAG,IAAI,GAAG,MAAM,CAAC;IAQ1B,UAAU,EAAG,OAAO,CAAC;IAGrB,SAAS,EAAG,MAAM,CAAC;CACpB"}