@effect/sql-mssql 4.0.0-beta.8 → 4.0.0-beta.81

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.
@@ -1,7 +1,19 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Microsoft SQL Server client implementation for Effect SQL, backed by the
3
+ * `tedious` driver.
4
+ *
5
+ * This module provides the `MssqlClient` service, constructors, layers, and SQL
6
+ * Server statement compiler. `make` creates a pooled Tedious client, checks the
7
+ * connection with `SELECT 1`, maps SQL Server failures to `SqlError`, and
8
+ * supports transactions with savepoints. The SQL Server-specific service adds
9
+ * typed Tedious parameters with `param`, stored procedure calls with `call`,
10
+ * direct or config-backed layers, and default parameter type mappings.
11
+ * Streaming queries are not implemented by this driver.
12
+ *
13
+ * @since 4.0.0
3
14
  */
4
15
  import * as Config from "effect/Config"
16
+ import * as Context from "effect/Context"
5
17
  import * as Duration from "effect/Duration"
6
18
  import * as Effect from "effect/Effect"
7
19
  import { identity } from "effect/Function"
@@ -9,12 +21,23 @@ import * as Layer from "effect/Layer"
9
21
  import * as Pool from "effect/Pool"
10
22
  import * as Redacted from "effect/Redacted"
11
23
  import * as Scope from "effect/Scope"
12
- import * as ServiceMap from "effect/ServiceMap"
13
24
  import * as Stream from "effect/Stream"
14
25
  import * as Reactivity from "effect/unstable/reactivity/Reactivity"
15
26
  import * as Client from "effect/unstable/sql/SqlClient"
16
27
  import type { Connection } from "effect/unstable/sql/SqlConnection"
17
- import { SqlError } from "effect/unstable/sql/SqlError"
28
+ import {
29
+ AuthenticationError,
30
+ AuthorizationError,
31
+ ConnectionError,
32
+ ConstraintError,
33
+ DeadlockError,
34
+ LockTimeoutError,
35
+ SerializationError,
36
+ SqlError,
37
+ SqlSyntaxError,
38
+ UniqueViolation,
39
+ UnknownError
40
+ } from "effect/unstable/sql/SqlError"
18
41
  import * as Statement from "effect/unstable/sql/Statement"
19
42
  import * as Tedious from "tedious"
20
43
  import type { ConnectionOptions } from "tedious/lib/connection.ts"
@@ -28,21 +51,116 @@ const ATTR_DB_NAMESPACE = "db.namespace"
28
51
  const ATTR_SERVER_ADDRESS = "server.address"
29
52
  const ATTR_SERVER_PORT = "server.port"
30
53
 
