metal-orm 1.1.22 → 1.1.23

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.
@@ -0,0 +1,30 @@
1
+ import type { ProcedureCallNode } from '../../ast/procedure.js';
2
+ import type { CompiledQuery } from '../abstract.js';
3
+
4
+ export interface CompiledProcedureCall extends CompiledQuery {
5
+ outParams: {
6
+ source: 'none' | 'firstResultSet' | 'lastResultSet';
7
+ names: string[];
8
+ };
9
+ }
10
+
11
+ /**
12
+ * Optional dialect capability for stored-procedure compilation.
13
+ *
14
+ * Dialects that do not support procedures simply do not implement this
15
+ * interface; unsupported behavior is resolved at the capability boundary
16
+ * rather than through mandatory methods that only throw.
17
+ */
18
+ export interface ProcedureCompiler {
19
+ compileProcedureCall(ast: ProcedureCallNode): CompiledProcedureCall;
20
+ }
21
+
22
+ export const isProcedureCompiler = (value: unknown): value is ProcedureCompiler =>
23
+ typeof (value as { compileProcedureCall?: unknown } | null)?.compileProcedureCall === 'function';
24
+
25
+ export const requireProcedureCompiler = (value: unknown): ProcedureCompiler => {
26
+ if (!isProcedureCompiler(value)) {
27
+ throw new Error('Stored procedures are not supported by this dialect.');
28
+ }
29
+ return value;
30
+ };
@@ -1,7 +1,7 @@
1
1
  // Dialect factory for the SQL DSL.
2
2
  // Centralizes how we go from a symbolic name ("sqlite") to a concrete Dialect instance.
3
3
 
4
- import { Dialect } from './abstract.js';
4
+ import type { Dialect } from './abstract.js';
5
5
  import { PostgresDialect } from './postgres/index.js';
6
6
  import { MySqlDialect } from './mysql/index.js';
7
7
  import { SqliteDialect } from './sqlite/index.js';
