@hedystia/db 2.0.0 → 2.0.2
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/dist/_virtual/_rolldown/runtime.cjs +13 -0
- package/dist/_virtual/_rolldown/runtime.mjs +17 -0
- package/dist/cache/manager.cjs +137 -0
- package/dist/cache/manager.cjs.map +1 -0
- package/dist/cache/manager.d.cts +72 -0
- package/dist/cache/manager.d.mts +72 -0
- package/dist/cache/manager.mjs +140 -0
- package/dist/cache/manager.mjs.map +1 -0
- package/dist/cache/memory-store.cjs +122 -0
- package/dist/cache/memory-store.cjs.map +1 -0
- package/dist/cache/memory-store.mjs +122 -0
- package/dist/cache/memory-store.mjs.map +1 -0
- package/dist/cli/commands/migration.cjs +22 -0
- package/dist/cli/commands/migration.cjs.map +1 -0
- package/dist/cli/commands/migration.mjs +32 -0
- package/dist/cli/commands/migration.mjs.map +1 -0
- package/dist/cli/commands/schema.cjs +21 -0
- package/dist/cli/commands/schema.cjs.map +1 -0
- package/dist/cli/commands/schema.mjs +30 -0
- package/dist/cli/commands/schema.mjs.map +1 -0
- package/dist/cli.cjs +50 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +57 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/constants.cjs +16 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.mjs +16 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/core/database.cjs +158 -0
- package/dist/core/database.cjs.map +1 -0
- package/dist/core/database.d.cts +74 -0
- package/dist/core/database.d.mts +74 -0
- package/dist/core/database.mjs +159 -0
- package/dist/core/database.mjs.map +1 -0
- package/dist/core/repository.cjs +416 -0
- package/dist/core/repository.cjs.map +1 -0
- package/dist/core/repository.d.cts +110 -0
- package/dist/core/repository.d.mts +110 -0
- package/dist/core/repository.mjs +416 -0
- package/dist/core/repository.mjs.map +1 -0
- package/dist/drivers/driver.cjs +11 -0
- package/dist/drivers/driver.cjs.map +1 -0
- package/dist/drivers/driver.mjs +11 -0
- package/dist/drivers/driver.mjs.map +1 -0
- package/dist/drivers/file.cjs +336 -0
- package/dist/drivers/file.cjs.map +1 -0
- package/dist/drivers/file.mjs +337 -0
- package/dist/drivers/file.mjs.map +1 -0
- package/dist/drivers/index.cjs +28 -0
- package/dist/drivers/index.cjs.map +1 -0
- package/dist/drivers/index.d.cts +14 -0
- package/dist/drivers/index.d.mts +14 -0
- package/dist/drivers/index.mjs +28 -0
- package/dist/drivers/index.mjs.map +1 -0
- package/dist/drivers/mysql.cjs +272 -0
- package/dist/drivers/mysql.cjs.map +1 -0
- package/dist/drivers/mysql.mjs +272 -0
- package/dist/drivers/mysql.mjs.map +1 -0
- package/dist/drivers/sql-compiler.cjs +284 -0
- package/dist/drivers/sql-compiler.cjs.map +1 -0
- package/dist/drivers/sql-compiler.d.cts +66 -0
- package/dist/drivers/sql-compiler.d.mts +66 -0
- package/dist/drivers/sql-compiler.mjs +276 -0
- package/dist/drivers/sql-compiler.mjs.map +1 -0
- package/dist/drivers/sqlite.cjs +262 -0
- package/dist/drivers/sqlite.cjs.map +1 -0
- package/dist/drivers/sqlite.mjs +262 -0
- package/dist/drivers/sqlite.mjs.map +1 -0
- package/dist/errors.cjs +74 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +46 -0
- package/dist/errors.d.mts +46 -0
- package/dist/errors.mjs +68 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/index.cjs +69 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.mts +15 -0
- package/dist/index.mjs +21 -0
- package/dist/index.mjs.map +1 -0
- package/dist/migrations/definition.cjs +20 -0
- package/dist/migrations/definition.cjs.map +1 -0
- package/dist/migrations/definition.d.cts +18 -0
- package/dist/migrations/definition.d.mts +18 -0
- package/dist/migrations/definition.mjs +23 -0
- package/dist/migrations/definition.mjs.map +1 -0
- package/dist/migrations/index.mjs +12 -0
- package/dist/migrations/index.mjs.map +1 -0
- package/dist/migrations/templates.cjs +39 -0
- package/dist/migrations/templates.cjs.map +1 -0
- package/dist/migrations/templates.d.cts +16 -0
- package/dist/migrations/templates.d.mts +16 -0
- package/dist/migrations/templates.mjs +41 -0
- package/dist/migrations/templates.mjs.map +1 -0
- package/dist/schema/column.cjs +161 -0
- package/dist/schema/column.cjs.map +1 -0
- package/dist/schema/column.d.cts +120 -0
- package/dist/schema/column.d.mts +120 -0
- package/dist/schema/column.mjs +161 -0
- package/dist/schema/column.mjs.map +1 -0
- package/dist/schema/columns/index.cjs +202 -0
- package/dist/schema/columns/index.cjs.map +1 -0
- package/dist/schema/columns/index.d.cts +141 -0
- package/dist/schema/columns/index.d.mts +141 -0
- package/dist/schema/columns/index.mjs +182 -0
- package/dist/schema/columns/index.mjs.map +1 -0
- package/dist/schema/registry.cjs +125 -0
- package/dist/schema/registry.cjs.map +1 -0
- package/dist/schema/registry.d.cts +66 -0
- package/dist/schema/registry.d.mts +66 -0
- package/dist/schema/registry.mjs +125 -0
- package/dist/schema/registry.mjs.map +1 -0
- package/dist/schema/table.cjs +39 -0
- package/dist/schema/table.cjs.map +1 -0
- package/dist/schema/table.d.cts +17 -0
- package/dist/schema/table.d.mts +17 -0
- package/dist/schema/table.mjs +39 -0
- package/dist/schema/table.mjs.map +1 -0
- package/dist/sync/synchronizer.cjs +43 -0
- package/dist/sync/synchronizer.cjs.map +1 -0
- package/dist/sync/synchronizer.d.cts +22 -0
- package/dist/sync/synchronizer.d.mts +22 -0
- package/dist/sync/synchronizer.mjs +43 -0
- package/dist/sync/synchronizer.mjs.map +1 -0
- package/dist/types.d.cts +229 -0
- package/dist/types.d.mts +229 -0
- package/dist/utils/fs.cjs +24 -0
- package/dist/utils/fs.cjs.map +1 -0
- package/dist/utils/fs.mjs +26 -0
- package/dist/utils/fs.mjs.map +1 -0
- package/dist/utils/index.mjs +14 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/naming.cjs +13 -0
- package/dist/utils/naming.cjs.map +1 -0
- package/dist/utils/naming.mjs +16 -0
- package/dist/utils/naming.mjs.map +1 -0
- package/dist/utils/stable-stringify.cjs +19 -0
- package/dist/utils/stable-stringify.cjs.map +1 -0
- package/dist/utils/stable-stringify.mjs +22 -0
- package/dist/utils/stable-stringify.mjs.map +1 -0
- package/package.json +64 -27
- package/readme.md +87 -105
- package/index.d.ts +0 -65
- package/index.js +0 -1
package/readme.md
CHANGED
|
@@ -1,137 +1,119 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
npm i @hedystia/db
|
|
5
|
-
|
|
6
|
-
yarn add @hedystia/db
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
## Nodejs Version
|
|
10
|
-
|
|
11
|
-
- `v18.0.0` or higher
|
|
12
|
-
|
|
13
|
-
## Links
|
|
14
|
-
|
|
15
|
-
- [Discord](https://discord.gg/aXvuUpvRQs) [Hedystia Discord]
|
|
16
|
-
- [Discord_Bot](https://hedystia.com) [Hedystia Bot]
|
|
17
|
-
- [Docs](https://docs.hedystia.com/db/start) [Hedystia Docs]
|
|
18
|
-
|
|
19
|
-
## Example
|
|
20
|
-
|
|
21
|
-
```js
|
|
22
|
-
const { default: Database } = require("@hedystia/db");
|
|
23
|
-
|
|
24
|
-
// Create a file named database.ht and enter the password
|
|
25
|
-
const database = new Database("./database.ht", "password");
|
|
26
|
-
|
|
27
|
-
// You can only use it once to create the table after that you can no longer use it.
|
|
28
|
-
database.createTable("users", ["id", "name", "email"]);
|
|
29
|
-
|
|
30
|
-
database.insert("users", { id: "1", name: "John Doe", email: "jdoe@example.com" });
|
|
1
|
+
# @hedystia/db
|
|
31
2
|
|
|
32
|
-
|
|
3
|
+
Next-gen TypeScript ORM for building type-safe database layers at lightspeed.
|
|
33
4
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.log("----------------------------------");
|
|
37
|
-
|
|
38
|
-
console.log(users);
|
|
39
|
-
|
|
40
|
-
database.addColumn("users", "phone");
|
|
41
|
-
|
|
42
|
-
database.addColumn("users", "lang", "en-US");
|
|
43
|
-
|
|
44
|
-
const newUsersPhone = database.select("users");
|
|
5
|
+
## Installation
|
|
45
6
|
|
|
46
|
-
|
|
7
|
+
```bash
|
|
8
|
+
bun add @hedystia/db
|
|
9
|
+
```
|
|
47
10
|
|
|
48
|
-
|
|
11
|
+
### Database Drivers
|
|
49
12
|
|
|
50
|
-
database.
|
|
13
|
+
Install the driver for your database. The ORM will automatically detect and use the most appropriate library available.
|
|
51
14
|
|
|
52
|
-
|
|
15
|
+
#### SQLite Driver
|
|
16
|
+
Supports multiple libraries in the following priority:
|
|
17
|
+
1. `better-sqlite3`
|
|
18
|
+
2. `sqlite3`
|
|
19
|
+
3. `sql.js`
|
|
20
|
+
4. `bun:sqlite`
|
|
53
21
|
|
|
54
|
-
|
|
22
|
+
```bash
|
|
23
|
+
# You can install any of these
|
|
55
24
|
|
|
56
|
-
|
|
25
|
+
bun add better-sqlite3
|
|
26
|
+
bun add sqlite3
|
|
27
|
+
bun add sql.js
|
|
57
28
|
|
|
58
|
-
|
|
29
|
+
# Or use bun:sqlite if you are using Bun
|
|
30
|
+
```
|
|
59
31
|
|
|
60
|
-
|
|
32
|
+
#### MySQL & MariaDB Driver
|
|
33
|
+
Supports both `mysql2` and `mysql` libraries.
|
|
34
|
+
- **Naming**: Use `database: "mysql"` or `database: "mariadb"`.
|
|
35
|
+
- **MariaDB**: Fully supported through the same drivers.
|
|
61
36
|
|
|
62
|
-
|
|
37
|
+
```bash
|
|
38
|
+
bun add mysql2 # Preferred
|
|
39
|
+
# or
|
|
40
|
+
bun add mysql
|
|
41
|
+
```
|
|
63
42
|
|
|
64
|
-
|
|
43
|
+
# File-based (no extra install needed)
|
|
65
44
|
|
|
66
|
-
|
|
45
|
+
## Quick Start
|
|
67
46
|
|
|
68
|
-
|
|
47
|
+
### Define your schema
|
|
69
48
|
|
|
70
|
-
|
|
49
|
+
```ts
|
|
50
|
+
import { table, integer, varchar, text } from "@hedystia/db";
|
|
71
51
|
|
|
72
|
-
|
|
52
|
+
export const users = table("users", {
|
|
53
|
+
id: integer().primaryKey().autoIncrement(),
|
|
54
|
+
name: varchar(255).notNull(),
|
|
55
|
+
email: varchar(255).unique(),
|
|
56
|
+
age: integer().default(0),
|
|
57
|
+
});
|
|
73
58
|
|
|
74
|
-
const
|
|
59
|
+
export const posts = table("posts", {
|
|
60
|
+
id: integer().primaryKey().autoIncrement(),
|
|
61
|
+
userId: integer().references(() => users.id, { onDelete: "CASCADE" }),
|
|
62
|
+
title: varchar(255).notNull(),
|
|
63
|
+
content: text(),
|
|
64
|
+
});
|
|
65
|
+
```
|
|
75
66
|
|
|
76
|
-
|
|
67
|
+
> **Note:** The `d.xxx()` prefix style (e.g., `d.integer()`) is still supported for backward compatibility.
|
|
77
68
|
|
|
78
|
-
|
|
69
|
+
### Create the database
|
|
79
70
|
|
|
80
|
-
|
|
71
|
+
```ts
|
|
72
|
+
import { database } from "@hedystia/db";
|
|
73
|
+
import { users, posts } from "./schemas";
|
|
81
74
|
|
|
82
|
-
const
|
|
75
|
+
const db = database({
|
|
76
|
+
schemas: [users, posts],
|
|
77
|
+
database: "sqlite",
|
|
78
|
+
connection: { filename: "./data.db" },
|
|
79
|
+
syncSchemas: true,
|
|
80
|
+
cache: true,
|
|
81
|
+
});
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
await db.initialize();
|
|
84
|
+
```
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
### Query your data
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
```ts
|
|
89
|
+
// Insert
|
|
90
|
+
const user = await db.users.insert({ name: "Alice", email: "alice@example.com" });
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
description: "Description",
|
|
94
|
-
timestamp: Date.now(),
|
|
95
|
-
},
|
|
96
|
-
() => {
|
|
97
|
-
database.createTableIfNotExists("test_migration", ["name"]);
|
|
98
|
-
database.insert("test_migration", { name: "John" });
|
|
99
|
-
},
|
|
100
|
-
);
|
|
92
|
+
// Find
|
|
93
|
+
const allUsers = await db.users.find();
|
|
94
|
+
const alice = await db.users.findFirst({ where: { name: "Alice" } });
|
|
101
95
|
|
|
102
|
-
|
|
96
|
+
// Update
|
|
97
|
+
await db.users.update({ where: { id: 1 }, data: { age: 26 } });
|
|
103
98
|
|
|
104
|
-
|
|
99
|
+
// Delete
|
|
100
|
+
await db.users.delete({ where: { id: 1 } });
|
|
105
101
|
|
|
106
|
-
|
|
102
|
+
// Relations
|
|
103
|
+
const usersWithPosts = await db.users.find({ with: { posts: true } });
|
|
104
|
+
```
|
|
107
105
|
|
|
108
|
-
|
|
106
|
+
## Features
|
|
109
107
|
|
|
110
|
-
|
|
108
|
+
- **One schema, multiple databases** — MySQL, SQLite, and File drivers
|
|
109
|
+
- **Type-safe queries** — Full TypeScript inference for all operations
|
|
110
|
+
- **Smart caching** — Adaptive TTL cache with automatic invalidation
|
|
111
|
+
- **Migrations** — CLI and programmatic migration support
|
|
112
|
+
- **Schema sync** — Automatic table creation and column diffing
|
|
113
|
+
- **Relations** — Foreign key references with eager loading
|
|
111
114
|
|
|
112
|
-
|
|
113
|
-
```
|
|
115
|
+
## Links
|
|
114
116
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
| ------------------------ | ---------------------------------------------- |
|
|
119
|
-
| `dropAll` | To drop all data from a table |
|
|
120
|
-
| `readTables` | To read the tables from the database |
|
|
121
|
-
| `enableMigrations` | To enable migrations |
|
|
122
|
-
| `createMigration` | To create a migration |
|
|
123
|
-
| `createTable` | To create a table |
|
|
124
|
-
| `deleteTable` | To delete a table |
|
|
125
|
-
| `createTableIfNotExists` | To create a table if it does not exist |
|
|
126
|
-
| `deleteTableIfExists` | To delete a table if it exists |
|
|
127
|
-
| `renameTable` | To rename a table |
|
|
128
|
-
| `addColumn` | To add a column to an already created table |
|
|
129
|
-
| `deleteColumn` | To remove a column to an already created table |
|
|
130
|
-
| `renameColumn` | To rename a column |
|
|
131
|
-
| `insert` | To insert a data in the table |
|
|
132
|
-
| `update` | To update a data in the table |
|
|
133
|
-
| `select` | To search for information in a table |
|
|
134
|
-
| `delete` | To delete a data from the table |
|
|
135
|
-
| `getTableNames` | To get the names of all tables |
|
|
136
|
-
| `getColumnNames` | To get the names of all columns |
|
|
137
|
-
| `getRecordCount` | To get the number of records in a table |
|
|
117
|
+
- [Documentation](https://docs.hedystia.com/db/start)
|
|
118
|
+
- [GitHub](https://github.com/Hedystia/Hedystia)
|
|
119
|
+
- [Discord](https://hedystia.com/discord)
|
package/index.d.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
interface Records {
|
|
2
|
-
[key: string]: unknown;
|
|
3
|
-
}
|
|
4
|
-
interface Table {
|
|
5
|
-
columns: string[];
|
|
6
|
-
records: Records[];
|
|
7
|
-
}
|
|
8
|
-
interface Migration {
|
|
9
|
-
id: string;
|
|
10
|
-
description: string;
|
|
11
|
-
timestamp: number;
|
|
12
|
-
applied: boolean;
|
|
13
|
-
}
|
|
14
|
-
export default class DataBase {
|
|
15
|
-
private queue;
|
|
16
|
-
private password;
|
|
17
|
-
private filePath;
|
|
18
|
-
private tables;
|
|
19
|
-
private migrations;
|
|
20
|
-
private migrationsEnabled;
|
|
21
|
-
constructor(filePath: string, password: string);
|
|
22
|
-
enableMigrations(): void;
|
|
23
|
-
createMigration(migration: Omit<Migration, "applied">, migrationFn: () => Promise<void> | void): Promise<void>;
|
|
24
|
-
createTable(tableName: string, columns?: string[]): void;
|
|
25
|
-
createTableIfNotExists(tableName: string, columns: string[]): void;
|
|
26
|
-
deleteTable(tableName: string): void;
|
|
27
|
-
deleteTableIfExists(tableName: string): void;
|
|
28
|
-
addColumn(tableName: string, column: string, defaultValue?: unknown): void;
|
|
29
|
-
deleteColumn(tableName: string, column: string): void;
|
|
30
|
-
insert(tableName: string, record: {
|
|
31
|
-
[key: string]: unknown;
|
|
32
|
-
}): void;
|
|
33
|
-
update(tableName: string, query: {
|
|
34
|
-
[key: string]: unknown;
|
|
35
|
-
}, newData: {
|
|
36
|
-
[key: string]: unknown;
|
|
37
|
-
}): void;
|
|
38
|
-
select(tableName: string, query?: {
|
|
39
|
-
[key: string]: unknown;
|
|
40
|
-
}): Records[];
|
|
41
|
-
delete(tableName: string, query?: {
|
|
42
|
-
[key: string]: unknown;
|
|
43
|
-
}): void;
|
|
44
|
-
readTables(): {
|
|
45
|
-
[key: string]: Table;
|
|
46
|
-
};
|
|
47
|
-
dropAll(): void;
|
|
48
|
-
renameTable(oldTableName: string, newTableName: string): void;
|
|
49
|
-
renameColumn(tableName: string, oldColumnName: string, newColumnName: string): void;
|
|
50
|
-
getTableNames(): string[];
|
|
51
|
-
getColumnNames(tableName: string): string[];
|
|
52
|
-
getRecordCount(tableName: string): number;
|
|
53
|
-
private processQueue;
|
|
54
|
-
private markMigrationAsApplied;
|
|
55
|
-
private insertTable;
|
|
56
|
-
private updateTable;
|
|
57
|
-
private deleteFromTable;
|
|
58
|
-
private dropAllData;
|
|
59
|
-
private renameTableInDb;
|
|
60
|
-
private renameColumnInDb;
|
|
61
|
-
private saveToFile;
|
|
62
|
-
private readFromFile;
|
|
63
|
-
private evpBytesToKey;
|
|
64
|
-
}
|
|
65
|
-
export {};
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var m=Object.create;var{getPrototypeOf:y,defineProperty:l,getOwnPropertyNames:b,getOwnPropertyDescriptor:F}=Object,p=Object.prototype.hasOwnProperty;var g=(e,t,s)=>{s=e!=null?m(y(e)):{};let i=t||!e||!e.__esModule?l(s,"default",{value:e,enumerable:!0}):s;for(let r of b(e))if(!p.call(i,r))l(i,r,{get:()=>e[r],enumerable:!0});return i},f=new WeakMap,T=(e)=>{var t=f.get(e),s;if(t)return t;if(t=l({},"__esModule",{value:!0}),e&&typeof e==="object"||typeof e==="function")b(e).map((i)=>!p.call(t,i)&&l(t,i,{get:()=>e[i],enumerable:!(s=F(e,i))||s.enumerable}));return f.set(e,t),t};var k=(e,t)=>{for(var s in t)l(e,s,{get:t[s],enumerable:!0,configurable:!0,set:(i)=>t[s]=()=>i})};var q={};k(q,{default:()=>c});module.exports=T(q);var h=g(require("node:fs")),u=g(require("node:crypto"));class c{queue=[];password;filePath;tables={};migrations=[];migrationsEnabled=!1;constructor(e,t){this.tables={},this.filePath=e||"./database.ht",this.password=t,this.queue=[]}enableMigrations(){this.migrationsEnabled=!0,this.createTableIfNotExists("migrations",["id","description","timestamp","applied"])}async createMigration(e,t){if(!this.migrationsEnabled)throw new Error("Migrations are not enabled. Call enableMigrations() first.");this.readFromFile();let s=this.select("migrations",{id:e.id});if(!s[0]||!s[0].applied){if(this.migrations.push({...e,applied:!1}),this.insert("migrations",{...e,applied:!1}),this.queue.push({method:"migration",table:"migrations",record:{...e,applied:!1}}),this.queue.length===1)await this.processQueue(t)}}createTable(e,t=[]){if(this.readFromFile(),this.tables[e])throw new Error(`Table "${e}" already exists.`);this.tables[e]={columns:t,records:[]},this.saveToFile()}createTableIfNotExists(e,t){if(this.readFromFile(),!this.tables[e])this.tables[e]={columns:t,records:[]},this.saveToFile()}deleteTable(e){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);delete this.tables[e],this.saveToFile()}deleteTableIfExists(e){if(this.readFromFile(),this.tables[e])delete this.tables[e],this.saveToFile()}addColumn(e,t,s){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);if(this.tables[e].columns.includes(t))throw new Error(`Column "${t}" already exists in table "${e}".`);this.tables[e].columns.push(t);for(let i of this.tables[e].records)i[t]=s??null;this.saveToFile()}deleteColumn(e,t){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);if(!this.tables[e].columns.includes(t))throw new Error(`Column "${t}" does not exist in table "${e}".`);let s=this.tables[e].columns.indexOf(t);this.tables[e].columns.splice(s,1);for(let i of this.tables[e].records)delete i[t];this.saveToFile()}insert(e,t){if(this.queue.push({method:"insert",table:e,record:t}),this.queue.length===1)this.processQueue()}update(e,t,s){if(this.queue.push({method:"update",table:e,query:t,newData:s}),this.queue.length===1)this.processQueue()}select(e,t={}){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);return this.tables[e].records.filter((s)=>Object.entries(t).every(([i,r])=>s[i]===r))}delete(e,t={}){if(this.queue.push({method:"delete",table:e,query:t}),this.queue.length===1)this.processQueue()}readTables(){return this.readFromFile(),this.tables}dropAll(){if(this.queue.push({method:"dropAllData"}),this.queue.length===1)this.processQueue()}renameTable(e,t){if(this.queue.push({method:"renameTable",table:e,newTableName:t}),this.queue.length===1)this.processQueue()}renameColumn(e,t,s){if(this.queue.push({method:"renameColumn",table:e,column:t,newColumnName:s}),this.queue.length===1)this.processQueue()}getTableNames(){return this.readFromFile(),Object.keys(this.tables)}getColumnNames(e){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);return this.tables[e].columns}getRecordCount(e){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);return this.tables[e].records.length}async processQueue(e){let t=this.queue[0];switch(t.method){case"insert":if(!t.table)throw new Error("Table name is required.");this.insertTable(t.table,t.record);break;case"update":if(!t.table)throw new Error("Table name is required.");this.updateTable(t.table,t.query,t.newData);break;case"delete":if(!t.table)throw new Error("Table name is required.");this.deleteFromTable(t.table,t.query);break;case"dropAllData":this.dropAllData();break;case"migration":if(e)await e(),this.markMigrationAsApplied(t.record?.id);break;case"renameTable":if(!t.table||!t.newTableName)throw new Error("Old and new table names are required.");this.renameTableInDb(t.table,t.newTableName);break;case"renameColumn":if(!t.table||!t.column||!t.newColumnName)throw new Error("Table, old column, and new column names are required.");this.renameColumnInDb(t.table,t.column,t.newColumnName);break}}markMigrationAsApplied(e){this.readFromFile();let t=this.select("migrations",{id:e});if(t.length>0)this.updateTable("migrations",{id:e},{...t[0],applied:!0});if(this.queue.shift(),this.queue.length>0)this.processQueue()}insertTable(e,t){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);let s=this.tables[e],i={};for(let r of s.columns)i[r]=t[r]||null;if(s.records.push(i),this.saveToFile(),this.queue.shift(),this.queue.length>0)this.processQueue()}updateTable(e,t,s){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);let i=this.tables[e],r=i.records.map((n)=>{let a=Object.entries(s);for(let[o,d]of a)if(i.columns.includes(o)&&Object.entries(t).every(([w,v])=>n[w]===v))n[o]=d;return n});if(i.records=r,this.saveToFile(),this.queue.shift(),this.queue.length>0)this.processQueue()}deleteFromTable(e,t){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);if(this.tables[e].records=this.tables[e].records.filter((s)=>!Object.entries(t).every(([i,r])=>s[i]===r)),this.saveToFile(),this.queue.shift(),this.queue.length>0)this.processQueue()}dropAllData(){this.readFromFile();for(let e in this.tables)this.tables[e].records=[];if(this.saveToFile(),this.queue.shift(),this.queue.length>0)this.processQueue()}renameTableInDb(e,t){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);if(this.tables[t])throw new Error(`Table "${t}" already exists.`);if(this.tables[t]=this.tables[e],delete this.tables[e],this.saveToFile(),this.queue.shift(),this.queue.length>0)this.processQueue()}renameColumnInDb(e,t,s){if(this.readFromFile(),!this.tables[e])throw new Error(`Table "${e}" does not exist.`);if(!this.tables[e].columns.includes(t))throw new Error(`Column "${t}" does not exist in table "${e}".`);if(this.tables[e].columns.includes(s))throw new Error(`Column "${s}" already exists in table "${e}".`);let i=this.tables[e].columns.indexOf(t);this.tables[e].columns[i]=s;for(let r of this.tables[e].records)r[s]=r[t],delete r[t];if(this.saveToFile(),this.queue.shift(),this.queue.length>0)this.processQueue()}saveToFile(){if(!this.filePath.endsWith(".ht"))throw new Error(`File path must include '.ht': ${this.filePath}`);let e=JSON.stringify(this.tables),t=u.default.randomBytes(8),s=Buffer.from(this.password,"utf-8"),{key:i,iv:r}=this.evpBytesToKey(s,t,32,16),n=u.default.createCipheriv("aes-256-cbc",i,r),a=Buffer.concat([n.update(Buffer.from(e,"utf8")),n.final()]),o=Buffer.concat([Buffer.from("Salted__"),t,a]);h.default.writeFileSync(this.filePath,o.toString("base64"))}readFromFile(){if(!h.default.existsSync(this.filePath))return;try{let e=h.default.readFileSync(this.filePath,"utf8"),t=Buffer.from(e,"base64");if(t.length<16||t.subarray(0,8).toString()!=="Salted__")throw new Error("Invalid encrypted data format");let s=t.subarray(8,16),i=t.subarray(16),r=Buffer.from(this.password,"utf-8"),{key:n,iv:a}=this.evpBytesToKey(r,s,32,16),o=u.default.createDecipheriv("aes-256-cbc",n,a),d=Buffer.concat([o.update(i),o.final()]).toString("utf8");this.tables=JSON.parse(d)}catch(e){this.tables={}}}evpBytesToKey(e,t,s,i){let r=Buffer.alloc(0),n=Buffer.alloc(0),a=s+i;while(r.length<a){let o=u.default.createHash("md5");if(n.length>0)o.update(n);o.update(e),o.update(t),n=o.digest(),r=Buffer.concat([r,n])}return{key:r.subarray(0,s),iv:r.subarray(s,s+i)}}}
|