forge-sql-orm 2.0.9 → 2.0.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.
Files changed (41) hide show
  1. package/README.md +67 -42
  2. package/dist/ForgeSQLORM.js +162 -16
  3. package/dist/ForgeSQLORM.js.map +1 -1
  4. package/dist/ForgeSQLORM.mjs +165 -19
  5. package/dist/ForgeSQLORM.mjs.map +1 -1
  6. package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
  7. package/dist/core/ForgeSQLORM.d.ts.map +1 -1
  8. package/dist/core/ForgeSQLQueryBuilder.d.ts +32 -0
  9. package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
  10. package/dist/core/SystemTables.d.ts +8 -6
  11. package/dist/core/SystemTables.d.ts.map +1 -1
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/lib/drizzle/extensions/selectAliased.d.ts +9 -0
  15. package/dist/lib/drizzle/extensions/selectAliased.d.ts.map +1 -0
  16. package/dist/utils/sqlUtils.d.ts +8 -4
  17. package/dist/utils/sqlUtils.d.ts.map +1 -1
  18. package/dist/webtriggers/applyMigrationsWebTrigger.d.ts +23 -0
  19. package/dist/webtriggers/applyMigrationsWebTrigger.d.ts.map +1 -1
  20. package/dist/webtriggers/dropMigrationWebTrigger.d.ts +20 -4
  21. package/dist/webtriggers/dropMigrationWebTrigger.d.ts.map +1 -1
  22. package/dist/webtriggers/fetchSchemaWebTrigger.d.ts +28 -0
  23. package/dist/webtriggers/fetchSchemaWebTrigger.d.ts.map +1 -0
  24. package/dist/webtriggers/index.d.ts +1 -0
  25. package/dist/webtriggers/index.d.ts.map +1 -1
  26. package/dist-cli/cli.js +5 -0
  27. package/dist-cli/cli.js.map +1 -1
  28. package/dist-cli/cli.mjs +8 -3
  29. package/dist-cli/cli.mjs.map +1 -1
  30. package/package.json +10 -10
  31. package/src/core/ForgeSQLCrudOperations.ts +0 -425
  32. package/src/core/ForgeSQLORM.ts +0 -228
  33. package/src/core/ForgeSQLQueryBuilder.ts +0 -319
  34. package/src/core/ForgeSQLSelectOperations.ts +0 -93
  35. package/src/core/SystemTables.ts +0 -7
  36. package/src/index.ts +0 -10
  37. package/src/utils/forgeDriver.ts +0 -39
  38. package/src/utils/sqlUtils.ts +0 -306
  39. package/src/webtriggers/applyMigrationsWebTrigger.ts +0 -26
  40. package/src/webtriggers/dropMigrationWebTrigger.ts +0 -35
  41. package/src/webtriggers/index.ts +0 -25
package/README.md CHANGED
@@ -11,7 +11,8 @@
11
11
  - ✅ **Automatic entity generation** from MySQL/tidb databases
12
12
  - ✅ **Automatic migration generation** from MySQL/tidb databases
13
13
  - ✅ **Drop Migrations** Generate a migration to drop all tables and clear migrations history for subsequent schema recreation
14
- - ✅ **Ready-to-use Migration Triggers** Built-in web triggers for applying and dropping migrations with proper error handling and security controls
14
+ - ✅ **Schema Fetching** Development-only web trigger to retrieve current database schema and generate SQL statements for schema recreation
15
+ - ✅ **Ready-to-use Migration Triggers** Built-in web triggers for applying migrations, dropping tables (development-only), and fetching schema (development-only) with proper error handling and security controls
15
16
  - ✅ **Optimistic Locking** Ensures data consistency by preventing conflicts when multiple users update the same record
16
17
  - ✅ **Type Safety** Full TypeScript support with proper type inference
17
18
 
@@ -19,11 +20,11 @@
19
20
 
20
21
  ### 1. Direct Drizzle Usage
21
22
  ```typescript
22
- import { drizzle } from "drizzle-orm/mysql-core";
23
+ import { drizzle } from "drizzle-orm/mysql-proxy";
23
24
  import { forgeDriver } from "forge-sql-orm";
24
25
  const db = drizzle(forgeDriver);
25
26
  ```
26
- Best for: Simple CRUD operations without optimistic locking. Note that you need to manually set `mapSelectFieldsWithAlias` for select fields to prevent field name collisions in Atlassian Forge SQL.
27
+ Best for: Simple CRUD operations without optimistic locking. Note that you need to manually patch drizzle `patchDbWithSelectAliased` for select fields to prevent field name collisions in Atlassian Forge SQL.
27
28
 
