forge-sql-orm 2.0.12 → 2.0.14
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 +10 -24
- package/dist/ForgeSQLORM.js +51 -19
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +51 -19
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/selectAliased.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts +1 -1
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/package.json +8 -18
- package/src/core/ForgeSQLCrudOperations.ts +1 -1
- package/src/core/ForgeSQLORM.ts +5 -4
- package/src/lib/drizzle/extensions/selectAliased.ts +56 -58
- package/src/lib/drizzle/extensions/types.d.ts +13 -13
- package/src/utils/sqlUtils.ts +96 -47
- package/dist-cli/cli.js +0 -965
- package/dist-cli/cli.js.map +0 -1
- package/dist-cli/cli.mjs +0 -964
- package/dist-cli/cli.mjs.map +0 -1
- package/dist-cli/forgeSqlOrmCLI.js +0 -19
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ Forge-SQL-ORM is designed to work with @forge/sql and requires some additional s
|
|
|
81
81
|
|
|
82
82
|
```sh
|
|
83
83
|
npm install forge-sql-orm @forge/sql drizzle-orm momment -S
|
|
84
|
-
npm install
|
|
84
|
+
npm install forge-sql-orm-cli -D
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
This will:
|
|
@@ -89,6 +89,7 @@ This will:
|
|
|
89
89
|
- Install @forge/sql, the Forge database layer
|
|
90
90
|
- Install Drizzle ORM and its MySQL driver
|
|
91
91
|
- Install TypeScript types for MySQL
|
|
92
|
+
- Install forge-sql-orm-cli A command-line interface tool for managing Atlassian Forge SQL migrations and model generation with Drizzle ORM integration.
|
|
92
93
|
|
|
93
94
|
## Direct Drizzle Usage with Custom Driver
|
|
94
95
|
|
|
@@ -127,7 +128,7 @@ This approach gives you direct access to all Drizzle ORM features while still us
|
|
|
127
128
|
1. **Generate initial schema from an existing database**
|
|
128
129
|
|
|
129
130
|
```sh
|
|
130
|
-
npx forge-sql-orm generate:model --dbName testDb --output ./database/schema
|
|
131
|
+
npx forge-sql-orm-cli generate:model --dbName testDb --output ./database/schema
|
|
131
132
|
```
|
|
132
133
|
|
|
133
134
|
_(This is done only once when setting up the project)_
|
|
@@ -135,7 +136,7 @@ This approach gives you direct access to all Drizzle ORM features while still us
|
|
|
135
136
|
2. **Create the first migration**
|
|
136
137
|
|
|
137
138
|
```sh
|
|
138
|
-
npx forge-sql-orm migrations:create --dbName testDb --entitiesPath ./database/schema --output ./database/migration
|
|
139
|
+
npx forge-sql-orm-cli migrations:create --dbName testDb --entitiesPath ./database/schema --output ./database/migration
|
|
139
140
|
```
|
|
140
141
|
|
|
141
142
|
_(This initializes the database migration structure, also done once)_
|
|
@@ -152,7 +153,7 @@ This approach gives you direct access to all Drizzle ORM features while still us
|
|
|
152
153
|
5. **Update the migration**
|
|
153
154
|
|
|
154
155
|
```sh
|
|
155
|
-
npx forge-sql-orm migrations:update --dbName testDb --entitiesPath ./database/schema --output ./database/migration
|
|
156
|
+
npx forge-sql-orm-cli migrations:update --dbName testDb --entitiesPath ./database/schema --output ./database/migration
|
|
156
157
|
```
|
|
157
158
|
|
|
158
159
|
- ⚠️ **Do NOT update schema before this step!**
|
|
@@ -165,7 +166,7 @@ This approach gives you direct access to all Drizzle ORM features while still us
|
|
|
165
166
|
7. **Update the schema**
|
|
166
167
|
|
|
167
168
|
```sh
|
|
168
|
-
npx forge-sql-orm generate:model --dbName testDb --output ./database/schema
|
|
169
|
+
npx forge-sql-orm-cli generate:model --dbName testDb --output ./database/schema
|
|
169
170
|
```
|
|
170
171
|
|
|
171
172
|
8. **Repeat steps 4-7 as needed**
|
|
@@ -194,12 +195,12 @@ Before using Drop Migrations, ensure that:
|
|
|
194
195
|
|
|
195
196
|
1. First, ensure your local schema matches the deployed database:
|
|
196
197
|
```bash
|
|
197
|
-
npx forge-sql-orm generate:model --output ./database/schema
|
|
198
|
+
npx forge-sql-orm-cli generate:model --output ./database/schema
|
|
198
199
|
```
|
|
199
200
|
|
|
200
201
|
2. Generate the drop migration:
|
|
201
202
|
```bash
|
|
202
|
-
npx forge-sql-orm migrations:drop --entitiesPath ./database/schema --output ./database/migration
|
|
203
|
+
npx forge-sql-orm-cli migrations:drop --entitiesPath ./database/schema --output ./database/migration
|
|
203
204
|
```
|
|
204
205
|
|
|
205
206
|
3. Deploy and run the migration in your Forge app:
|
|
@@ -214,7 +215,7 @@ Before using Drop Migrations, ensure that:
|
|
|
214
215
|
|
|
215
216
|
4. After dropping all tables, you can create a new migration to recreate the schema:
|
|
216
217
|
```bash
|
|
217
|
-
npx forge-sql-orm migrations:create --entitiesPath ./database/schema --output ./database/migration --force
|
|
218
|
+
npx forge-sql-orm-cli migrations:create --entitiesPath ./database/schema --output ./database/migration --force
|
|
218
219
|
```
|
|
219
220
|
The `--force` parameter is required here because we're creating a new migration after dropping all tables.
|
|
220
221
|
|
|
@@ -535,22 +536,7 @@ The `ForgeSqlOrmOptions` object allows customization of ORM behavior:
|
|
|
535
536
|
|
|
536
537
|
## CLI Commands
|
|
537
538
|
|
|
538
|
-
|
|
539
|
-
$ npx forge-sql-orm --help
|
|
540
|
-
|
|
541
|
-
Usage: forge-sql-orm [options] [command]
|
|
542
|
-
|
|
543
|
-
Options:
|
|
544
|
-
-V, --version Output the version number
|
|
545
|
-
-h, --help Display help for command
|
|
546
|
-
|
|
547
|
-
Commands:
|
|
548
|
-
generate:model [options] Generate Drizzle models from the database
|
|
549
|
-
migrations:create [options] Generate an initial migration for the entire database
|
|
550
|
-
migrations:update [options] Generate a migration to update the database schema
|
|
551
|
-
migrations:drop [options] Generate a migration to drop all tables
|
|
552
|
-
help [command] Display help for a specific command
|
|
553
|
-
```
|
|
539
|
+
Documentation [here](forge-sql-orm-cli/README.md)
|
|
554
540
|
|
|
555
541
|
## Web Triggers for Migrations
|
|
556
542
|
|
package/dist/ForgeSQLORM.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
3
|
const drizzleOrm = require("drizzle-orm");
|
|
4
4
|
const moment = require("moment");
|
|
5
|
-
const table = require("drizzle-orm/table");
|
|
6
5
|
const sql = require("drizzle-orm/sql/sql");
|
|
7
6
|
const sql$1 = require("@forge/sql");
|
|
8
7
|
const mysqlProxy = require("drizzle-orm/mysql-proxy");
|
|
9
8
|
const mysqlCore = require("drizzle-orm/mysql-core");
|
|
10
9
|
const moment$1 = require("moment/moment.js");
|
|
10
|
+
const table = require("drizzle-orm/table");
|
|
11
11
|
const parseDateTime = (value, format) => {
|
|
12
12
|
const m = moment(value, format, true);
|
|
13
13
|
if (!m.isValid()) {
|
|
@@ -131,12 +131,12 @@ function generateDropTableStatements(tables) {
|
|
|
131
131
|
dropStatements.push(`DELETE FROM __migrations;`);
|
|
132
132
|
return dropStatements;
|
|
133
133
|
}
|
|
134
|
-
function mapSelectTableToAlias(table2, aliasMap) {
|
|
134
|
+
function mapSelectTableToAlias(table2, uniqPrefix, 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 uniqName = `a_${tableName}_${column.name}
|
|
139
|
+
const uniqName = `a_${uniqPrefix}_${tableName}_${column.name}`.toLowerCase();
|
|
140
140
|
const fieldAlias = drizzleOrm.sql.raw(uniqName);
|
|
141
141
|
selectionsTableFields[name] = drizzleOrm.sql`${column} as \`${fieldAlias}\``;
|
|
142
142
|
aliasMap[uniqName] = column;
|
|
@@ -146,13 +146,13 @@ function mapSelectTableToAlias(table2, aliasMap) {
|
|
|
146
146
|
function isDrizzleColumn(column) {
|
|
147
147
|
return column && typeof column === "object" && "table" in column;
|
|
148
148
|
}
|
|
149
|
-
function mapSelectAllFieldsToAlias(selections, name, fields, aliasMap) {
|
|
149
|
+
function mapSelectAllFieldsToAlias(selections, name, uniqName, fields, aliasMap) {
|
|
150
150
|
if (drizzleOrm.isTable(fields)) {
|
|
151
|
-
selections[name] = mapSelectTableToAlias(fields, aliasMap);
|
|
151
|
+
selections[name] = mapSelectTableToAlias(fields, uniqName, aliasMap);
|
|
152
152
|
} else if (isDrizzleColumn(fields)) {
|
|
153
153
|
const column = fields;
|
|
154
|
-
const
|
|
155
|
-
let aliasName = drizzleOrm.sql.raw(
|
|
154
|
+
const uniqAliasName = `a_${uniqName}_${column.name}`.toLowerCase();
|
|
155
|
+
let aliasName = drizzleOrm.sql.raw(uniqAliasName);
|
|
156
156
|
selections[name] = drizzleOrm.sql`${column} as \`${aliasName}\``;
|
|
157
157
|
aliasMap[uniqName] = column;
|
|
158
158
|
} else if (sql.isSQLWrapper(fields)) {
|
|
@@ -160,7 +160,7 @@ function mapSelectAllFieldsToAlias(selections, name, fields, aliasMap) {
|
|
|
160
160
|
} else {
|
|
161
161
|
const innerSelections = {};
|
|
162
162
|
Object.entries(fields).forEach(([iname, ifields]) => {
|
|
163
|
-
mapSelectAllFieldsToAlias(innerSelections, iname, ifields, aliasMap);
|
|
163
|
+
mapSelectAllFieldsToAlias(innerSelections, iname, `${uniqName}_${iname}`, ifields, aliasMap);
|
|
164
164
|
});
|
|
165
165
|
selections[name] = innerSelections;
|
|
166
166
|
}
|
|
@@ -173,7 +173,7 @@ function mapSelectFieldsWithAlias(fields) {
|
|
|
173
173
|
const aliasMap = {};
|
|
174
174
|
const selections = {};
|
|
175
175
|
Object.entries(fields).forEach(([name, fields2]) => {
|
|
176
|
-
mapSelectAllFieldsToAlias(selections, name, fields2, aliasMap);
|
|
176
|
+
mapSelectAllFieldsToAlias(selections, name, name, fields2, aliasMap);
|
|
177
177
|
});
|
|
178
178
|
return { selections, aliasMap };
|
|
179
179
|
}
|
|
@@ -218,7 +218,11 @@ function transformObject(obj, selections, aliasMap) {
|
|
|
218
218
|
if (alias && aliasMap[alias]) {
|
|
219
219
|
result[key] = transformValue(value, alias, aliasMap);
|
|
220
220
|
} else if (selection && typeof selection === "object" && !sql.isSQLWrapper(selection)) {
|
|
221
|
-
result[key] = transformObject(
|
|
221
|
+
result[key] = transformObject(
|
|
222
|
+
value,
|
|
223
|
+
selection,
|
|
224
|
+
aliasMap
|
|
225
|
+
);
|
|
222
226
|
} else {
|
|
223
227
|
result[key] = value;
|
|
224
228
|
}
|
|
@@ -227,9 +231,38 @@ function transformObject(obj, selections, aliasMap) {
|
|
|
227
231
|
}
|
|
228
232
|
function applyFromDriverTransform(rows, selections, aliasMap) {
|
|
229
233
|
return rows.map((row) => {
|
|
230
|
-
|
|
234
|
+
const transformed = transformObject(
|
|
235
|
+
row,
|
|
236
|
+
selections,
|
|
237
|
+
aliasMap
|
|
238
|
+
);
|
|
239
|
+
return processNullBranches(transformed);
|
|
231
240
|
});
|
|
232
241
|
}
|
|
242
|
+
function processNullBranches(obj) {
|
|
243
|
+
if (obj === null || typeof obj !== "object" || obj === void 0) {
|
|
244
|
+
return obj;
|
|
245
|
+
}
|
|
246
|
+
const result = {};
|
|
247
|
+
let allNull = true;
|
|
248
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
249
|
+
if (value === null || value === void 0) {
|
|
250
|
+
result[key] = null;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (typeof value === "object" && (value !== null || value !== void 0)) {
|
|
254
|
+
const processed = processNullBranches(value);
|
|
255
|
+
result[key] = processed;
|
|
256
|
+
if (processed !== null) {
|
|
257
|
+
allNull = false;
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
result[key] = value;
|
|
261
|
+
allNull = false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return allNull ? null : result;
|
|
265
|
+
}
|
|
233
266
|
class ForgeSQLCrudOperations {
|
|
234
267
|
forgeOperations;
|
|
235
268
|
options;
|
|
@@ -620,13 +653,10 @@ function createAliasedSelectBuilder(db, fields, selectFn) {
|
|
|
620
653
|
};
|
|
621
654
|
}
|
|
622
655
|
if (prop === "then") {
|
|
623
|
-
return (onfulfilled, onrejected) => target.execute().then(
|
|
624
|
-
(rows
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
},
|
|
628
|
-
onrejected
|
|
629
|
-
);
|
|
656
|
+
return (onfulfilled, onrejected) => target.execute().then((rows) => {
|
|
657
|
+
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
658
|
+
return onfulfilled?.(transformed);
|
|
659
|
+
}, onrejected);
|
|
630
660
|
}
|
|
631
661
|
const value = Reflect.get(target, prop, receiver);
|
|
632
662
|
if (typeof value === "function") {
|
|
@@ -671,7 +701,9 @@ class ForgeSQLORMImpl {
|
|
|
671
701
|
if (newOptions.logRawSqlQuery) {
|
|
672
702
|
console.debug("Initializing ForgeSQLORM...");
|
|
673
703
|
}
|
|
674
|
-
this.drizzle = patchDbWithSelectAliased(
|
|
704
|
+
this.drizzle = patchDbWithSelectAliased(
|
|
705
|
+
mysqlProxy.drizzle(forgeDriver, { logger: newOptions.logRawSqlQuery })
|
|
706
|
+
);
|
|
675
707
|
this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);
|
|
676
708
|
this.fetchOperations = new ForgeSQLSelectOperations(newOptions);
|
|
677
709
|
} catch (error) {
|