forge-sql-orm 1.0.31 → 2.0.0
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/README.md +216 -695
- package/dist/ForgeSQLORM.js +526 -564
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +527 -554
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts +101 -130
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts +11 -10
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +275 -111
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts +65 -22
- package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
- package/dist/core/SystemTables.d.ts +59 -0
- package/dist/core/SystemTables.d.ts.map +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts +53 -6
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist-cli/cli.js +461 -397
- package/dist-cli/cli.js.map +1 -1
- package/dist-cli/cli.mjs +461 -397
- package/dist-cli/cli.mjs.map +1 -1
- package/package.json +21 -27
- package/src/core/ForgeSQLCrudOperations.ts +360 -473
- package/src/core/ForgeSQLORM.ts +38 -79
- package/src/core/ForgeSQLQueryBuilder.ts +255 -132
- package/src/core/ForgeSQLSelectOperations.ts +185 -72
- package/src/core/SystemTables.ts +7 -0
- package/src/index.ts +1 -2
- package/src/utils/sqlUtils.ts +164 -22
- package/dist/core/ComplexQuerySchemaBuilder.d.ts +0 -38
- package/dist/core/ComplexQuerySchemaBuilder.d.ts.map +0 -1
- package/dist/knex/index.d.ts +0 -4
- package/dist/knex/index.d.ts.map +0 -1
- package/src/core/ComplexQuerySchemaBuilder.ts +0 -63
- package/src/knex/index.ts +0 -4
package/src/core/ForgeSQLORM.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import type { EntityName, LoggingOptions } from "..";
|
|
2
|
-
import type { EntitySchema } from "@mikro-orm/core/metadata/EntitySchema";
|
|
3
|
-
import type { AnyEntity, EntityClass, EntityClassGroup } from "@mikro-orm/core/typings";
|
|
4
|
-
import type { QueryBuilder } from "@mikro-orm/knex/query";
|
|
5
|
-
import { MemoryCacheAdapter, MikroORM, NullCacheAdapter } from "@mikro-orm/mysql";
|
|
6
1
|
import { ForgeSQLCrudOperations } from "./ForgeSQLCrudOperations";
|
|
7
2
|
import {
|
|
8
3
|
CRUDForgeSQL,
|
|
@@ -11,52 +6,36 @@ import {
|
|
|
11
6
|
SchemaSqlForgeSql,
|
|
12
7
|
} from "./ForgeSQLQueryBuilder";
|
|
13
8
|
import { ForgeSQLSelectOperations } from "./ForgeSQLSelectOperations";
|
|
14
|
-
import
|
|
9
|
+
import { drizzle } from "drizzle-orm/mysql2";
|
|
10
|
+
import { MySql2Database } from "drizzle-orm/mysql2/driver";
|
|
15
11
|
|
|
16
12
|
/**
|
|
17
|
-
* Implementation of ForgeSQLORM that
|
|
13
|
+
* Implementation of ForgeSQLORM that uses Drizzle ORM for query building.
|
|
14
|
+
* This class provides a bridge between Forge SQL and Drizzle ORM, allowing
|
|
15
|
+
* to use Drizzle's query builder while executing queries through Forge SQL.
|
|
18
16
|
*/
|
|
19
17
|
class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
20
18
|
private static instance: ForgeSQLORMImpl | null = null;
|
|
21
|
-
private readonly
|
|
19
|
+
private readonly drizzle: MySql2Database<Record<string, unknown>>;
|
|
22
20
|
private readonly crudOperations: CRUDForgeSQL;
|
|
23
21
|
private readonly fetchOperations: SchemaSqlForgeSql;
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* Private constructor to enforce singleton behavior.
|
|
27
|
-
* @param entities - The list of entities for ORM initialization.
|
|
28
25
|
* @param options - Options for configuring ForgeSQL ORM behavior.
|
|
29
26
|
*/
|
|
30
|
-
private constructor(
|
|
31
|
-
entities: (EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[],
|
|
32
|
-
options?: ForgeSqlOrmOptions,
|
|
33
|
-
) {
|
|
34
|
-
|
|
27
|
+
private constructor(options?: ForgeSqlOrmOptions) {
|
|
35
28
|
try {
|
|
36
|
-
const newOptions: ForgeSqlOrmOptions = options ?? {
|
|
37
|
-
|
|
29
|
+
const newOptions: ForgeSqlOrmOptions = options ?? {
|
|
30
|
+
logRawSqlQuery: false,
|
|
31
|
+
disableOptimisticLocking: false,
|
|
32
|
+
};
|
|
33
|
+
if (newOptions.logRawSqlQuery) {
|
|
38
34
|
console.debug("Initializing ForgeSQLORM...");
|
|
39
35
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
disableForeignKeys: false,
|
|
44
|
-
},
|
|
45
|
-
discovery: {
|
|
46
|
-
warnWhenNoEntities: true,
|
|
47
|
-
},
|
|
48
|
-
resultCache: {
|
|
49
|
-
adapter: NullCacheAdapter,
|
|
50
|
-
},
|
|
51
|
-
metadataCache: {
|
|
52
|
-
enabled: false,
|
|
53
|
-
adapter: MemoryCacheAdapter,
|
|
54
|
-
},
|
|
55
|
-
entities: entities,
|
|
56
|
-
preferTs: false,
|
|
57
|
-
debug: false,
|
|
58
|
-
});
|
|
59
|
-
|
|
36
|
+
// Initialize Drizzle instance for query building only
|
|
37
|
+
// This instance should not be used for direct database connections
|
|
38
|
+
this.drizzle = drizzle("");
|
|
60
39
|
this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);
|
|
61
40
|
this.fetchOperations = new ForgeSQLSelectOperations(newOptions);
|
|
62
41
|
} catch (error) {
|
|
@@ -67,16 +46,12 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
67
46
|
|
|
68
47
|
/**
|
|
69
48
|
* Returns the singleton instance of ForgeSQLORMImpl.
|
|
70
|
-
* @param entities - List of entities (required only on first initialization).
|
|
71
49
|
* @param options - Options for configuring ForgeSQL ORM behavior.
|
|
72
50
|
* @returns The singleton instance of ForgeSQLORMImpl.
|
|
73
51
|
*/
|
|
74
|
-
static getInstance(
|
|
75
|
-
entities: (EntityClass<AnyEntity> | EntityClassGroup<AnyEntity> | EntitySchema)[],
|
|
76
|
-
options?: ForgeSqlOrmOptions,
|
|
77
|
-
): ForgeSqlOperation {
|
|
52
|
+
static getInstance(options?: ForgeSqlOrmOptions): ForgeSqlOperation {
|
|
78
53
|
if (!ForgeSQLORMImpl.instance) {
|
|
79
|
-
ForgeSQLORMImpl.instance = new ForgeSQLORMImpl(
|
|
54
|
+
ForgeSQLORMImpl.instance = new ForgeSQLORMImpl(options);
|
|
80
55
|
}
|
|
81
56
|
return ForgeSQLORMImpl.instance;
|
|
82
57
|
}
|
|
@@ -98,41 +73,28 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
98
73
|
}
|
|
99
74
|
|
|
100
75
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
entityName: EntityName<Entity> | QueryBuilder<Entity>,
|
|
109
|
-
alias?: RootAlias,
|
|
110
|
-
loggerContext?: LoggingOptions,
|
|
111
|
-
): QueryBuilder<Entity, RootAlias> {
|
|
112
|
-
return this.mikroORM.em.createQueryBuilder(entityName, alias, undefined, loggerContext);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Provides access to the underlying Knex instance for building complex query parts.
|
|
117
|
-
* enabling advanced query customization and performance tuning.
|
|
118
|
-
* @returns The Knex instance, which can be used for query building.
|
|
76
|
+
* Returns a Drizzle query builder instance.
|
|
77
|
+
*
|
|
78
|
+
* ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.
|
|
79
|
+
* The returned instance should NOT be used for direct database connections or query execution.
|
|
80
|
+
* All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.
|
|
81
|
+
*
|
|
82
|
+
* @returns A Drizzle query builder instance for query construction only.
|
|
119
83
|
*/
|
|
120
|
-
|
|
121
|
-
return this.
|
|
84
|
+
getDrizzleQueryBuilder(): MySql2Database<Record<string, unknown>> {
|
|
85
|
+
return this.drizzle;
|
|
122
86
|
}
|
|
123
87
|
}
|
|
124
88
|
|
|
125
89
|
/**
|
|
126
90
|
* Public class that acts as a wrapper around the private ForgeSQLORMImpl.
|
|
91
|
+
* Provides a clean interface for working with Forge SQL and Drizzle ORM.
|
|
127
92
|
*/
|
|
128
93
|
class ForgeSQLORM {
|
|
129
94
|
private readonly ormInstance: ForgeSqlOperation;
|
|
130
95
|
|
|
131
|
-
constructor(
|
|
132
|
-
|
|
133
|
-
options?: ForgeSqlOrmOptions,
|
|
134
|
-
) {
|
|
135
|
-
this.ormInstance = ForgeSQLORMImpl.getInstance(entities, options);
|
|
96
|
+
constructor(options?: ForgeSqlOrmOptions) {
|
|
97
|
+
this.ormInstance = ForgeSQLORMImpl.getInstance(options);
|
|
136
98
|
}
|
|
137
99
|
|
|
138
100
|
/**
|
|
@@ -151,20 +113,17 @@ class ForgeSQLORM {
|
|
|
151
113
|
return this.ormInstance.fetch();
|
|
152
114
|
}
|
|
153
115
|
|
|
154
|
-
getKnex(): Knex<any, any[]> {
|
|
155
|
-
return this.ormInstance.getKnex();
|
|
156
|
-
}
|
|
157
|
-
|
|
158
116
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
117
|
+
* Returns a Drizzle query builder instance.
|
|
118
|
+
*
|
|
119
|
+
* ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.
|
|
120
|
+
* The returned instance should NOT be used for direct database connections or query execution.
|
|
121
|
+
* All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.
|
|
122
|
+
*
|
|
123
|
+
* @returns A Drizzle query builder instance for query construction only.
|
|
161
124
|
*/
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
alias?: RootAlias,
|
|
165
|
-
loggerContext?: LoggingOptions,
|
|
166
|
-
): QueryBuilder<Entity, RootAlias> {
|
|
167
|
-
return this.ormInstance.createQueryBuilder(entityName, alias, loggerContext);
|
|
125
|
+
getDrizzleQueryBuilder(): MySql2Database<Record<string, unknown>> {
|
|
126
|
+
return this.ormInstance.getDrizzleQueryBuilder();
|
|
168
127
|
}
|
|
169
128
|
}
|
|
170
129
|
|
|
@@ -1,197 +1,320 @@
|
|
|
1
1
|
import { UpdateQueryResponse } from "@forge/sql";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
2
|
+
import { SqlParameters } from "@forge/sql/out/sql-statement";
|
|
3
|
+
import { MySql2Database } from "drizzle-orm/mysql2/driver";
|
|
4
|
+
import { AnyMySqlSelectQueryBuilder, AnyMySqlTable, customType } from "drizzle-orm/mysql-core";
|
|
5
|
+
import { MySqlSelectDynamic } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
6
|
+
import { InferInsertModel, SQL } from "drizzle-orm";
|
|
7
|
+
import moment from "moment/moment";
|
|
8
|
+
import { parseDateTime } from "../utils/sqlUtils";
|
|
9
|
+
|
|
10
|
+
// ============= Core Types =============
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Interface representing the main ForgeSQL operations.
|
|
14
|
+
* Provides access to CRUD operations and schema-level SQL operations.
|
|
12
15
|
*/
|
|
13
16
|
export interface ForgeSqlOperation extends QueryBuilderForgeSql {
|
|
14
17
|
/**
|
|
15
|
-
* Provides CRUD operations.
|
|
18
|
+
* Provides CRUD (Create, Read, Update, Delete) operations.
|
|
19
|
+
* @returns {CRUDForgeSQL} Interface for performing CRUD operations
|
|
16
20
|
*/
|
|
17
21
|
crud(): CRUDForgeSQL;
|
|
18
22
|
|
|
19
23
|
/**
|
|
20
24
|
* Provides schema-level SQL fetch operations.
|
|
25
|
+
* @returns {SchemaSqlForgeSql} Interface for executing schema-bound SQL queries
|
|
21
26
|
*/
|
|
22
27
|
fetch(): SchemaSqlForgeSql;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
/**
|
|
26
|
-
*
|
|
31
|
+
* Interface for Query Builder operations.
|
|
32
|
+
* Provides access to the underlying Drizzle ORM query builder.
|
|
27
33
|
*/
|
|
28
|
-
export interface
|
|
29
|
-
/**
|
|
30
|
-
* Enables logging of raw SQL queries in the Atlassian Forge Developer Console.
|
|
31
|
-
*/
|
|
32
|
-
logRawSqlQuery?: boolean;
|
|
34
|
+
export interface QueryBuilderForgeSql {
|
|
33
35
|
/**
|
|
34
|
-
*
|
|
36
|
+
* Creates a new query builder for the given entity.
|
|
37
|
+
* @returns {MySql2Database<Record<string, unknown>>} The Drizzle database instance for building queries
|
|
35
38
|
*/
|
|
36
|
-
|
|
39
|
+
getDrizzleQueryBuilder(): MySql2Database<Record<string, unknown>>;
|
|
37
40
|
}
|
|
38
41
|
|
|
42
|
+
// ============= CRUD Operations =============
|
|
43
|
+
|
|
39
44
|
/**
|
|
40
|
-
* Interface for
|
|
45
|
+
* Interface for CRUD (Create, Read, Update, Delete) operations.
|
|
46
|
+
* Provides methods for basic database operations with support for optimistic locking.
|
|
41
47
|
*/
|
|
42
|
-
export interface
|
|
43
|
-
/**
|
|
44
|
-
* Executes a schema-bound SQL query and maps the result to the specified entity schema.
|
|
45
|
-
* @param query - The SQL query to execute.
|
|
46
|
-
* @param schema - The entity schema.
|
|
47
|
-
* @returns A list of mapped entity objects.
|
|
48
|
-
*/
|
|
49
|
-
executeSchemaSQL<T extends object>(query: string, schema: EntitySchema<T>): Promise<T[]>;
|
|
50
|
-
|
|
48
|
+
export interface CRUDForgeSQL {
|
|
51
49
|
/**
|
|
52
|
-
*
|
|
53
|
-
* @
|
|
54
|
-
* @param schema - The entity schema
|
|
55
|
-
* @
|
|
50
|
+
* Inserts multiple records into the database.
|
|
51
|
+
* @template T - The type of the table schema
|
|
52
|
+
* @param {T} schema - The entity schema
|
|
53
|
+
* @param {Partial<InferInsertModel<T>>[]} models - The list of entities to insert
|
|
54
|
+
* @param {boolean} [updateIfExists] - Whether to update the row if it already exists (default: false)
|
|
55
|
+
* @returns {Promise<number>} The number of inserted rows
|
|
56
|
+
* @throws {Error} If the insert operation fails
|
|
56
57
|
*/
|
|
57
|
-
|
|
58
|
+
insert<T extends AnyMySqlTable>(
|
|
59
|
+
schema: T,
|
|
60
|
+
models: Partial<InferInsertModel<T>>[],
|
|
61
|
+
updateIfExists?: boolean,
|
|
62
|
+
): Promise<number>;
|
|
58
63
|
|
|
59
64
|
/**
|
|
60
|
-
*
|
|
61
|
-
* @
|
|
62
|
-
* @
|
|
65
|
+
* Deletes a record by its ID.
|
|
66
|
+
* @template T - The type of the table schema
|
|
67
|
+
* @param {unknown} id - The ID of the record to delete
|
|
68
|
+
* @param {T} schema - The entity schema
|
|
69
|
+
* @returns {Promise<number>} The number of rows affected
|
|
70
|
+
* @throws {Error} If the delete operation fails
|
|
63
71
|
*/
|
|
64
|
-
|
|
72
|
+
deleteById<T extends AnyMySqlTable>(id: unknown, schema: T): Promise<number>;
|
|
65
73
|
|
|
66
74
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
75
|
+
* Updates a record by its ID with optimistic locking support.
|
|
76
|
+
* If a version field is defined in the schema, versioning is applied:
|
|
77
|
+
* - the current record version is retrieved
|
|
78
|
+
* - checked for concurrent modifications
|
|
79
|
+
* - and then incremented
|
|
80
|
+
*
|
|
81
|
+
* @template T - The type of the table schema
|
|
82
|
+
* @param {Partial<InferInsertModel<T>>} entity - The entity with updated values
|
|
83
|
+
* @param {T} schema - The entity schema
|
|
84
|
+
* @returns {Promise<number>} The number of rows affected
|
|
85
|
+
* @throws {Error} If the primary key is not included in the update fields
|
|
86
|
+
* @throws {Error} If optimistic locking check fails
|
|
71
87
|
*/
|
|
72
|
-
|
|
88
|
+
updateById<T extends AnyMySqlTable>(
|
|
89
|
+
entity: Partial<InferInsertModel<T>>,
|
|
90
|
+
schema: T,
|
|
91
|
+
): Promise<number>;
|
|
73
92
|
|
|
74
93
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
94
|
+
* Updates specified fields of records based on provided conditions.
|
|
95
|
+
* If the "where" parameter is not provided, the WHERE clause is built from the entity fields
|
|
96
|
+
* that are not included in the list of fields to update.
|
|
97
|
+
*
|
|
98
|
+
* @template T - The type of the table schema
|
|
99
|
+
* @param {Partial<InferInsertModel<T>>} updateData - The object containing values to update
|
|
100
|
+
* @param {T} schema - The entity schema
|
|
101
|
+
* @param {SQL<unknown>} [where] - Optional filtering conditions for the WHERE clause
|
|
102
|
+
* @returns {Promise<number>} The number of affected rows
|
|
103
|
+
* @throws {Error} If no filtering criteria are provided
|
|
104
|
+
* @throws {Error} If the update operation fails
|
|
79
105
|
*/
|
|
80
|
-
|
|
106
|
+
updateFields<T extends AnyMySqlTable>(
|
|
107
|
+
updateData: Partial<InferInsertModel<T>>,
|
|
108
|
+
schema: T,
|
|
109
|
+
where?: SQL<unknown>,
|
|
110
|
+
): Promise<number>;
|
|
81
111
|
}
|
|
82
112
|
|
|
113
|
+
// ============= Schema SQL Operations =============
|
|
114
|
+
|
|
83
115
|
/**
|
|
84
|
-
* Interface for
|
|
116
|
+
* Interface for schema-level SQL operations.
|
|
117
|
+
* Provides methods for executing SQL queries with schema binding and type safety.
|
|
85
118
|
*/
|
|
86
|
-
export interface
|
|
119
|
+
export interface SchemaSqlForgeSql {
|
|
87
120
|
/**
|
|
88
|
-
*
|
|
89
|
-
* @
|
|
90
|
-
* @param
|
|
91
|
-
* @
|
|
92
|
-
* @
|
|
121
|
+
* Executes a Drizzle query and returns the result.
|
|
122
|
+
* @template T - The type of the query builder
|
|
123
|
+
* @param {T} query - The Drizzle query to execute
|
|
124
|
+
* @returns {Promise<Awaited<T>>} The query result
|
|
125
|
+
* @throws {Error} If the query execution fails
|
|
93
126
|
*/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
updateIfExists?: boolean,
|
|
98
|
-
): Promise<number>;
|
|
127
|
+
executeQuery<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(
|
|
128
|
+
query: T,
|
|
129
|
+
): Promise<Awaited<T>>;
|
|
99
130
|
|
|
100
131
|
/**
|
|
101
|
-
*
|
|
102
|
-
* @
|
|
103
|
-
* @param
|
|
104
|
-
* @returns
|
|
132
|
+
* Executes a Drizzle query and returns a single result.
|
|
133
|
+
* @template T - The type of the query builder
|
|
134
|
+
* @param {T} query - The Drizzle query to execute
|
|
135
|
+
* @returns {Promise<Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined>} A single result object or undefined
|
|
136
|
+
* @throws {Error} If more than one record is returned
|
|
137
|
+
* @throws {Error} If the query execution fails
|
|
105
138
|
*/
|
|
106
|
-
|
|
139
|
+
executeQueryOnlyOne<T extends MySqlSelectDynamic<AnyMySqlSelectQueryBuilder>>(
|
|
140
|
+
query: T,
|
|
141
|
+
): Promise<
|
|
142
|
+
Awaited<T> extends Array<any> ? Awaited<T>[number] | undefined : Awaited<T> | undefined
|
|
143
|
+
>;
|
|
107
144
|
|
|
108
145
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* * @param schema - The entity schema.
|
|
116
|
-
* * @throws If the primary key is not included in the update fields.
|
|
117
|
-
* */
|
|
118
|
-
updateById<T extends object>(entity: Partial<T>, schema: EntitySchema<T>): Promise<void>;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Updates specified fields of records based on provided conditions.
|
|
122
|
-
* If the "where" parameter is not provided, the WHERE clause is built from the entity fields
|
|
123
|
-
* that are not included in the list of fields to update.
|
|
124
|
-
*
|
|
125
|
-
* @param entity - The object containing values to update and potential criteria for filtering.
|
|
126
|
-
* @param fields - Array of field names to update.
|
|
127
|
-
* @param schema - The entity schema.
|
|
128
|
-
* @param where - Optional filtering conditions for the WHERE clause.
|
|
129
|
-
* @returns The number of affected rows.
|
|
130
|
-
* @throws If no filtering criteria are provided (either via "where" or from the remaining entity fields).
|
|
146
|
+
* Executes a raw SQL query and returns the results.
|
|
147
|
+
* @template T - The type of the result objects
|
|
148
|
+
* @param {string} query - The raw SQL query
|
|
149
|
+
* @param {SqlParameters[]} [params] - Optional SQL parameters
|
|
150
|
+
* @returns {Promise<T[]>} A list of results as objects
|
|
151
|
+
* @throws {Error} If the query execution fails
|
|
131
152
|
*/
|
|
132
|
-
|
|
133
|
-
entity: Partial<T>,
|
|
134
|
-
fields: EntityKey<T>[],
|
|
135
|
-
schema: EntitySchema<T>,
|
|
136
|
-
where?: QBFilterQuery<T>,
|
|
137
|
-
): Promise<number>
|
|
153
|
+
executeRawSQL<T extends object | unknown>(query: string, params?: SqlParameters[]): Promise<T[]>;
|
|
138
154
|
|
|
139
155
|
/**
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* @param entity - The entity with updated values.
|
|
147
|
-
* @param fields - The list of field names to update.
|
|
148
|
-
* @param schema - The entity schema.
|
|
149
|
-
* @throws If the primary key is not included in the update fields.
|
|
156
|
+
* Executes a raw SQL update query.
|
|
157
|
+
* @param {string} query - The raw SQL update query
|
|
158
|
+
* @param {SqlParameters[]} [params] - Optional SQL parameters
|
|
159
|
+
* @returns {Promise<UpdateQueryResponse>} The update response containing affected rows
|
|
160
|
+
* @throws {Error} If the update operation fails
|
|
150
161
|
*/
|
|
151
|
-
|
|
152
|
-
entity: T,
|
|
153
|
-
fields: EntityKey<T>[],
|
|
154
|
-
schema: EntitySchema<T>,
|
|
155
|
-
): Promise<void>;
|
|
162
|
+
executeRawUpdateSQL(query: string, params?: unknown[]): Promise<UpdateQueryResponse>;
|
|
156
163
|
}
|
|
157
164
|
|
|
165
|
+
// ============= Configuration Types =============
|
|
166
|
+
|
|
158
167
|
/**
|
|
159
|
-
* Interface for
|
|
168
|
+
* Interface for version field metadata.
|
|
169
|
+
* Defines the configuration for optimistic locking version fields.
|
|
160
170
|
*/
|
|
161
|
-
export interface
|
|
171
|
+
export interface VersionFieldMetadata {
|
|
172
|
+
/** Name of the version field */
|
|
173
|
+
fieldName: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Interface for table metadata.
|
|
178
|
+
* Defines the configuration for a specific table.
|
|
179
|
+
*/
|
|
180
|
+
export interface TableMetadata {
|
|
181
|
+
/** Name of the table */
|
|
182
|
+
tableName: string;
|
|
183
|
+
/** Version field configuration for optimistic locking */
|
|
184
|
+
versionField: VersionFieldMetadata;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Type for additional metadata configuration.
|
|
189
|
+
* Maps table names to their metadata configuration.
|
|
190
|
+
*/
|
|
191
|
+
export type AdditionalMetadata = Record<string, TableMetadata>;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Options for configuring ForgeSQL ORM behavior.
|
|
195
|
+
*/
|
|
196
|
+
export interface ForgeSqlOrmOptions {
|
|
162
197
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* @
|
|
166
|
-
* @param loggerContext - Logging options.
|
|
167
|
-
* @returns The query builder instance.
|
|
198
|
+
* Enables logging of raw SQL queries in the Atlassian Forge Developer Console.
|
|
199
|
+
* Useful for debugging and monitoring SQL operations.
|
|
200
|
+
* @default false
|
|
168
201
|
*/
|
|
169
|
-
|
|
170
|
-
entityName: EntityName<Entity> | QueryBuilder<Entity>,
|
|
171
|
-
alias?: RootAlias,
|
|
172
|
-
loggerContext?: LoggingOptions,
|
|
173
|
-
): QueryBuilder<Entity, RootAlias>;
|
|
174
|
-
|
|
202
|
+
logRawSqlQuery?: boolean;
|
|
175
203
|
/**
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
* @
|
|
204
|
+
* Enables logging of raw SQL queries in the Atlassian Forge Developer Console.
|
|
205
|
+
* Useful for debugging and monitoring SQL operations.
|
|
206
|
+
* @default false
|
|
179
207
|
*/
|
|
180
|
-
|
|
181
|
-
}
|
|
208
|
+
logRawSqlQueryParams?: boolean;
|
|
182
209
|
|
|
183
|
-
export interface ComplexQuerySchemaBuilder<T> {
|
|
184
210
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* @
|
|
188
|
-
* @returns The updated instance of the builder.
|
|
211
|
+
* Disables optimistic locking for all operations.
|
|
212
|
+
* When enabled, version checks are skipped during updates.
|
|
213
|
+
* @default false
|
|
189
214
|
*/
|
|
190
|
-
|
|
215
|
+
disableOptimisticLocking?: boolean;
|
|
191
216
|
|
|
192
217
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
218
|
+
* Additional metadata for table configuration.
|
|
219
|
+
* Allows specifying table-specific settings and behaviors.
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* {
|
|
223
|
+
* users: {
|
|
224
|
+
* tableName: "users",
|
|
225
|
+
* versionField: {
|
|
226
|
+
* fieldName: "updatedAt",
|
|
227
|
+
* type: "datetime",
|
|
228
|
+
* nullable: false
|
|
229
|
+
* }
|
|
230
|
+
* }
|
|
231
|
+
* }
|
|
232
|
+
* ```
|
|
195
233
|
*/
|
|
196
|
-
|
|
234
|
+
additionalMetadata?: AdditionalMetadata;
|
|
197
235
|
}
|
|
236
|
+
|
|
237
|
+
// ============= Custom Types =============
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Custom type for MySQL datetime fields.
|
|
241
|
+
* Handles conversion between JavaScript Date objects and MySQL datetime strings.
|
|
242
|
+
*/
|
|
243
|
+
export const mySqlDateTimeString = customType<{
|
|
244
|
+
data: Date;
|
|
245
|
+
driver: string;
|
|
246
|
+
config: { format?: string };
|
|
247
|
+
}>({
|
|
248
|
+
dataType() {
|
|
249
|
+
return "datetime";
|
|
250
|
+
},
|
|
251
|
+
toDriver(value: Date) {
|
|
252
|
+
return moment(value as Date).format("YYYY-MM-DDTHH:mm:ss.SSS");
|
|
253
|
+
},
|
|
254
|
+
fromDriver(value: unknown) {
|
|
255
|
+
const format = "YYYY-MM-DDTHH:mm:ss.SSS";
|
|
256
|
+
return parseDateTime(value as string, format);
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Custom type for MySQL timestamp fields.
|
|
262
|
+
* Handles conversion between JavaScript Date objects and MySQL timestamp strings.
|
|
263
|
+
*/
|
|
264
|
+
export const mySqlTimestampString = customType<{
|
|
265
|
+
data: Date;
|
|
266
|
+
driver: string;
|
|
267
|
+
config: { format?: string };
|
|
268
|
+
}>({
|
|
269
|
+
dataType() {
|
|
270
|
+
return "timestamp";
|
|
271
|
+
},
|
|
272
|
+
toDriver(value: Date) {
|
|
273
|
+
return moment(value as Date).format("YYYY-MM-DDTHH:mm:ss.SSS");
|
|
274
|
+
},
|
|
275
|
+
fromDriver(value: unknown) {
|
|
276
|
+
const format = "YYYY-MM-DDTHH:mm:ss.SSS";
|
|
277
|
+
return parseDateTime(value as string, format);
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Custom type for MySQL date fields.
|
|
283
|
+
* Handles conversion between JavaScript Date objects and MySQL date strings.
|
|
284
|
+
*/
|
|
285
|
+
export const mySqlDateString = customType<{
|
|
286
|
+
data: Date;
|
|
287
|
+
driver: string;
|
|
288
|
+
config: { format?: string };
|
|
289
|
+
}>({
|
|
290
|
+
dataType() {
|
|
291
|
+
return "date";
|
|
292
|
+
},
|
|
293
|
+
toDriver(value: Date) {
|
|
294
|
+
return moment(value as Date).format("YYYY-MM-DD");
|
|
295
|
+
},
|
|
296
|
+
fromDriver(value: unknown) {
|
|
297
|
+
const format = "YYYY-MM-DD";
|
|
298
|
+
return parseDateTime(value as string, format);
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Custom type for MySQL time fields.
|
|
304
|
+
* Handles conversion between JavaScript Date objects and MySQL time strings.
|
|
305
|
+
*/
|
|
306
|
+
export const mySqlTimeString = customType<{
|
|
307
|
+
data: Date;
|
|
308
|
+
driver: string;
|
|
309
|
+
config: { format?: string };
|
|
310
|
+
}>({
|
|
311
|
+
dataType() {
|
|
312
|
+
return "time";
|
|
313
|
+
},
|
|
314
|
+
toDriver(value: Date) {
|
|
315
|
+
return moment(value as Date).format("HH:mm:ss.SSS");
|
|
316
|
+
},
|
|
317
|
+
fromDriver(value: unknown) {
|
|
318
|
+
return parseDateTime(value as string, "HH:mm:ss.SSS");
|
|
319
|
+
},
|
|
320
|
+
});
|