@rc312/effect-snowflake 0.0.0-stage → 0.2.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +174 -2
  4. package/dist/adbc-driver.d.ts +49 -0
  5. package/dist/adbc-driver.d.ts.map +1 -0
  6. package/dist/adbc-driver.js +29 -0
  7. package/dist/adbc-driver.js.map +1 -0
  8. package/dist/index.d.ts +96 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +89 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/internal/client.d.ts +6 -0
  13. package/dist/internal/client.d.ts.map +1 -0
  14. package/dist/internal/client.js +29 -0
  15. package/dist/internal/client.js.map +1 -0
  16. package/dist/internal/configuration.d.ts +4 -0
  17. package/dist/internal/configuration.d.ts.map +1 -0
  18. package/dist/internal/configuration.js +51 -0
  19. package/dist/internal/configuration.js.map +1 -0
  20. package/dist/internal/connection.d.ts +25 -0
  21. package/dist/internal/connection.d.ts.map +1 -0
  22. package/dist/internal/connection.js +39 -0
  23. package/dist/internal/connection.js.map +1 -0
  24. package/dist/internal/lifecycle.d.ts +9 -0
  25. package/dist/internal/lifecycle.d.ts.map +1 -0
  26. package/dist/internal/lifecycle.js +81 -0
  27. package/dist/internal/lifecycle.js.map +1 -0
  28. package/dist/internal/native.d.ts +4 -0
  29. package/dist/internal/native.d.ts.map +1 -0
  30. package/dist/internal/native.js +5 -0
  31. package/dist/internal/native.js.map +1 -0
  32. package/dist/internal/session.d.ts +6 -0
  33. package/dist/internal/session.d.ts.map +1 -0
  34. package/dist/internal/session.js +46 -0
  35. package/dist/internal/session.js.map +1 -0
  36. package/dist/internal/transaction.d.ts +6 -0
  37. package/dist/internal/transaction.d.ts.map +1 -0
  38. package/dist/internal/transaction.js +38 -0
  39. package/dist/internal/transaction.js.map +1 -0
  40. package/dist/models.d.ts +99 -0
  41. package/dist/models.d.ts.map +1 -0
  42. package/dist/models.js +2 -0
  43. package/dist/models.js.map +1 -0
  44. package/dist/snowflake-error.d.ts +19 -0
  45. package/dist/snowflake-error.d.ts.map +1 -0
  46. package/dist/snowflake-error.js +13 -0
  47. package/dist/snowflake-error.js.map +1 -0
  48. package/examples/.env.example +16 -0
  49. package/examples/README.md +73 -0
  50. package/examples/check.ts +12 -0
  51. package/examples/composition.ts +24 -0
  52. package/examples/options.ts +80 -0
  53. package/examples/query.ts +4 -0
  54. package/examples/run.ts +30 -0
  55. package/examples/scenarios.ts +114 -0
  56. package/examples/stream.ts +4 -0
  57. package/examples/transaction.ts +4 -0
  58. package/package.json +59 -4
  59. package/src/adbc-driver.ts +83 -0
  60. package/src/index.ts +151 -0
  61. package/src/internal/client.ts +69 -0
  62. package/src/internal/configuration.ts +63 -0
  63. package/src/internal/connection.ts +83 -0
  64. package/src/internal/lifecycle.ts +186 -0
  65. package/src/internal/native.ts +9 -0
  66. package/src/internal/session.ts +111 -0
  67. package/src/internal/transaction.ts +88 -0
  68. package/src/models.ts +126 -0
  69. package/src/snowflake-error.ts +17 -0