54
+ const mssqlNumberFromCause = (cause: unknown): number | undefined => {
55
+ if (typeof cause !== "object" || cause === null || !("number" in cause)) {
56
+ return undefined
57
+ }
58
+ const number = cause.number
59
+ return typeof number === "number" ? number : undefined
60
+ }
61
+
62
+ const mssqlConnectionErrorCodes = new Set([233, 10054])
63
+ const mssqlAuthenticationErrorCodes = new Set([4060, 18452, 18456])
64
+ const mssqlAuthorizationErrorCodes = new Set([229, 230, 262, 297, 300])
65
+ const mssqlSyntaxErrorCodes = new Set([102, 207, 208, 2714])
66
+ const mssqlConstraintErrorCodes = new Set([515, 547])
67
+
68
+ const UNKNOWN_CONSTRAINT = "unknown"
69
+
70
+ const normalizeConstraintIdentifier = (identifier: unknown): string => {
71
+ if (typeof identifier !== "string") {
72
+ return UNKNOWN_CONSTRAINT
73
+ }
74
+ const trimmed = identifier.trim()
75
+ return trimmed.length === 0 ? UNKNOWN_CONSTRAINT : trimmed
76
+ }
77
+
78
+ const mssqlCauseProperty = (cause: unknown, property: "constraint" | "message"): unknown => {
79
+ if (typeof cause !== "object" || cause === null || !(property in cause)) {
80
+ return undefined
81
+ }
82
+ return (cause as Record<string, unknown>)[property]
83
+ }
84
+
85
+ const mssqlUniqueViolationConstraintFromMessage = (number: 2601 | 2627, message: unknown): string => {
86
+ if (typeof message !== "string") {
87
+ return UNKNOWN_CONSTRAINT
88
+ }
89
+ const match = number === 2627 ?
90
+ /\bconstraint\s+'([^']*)'/i.exec(message) :
91
+ /\bunique index\s+'([^']*)'/i.exec(message)
92
+ return match === null ? UNKNOWN_CONSTRAINT : normalizeConstraintIdentifier(match[1])
93
+ }
94
+
95
+ const mssqlUniqueViolationConstraintFromCause = (number: 2601 | 2627, cause: unknown): string => {
96
+ const constraint = normalizeConstraintIdentifier(mssqlCauseProperty(cause, "constraint"))
97
+ if (constraint !== UNKNOWN_CONSTRAINT) {
98
+ return constraint
99
+ }
100
+ return mssqlUniqueViolationConstraintFromMessage(number, mssqlCauseProperty(cause, "message"))
101
+ }
102
+
103
+ const classifyError = (
104
+ cause: unknown,
105
+ message: string,
106
+ operation: string,
107
+ fallback: "connection" | "unknown" = "unknown"
108
+ ) => {
109
+ const props = { cause, message, operation }
110
+ const number = mssqlNumberFromCause(cause)
111
+ if (number !== undefined) {
112
+ if (mssqlConnectionErrorCodes.has(number)) {
113
+ return new ConnectionError(props)
114
+ }
115
+ if (mssqlAuthenticationErrorCodes.has(number)) {
116
+ return new AuthenticationError(props)
117
+ }
118
+ if (mssqlAuthorizationErrorCodes.has(number)) {
119
+ return new AuthorizationError(props)
120
+ }
121
+ if (mssqlSyntaxErrorCodes.has(number)) {
122
+ return new SqlSyntaxError(props)
123
+ }
124
+ if (number === 2601 || number === 2627) {
125
+ return new UniqueViolation({ ...props, constraint: mssqlUniqueViolationConstraintFromCause(number, cause) })
126
+ }
127
+ if (mssqlConstraintErrorCodes.has(number)) {
128
+ return new ConstraintError(props)
129
+ }
130
+ if (number === 1205) {
131
+ return new DeadlockError(props)
132
+ }
133
+ if (number === 3960) {
134
+ return new SerializationError(props)
135
+ }
136
+ if (number === 1222) {
137
+ return new LockTimeoutError(props)
138
+ }
139
+ }
140
+ return fallback === "connection" ? new ConnectionError(props) : new UnknownError(props)
141
+ }
142
+
31
143
  /**
32
- * @category type ids
33
- * @since 1.0.0
144
+ * Runtime type identifier used to mark `MssqlClient` values.
145
+ *
146
+ * @category type IDs
147
+ * @since 4.0.0
34
148
  */
35
149
  export const TypeId: unique symbol = Symbol.for("@effect/sql-mssql/MssqlClient")
36
150
 
37
151
  /**
38
- * @category type ids
39
- * @since 1.0.0
152
+ * Type-level identifier used to mark `MssqlClient` values.
153
+ *
154
+ * @category type IDs
155
+ * @since 4.0.0
40
156
  */
41
157
  export type TypeId = typeof TypeId
42
158
 
43
159
  /**
160
+ * Microsoft SQL Server client service, extending `SqlClient` with typed parameter fragments and stored procedure calls.
161
+ *
44
162
  * @category models
45
- * @since 1.0.0
163
+ * @since 4.0.0
46
164
  */
