@aceitadev/adatabase 0.2.5 → 0.3.5
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/README.md +171 -66
- package/dist/SchemaManager.js +12 -20
- package/dist/decorators/Column.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,66 +1,171 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
npm install
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
# aDatabase ORM
|
|
2
|
+
|
|
3
|
+
aDatabase is a lightweight and easy-to-use ORM (Object-Relational Mapping) for TypeScript, inspired by the Active Record pattern. It allows you to interact with your database using object-oriented syntax, abstracting away the need to write raw SQL queries for most common operations.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
* **Active Record Pattern**: Models represent database tables and instances represent rows.
|
|
8
|
+
* **Decorator-based Schema**: Define your database schema using simple decorators.
|
|
9
|
+
* **Multi-database Support**: Supports both MySQL and PostgreSQL.
|
|
10
|
+
* **Query Builder**: A fluent API for building complex queries.
|
|
11
|
+
* **Schema Migration**: Keep your database schema in sync with your models.
|
|
12
|
+
* **Relationships**: Supports `HasOne`, `HasMany`, and `BelongsTo` relationships.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @aceitadev/adatabase
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
First, you need to initialize the database connection. This should be done once when your application starts.
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { init } from '@aceitadev/adatabase';
|
|
26
|
+
|
|
27
|
+
init('mysql', {
|
|
28
|
+
host: 'localhost',
|
|
29
|
+
user: 'root',
|
|
30
|
+
password: 'password',
|
|
31
|
+
database: 'my_database'
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Supported database types are `'mysql'` and `'postgres'`.
|
|
36
|
+
|
|
37
|
+
## Defining Models
|
|
38
|
+
|
|
39
|
+
Models are defined as classes that extend `ActiveRecord`. You use decorators to map the class and its properties to a database table and its columns.
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { ActiveRecord, Table, Id, Column } from '@aceitadev/adatabase';
|
|
43
|
+
|
|
44
|
+
@Table('users')
|
|
45
|
+
export class User extends ActiveRecord {
|
|
46
|
+
@Id()
|
|
47
|
+
id: number;
|
|
48
|
+
|
|
49
|
+
@Column({ type: String })
|
|
50
|
+
name: string;
|
|
51
|
+
|
|
52
|
+
@Column({ type: String, unique: true })
|
|
53
|
+
email: string;
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## CRUD Operations
|
|
58
|
+
|
|
59
|
+
### Creating and Saving Records
|
|
60
|
+
|
|
61
|
+
To create a new record, instantiate a model and call the `save()` method.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const user = new User();
|
|
65
|
+
user.name = 'John Doe';
|
|
66
|
+
user.email = 'john.doe@example.com';
|
|
67
|
+
await user.save();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Finding Records
|
|
71
|
+
|
|
72
|
+
Use the static `find()` method to get a `QueryBuilder` instance.
|
|
73
|
+
|
|
74
|
+
**Find all users:**
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const users = await User.find().get();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Find a single user by ID:**
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const user = await User.find().where('id', '=', 1).first();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Find users with a specific condition:**
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const users = await User.find().where('name', 'LIKE', 'John%').get();
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Updating Records
|
|
93
|
+
|
|
94
|
+
To update a record, modify its properties and call `save()` again.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const user = await User.find().where('id', '=', 1).first();
|
|
98
|
+
if (user) {
|
|
99
|
+
user.name = 'Jane Doe';
|
|
100
|
+
await user.save();
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Deleting Records
|
|
105
|
+
|
|
106
|
+
To delete a record, call the `delete()` method on a model instance.
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const user = await User.find().where('id', '=', 1).first();
|
|
110
|
+
if (user) {
|
|
111
|
+
await user.delete();
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Relationships
|
|
116
|
+
|
|
117
|
+
You can define relationships between your models using the `@BelongsTo`, `@HasMany`, and `@HasOne` decorators.
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { ActiveRecord, Table, Id, Column, BelongsTo, HasMany } from '@aceitadev/adatabase';
|
|
121
|
+
|
|
122
|
+
@Table('posts')
|
|
123
|
+
export class Post extends ActiveRecord {
|
|
124
|
+
@Id()
|
|
125
|
+
id: number;
|
|
126
|
+
|
|
127
|
+
@Column({ type: String })
|
|
128
|
+
title: string;
|
|
129
|
+
|
|
130
|
+
@Column({ type: Number })
|
|
131
|
+
userId: number;
|
|
132
|
+
|
|
133
|
+
@BelongsTo(() => User, { foreignKey: 'userId' })
|
|
134
|
+
user: User;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@Table('users')
|
|
138
|
+
export class User extends ActiveRecord {
|
|
139
|
+
@Id()
|
|
140
|
+
id: number;
|
|
141
|
+
|
|
142
|
+
@Column({ type: String })
|
|
143
|
+
name: string;
|
|
144
|
+
|
|
145
|
+
@HasMany(() => Post, { foreignKey: 'userId' })
|
|
146
|
+
posts: Post[];
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
To eager-load relationships, use the `include()` method in the `QueryBuilder`.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const userWithPosts = await User.find().where('id', '=', 1).include(Post).first();
|
|
154
|
+
console.log(userWithPosts.posts);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Schema Migration
|
|
158
|
+
|
|
159
|
+
The `SchemaManager` helps you keep your database schema in sync with your models.
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { SchemaManager } from '@aceitadev/adatabase';
|
|
163
|
+
import { User, Post } from './models'; // Import your models
|
|
164
|
+
|
|
165
|
+
const schemaManager = new SchemaManager([User, Post]);
|
|
166
|
+
await schemaManager.migrate();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
When you run `migrate()`, the `SchemaManager` will:
|
|
170
|
+
* Create tables that don't exist.
|
|
171
|
+
* Add columns that are missing from existing tables.
|
package/dist/SchemaManager.js
CHANGED
|
@@ -46,15 +46,9 @@ class SchemaManager {
|
|
|
46
46
|
const colsSql = Object.entries(columns).map(([k, v]) => `\`${k}\` ${v}`).join(", ");
|
|
47
47
|
let indexSql = "";
|
|
48
48
|
if (adapter.type === 'mysql' && indexes.length > 0) {
|
|
49
|
-
indexSql = ", " + indexes.map(col => `INDEX
|
|
50
|
-
${col}
|
|
51
|
-
(
|
|
52
|
-
${col}
|
|
53
|
-
)`).join(", ");
|
|
49
|
+
indexSql = ", " + indexes.map(col => `INDEX \`${col}\` (\`${col}\`)`).join(", ");
|
|
54
50
|
}
|
|
55
|
-
const sql = `CREATE TABLE
|
|
56
|
-
${table}
|
|
57
|
-
(${colsSql}${indexSql});`;
|
|
51
|
+
const sql = `CREATE TABLE \`${table}\` (${colsSql}${indexSql});`;
|
|
58
52
|
const conn = yield (0, Database_1.getConnection)();
|
|
59
53
|
try {
|
|
60
54
|
yield (0, Database_1.execute)(sql, [], conn);
|
|
@@ -66,13 +60,7 @@ ${table}
|
|
|
66
60
|
if (adapter.type === 'postgres' && indexes.length > 0) {
|
|
67
61
|
for (const col of indexes) {
|
|
68
62
|
const indexName = `idx_${table}_${col}`;
|
|
69
|
-
const indexCreationSql = `CREATE INDEX
|
|
70
|
-
${indexName}
|
|
71
|
-
ON
|
|
72
|
-
${table}
|
|
73
|
-
(
|
|
74
|
-
${col}
|
|
75
|
-
);`;
|
|
63
|
+
const indexCreationSql = `CREATE INDEX \`${indexName}\` ON \`${table}\` (\`${col}\`);`;
|
|
76
64
|
const indexConn = yield (0, Database_1.getConnection)();
|
|
77
65
|
try {
|
|
78
66
|
yield (0, Database_1.execute)(indexCreationSql, [], indexConn);
|
|
@@ -88,11 +76,7 @@ ${col}
|
|
|
88
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
89
77
|
for (const [col, type] of Object.entries(desired)) {
|
|
90
78
|
if (!existing.hasOwnProperty(col)) {
|
|
91
|
-
const sql = `ALTER TABLE
|
|
92
|
-
${table}
|
|
93
|
-
ADD COLUMN
|
|
94
|
-
${col}
|
|
95
|
-
${type};`;
|
|
79
|
+
const sql = `ALTER TABLE \`${table}\` ADD COLUMN \`${col}\` ${type};`;
|
|
96
80
|
const conn = yield (0, Database_1.getConnection)();
|
|
97
81
|
try {
|
|
98
82
|
yield (0, Database_1.execute)(sql, [], conn);
|
|
@@ -136,6 +120,14 @@ ${col}
|
|
|
136
120
|
continue;
|
|
137
121
|
}
|
|
138
122
|
let sqlType = this.getSqlTypeForClass(type);
|
|
123
|
+
if (type === Number && opts.decimal) {
|
|
124
|
+
if (Array.isArray(opts.decimal) && opts.decimal.length === 2) {
|
|
125
|
+
sqlType = `DECIMAL(${opts.decimal[0]}, ${opts.decimal[1]})`;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
sqlType = 'DECIMAL(10, 2)';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
139
131
|
if (type === String && opts && opts.limit) {
|
|
140
132
|
sqlType = `VARCHAR(${opts.limit})`;
|
|
141
133
|
}
|
|
@@ -7,6 +7,7 @@ export type ColumnOptions = {
|
|
|
7
7
|
limit?: number;
|
|
8
8
|
type?: any;
|
|
9
9
|
index?: boolean;
|
|
10
|
+
decimal?: boolean | [number, number];
|
|
10
11
|
};
|
|
11
12
|
export declare function Column(options: ColumnOptions): (target: any, propertyKey: string) => void;
|
|
12
13
|
export declare function getColumnMeta(ctor: Function): Map<string, any> | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aceitadev/adatabase",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Uma biblioteca para facilitar a interação com bancos de dados MySQL e PostgreSQL em projetos TypeScript/Node.js.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|