@stacksjs/database 0.70.258 → 0.70.260

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.
Files changed (50) hide show
  1. package/dist/auth-tables.js +18 -137
  2. package/dist/column.js +1 -26
  3. package/dist/custom/audits.js +20 -54
  4. package/dist/custom/errors.js +16 -46
  5. package/dist/custom/index.js +1 -3
  6. package/dist/custom/jobs.js +13 -137
  7. package/dist/database.js +1 -181
  8. package/dist/datetime-columns.js +2 -79
  9. package/dist/ddl-constraints.js +7 -111
  10. package/dist/defaults.js +1 -48
  11. package/dist/dialect.js +1 -79
  12. package/dist/driver-config.js +1 -172
  13. package/dist/drivers/defaults/index.js +1 -1
  14. package/dist/drivers/defaults/traits.js +1 -29
  15. package/dist/drivers/dynamodb.js +1 -607
  16. package/dist/drivers/helpers.js +1 -206
  17. package/dist/drivers/index.js +1 -9
  18. package/dist/drivers/mysql.js +58 -299
  19. package/dist/drivers/postgres.js +78 -368
  20. package/dist/drivers/sqlite.js +61 -379
  21. package/dist/ensure-database.js +1 -145
  22. package/dist/fk-audit.js +3 -187
  23. package/dist/index.js +1 -64
  24. package/dist/managed-columns.js +1 -59
  25. package/dist/migration-dialect.js +4 -107
  26. package/dist/migration-ledger.js +1 -382
  27. package/dist/migration-lock.js +1 -143
  28. package/dist/migrations.js +15 -1118
  29. package/dist/model-sources.js +1 -76
  30. package/dist/notification-tables.js +4 -49
  31. package/dist/query-logger.js +2 -241
  32. package/dist/query-parser.js +1 -93
  33. package/dist/rbac-tables.js +6 -61
  34. package/dist/relation-columns.js +1 -66
  35. package/dist/replicas.js +1 -74
  36. package/dist/safe-migrations.js +2 -52
  37. package/dist/schema.js +1 -10
  38. package/dist/seeder.js +1 -457
  39. package/dist/sql-helpers.js +1 -50
  40. package/dist/table.js +1 -26
  41. package/dist/tools/setup.js +1 -6
  42. package/dist/trait-tables.js +8 -153
  43. package/dist/transaction-context.js +1 -62
  44. package/dist/types.js +1 -98
  45. package/dist/unique-audit.js +3 -155
  46. package/dist/utils.js +1 -285
  47. package/dist/uuid-columns.js +1 -68
  48. package/dist/validators.js +1 -122
  49. package/dist/vschema.js +2 -121
  50. package/package.json +20 -13
