@stacksjs/database 0.70.88 → 0.70.90
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-tables.d.ts +60 -0
- package/dist/auth-tables.js +220 -0
- package/dist/class-seeder.d.ts +65 -0
- package/dist/class-seeder.js +116 -0
- package/dist/column.d.ts +17 -0
- package/dist/column.js +26 -0
- package/dist/custom/audits.d.ts +16 -0
- package/dist/custom/audits.js +57 -0
- package/dist/custom/errors.d.ts +1 -0
- package/dist/custom/errors.js +48 -0
- package/dist/custom/index.d.ts +3 -0
- package/dist/custom/index.js +3 -0
- package/dist/custom/jobs.d.ts +3 -0
- package/dist/custom/jobs.js +449 -0
- package/dist/database.d.ts +89 -0
- package/dist/database.js +178 -0
- package/dist/defaults.d.ts +48 -0
- package/dist/defaults.js +48 -0
- package/dist/driver-config.d.ts +149 -0
- package/dist/driver-config.js +144 -0
- package/dist/drivers/defaults/index.d.ts +2 -0
- package/dist/drivers/defaults/index.js +2 -0
- package/dist/drivers/defaults/passwords.d.ts +4 -0
- package/dist/drivers/defaults/passwords.js +106 -0
- package/dist/drivers/defaults/traits.d.ts +33 -0
- package/dist/drivers/defaults/traits.js +1125 -0
- package/dist/drivers/dynamodb.d.ts +200 -0
- package/dist/drivers/dynamodb.js +607 -0
- package/dist/drivers/helpers.d.ts +35 -0
- package/dist/drivers/helpers.js +206 -0
- package/dist/drivers/index.d.ts +16 -0
- package/dist/drivers/index.js +9 -0
- package/dist/drivers/mysql.d.ts +7 -0
- package/dist/drivers/mysql.js +322 -0
- package/dist/drivers/postgres.d.ts +7 -0
- package/dist/drivers/postgres.js +411 -0
- package/dist/drivers/sqlite.d.ts +20 -0
- package/dist/drivers/sqlite.js +397 -0
- package/dist/factory.d.ts +41 -0
- package/dist/factory.js +51 -0
- package/dist/fk-audit.d.ts +101 -0
- package/dist/fk-audit.js +181 -0
- package/dist/index.d.ts +149 -0
- package/dist/index.js +55 -0
- package/dist/migration-lock.d.ts +23 -0
- package/dist/migration-lock.js +143 -0
- package/dist/migrations.d.ts +76 -0
- package/dist/migrations.js +528 -0
- package/dist/notification-tables.d.ts +20 -0
- package/dist/notification-tables.js +54 -0
- package/dist/query-logger.d.ts +26 -0
- package/dist/query-logger.js +213 -0
- package/dist/query-parser.d.ts +4 -0
- package/dist/query-parser.js +93 -0
- package/dist/rbac-tables.d.ts +17 -0
- package/dist/rbac-tables.js +84 -0
- package/dist/safe-migrations.d.ts +72 -0
- package/dist/safe-migrations.js +59 -0
- package/dist/schema.d.ts +4 -0
- package/dist/schema.js +10 -0
- package/dist/seed-scaffold.d.ts +34 -0
- package/dist/seed-scaffold.js +144 -0
- package/dist/seeder.d.ts +116 -0
- package/dist/seeder.js +363 -0
- package/dist/sql-helpers.d.ts +33 -0
- package/dist/sql-helpers.js +24 -0
- package/dist/table.d.ts +7 -0
- package/dist/table.js +26 -0
- package/dist/tools/setup.d.ts +1 -0
- package/dist/tools/setup.js +6 -0
- package/dist/transaction-context.d.ts +52 -0
- package/dist/transaction-context.js +62 -0
- package/dist/types.d.ts +151 -0
- package/dist/types.js +23 -0
- package/dist/unique-audit.d.ts +60 -0
- package/dist/unique-audit.js +174 -0
- package/dist/utils.d.ts +189 -0
- package/dist/utils.js +163 -0
- package/dist/uuid-columns.d.ts +22 -0
- package/dist/uuid-columns.js +68 -0
- package/dist/validators.d.ts +26 -0
- package/dist/validators.js +122 -0
- package/package.json +11 -11
package/dist/database.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { createQueryBuilder, setConfig } from "@stacksjs/query-builder";
|
|
2
|
+
import { env as stacksEnv } from "@stacksjs/env";
|
|
3
|
+
|
|
4
|
+
export class Database {
|
|
5
|
+
_queryBuilder = null;
|
|
6
|
+
_options;
|
|
7
|
+
_initialized = !1;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this._options = {
|
|
10
|
+
verbose: !1,
|
|
11
|
+
timestamps: {
|
|
12
|
+
createdAt: "created_at",
|
|
13
|
+
updatedAt: "updated_at",
|
|
14
|
+
defaultOrderColumn: "created_at"
|
|
15
|
+
},
|
|
16
|
+
softDeletes: {
|
|
17
|
+
enabled: !1,
|
|
18
|
+
column: "deleted_at",
|
|
19
|
+
defaultFilter: !0
|
|
20
|
+
},
|
|
21
|
+
...options
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
get driver() {
|
|
25
|
+
return this._options.driver;
|
|
26
|
+
}
|
|
27
|
+
get connection() {
|
|
28
|
+
return this._options.connection;
|
|
29
|
+
}
|
|
30
|
+
get isInitialized() {
|
|
31
|
+
return this._initialized;
|
|
32
|
+
}
|
|
33
|
+
get query() {
|
|
34
|
+
if (!this._queryBuilder)
|
|
35
|
+
this.initialize();
|
|
36
|
+
return this._queryBuilder;
|
|
37
|
+
}
|
|
38
|
+
initialize() {
|
|
39
|
+
if (this._initialized)
|
|
40
|
+
return;
|
|
41
|
+
setConfig({
|
|
42
|
+
dialect: this._options.driver,
|
|
43
|
+
database: this._options.connection,
|
|
44
|
+
verbose: this._options.verbose,
|
|
45
|
+
timestamps: this._options.timestamps,
|
|
46
|
+
softDeletes: this._options.softDeletes,
|
|
47
|
+
hooks: this._options.hooks
|
|
48
|
+
});
|
|
49
|
+
this._queryBuilder = createQueryBuilder();
|
|
50
|
+
this._initialized = !0;
|
|
51
|
+
}
|
|
52
|
+
switchDriver(driver, connection) {
|
|
53
|
+
this.close();
|
|
54
|
+
this._options.driver = driver;
|
|
55
|
+
this._options.connection = connection;
|
|
56
|
+
this._initialized = !1;
|
|
57
|
+
this.initialize();
|
|
58
|
+
}
|
|
59
|
+
async close() {
|
|
60
|
+
if (this._queryBuilder && typeof this._queryBuilder.close === "function")
|
|
61
|
+
await this._queryBuilder.close();
|
|
62
|
+
this._queryBuilder = null;
|
|
63
|
+
this._initialized = !1;
|
|
64
|
+
}
|
|
65
|
+
static fromConfig(config, env) {
|
|
66
|
+
const driver = config.default;
|
|
67
|
+
let connection;
|
|
68
|
+
switch (driver) {
|
|
69
|
+
case "sqlite": {
|
|
70
|
+
connection = { database: env === "testing" ? config.connections.sqlite?.database?.replace(".sqlite", "_testing.sqlite") || "database/stacks_testing.sqlite" : config.connections.sqlite?.database || "database/stacks.sqlite" };
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case "mysql": {
|
|
74
|
+
const mysql = config.connections.mysql;
|
|
75
|
+
connection = {
|
|
76
|
+
database: mysql?.name || "stacks",
|
|
77
|
+
host: mysql?.host || "127.0.0.1",
|
|
78
|
+
port: mysql?.port || 3306,
|
|
79
|
+
username: mysql?.username || "root",
|
|
80
|
+
password: mysql?.password || ""
|
|
81
|
+
};
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case "singlestore": {
|
|
85
|
+
const singlestore = config.connections.singlestore;
|
|
86
|
+
connection = {
|
|
87
|
+
database: singlestore?.name || "stacks",
|
|
88
|
+
host: singlestore?.host || "127.0.0.1",
|
|
89
|
+
port: singlestore?.port || 3306,
|
|
90
|
+
username: singlestore?.username || "root",
|
|
91
|
+
password: singlestore?.password || ""
|
|
92
|
+
};
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case "postgres": {
|
|
96
|
+
const postgres = config.connections.postgres, dbName = postgres?.name || "stacks";
|
|
97
|
+
connection = {
|
|
98
|
+
database: env === "testing" ? `${dbName}_testing` : dbName,
|
|
99
|
+
host: postgres?.host || "127.0.0.1",
|
|
100
|
+
port: postgres?.port || 5432,
|
|
101
|
+
username: postgres?.username || "",
|
|
102
|
+
password: postgres?.password || ""
|
|
103
|
+
};
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case "dynamodb":
|
|
107
|
+
throw Error("[database] DB_CONNECTION=dynamodb is not a SQL driver. Use the entity-style `dynamo.entity(...)` API for DynamoDB access, or set DB_CONNECTION to sqlite/mysql/postgres for SQL workloads.");
|
|
108
|
+
default:
|
|
109
|
+
throw Error(`[database] Unknown DB_CONNECTION "${String(driver)}". Allowed values: sqlite, mysql, postgres.`);
|
|
110
|
+
}
|
|
111
|
+
return new Database({
|
|
112
|
+
driver,
|
|
113
|
+
connection,
|
|
114
|
+
verbose: env !== "production"
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
static fromEnv() {
|
|
118
|
+
const driver = stacksEnv.DB_CONNECTION || "sqlite";
|
|
119
|
+
let connection;
|
|
120
|
+
switch (driver) {
|
|
121
|
+
case "sqlite":
|
|
122
|
+
connection = {
|
|
123
|
+
database: stacksEnv.DB_DATABASE || "database/stacks.sqlite"
|
|
124
|
+
};
|
|
125
|
+
break;
|
|
126
|
+
case "mysql":
|
|
127
|
+
case "singlestore":
|
|
128
|
+
connection = {
|
|
129
|
+
database: stacksEnv.DB_DATABASE || "stacks",
|
|
130
|
+
host: stacksEnv.DB_HOST || "127.0.0.1",
|
|
131
|
+
port: stacksEnv.DB_PORT || 3306,
|
|
132
|
+
username: stacksEnv.DB_USERNAME || "root",
|
|
133
|
+
password: stacksEnv.DB_PASSWORD || ""
|
|
134
|
+
};
|
|
135
|
+
break;
|
|
136
|
+
case "postgres":
|
|
137
|
+
connection = {
|
|
138
|
+
database: stacksEnv.DB_DATABASE || "stacks",
|
|
139
|
+
host: stacksEnv.DB_HOST || "127.0.0.1",
|
|
140
|
+
port: stacksEnv.DB_PORT || 5432,
|
|
141
|
+
username: stacksEnv.DB_USERNAME || "",
|
|
142
|
+
password: stacksEnv.DB_PASSWORD || ""
|
|
143
|
+
};
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
connection = { database: ":memory:" };
|
|
147
|
+
}
|
|
148
|
+
return new Database({
|
|
149
|
+
driver,
|
|
150
|
+
connection,
|
|
151
|
+
verbose: stacksEnv.APP_ENV !== "prod"
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export function createDatabase(options) {
|
|
156
|
+
return new Database(options);
|
|
157
|
+
}
|
|
158
|
+
export function createSqliteDatabase(database, options) {
|
|
159
|
+
return new Database({
|
|
160
|
+
driver: "sqlite",
|
|
161
|
+
connection: { database },
|
|
162
|
+
...options
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
export function createPostgresDatabase(connection, options) {
|
|
166
|
+
return new Database({
|
|
167
|
+
driver: "postgres",
|
|
168
|
+
connection,
|
|
169
|
+
...options
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
export function createMysqlDatabase(connection, options) {
|
|
173
|
+
return new Database({
|
|
174
|
+
driver: "mysql",
|
|
175
|
+
connection,
|
|
176
|
+
...options
|
|
177
|
+
});
|
|
178
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get default connection config for a given database driver.
|
|
3
|
+
* Reads from the typed env proxy so values are auto-coerced.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getConnectionDefaults(driver: string, envProxy?: Record<string, any>): ConnectionDefaults;
|
|
6
|
+
/**
|
|
7
|
+
* Database Defaults & Constants
|
|
8
|
+
*
|
|
9
|
+
* Centralizes all hardcoded default values for database connections
|
|
10
|
+
* so they are defined once and easily discoverable.
|
|
11
|
+
*/
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// HOST / PORT DEFAULTS
|
|
14
|
+
// ============================================================================
|
|
15
|
+
export declare const DB_HOST_DEFAULT: '127.0.0.1';
|
|
16
|
+
export declare const DB_PORTS: {
|
|
17
|
+
mysql: 3306;
|
|
18
|
+
postgres: 5432;
|
|
19
|
+
sqlite: 0
|
|
20
|
+
};
|
|
21
|
+
export declare const DB_NAMES: {
|
|
22
|
+
default: 'stacks';
|
|
23
|
+
sqlitePath: 'database/stacks.sqlite';
|
|
24
|
+
sqliteTestingPath: 'database/stacks_testing.sqlite'
|
|
25
|
+
};
|
|
26
|
+
export declare const DB_USERS: {
|
|
27
|
+
mysql: 'root';
|
|
28
|
+
postgres: 'postgres';
|
|
29
|
+
sqlite: ''
|
|
30
|
+
};
|
|
31
|
+
export declare const REDIS_DEFAULTS: {
|
|
32
|
+
host: 'localhost';
|
|
33
|
+
port: 6379
|
|
34
|
+
};
|
|
35
|
+
export declare const AWS_DEFAULTS: {
|
|
36
|
+
region: 'us-east-1'
|
|
37
|
+
};
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// CONNECTION CONFIG BUILDERS
|
|
40
|
+
// ============================================================================
|
|
41
|
+
export declare interface ConnectionDefaults {
|
|
42
|
+
database: string
|
|
43
|
+
host?: string
|
|
44
|
+
port?: number
|
|
45
|
+
username?: string
|
|
46
|
+
password?: string
|
|
47
|
+
prefix?: string
|
|
48
|
+
}
|
package/dist/defaults.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const DB_HOST_DEFAULT = "127.0.0.1", DB_PORTS = {
|
|
2
|
+
mysql: 3306,
|
|
3
|
+
postgres: 5432,
|
|
4
|
+
sqlite: 0
|
|
5
|
+
}, DB_NAMES = {
|
|
6
|
+
default: "stacks",
|
|
7
|
+
sqlitePath: "database/stacks.sqlite",
|
|
8
|
+
sqliteTestingPath: "database/stacks_testing.sqlite"
|
|
9
|
+
}, DB_USERS = {
|
|
10
|
+
mysql: "root",
|
|
11
|
+
postgres: "postgres",
|
|
12
|
+
sqlite: ""
|
|
13
|
+
}, REDIS_DEFAULTS = {
|
|
14
|
+
host: "localhost",
|
|
15
|
+
port: 6379
|
|
16
|
+
}, AWS_DEFAULTS = {
|
|
17
|
+
region: "us-east-1"
|
|
18
|
+
};
|
|
19
|
+
export function getConnectionDefaults(driver, envProxy) {
|
|
20
|
+
const e = envProxy ?? {};
|
|
21
|
+
switch (driver) {
|
|
22
|
+
case "sqlite":
|
|
23
|
+
return {
|
|
24
|
+
database: e.DB_DATABASE_PATH || DB_NAMES.sqlitePath,
|
|
25
|
+
prefix: ""
|
|
26
|
+
};
|
|
27
|
+
case "mysql":
|
|
28
|
+
return {
|
|
29
|
+
database: e.DB_DATABASE || DB_NAMES.default,
|
|
30
|
+
host: e.DB_HOST || DB_HOST_DEFAULT,
|
|
31
|
+
port: e.DB_PORT || DB_PORTS.mysql,
|
|
32
|
+
username: e.DB_USERNAME || DB_USERS.mysql,
|
|
33
|
+
password: e.DB_PASSWORD || "",
|
|
34
|
+
prefix: ""
|
|
35
|
+
};
|
|
36
|
+
case "postgres":
|
|
37
|
+
return {
|
|
38
|
+
database: e.DB_DATABASE || DB_NAMES.default,
|
|
39
|
+
host: e.DB_HOST || DB_HOST_DEFAULT,
|
|
40
|
+
port: e.DB_PORT || DB_PORTS.postgres,
|
|
41
|
+
username: e.DB_USERNAME || DB_USERS.postgres,
|
|
42
|
+
password: e.DB_PASSWORD || "",
|
|
43
|
+
prefix: ""
|
|
44
|
+
};
|
|
45
|
+
default:
|
|
46
|
+
return { database: ":memory:" };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { StacksDialect } from '@stacksjs/query-builder';
|
|
2
|
+
/**
|
|
3
|
+
* Get the connection string for a given driver and configuration
|
|
4
|
+
*/
|
|
5
|
+
export declare function getConnectionString(driver: StacksDialect, config: DatabaseConnections[keyof DatabaseConnections]): string;
|
|
6
|
+
/**
|
|
7
|
+
* Validate driver configuration
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateDriverConfig(driver: StacksDialect, config: DatabaseConnections[keyof DatabaseConnections]): { valid: boolean, errors: string[] };
|
|
10
|
+
/**
|
|
11
|
+
* Merge user configuration with defaults
|
|
12
|
+
*/
|
|
13
|
+
export declare function mergeWithDefaults<T extends keyof DatabaseConnections>(driver: T, config: Partial<DatabaseConnections[T]>): DatabaseConnections[T];
|
|
14
|
+
/**
|
|
15
|
+
* Get the appropriate configuration for a driver from environment variables
|
|
16
|
+
*/
|
|
17
|
+
export declare function getConfigFromEnv(driver: StacksDialect): DatabaseConnections[keyof DatabaseConnections];
|
|
18
|
+
/**
|
|
19
|
+
* Detect the best available driver based on environment
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectDriver(): StacksDialect;
|
|
22
|
+
/**
|
|
23
|
+
* Default configuration values for each driver
|
|
24
|
+
* @defaultValue
|
|
25
|
+
* ```ts
|
|
26
|
+
* {
|
|
27
|
+
* sqlite: { database: 'database/stacks.sqlite', prefix: '' },
|
|
28
|
+
* mysql: {
|
|
29
|
+
* name: 'stacks',
|
|
30
|
+
* host: '127.0.0.1',
|
|
31
|
+
* port: 3306,
|
|
32
|
+
* username: 'root',
|
|
33
|
+
* password: '',
|
|
34
|
+
* prefix: '',
|
|
35
|
+
* charset: 'utf8mb4',
|
|
36
|
+
* collation: 'utf8mb4_unicode_ci'
|
|
37
|
+
* },
|
|
38
|
+
* singlestore: {
|
|
39
|
+
* name: 'stacks',
|
|
40
|
+
* host: '127.0.0.1',
|
|
41
|
+
* port: 3306,
|
|
42
|
+
* username: 'root',
|
|
43
|
+
* password: '',
|
|
44
|
+
* prefix: '',
|
|
45
|
+
* charset: 'utf8mb4',
|
|
46
|
+
* ssl: false
|
|
47
|
+
* },
|
|
48
|
+
* postgres: {
|
|
49
|
+
* name: 'stacks',
|
|
50
|
+
* host: '127.0.0.1',
|
|
51
|
+
* port: 5432,
|
|
52
|
+
* username: 'postgres',
|
|
53
|
+
* password: '',
|
|
54
|
+
* prefix: '',
|
|
55
|
+
* schema: 'public'
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare const driverDefaults: Record<StacksDialect, Partial<SqliteConfig | MysqlConfig | SinglestoreConfig | PostgresConfig | DynamoDbConfig>>;
|
|
61
|
+
/**
|
|
62
|
+
* SQLite specific configuration
|
|
63
|
+
*/
|
|
64
|
+
export declare interface SqliteConfig {
|
|
65
|
+
database: string
|
|
66
|
+
prefix?: string
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* MySQL specific configuration
|
|
70
|
+
*/
|
|
71
|
+
export declare interface MysqlConfig {
|
|
72
|
+
name: string
|
|
73
|
+
host?: string
|
|
74
|
+
port?: number
|
|
75
|
+
username?: string
|
|
76
|
+
password?: string
|
|
77
|
+
prefix?: string
|
|
78
|
+
charset?: string
|
|
79
|
+
collation?: string
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* SingleStore specific configuration.
|
|
83
|
+
*
|
|
84
|
+
* SingleStore (formerly MemSQL) speaks the MySQL wire protocol, so it shares
|
|
85
|
+
* MySQL's connection shape. It diverges only in DDL (distributed tables with
|
|
86
|
+
* SHARD KEY / SORT KEY, no foreign keys) — handled by the migration generator,
|
|
87
|
+
* not by the connection layer.
|
|
88
|
+
*/
|
|
89
|
+
export declare interface SinglestoreConfig {
|
|
90
|
+
name: string
|
|
91
|
+
host?: string
|
|
92
|
+
port?: number
|
|
93
|
+
username?: string
|
|
94
|
+
password?: string
|
|
95
|
+
prefix?: string
|
|
96
|
+
charset?: string
|
|
97
|
+
ssl?: boolean
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* PostgreSQL specific configuration
|
|
101
|
+
*/
|
|
102
|
+
export declare interface PostgresConfig {
|
|
103
|
+
name: string
|
|
104
|
+
host?: string
|
|
105
|
+
port?: number
|
|
106
|
+
username?: string
|
|
107
|
+
password?: string
|
|
108
|
+
prefix?: string
|
|
109
|
+
schema?: string
|
|
110
|
+
sslMode?: 'disable' | 'require' | 'verify-ca' | 'verify-full'
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* DynamoDB specific configuration
|
|
114
|
+
*/
|
|
115
|
+
export declare interface DynamoDbConfig {
|
|
116
|
+
key: string
|
|
117
|
+
secret: string
|
|
118
|
+
region?: string
|
|
119
|
+
prefix?: string
|
|
120
|
+
endpoint?: string
|
|
121
|
+
tableName?: string
|
|
122
|
+
singleTable?: {
|
|
123
|
+
enabled?: boolean
|
|
124
|
+
pkAttribute?: string
|
|
125
|
+
skAttribute?: string
|
|
126
|
+
entityTypeAttribute?: string
|
|
127
|
+
keyDelimiter?: string
|
|
128
|
+
gsiCount?: number
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* All database connections configuration
|
|
133
|
+
*/
|
|
134
|
+
export declare interface DatabaseConnections {
|
|
135
|
+
sqlite?: SqliteConfig
|
|
136
|
+
mysql?: MysqlConfig
|
|
137
|
+
singlestore?: SinglestoreConfig
|
|
138
|
+
postgres?: PostgresConfig
|
|
139
|
+
dynamodb?: DynamoDbConfig
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Full database configuration
|
|
143
|
+
*/
|
|
144
|
+
export declare interface FullDatabaseConfig {
|
|
145
|
+
default: StacksDialect
|
|
146
|
+
connections: DatabaseConnections
|
|
147
|
+
migrations?: string
|
|
148
|
+
migrationLocks?: string
|
|
149
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { env } from "@stacksjs/env";
|
|
2
|
+
export const driverDefaults = {
|
|
3
|
+
sqlite: {
|
|
4
|
+
database: "database/stacks.sqlite",
|
|
5
|
+
prefix: ""
|
|
6
|
+
},
|
|
7
|
+
mysql: {
|
|
8
|
+
name: "stacks",
|
|
9
|
+
host: "127.0.0.1",
|
|
10
|
+
port: 3306,
|
|
11
|
+
username: "root",
|
|
12
|
+
password: "",
|
|
13
|
+
prefix: "",
|
|
14
|
+
charset: "utf8mb4",
|
|
15
|
+
collation: "utf8mb4_unicode_ci"
|
|
16
|
+
},
|
|
17
|
+
singlestore: {
|
|
18
|
+
name: "stacks",
|
|
19
|
+
host: "127.0.0.1",
|
|
20
|
+
port: 3306,
|
|
21
|
+
username: "root",
|
|
22
|
+
password: "",
|
|
23
|
+
prefix: "",
|
|
24
|
+
charset: "utf8mb4",
|
|
25
|
+
ssl: !1
|
|
26
|
+
},
|
|
27
|
+
postgres: {
|
|
28
|
+
name: "stacks",
|
|
29
|
+
host: "127.0.0.1",
|
|
30
|
+
port: 5432,
|
|
31
|
+
username: "postgres",
|
|
32
|
+
password: "",
|
|
33
|
+
prefix: "",
|
|
34
|
+
schema: "public"
|
|
35
|
+
},
|
|
36
|
+
browser: {}
|
|
37
|
+
};
|
|
38
|
+
export function getConnectionString(driver, config) {
|
|
39
|
+
switch (driver) {
|
|
40
|
+
case "sqlite": {
|
|
41
|
+
const sqliteConfig = config;
|
|
42
|
+
if (sqliteConfig.database === ":memory:")
|
|
43
|
+
return ":memory:";
|
|
44
|
+
return `sqlite://${sqliteConfig.database}`;
|
|
45
|
+
}
|
|
46
|
+
case "mysql": {
|
|
47
|
+
const mysqlConfig = config, { name, host = "127.0.0.1", port = 3306, username = "root", password = "" } = mysqlConfig;
|
|
48
|
+
return `mysql://${username}:${password}@${host}:${port}/${name}`;
|
|
49
|
+
}
|
|
50
|
+
case "singlestore": {
|
|
51
|
+
const ssConfig = config, { name, host = "127.0.0.1", port = 3306, username = "root", password = "" } = ssConfig;
|
|
52
|
+
return `mysql://${username}:${password}@${host}:${port}/${name}`;
|
|
53
|
+
}
|
|
54
|
+
case "postgres": {
|
|
55
|
+
const pgConfig = config, { name, host = "127.0.0.1", port = 5432, username = "postgres", password = "" } = pgConfig;
|
|
56
|
+
return `postgres://${username}:${password}@${host}:${port}/${name}`;
|
|
57
|
+
}
|
|
58
|
+
default:
|
|
59
|
+
throw Error(`Unsupported driver: ${driver}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function validateDriverConfig(driver, config) {
|
|
63
|
+
const errors = [];
|
|
64
|
+
switch (driver) {
|
|
65
|
+
case "sqlite": {
|
|
66
|
+
if (!config.database)
|
|
67
|
+
errors.push("SQLite requires a database path");
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case "mysql": {
|
|
71
|
+
if (!config.name)
|
|
72
|
+
errors.push("MySQL requires a database name");
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case "singlestore": {
|
|
76
|
+
if (!config.name)
|
|
77
|
+
errors.push("SingleStore requires a database name");
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case "postgres": {
|
|
81
|
+
if (!config.name)
|
|
82
|
+
errors.push("PostgreSQL requires a database name");
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
default:
|
|
86
|
+
errors.push(`Unsupported driver: ${driver}`);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
valid: errors.length === 0,
|
|
90
|
+
errors
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export function mergeWithDefaults(driver, config) {
|
|
94
|
+
return { ...driverDefaults[driver], ...config };
|
|
95
|
+
}
|
|
96
|
+
export function getConfigFromEnv(driver) {
|
|
97
|
+
switch (driver) {
|
|
98
|
+
case "sqlite":
|
|
99
|
+
return {
|
|
100
|
+
database: env.DB_DATABASE || "database/stacks.sqlite",
|
|
101
|
+
prefix: env.DB_PREFIX || ""
|
|
102
|
+
};
|
|
103
|
+
case "mysql":
|
|
104
|
+
return {
|
|
105
|
+
name: env.DB_DATABASE || "stacks",
|
|
106
|
+
host: env.DB_HOST || "127.0.0.1",
|
|
107
|
+
port: env.DB_PORT ?? 3306,
|
|
108
|
+
username: env.DB_USERNAME || "root",
|
|
109
|
+
password: env.DB_PASSWORD || "",
|
|
110
|
+
prefix: env.DB_PREFIX || ""
|
|
111
|
+
};
|
|
112
|
+
case "singlestore":
|
|
113
|
+
return {
|
|
114
|
+
name: env.DB_DATABASE || "stacks",
|
|
115
|
+
host: env.DB_HOST || "127.0.0.1",
|
|
116
|
+
port: env.DB_PORT ?? 3306,
|
|
117
|
+
username: env.DB_USERNAME || "root",
|
|
118
|
+
password: env.DB_PASSWORD || "",
|
|
119
|
+
prefix: env.DB_PREFIX || "",
|
|
120
|
+
ssl: env.DB_SSL === "true" || env.DB_SSL === "1"
|
|
121
|
+
};
|
|
122
|
+
case "postgres":
|
|
123
|
+
return {
|
|
124
|
+
name: env.DB_DATABASE || "stacks",
|
|
125
|
+
host: env.DB_HOST || "127.0.0.1",
|
|
126
|
+
port: env.DB_PORT ?? 5432,
|
|
127
|
+
username: env.DB_USERNAME || "postgres",
|
|
128
|
+
password: env.DB_PASSWORD || "",
|
|
129
|
+
prefix: env.DB_PREFIX || "",
|
|
130
|
+
schema: env.DB_SCHEMA || "public"
|
|
131
|
+
};
|
|
132
|
+
default:
|
|
133
|
+
throw Error(`Unsupported driver: ${driver}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
export function detectDriver() {
|
|
137
|
+
if (env.DB_CONNECTION)
|
|
138
|
+
return env.DB_CONNECTION;
|
|
139
|
+
if (env.DATABASE_URL?.startsWith("postgres"))
|
|
140
|
+
return "postgres";
|
|
141
|
+
if (env.DATABASE_URL?.startsWith("mysql"))
|
|
142
|
+
return "mysql";
|
|
143
|
+
return "sqlite";
|
|
144
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { log } from "@stacksjs/logging";
|
|
2
|
+
function italic(str) {
|
|
3
|
+
return `\x1B[3m${str}\x1B[23m`;
|
|
4
|
+
}
|
|
5
|
+
import { path } from "@stacksjs/path";
|
|
6
|
+
import { hasMigrationBeenCreated } from "../helpers";
|
|
7
|
+
export async function createPasswordResetsTable() {
|
|
8
|
+
if (await hasMigrationBeenCreated("password_resets"))
|
|
9
|
+
return;
|
|
10
|
+
let migrationContent = `import type { Database } from '@stacksjs/database'
|
|
11
|
+
`;
|
|
12
|
+
migrationContent += `import { sql } from '@stacksjs/database'
|
|
13
|
+
|
|
14
|
+
`;
|
|
15
|
+
migrationContent += `export async function up(db: Database<any>) {
|
|
16
|
+
`;
|
|
17
|
+
migrationContent += ` await db.schema
|
|
18
|
+
`;
|
|
19
|
+
migrationContent += ` .createTable('password_resets')
|
|
20
|
+
`;
|
|
21
|
+
migrationContent += ` .addColumn('email', 'varchar(255)', col => col.notNull())
|
|
22
|
+
`;
|
|
23
|
+
migrationContent += ` .addColumn('token', 'varchar(255)', col => col.notNull())
|
|
24
|
+
`;
|
|
25
|
+
migrationContent += ` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))
|
|
26
|
+
`;
|
|
27
|
+
migrationContent += ` .execute()
|
|
28
|
+
|
|
29
|
+
`;
|
|
30
|
+
migrationContent += ` await db.schema
|
|
31
|
+
`;
|
|
32
|
+
migrationContent += ` .createIndex('password_resets_email_index')
|
|
33
|
+
`;
|
|
34
|
+
migrationContent += ` .on('password_resets')
|
|
35
|
+
`;
|
|
36
|
+
migrationContent += ` .column('email')
|
|
37
|
+
`;
|
|
38
|
+
migrationContent += ` .execute()
|
|
39
|
+
|
|
40
|
+
`;
|
|
41
|
+
migrationContent += ` await db.schema
|
|
42
|
+
`;
|
|
43
|
+
migrationContent += ` .createIndex('password_resets_token_index')
|
|
44
|
+
`;
|
|
45
|
+
migrationContent += ` .on('password_resets')
|
|
46
|
+
`;
|
|
47
|
+
migrationContent += ` .column('token')
|
|
48
|
+
`;
|
|
49
|
+
migrationContent += ` .execute()
|
|
50
|
+
`;
|
|
51
|
+
migrationContent += `}
|
|
52
|
+
`;
|
|
53
|
+
const migrationFileName = `${new Date().getTime().toString()}-create-password-resets-table.ts`, migrationFilePath = path.userMigrationsPath(migrationFileName);
|
|
54
|
+
await Bun.write(migrationFilePath, migrationContent);
|
|
55
|
+
log.success(`Created migration: ${italic(migrationFileName)}`);
|
|
56
|
+
}
|
|
57
|
+
export async function createPostgresPasswordResetsTable() {
|
|
58
|
+
if (await hasMigrationBeenCreated("password_resets"))
|
|
59
|
+
return;
|
|
60
|
+
let migrationContent = `import type { Database } from '@stacksjs/database'
|
|
61
|
+
`;
|
|
62
|
+
migrationContent += `import { sql } from '@stacksjs/database'
|
|
63
|
+
|
|
64
|
+
`;
|
|
65
|
+
migrationContent += `export async function up(db: Database<any>) {
|
|
66
|
+
`;
|
|
67
|
+
migrationContent += ` await db.schema
|
|
68
|
+
`;
|
|
69
|
+
migrationContent += ` .createTable('password_resets')
|
|
70
|
+
`;
|
|
71
|
+
migrationContent += ` .addColumn('email', 'varchar(255)', col => col.notNull())
|
|
72
|
+
`;
|
|
73
|
+
migrationContent += ` .addColumn('token', 'varchar(255)', col => col.notNull())
|
|
74
|
+
`;
|
|
75
|
+
migrationContent += ` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))
|
|
76
|
+
`;
|
|
77
|
+
migrationContent += ` .execute()
|
|
78
|
+
|
|
79
|
+
`;
|
|
80
|
+
migrationContent += ` await db.schema
|
|
81
|
+
`;
|
|
82
|
+
migrationContent += ` .createIndex('password_resets_email_index')
|
|
83
|
+
`;
|
|
84
|
+
migrationContent += ` .on('password_resets')
|
|
85
|
+
`;
|
|
86
|
+
migrationContent += ` .column('email')
|
|
87
|
+
`;
|
|
88
|
+
migrationContent += ` .execute()
|
|
89
|
+
|
|
90
|
+
`;
|
|
91
|
+
migrationContent += ` await db.schema
|
|
92
|
+
`;
|
|
93
|
+
migrationContent += ` .createIndex('password_resets_token_index')
|
|
94
|
+
`;
|
|
95
|
+
migrationContent += ` .on('password_resets')
|
|
96
|
+
`;
|
|
97
|
+
migrationContent += ` .column('token')
|
|
98
|
+
`;
|
|
99
|
+
migrationContent += ` .execute()
|
|
100
|
+
`;
|
|
101
|
+
migrationContent += `}
|
|
102
|
+
`;
|
|
103
|
+
const migrationFileName = `${new Date().getTime().toString()}-create-password-resets-table.ts`, migrationFilePath = path.userMigrationsPath(migrationFileName);
|
|
104
|
+
await Bun.write(migrationFilePath, migrationContent);
|
|
105
|
+
log.success(`Created migration: ${italic(migrationFileName)}`);
|
|
106
|
+
}
|