28
29
  ### 2. Full Forge-SQL-ORM Usage
29
30
  ```typescript
@@ -53,14 +54,14 @@ await forgeSQL
53
54
 
54
55
  ### Using Direct Drizzle
55
56
  ```typescript
56
- import { drizzle } from "drizzle-orm/mysql-core";
57
- import { forgeDriver, mapSelectFieldsWithAlias } from "forge-sql-orm";
57
+ import { drizzle } from "drizzle-orm/mysql-proxy";
58
+ import { forgeDriver, patchDbWithSelectAliased } from "forge-sql-orm";
58
59
 
59
- const db = drizzle(forgeDriver);
60
+ const db = patchDbWithSelectAliased(drizzle(forgeDriver));
60
61
 
61
62
  // Manual field name collision prevention
62
63
  await db
63
- .select(mapSelectFieldsWithAlias({user: users, order: orders}))
64
+ .selectAliased({user: users, order: orders})
64
65
  .from(orders)
65
66
  .innerJoin(users, eq(orders.userId, users.id));
66
67
  ```
@@ -71,6 +72,7 @@ await db
71
72
  - The solution automatically creates unique aliases for each field by prefixing them with the table name
72
73
  - This ensures that fields with the same name from different tables remain distinct in the query results
73
74
 
75
+
74
76
  ## Installation
75
77
 
76
78
  Forge-SQL-ORM is designed to work with @forge/sql and requires some additional setup to ensure compatibility within Atlassian Forge.
@@ -94,10 +96,10 @@ If you prefer to use Drizzle ORM directly without the additional features of For
94
96
 
95
97
  ```typescript
96
98
  import { drizzle } from "drizzle-orm/mysql-proxy";
97
- import { forgeDriver } from "forge-sql-orm";
99
+ import { forgeDriver, patchDbWithSelectAliased } from "forge-sql-orm";
98
100
 
99
- // Initialize drizzle with the custom driver
100
- const db = drizzle(forgeDriver);
101
+ // Initialize drizzle with the custom driver and patch it for aliased selects
102
+ const db = patchDbWithSelectAliased(drizzle(forgeDriver));
101
103
 
102
104
  // Use drizzle directly
103
105
  const users = await db.select().from(users);
@@ -377,7 +379,6 @@ const result = await db
377
379
 
378
380
  ### Complex Queries
379
381
  ```js
380
-
381
382
  // Using joins with automatic field name collision prevention
382
383
  // With forgeSQL
383
384
  const orderWithUser = await forgeSQL
@@ -386,9 +387,9 @@ const orderWithUser = await forgeSQL
386
387
  .innerJoin(users, eq(orders.userId, users.id));
387
388
 
388
389
  // OR with direct drizzle
389
- const db = drizzle(forgeDriver);
390
+ const db = patchDbWithSelectAliased(drizzle(forgeDriver));
390
391
  const orderWithUser = await db
391
- .select(mapSelectFieldsWithAlias({user: users, order: orders}))
392
+ .selectAliased({user: users, order: orders})
392
393
  .from(orders)
393
394
  .innerJoin(users, eq(orders.userId, users.id));
394
395
  // Returns: {
@@ -398,33 +399,11 @@ const orderWithUser = await db
398
399
  // order_product: "Product 1"
399
400
  // }
400
401
 
401
- // Using distinct select with automatic field name collision prevention
402
- const uniqueOrdersWithUsers = await forgeSQL
403
- .selectDistinct({user: users, order: orders})
404
- .from(orders)
405
- .innerJoin(users, eq(orders.userId, users.id));
406
-
407
- // Finding duplicates
408
- // With forgeSQL
409
- const duplicates = await forgeSQL
410
- .getDrizzleQueryBuilder()
411
- .select({
412
- name: Users.name,
413
- count: sql<number>`COUNT(*) as \`count\``
414
- }).from(Users)
415
- .groupBy(Users.name)
416
- .having(sql`COUNT(*) > 1`);
417
-
418
- // OR with direct drizzle
419
- const db = drizzle(forgeDriver);
420
- const duplicates = await db
421
- .select({
422
- name: Users.name,
423
- count: sql<number>`COUNT(*) as \`count\``
424
- }).from(Users)
425
- .groupBy(Users.name)
426
- .having(sql`COUNT(*) > 1`);
427
- // Returns: { name: "John Doe", count: 2 }
402
+ // Using distinct with aliases
403
+ const uniqueUsers = await db
404
+ .selectAliasedDistinct({user: users})
405
+ .from(users);
406
+ // Returns unique users with aliased fields
428
407
 