@@ -1,57 +1,4 @@
1
- import process from "node:process";
2
- import { randomBytes } from "node:crypto";
3
- import { log } from "@stacksjs/logging";
4
- import { env as envVars } from "@stacksjs/env";
5
- import { db } from "./utils";
6
- import { sqlHelpers } from "./sql-helpers";
7
- function getDbDriver() {
8
- return envVars.DB_CONNECTION || "sqlite";
9
- }
10
- export function usersEmailVerifiedAtSql(sql) {
11
- return `ALTER TABLE users ADD COLUMN email_verified_at ${sql.nullableTimestamp}`;
12
- }
13
- export function usersPasswordChangedAtSql(sql) {
14
- return `ALTER TABLE users ADD COLUMN password_changed_at ${sql.nullableTimestamp}`;
15
- }
16
- export function usersTwoFactorColumnsSql(sql) {
17
- return [
18
- "ALTER TABLE users ADD COLUMN two_factor_secret VARCHAR(255)",
19
- `ALTER TABLE users ADD COLUMN two_factor_enabled BOOLEAN NOT NULL DEFAULT ${sql.boolFalse}`,
20
- "ALTER TABLE users ADD COLUMN two_factor_last_used_step BIGINT"
21
- ];
22
- }
23
- export function usersStripeIdSql() {
24
- return "ALTER TABLE users ADD COLUMN stripe_id VARCHAR(255)";
25
- }
26
- export async function ensureUsersAuthColumns(sql, options = {}) {
27
- const alters = [
28
- usersEmailVerifiedAtSql(sql),
29
- usersPasswordChangedAtSql(sql),
30
- ...usersTwoFactorColumnsSql(sql),
31
- usersStripeIdSql()
32
- ];
33
- for (const alterSql of alters)
34
- try {
35
- await db.unsafe(alterSql).execute();
36
- } catch {
37
- if (options.verbose)
38
- log.debug(`[auth-tables] Skipped (already applied or users missing): ${alterSql}`);
39
- }
40
- try {
41
- await db.unsafe("CREATE UNIQUE INDEX IF NOT EXISTS idx_users_stripe_id ON users(stripe_id)").execute();
42
- } catch {
43
- if (options.verbose)
44
- log.debug("[auth-tables] Skipped users.stripe_id unique index (already applied or users missing)");
45
- }
46
- }
47
- export async function migrateAuthTables(options = {}) {
48
- const dbDriver = getDbDriver(), sql = sqlHelpers(dbDriver), { isPostgres, boolTrue, now, pkColumn, nullableTimestamp, datetime } = sql;
49
- if (options.verbose)
50
- log.info(`Creating auth tables for ${dbDriver}...`);
51
- try {
52
- if (options.verbose)
53
- log.info("Creating oauth_clients table...");
54
- await db.unsafe(`
1
+ import process from"node:process";import{randomBytes}from"node:crypto";import{log}from"@stacksjs/logging";import{env as envVars}from"@stacksjs/env";import{db}from"./utils";import{sqlHelpers}from"./sql-helpers";function getDbDriver(){return envVars.DB_CONNECTION||"sqlite"}export function usersEmailVerifiedAtSql(sql){return`ALTER TABLE users ADD COLUMN email_verified_at ${sql.nullableTimestamp}`}export function usersPasswordChangedAtSql(sql){return`ALTER TABLE users ADD COLUMN password_changed_at ${sql.nullableTimestamp}`}export function usersTwoFactorColumnsSql(sql){return["ALTER TABLE users ADD COLUMN two_factor_secret VARCHAR(255)",`ALTER TABLE users ADD COLUMN two_factor_enabled BOOLEAN NOT NULL DEFAULT ${sql.boolFalse}`,"ALTER TABLE users ADD COLUMN two_factor_last_used_step BIGINT"]}export function usersStripeIdSql(){return"ALTER TABLE users ADD COLUMN stripe_id VARCHAR(255)"}export async function ensureUsersAuthColumns(sql,options={}){const alters=[usersEmailVerifiedAtSql(sql),usersPasswordChangedAtSql(sql),...usersTwoFactorColumnsSql(sql),usersStripeIdSql()];for(const alterSql of alters)try{await db.unsafe(alterSql).execute()}catch{if(options.verbose)log.debug(`[auth-tables] Skipped (already applied or users missing): ${alterSql}`)}try{await db.unsafe("CREATE UNIQUE INDEX IF NOT EXISTS idx_users_stripe_id ON users(stripe_id)").execute()}catch{if(options.verbose)log.debug("[auth-tables] Skipped users.stripe_id unique index (already applied or users missing)")}}export async function migrateAuthTables(options={}){const dbDriver=getDbDriver(),sql=sqlHelpers(dbDriver),{isPostgres,boolTrue,now,pkColumn,nullableTimestamp,datetime}=sql;if(options.verbose)log.info(`Creating auth tables for ${dbDriver}...`);try{if(options.verbose)log.info("Creating oauth_clients table...");await db.unsafe(`
55
2
  CREATE TABLE IF NOT EXISTS oauth_clients (
56
3
  ${pkColumn},
57
4
  name VARCHAR(255) NOT NULL,
@@ -64,10 +11,7 @@ export async function migrateAuthTables(options = {}) {
64
11
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP,
65
12
  updated_at ${nullableTimestamp}
66
13
  )
67
- `).execute();
68
- if (options.verbose)
69
- log.info("Creating oauth_access_tokens table...");
70
- await db.unsafe(`
14
+ `).execute();if(options.verbose)log.info("Creating oauth_access_tokens table...");await db.unsafe(`
71
15
  CREATE TABLE IF NOT EXISTS oauth_access_tokens (
72
16
  ${pkColumn},
73
17
  user_id INTEGER NOT NULL,
@@ -80,11 +24,7 @@ export async function migrateAuthTables(options = {}) {
80
24
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP,
81
25
  updated_at ${nullableTimestamp}
82
26
  )
83
- `).execute();
84
- await createTokenIndex("idx_oauth_access_tokens_token", "oauth_access_tokens", "token");
85
- if (options.verbose)
86
- log.info("Creating oauth_refresh_tokens table...");
87
- await db.unsafe(`
27
+ `).execute();await createTokenIndex("idx_oauth_access_tokens_token","oauth_access_tokens","token");if(options.verbose)log.info("Creating oauth_refresh_tokens table...");await db.unsafe(`
88
28
  CREATE TABLE IF NOT EXISTS oauth_refresh_tokens (
89
29
  ${pkColumn},
90
30
  access_token_id INTEGER NOT NULL,
@@ -93,26 +33,16 @@ export async function migrateAuthTables(options = {}) {
93
33
  expires_at ${nullableTimestamp},
94
34
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP
95
35
  )
96
- `).execute();
97
- await createTokenIndex("idx_oauth_refresh_tokens_token", "oauth_refresh_tokens", "token");
98
- if (options.verbose)
99
- log.info("Creating password_resets table...");
100
- await db.unsafe(`
36
+ `).execute();await createTokenIndex("idx_oauth_refresh_tokens_token","oauth_refresh_tokens","token");if(options.verbose)log.info("Creating password_resets table...");await db.unsafe(`
101
37
  CREATE TABLE IF NOT EXISTS password_resets (
102
38
  ${pkColumn},
103
39
  email VARCHAR(255) NOT NULL,
104
40
  token VARCHAR(255) NOT NULL,
105
41
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP
106
42
  )
107
- `).execute();
108
- try {
109
- await db.unsafe(`
43
+ `).execute();try{await db.unsafe(`
110
44
  CREATE INDEX IF NOT EXISTS idx_password_resets_email ON password_resets(email)
111
- `).execute();
112
- } catch {}
113
- if (options.verbose)
114
- log.info("Creating passkeys table...");
115
- await db.unsafe(`
45
+ `).execute()}catch{}if(options.verbose)log.info("Creating passkeys table...");await db.unsafe(`
116
46
  CREATE TABLE IF NOT EXISTS passkeys (
117
47
  id VARCHAR(255) PRIMARY KEY,
118
48
  cred_public_key TEXT NOT NULL,
@@ -127,15 +57,9 @@ export async function migrateAuthTables(options = {}) {
127
57
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP,
128
58
  last_used_at ${nullableTimestamp}
129
59
  )
130
- `).execute();
131
- try {
132
- await db.unsafe(`
60
+ `).execute();try{await db.unsafe(`
133
61
  CREATE INDEX IF NOT EXISTS idx_passkeys_user_id ON passkeys(user_id)
134
- `).execute();
135
- } catch {}
136
- if (options.verbose)
137
- log.info("Creating webauthn_challenges table...");
138
- await db.unsafe(`
62
+ `).execute()}catch{}if(options.verbose)log.info("Creating webauthn_challenges table...");await db.unsafe(`
139
63
  CREATE TABLE IF NOT EXISTS webauthn_challenges (
140
64
  ${pkColumn},
141
65
  user_id INTEGER NOT NULL,
@@ -144,77 +68,34 @@ export async function migrateAuthTables(options = {}) {
144
68
  expires_at ${datetime} NOT NULL,
145
69
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP
146
70
  )
147
- `).execute();
148
- try {
149
- await db.unsafe(`
71
+ `).execute();try{await db.unsafe(`
150
72
  CREATE UNIQUE INDEX IF NOT EXISTS idx_webauthn_challenges_user_purpose ON webauthn_challenges(user_id, purpose)
151
- `).execute();
152
- } catch {}
153
- if (options.verbose)
154
- log.info("Creating two_factor_challenges table...");
155
- await db.unsafe(`
73
+ `).execute()}catch{}if(options.verbose)log.info("Creating two_factor_challenges table...");await db.unsafe(`
156
74
  CREATE TABLE IF NOT EXISTS two_factor_challenges (
157
75
  id VARCHAR(255) PRIMARY KEY,
158
76
  user_id INTEGER NOT NULL,
159
77
  expires_at ${datetime} NOT NULL,
160
78
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP
161
79
  )
162
- `).execute();
163
- try {
164
- await db.unsafe(`
80
+ `).execute();try{await db.unsafe(`
165
81
  CREATE INDEX IF NOT EXISTS idx_two_factor_challenges_user_id ON two_factor_challenges(user_id)
166
- `).execute();
167
- } catch {}
168
- if (options.verbose)
169
- log.info("Creating two_factor_pending_secrets table...");
170
- await db.unsafe(`
82
+ `).execute()}catch{}if(options.verbose)log.info("Creating two_factor_pending_secrets table...");await db.unsafe(`
171
83
  CREATE TABLE IF NOT EXISTS two_factor_pending_secrets (
172
84
  user_id INTEGER PRIMARY KEY,
173
85
  secret VARCHAR(255) NOT NULL,
174
86
  expires_at ${datetime} NOT NULL,
175
87
  created_at ${datetime} DEFAULT CURRENT_TIMESTAMP
176
88
  )
177
- `).execute();
178
- if (options.verbose)
179
- log.info("Ensuring users auth columns exist (users may not exist yet on a fresh install \u2014 see ensureUsersAuthColumns)...");
180
- await ensureUsersAuthColumns(sql, options);
181
- if (options.verbose)
182
- log.info("Ensuring personal access client exists...");
183
- if ((await db.unsafe(`
89
+ `).execute();if(options.verbose)log.info("Ensuring users auth columns exist (users may not exist yet on a fresh install \u2014 see ensureUsersAuthColumns)...");await ensureUsersAuthColumns(sql,options);if(options.verbose)log.info("Ensuring personal access client exists...");if((await db.unsafe(`
184
90
  SELECT id FROM oauth_clients WHERE personal_access_client = ${boolTrue} LIMIT 1
185
- `).execute())?.length === 0) {
186
- const secret = randomBytes(40).toString("hex");
187
- if (isPostgres)
188
- await db.unsafe(`
91
+ `).execute())?.length===0){const secret=randomBytes(40).toString("hex");if(isPostgres)await db.unsafe(`
189
92
  INSERT INTO oauth_clients (name, secret, provider, redirect, personal_access_client, password_client, revoked, created_at)
190
93
  VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())
191
- `, ["Personal Access Client", secret, "local", "http://localhost", !0, !1, !1]).execute();
192
- else
193
- await db.unsafe(`
94
+ `,["Personal Access Client",secret,"local","http://localhost",!0,!1,!1]).execute();else await db.unsafe(`
194
95
  INSERT INTO oauth_clients (name, secret, provider, redirect, personal_access_client, password_client, revoked, created_at)
195
96
  VALUES (?, ?, ?, ?, ?, ?, ?, ${now})
196
- `, ["Personal Access Client", secret, "local", "http://localhost", 1, 0, 0]).execute();
197
- if (options.verbose)
198
- log.success("Personal access client created");
199
- }
200
- log.debug("Auth tables migrated successfully");
201
- return { success: !0 };
202
- } catch (error) {
203
- const errorMessage = error instanceof Error ? error.message : String(error);
204
- log.error("Failed to migrate auth tables:", errorMessage);
205
- return { success: !1, error: errorMessage };
206
- }
207
- }
208
- async function createTokenIndex(indexName, tableName, column) {
209
- try {
210
- await db.unsafe(`
97
+ `,["Personal Access Client",secret,"local","http://localhost",1,0,0]).execute();if(options.verbose)log.success("Personal access client created")}log.debug("Auth tables migrated successfully");return{success:!0}}catch(error){const errorMessage=error instanceof Error?error.message:String(error);log.error("Failed to migrate auth tables:",errorMessage);return{success:!1,error:errorMessage}}}async function createTokenIndex(indexName,tableName,column){try{await db.unsafe(`
211
98
  CREATE INDEX IF NOT EXISTS ${indexName} ON ${tableName}(${column}(255))
212
- `).execute();
213
- } catch {
214
- try {
215
- await db.unsafe(`
99
+ `).execute()}catch{try{await db.unsafe(`
216
100
  CREATE INDEX IF NOT EXISTS ${indexName} ON ${tableName}(${column})
217
- `).execute();
218
- } catch {}
219
- }
220
- }
101
+ `).execute()}catch{}}}
package/dist/column.js CHANGED
@@ -1,26 +1 @@
1
- export class Column {
2
- name;
3
- type;
4
- options;
5
- constructor(name, type, options = {}) {
6
- this.name = name;
7
- this.type = type;
8
- this.options = options;
9
- }
10
- notNullable() {
11
- this.options.notNull = !0;
12
- return this;
13
- }
14
- defaultTo(value) {
15
- this.options.default = value;
16
- return this;
17
- }
18
- primary() {
19
- this.options.primaryKey = !0;
20
- return this;
21
- }
22
- autoIncrement() {
23
- this.options.autoIncrement = !0;
24
- return this;
25
- }
26
- }
1
+ export class Column{name;type;options;constructor(name,type,options={}){this.name=name;this.type=type;this.options=options}notNullable(){this.options.notNull=!0;return this}defaultTo(value){this.options.default=value;return this}primary(){this.options.primaryKey=!0;return this}autoIncrement(){this.options.autoIncrement=!0;return this}}
@@ -1,57 +1,23 @@
1
- import { log } from "@stacksjs/logging";
2
- import { database } from "@stacksjs/config";
3
- import { path } from "@stacksjs/path";
4
- import { hasTableBeenMigrated } from "../drivers/helpers";
5
- export async function createModelAuditsTable() {
6
- if (!["sqlite", "mysql"].includes(getDriver()))
7
- return;
8
- if (await hasTableBeenMigrated("model_audits"))
9
- return;
10
- let migrationContent = `import type { Database } from '@stacksjs/database'
1
+ import{log}from"@stacksjs/logging";import{database}from"@stacksjs/config";import{path}from"@stacksjs/path";import{hasTableBeenMigrated}from"../drivers/helpers";export async function createModelAuditsTable(){if(!["sqlite","mysql"].includes(getDriver()))return;if(await hasTableBeenMigrated("model_audits"))return;let migrationContent=`import type { Database } from '@stacksjs/database'
11
2
  import { sql } from '@stacksjs/database'
12
3
 
13
- `;
14
- migrationContent += `export async function up(db: Database<any>) {
15
- `;
16
- migrationContent += ` await db.schema
17
- `;
18
- migrationContent += ` .createTable('model_audits')
19
- `;
20
- migrationContent += ` .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
21
- `;
22
- migrationContent += ` .addColumn('auditable_type', 'varchar(255)', col => col.notNull())
23
- `;
24
- migrationContent += ` .addColumn('auditable_id', 'varchar(255)', col => col.notNull())
25
- `;
26
- migrationContent += ` .addColumn('event', 'varchar(32)', col => col.notNull())
27
- `;
28
- migrationContent += ` .addColumn('old_values', 'text')
29
- `;
30
- migrationContent += ` .addColumn('new_values', 'text')
31
- `;
32
- migrationContent += ` .addColumn('user_id', 'integer')
33
- `;
34
- migrationContent += ` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))
35
- `;
36
- migrationContent += ` .execute()
4
+ `;migrationContent+=`export async function up(db: Database<any>) {
5
+ `;migrationContent+=` await db.schema
6
+ `;migrationContent+=` .createTable('model_audits')
7
+ `;migrationContent+=` .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
8
+ `;migrationContent+=` .addColumn('auditable_type', 'varchar(255)', col => col.notNull())
9
+ `;migrationContent+=` .addColumn('auditable_id', 'varchar(255)', col => col.notNull())
10
+ `;migrationContent+=` .addColumn('event', 'varchar(32)', col => col.notNull())
11
+ `;migrationContent+=` .addColumn('old_values', 'text')
12
+ `;migrationContent+=` .addColumn('new_values', 'text')
13
+ `;migrationContent+=` .addColumn('user_id', 'integer')
14
+ `;migrationContent+=` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))
15
+ `;migrationContent+=` .execute()
37
16
 
38
- `;
39
- migrationContent += ` await db.schema
40
- `;
41
- migrationContent += ` .createIndex('idx_model_audits_lookup')
42
- `;
43
- migrationContent += ` .on('model_audits')
44
- `;
45
- migrationContent += ` .columns(['auditable_type', 'auditable_id', 'created_at'])
46
- `;
47
- migrationContent += ` .execute()
48
- `;
49
- migrationContent += `}
50
- `;
51
- const migrationFileName = `${new Date().getTime().toString()}-create-model-audits-table.ts`, migrationFilePath = path.userMigrationsPath(migrationFileName);
52
- await Bun.write(migrationFilePath, migrationContent);
53
- log.success("Created model_audits table migration");
54
- }
55
- function getDriver() {
56
- return database.default || "";
57
- }
17
+ `;migrationContent+=` await db.schema
18
+ `;migrationContent+=` .createIndex('idx_model_audits_lookup')
19
+ `;migrationContent+=` .on('model_audits')
20
+ `;migrationContent+=` .columns(['auditable_type', 'auditable_id', 'created_at'])
21
+ `;migrationContent+=` .execute()
22
+ `;migrationContent+=`}
23
+ `;const migrationFileName=`${new Date().getTime().toString()}-create-model-audits-table.ts`,migrationFilePath=path.userMigrationsPath(migrationFileName);await Bun.write(migrationFilePath,migrationContent);log.success("Created model_audits table migration")}function getDriver(){return database.default||""}
@@ -1,48 +1,18 @@
1
- import { log } from "@stacksjs/logging";
2
- import { database } from "@stacksjs/config";
3
- import { path } from "@stacksjs/path";
4
- import { hasTableBeenMigrated } from "../drivers/helpers";
5
- export async function createErrorsTable() {
6
- if (["sqlite", "mysql"].includes(getDriver())) {
7
- if (await hasTableBeenMigrated("errors"))
8
- return;
9
- let migrationContent = `import type { Database } from '@stacksjs/database'
1
+ import{log}from"@stacksjs/logging";import{database}from"@stacksjs/config";import{path}from"@stacksjs/path";import{hasTableBeenMigrated}from"../drivers/helpers";export async function createErrorsTable(){if(["sqlite","mysql"].includes(getDriver())){if(await hasTableBeenMigrated("errors"))return;let migrationContent=`import type { Database } from '@stacksjs/database'
10
2
  import { sql } from '@stacksjs/database'
11
3
 
12
- `;
13
- migrationContent += `export async function up(db: Database<any>) {
14
- `;
15
- migrationContent += ` await db.schema
16
- `;
17
- migrationContent += ` .createTable('errors')
18
- `;
19
- migrationContent += ` .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
20
- `;
21
- migrationContent += ` .addColumn('type', 'varchar(255)', col => col.notNull())
22
- `;
23
- migrationContent += ` .addColumn('message', 'text', col => col.notNull())
24
- `;
25
- migrationContent += ` .addColumn('stack', 'text')
26
- `;
27
- migrationContent += ` .addColumn('status', 'integer', col => col.notNull().defaultTo(0))
28
- `;
29
- migrationContent += ` .addColumn('user_id', 'integer')
30
- `;
31
- migrationContent += ` .addColumn('additional_info', 'text')
32
- `;
33
- migrationContent += ` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))
34
- `;
35
- migrationContent += ` .addColumn('updated_at', 'timestamp')
36
- `;
37
- migrationContent += ` .execute()
38
- `;
39
- migrationContent += `}
40
- `;
41
- const migrationFileName = `${new Date().getTime().toString()}-create-errors-table.ts`, migrationFilePath = path.userMigrationsPath(migrationFileName);
42
- await Bun.write(migrationFilePath, migrationContent);
43
- log.success("Created errors table");
44
- }
45
- }
46
- function getDriver() {
47
- return database.default || "";
48
- }
4
+ `;migrationContent+=`export async function up(db: Database<any>) {
5
+ `;migrationContent+=` await db.schema
6
+ `;migrationContent+=` .createTable('errors')
7
+ `;migrationContent+=` .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
8
+ `;migrationContent+=` .addColumn('type', 'varchar(255)', col => col.notNull())
9
+ `;migrationContent+=` .addColumn('message', 'text', col => col.notNull())
10
+ `;migrationContent+=` .addColumn('stack', 'text')
11
+ `;migrationContent+=` .addColumn('status', 'integer', col => col.notNull().defaultTo(0))
12
+ `;migrationContent+=` .addColumn('user_id', 'integer')
13
+ `;migrationContent+=` .addColumn('additional_info', 'text')
14
+ `;migrationContent+=` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))
15
+ `;migrationContent+=` .addColumn('updated_at', 'timestamp')
16
+ `;migrationContent+=` .execute()
17
+ `;migrationContent+=`}
18
+ `;const migrationFileName=`${new Date().getTime().toString()}-create-errors-table.ts`,migrationFilePath=path.userMigrationsPath(migrationFileName);await Bun.write(migrationFilePath,migrationContent);log.success("Created errors table")}}function getDriver(){return database.default||""}
@@ -1,3 +1 @@
1
- export * from "./audits";
2
- export * from "./errors";
3
- export * from "./jobs";
1
+ export*from"./audits";export*from"./errors";export*from"./jobs";
@@ -1,73 +1,4 @@
1
- import { err, ok } from "@stacksjs/error-handling";
2
- import { existsSync, readdirSync, writeFileSync, mkdirSync } from "node:fs";
3
- import { join } from "node:path";
4
- import process from "node:process";
5
- import Database from "bun:sqlite";
6
- import { env as envVars } from "@stacksjs/env";
7
- function getDriver() {
8
- return envVars.DB_CONNECTION || "sqlite";
9
- }
10
- function getMigrationsPath() {
11
- return join(process.cwd(), "database", "migrations");
12
- }
13
- function hasJobsMigrationBeenCreated() {
14
- try {
15
- const migrationsPath = getMigrationsPath();
16
- if (!existsSync(migrationsPath))
17
- return !1;
18
- return readdirSync(migrationsPath).some((file) => file.includes("create-jobs-table"));
19
- } catch {
20
- return !1;
21
- }
22
- }
23
- async function jobBatchesTableExists() {
24
- const sqlitePath = getDatabasePath();
25
- if (existsSync(sqlitePath))
26
- try {
27
- const sqlite = new Database(sqlitePath), result = sqlite.query("SELECT name FROM sqlite_master WHERE type='table' AND name='job_batches'").get();
28
- sqlite.close();
29
- return result !== null;
30
- } catch {}
31
- if (getDriver() !== "sqlite")
32
- try {
33
- const { db } = await import("../utils");
34
- await db.selectFrom("job_batches").select("id").limit(1).execute();
35
- return !0;
36
- } catch {
37
- return !1;
38
- }
39
- return !1;
40
- }
41
- function getDatabasePath() {
42
- const appRoot = envVars.APP_ROOT || process.cwd();
43
- return join(appRoot, "database", "stacks.sqlite");
44
- }
45
- async function jobsTableExists() {
46
- const driver = getDriver(), sqlitePath = getDatabasePath();
47
- if (existsSync(sqlitePath))
48
- try {
49
- const sqlite = new Database(sqlitePath), result = sqlite.query("SELECT name FROM sqlite_master WHERE type='table' AND name='jobs'").get();
50
- sqlite.close();
51
- return result !== null;
52
- } catch {}
53
- if (driver !== "sqlite")
54
- try {
55
- const { db } = await import("../utils");
56
- await db.selectFrom("jobs").select("id").limit(1).execute();
57
- return !0;
58
- } catch {
59
- return !1;
60
- }
61
- return !1;
62
- }
63
- export async function createJobsMigration() {
64
- try {
65
- const driver = getDriver();
66
- if (["sqlite", "mysql", "postgres"].includes(driver)) {
67
- if (!hasJobsMigrationBeenCreated()) {
68
- let migrationContent = "";
69
- if (driver === "sqlite")
70
- migrationContent = `-- Create jobs table
1
+ import{err,ok}from"@stacksjs/error-handling";import{existsSync,readdirSync,writeFileSync,mkdirSync}from"node:fs";import{join}from"node:path";import process from"node:process";import Database from"bun:sqlite";import{env as envVars}from"@stacksjs/env";function getDriver(){return envVars.DB_CONNECTION||"sqlite"}function getMigrationsPath(){return join(process.cwd(),"database","migrations")}function hasJobsMigrationBeenCreated(){try{const migrationsPath=getMigrationsPath();if(!existsSync(migrationsPath))return!1;return readdirSync(migrationsPath).some((file)=>file.includes("create-jobs-table"))}catch{return!1}}async function jobBatchesTableExists(){const sqlitePath=getDatabasePath();if(existsSync(sqlitePath))try{const sqlite=new Database(sqlitePath),result=sqlite.query("SELECT name FROM sqlite_master WHERE type='table' AND name='job_batches'").get();sqlite.close();return result!==null}catch{}if(getDriver()!=="sqlite")try{const{db}=await import("../utils");await db.selectFrom("job_batches").select("id").limit(1).execute();return!0}catch{return!1}return!1}function getDatabasePath(){const appRoot=envVars.APP_ROOT||process.cwd();return join(appRoot,"database","stacks.sqlite")}async function jobsTableExists(){const driver=getDriver(),sqlitePath=getDatabasePath();if(existsSync(sqlitePath))try{const sqlite=new Database(sqlitePath),result=sqlite.query("SELECT name FROM sqlite_master WHERE type='table' AND name='jobs'").get();sqlite.close();return result!==null}catch{}if(driver!=="sqlite")try{const{db}=await import("../utils");await db.selectFrom("jobs").select("id").limit(1).execute();return!0}catch{return!1}return!1}export async function createJobsMigration(){try{const driver=getDriver();if(["sqlite","mysql","postgres"].includes(driver)){if(!hasJobsMigrationBeenCreated()){let migrationContent="";if(driver==="sqlite")migrationContent=`-- Create jobs table
71
2
  CREATE TABLE IF NOT EXISTS jobs (
72
3
  id INTEGER PRIMARY KEY AUTOINCREMENT,
73
4
  queue TEXT NOT NULL DEFAULT 'default',
@@ -162,9 +93,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
162
93
  paused_at DATETIME,
163
94
  resume_at DATETIME
164
95
  );
165
- `;
166
- else if (driver === "mysql")
167
- migrationContent = `-- Create jobs table
96
+ `;else if(driver==="mysql")migrationContent=`-- Create jobs table
168
97
  CREATE TABLE IF NOT EXISTS jobs (
169
98
  id INT AUTO_INCREMENT PRIMARY KEY,
170
99
  queue VARCHAR(255) NOT NULL DEFAULT 'default',
@@ -244,9 +173,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
244
173
  paused_at TIMESTAMP NULL,
245
174
  resume_at TIMESTAMP NULL
246
175
  );
247
- `;
248
- else if (driver === "postgres")
249
- migrationContent = `-- Create jobs table
176
+ `;else if(driver==="postgres")migrationContent=`-- Create jobs table
250
177
  CREATE TABLE IF NOT EXISTS jobs (
251
178
  id SERIAL PRIMARY KEY,
252
179
  queue VARCHAR(255) NOT NULL DEFAULT 'default',
@@ -326,21 +253,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
326
253
  paused_at TIMESTAMP,
327
254
  resume_at TIMESTAMP
328
255
  );
329
- `;
330
- const migrationFileName = `${new Date().getTime().toString()}-create-jobs-table.sql`, migrationsPath = getMigrationsPath();
331
- if (!existsSync(migrationsPath))
332
- mkdirSync(migrationsPath, { recursive: !0 });
333
- const migrationFilePath = join(migrationsPath, migrationFileName);
334
- writeFileSync(migrationFilePath, migrationContent);
335
- console.log("\u2713 Created jobs migration file");
336
- } else
337
- console.log("\u2713 Jobs migration file already exists");
338
- if (!await jobsTableExists()) {
339
- console.log(" Running migration...");
340
- const sqlitePath = getDatabasePath();
341
- if (driver === "sqlite" || existsSync(sqlitePath)) {
342
- const sqlite = new Database(sqlitePath);
343
- sqlite.run(`CREATE TABLE IF NOT EXISTS jobs (
256
+ `;const migrationFileName=`${new Date().getTime().toString()}-create-jobs-table.sql`,migrationsPath=getMigrationsPath();if(!existsSync(migrationsPath))mkdirSync(migrationsPath,{recursive:!0});const migrationFilePath=join(migrationsPath,migrationFileName);writeFileSync(migrationFilePath,migrationContent);console.log("\u2713 Created jobs migration file")}else console.log("\u2713 Jobs migration file already exists");if(!await jobsTableExists()){console.log(" Running migration...");const sqlitePath=getDatabasePath();if(driver==="sqlite"||existsSync(sqlitePath)){const sqlite=new Database(sqlitePath);sqlite.run(`CREATE TABLE IF NOT EXISTS jobs (
344
257
  id INTEGER PRIMARY KEY AUTOINCREMENT,
345
258
  queue TEXT NOT NULL DEFAULT 'default',
346
259
  payload TEXT NOT NULL,
@@ -349,8 +262,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
349
262
  available_at INTEGER,
350
263
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
351
264
  updated_at DATETIME
352
- )`);
353
- sqlite.run(`CREATE TABLE IF NOT EXISTS failed_jobs (
265
+ )`);sqlite.run(`CREATE TABLE IF NOT EXISTS failed_jobs (
354
266
  id INTEGER PRIMARY KEY AUTOINCREMENT,
355
267
  uuid TEXT NOT NULL,
356
268
  connection TEXT NOT NULL,
@@ -363,11 +275,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
363
275
  failed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
364
276
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
365
277
  updated_at DATETIME
366
- )`);
367
- sqlite.close();
368
- } else if (driver === "mysql") {
369
- const { db } = await import("../utils");
370
- await db.unsafe(`CREATE TABLE IF NOT EXISTS jobs (
278
+ )`);sqlite.close()}else if(driver==="mysql"){const{db}=await import("../utils");await db.unsafe(`CREATE TABLE IF NOT EXISTS jobs (
371
279
  id INT AUTO_INCREMENT PRIMARY KEY,
372
280
  queue VARCHAR(255) NOT NULL DEFAULT 'default',
373
281
  payload LONGTEXT NOT NULL,
@@ -376,8 +284,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
376
284
  available_at INT UNSIGNED NULL,
377
285
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
378
286
  updated_at TIMESTAMP NULL
379
- )`).execute();
380
- await db.unsafe(`CREATE TABLE IF NOT EXISTS failed_jobs (
287
+ )`).execute();await db.unsafe(`CREATE TABLE IF NOT EXISTS failed_jobs (
381
288
  id INT AUTO_INCREMENT PRIMARY KEY,
382
289
  uuid VARCHAR(255) NOT NULL,
383
290
  connection VARCHAR(255) NOT NULL,
@@ -390,10 +297,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
390
297
  failed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
391
298
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
392
299
  updated_at TIMESTAMP NULL
393
- )`).execute();
394
- } else if (driver === "postgres") {
395
- const { db } = await import("../utils");
396
- await db.unsafe(`CREATE TABLE IF NOT EXISTS jobs (
300
+ )`).execute()}else if(driver==="postgres"){const{db}=await import("../utils");await db.unsafe(`CREATE TABLE IF NOT EXISTS jobs (
397
301
  id SERIAL PRIMARY KEY,
398
302
  queue VARCHAR(255) NOT NULL DEFAULT 'default',
399
303
  payload TEXT NOT NULL,
@@ -402,8 +306,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
402
306
  available_at INTEGER,
403
307
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
404
308
  updated_at TIMESTAMP
405
- )`).execute();
406
- await db.unsafe(`CREATE TABLE IF NOT EXISTS failed_jobs (
309
+ )`).execute();await db.unsafe(`CREATE TABLE IF NOT EXISTS failed_jobs (
407
310
  id SERIAL PRIMARY KEY,
408
311
  uuid VARCHAR(255) NOT NULL,
409
312
  connection VARCHAR(255) NOT NULL,
@@ -416,17 +319,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
416
319
  failed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
417
320
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
418
321
  updated_at TIMESTAMP
419
- )`).execute();
420
- }
421
- console.log("\u2713 Jobs and failed_jobs tables created");
422
- } else
423
- console.log("\u2713 Jobs tables already exist");
424
- if (!await jobBatchesTableExists()) {
425
- console.log(" Creating job_batches table...");
426
- const sqlitePath = getDatabasePath();
427
- if (driver === "sqlite" || existsSync(sqlitePath)) {
428
- const sqlite = new Database(sqlitePath);
429
- sqlite.run(`CREATE TABLE IF NOT EXISTS job_batches (
322
+ )`).execute()}console.log("\u2713 Jobs and failed_jobs tables created")}else console.log("\u2713 Jobs tables already exist");if(!await jobBatchesTableExists()){console.log(" Creating job_batches table...");const sqlitePath=getDatabasePath();if(driver==="sqlite"||existsSync(sqlitePath)){const sqlite=new Database(sqlitePath);sqlite.run(`CREATE TABLE IF NOT EXISTS job_batches (
430
323
  id TEXT PRIMARY KEY,
431
324
  name TEXT NOT NULL DEFAULT '',
432
325
  total_jobs INTEGER NOT NULL DEFAULT 0,
@@ -437,11 +330,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
437
330
  cancelled_at DATETIME,
438
331
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
439
332
  finished_at DATETIME
440
- )`);
441
- sqlite.close();
442
- } else if (driver === "mysql") {
443
- const { db } = await import("../utils");
444
- await db.unsafe(`CREATE TABLE IF NOT EXISTS job_batches (
333
+ )`);sqlite.close()}else if(driver==="mysql"){const{db}=await import("../utils");await db.unsafe(`CREATE TABLE IF NOT EXISTS job_batches (
445
334
  id VARCHAR(255) PRIMARY KEY,
446
335
  name VARCHAR(255) NOT NULL DEFAULT '',
447
336
  total_jobs INT NOT NULL DEFAULT 0,
@@ -452,10 +341,7 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
452
341
  cancelled_at TIMESTAMP NULL,
453
342
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
454
343
  finished_at TIMESTAMP NULL
455
- )`).execute();
456
- } else if (driver === "postgres") {
457
- const { db } = await import("../utils");
458
- await db.unsafe(`CREATE TABLE IF NOT EXISTS job_batches (
344
+ )`).execute()}else if(driver==="postgres"){const{db}=await import("../utils");await db.unsafe(`CREATE TABLE IF NOT EXISTS job_batches (
459
345
  id VARCHAR(255) PRIMARY KEY,
460
346
  name VARCHAR(255) NOT NULL DEFAULT '',
461
347
  total_jobs INTEGER NOT NULL DEFAULT 0,
@@ -466,14 +352,4 @@ CREATE TABLE IF NOT EXISTS queue_circuit_state (
466
352
  cancelled_at TIMESTAMP,
467
353
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
468
354
  finished_at TIMESTAMP
469
- )`).execute();
470
- }
471
- console.log("\u2713 job_batches table created");
472
- } else
473
- console.log("\u2713 job_batches table already exists");
474
- }
475
- return ok("Migration created and executed.");
476
- } catch (error) {
477
- return err(error instanceof Error ? error : Error(String(error)));
478
- }
479
- }
355
+ )`).execute()}console.log("\u2713 job_batches table created")}else console.log("\u2713 job_batches table already exists")}return ok("Migration created and executed.")}catch(error){return err(error instanceof Error?error:Error(String(error)))}}