@@ -42,9 +42,8 @@ export class DialectFactory {
42
42
  /**
43
43
  * Register (or override) a dialect factory for a key.
44
44
  *
45
- * Examples:
46
- * DialectFactory.register('sqlite', () => new SqliteDialect());
47
- * DialectFactory.register('my-tenant-dialect', () => new CustomDialect());
45
+ * Implementations are structural: extending DialectBase/SqlDialectBase is
46
+ * optional. A composed object satisfying Dialect is a valid registration.
48
47
  */
49
48
  public static register(key: DialectKey, factory: DialectFactoryFn): void {
50
49
  this.registry.set(key, factory);
@@ -1,4 +1,5 @@
1
- import { CompilerContext, CompiledProcedureCall } from '../abstract.js';
1
+ import { CompilerContext } from '../abstract.js';
2
+ import type { CompiledProcedureCall, ProcedureCompiler } from '../capabilities/procedure-compiler.js';
2
3
  import {
3
4
  SelectQueryNode,
4
5
  InsertQueryNode,
@@ -21,7 +22,7 @@ const toProcedureParamReference = (value: string): string =>
21
22
  /**
22
23
  * Microsoft SQL Server dialect implementation
23
24
  */
24
- export class SqlServerDialect extends SqlDialectBase {
25
+ export class SqlServerDialect extends SqlDialectBase implements ProcedureCompiler {
25
26
  protected readonly dialect = 'mssql';
26
27
  /**
27
28
  * Creates a new SqlServerDialect instance
@@ -1,4 +1,5 @@
1
- import { CompilerContext, CompiledProcedureCall } from '../abstract.js';
1
+ import { CompilerContext } from '../abstract.js';
2
+ import type { CompiledProcedureCall, ProcedureCompiler } from '../capabilities/procedure-compiler.js';
2
3
  import { JsonPathNode, IsDistinctExpressionNode } from '../../ast/expression.js';
3
4
  import { InsertQueryNode } from '../../ast/query.js';
4
5
  import { SqlDialectBase } from '../base/sql-dialect.js';
@@ -11,7 +12,7 @@ const sanitizeVariableSuffix = (value: string): string =>
11
12
  /**
12
13
  * MySQL dialect implementation
13
14
  */
14
- export class MySqlDialect extends SqlDialectBase {
15
+ export class MySqlDialect extends SqlDialectBase implements ProcedureCompiler {
15
16
  protected readonly dialect = 'mysql';
16
17
  /**
17
18
  * Creates a new MySqlDialect instance
@@ -1,4 +1,5 @@
1
- import { CompilerContext, CompiledProcedureCall } from '../abstract.js';
1
+ import { CompilerContext } from '../abstract.js';
2
+ import type { CompiledProcedureCall, ProcedureCompiler } from '../capabilities/procedure-compiler.js';
2
3
  import { JsonPathNode, ColumnNode, BitwiseExpressionNode } from '../../ast/expression.js';
3
4
  import { InsertQueryNode, TableNode } from '../../ast/query.js';
4
5
  import { SqlDialectBase } from '../base/sql-dialect.js';
@@ -9,7 +10,7 @@ import { ProcedureCallNode } from '../../ast/procedure.js';
9
10
  /**
10
11
  * PostgreSQL dialect implementation
11
12
  */
12
- export class PostgresDialect extends SqlDialectBase {
13
+ export class PostgresDialect extends SqlDialectBase implements ProcedureCompiler {
13
14
  protected readonly dialect = 'postgres';
14
15
  /**
15
16
  * Creates a new PostgresDialect instance
@@ -1,9 +1,8 @@
1
- import { CompilerContext, CompiledProcedureCall } from '../abstract.js';
1
+ import { CompilerContext } from '../abstract.js';
2
2
  import { JsonPathNode, ColumnNode, BitwiseExpressionNode } from '../../ast/expression.js';
3
3
  import { InsertQueryNode, TableNode } from '../../ast/query.js';
4
4
  import { SqlDialectBase } from '../base/sql-dialect.js';
5
5
  import { SqliteFunctionStrategy } from './functions.js';
6
- import { ProcedureCallNode } from '../../ast/procedure.js';
7
6
 
8
7
  /**
9
8
  * SQLite dialect implementation
@@ -104,9 +103,4 @@ export class SqliteDialect extends SqlDialectBase {
104
103
  supportsDmlReturningClause(): boolean {
105
104
  return true;
106
105
  }
107
-
108
- compileProcedureCall(_ast: ProcedureCallNode): CompiledProcedureCall {
109
- void _ast;
110
- throw new Error('Stored procedures are not supported by the SQLite dialect.');
111
- }
112
106
  }
package/src/index.ts CHANGED
@@ -17,6 +17,9 @@ export * from './core/ast/expression.js';
17
17
  export * from './core/ast/procedure.js';
18
18
  export * from './core/ast/window-functions.js';
19
19
  export * from './core/hydration/types.js';
20
+ export * from './core/dialect/abstract.js';
21
+ export * from './core/dialect/dialect-factory.js';
22
+ export * from './core/dialect/capabilities/procedure-compiler.js';
20
23
  export * from './core/dialect/mysql/index.js';
21
24
  export * from './core/dialect/mssql/index.js';
22
25
  export * from './core/dialect/sqlite/index.js';
@@ -85,4 +88,4 @@ export * from './tree/index.js';
85
88
  export * from './cache/index.js';
86
89
 
87
90
  // Bulk operations module
88
- export * from './bulk/index.js';
91
+ export * from './bulk/index.js';
@@ -1,7 +1,8 @@
1
1
  import type { ProcedureCallNode } from '../core/ast/procedure.js';
2
2
  import type { QueryResult } from '../core/execution/db-executor.js';
3
3
  import { payloadResultSets } from '../core/execution/db-executor.js';
4
- import type { CompiledProcedureCall } from '../core/dialect/abstract.js';
4
+ import type { CompiledProcedureCall } from '../core/dialect/capabilities/procedure-compiler.js';
5
+ import { requireProcedureCompiler } from '../core/dialect/capabilities/procedure-compiler.js';
5
6
  import type { OrmSession } from './orm-session.js';
6
7
 
7
8
  export interface ProcedureExecutionResult {
@@ -63,7 +64,7 @@ export const executeProcedureAst = async (
63
64
  ast: ProcedureCallNode
64
65
  ): Promise<ProcedureExecutionResult> => {
65
66
  const execCtx = session.getExecutionContext();
66
- const compiled = execCtx.dialect.compileProcedureCall(ast);
67
+ const compiled = requireProcedureCompiler(execCtx.dialect).compileProcedureCall(ast);
67
68
  const payload = await execCtx.interceptors.run(
68
69
  { sql: compiled.sql, params: compiled.params },
69
70
  execCtx.executor
@@ -1,5 +1,7 @@
1
1
  import type { ProcedureCallNode, ProcedureParamNode } from '../core/ast/procedure.js';
2
- import type { CompiledProcedureCall, Dialect } from '../core/dialect/abstract.js';
2
+ import type { Dialect } from '../core/dialect/abstract.js';
3
+ import type { CompiledProcedureCall } from '../core/dialect/capabilities/procedure-compiler.js';
4
+ import { requireProcedureCompiler } from '../core/dialect/capabilities/procedure-compiler.js';
3
5
  import { DialectKey, resolveDialectInput } from '../core/dialect/dialect-factory.js';
4
6
  import { valueToOperand, ValueOperandInput } from '../core/ast/expression-builders.js';
5
7
  import type { OrmSession } from '../orm/orm-session.js';
@@ -82,8 +84,7 @@ export class ProcedureCallBuilder {
82
84
 
83
85
  compile(dialect: ProcedureDialectInput): CompiledProcedureCall {
84
86
  const resolved = resolveDialectInput(dialect);
85
- this.validateMssqlOutDbType(resolved);
86
- return resolved.compileProcedureCall(this.getAST());
87
+ return requireProcedureCompiler(resolved).compileProcedureCall(this.getAST());
87
88
  }
88
89
 
89
90
  toSql(dialect: ProcedureDialectInput): string {
@@ -99,23 +100,8 @@ export class ProcedureCallBuilder {
99
100
  }
100
101
 
101
102
  async execute(session: OrmSession): Promise<ProcedureExecutionResult> {
102
- this.validateMssqlOutDbType(session.getExecutionContext().dialect);
103
103
  return executeProcedureAst(session, this.getAST());
104
104
  }
105
-
106
- private validateMssqlOutDbType(dialect: Dialect): void {
107
- const isMssqlDialect = dialect.constructor.name === 'SqlServerDialect';
108
- if (!isMssqlDialect) return;
109
-
110
- for (const param of this.ast.params) {
111
- const needsDbType = param.direction === 'out' || param.direction === 'inout';
112
- if (needsDbType && !param.dbType) {
113
- throw new Error(
114
- `MSSQL requires "dbType" for procedure parameter "${param.name}" with direction "${param.direction}".`
115
- );
116
- }
117
- }
118
- }
119
105
  }
120
106
 
121
107
  export const callProcedure = (name: string, options?: CallProcedureOptions): ProcedureCallBuilder =>