429
408
  // Using executeQueryOnlyOne for unique results
430
409
  const userStats = await forgeSQL
@@ -575,7 +554,7 @@ Commands:
575
554
 
576
555
  ## Web Triggers for Migrations
577
556
 
578
- Forge-SQL-ORM provides two web triggers for managing database migrations in Atlassian Forge:
557
+ Forge-SQL-ORM provides web triggers for managing database migrations in Atlassian Forge:
579
558
 
580
559
  ### 1. Apply Migrations Trigger
581
560
 
@@ -647,10 +626,57 @@ Configure in `manifest.yml`:
647
626
  handler: index.dropMigrations
648
627
  ```
649
628
 
629
+ ### 3. Fetch Schema Trigger
630
+
631
+ ⚠️ **DEVELOPMENT ONLY**: This trigger is designed for development environments only and should not be used in production.
632
+
633
+ This trigger retrieves the current database schema from Atlassian Forge SQL and generates SQL statements that can be used to recreate the database structure. It's useful for:
634
+ - Development environment setup
635
+ - Schema documentation
636
+ - Database structure verification
637
+ - Creating backup scripts
638
+
639
+ **Security Considerations**:
640
+ - This trigger exposes your database structure
641
+ - It temporarily disables foreign key checks
642
+ - It may expose sensitive table names and structures
643
+ - Should only be used in development environments
644
+
645
+ ```typescript
646
+ // Example usage in your Forge app
647
+ import { fetchSchemaWebTrigger } from "forge-sql-orm";
648
+
649
+ export const fetchSchema = async () => {
650
+ return fetchSchemaWebTrigger();
651
+ };
652
+ ```
653
+
654
+ Configure in `manifest.yml`:
655
+ ```yaml
656
+ webtrigger:
657
+ - key: fetch-schema
658
+ function: fetchSchema
659
+ sql:
660
+ - key: main
661
+ engine: mysql
662
+ function:
663
+ - key: fetchSchema
664
+ handler: index.fetchSchema
665
+ ```
666
+
667
+ The response will contain SQL statements like:
668
+ ```sql
669
+ SET foreign_key_checks = 0;
670
+ CREATE TABLE IF NOT EXISTS users (...);
671
+ CREATE TABLE IF NOT EXISTS orders (...);
672
+ SET foreign_key_checks = 1;
673
+ ```
674
+
650
675
  ### Important Notes
651
676
 
652
677
  **Security Considerations**:
653
678
  - The drop migrations trigger should be restricted to development environments
679
+ - The fetch schema trigger should only be used in development
654
680
  - Consider implementing additional authentication for these endpoints
655
681
 
656
682
  **Best Practices**:
@@ -659,7 +685,6 @@ Configure in `manifest.yml`:
659
685
  - Use these triggers as part of your deployment pipeline
660
686
  - Monitor the execution logs in the Forge Developer Console
661
687
 
662
-
663
688
  ## License
664
689
  This project is licensed under the **MIT License**.
665
690
  Feel free to use it for commercial and personal projects.
@@ -131,32 +131,36 @@ function generateDropTableStatements(tables) {
131
131
  dropStatements.push(`DELETE FROM __migrations;`);
132
132
  return dropStatements;
133
133
  }
134
- function mapSelectTableToAlias(table2) {
134
+ function mapSelectTableToAlias(table2, aliasMap) {
135
135
  const { columns, tableName } = getTableMetadata(table2);
136
136
  const selectionsTableFields = {};
137
137
  Object.keys(columns).forEach((name) => {
138
138
  const column = columns[name];
139
- const fieldAlias = drizzleOrm.sql.raw(`${tableName}_${column.name}`);
139
+ const uniqName = `a_${tableName}_${column.name}`;
140
+ const fieldAlias = drizzleOrm.sql.raw(uniqName);
140
141
  selectionsTableFields[name] = drizzleOrm.sql`${column} as \`${fieldAlias}\``;
142
+ aliasMap[uniqName] = column;
141
143
  });
142
144
  return selectionsTableFields;
143
145
  }
144
146
  function isDrizzleColumn(column) {
145
147
  return column && typeof column === "object" && "table" in column;
146
148
  }