47
165
  export interface MssqlClient extends Client.SqlClient {
48
166
  readonly [TypeId]: TypeId
@@ -65,14 +183,23 @@ export interface MssqlClient extends Client.SqlClient {
65
183
  }
66
184
 
67
185
  /**
68
- * @category tags
69
- * @since 1.0.0
186
+ * Service tag for the Microsoft SQL Server client service.
187
+ *
188
+ * **When to use**
189
+ *
190
+ * Use to access or provide a Microsoft SQL Server client through the Effect
191
+ * context.
192
+ *
193
+ * @category services
194
+ * @since 4.0.0
70
195
  */
71
- export const MssqlClient = ServiceMap.Service<MssqlClient>("@effect/sql-mssql/MssqlClient")
196
+ export const MssqlClient = Context.Service<MssqlClient>("@effect/sql-mssql/MssqlClient")
72
197
 
73
198
  /**
199
+ * Configuration for a Microsoft SQL Server client, including connection, authentication, pool, parameter type, span attribute, and query/result name transform options.
200
+ *
74
201
  * @category models
75
- * @since 1.0.0
202
+ * @since 4.0.0
76
203
  */
77
204
  export interface MssqlClientConfig {
78
205
  readonly domain?: string | undefined
@@ -111,14 +238,18 @@ interface MssqlConnection extends Connection {
111
238
  readonly rollback: (name?: string) => Effect.Effect<void, SqlError>
112
239
  }
113
240
 
114
- const TransactionConnection = Client.TransactionConnection as unknown as ServiceMap.Service<
241
+ const TransactionConnection = Client.TransactionConnection as unknown as (clientId: number) => Context.Service<
115
242
  readonly [conn: MssqlConnection, counter: number],
116
243
  readonly [conn: MssqlConnection, counter: number]
117
244
  >
118
245
 
246
+ let clientIdCounter = 0
247
+
119
248
  /**
249
+ * Creates a scoped Microsoft SQL Server client backed by a connection pool, with transaction and stored procedure support. Streaming queries are not implemented.
250
+ *
120
251
  * @category constructors
121
- * @since 1.0.0
252
+ * @since 4.0.0
122
253
  */
123
254
  export const make = (
124
255
  options: MssqlClientConfig
@@ -174,7 +305,9 @@ export const make = (
174
305
  yield* Effect.callback<void, SqlError>((resume) => {
175
306
  conn.connect((cause) => {
176
307
  if (cause) {
177
- resume(Effect.fail(new SqlError({ cause, message: "Failed to connect" })))
308
+ resume(
309
+ Effect.fail(new SqlError({ reason: classifyError(cause, "Failed to connect", "connect", "connection") }))
310
+ )
178
311
  } else {
179
312
  resume(Effect.void)
180
313
  }
@@ -189,7 +322,9 @@ export const make = (
189
322
  Effect.callback<any, SqlError>((resume) => {
190
323
  const req = new Tedious.Request(sql, (cause, _rowCount, result) => {
191
324
  if (cause) {
192
- resume(Effect.fail(new SqlError({ cause, message: "Failed to execute statement" })))
325
+ resume(
326
+ Effect.fail(new SqlError({ reason: classifyError(cause, "Failed to execute statement", "execute") }))
327
+ )
193
328
  return
194
329
  }
195
330
 
@@ -232,7 +367,9 @@ export const make = (
232
367
  escape(procedure.name),
233
368
  (cause, _, rows) => {
234
369
  if (cause) {
235
- resume(Effect.fail(new SqlError({ cause, message: "Failed to execute statement" })))
370
+ resume(
371
+ Effect.fail(new SqlError({ reason: classifyError(cause, "Failed to execute statement", "execute") }))
372
+ )
236
373
  } else {
237
374
  rows = rowsToObjects(rows)
238
375
  if (transformRows) {
@@ -291,7 +428,13 @@ export const make = (
291
428
  begin: Effect.callback<void, SqlError>((resume) => {
292
429
  conn.beginTransaction((cause) => {
293
430
  if (cause) {
294
- resume(Effect.fail(new SqlError({ cause, message: "Failed to begin transaction" })))
431
+ resume(
432
+ Effect.fail(
433
+ new SqlError({
434
+ reason: classifyError(cause, "Failed to begin transaction", "beginTransaction")
435
+ })
436
+ )
437
+ )
295
438
  } else {
296
439
  resume(Effect.void)
297
440
  }
@@ -300,7 +443,13 @@ export const make = (
300
443
  commit: Effect.callback<void, SqlError>((resume) => {
301
444
  conn.commitTransaction((cause) => {
302
445
  if (cause) {
303
- resume(Effect.fail(new SqlError({ cause, message: "Failed to commit transaction" })))
446
+ resume(
447
+ Effect.fail(
448
+ new SqlError({
449
+ reason: classifyError(cause, "Failed to commit transaction", "commitTransaction")
450
+ })
451
+ )
452
+ )
304
453
  } else {
305
454
  resume(Effect.void)
306
455
  }
@@ -310,7 +459,11 @@ export const make = (
310
459
  Effect.callback<void, SqlError>((resume) => {
311
460
  conn.saveTransaction((cause) => {
312
461
  if (cause) {
313
- resume(Effect.fail(new SqlError({ cause, message: "Failed to create savepoint" })))
462
+ resume(
463
+ Effect.fail(
464
+ new SqlError({ reason: classifyError(cause, "Failed to create savepoint", "createSavepoint") })
465
+ )
466
+ )
314
467
  } else {
315
468
  resume(Effect.void)
316
469
  }
@@ -320,7 +473,13 @@ export const make = (
320
473
  Effect.callback<void, SqlError>((resume) => {
321
474
  conn.rollbackTransaction((cause) => {
322
475
  if (cause) {
323
- resume(Effect.fail(new SqlError({ cause, message: "Failed to rollback transaction" })))
476
+ resume(
477
+ Effect.fail(
478
+ new SqlError({
479
+ reason: classifyError(cause, "Failed to rollback transaction", "rollbackTransaction")
480
+ })
481
+ )
482
+ )
324
483
  } else {
325
484
  resume(Effect.void)
326
485
  }
@@ -349,22 +508,29 @@ export const make = (
349
508
 
350
509
  yield* Pool.get(pool).pipe(
351
510
  Effect.tap((connection) => connection.executeUnprepared("SELECT 1", [], undefined)),
352
- Effect.mapError(({ cause }) => new SqlError({ cause, message: "MssqlClient: Failed to connect" })),
511
+ Effect.mapError((cause) =>
512
+ new SqlError({ reason: classifyError(cause, "MssqlClient: Failed to connect", "connect", "connection") })
513
+ ),
353
514
  Effect.scoped,
354
515
  Effect.timeoutOrElse({
355
516
  duration: options.connectTimeout ?? Duration.seconds(5),
356
- onTimeout: () =>
517
+ orElse: () =>
357
518
  Effect.fail(
358
519
  new SqlError({
359
- message: "MssqlClient: Connection timeout",
360
- cause: new Error("connection timeout")
520
+ reason: new ConnectionError({
521
+ message: "MssqlClient: Connection timeout",
522
+ cause: new Error("connection timeout"),
523
+ operation: "connect"
524
+ })
361
525
  })
362
526
  )
363
527
  })
364
528
  )
365
529
 
530
+ const transactionService = TransactionConnection(clientIdCounter++)
531
+
366
532
  const withTransaction = Client.makeWithTransaction({
367
- transactionService: TransactionConnection,
533
+ transactionService,
368
534
  spanAttributes,
369
535
  acquireConnection: Effect.gen(function*() {
370
536
  const scope = Scope.makeUnsafe()
@@ -382,6 +548,7 @@ export const make = (
382
548
  yield* Client.make({
383
549
  acquirer: Pool.get(pool),
384
550
  compiler,
551
+ transactionService: transactionService as any,
385
552
  spanAttributes,
386
553
  transformRows
387
554
  }),
@@ -426,42 +593,48 @@ export const make = (
426
593
  })
427
594
 
428
595
  /**
596
+ * Creates a layer from a `Config`-wrapped SQL Server client configuration, providing both `MssqlClient` and `SqlClient`.
597
+ *
429
598
  * @category layers
430
- * @since 1.0.0
599
+ * @since 4.0.0
431
600
  */
432
601
  export const layerConfig: (
433
602
  config: Config.Wrap<MssqlClientConfig>
434
603
  ) => Layer.Layer<Client.SqlClient | MssqlClient, Config.ConfigError | SqlError> = (
435
604
  config: Config.Wrap<MssqlClientConfig>
436
605
  ): Layer.Layer<Client.SqlClient | MssqlClient, Config.ConfigError | SqlError> =>
437
- Layer.effectServices(
438
- Config.unwrap(config).asEffect().pipe(
606
+ Layer.effectContext(
607
+ Config.unwrap(config).pipe(
439
608
  Effect.flatMap(make),
440
609
  Effect.map((client) =>
441
- ServiceMap.make(MssqlClient, client).pipe(
442
- ServiceMap.add(Client.SqlClient, client)
610
+ Context.make(MssqlClient, client).pipe(
611
+ Context.add(Client.SqlClient, client)
443
612
  )
444
613
  )
445
614
  )
446
615
  ).pipe(Layer.provide(Reactivity.layer))
447
616
 
448
617
  /**
618
+ * Creates a layer from a concrete SQL Server client configuration, providing both `MssqlClient` and `SqlClient`.
619
+ *
449
620
  * @category layers
450
- * @since 1.0.0
621
+ * @since 4.0.0
451
622
  */
452
623
  export const layer = (
453
624
  config: MssqlClientConfig
454
625
  ): Layer.Layer<Client.SqlClient | MssqlClient, never | SqlError> =>
455
- Layer.effectServices(
626
+ Layer.effectContext(
456
627
  Effect.map(make(config), (client) =>
457
- ServiceMap.make(MssqlClient, client).pipe(
458
- ServiceMap.add(Client.SqlClient, client)
628
+ Context.make(MssqlClient, client).pipe(
629
+ Context.add(Client.SqlClient, client)
459
630
  ))
460
631
  ).pipe(Layer.provide(Reactivity.layer))
461
632
 
462
633
  /**
634
+ * Creates the SQL Server statement compiler, using `@1`-style placeholders, bracket-escaped identifiers, and SQL Server `OUTPUT INSERTED` returning clauses.
635
+ *
463
636
  * @category compiler
464
- * @since 1.0.0
637
+ * @since 4.0.0
465
638
  */
466
639
  export const makeCompiler = (transform?: (_: string) => string) =>
467
640
  Statement.makeCompiler<MssqlCustom>({
@@ -510,7 +683,10 @@ function numberToParamName(n: number) {
510
683
  }
511
684
 
512
685
  /**
513
- * @since 1.0.0
686
+ * Default mapping from Effect SQL primitive value kinds to Tedious SQL Server parameter data types.
687
+ *
688
+ * @category configuration
689
+ * @since 4.0.0
514
690
  */
515
691
  export const defaultParameterTypes: Record<Statement.PrimitiveKind, DataType> = {
516
692
  string: Tedious.TYPES.VarChar,
@@ -1,5 +1,13 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Utilities for applying Effect SQL migrations to Microsoft SQL Server.
3
+ *
4
+ * This module re-exports the shared `Migrator` loaders and error types, then
5
+ * provides `run` and `layer` helpers for applying ordered migrations through
6
+ * the current SQL Server `SqlClient`. `run` returns the applied migration IDs
7
+ * and names, while `layer` runs migrations during layer construction and
8
+ * provides no services.
9
+ *
10
+ * @since 4.0.0
3
11
  */
4
12
  import type * as Effect from "effect/Effect"
5
13
  import * as Layer from "effect/Layer"
@@ -8,13 +16,15 @@ import type * as Client from "effect/unstable/sql/SqlClient"
8
16
  import type { SqlError } from "effect/unstable/sql/SqlError"
9
17
 
10
18
  /**
11
- * @since 1.0.0
19
+ * @since 4.0.0
12
20
  */
13
21
  export * from "effect/unstable/sql/Migrator"
14
22
 
15
23
  /**
16
- * @category constructor
17
- * @since 1.0.0
24
+ * Runs SQL migrations using the configured `SqlClient`, returning the migrations that were applied.
25
+ *
26
+ * @category constructors
27
+ * @since 4.0.0
18
28
  */
19
29
  export const run: <R>(
20
30
  options: Migrator.MigratorOptions<R>
@@ -25,8 +35,10 @@ export const run: <R>(
25
35
  > = Migrator.make({})
26
36
 
27
37
  /**
38
+ * Creates a layer that runs the configured SQL migrations during layer construction.
39
+ *
28
40
  * @category layers
29
- * @since 1.0.0
41
+ * @since 4.0.0
30
42
  */
31
43
  export const layer = <R>(
32
44
  options: Migrator.MigratorOptions<R>
package/src/Parameter.ts CHANGED
@@ -1,25 +1,41 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Typed SQL Server stored procedure parameter metadata.
3
+ *
4
+ * This module builds {@link Parameter} values that pair a stored procedure
5
+ * parameter name with a Tedious `DataType`, Tedious `ParameterOptions`, and a
6
+ * phantom TypeScript value type. `Procedure.param` and
7
+ * `Procedure.outputParam` use this metadata, and `MssqlClient.call` forwards it
8
+ * to Tedious when registering input and output parameters.
9
+ *
10
+ * @see {@link make} for constructing parameter metadata directly.
11
+ *
12
+ * @since 4.0.0
3
13
  */
4
14
  import { identity } from "effect/Function"
5
15
  import type { DataType } from "tedious/lib/data-type.ts"
6
16
  import type { ParameterOptions } from "tedious/lib/request.ts"
7
17
 
8
18
  /**
9
- * @category type id
10
- * @since 1.0.0
19
+ * Runtime type identifier used to mark SQL Server stored procedure parameter metadata.
20
+ *
21
+ * @category type IDs
22
+ * @since 4.0.0
11
23
  */
12
24
  export const TypeId: TypeId = "~@effect/sql-mssql/Parameter"
13
25
 
14
26
  /**
15
- * @category type id
16
- * @since 1.0.0
27
+ * Type-level identifier used to mark SQL Server stored procedure parameter metadata.
28
+ *
29
+ * @category type IDs
30
+ * @since 4.0.0
17
31
  */
18
32
  export type TypeId = "~@effect/sql-mssql/Parameter"
19
33
 
20
34
  /**
21
- * @category model
22
- * @since 1.0.0
35
+ * Metadata for a SQL Server stored procedure parameter, including its name, Tedious data type, options, and phantom value type.
36
+ *
37
+ * @category models
38
+ * @since 4.0.0
23
39
  */
24
40
  export interface Parameter<out A> {
25
41
  readonly [TypeId]: (_: never) => A
@@ -30,8 +46,10 @@ export interface Parameter<out A> {
30
46
  }
31
47
 
32
48
  /**
33
- * @category constructor
34
- * @since 1.0.0
49
+ * Creates typed metadata for a SQL Server stored procedure parameter.
50
+ *
51
+ * @category constructors
52
+ * @since 4.0.0
35
53
  */
36
54
  export const make = <A>(
37
55
  name: string,
package/src/Procedure.ts CHANGED
@@ -1,5 +1,13 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Typed metadata builders for Microsoft SQL Server stored procedure calls.
3
+ *
4
+ * This module defines the `Procedure` values consumed by `MssqlClient.call`.
5
+ * `make` starts a procedure definition, `param` and `outputParam` add typed
6
+ * Tedious parameter metadata, `withRows` sets the expected row type, and
7
+ * `compile` binds input values before execution. The module also defines the
8
+ * typed result shape for output parameters and returned rows.
9
+ *
10
+ * @since 4.0.0
3
11
  */
4
12
  import { identity } from "effect/Function"
5
13
  import type { Pipeable } from "effect/Pipeable"
@@ -11,20 +19,26 @@ import type { ParameterOptions } from "tedious/lib/request.ts"
11
19
  import * as Parameter from "./Parameter.ts"
12
20
 
13
21
  /**
14
- * @category type id
15
- * @since 1.0.0
22
+ * Runtime type identifier used to mark SQL Server stored procedure definitions.
23
+ *
24
+ * @category type IDs
25
+ * @since 4.0.0
16
26
  */
17
27
  export const TypeId: TypeId = "~@effect/sql-mssql/Procedure"
18
28
 
19
29
  /**
20
- * @category type id
21
- * @since 1.0.0
30
+ * Type-level identifier used to mark SQL Server stored procedure definitions.
31
+ *
32
+ * @category type IDs
33
+ * @since 4.0.0
22
34
  */
23
35
  export type TypeId = "~@effect/sql-mssql/Procedure"
24
36
 
25
37
  /**
26
- * @category model
27
- * @since 1.0.0
38
+ * Pipeable definition of a SQL Server stored procedure, tracking its input parameters, output parameters, and result row type.
39
+ *
40
+ * @category models
41
+ * @since 4.0.0
28
42
  */
29
43
  export interface Procedure<
30
44
  I extends Record<string, Parameter.Parameter<any>>,
@@ -41,8 +55,10 @@ export interface Procedure<
41
55
  }
42
56
 
43
57
  /**
44
- * @category model
45
- * @since 1.0.0
58
+ * Stored procedure definition with concrete input values bound for execution.
59
+ *
60
+ * @category models
61
+ * @since 4.0.0
46
62
  */
47
63
  export interface ProcedureWithValues<
48
64
  I extends Record<string, Parameter.Parameter<any>>,
@@ -53,11 +69,16 @@ export interface ProcedureWithValues<
53
69
  }
54
70
 
55
71
  /**
56
- * @since 1.0.0
72
+ * Namespace containing type helpers and result types for SQL Server stored procedures.
73
+ *
74
+ * @since 4.0.0
57
75
  */
58
- export namespace Procedure {
76
+ export declare namespace Procedure {
59
77
  /**
60
- * @since 1.0.0
78
+ * Maps a record of `Parameter` metadata to the corresponding record of parameter value types.
79
+ *
80
+ * @category utility types
81
+ * @since 4.0.0
61
82
  */
62
83
  export type ParametersRecord<
63
84
  A extends Record<string, Parameter.Parameter<any>>
@@ -69,8 +90,10 @@ export namespace Procedure {
69
90
  & {}
70
91
 
71
92
  /**
72
- * @category model
73
- * @since 1.0.0
93
+ * Result of a SQL Server stored procedure call, containing typed output parameter values and returned rows.
94
+ *
95
+ * @category models
96
+ * @since 4.0.0
74
97
  */
75
98
  export interface Result<
76
99
  O extends Record<string, Parameter.Parameter<any>>,
@@ -94,8 +117,10 @@ const procedureProto = {
94
117
  }
95
118
 
96
119
  /**
97
- * @category constructor
98
- * @since 1.0.0
120
+ * Creates an empty SQL Server stored procedure definition for the given procedure name.
121
+ *
122
+ * @category constructors
123
+ * @since 4.0.0
99
124
  */
100
125
  export const make = (name: string): Procedure<{}, {}> => {
101
126
  const procedure = Object.create(procedureProto)
@@ -106,8 +131,10 @@ export const make = (name: string): Procedure<{}, {}> => {
106
131
  }
107
132
 
108
133
  /**
109
- * @category combinator
110
- * @since 1.0.0
134
+ * Adds a typed input parameter to a SQL Server stored procedure definition.
135
+ *
136
+ * @category combinators
137
+ * @since 4.0.0
111
138
  */
112
139
  export const param = <A>() =>
113
140
  <N extends string, T extends DataType>(
@@ -129,8 +156,10 @@ export const param = <A>() =>
129
156
  })
130
157
 
131
158
  /**
132
- * @category combinator
133
- * @since 1.0.0
159
+ * Adds a typed output parameter to a SQL Server stored procedure definition.
160
+ *
161
+ * @category combinators
162
+ * @since 4.0.0
134
163
  */
135
164
  export const outputParam = <A>() =>
136
165
  <N extends string, T extends DataType>(
@@ -152,8 +181,10 @@ export const outputParam = <A>() =>
152
181
  })
153
182
 
154
183
  /**
155
- * @category combinator
156
- * @since 1.0.0
184
+ * Sets the expected row type for a SQL Server stored procedure definition.
185
+ *
186
+ * @category combinators
187
+ * @since 4.0.0
157
188
  */
158
189
  export const withRows = <A extends object = Row>() =>
159
190
  <
@@ -164,8 +195,10 @@ export const withRows = <A extends object = Row>() =>
164
195
  ): Procedure<I, O, A> => self as any
165
196
 
166
197
  /**
167
- * @category combinator
168
- * @since 1.0.0
198
+ * Binds input values to a SQL Server stored procedure definition, producing a value that can be executed with `MssqlClient.call`.
199
+ *
200
+ * @category combinators
201
+ * @since 4.0.0
169
202
  */
170
203
  export const compile = <
171
204
  I extends Record<string, Parameter.Parameter<any>>,