metal-orm 1.1.10 → 1.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metal-orm",
3
- "version": "1.1.10",
3
+ "version": "1.1.11",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "engines": {
@@ -5,15 +5,20 @@ import { buildSchemaMetadata } from './schema.mjs';
5
5
  const escapeJsString = value => value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
6
6
 
7
7
  const sanitizePropertyName = columnName => {
8
- if (!columnName) return '';
8
+ if (typeof columnName !== 'string' || !columnName) return '';
9
9
  return columnName
10
10
  .replace(/\s+/g, '_')
11
11
  .replace(/[^a-zA-Z0-9_$]/g, '_')
12
12
  .replace(/^[0-9]/, '_$&');
13
13
  };
14
14
 
15
+ const normalizeColumns = columns =>
16
+ (Array.isArray(columns) ? columns : []).filter(
17
+ column => column && typeof column.name === 'string' && column.name.trim().length > 0
18
+ );
19
+
15
20
  const formatJsDoc = comment => {
16
- if (!comment) return null;
21
+ if (typeof comment !== 'string') return null;
17
22
  const normalized = comment.replace(/\r\n?/g, '\n').trim();
18
23
  if (!normalized) return null;
19
24
  const lines = normalized.split('\n').map(line => line.replace(/\*\//g, '*\\/'));
@@ -152,7 +157,7 @@ const buildColumnRemarks = column => {
152
157
 
153
158
  const buildColumnDoc = column => {
154
159
  const entries = [];
155
- if (column.comment) {
160
+ if (typeof column.comment === 'string' && column.comment) {
156
161
  entries.push(column.comment);
157
162
  }
158
163
  const defaultValue = formatDefaultValueForDoc(column.default);
@@ -190,12 +195,13 @@ const renderColumnExpression = (column, tablePk, tableSchema, defaultSchema, pro
190
195
  : `col.default(${expr}, ${def.code})`;
191
196
  }
192
197
  }
193
- if (column.references) {
198
+ if (
199
+ column.references &&
200
+ typeof column.references.table === 'string' &&
201
+ typeof column.references.column === 'string'
202
+ ) {
194
203
  const refTable = normalizeReferenceTable(column.references.table, tableSchema, defaultSchema);
195
- const refParts = [
196
- `table: '${escapeJsString(refTable)}'`,
197
- `column: '${escapeJsString(column.references.column)}'`
198
- ];
204
+ const refParts = [`table: '${escapeJsString(refTable)}'`, `column: '${escapeJsString(column.references.column)}'`];
199
205
  if (column.references.onDelete) refParts.push(`onDelete: '${escapeJsString(column.references.onDelete)}'`);
200
206
  if (column.references.onUpdate) refParts.push(`onUpdate: '${escapeJsString(column.references.onUpdate)}'`);
201
207
  expr = `col.references(${expr}, { ${refParts.join(', ')} })`;
@@ -277,9 +283,10 @@ const renderEntityClassLines = ({ table, className, naming, relations, resolveCl
277
283
  lines.push(`@Entity(${entityOpts})`);
278
284
  lines.push(`export class ${className} {`);
279
285
 
280
- const columnPropertyNames = new Set(table.columns.map(col => sanitizePropertyName(col.name)));
286
+ const tableColumns = normalizeColumns(table.columns);
287
+ const columnPropertyNames = new Set(tableColumns.map(col => sanitizePropertyName(col.name)));
281
288
 
282
- for (const col of table.columns) {
289
+ for (const col of tableColumns) {
283
290
  const propertyName = sanitizePropertyName(col.name);
284
291
  const rendered = renderColumnExpression(col, table.primaryKey, table.schema, defaultSchema, propertyName);
285
292
  appendJsDoc(lines, rendered.comment, ' ');
@@ -414,7 +421,9 @@ const computeTableUsage = (table, relations, defaultSchema, treeConfig) => {
414
421
  needsTreeChildrenDecorator: false
415
422
  };
416
423
 
417
- for (const col of table.columns) {
424
+ const tableColumns = normalizeColumns(table.columns);
425
+
426
+ for (const col of tableColumns) {
418
427
  usage.needsCol = true;
419
428
  const rendered = renderColumnExpression(col, table.primaryKey, table.schema, defaultSchema);
420
429
  if (rendered.decorator === 'PrimaryKey') {
@@ -552,7 +561,7 @@ export const renderEntityFile = (schema, options) => {
552
561
 
553
562
  // Views only need col and Column decorator
554
563
  for (const view of views) {
555
- if (view.columns.length > 0) {
564
+ if (normalizeColumns(view.columns).length > 0) {
556
565
  aggregateUsage.needsCol = true;
557
566
  aggregateUsage.needsColumnDecorator = true;
558
567
  }
@@ -1,33 +1,42 @@
1
- import { detectTreeTable, mapTreeTables } from './tree-detection.mjs';
2
-
3
- const normalizeName = name => (typeof name === 'string' && name.includes('.') ? name.split('.').pop() : name);
4
-
5
- export const mapRelations = (tables, naming) => {
6
- const relationMap = new Map();
7
- const relationKeys = new Map();
8
- const fkIndex = new Map();
9
- const uniqueSingleColumns = new Map();
10
-
11
- for (const table of tables) {
12
- relationMap.set(table.name, []);
13
- relationKeys.set(table.name, new Set());
14
- for (const col of table.columns) {
15
- if (col.references) {
16
- const list = fkIndex.get(table.name) || [];
17
- list.push(col);
18
- fkIndex.set(table.name, list);
19
- }
1
+ import { detectTreeTable, mapTreeTables } from './tree-detection.mjs';
2
+
3
+ const normalizeName = name => (typeof name === 'string' && name.includes('.') ? name.split('.').pop() : name);
4
+ const normalizeTableColumns = columns =>
5
+ (Array.isArray(columns) ? columns : []).filter(
6
+ col => col && typeof col.name === 'string' && col.name.trim().length > 0
7
+ );
8
+ const normalizeTables = tables => (Array.isArray(tables) ? tables : []);
9
+
10
+ export const mapRelations = (tables, naming) => {
11
+ const relationMap = new Map();
12
+ const relationKeys = new Map();
13
+ const fkIndex = new Map();
14
+ const uniqueSingleColumns = new Map();
15
+ const normalizedTables = normalizeTables(tables).filter(
16
+ table => table && typeof table.name === 'string' && table.name.trim().length > 0
17
+ );
18
+
19
+ for (const table of normalizedTables) {
20
+ const tableColumns = normalizeTableColumns(table.columns);
21
+ relationMap.set(table.name, []);
22
+ relationKeys.set(table.name, new Set());
23
+ for (const col of tableColumns) {
24
+ if (col.references) {
25
+ const list = fkIndex.get(table.name) || [];
26
+ list.push(col);
27
+ fkIndex.set(table.name, list);
28
+ }
20
29
  }
21
30
 
22
31
  const uniqueCols = new Set();
23
- if (Array.isArray(table.primaryKey) && table.primaryKey.length === 1) {
24
- uniqueCols.add(table.primaryKey[0]);
25
- }
26
- for (const col of table.columns) {
27
- if (col.unique) uniqueCols.add(col.name);
28
- }
29
- for (const idx of table.indexes || []) {
30
- if (!idx?.unique) continue;
32
+ if (Array.isArray(table.primaryKey) && table.primaryKey.length === 1) {
33
+ uniqueCols.add(table.primaryKey[0]);
34
+ }
35
+ for (const col of tableColumns) {
36
+ if (col.unique) uniqueCols.add(col.name);
37
+ }
38
+ for (const idx of table.indexes || []) {
39
+ if (!idx?.unique) continue;
31
40
  if (!Array.isArray(idx.columns) || idx.columns.length !== 1 || !idx.columns[0]?.column) continue;
32
41
  const columnName = idx.columns[0].column;
33
42
  if (idx.where) {
@@ -38,15 +47,15 @@ export const mapRelations = (tables, naming) => {
38
47
  uniqueCols.add(columnName);
39
48
  }
40
49
  uniqueSingleColumns.set(table.name, uniqueCols);
41
- }
42
-
43
- const findTable = name => {
44
- const norm = normalizeName(name);
45
- return tables.find(t => t.name === name || t.name === norm);
46
- };
47
-
50
+ }
51
+
52
+ const findTable = name => {
53
+ const norm = normalizeName(name);
54
+ return normalizedTables.find(t => t.name === name || t.name === norm);
55
+ };
56
+
48
57
  const pivotTables = new Set();
49
- for (const table of tables) {
58
+ for (const table of normalizedTables) {
50
59
  const fkCols = fkIndex.get(table.name) || [];
51
60
  const hasSelfReference = fkCols.some(c => normalizeName(c.references.table) === table.name);
52
61
  const distinctTargets = Array.from(new Set(fkCols.map(c => normalizeName(c.references.table))));
@@ -84,11 +93,11 @@ export const mapRelations = (tables, naming) => {
84
93
  }
85
94
  }
86
95
  }
87
- }
88
-
89
- for (const table of tables) {
90
- const fkCols = fkIndex.get(table.name) || [];
91
- for (const fk of fkCols) {
96
+ }
97
+
98
+ for (const table of normalizedTables) {
99
+ const fkCols = fkIndex.get(table.name) || [];
100
+ for (const fk of fkCols) {
92
101
  const targetTable = fk.references.table;
93
102
  const targetKey = normalizeName(targetTable);
94
103
  const belongsKey = relationKeys.get(table.name);
@@ -130,39 +139,44 @@ export const mapRelations = (tables, naming) => {
130
139
  return relationMap;
131
140
  };
132
141
 
133
- export const buildSchemaMetadata = (schema, naming) => {
134
- const tables = schema.tables.map(t => {
135
- const indexes = Array.isArray(t.indexes) ? t.indexes.map(idx => ({ ...idx })) : [];
136
- const uniqueSingleColumns = new Set(
137
- indexes
138
- .filter(idx => idx?.unique && !idx?.where && Array.isArray(idx.columns) && idx.columns.length === 1)
139
- .map(idx => idx.columns[0]?.column)
140
- .filter(Boolean)
141
- );
142
-
143
- return {
144
- name: t.name,
145
- schema: t.schema,
146
- columns: (t.columns || []).map(col => {
147
- const unique = col.unique !== undefined ? col.unique : uniqueSingleColumns.has(col.name) ? true : undefined;
148
- return { ...col, unique };
149
- }),
150
- primaryKey: t.primaryKey || [],
151
- indexes,
152
- isView: false
153
- };
154
- });
155
-
156
- const views = (schema.views || []).map(v => ({
157
- name: v.name,
158
- schema: v.schema,
159
- columns: (v.columns || []).map(col => ({ ...col })),
160
- primaryKey: [],
161
- indexes: [],
162
- isView: true,
163
- definition: v.definition,
164
- comment: v.comment
165
- }));
142
+ export const buildSchemaMetadata = (schema, naming) => {
143
+ const tables = normalizeTables(schema?.tables)
144
+ .filter(t => t && typeof t.name === 'string' && t.name.trim().length > 0)
145
+ .map(t => {
146
+ const columns = normalizeTableColumns(t.columns).map(col => ({ ...col }));
147
+ const indexes = Array.isArray(t.indexes) ? t.indexes.map(idx => ({ ...idx })) : [];
148
+ const uniqueSingleColumns = new Set(
149
+ indexes
150
+ .filter(idx => idx?.unique && !idx?.where && Array.isArray(idx.columns) && idx.columns.length === 1)
151
+ .map(idx => idx.columns[0]?.column)
152
+ .filter(Boolean)
153
+ );
154
+
155
+ return {
156
+ name: t.name,
157
+ schema: t.schema,
158
+ columns: columns.map(col => {
159
+ const unique = col.unique !== undefined ? col.unique : uniqueSingleColumns.has(col.name) ? true : undefined;
160
+ return { ...col, unique };
161
+ }),
162
+ primaryKey: t.primaryKey || [],
163
+ indexes,
164
+ isView: false
165
+ };
166
+ });
167
+
168
+ const views = normalizeTables(schema?.views)
169
+ .filter(v => v && typeof v.name === 'string' && v.name.trim().length > 0)
170
+ .map(v => ({
171
+ name: v.name,
172
+ schema: v.schema,
173
+ columns: normalizeTableColumns(v.columns).map(col => ({ ...col })),
174
+ primaryKey: [],
175
+ indexes: [],
176
+ isView: true,
177
+ definition: v.definition,
178
+ comment: v.comment
179
+ }));
166
180
 
167
181
  const allEntities = [...tables, ...views];
168
182
 
@@ -16,38 +16,40 @@
16
16
  * @param {Object} naming - Naming strategy instance
17
17
  * @returns {Object|null} Tree configuration if detected, null otherwise
18
18
  */
19
- export const detectTreeTable = (table, naming) => {
20
- const columns = table.columns || [];
21
- const columnNames = new Set(columns.map(c => c.name));
22
-
23
- // Common patterns for tree columns
24
- const parentPatterns = ['parentId', 'parent_id', 'parent'];
25
- const leftPatterns = ['lft', 'left', 'leftValue', 'left_value'];
26
- const rightPatterns = ['rght', 'right', 'rightValue', 'right_value'];
27
- const depthPatterns = ['depth', 'level', 'treeLevel', 'tree_level', 'cod_nivel'];
28
-
29
- // Find matching columns
30
- const parentCol = columns.find(c =>
31
- parentPatterns.includes(c.name) ||
32
- c.name.toLowerCase().includes('parent')
33
- );
34
-
35
- const leftCol = columns.find(c =>
36
- leftPatterns.includes(c.name) ||
37
- c.name.toLowerCase().includes('left')
38
- );
39
-
40
- const rightCol = columns.find(c =>
41
- rightPatterns.includes(c.name) ||
42
- c.name.toLowerCase().includes('right')
43
- );
44
-
45
- const depthCol = columns.find(c =>
46
- depthPatterns.includes(c.name) ||
47
- c.name.toLowerCase().includes('depth') ||
48
- c.name.toLowerCase().includes('level') ||
49
- c.name.toLowerCase().includes('nivel')
50
- );
19
+ export const detectTreeTable = (table, naming) => {
20
+ const columns = Array.isArray(table?.columns) ? table.columns : [];
21
+ const getColumnName = column =>
22
+ column && typeof column.name === 'string' && column.name.trim().length > 0 ? column.name : undefined;
23
+
24
+ // Common patterns for tree columns
25
+ const parentPatterns = ['parentId', 'parent_id', 'parent'];
26
+ const leftPatterns = ['lft', 'left', 'leftValue', 'left_value'];
27
+ const rightPatterns = ['rght', 'right', 'rightValue', 'right_value'];
28
+ const depthPatterns = ['depth', 'level', 'treeLevel', 'tree_level', 'cod_nivel'];
29
+
30
+ const matchesTreePattern = (column, patterns, term) => {
31
+ const name = getColumnName(column);
32
+ if (!name) return false;
33
+ return patterns.includes(name) || name.toLowerCase().includes(term);
34
+ };
35
+
36
+ // Find matching columns
37
+ const parentCol = columns.find(c => matchesTreePattern(c, parentPatterns, 'parent'));
38
+
39
+ const leftCol = columns.find(c => matchesTreePattern(c, leftPatterns, 'left'));
40
+
41
+ const rightCol = columns.find(c => matchesTreePattern(c, rightPatterns, 'right'));
42
+
43
+ const depthCol = columns.find(c => {
44
+ const name = getColumnName(c);
45
+ if (!name) return false;
46
+ return (
47
+ depthPatterns.includes(name) ||
48
+ name.toLowerCase().includes('depth') ||
49
+ name.toLowerCase().includes('level') ||
50
+ name.toLowerCase().includes('nivel')
51
+ );
52
+ });
51
53
 
52
54
  // Validate: must have parent, left, and right columns
53
55
  if (!parentCol || !leftCol || !rightCol) {
@@ -86,25 +88,29 @@ export const detectTreeTable = (table, naming) => {
86
88
  config.depthKey = depthCol.name;
87
89
  }
88
90
 
89
- // Detect scope columns (columns that might be used for multi-tree scoping)
90
- const scopeColumns = columns.filter(c => {
91
- // Skip tree columns and primary key
92
- if (c.name === config.parentKey || c.name === config.leftKey ||
93
- c.name === config.rightKey || c.name === config.depthKey) {
94
- return false;
95
- }
96
- // Skip if it's the primary key
97
- if (table.primaryKey?.includes(c.name)) {
98
- return false;
99
- }
100
- // Skip if it has a foreign key to another table
101
- if (c.references && c.references.table !== table.name) {
102
- return false;
103
- }
104
- // Look for columns that might be scope columns (e.g., tenantId, organizationId)
105
- const scopePatterns = ['tenant', 'organization', 'company', 'site', 'workspace'];
106
- return scopePatterns.some(pattern => c.name.toLowerCase().includes(pattern));
107
- }).map(c => c.name);
91
+ // Detect scope columns (columns that might be used for multi-tree scoping)
92
+ const scopeColumns = columns.filter(c => {
93
+ const name = getColumnName(c);
94
+ if (!name) {
95
+ return false;
96
+ }
97
+ // Skip tree columns and primary key
98
+ if (name === config.parentKey || name === config.leftKey ||
99
+ name === config.rightKey || name === config.depthKey) {
100
+ return false;
101
+ }
102
+ // Skip if it's the primary key
103
+ if (table.primaryKey?.includes(name)) {
104
+ return false;
105
+ }
106
+ // Skip if it has a foreign key to another table
107
+ if (c.references && c.references.table !== table.name) {
108
+ return false;
109
+ }
110
+ // Look for columns that might be scope columns (e.g., tenantId, organizationId)
111
+ const scopePatterns = ['tenant', 'organization', 'company', 'site', 'workspace'];
112
+ return scopePatterns.some(pattern => name.toLowerCase().includes(pattern));
113
+ }).map(c => getColumnName(c)).filter(Boolean);
108
114
 
109
115
  if (scopeColumns.length > 0) {
110
116
  config.scope = scopeColumns;
@@ -119,15 +125,15 @@ export const detectTreeTable = (table, naming) => {
119
125
  * @param {Object} naming - Naming strategy instance
120
126
  * @returns {Map} Map of table name to tree configuration
121
127
  */
122
- export const mapTreeTables = (tables, naming) => {
123
- const treeMap = new Map();
124
-
125
- for (const table of tables) {
126
- const treeConfig = detectTreeTable(table, naming);
127
- if (treeConfig) {
128
- treeMap.set(table.name, treeConfig);
129
- }
130
- }
128
+ export const mapTreeTables = (tables, naming) => {
129
+ const treeMap = new Map();
130
+
131
+ for (const table of Array.isArray(tables) ? tables : []) {
132
+ const treeConfig = detectTreeTable(table, naming);
133
+ if (treeConfig && table && typeof table.name === 'string' && table.name.trim().length > 0) {
134
+ treeMap.set(table.name, treeConfig);
135
+ }
136
+ }
131
137
 
132
138
  return treeMap;
133
139
  };
@@ -150,4 +156,4 @@ export const getTreeConfig = (tableName, treeMap) => {
150
156
  */
151
157
  export const isTreeTable = (tableName, treeMap) => {
152
158
  return treeMap.has(tableName);
153
- };
159
+ };
@@ -8,9 +8,7 @@ import type { ValueOperandInput } from '../core/ast/expression.js';
8
8
  import type { ExpressionNode } from '../core/ast/expression-nodes.js';
9
9
  import { BulkBaseExecutor, type BulkExecutorOptions } from './bulk-executor.base.js';
10
10
  import { createBulkExecutionContext, executeCompiled } from './bulk-context.js';
11
- import { splitIntoChunks, runWithConcurrency, runChunk, maybeTransaction, aggregateOutcomes, aggregateOutcomesWithTimings } from './bulk-utils.js';
12
-
13
- const DEFAULT_CHUNK_SIZE = 1000;
11
+ import { maybeTransaction } from './bulk-utils.js';
14
12
 
15
13
  interface DeleteExecutorOptions extends BulkExecutorOptions {
16
14
  by?: string;
@@ -30,7 +28,7 @@ export class BulkDeleteExecutor extends BulkBaseExecutor<DeleteExecutorOptions>
30
28
  this.byColumnName = options.by ?? findPrimaryKey(table);
31
29
  }
32
30
 
33
- protected async executeChunk(chunk: ValueOperandInput[], chunkIndex: number): Promise<ChunkOutcome> {
31
+ protected async executeChunk(chunk: ValueOperandInput[], _chunkIndex: number): Promise<ChunkOutcome> {
34
32
  const byColumn = this.table.columns[this.byColumnName];
35
33
  if (!byColumn) {
36
34
  throw new Error(
@@ -39,7 +37,7 @@ export class BulkDeleteExecutor extends BulkBaseExecutor<DeleteExecutorOptions>
39
37
  }
40
38
 
41
39
  const extraWhere = this.options.where;
42
- const inExpr = inList(byColumn, chunk as any);
40
+ const inExpr = inList(byColumn, chunk as unknown as Parameters<typeof inList>[1]);
43
41
  const finalWhere = extraWhere ? and(inExpr, extraWhere) : inExpr;
44
42
 
45
43
  const builder = new DeleteQueryBuilder(this.table).where(finalWhere as ExpressionNode);
@@ -4,6 +4,7 @@ import type { OrmSession } from '../orm/orm-session.js';
4
4
  import type { BulkInsertOptions, ChunkOutcome, InsertRow } from './bulk-types.js';
5
5
  import { BulkBaseExecutor, type BulkExecutorOptions } from './bulk-executor.base.js';
6
6
  import { resolveReturningColumns, flattenQueryResults, executeCompiled } from './bulk-context.js';
7
+ import type { ValueOperandInput } from '../core/ast/expression.js';
7
8
 
8
9
  interface InsertExecutorOptions extends BulkExecutorOptions {
9
10
  returning?: boolean | import('../schema/column-types.js').ColumnDef[];
@@ -20,25 +21,24 @@ export class BulkInsertExecutor extends BulkBaseExecutor<InsertExecutorOptions>
20
21
  super(session, table, rows, options);
21
22
  }
22
23
 
23
- protected async executeChunk(chunk: InsertRow[], chunkIndex: number): Promise<ChunkOutcome> {
24
+ protected async executeChunk(chunk: InsertRow[], _chunkIndex: number): Promise<ChunkOutcome> {
24
25
  const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
25
26
 
26
- let builder: InsertQueryBuilder<unknown> | ConflictBuilder<unknown> =
27
- new InsertQueryBuilder(this.table).values(chunk);
27
+ let builder: InsertQueryBuilder<unknown> | ConflictBuilder<unknown> = new InsertQueryBuilder(this.table).values(chunk);
28
28
 
29
29
  if (this.options.onConflict) {
30
30
  const conflictColumns = this.options.onConflict.target?.columns ?? [];
31
- builder = (builder as InsertQueryBuilder<unknown>).onConflict(conflictColumns as any);
31
+ const conflictBuilder = (builder as InsertQueryBuilder<unknown>).onConflict(conflictColumns);
32
32
 
33
33
  if (this.options.onConflict.action.type === 'DoNothing') {
34
- builder = (builder as ConflictBuilder<unknown>).doNothing();
34
+ builder = conflictBuilder.doNothing();
35
35
  } else if (this.options.onConflict.action.type === 'DoUpdate' && this.options.onConflict.action.set) {
36
- const setMap: Record<string, unknown> = {};
36
+ const setMap: Record<string, ValueOperandInput> = {};
37
37
  for (const assignment of this.options.onConflict.action.set) {
38
38
  const colName = typeof assignment.column === 'object' ? assignment.column.name : assignment.column;
39
39
  setMap[colName] = assignment.value;
40
40
  }
41
- builder = (builder as ConflictBuilder<unknown>).doUpdate(setMap as any);
41
+ builder = conflictBuilder.doUpdate(setMap);
42
42
  }
43
43
  }
44
44
 
@@ -34,7 +34,7 @@ export class BulkUpdateExecutor extends BulkBaseExecutor<UpdateExecutorOptions>
34
34
  this.byColumns = resolveByColumns(table, options.by);
35
35
  }
36
36
 
37
- protected async executeChunk(chunk: UpdateRow[], chunkIndex: number): Promise<ChunkOutcome> {
37
+ protected async executeChunk(chunk: UpdateRow[], _chunkIndex: number): Promise<ChunkOutcome> {
38
38
  const allReturning: Record<string, unknown>[] = [];
39
39
  const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
40
40
  const extraWhere = this.options.where;
@@ -152,7 +152,7 @@ export async function bulkUpdateWhere<TTable extends TableDef>(
152
152
  const buildTask = (chunk: ValueOperandInput[], chunkIndex: number) => async (): Promise<ChunkOutcome> => {
153
153
  return runChunk(
154
154
  async () => {
155
- const inExpr = inList(byColumn, chunk as any);
155
+ const inExpr = inList(byColumn, chunk as unknown as Parameters<typeof inList>[1]);
156
156
  const finalWhere = extraWhere ? and(inExpr, extraWhere) : inExpr;
157
157
 
158
158
  let builder = new UpdateQueryBuilder(table).set(set as Record<string, unknown>).where(finalWhere);
@@ -3,12 +3,10 @@ import { findPrimaryKey } from '../query-builder/hydration-planner.js';
3
3
  import type { TableDef } from '../schema/table.js';
4
4
  import type { OrmSession } from '../orm/orm-session.js';
5
5
  import type { BulkUpsertOptions, ChunkOutcome, InsertRow } from './bulk-types.js';
6
- import type { UpsertClause } from '../core/ast/query.js';
7
6
  import type { ValueOperandInput } from '../core/ast/expression.js';
8
7
  import type { ColumnNode } from '../core/ast/expression.js';
9
8
  import { BulkBaseExecutor, type BulkExecutorOptions } from './bulk-executor.base.js';
10
- import { resolveReturningColumns, flattenQueryResults, executeCompiled, createBulkExecutionContext } from './bulk-context.js';
11
- import { splitIntoChunks, runWithConcurrency, runChunk, maybeTransaction, aggregateOutcomes, aggregateOutcomesWithTimings } from './bulk-utils.js';
9
+ import { resolveReturningColumns, flattenQueryResults, executeCompiled } from './bulk-context.js';
12
10
 
13
11
  interface UpsertExecutorOptions extends BulkExecutorOptions {
14
12
  conflictColumns?: string[];
@@ -44,22 +42,22 @@ export class BulkUpsertExecutor extends BulkBaseExecutor<UpsertExecutorOptions>
44
42
  Object.keys(rows[0] ?? {}).filter(col => !conflictSet.has(col) && col in table.columns);
45
43
  }
46
44
 
47
- protected async executeChunk(chunk: InsertRow[], chunkIndex: number): Promise<ChunkOutcome> {
45
+ protected async executeChunk(chunk: InsertRow[], _chunkIndex: number): Promise<ChunkOutcome> {
48
46
  const returningColumns = resolveReturningColumns(this.ctx, this.table, this.options.returning);
49
47
 
50
48
  const set: Record<string, ValueOperandInput> = {};
51
49
  for (const col of this.updateColumns) {
52
- set[col] = { type: 'ExcludedColumn', name: col } as any;
50
+ set[col] = { type: 'ExcludedColumn', name: col } as unknown as ValueOperandInput;
53
51
  }
54
52
 
55
53
  let builder: InsertQueryBuilder<unknown>;
56
54
 
57
55
  if (this.updateColumns.length === 0) {
58
- builder = new InsertQueryBuilder(this.table).values(chunk).onConflict(this.conflictTargetNodes as any).doNothing();
56
+ builder = new InsertQueryBuilder(this.table).values(chunk).onConflict(this.conflictTargetNodes).doNothing();
59
57
  } else {
60
58
  builder = new InsertQueryBuilder(this.table)
61
59
  .values(chunk)
62
- .onConflict(this.conflictTargetNodes as any)
60
+ .onConflict(this.conflictTargetNodes)
63
61
  .doUpdate(set);
64
62
  }
65
63