147
- function mapSelectAllFieldsToAlias(selections, name, fields) {
149
+ function mapSelectAllFieldsToAlias(selections, name, fields, aliasMap) {
148
150
  if (drizzleOrm.isTable(fields)) {
149
- selections[name] = mapSelectTableToAlias(fields);
151
+ selections[name] = mapSelectTableToAlias(fields, aliasMap);
150
152
  } else if (isDrizzleColumn(fields)) {
151
153
  const column = fields;
152
- let aliasName = drizzleOrm.sql.raw(`${table.getTableName(column.table)}_${column.name}`);
154
+ const uniqName = `a_${table.getTableName(column.table)}_${column.name}`;
155
+ let aliasName = drizzleOrm.sql.raw(uniqName);
153
156
  selections[name] = drizzleOrm.sql`${column} as \`${aliasName}\``;
157
+ aliasMap[uniqName] = column;
154
158
  } else if (sql.isSQLWrapper(fields)) {
155
159
  selections[name] = fields;
156
160
  } else {
157
161
  const innerSelections = {};
158
162
  Object.entries(fields).forEach(([iname, ifields]) => {
159
- mapSelectAllFieldsToAlias(innerSelections, iname, ifields);
163
+ mapSelectAllFieldsToAlias(innerSelections, iname, ifields, aliasMap);
160
164
  });
161
165
  selections[name] = innerSelections;
162
166
  }
@@ -166,11 +170,65 @@ function mapSelectFieldsWithAlias(fields) {
166
170
  if (!fields) {
167
171
  throw new Error("fields is empty");
168
172
  }
173
+ const aliasMap = {};
169
174
  const selections = {};
170
175
  Object.entries(fields).forEach(([name, fields2]) => {
171
- mapSelectAllFieldsToAlias(selections, name, fields2);
176
+ mapSelectAllFieldsToAlias(selections, name, fields2, aliasMap);
177
+ });
178
+ return { selections, aliasMap };
179
+ }
180
+ function getAliasFromDrizzleAlias(value) {
181
+ const isSQL = value !== null && typeof value === "object" && sql.isSQLWrapper(value) && "queryChunks" in value;
182
+ if (isSQL) {
183
+ const sql2 = value;
184
+ const queryChunks = sql2.queryChunks;
185
+ if (queryChunks.length > 3) {
186
+ const aliasNameChunk = queryChunks[queryChunks.length - 2];
187
+ if (sql.isSQLWrapper(aliasNameChunk) && "queryChunks" in aliasNameChunk) {
188
+ const aliasNameChunkSql = aliasNameChunk;
189
+ if (aliasNameChunkSql && aliasNameChunkSql.queryChunks.length === 1) {
190
+ const queryChunksStringChunc = aliasNameChunkSql.queryChunks[0];
191
+ if (queryChunksStringChunc && "value" in queryChunksStringChunc) {
192
+ const values = queryChunksStringChunc.value;
193
+ if (values && values.length === 1) {
194
+ return values[0];
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ return void 0;
202
+ }
203
+ function transformValue(value, alias, aliasMap) {
204
+ const column = aliasMap[alias];
205
+ if (!column) return value;
206
+ let customColumn = column;
207
+ const fromDriver = customColumn?.mapFrom;
208
+ if (fromDriver && value !== null && value !== void 0) {
209
+ return fromDriver(value);
210
+ }
211
+ return value;
212
+ }
213
+ function transformObject(obj, selections, aliasMap) {
214
+ const result = {};
215
+ for (const [key, value] of Object.entries(obj)) {
216
+ const selection = selections[key];
217
+ const alias = getAliasFromDrizzleAlias(selection);
218
+ if (alias && aliasMap[alias]) {
219
+ result[key] = transformValue(value, alias, aliasMap);
220
+ } else if (selection && typeof selection === "object" && !sql.isSQLWrapper(selection)) {
221
+ result[key] = transformObject(value, selection, aliasMap);
222
+ } else {
223
+ result[key] = value;
224
+ }
225
+ }
226
+ return result;
227
+ }
228
+ function applyFromDriverTransform(rows, selections, aliasMap) {
229
+ return rows.map((row) => {
230
+ return transformObject(row, selections, aliasMap);
172
231
  });
173
- return selections;
174
232
  }
175
233
  class ForgeSQLCrudOperations {
176
234
  forgeOperations;
@@ -549,6 +607,52 @@ const forgeDriver = async (query, params, method) => {
549
607
  throw error;
550
608
  }
551
609
  };
610
+ function createAliasedSelectBuilder(db, fields, selectFn) {
611
+ const { selections, aliasMap } = mapSelectFieldsWithAlias(fields);
612
+ const builder = selectFn(selections);
613
+ const wrapBuilder = (rawBuilder) => {
614
+ return new Proxy(rawBuilder, {
615
+ get(target, prop, receiver) {
616
+ if (prop === "execute") {
617
+ return async (...args) => {
618
+ const rows = await target.execute(...args);
619
+ return applyFromDriverTransform(rows, selections, aliasMap);
620
+ };
621
+ }
622
+ if (prop === "then") {
623
+ return (onfulfilled, onrejected) => target.execute().then(
624
+ (rows) => {
625
+ const transformed = applyFromDriverTransform(rows, selections, aliasMap);
626
+ return onfulfilled?.(transformed);
627
+ },
628
+ onrejected
629
+ );
630
+ }
631
+ const value = Reflect.get(target, prop, receiver);
632
+ if (typeof value === "function") {
633
+ return (...args) => {
634
+ const result = value.apply(target, args);
635
+ if (typeof result === "object" && result !== null && "execute" in result) {
636
+ return wrapBuilder(result);
637
+ }
638
+ return result;
639
+ };
640
+ }
641
+ return value;
642
+ }
643
+ });
644
+ };
645
+ return wrapBuilder(builder);
646
+ }
647
+ function patchDbWithSelectAliased(db) {
648
+ db.selectAliased = function(fields) {
649
+ return createAliasedSelectBuilder(db, fields, (selections) => db.select(selections));
650
+ };
651
+ db.selectAliasedDistinct = function(fields) {
652
+ return createAliasedSelectBuilder(db, fields, (selections) => db.selectDistinct(selections));
653
+ };
654
+ return db;
655
+ }
552
656
  class ForgeSQLORMImpl {
553
657
  static instance = null;
554
658
  drizzle;
@@ -567,7 +671,7 @@ class ForgeSQLORMImpl {
567
671
  if (newOptions.logRawSqlQuery) {
568
672
  console.debug("Initializing ForgeSQLORM...");
569
673
  }
570
- this.drizzle = mysqlProxy.drizzle(forgeDriver, { logger: newOptions.logRawSqlQuery });
674
+ this.drizzle = patchDbWithSelectAliased(mysqlProxy.drizzle(forgeDriver, { logger: newOptions.logRawSqlQuery }));
571
675
  this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);
572
676
  this.fetchOperations = new ForgeSQLSelectOperations(newOptions);
573
677
  } catch (error) {
@@ -632,7 +736,7 @@ class ForgeSQLORMImpl {
632
736
  if (!fields) {
633
737
  throw new Error("fields is empty");
634
738
  }
635
- return this.drizzle.select(mapSelectFieldsWithAlias(fields));
739
+ return this.drizzle.selectAliased(fields);
636
740
  }
637
741
  /**
638
742
  * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.
@@ -654,7 +758,7 @@ class ForgeSQLORMImpl {
654
758
  if (!fields) {
655
759
  throw new Error("fields is empty");
656
760
  }
657
- return this.drizzle.selectDistinct(mapSelectFieldsWithAlias(fields));
761
+ return this.drizzle.selectAliasedDistinct(fields);
658
762
  }
659
763
  }
660
764
  class ForgeSQLORM {
@@ -679,7 +783,7 @@ class ForgeSQLORM {
679
783
  * ```
680
784
  */
681
785
  select(fields) {
682
- return this.ormInstance.getDrizzleQueryBuilder().select(mapSelectFieldsWithAlias(fields));
786
+ return this.ormInstance.select(fields);
683
787
  }
684
788
  /**
685
789
  * Creates a distinct select query with unique field aliases to prevent field name collisions in joins.
@@ -698,7 +802,7 @@ class ForgeSQLORM {
698
802
  * ```
699
803
  */
700
804
  selectDistinct(fields) {
701
- return this.ormInstance.getDrizzleQueryBuilder().selectDistinct(mapSelectFieldsWithAlias(fields));
805
+ return this.ormInstance.selectDistinct(fields);
702
806
  }
703
807
  /**
704
808
  * Proxies the `crud` method from `ForgeSQLORMImpl`.
@@ -794,8 +898,8 @@ const applySchemaMigrations = async (migration) => {
794
898
  console.log("Provisioning the database");
795
899
  await sql$1.sql._provision();
796
900
  console.info("Running schema migrations");
797
- const migrations = await migration(sql$1.migrationRunner);
798
- const successfulMigrations = await migrations.run();
901
+ const migrations2 = await migration(sql$1.migrationRunner);
902
+ const successfulMigrations = await migrations2.run();
799
903
  console.info("Migrations applied:", successfulMigrations);
800
904
  const migrationHistory = (await sql$1.migrationRunner.list()).map((y) => `${y.id}, ${y.name}, ${y.migratedAt.toUTCString()}`).join("\n");
801
905
  console.info("Migrations history:\nid, name, migrated_at\n", migrationHistory);
@@ -806,6 +910,46 @@ const applySchemaMigrations = async (migration) => {
806
910
  body: "Migrations successfully executed"
807
911
  };
808
912
  };
913
+ const migrations = mysqlCore.mysqlTable("__migrations", {
914
+ id: mysqlCore.bigint("id", { mode: "number" }).primaryKey().autoincrement(),
915
+ name: mysqlCore.varchar("name", { length: 255 }).notNull(),
916
+ migratedAt: mysqlCore.timestamp("migratedAt").defaultNow().notNull()
917
+ });
918
+ const forgeSystemTables = [migrations];
919
+ async function fetchSchemaWebTrigger() {
920
+ try {
921
+ const tables = await getTables();
922
+ const createTableStatements = await generateCreateTableStatements(tables);
923
+ const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);
924
+ return getHttpResponse(200, sqlStatements.join(";\n"));
925
+ } catch (error) {
926
+ console.error(JSON.stringify(error));
927
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
928
+ return getHttpResponse(500, errorMessage);
929
+ }
930
+ }
931
+ async function getTables() {
932
+ const tables = await sql$1.sql.executeDDL("SHOW TABLES");
933
+ return tables.rows.flatMap((tableInfo) => Object.values(tableInfo));
934
+ }
935
+ async function generateCreateTableStatements(tables) {
936
+ const statements = [];
937
+ for (const table2 of tables) {
938
+ const createTableResult = await sql$1.sql.executeDDL(`SHOW CREATE TABLE ${table2}`);
939
+ const createTableStatements = createTableResult.rows.filter((row) => !isSystemTable(row.Table)).map((row) => formatCreateTableStatement(row["Create Table"]));
940
+ statements.push(...createTableStatements);
941
+ }
942
+ return statements;
943
+ }
944
+ function isSystemTable(tableName) {
945
+ return forgeSystemTables.some((st) => table.getTableName(st) === tableName);
946
+ }
947
+ function formatCreateTableStatement(statement) {
948
+ return statement.replace(/"/g, "").replace("CREATE TABLE", "CREATE TABLE IF NOT EXISTS");
949
+ }
950
+ function wrapWithForeignKeyChecks(statements) {
951
+ return ["SET foreign_key_checks = 0", ...statements, "SET foreign_key_checks = 1"];
952
+ }
809
953
  const getHttpResponse = (statusCode, body) => {
810
954
  let statusText = "";
811
955
  if (statusCode === 200) {
@@ -822,10 +966,12 @@ const getHttpResponse = (statusCode, body) => {
822
966
  };
823
967
  exports.ForgeSQLCrudOperations = ForgeSQLCrudOperations;
824
968
  exports.ForgeSQLSelectOperations = ForgeSQLSelectOperations;
969
+ exports.applyFromDriverTransform = applyFromDriverTransform;
825
970
  exports.applySchemaMigrations = applySchemaMigrations;
826
971
  exports.default = ForgeSQLORM;
827
972
  exports.dropSchemaMigrations = dropSchemaMigrations;
828
973
  exports.extractAlias = extractAlias;
974
+ exports.fetchSchemaWebTrigger = fetchSchemaWebTrigger;
829
975
  exports.forgeDateString = forgeDateString;
830
976
  exports.forgeDateTimeString = forgeDateTimeString;
831
977
  exports.forgeDriver = forgeDriver;
@@ -837,6 +983,6 @@ exports.getPrimaryKeys = getPrimaryKeys;
837
983
  exports.getTableMetadata = getTableMetadata;
838
984
  exports.mapSelectAllFieldsToAlias = mapSelectAllFieldsToAlias;
839
985
  exports.mapSelectFieldsWithAlias = mapSelectFieldsWithAlias;
840
- exports.mapSelectTableToAlias = mapSelectTableToAlias;
841
986
  exports.parseDateTime = parseDateTime;
987
+ exports.patchDbWithSelectAliased = patchDbWithSelectAliased;
842
988
  //# sourceMappingURL=ForgeSQLORM.js.map