exisjs 0.5.9 → 0.5.11
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/auth/index.d.ts +3 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +4 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/oauth/core.d.ts +96 -0
- package/dist/auth/oauth/core.d.ts.map +1 -0
- package/dist/auth/oauth/core.js +203 -0
- package/dist/auth/oauth/core.js.map +1 -0
- package/dist/auth/oauth/index.d.ts +45 -0
- package/dist/auth/oauth/index.d.ts.map +1 -0
- package/dist/auth/oauth/index.js +64 -0
- package/dist/auth/oauth/index.js.map +1 -0
- package/dist/auth/oauth/middleware.d.ts +63 -0
- package/dist/auth/oauth/middleware.d.ts.map +1 -0
- package/dist/auth/oauth/middleware.js +164 -0
- package/dist/auth/oauth/middleware.js.map +1 -0
- package/dist/auth/oauth/providers/custom.d.ts +41 -0
- package/dist/auth/oauth/providers/custom.d.ts.map +1 -0
- package/dist/auth/oauth/providers/custom.js +204 -0
- package/dist/auth/oauth/providers/custom.js.map +1 -0
- package/dist/auth/oauth/providers/discord.d.ts +23 -0
- package/dist/auth/oauth/providers/discord.d.ts.map +1 -0
- package/dist/auth/oauth/providers/discord.js +130 -0
- package/dist/auth/oauth/providers/discord.js.map +1 -0
- package/dist/auth/oauth/providers/facebook.d.ts +28 -0
- package/dist/auth/oauth/providers/facebook.d.ts.map +1 -0
- package/dist/auth/oauth/providers/facebook.js +124 -0
- package/dist/auth/oauth/providers/facebook.js.map +1 -0
- package/dist/auth/oauth/providers/github.d.ts +25 -0
- package/dist/auth/oauth/providers/github.d.ts.map +1 -0
- package/dist/auth/oauth/providers/github.js +132 -0
- package/dist/auth/oauth/providers/github.js.map +1 -0
- package/dist/auth/oauth/providers/google.d.ts +23 -0
- package/dist/auth/oauth/providers/google.d.ts.map +1 -0
- package/dist/auth/oauth/providers/google.js +134 -0
- package/dist/auth/oauth/providers/google.js.map +1 -0
- package/dist/auth/oauth/providers/microsoft.d.ts +28 -0
- package/dist/auth/oauth/providers/microsoft.d.ts.map +1 -0
- package/dist/auth/oauth/providers/microsoft.js +136 -0
- package/dist/auth/oauth/providers/microsoft.js.map +1 -0
- package/dist/auth/oauth/types.d.ts +158 -0
- package/dist/auth/oauth/types.d.ts.map +1 -0
- package/dist/auth/oauth/types.js +4 -0
- package/dist/auth/oauth/types.js.map +1 -0
- package/dist/auth/session.d.ts +4 -1
- package/dist/auth/session.d.ts.map +1 -1
- package/dist/auth/session.js +33 -5
- package/dist/auth/session.js.map +1 -1
- package/dist/cache/store.d.ts +11 -3
- package/dist/cache/store.d.ts.map +1 -1
- package/dist/cache/store.js +87 -19
- package/dist/cache/store.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +4 -6
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/database/adapters/mongodb.d.ts +58 -0
- package/dist/database/adapters/mongodb.d.ts.map +1 -0
- package/dist/database/adapters/mongodb.js +264 -0
- package/dist/database/adapters/mongodb.js.map +1 -0
- package/dist/database/adapters/mysql.d.ts +27 -0
- package/dist/database/adapters/mysql.d.ts.map +1 -0
- package/dist/database/adapters/mysql.js +188 -0
- package/dist/database/adapters/mysql.js.map +1 -0
- package/dist/database/adapters/postgres.d.ts +28 -0
- package/dist/database/adapters/postgres.d.ts.map +1 -0
- package/dist/database/adapters/postgres.js +174 -0
- package/dist/database/adapters/postgres.js.map +1 -0
- package/dist/database/adapters/sqlite.d.ts +27 -0
- package/dist/database/adapters/sqlite.d.ts.map +1 -0
- package/dist/database/adapters/sqlite.js +149 -0
- package/dist/database/adapters/sqlite.js.map +1 -0
- package/dist/database/index.d.ts +42 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +58 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/manager.d.ts +114 -0
- package/dist/database/manager.d.ts.map +1 -0
- package/dist/database/manager.js +269 -0
- package/dist/database/manager.js.map +1 -0
- package/dist/database/migration.d.ts +57 -0
- package/dist/database/migration.d.ts.map +1 -0
- package/dist/database/migration.js +329 -0
- package/dist/database/migration.js.map +1 -0
- package/dist/database/query-builder.d.ts +89 -0
- package/dist/database/query-builder.d.ts.map +1 -0
- package/dist/database/query-builder.js +353 -0
- package/dist/database/query-builder.js.map +1 -0
- package/dist/database/types.d.ts +184 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +4 -0
- package/dist/database/types.js.map +1 -0
- package/dist/docs/ARCHITECTURE.md +349 -0
- package/dist/docs/BENCHMARKS.md +36 -0
- package/dist/docs/README.md +34 -0
- package/dist/docs/content/README.md +44 -0
- package/dist/docs/content/adapters.mdx +199 -0
- package/dist/docs/content/cache.mdx +239 -0
- package/dist/docs/content/circuit-breaker.mdx +130 -0
- package/dist/docs/content/cli/commands.mdx +214 -0
- package/dist/docs/content/cli/overview.mdx +92 -0
- package/dist/docs/content/cli/usage.mdx +61 -0
- package/dist/docs/content/config.mdx +214 -0
- package/dist/docs/content/controllers.mdx +241 -0
- package/dist/docs/content/cron.mdx +109 -0
- package/dist/docs/content/database.mdx +209 -0
- package/dist/docs/content/dataloader.mdx +170 -0
- package/dist/docs/content/decorators.mdx +204 -0
- package/dist/docs/content/errors.mdx +344 -0
- package/dist/docs/content/gateways.mdx +376 -0
- package/dist/docs/content/installation.mdx +210 -0
- package/dist/docs/content/introduction.mdx +96 -0
- package/dist/docs/content/middleware.mdx +441 -0
- package/dist/docs/content/modules.mdx +144 -0
- package/dist/docs/content/oauth.mdx +179 -0
- package/dist/docs/content/providers.mdx +147 -0
- package/dist/docs/content/queues.mdx +177 -0
- package/dist/docs/content/requests.mdx +293 -0
- package/dist/docs/content/responses.mdx +271 -0
- package/dist/docs/content/routing.mdx +541 -0
- package/dist/docs/content/rpc.mdx +146 -0
- package/dist/docs/content/security.mdx +294 -0
- package/dist/docs/content/sse.mdx +159 -0
- package/dist/docs/content/structure.mdx +116 -0
- package/dist/docs/content/testing.mdx +139 -0
- package/dist/docs/content/validation.mdx +249 -0
- package/dist/docs/content/websockets.mdx +289 -0
- package/dist/docs/integrations/README.md +23 -0
- package/dist/docs/integrations/jwt.mdx +151 -0
- package/dist/docs/integrations/mongo.mdx +183 -0
- package/dist/docs/integrations/observability.mdx +125 -0
- package/dist/docs/integrations/openai.mdx +108 -0
- package/dist/docs/integrations/postgres.mdx +190 -0
- package/dist/docs/integrations/posthog.mdx +122 -0
- package/dist/docs/integrations/redis.mdx +141 -0
- package/dist/docs/integrations/resend.mdx +117 -0
- package/dist/docs/integrations/s3.mdx +122 -0
- package/dist/docs/integrations/swagger.mdx +113 -0
- package/dist/docs/reference/README.md +3 -0
- package/dist/docs/reference/adapters.mdx +130 -0
- package/dist/docs/reference/auth.mdx +183 -0
- package/dist/docs/reference/cache.mdx +132 -0
- package/dist/docs/reference/circuit-breaker.mdx +71 -0
- package/dist/docs/reference/config.mdx +118 -0
- package/dist/docs/reference/context.mdx +168 -0
- package/dist/docs/reference/dataloader.mdx +91 -0
- package/dist/docs/reference/decorators.mdx +293 -0
- package/dist/docs/reference/di.mdx +123 -0
- package/dist/docs/reference/error.mdx +170 -0
- package/dist/docs/reference/exis.mdx +124 -0
- package/dist/docs/reference/middleware.mdx +304 -0
- package/dist/docs/reference/plugin.mdx +113 -0
- package/dist/docs/reference/queue.mdx +155 -0
- package/dist/docs/reference/router.mdx +248 -0
- package/dist/docs/reference/sanitize.mdx +130 -0
- package/dist/docs/reference/storage.mdx +116 -0
- package/dist/docs/reference/swagger.mdx +132 -0
- package/dist/docs/reference/testing.mdx +145 -0
- package/dist/docs/reference/validator.mdx +186 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/backpressure.d.ts.map +1 -1
- package/dist/middleware/backpressure.js +21 -12
- package/dist/middleware/backpressure.js.map +1 -1
- package/dist/middleware/cache.d.ts +6 -0
- package/dist/middleware/cache.d.ts.map +1 -1
- package/dist/middleware/cache.js +84 -28
- package/dist/middleware/cache.js.map +1 -1
- package/dist/middleware/idempotency.d.ts +4 -1
- package/dist/middleware/idempotency.d.ts.map +1 -1
- package/dist/middleware/idempotency.js +29 -4
- package/dist/middleware/idempotency.js.map +1 -1
- package/dist/middleware/ip-filter.d.ts.map +1 -1
- package/dist/middleware/ip-filter.js +16 -0
- package/dist/middleware/ip-filter.js.map +1 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +29 -12
- package/dist/middleware/rate-limit.js.map +1 -1
- package/dist/queue/drivers/MemoryDriver.d.ts +6 -3
- package/dist/queue/drivers/MemoryDriver.d.ts.map +1 -1
- package/dist/queue/drivers/MemoryDriver.js +76 -23
- package/dist/queue/drivers/MemoryDriver.js.map +1 -1
- package/dist/server/bootstrapper.d.ts +3 -0
- package/dist/server/bootstrapper.d.ts.map +1 -1
- package/dist/server/bootstrapper.js +56 -8
- package/dist/server/bootstrapper.js.map +1 -1
- package/dist/server/bun-adapter.d.ts +2 -0
- package/dist/server/bun-adapter.d.ts.map +1 -1
- package/dist/server/bun-adapter.js +23 -12
- package/dist/server/bun-adapter.js.map +1 -1
- package/dist/server/request-handler.d.ts +0 -2
- package/dist/server/request-handler.d.ts.map +1 -1
- package/dist/server/request-handler.js +2 -24
- package/dist/server/request-handler.js.map +1 -1
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +24 -11
- package/dist/server/request.js.map +1 -1
- package/dist/server/uws-adapter.d.ts +80 -0
- package/dist/server/uws-adapter.d.ts.map +1 -0
- package/dist/server/uws-adapter.js +357 -0
- package/dist/server/uws-adapter.js.map +1 -0
- package/dist/server/ws-orchestrator.d.ts +1 -0
- package/dist/server/ws-orchestrator.d.ts.map +1 -1
- package/dist/server/ws-orchestrator.js +83 -0
- package/dist/server/ws-orchestrator.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/validator/tex.d.ts +21 -16
- package/dist/validator/tex.d.ts.map +1 -1
- package/dist/validator/tex.js.map +1 -1
- package/package.json +11 -3
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Database Manager.
|
|
4
|
+
*
|
|
5
|
+
* The central orchestrator for all database connections. Manages named connections,
|
|
6
|
+
* provides lifecycle integration with the ExisJS app (auto-disconnect on shutdown),
|
|
7
|
+
* and exposes the query builder, raw query execution, and migration system.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* import { db, createDatabase } from 'exisjs/database'
|
|
11
|
+
*
|
|
12
|
+
* // Quick setup
|
|
13
|
+
* const database = createDatabase({ dialect: 'postgres', url: process.env.DATABASE_URL })
|
|
14
|
+
* await database.connect()
|
|
15
|
+
*
|
|
16
|
+
* // Query
|
|
17
|
+
* const users = await database.query<User>('SELECT * FROM users')
|
|
18
|
+
* const admins = await database.table('users').where('role', '=', 'admin').rows()
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.db = exports.DatabaseManager = void 0;
|
|
22
|
+
exports.createDatabase = createDatabase;
|
|
23
|
+
exports.setDefaultDatabase = setDefaultDatabase;
|
|
24
|
+
const query_builder_1 = require("./query-builder");
|
|
25
|
+
const migration_1 = require("./migration");
|
|
26
|
+
/**
|
|
27
|
+
* Create a database adapter for the given dialect.
|
|
28
|
+
*/
|
|
29
|
+
function createAdapter(config) {
|
|
30
|
+
switch (config.dialect) {
|
|
31
|
+
case 'postgres': {
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
33
|
+
const { PostgresAdapter } = require('./adapters/postgres');
|
|
34
|
+
return new PostgresAdapter(config);
|
|
35
|
+
}
|
|
36
|
+
case 'mysql': {
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
38
|
+
const { MysqlAdapter } = require('./adapters/mysql');
|
|
39
|
+
return new MysqlAdapter(config);
|
|
40
|
+
}
|
|
41
|
+
case 'sqlite': {
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
43
|
+
const { SqliteAdapter } = require('./adapters/sqlite');
|
|
44
|
+
return new SqliteAdapter(config);
|
|
45
|
+
}
|
|
46
|
+
case 'mongodb': {
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
48
|
+
const { MongodbAdapter } = require('./adapters/mongodb');
|
|
49
|
+
return new MongodbAdapter(config);
|
|
50
|
+
}
|
|
51
|
+
default:
|
|
52
|
+
throw new Error(`Unsupported database dialect: ${config.dialect}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
class DatabaseManager {
|
|
56
|
+
constructor() {
|
|
57
|
+
this.connections = new Map();
|
|
58
|
+
this.configs = new Map();
|
|
59
|
+
this.defaultName = 'default';
|
|
60
|
+
this.migrator = null;
|
|
61
|
+
// ─── Private ───────────────────────────────────────────────────────────────
|
|
62
|
+
this.shutdownRegistered = false;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Add a named database connection.
|
|
66
|
+
* The first connection added becomes the default.
|
|
67
|
+
*/
|
|
68
|
+
addConnection(config, name) {
|
|
69
|
+
const connName = name || this.defaultName;
|
|
70
|
+
const adapter = createAdapter(config);
|
|
71
|
+
this.connections.set(connName, adapter);
|
|
72
|
+
this.configs.set(connName, config);
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Connect all registered connections (or a specific named connection).
|
|
77
|
+
*/
|
|
78
|
+
async connect(name) {
|
|
79
|
+
if (name) {
|
|
80
|
+
const adapter = this.getAdapter(name);
|
|
81
|
+
await adapter.connect();
|
|
82
|
+
this.registerShutdownHook();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const promises = [];
|
|
86
|
+
for (const [, adapter] of this.connections) {
|
|
87
|
+
promises.push(adapter.connect());
|
|
88
|
+
}
|
|
89
|
+
await Promise.all(promises);
|
|
90
|
+
this.registerShutdownHook();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Disconnect all connections (or a specific named connection).
|
|
94
|
+
*/
|
|
95
|
+
async disconnect(name) {
|
|
96
|
+
if (name) {
|
|
97
|
+
const adapter = this.connections.get(name);
|
|
98
|
+
if (adapter) {
|
|
99
|
+
await adapter.disconnect();
|
|
100
|
+
this.connections.delete(name);
|
|
101
|
+
this.configs.delete(name);
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const promises = [];
|
|
106
|
+
for (const [, adapter] of this.connections) {
|
|
107
|
+
promises.push(adapter.disconnect());
|
|
108
|
+
}
|
|
109
|
+
await Promise.all(promises);
|
|
110
|
+
this.connections.clear();
|
|
111
|
+
this.configs.clear();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Execute a SELECT query on the default (or named) connection.
|
|
115
|
+
*/
|
|
116
|
+
async query(sql, params, connectionName) {
|
|
117
|
+
const adapter = this.getAdapter(connectionName || this.defaultName);
|
|
118
|
+
return adapter.query(sql, params);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Execute an INSERT, UPDATE, or DELETE on the default (or named) connection.
|
|
122
|
+
*/
|
|
123
|
+
async execute(sql, params, connectionName) {
|
|
124
|
+
const adapter = this.getAdapter(connectionName || this.defaultName);
|
|
125
|
+
return adapter.execute(sql, params);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Execute a series of operations within an atomic transaction.
|
|
129
|
+
*/
|
|
130
|
+
async transaction(fn, connectionName) {
|
|
131
|
+
const adapter = this.getAdapter(connectionName || this.defaultName);
|
|
132
|
+
return adapter.transaction(fn);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Start building a query for a table (chainable query builder).
|
|
136
|
+
*/
|
|
137
|
+
table(tableName, connectionName) {
|
|
138
|
+
const adapter = this.getAdapter(connectionName || this.defaultName);
|
|
139
|
+
return new query_builder_1.QueryBuilder(adapter, tableName);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if a connection is healthy.
|
|
143
|
+
*/
|
|
144
|
+
async isHealthy(connectionName) {
|
|
145
|
+
const adapter = this.connections.get(connectionName || this.defaultName);
|
|
146
|
+
if (!adapter)
|
|
147
|
+
return false;
|
|
148
|
+
return adapter.isHealthy();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check health of all connections.
|
|
152
|
+
*/
|
|
153
|
+
async healthCheck() {
|
|
154
|
+
const results = {};
|
|
155
|
+
for (const [name, adapter] of this.connections) {
|
|
156
|
+
try {
|
|
157
|
+
results[name] = await adapter.isHealthy();
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
results[name] = false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return results;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get the raw adapter for a connection (for advanced use cases).
|
|
167
|
+
*/
|
|
168
|
+
getAdapter(name) {
|
|
169
|
+
const connName = name || this.defaultName;
|
|
170
|
+
const adapter = this.connections.get(connName);
|
|
171
|
+
if (!adapter) {
|
|
172
|
+
throw new Error(`Database connection '${connName}' not found. Did you call addConnection() and connect()?`);
|
|
173
|
+
}
|
|
174
|
+
return adapter;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get the raw underlying client for a connection.
|
|
178
|
+
*/
|
|
179
|
+
getRawClient(name) {
|
|
180
|
+
return this.getAdapter(name).getRawClient();
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get the dialect of a connection.
|
|
184
|
+
*/
|
|
185
|
+
getDialect(name) {
|
|
186
|
+
return this.getAdapter(name).dialect;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get the migration system for the default connection.
|
|
190
|
+
*/
|
|
191
|
+
getMigrator(config, connectionName) {
|
|
192
|
+
if (!this.migrator || connectionName) {
|
|
193
|
+
const adapter = this.getAdapter(connectionName || this.defaultName);
|
|
194
|
+
this.migrator = new migration_1.Migrator(adapter, config);
|
|
195
|
+
}
|
|
196
|
+
return this.migrator;
|
|
197
|
+
}
|
|
198
|
+
registerShutdownHook() {
|
|
199
|
+
if (this.shutdownRegistered)
|
|
200
|
+
return;
|
|
201
|
+
this.shutdownRegistered = true;
|
|
202
|
+
try {
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
204
|
+
const { getActiveApp } = require('../server/app');
|
|
205
|
+
const app = getActiveApp();
|
|
206
|
+
if (app && typeof app.onShutdown === 'function') {
|
|
207
|
+
app.onShutdown(async () => {
|
|
208
|
+
await this.disconnect();
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
// Not in an app context — user must disconnect manually
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
exports.DatabaseManager = DatabaseManager;
|
|
218
|
+
// ─── Factory & Singleton ─────────────────────────────────────────────────────
|
|
219
|
+
let defaultManager = null;
|
|
220
|
+
/**
|
|
221
|
+
* Create a new DatabaseManager with the given configuration.
|
|
222
|
+
* This is the recommended way to set up a database connection.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* const db = createDatabase({
|
|
227
|
+
* dialect: 'postgres',
|
|
228
|
+
* url: process.env.DATABASE_URL,
|
|
229
|
+
* })
|
|
230
|
+
* await db.connect()
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
function createDatabase(config) {
|
|
234
|
+
const manager = new DatabaseManager();
|
|
235
|
+
manager.addConnection(config);
|
|
236
|
+
// Set as the global default if none exists
|
|
237
|
+
if (!defaultManager) {
|
|
238
|
+
defaultManager = manager;
|
|
239
|
+
}
|
|
240
|
+
return manager;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Lazy-initialized global database proxy.
|
|
244
|
+
* Forwards all calls to the default DatabaseManager.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* import { db } from 'exisjs/database'
|
|
249
|
+
*
|
|
250
|
+
* // After createDatabase() has been called elsewhere:
|
|
251
|
+
* const users = await db.query('SELECT * FROM users')
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
exports.db = new Proxy({}, {
|
|
255
|
+
get(_target, prop) {
|
|
256
|
+
if (!defaultManager) {
|
|
257
|
+
throw new Error('No database has been configured. Call createDatabase() first.');
|
|
258
|
+
}
|
|
259
|
+
const value = defaultManager[prop];
|
|
260
|
+
return typeof value === 'function' ? value.bind(defaultManager) : value;
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
/**
|
|
264
|
+
* Set or replace the default DatabaseManager.
|
|
265
|
+
*/
|
|
266
|
+
function setDefaultDatabase(manager) {
|
|
267
|
+
defaultManager = manager;
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/database/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Migration System.
|
|
3
|
+
*
|
|
4
|
+
* Tracks applied migrations in a `_exis_migrations` table and provides
|
|
5
|
+
* up/down/status operations. Migrations are ordered by filename and
|
|
6
|
+
* applied in batches for clean rollbacks.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const migrator = new Migrator(adapter, { directory: './migrations' })
|
|
10
|
+
* await migrator.up() // Apply all pending migrations
|
|
11
|
+
* await migrator.down() // Rollback the last batch
|
|
12
|
+
* await migrator.status() // Get migration status
|
|
13
|
+
*/
|
|
14
|
+
import type { DatabaseAdapter, MigrationConfig } from './types';
|
|
15
|
+
export declare class Migrator {
|
|
16
|
+
private adapter;
|
|
17
|
+
private config;
|
|
18
|
+
constructor(adapter: DatabaseAdapter, config?: MigrationConfig);
|
|
19
|
+
/**
|
|
20
|
+
* Ensure the migrations tracking table exists.
|
|
21
|
+
*/
|
|
22
|
+
ensureTable(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Apply all pending migrations.
|
|
25
|
+
* @returns The names of the migrations that were applied.
|
|
26
|
+
*/
|
|
27
|
+
up(): Promise<string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Rollback the last batch of migrations.
|
|
30
|
+
* @returns The names of the migrations that were rolled back.
|
|
31
|
+
*/
|
|
32
|
+
down(): Promise<string[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Rollback all migrations.
|
|
35
|
+
*/
|
|
36
|
+
reset(): Promise<string[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Get the status of all migrations.
|
|
39
|
+
*/
|
|
40
|
+
status(): Promise<{
|
|
41
|
+
name: string;
|
|
42
|
+
applied: boolean;
|
|
43
|
+
batch?: number;
|
|
44
|
+
appliedAt?: Date;
|
|
45
|
+
}[]>;
|
|
46
|
+
/**
|
|
47
|
+
* Create a new migration file in the migrations directory.
|
|
48
|
+
*/
|
|
49
|
+
create(name: string): Promise<string>;
|
|
50
|
+
private loadMigrations;
|
|
51
|
+
private getApplied;
|
|
52
|
+
private getAppliedRecords;
|
|
53
|
+
private getNextBatch;
|
|
54
|
+
private getLastBatch;
|
|
55
|
+
private getMigrationsInBatch;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/database/migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAGhB,MAAM,SAAS,CAAA;AAIhB,qBAAa,QAAQ;IACnB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAA2B;gBAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,eAAe;IAQ9D;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BlC;;;OAGG;IACG,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAwC7B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA6C/B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAahC;;OAEG;IACG,MAAM,IAAI,OAAO,CACrB;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,IAAI,CAAA;KAAE,EAAE,CACvE;IAkBD;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAoC7B,cAAc;YA8Cd,UAAU;YAKV,iBAAiB;YAwBjB,YAAY;YAIZ,YAAY;YAmBZ,oBAAoB;CA0BnC"}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Built-in Migration System.
|
|
4
|
+
*
|
|
5
|
+
* Tracks applied migrations in a `_exis_migrations` table and provides
|
|
6
|
+
* up/down/status operations. Migrations are ordered by filename and
|
|
7
|
+
* applied in batches for clean rollbacks.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const migrator = new Migrator(adapter, { directory: './migrations' })
|
|
11
|
+
* await migrator.up() // Apply all pending migrations
|
|
12
|
+
* await migrator.down() // Rollback the last batch
|
|
13
|
+
* await migrator.status() // Get migration status
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.Migrator = void 0;
|
|
50
|
+
const promises_1 = require("node:fs/promises");
|
|
51
|
+
const node_path_1 = require("node:path");
|
|
52
|
+
const DEFAULT_TABLE = '_exis_migrations';
|
|
53
|
+
class Migrator {
|
|
54
|
+
constructor(adapter, config) {
|
|
55
|
+
this.adapter = adapter;
|
|
56
|
+
this.config = {
|
|
57
|
+
directory: config?.directory || './migrations',
|
|
58
|
+
tableName: config?.tableName || DEFAULT_TABLE,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Ensure the migrations tracking table exists.
|
|
63
|
+
*/
|
|
64
|
+
async ensureTable() {
|
|
65
|
+
const { tableName } = this.config;
|
|
66
|
+
const dialect = this.adapter.dialect;
|
|
67
|
+
if (dialect === 'mongodb') {
|
|
68
|
+
// MongoDB doesn't need a schema — we just use a collection
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const createSQL = dialect === 'sqlite'
|
|
72
|
+
? `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
73
|
+
name TEXT PRIMARY KEY,
|
|
74
|
+
batch INTEGER NOT NULL,
|
|
75
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
76
|
+
)`
|
|
77
|
+
: dialect === 'mysql'
|
|
78
|
+
? `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
79
|
+
name VARCHAR(255) PRIMARY KEY,
|
|
80
|
+
batch INT NOT NULL,
|
|
81
|
+
applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
82
|
+
)`
|
|
83
|
+
: `CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
84
|
+
name VARCHAR(255) PRIMARY KEY,
|
|
85
|
+
batch INT NOT NULL,
|
|
86
|
+
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
87
|
+
)`;
|
|
88
|
+
await this.adapter.execute(createSQL);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Apply all pending migrations.
|
|
92
|
+
* @returns The names of the migrations that were applied.
|
|
93
|
+
*/
|
|
94
|
+
async up() {
|
|
95
|
+
await this.ensureTable();
|
|
96
|
+
const applied = await this.getApplied();
|
|
97
|
+
const allMigrations = await this.loadMigrations();
|
|
98
|
+
const pending = allMigrations.filter((m) => !applied.has(m.name));
|
|
99
|
+
if (pending.length === 0) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
const batch = await this.getNextBatch();
|
|
103
|
+
const appliedNames = [];
|
|
104
|
+
for (const migration of pending) {
|
|
105
|
+
await this.adapter.transaction(async (tx) => {
|
|
106
|
+
// Run the migration
|
|
107
|
+
await migration.up(this.adapter);
|
|
108
|
+
// Record it
|
|
109
|
+
if (this.adapter.dialect === 'mongodb') {
|
|
110
|
+
await this.adapter.execute('_exis_migrations.insertOne', [
|
|
111
|
+
{ name: migration.name, batch, applied_at: new Date() },
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const placeholder = this.adapter.dialect === 'postgres' ? '$1' : '?';
|
|
116
|
+
const placeholder2 = this.adapter.dialect === 'postgres' ? '$2' : '?';
|
|
117
|
+
await tx.execute(`INSERT INTO ${this.config.tableName} (name, batch) VALUES (${placeholder}, ${placeholder2})`, [migration.name, batch]);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
appliedNames.push(migration.name);
|
|
121
|
+
}
|
|
122
|
+
return appliedNames;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Rollback the last batch of migrations.
|
|
126
|
+
* @returns The names of the migrations that were rolled back.
|
|
127
|
+
*/
|
|
128
|
+
async down() {
|
|
129
|
+
await this.ensureTable();
|
|
130
|
+
const lastBatch = await this.getLastBatch();
|
|
131
|
+
if (lastBatch === 0) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
const batchMigrations = await this.getMigrationsInBatch(lastBatch);
|
|
135
|
+
const allMigrations = await this.loadMigrations();
|
|
136
|
+
const migrationMap = new Map(allMigrations.map((m) => [m.name, m]));
|
|
137
|
+
const rolledBack = [];
|
|
138
|
+
// Rollback in reverse order
|
|
139
|
+
for (const record of batchMigrations.reverse()) {
|
|
140
|
+
const migration = migrationMap.get(record.name);
|
|
141
|
+
if (!migration) {
|
|
142
|
+
throw new Error(`Migration file for '${record.name}' not found. Cannot rollback.`);
|
|
143
|
+
}
|
|
144
|
+
await this.adapter.transaction(async (tx) => {
|
|
145
|
+
await migration.down(this.adapter);
|
|
146
|
+
if (this.adapter.dialect === 'mongodb') {
|
|
147
|
+
await this.adapter.execute('_exis_migrations.deleteOne', [
|
|
148
|
+
{ name: record.name },
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const placeholder = this.adapter.dialect === 'postgres' ? '$1' : '?';
|
|
153
|
+
await tx.execute(`DELETE FROM ${this.config.tableName} WHERE name = ${placeholder}`, [record.name]);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
rolledBack.push(record.name);
|
|
157
|
+
}
|
|
158
|
+
return rolledBack;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Rollback all migrations.
|
|
162
|
+
*/
|
|
163
|
+
async reset() {
|
|
164
|
+
const rolledBack = [];
|
|
165
|
+
let batch = await this.getLastBatch();
|
|
166
|
+
while (batch > 0) {
|
|
167
|
+
const names = await this.down();
|
|
168
|
+
rolledBack.push(...names);
|
|
169
|
+
batch = await this.getLastBatch();
|
|
170
|
+
}
|
|
171
|
+
return rolledBack;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get the status of all migrations.
|
|
175
|
+
*/
|
|
176
|
+
async status() {
|
|
177
|
+
await this.ensureTable();
|
|
178
|
+
const applied = await this.getAppliedRecords();
|
|
179
|
+
const allMigrations = await this.loadMigrations();
|
|
180
|
+
const appliedMap = new Map(applied.map((r) => [r.name, r]));
|
|
181
|
+
return allMigrations.map((m) => {
|
|
182
|
+
const record = appliedMap.get(m.name);
|
|
183
|
+
return {
|
|
184
|
+
name: m.name,
|
|
185
|
+
applied: !!record,
|
|
186
|
+
batch: record?.batch,
|
|
187
|
+
appliedAt: record?.appliedAt,
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Create a new migration file in the migrations directory.
|
|
193
|
+
*/
|
|
194
|
+
async create(name) {
|
|
195
|
+
const { mkdir, writeFile } = await Promise.resolve().then(() => __importStar(require('node:fs/promises')));
|
|
196
|
+
const dir = (0, node_path_1.resolve)(this.config.directory);
|
|
197
|
+
await mkdir(dir, { recursive: true });
|
|
198
|
+
const timestamp = new Date()
|
|
199
|
+
.toISOString()
|
|
200
|
+
.replace(/[-:T]/g, '')
|
|
201
|
+
.slice(0, 14);
|
|
202
|
+
const filename = `${timestamp}_${name}.ts`;
|
|
203
|
+
const filepath = (0, node_path_1.resolve)(dir, filename);
|
|
204
|
+
const template = `import type { DatabaseAdapter } from 'exisjs/database'
|
|
205
|
+
|
|
206
|
+
export default {
|
|
207
|
+
name: '${timestamp}_${name}',
|
|
208
|
+
|
|
209
|
+
async up(db: DatabaseAdapter): Promise<void> {
|
|
210
|
+
// Write your migration here
|
|
211
|
+
// await db.execute('CREATE TABLE ...')
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
async down(db: DatabaseAdapter): Promise<void> {
|
|
215
|
+
// Write the rollback here
|
|
216
|
+
// await db.execute('DROP TABLE ...')
|
|
217
|
+
},
|
|
218
|
+
}
|
|
219
|
+
`;
|
|
220
|
+
await writeFile(filepath, template, 'utf-8');
|
|
221
|
+
return filepath;
|
|
222
|
+
}
|
|
223
|
+
// ─── Private Helpers ───────────────────────────────────────────────────────
|
|
224
|
+
async loadMigrations() {
|
|
225
|
+
const dir = (0, node_path_1.resolve)(this.config.directory);
|
|
226
|
+
let files;
|
|
227
|
+
try {
|
|
228
|
+
files = await (0, promises_1.readdir)(dir);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
const migrationFiles = files
|
|
234
|
+
.filter((f) => {
|
|
235
|
+
const ext = (0, node_path_1.extname)(f);
|
|
236
|
+
return ext === '.ts' || ext === '.js' || ext === '.mjs';
|
|
237
|
+
})
|
|
238
|
+
.sort();
|
|
239
|
+
const migrations = [];
|
|
240
|
+
for (const file of migrationFiles) {
|
|
241
|
+
const filepath = (0, node_path_1.resolve)(dir, file);
|
|
242
|
+
try {
|
|
243
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
244
|
+
const mod = require(filepath);
|
|
245
|
+
const migration = mod.default || mod;
|
|
246
|
+
if (migration &&
|
|
247
|
+
typeof migration.up === 'function' &&
|
|
248
|
+
typeof migration.down === 'function') {
|
|
249
|
+
migrations.push({
|
|
250
|
+
name: migration.name || (0, node_path_1.basename)(file, (0, node_path_1.extname)(file)),
|
|
251
|
+
up: migration.up,
|
|
252
|
+
down: migration.down,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
throw new Error(`Failed to load migration '${file}': ${err.message}`, {
|
|
258
|
+
cause: err,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return migrations;
|
|
263
|
+
}
|
|
264
|
+
async getApplied() {
|
|
265
|
+
const records = await this.getAppliedRecords();
|
|
266
|
+
return new Set(records.map((r) => r.name));
|
|
267
|
+
}
|
|
268
|
+
async getAppliedRecords() {
|
|
269
|
+
if (this.adapter.dialect === 'mongodb') {
|
|
270
|
+
const result = await this.adapter.query('_exis_migrations', [{}]);
|
|
271
|
+
return result.rows.map((r) => ({
|
|
272
|
+
name: r.name,
|
|
273
|
+
batch: r.batch,
|
|
274
|
+
appliedAt: new Date(r.applied_at),
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
const result = await this.adapter.query(`SELECT name, batch, applied_at FROM ${this.config.tableName} ORDER BY name`);
|
|
279
|
+
return result.rows.map((r) => ({
|
|
280
|
+
name: r.name,
|
|
281
|
+
batch: r.batch,
|
|
282
|
+
appliedAt: new Date(r.applied_at),
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async getNextBatch() {
|
|
290
|
+
return (await this.getLastBatch()) + 1;
|
|
291
|
+
}
|
|
292
|
+
async getLastBatch() {
|
|
293
|
+
if (this.adapter.dialect === 'mongodb') {
|
|
294
|
+
const result = await this.adapter.query('_exis_migrations', [
|
|
295
|
+
{},
|
|
296
|
+
{ sort: { batch: -1 }, limit: 1 },
|
|
297
|
+
]);
|
|
298
|
+
return result.rows[0]?.batch ?? 0;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
const result = await this.adapter.query(`SELECT MAX(batch) as max_batch FROM ${this.config.tableName}`);
|
|
302
|
+
return result.rows[0]?.max_batch ?? 0;
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
return 0;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
async getMigrationsInBatch(batch) {
|
|
309
|
+
if (this.adapter.dialect === 'mongodb') {
|
|
310
|
+
const result = await this.adapter.query('_exis_migrations', [
|
|
311
|
+
{ batch },
|
|
312
|
+
]);
|
|
313
|
+
return result.rows.map((r) => ({
|
|
314
|
+
name: r.name,
|
|
315
|
+
batch: r.batch,
|
|
316
|
+
appliedAt: new Date(r.applied_at),
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
const placeholder = this.adapter.dialect === 'postgres' ? '$1' : '?';
|
|
320
|
+
const result = await this.adapter.query(`SELECT name, batch, applied_at FROM ${this.config.tableName} WHERE batch = ${placeholder} ORDER BY name`, [batch]);
|
|
321
|
+
return result.rows.map((r) => ({
|
|
322
|
+
name: r.name,
|
|
323
|
+
batch: r.batch,
|
|
324
|
+
appliedAt: new Date(r.applied_at),
|
|
325
|
+
}));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
exports.Migrator = Migrator;
|
|
329
|
+
//# sourceMappingURL=migration.js.map
|