@@ -0,0 +1,25 @@
1
+ import type { Scope } from "effect";
2
+ import { Effect } from "effect";
3
+ import { AdbcDriver } from "../adbc-driver.ts";
4
+ import type { Connection as NativeConnection } from "../adbc-driver.ts";
5
+ import type { SnowflakeOptions } from "../models.ts";
6
+ import type { SnowflakeError } from "../snowflake-error.ts";
7
+ /** One native connection and the lifetime shared by all of its sessions. */
8
+ export interface Connection {
9
+ readonly native: NativeConnection;
10
+ readonly owner: Scope.Scope;
11
+ readonly isOpen: () => boolean;
12
+ readonly isHealthy: () => boolean;
13
+ readonly cleanup: <A>(operation: string, run: () => Promise<A>) => Effect.Effect<A>;
14
+ readonly setAutoCommit: (enabled: boolean) => Effect.Effect<void, SnowflakeError>;
15
+ }
16
+ /** Called inside the client's private sequential scope. Dependencies are captured once. */
17
+ export declare const make: (options: SnowflakeOptions) => Effect.Effect<{
18
+ cleanup: <A>(operation: string, run: () => Promise<A>) => Effect.Effect<A>;
19
+ isHealthy: () => boolean;
20
+ isOpen: () => boolean;
21
+ native: NativeConnection;
22
+ owner: Scope.Scope;
23
+ setAutoCommit: (enabled: boolean) => Effect.Effect<void, SnowflakeError, never>;
24
+ }, SnowflakeError, AdbcDriver | Scope.Scope>;
25
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/internal/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,MAAM,EAAQ,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,IAAI,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAK5D,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAClB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAClB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,CACtB,OAAO,EAAE,OAAO,KACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;CAC1C;AAED,2FAA2F;AAC3F,eAAO,MAAM,IAAI;cAVI,CAAC,aACP,MAAM,OACZ,MAAM,OAAO,CAAC,CAAC,CAAC,KAClB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;;;;;6BAuDM,OAAO;4CAMlC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { Effect, flow } from "effect";
2
+ import { AdbcDriver } from "../adbc-driver.js";
3
+ import { failure } from "../snowflake-error.js";
4
+ import { configuration } from "./configuration.js";
5
+ import { asCleanup } from "./lifecycle.js";
6
+ import { call } from "./native.js";
7
+ /** Called inside the client's private sequential scope. Dependencies are captured once. */
8
+ export const make = Effect.fnUntraced(function* acquireConnection(options) {
9
+ const driver = yield* AdbcDriver;
10
+ const owner = yield* Effect.scope;
11
+ const config = yield* Effect.try({
12
+ catch: failure("options"),
13
+ try: () => configuration(options),
14
+ });
15
+ let open = true;
16
+ let healthy = true;
17
+ const invalidate = Effect.sync(() => {
18
+ healthy = false;
19
+ });
20
+ const finalize = flow(Effect.tapError(() => invalidate), asCleanup);
21
+ const cleanup = (operation, run) => call(operation, run).pipe(finalize);
22
+ const database = yield* Effect.acquireRelease(driver.open(config), (resource) => cleanup("database.close", () => resource.close()));
23
+ const native = yield* Effect.acquireRelease(call("connect", () => database.connect()), (resource) => cleanup("connection.close", () => resource.close()));
24
+ yield* Effect.addFinalizer(() => Effect.sync(() => {
25
+ open = false;
26
+ }));
27
+ return {
28
+ cleanup,
29
+ isHealthy: () => healthy,
30
+ isOpen: () => open && healthy,
31
+ native,
32
+ owner,
33
+ setAutoCommit: (enabled) => Effect.try({
34
+ catch: failure("transaction.autocommit"),
35
+ try: () => native.setAutoCommit(enabled),
36
+ }).pipe(Effect.tapError(() => invalidate)),
37
+ };
38
+ });
39
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/internal/connection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAiBnC,2FAA2F;AAC3F,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,iBAAiB,CAC/D,OAAyB;IAEzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC;IACjC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;IAElC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QAC/B,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC;QACzB,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC;KAClC,CAAC,CAAC;IAEH,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QAClC,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,IAAI,CACnB,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EACjC,SAAS,CACV,CAAC;IAEF,MAAM,OAAO,GAA0B,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CACxD,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEtC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAC3C,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EACnB,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAChE,CAAC;IAEF,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CACzC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EACzC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAClE,CAAC;IAEF,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACf,IAAI,GAAG,KAAK,CAAC;IACf,CAAC,CAAC,CACH,CAAC;IAEF,OAAO;QACL,OAAO;QACP,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO;QACxB,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,OAAO;QAC7B,MAAM;QACN,KAAK;QACL,aAAa,EAAE,CAAC,OAAgB,EAAE,EAAE,CAClC,MAAM,CAAC,GAAG,CAAC;YACT,KAAK,EAAE,OAAO,CAAC,wBAAwB,CAAC;YACxC,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC;SACzC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC;KACxB,CAAC;AACzB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { RecordBatch } from "apache-arrow";
2
+ import { Effect, Scope, Stream } from "effect";
3
+ import type { SnowflakeError } from "../snowflake-error.ts";
4
+ export declare const asCleanup: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, never, R>;
5
+ export declare const owned: <A, E, R>(effect: Effect.Effect<A, E, R>, scope: Scope.Scope, isOpen: () => boolean) => Effect.Effect<A, E | SnowflakeError, R>;
6
+ export declare const ownedStream: (stream: Stream.Stream<RecordBatch, SnowflakeError>, owner: Scope.Scope, isOpen: () => boolean) => Stream.Stream<RecordBatch<any>, SnowflakeError, never>;
7
+ /** Join interrupted acquisition before releasing its late native resources. */
8
+ export declare const acquireOwner: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SnowflakeError, Scope.Scope | Exclude<R, Scope.Scope>>;
9
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/internal/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAS,MAAM,EAAe,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAY5D,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,+BACY,CAAC;AAiE9E,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,UACnB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SACvB,KAAK,CAAC,KAAK,UACV,MAAM,OAAO,KACpB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,cAAc,EAAE,CAAC,CAStC,CAAC;AAmEJ,eAAO,MAAM,WAAW,WACd,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,SAC3C,KAAK,CAAC,KAAK,UACV,MAAM,OAAO,2DACsC,CAAC;AAE9D,+EAA+E;AAC/E,eAAO,MAAM,YAAY,GACvB,CAAC,EACD,CAAC,EACD,CAAC,8GAaD,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { Cause, Effect, Exit, Fiber, Scope, Stream } from "effect";
2
+ import { failure } from "../snowflake-error.js";
3
+ const cleanupReason = (reason) => Cause.isFailReason(reason)
4
+ ? Cause.makeDieReason(reason.error).annotate(Cause.reasonAnnotations(reason))
5
+ : reason;
6
+ const cleanupCause = (cause) => Cause.fromReasons(cause.reasons.map(cleanupReason));
7
+ export const asCleanup = (effect) => Effect.catchCause(effect, (cause) => Effect.failCause(cleanupCause(cause)));
8
+ const cleanupExit = (exit) => {
9
+ if (Exit.isFailure(exit)) {
10
+ const reasons = exit.cause.reasons.filter((reason) => !Cause.isInterruptReason(reason));
11
+ if (reasons.length > 0) {
12
+ return Effect.failCause(Cause.fromReasons(reasons)).pipe(asCleanup);
13
+ }
14
+ }
15
+ return Effect.void;
16
+ };
17
+ const observeCleanup = (fiber) => Fiber.await(fiber).pipe(Effect.flatMap(cleanupExit));
18
+ const stopOperation = Effect.fnUntraced(function* stopOwnedOperation(fiber) {
19
+ if (fiber.pollUnsafe() !== undefined) {
20
+ return;
21
+ }
22
+ yield* Fiber.interrupt(fiber);
23
+ yield* observeCleanup(fiber);
24
+ });
25
+ const acquireOperation = Effect.fnUntraced(function* acquireOwnedOperation(effect, scope) {
26
+ const lifetime = yield* Scope.fork(scope, "sequential");
27
+ const fiber = yield* Effect.forkIn(Effect.interruptible(effect), lifetime);
28
+ // forkIn joins on closure but discards the exit; observe cleanup failures too.
29
+ const stop = yield* stopOperation(fiber).pipe(Effect.cached);
30
+ yield* Scope.addFinalizer(lifetime, stop);
31
+ return { fiber, lifetime, stop };
32
+ });
33
+ const releaseOperation = ({ fiber, lifetime, stop }, exit) => stop.pipe(Effect.andThen(Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)
34
+ ? observeCleanup(fiber)
35
+ : Effect.void), Effect.ensuring(Scope.close(lifetime, exit)));
36
+ // Each operation belongs to both its caller and its client/session Scope. Closing
37
+ // either interrupts AND joins it before the ADBC connection can be destroyed.
38
+ export const owned = (effect, scope, isOpen) => Effect.suspend(() => isOpen()
39
+ ? Effect.acquireUseRelease(acquireOperation(effect, scope), ({ fiber }) => Fiber.join(fiber), releaseOperation)
40
+ : Effect.fail(failure("closed")()));
41
+ // Finalizers and concurrent callers must join the same teardown. Scope.close
42
+ // marks a scope closed before its finalizers settle, so it cannot provide this
43
+ // join by itself. Keep the parent registration attached until teardown finishes.
44
+ const makeLifetime = Effect.fnUntraced(function* makeOwnedLifetime(owner) {
45
+ const registration = yield* Scope.fork(owner, "sequential");
46
+ const scope = yield* Scope.make("sequential");
47
+ // Native resources must finalize after any fiber that can acquire or use them.
48
+ const resources = yield* Scope.fork(scope, "sequential");
49
+ let firstExit;
50
+ let retired = false;
51
+ let open = true;
52
+ const retire = Effect.suspend(() => {
53
+ retired = true;
54
+ return Scope.close(registration, firstExit ?? Exit.void);
55
+ });
56
+ const teardown = yield* Effect.suspend(() => {
57
+ open = false;
58
+ return Scope.close(scope, firstExit ?? Exit.void);
59
+ }).pipe(Effect.ensuring(retire), Effect.uninterruptible, Effect.cached);
60
+ const close = (exit) => Effect.suspend(() => {
61
+ firstExit ??= exit;
62
+ return teardown;
63
+ });
64
+ yield* Scope.addFinalizerExit(registration, (exit) => retired ? Effect.void : close(exit));
65
+ return { close, isOpen: () => open, resources, scope };
66
+ });
67
+ const acquireOwnedStream = Effect.fnUntraced(function* acquireStreamLifetime(stream, owner, isOpen) {
68
+ if (!isOpen()) {
69
+ return yield* failure("closed")();
70
+ }
71
+ const lifetime = yield* Effect.acquireRelease(makeLifetime(owner), (resource, exit) => resource.close(exit));
72
+ const active = () => lifetime.isOpen() && isOpen();
73
+ const pull = yield* owned(Stream.toPull(stream).pipe(Scope.provide(lifetime.resources)), lifetime.scope, active);
74
+ return Stream.fromPull(Effect.succeed(owned(pull, lifetime.scope, active)));
75
+ });
76
+ export const ownedStream = (stream, owner, isOpen) => Stream.unwrap(acquireOwnedStream(stream, owner, isOpen));
77
+ /** Join interrupted acquisition before releasing its late native resources. */
78
+ export const acquireOwner = Effect.fnUntraced(function* acquireClientOwner(self) {
79
+ return yield* Effect.acquireUseRelease(makeLifetime(yield* Effect.scope), (lifetime) => owned(self.pipe(Scope.provide(lifetime.resources)), lifetime.scope, lifetime.isOpen), (lifetime, exit) => Exit.isFailure(exit) ? lifetime.close(exit) : Effect.void);
80
+ });
81
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/internal/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Effect } from "effect";
2
+ /** ADBC JS cannot cancel promises; settle before releasing or reusing resources. */
3
+ export declare const call: <A>(operation: string, run: () => Promise<A>) => Effect.Effect<A, import("../snowflake-error.ts").SnowflakeError, never>;
4
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/internal/native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,oFAAoF;AACpF,eAAO,MAAM,IAAI,GAAI,CAAC,aAAa,MAAM,OAAO,MAAM,OAAO,CAAC,CAAC,CAAC,4EAG7D,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Effect } from "effect";
2
+ import { failure } from "../snowflake-error.js";
3
+ /** ADBC JS cannot cancel promises; settle before releasing or reusing resources. */
4
+ export const call = (operation, run) => Effect.tryPromise({ catch: failure(operation), try: run }).pipe(Effect.uninterruptible);
5
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../../src/internal/native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,oFAAoF;AACpF,MAAM,CAAC,MAAM,IAAI,GAAG,CAAI,SAAiB,EAAE,GAAqB,EAAE,EAAE,CAClE,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAC7D,MAAM,CAAC,eAAe,CACvB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Scope, Semaphore } from "effect";
2
+ import type { SnowflakeSession } from "../models.ts";
3
+ import type { Connection } from "./connection.ts";
4
+ /** Build session operations over a captured connection, permit, and owning scope. */
5
+ export declare const make: (connection: Connection, owner: Scope.Scope, mutex: Semaphore.Semaphore, active: () => boolean) => SnowflakeSession;
6
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/internal/session.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAG/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAkClD,qFAAqF;AACrF,eAAO,MAAM,IAAI,eACH,UAAU,SACf,KAAK,CAAC,KAAK,SACX,SAAS,CAAC,SAAS,UAClB,MAAM,OAAO,KACpB,gBA8DF,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { Table } from "apache-arrow";
2
+ import { Cause, Effect, flow, pipe, Stream } from "effect";
3
+ import { failure } from "../snowflake-error.js";
4
+ import { owned, ownedStream } from "./lifecycle.js";
5
+ import { call } from "./native.js";
6
+ const executeStatement = (statement) => call("execute", () => statement.executeUpdate());
7
+ const collectBatches = (source) => call("query.read", async () => {
8
+ await source.open();
9
+ const { schema } = source;
10
+ const batches = [];
11
+ for await (const batch of source) {
12
+ batches.push(batch);
13
+ }
14
+ return new Table(schema, batches);
15
+ });
16
+ // fromAsyncIterable installs an unsanitized iterator.return finalizer. The scoped
17
+ // reader.cancel owns cleanup; this pull only reads on downstream demand.
18
+ const streamBatches = (source) => pipe(call("stream.read", () => Promise.resolve(source.next())), Effect.flatMap((result) => result.done ? Cause.done() : Effect.succeed([result.value])), Effect.succeed, Stream.fromPull);
19
+ /** Build session operations over a captured connection, permit, and owning scope. */
20
+ export const make = (connection, owner, mutex, active) => {
21
+ const statement = Effect.fnUntraced(function* acquireStatement(sql, parameters) {
22
+ if (!active()) {
23
+ return yield* failure("closed")();
24
+ }
25
+ const resource = yield* Effect.acquireRelease(call("statement.create", () => connection.native.createStatement()), (value) => connection.cleanup("statement.close", () => value.close()));
26
+ yield* call("statement.sql", () => resource.setSqlQuery(sql));
27
+ if (parameters !== undefined) {
28
+ yield* call("statement.bind", () => resource.bind(parameters));
29
+ }
30
+ return resource;
31
+ });
32
+ const reader = Effect.fnUntraced(function* acquireReader(sql, parameters) {
33
+ const resource = yield* statement(sql, parameters);
34
+ return yield* Effect.acquireRelease(call("query", () => resource.executeQuery()), (value) => connection.cleanup("reader.close", async () => {
35
+ await value.cancel();
36
+ }));
37
+ });
38
+ const run = (effect) => pipe(effect, Effect.scoped, mutex.withPermit, (self) => owned(self, owner, active));
39
+ const permit = Effect.acquireRelease(mutex.take(1), () => mutex.release(1));
40
+ return {
41
+ execute: Effect.fn("Snowflake.execute")(flow(statement, Effect.flatMap(executeStatement), run)),
42
+ query: Effect.fn("Snowflake.query")(flow(reader, Effect.flatMap(collectBatches), run)),
43
+ stream: (sql, parameters) => pipe(permit, Effect.andThen(reader(sql, parameters)), Effect.map(streamBatches), Stream.unwrap, (self) => ownedStream(self, owner, active), Stream.withSpan("Snowflake.stream")),
44
+ };
45
+ };
46
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/internal/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Semaphore } from "effect";
2
+ import type { SnowflakeClient } from "../models.ts";
3
+ import type { Connection } from "./connection.ts";
4
+ /** Serialize the whole transaction and finish native finalization before interruption. */
5
+ export declare const make: (connection: Connection, mutex: Semaphore.Semaphore) => SnowflakeClient["transaction"];
6
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/internal/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,cAAc,CAAC;AAEtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA0BlD,0FAA0F;AAC1F,eAAO,MAAM,IAAI,eACH,UAAU,SACf,SAAS,CAAC,SAAS,KACzB,eAAe,CAAC,aAAa,CAqD/B,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { Effect, Exit, Semaphore } from "effect";
2
+ import { failure } from "../snowflake-error.js";
3
+ import { asCleanup, owned } from "./lifecycle.js";
4
+ import { call } from "./native.js";
5
+ import * as Session from "./session.js";
6
+ /** The callback owns its session; closing its scope expires escaped operations. */
7
+ const acquireSession = Effect.fnUntraced(function* acquireTransactionSession(connection) {
8
+ let active = true;
9
+ const owner = yield* Effect.scope;
10
+ yield* Effect.addFinalizer(() => Effect.sync(() => {
11
+ active = false;
12
+ }));
13
+ const lock = yield* Semaphore.make(1);
14
+ return Session.make(connection, owner, lock, () => active && connection.isOpen());
15
+ });
16
+ /** Serialize the whole transaction and finish native finalization before interruption. */
17
+ export const make = (connection, mutex) => {
18
+ const begin = Effect.suspend(() => connection.isOpen()
19
+ ? connection.setAutoCommit(false)
20
+ : Effect.fail(failure("closed")()));
21
+ const commit = Effect.suspend(() => connection.isHealthy()
22
+ ? call("transaction.commit", () => connection.native.commit())
23
+ : Effect.fail(failure("transaction.invalidated")()));
24
+ const rollback = connection.cleanup("transaction.rollback", () => connection.native.rollback());
25
+ const restoreAutoCommit = Effect.suspend(() => connection.isHealthy()
26
+ ? connection.setAutoCommit(true).pipe(asCleanup)
27
+ : Effect.void);
28
+ const rollbackOnFailure = (exit) => Exit.isFailure(exit) ? rollback : Effect.void;
29
+ const complete = (self) => self.pipe(Effect.tap(() => commit), Effect.onExit((exit) => rollbackOnFailure(exit)), Effect.ensuring(restoreAutoCommit));
30
+ const runBody = (use) => acquireSession(connection).pipe(Effect.flatMap(use), Effect.scoped);
31
+ const transact = (use) => Effect.uninterruptibleMask((restore) => {
32
+ // Only the callback is interruptible; its scope closes before commit.
33
+ const body = restore(runBody(use));
34
+ return begin.pipe(Effect.andThen(complete(body)));
35
+ });
36
+ return Effect.fn("Snowflake.transaction")((use) => transact(use).pipe(mutex.withPermit, (self) => owned(self, connection.owner, connection.isOpen)));
37
+ };
38
+ //# sourceMappingURL=transaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/internal/transaction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import type { RecordBatch, Table } from "apache-arrow";
2
+ import type { Effect, Redacted, Stream } from "effect";
3
+ import type { SnowflakeError } from "./snowflake-error.ts";
4
+ /**
5
+ * Snowflake ADBC connection settings. Named fields override `databaseOptions`.
6
+ * Credentials are revealed only while constructing the native database options.
7
+ * @since 0.1.0
8
+ */
9
+ export interface SnowflakeOptions {
10
+ /** Snowflake account identifier, for example `myorg-myaccount`. */
11
+ readonly account: string;
12
+ /** Login user. Some native authentication methods obtain identity elsewhere. */
13
+ readonly username?: string;
14
+ /** Login password, wrapped in `Redacted`. */
15
+ readonly password?: Redacted.Redacted<string>;
16
+ /** Default database for unqualified SQL names. */
17
+ readonly database?: string;
18
+ /** Default schema within the selected database. */
19
+ readonly schema?: string;
20
+ /** Compute warehouse used to execute queries. */
21
+ readonly warehouse?: string;
22
+ /** Snowflake role to activate for the session. */
23
+ readonly role?: string;
24
+ /** ADBC authentication name; the driver defaults to `auth_snowflake`. These differ from SDK authenticator names. */
25
+ readonly authenticator?: "auth_snowflake" | "auth_oauth" | "auth_ext_browser" | "auth_okta" | "auth_jwt" | "auth_mfa" | "auth_pat" | "auth_wif";
26
+ /** Redacted authentication token, passed as the native `auth_token` option. */
27
+ readonly token?: Redacted.Redacted<string>;
28
+ /** Redacted inline PKCS#8 PEM used with `auth_jwt`. */
29
+ readonly privateKey?: Redacted.Redacted<string>;
30
+ /** Redacted passphrase for an encrypted inline PKCS#8 PEM. */
31
+ readonly privateKeyPass?: Redacted.Redacted<string>;
32
+ /** Path to a native-driver-supported private-key file; not inline PEM. */
33
+ readonly privateKeyPath?: string;
34
+ /** Driver name or absolute library/manifest path. Defaults to snowflake. */
35
+ readonly driver?: string;
36
+ /** Additional driver manifest directories, searched before standard locations. */
37
+ readonly manifestSearchPaths?: readonly string[];
38
+ /** Advanced native options. Redact every value, including connection URIs. */
39
+ readonly databaseOptions?: Readonly<Record<string, Redacted.Redacted<string>>>;
40
+ }
41
+ /**
42
+ * Serialized operations on a single connection. A transaction session expires
43
+ * when its callback exits. Fully consume a stream before reusing that session.
44
+ * @since 0.1.0
45
+ */
46
+ export interface SnowflakeSession {
47
+ /**
48
+ * Collect a result into an Arrow table, preserving its schema for empty results.
49
+ * @param sql Trusted SQL text with `?` placeholders; values are never interpolated.
50
+ * @param parameters Arrow columns in placeholder order, normally one parameter row.
51
+ * @returns A lazy Effect that owns a fresh statement and reader until collection ends.
52
+ * Native errors become `SnowflakeError`; cleanup failures remain defects.
53
+ */
54
+ readonly query: (sql: string, parameters?: Table) => Effect.Effect<Table, SnowflakeError>;
55
+ /**
56
+ * Execute DDL or DML using a fresh, scoped statement.
57
+ * @param sql Trusted SQL text with optional `?` placeholders.
58
+ * @param parameters Arrow columns in placeholder order.
59
+ * @returns The affected row count, or `-1` when the native driver cannot report it.
60
+ * Snowflake DDL may implicitly commit; execute it outside transaction callbacks.
61
+ */
62
+ readonly execute: (sql: string, parameters?: Table) => Effect.Effect<number, SnowflakeError>;
63
+ /**
64
+ * Pull Arrow record batches lazily without collecting the full result.
65
+ * @param sql Trusted SQL text with optional `?` placeholders.
66
+ * @param parameters Arrow columns in placeholder order.
67
+ * @returns A stream that holds the connection until consumption and cleanup finish.
68
+ * Early termination releases the reader before its statement. In-flight native
69
+ * reads settle before interruption completes; ADBC JS provides no cancellation.
70
+ */
71
+ readonly stream: (sql: string, parameters?: Table) => Stream.Stream<RecordBatch, SnowflakeError>;
72
+ }
73
+ /**
74
+ * A scoped connection with exclusive transaction callbacks.
75
+ * @since 0.1.0
76
+ */
77
+ export interface SnowflakeClient extends SnowflakeSession {
78
+ /**
79
+ * Run an Effect inside this client's transaction. Composes with `pipe` and
80
+ * preserves its success, errors, and environment. Captured repositories and
81
+ * client methods automatically use the active session on this fiber.
82
+ */
83
+ readonly withTransaction: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SnowflakeError, R>;
84
+ /**
85
+ * Disable autocommit, run `use`, and commit its success or roll back its failure.
86
+ * @param use Callback using the supplied session; await all work before returning.
87
+ * @returns The callback value, preserving its error and service requirements.
88
+ * Defects and callback interruption also roll back. Once commit starts, its
89
+ * outcome and autocommit restoration finish before interruption is accepted;
90
+ * an interrupted caller may therefore observe an already committed transaction.
91
+ * Failed commits attempt rollback. Recovered cleanup defects still prevent
92
+ * commit and fail with operation `transaction.invalidated`.
93
+ * Failed rollback or autocommit restoration invalidates the client, and cleanup
94
+ * defects accompany the original failure. Captured client methods resolve the
95
+ * active transaction session. Nested transactions fail with `transaction.nested`.
96
+ */
97
+ readonly transaction: <A, E, R>(use: (session: SnowflakeSession) => Effect.Effect<A, E, R>) => Effect.Effect<A, E | SnowflakeError, R>;
98
+ }
99
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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"}
package/dist/models.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import { Schema } from "effect";
2
+ declare const SnowflakeError_base: Schema.Class<SnowflakeError, Schema.TaggedStruct<"SnowflakeError", {
3
+ readonly message: Schema.String;
4
+ readonly operation: Schema.String;
5
+ }>, import("effect/Cause").YieldableError & {
6
+ readonly brand: unique symbol;
7
+ }>;
8
+ /**
9
+ * Sanitized native failure with an operation label and a generic message.
10
+ * Raw native messages, SQL, bind values, credentials, and original causes are
11
+ * intentionally excluded. Operation failures use the typed error channel;
12
+ * cleanup failures are promoted to defects while preserving the original Cause.
13
+ * @since 0.1.0
14
+ */
15
+ export declare class SnowflakeError extends SnowflakeError_base {
16
+ }
17
+ export declare const failure: (operation: string) => () => SnowflakeError;
18
+ export {};
19
+ //# sourceMappingURL=snowflake-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snowflake-error.d.ts","sourceRoot":"","sources":["../src/snowflake-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;;oBAYZ,OAAO,MAAM;;AAVjC;;;;;;GAMG;AAEH,qBAAa,cAAe,SAAQ,mBAGuC;CAAG;AAE9E,eAAO,MAAM,OAAO,cAAe,MAAM,yBACoC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Schema } from "effect";
2
+ /**
3
+ * Sanitized native failure with an operation label and a generic message.
4
+ * Raw native messages, SQL, bind values, credentials, and original causes are
5
+ * intentionally excluded. Operation failures use the typed error channel;
6
+ * cleanup failures are promoted to defects while preserving the original Cause.
7
+ * @since 0.1.0
8
+ */
9
+ // oxlint-disable-next-line unicorn/throw-new-error -- Schema.TaggedError is a class factory.
10
+ export class SnowflakeError extends Schema.TaggedError()("SnowflakeError", { message: Schema.String, operation: Schema.String }) {
11
+ }
12
+ export const failure = (operation) => () => new SnowflakeError({ message: `Snowflake ${operation} failed`, operation });
13
+ //# sourceMappingURL=snowflake-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snowflake-error.js","sourceRoot":"","sources":["../src/snowflake-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC;;;;;;GAMG;AACH,6FAA6F;AAC7F,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,WAAW,EAGnD,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;CAAG;AAE9E,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,GAAG,EAAE,CACjD,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,aAAa,SAAS,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ # Copy to packages/effect-snowflake/.env. Real .env files are ignored by Git.
2
+ SNOWFLAKE_ACCOUNT=myorg-myaccount
3
+ SNOWFLAKE_USERNAME=example_user
4
+ SNOWFLAKE_DATABASE=EXAMPLE_DB
5
+ SNOWFLAKE_SCHEMA=PUBLIC
6
+ SNOWFLAKE_WAREHOUSE=EXAMPLE_WH
7
+ SNOWFLAKE_AUTHENTICATOR=auth_jwt
8
+ # Choose an existing key file, or supply inline PKCS#8 PEM with SNOWFLAKE_PRIVATE_KEY.
9
+ SNOWFLAKE_PRIVATE_KEY_PATH=/absolute/path/to/rsa_key.p8
10
+ # SNOWFLAKE_PRIVATE_KEY_PASS=encrypted-key-passphrase
11
+ # SNOWFLAKE_ROLE=EXAMPLE_ROLE
12
+ # SNOWFLAKE_ADBC_DRIVER=/absolute/path/to/libadbc_driver_snowflake.so
13
+ # For password authentication use auth_snowflake and SNOWFLAKE_PASSWORD.
14
+ # For OAuth use auth_oauth and SNOWFLAKE_TOKEN.
15
+ # The live E2E suite contacts Snowflake only when this is 1.
16
+ SNOWFLAKE_E2E=0
@@ -0,0 +1,73 @@
1
+ # Snowflake ADBC examples
2
+
3
+ These are Node.js programs that import the built `@rc312/effect-snowflake` public API. They use the same configuration and scenario functions as the [live E2E suite](../e2e/snowflake.test.ts).
4
+
5
+ ## Setup
6
+
7
+ From the repository root, install dependencies and the native Snowflake driver:
8
+
9
+ ```sh
10
+ bun install
11
+ npm install -g @columnar-tech/dbc
12
+ dbc install snowflake
13
+ cp packages/effect-snowflake/examples/.env.example packages/effect-snowflake/.env
14
+ ```
15
+
16
+ Edit `packages/effect-snowflake/.env` for a development account, warehouse, database, and schema. The template uses JWT authentication and a private-key file path. For inline keys, remove `SNOWFLAKE_PRIVATE_KEY_PATH` and set `SNOWFLAKE_PRIVATE_KEY` to a PKCS#8 PEM. `SNOWFLAKE_PRIVATE_KEY_PASS` supplies an encrypted inline key's passphrase. For password authentication, set `SNOWFLAKE_AUTHENTICATOR=auth_snowflake` and `SNOWFLAKE_PASSWORD`; for OAuth use `auth_oauth` and `SNOWFLAKE_TOKEN`.
17
+
18
+ The examples need Node.js 22.19+ and Bun for workspace build scripts. The Node entrypoints load the package-local `.env` using `--env-file-if-exists`; exported environment variables take precedence. Real `.env` files are ignored by Git. Do not commit credentials. Secrets are loaded through `Config.Redacted`, and the configuration check never prints their values.
19
+
20
+ If manifest discovery is unavailable, set `SNOWFLAKE_ADBC_DRIVER` to the absolute path of an installed driver library or manifest. The shared configuration sets native login and network timeouts to 30 seconds and request retries to 60 seconds. These bound individual native operations; they are not an overall scenario deadline.
21
+
22
+ ## Run
23
+
24
+ All commands below run from the repository root and build the library and examples before starting Node:
25
+
26
+ ```sh
27
+ # Check environment configuration without loading the native addon or connecting.
28
+ bun run --cwd packages/effect-snowflake example:check
29
+
30
+ # Bind int64, text, boolean, and a typed null; decode one Arrow row.
31
+ bun run --cwd packages/effect-snowflake example:query
32
+
33
+ # Drain a stream, stop another after one nonempty batch, and reuse the connection.
34
+ bun run --cwd packages/effect-snowflake example:stream
35
+
36
+ # Commit one insert and roll another back using a session-temporary table.
37
+ bun run --cwd packages/effect-snowflake example:transaction
38
+
39
+ # Compose a service accessor, Arrow binding, decoding, and a transaction with flow.
40
+ bun run --cwd packages/effect-snowflake example:composition
41
+ ```
42
+
43
+ The query example casts the int64 result to VARCHAR before decoding it, preserving the exact value `9007199254740993`. It uses explicit Arrow types and places parameter columns in SQL placeholder order. Values containing SQL punctuation remain bind values.
44
+
45
+ The streaming example counts 1,000 generated rows and then consumes one nonempty batch from a 100,000-row result. Batch size is driver-controlled, so the first batch may contain the entire result. It finishes that consumer before executing the follow-up query on the same connection.
46
+
47
+ The transaction example creates `EFFECT_SNOWFLAKE_EXAMPLE` as a temporary table before either transaction, because Snowflake DDL implicitly commits. It commits ID 1, rolls back ID 2 with a typed failure, reads back only ID 1, and drops the table in a finalizer. It requires permission to create temporary tables in the configured schema. Each run uses its own session, and no application table is modified. Warehouse queries can incur Snowflake usage charges.
48
+
49
+ The application boundary in `run.ts` provides a shared Snowflake service Layer and an explicit native driver Layer. It captures configuration once, keeps the connection alive for the whole program, prints only the result, and exits unsuccessfully if acquisition, execution, decoding, or cleanup fails. `composition.ts` uses `flow` and `Snowflake.withTransaction`; `scenarios.ts` also demonstrates the captured client's `withTransaction` combinator. ADBC JS has no native cancellation API; interruption waits for in-flight native work to settle before releasing its resources.
50
+
51
+ ## Live E2E checks
52
+
53
+ Set `SNOWFLAKE_E2E=1` in the package-local `.env` or exported environment, then run:
54
+
55
+ ```sh
56
+ bun run --cwd packages/effect-snowflake test:e2e
57
+ ```
58
+
59
+ The suite checks the actual native Snowflake path for parameter precision, full and early stream consumption, connection reuse, committed and rolled-back data, empty-result schema, and retained-client rejection after scope closure. Every case acquires its own connection. The temporary table is scoped to its session and dropped explicitly.
60
+
61
+ Without `SNOWFLAKE_E2E=1`, the suite reports its live cases as skipped. When enabled, missing configuration, missing drivers, authentication failures, and incorrect results fail the suite. Tests have a two-minute harness timeout, but the adapter still must await a non-cancellable native operation during cleanup; a hung native driver can outlast the harness timeout. These checks are separate from the ordinary credential-free unit tests.
62
+
63
+ ## Test and inspect coverage
64
+
65
+ ```sh
66
+ bun run --cwd packages/effect-snowflake typecheck
67
+ bun run --cwd packages/effect-snowflake test:cli
68
+ bun run --cwd packages/effect-snowflake test:coverage
69
+ ```
70
+
71
+ The ordinary test command also runs compiled Node entrypoints as subprocesses, checking configuration validation, sanitized native errors, exit codes, and E2E opt-in behavior without credentials.
72
+
73
+ Coverage enforces at least 95% lines, statements, and functions, and 90% branches for the library sources. The coverage command writes a terminal summary, `coverage/coverage-summary.json`, and `coverage/index.html`. Unit tests use real Arrow IPC and controlled native-resource implementations with deterministic Promise and Effect gates. They cover asynchronous driver failures, scope retirement, delayed native acquisition and reads, combined failure causes, reader teardown, transaction rollback, configuration, and tracing redaction.
@@ -0,0 +1,12 @@
1
+ import { Effect } from "effect";
2
+
3
+ import { optionsFromEnv } from "./options.ts";
4
+
5
+ // Validate names and credential wrapping without loading the native driver.
6
+ try {
7
+ await Effect.runPromise(optionsFromEnv());
8
+ console.info("Snowflake example configuration is valid.");
9
+ } catch (error) {
10
+ console.error(error);
11
+ process.exitCode = 1;
12
+ }