@keystrokehq/snowflake 0.0.1

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 (81) hide show
  1. package/README.md +247 -0
  2. package/dist/_official/index.d.mts +2 -0
  3. package/dist/_official/index.mjs +3 -0
  4. package/dist/_runtime/index.d.mts +1 -0
  5. package/dist/_runtime/index.mjs +1 -0
  6. package/dist/accounts.d.mts +40 -0
  7. package/dist/accounts.mjs +51 -0
  8. package/dist/bulk.d.mts +71 -0
  9. package/dist/bulk.mjs +65 -0
  10. package/dist/catalog.d.mts +144 -0
  11. package/dist/catalog.mjs +158 -0
  12. package/dist/client.d.mts +44 -0
  13. package/dist/client.mjs +273 -0
  14. package/dist/common-BnKTPQXc.mjs +92 -0
  15. package/dist/connection.d.mts +2 -0
  16. package/dist/connection.mjs +3 -0
  17. package/dist/databases.d.mts +2 -0
  18. package/dist/databases.mjs +3 -0
  19. package/dist/errors-DKnc9o_a.mjs +95 -0
  20. package/dist/events.d.mts +382 -0
  21. package/dist/events.mjs +291 -0
  22. package/dist/file-formats.d.mts +39 -0
  23. package/dist/file-formats.mjs +48 -0
  24. package/dist/functions.d.mts +53 -0
  25. package/dist/functions.mjs +56 -0
  26. package/dist/grants.d.mts +93 -0
  27. package/dist/grants.mjs +102 -0
  28. package/dist/index.d.mts +1 -0
  29. package/dist/index.mjs +1 -0
  30. package/dist/integration-CCWMSTlO.d.mts +170 -0
  31. package/dist/integration-Dptv8L0L.mjs +207 -0
  32. package/dist/org-admin.d.mts +80 -0
  33. package/dist/org-admin.mjs +79 -0
  34. package/dist/pipes.d.mts +119 -0
  35. package/dist/pipes.mjs +106 -0
  36. package/dist/procedures.d.mts +61 -0
  37. package/dist/procedures.mjs +79 -0
  38. package/dist/results.d.mts +16 -0
  39. package/dist/results.mjs +64 -0
  40. package/dist/retry-0hMfb8cC.mjs +164 -0
  41. package/dist/retry-w7cTp1QL.d.mts +10 -0
  42. package/dist/roles.d.mts +60 -0
  43. package/dist/roles.mjs +74 -0
  44. package/dist/rows.d.mts +106 -0
  45. package/dist/rows.mjs +223 -0
  46. package/dist/schemas/index.d.mts +2 -0
  47. package/dist/schemas/index.mjs +4 -0
  48. package/dist/schemas-catalog.d.mts +2 -0
  49. package/dist/schemas-catalog.mjs +3 -0
  50. package/dist/shares.d.mts +56 -0
  51. package/dist/shares.mjs +77 -0
  52. package/dist/sql-options-2k5xQ-oS.d.mts +32 -0
  53. package/dist/sql-options-DI-OmLU6.mjs +79 -0
  54. package/dist/sql-safety-CywdR3EP.mjs +56 -0
  55. package/dist/sql.d.mts +84 -0
  56. package/dist/sql.mjs +209 -0
  57. package/dist/stages.d.mts +64 -0
  58. package/dist/stages.mjs +81 -0
  59. package/dist/statements-B2ThF_4b.mjs +81 -0
  60. package/dist/statements-DJL0qVNA.d.mts +238 -0
  61. package/dist/status-page.d.mts +510 -0
  62. package/dist/status-page.mjs +261 -0
  63. package/dist/streaming.d.mts +70 -0
  64. package/dist/streaming.mjs +56 -0
  65. package/dist/streams.d.mts +71 -0
  66. package/dist/streams.mjs +78 -0
  67. package/dist/tables.d.mts +2 -0
  68. package/dist/tables.mjs +3 -0
  69. package/dist/tasks.d.mts +79 -0
  70. package/dist/tasks.mjs +104 -0
  71. package/dist/triggers.d.mts +578 -0
  72. package/dist/triggers.mjs +1363 -0
  73. package/dist/users.d.mts +61 -0
  74. package/dist/users.mjs +67 -0
  75. package/dist/verification.d.mts +201 -0
  76. package/dist/verification.mjs +512 -0
  77. package/dist/views.d.mts +2 -0
  78. package/dist/views.mjs +3 -0
  79. package/dist/warehouses.d.mts +68 -0
  80. package/dist/warehouses.mjs +101 -0
  81. package/package.json +190 -0
@@ -0,0 +1,158 @@
1
+ import { executeSql } from "./sql.mjs";
2
+ import { i as quoteIdentifier, n as inClause, r as likeClause, t as buildFqn } from "./sql-safety-CywdR3EP.mjs";
3
+
4
+ //#region src/catalog.ts
5
+ function limitClause(limit) {
6
+ return limit && limit > 0 ? ` LIMIT ${Math.floor(limit)}` : "";
7
+ }
8
+ function toScope(options) {
9
+ if (options.inAccount) return " IN ACCOUNT";
10
+ if (options.inSchema) return inClause("SCHEMA", buildFqn(options.inSchema.database, options.inSchema.schema));
11
+ if (options.inDatabase) return inClause("DATABASE", quoteIdentifier(options.inDatabase));
12
+ return "";
13
+ }
14
+ async function runShow(client, sql, ctx) {
15
+ const result = await executeSql(client, {
16
+ statement: sql,
17
+ warehouse: ctx.warehouse,
18
+ role: ctx.role,
19
+ database: ctx.database,
20
+ schema: ctx.schema
21
+ });
22
+ return {
23
+ rows: result.rows,
24
+ columns: result.columns.map((c) => ({
25
+ name: c.name,
26
+ type: c.type
27
+ }))
28
+ };
29
+ }
30
+ async function showDatabases(client, options = {}) {
31
+ return runShow(client, `SHOW DATABASES${likeClause(options.like)}${limitClause(options.limit)}`, options);
32
+ }
33
+ async function showSchemas(client, options = {}) {
34
+ return runShow(client, `SHOW${options.history ? " HISTORY" : ""} SCHEMAS${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
35
+ }
36
+ async function showTables(client, options = {}) {
37
+ return runShow(client, `SHOW${options.terse ? " TERSE" : ""}${options.history ? " HISTORY" : ""} TABLES${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
38
+ }
39
+ async function showViews(client, options = {}) {
40
+ return runShow(client, `SHOW${options.terse ? " TERSE" : ""} VIEWS${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
41
+ }
42
+ async function showMaterializedViews(client, options = {}) {
43
+ return runShow(client, `SHOW MATERIALIZED VIEWS${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
44
+ }
45
+ async function showColumns(client, options = {}) {
46
+ let scope = "";
47
+ if (options.inTable) scope = ` IN TABLE ${buildFqn(options.inTable.database, options.inTable.schema, options.inTable.table)}`;
48
+ else if (options.inView) scope = ` IN VIEW ${buildFqn(options.inView.database, options.inView.schema, options.inView.view)}`;
49
+ else if (options.inSchema) scope = ` IN SCHEMA ${buildFqn(options.inSchema.database, options.inSchema.schema)}`;
50
+ else if (options.inDatabase) scope = ` IN DATABASE ${quoteIdentifier(options.inDatabase)}`;
51
+ return runShow(client, `SHOW COLUMNS${scope}${likeClause(options.like)}${limitClause(options.limit)}`, options);
52
+ }
53
+ async function showWarehouses(client, options = {}) {
54
+ return runShow(client, `SHOW WAREHOUSES${likeClause(options.like)}${limitClause(options.limit)}`, options);
55
+ }
56
+ async function showRoles(client, options = {}) {
57
+ return runShow(client, `SHOW ROLES${likeClause(options.like)}${limitClause(options.limit)}`, options);
58
+ }
59
+ async function showUsers(client, options = {}) {
60
+ return runShow(client, `SHOW USERS${likeClause(options.like)}${limitClause(options.limit)}`, options);
61
+ }
62
+ async function showStages(client, options = {}) {
63
+ return runShow(client, `SHOW STAGES${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
64
+ }
65
+ async function showPipes(client, options = {}) {
66
+ return runShow(client, `SHOW PIPES${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
67
+ }
68
+ async function showTasks(client, options = {}) {
69
+ return runShow(client, `SHOW${options.terse ? " TERSE" : ""} TASKS${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
70
+ }
71
+ async function showStreams(client, options = {}) {
72
+ return runShow(client, `SHOW STREAMS${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
73
+ }
74
+ async function showShares(client, options = {}) {
75
+ return runShow(client, `SHOW SHARES${likeClause(options.like)}${limitClause(options.limit)}`, options);
76
+ }
77
+ async function showFunctions(client, options = {}) {
78
+ return runShow(client, `SHOW FUNCTIONS${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
79
+ }
80
+ async function showProcedures(client, options = {}) {
81
+ return runShow(client, `SHOW PROCEDURES${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
82
+ }
83
+ async function showFileFormats(client, options = {}) {
84
+ return runShow(client, `SHOW FILE FORMATS${toScope(options)}${likeClause(options.like)}${limitClause(options.limit)}`, options);
85
+ }
86
+ async function showGrants(client, options = {}) {
87
+ let tail = "";
88
+ if (options.on) {
89
+ const fqn = buildFqn(options.on.database, options.on.schema, options.on.name);
90
+ tail = ` ON ${options.on.objectType.toUpperCase()} ${fqn}`;
91
+ } else if (options.toRole) tail = ` TO ROLE ${quoteIdentifier(options.toRole)}`;
92
+ else if (options.toUser) tail = ` TO USER ${quoteIdentifier(options.toUser)}`;
93
+ else if (options.toShare) tail = ` TO SHARE ${quoteIdentifier(options.toShare)}`;
94
+ else if (options.ofRole) tail = ` OF ROLE ${quoteIdentifier(options.ofRole)}`;
95
+ else if (options.ofShare) tail = ` OF SHARE ${quoteIdentifier(options.ofShare)}`;
96
+ return runShow(client, `SHOW GRANTS${tail}${likeClause(options.like)}`, options);
97
+ }
98
+ async function describeTable(client, options) {
99
+ return runShow(client, `DESCRIBE TABLE ${buildFqn(options.database, options.schema, options.table)}${options.type ? ` TYPE = ${options.type}` : ""}`, options);
100
+ }
101
+ /**
102
+ * Composio `SNOWFLAKE_BASIC_EXPLORE_COLUMNS` parity — pull a small distinct
103
+ * sample from each requested column to help LLMs disambiguate column
104
+ * semantics.
105
+ */
106
+ async function exploreColumns(client, options) {
107
+ const fqn = buildFqn(options.database, options.schema, options.table);
108
+ const columns = options.columns && options.columns.length > 0 ? options.columns : (await describeTable(client, options)).rows.map((row) => row.name ?? row.NAME).filter((name) => Boolean(name));
109
+ const limit = options.limit ?? 100;
110
+ const samples = [];
111
+ for (const column of columns) {
112
+ const distinctValues = (await executeSql(client, {
113
+ statement: `SELECT DISTINCT ${quoteIdentifier(column)} AS v FROM ${fqn} LIMIT ${Math.max(1, Math.floor(limit))}`,
114
+ warehouse: options.warehouse,
115
+ role: options.role
116
+ })).rows.map((row) => row.V ?? row.v);
117
+ samples.push({
118
+ column,
119
+ distinctValues
120
+ });
121
+ }
122
+ return {
123
+ table: fqn,
124
+ samples
125
+ };
126
+ }
127
+ function applyNameFilter(rows, substring) {
128
+ if (!substring) return [...rows];
129
+ const needle = substring.toLowerCase();
130
+ return rows.filter((row) => {
131
+ const name = row.name ?? row.NAME;
132
+ return typeof name === "string" && name.toLowerCase().includes(needle);
133
+ });
134
+ }
135
+ async function findDatabases(client, options = {}) {
136
+ const result = await showDatabases(client, options);
137
+ return {
138
+ columns: result.columns,
139
+ rows: applyNameFilter(result.rows, options.nameContains)
140
+ };
141
+ }
142
+ async function findSchemas(client, options = {}) {
143
+ const result = await showSchemas(client, options);
144
+ return {
145
+ columns: result.columns,
146
+ rows: applyNameFilter(result.rows, options.nameContains)
147
+ };
148
+ }
149
+ async function findTables(client, options = {}) {
150
+ const result = await showTables(client, options);
151
+ return {
152
+ columns: result.columns,
153
+ rows: applyNameFilter(result.rows, options.nameContains)
154
+ };
155
+ }
156
+
157
+ //#endregion
158
+ export { describeTable, exploreColumns, findDatabases, findSchemas, findTables, showColumns, showDatabases, showFileFormats, showFunctions, showGrants, showMaterializedViews, showPipes, showProcedures, showRoles, showSchemas, showShares, showStages, showStreams, showTables, showTasks, showUsers, showViews, showWarehouses };
@@ -0,0 +1,44 @@
1
+ import { n as SnowflakeCredentials } from "./integration-CCWMSTlO.mjs";
2
+ import { t as RetryPolicy } from "./retry-w7cTp1QL.mjs";
3
+
4
+ //#region src/client.d.ts
5
+ type SnowflakeAuthTokenType = 'KEYPAIR_JWT' | 'OAUTH' | 'PROGRAMMATIC_ACCESS_TOKEN' | 'BASIC';
6
+ type SnowflakeHttpMethod = 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT';
7
+ type QueryPrimitive = string | number | boolean;
8
+ type SnowflakeQueryValue = QueryPrimitive | readonly QueryPrimitive[] | null | undefined;
9
+ interface SnowflakeQuery {
10
+ readonly [key: string]: SnowflakeQueryValue;
11
+ }
12
+ interface SnowflakeRequestInit {
13
+ readonly method?: SnowflakeHttpMethod;
14
+ readonly body?: unknown;
15
+ readonly query?: SnowflakeQuery;
16
+ readonly headers?: Readonly<Record<string, string>>;
17
+ readonly timeoutMs?: number;
18
+ readonly requestId?: string;
19
+ /** Raw body; when true the response object is returned verbatim. */
20
+ readonly raw?: boolean;
21
+ /** Disable retries for this call (statement cancel, etc.). */
22
+ readonly retry?: boolean | RetryPolicy;
23
+ }
24
+ interface SnowflakeClientOptions {
25
+ readonly fetchImpl?: typeof fetch;
26
+ readonly timeoutMs?: number;
27
+ readonly retry?: RetryPolicy;
28
+ readonly sleep?: (ms: number) => Promise<void>;
29
+ readonly now?: () => number;
30
+ readonly userAgent?: string;
31
+ readonly randomUUID?: () => string;
32
+ }
33
+ interface SnowflakeClient {
34
+ readonly host: string;
35
+ readonly account: string;
36
+ readonly credentials: SnowflakeCredentials;
37
+ request<T = unknown>(path: string, init?: SnowflakeRequestInit): Promise<T>;
38
+ requestRaw(path: string, init?: SnowflakeRequestInit): Promise<Response>;
39
+ buildUrl(path: string, query?: SnowflakeQuery): string;
40
+ }
41
+ declare function createSnowflakeClient(rawCredentials: SnowflakeCredentials | unknown, options?: SnowflakeClientOptions): SnowflakeClient;
42
+ declare function resolveHost(credentials: SnowflakeCredentials): string;
43
+ //#endregion
44
+ export { SnowflakeAuthTokenType, SnowflakeClient, SnowflakeClientOptions, SnowflakeHttpMethod, SnowflakeQuery, SnowflakeQueryValue, SnowflakeRequestInit, createSnowflakeClient, resolveHost };
@@ -0,0 +1,273 @@
1
+ import { t as parseSnowflakeCredentials } from "./integration-Dptv8L0L.mjs";
2
+ import { a as extractSnowflakeMessage, c as parseRetryAfterHeader, i as extractSnowflakeCode, n as SnowflakeSqlError, o as extractSnowflakeSqlState, r as classifySnowflakeHttpStatus, s as extractSnowflakeStatementHandle, t as SnowflakeApiError } from "./errors-DKnc9o_a.mjs";
3
+ import { a as createSnowflakeJwt, i as shouldRetry, n as computeBackoffMs, r as defaultSleep, t as DEFAULT_RETRY_POLICY } from "./retry-0hMfb8cC.mjs";
4
+
5
+ //#region src/client.ts
6
+ /**
7
+ * Core HTTP client for the Snowflake integration.
8
+ *
9
+ * Shape — kept intentionally generic so the same client backs every domain
10
+ * module (SQL API v2, Snowpipe REST, org-admin REST). Higher-level helpers
11
+ * (`sql.ts`, `pipes.ts`, ...) consume `SnowflakeClient.request` and layer
12
+ * their own schemas on top.
13
+ *
14
+ * Responsibilities:
15
+ * - resolve credentials -> `Authorization` header + auth-token-type header
16
+ * - sign JWTs for `mode=keypair` and cache them until expiry
17
+ * - apply default retry policy with exponential backoff + `Retry-After`
18
+ * - classify non-2xx responses into structured errors (see `errors.ts`)
19
+ * - attach a deterministic `requestId` for idempotent statement submission
20
+ */
21
+ const DEFAULT_TIMEOUT_MS = 3e4;
22
+ const JWT_REFRESH_SKEW_SECONDS = 60;
23
+ const USER_AGENT = "keystroke-integration-snowflake/0.0.0";
24
+ function createSnowflakeClient(rawCredentials, options = {}) {
25
+ const credentials = isSnowflakeCredentials(rawCredentials) ? rawCredentials : parseSnowflakeCredentials(rawCredentials);
26
+ const fetchImpl = options.fetchImpl ?? fetch;
27
+ const sleep = options.sleep ?? defaultSleep;
28
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
29
+ const retryPolicy = options.retry ?? DEFAULT_RETRY_POLICY;
30
+ const now = options.now ?? (() => Date.now());
31
+ const userAgent = options.userAgent ?? USER_AGENT;
32
+ const randomUUID = options.randomUUID ?? (() => typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : pseudoRandomUuid());
33
+ const host = resolveHost(credentials);
34
+ const account = credentials.SNOWFLAKE_ACCOUNT.trim();
35
+ let cachedJwt;
36
+ async function authorization() {
37
+ if (credentials.mode === "keypair") {
38
+ const nowMs = now();
39
+ if (!cachedJwt || cachedJwt.expiresAtMs - JWT_REFRESH_SKEW_SECONDS * 1e3 <= nowMs) {
40
+ if (!credentials.SNOWFLAKE_USER || !credentials.SNOWFLAKE_PRIVATE_KEY) throw new SnowflakeApiError({
41
+ kind: "auth",
42
+ status: 0,
43
+ message: "SNOWFLAKE_USER and SNOWFLAKE_PRIVATE_KEY are required for keypair mode"
44
+ });
45
+ const jwt = await createSnowflakeJwt({
46
+ account,
47
+ user: credentials.SNOWFLAKE_USER,
48
+ privateKeyPem: credentials.SNOWFLAKE_PRIVATE_KEY,
49
+ publicKeyFingerprint: credentials.SNOWFLAKE_PUBLIC_KEY_FP,
50
+ now: () => nowMs
51
+ });
52
+ cachedJwt = {
53
+ token: jwt.token,
54
+ expiresAtMs: jwt.expiresAt * 1e3
55
+ };
56
+ }
57
+ return {
58
+ header: `Bearer ${cachedJwt.token}`,
59
+ tokenType: "KEYPAIR_JWT"
60
+ };
61
+ }
62
+ if (credentials.mode === "oauth") {
63
+ if (!credentials.SNOWFLAKE_OAUTH_ACCESS_TOKEN) throw new SnowflakeApiError({
64
+ kind: "auth",
65
+ status: 0,
66
+ message: "SNOWFLAKE_OAUTH_ACCESS_TOKEN is required for oauth mode"
67
+ });
68
+ return {
69
+ header: `Bearer ${credentials.SNOWFLAKE_OAUTH_ACCESS_TOKEN}`,
70
+ tokenType: "OAUTH"
71
+ };
72
+ }
73
+ if (credentials.mode === "pat") {
74
+ if (!credentials.SNOWFLAKE_PAT) throw new SnowflakeApiError({
75
+ kind: "auth",
76
+ status: 0,
77
+ message: "SNOWFLAKE_PAT is required for pat mode"
78
+ });
79
+ return {
80
+ header: `Bearer ${credentials.SNOWFLAKE_PAT}`,
81
+ tokenType: "PROGRAMMATIC_ACCESS_TOKEN"
82
+ };
83
+ }
84
+ if (!credentials.SNOWFLAKE_USER || !credentials.SNOWFLAKE_PASSWORD) throw new SnowflakeApiError({
85
+ kind: "auth",
86
+ status: 0,
87
+ message: "SNOWFLAKE_USER and SNOWFLAKE_PASSWORD are required for basic mode"
88
+ });
89
+ return {
90
+ header: `Basic ${base64EncodeString(`${credentials.SNOWFLAKE_USER}:${credentials.SNOWFLAKE_PASSWORD}`)}`,
91
+ tokenType: "BASIC"
92
+ };
93
+ }
94
+ function buildUrl(path, query) {
95
+ return `${path.startsWith("http://") || path.startsWith("https://") ? path : `https://${host}${path.startsWith("/") ? path : `/${path}`}`}${toQueryString(query)}`;
96
+ }
97
+ async function requestRaw(path, init = {}) {
98
+ const method = init.method ?? "GET";
99
+ const policy = resolveRetryPolicy(init.retry, retryPolicy);
100
+ const attemptTimeoutMs = init.timeoutMs ?? timeoutMs;
101
+ const requestId = init.requestId ?? randomUUID();
102
+ const url = buildUrl(path, {
103
+ ...init.query ?? {},
104
+ ...method === "POST" && path.includes("/api/v2/statements") ? { requestId } : {}
105
+ });
106
+ let body;
107
+ const headers = {
108
+ Accept: "application/json",
109
+ "User-Agent": userAgent,
110
+ ...init.headers
111
+ };
112
+ if (init.body !== void 0) {
113
+ headers["Content-Type"] = "application/json";
114
+ body = JSON.stringify(init.body);
115
+ }
116
+ let attempt = 0;
117
+ for (;;) {
118
+ const auth = await authorization();
119
+ headers.Authorization = auth.header;
120
+ headers["X-Snowflake-Authorization-Token-Type"] = auth.tokenType;
121
+ const controller = new AbortController();
122
+ const timer = setTimeout(() => controller.abort(), attemptTimeoutMs);
123
+ let response;
124
+ try {
125
+ response = await fetchImpl(url, {
126
+ method,
127
+ headers,
128
+ ...body !== void 0 ? { body } : {},
129
+ signal: controller.signal
130
+ });
131
+ } catch (error) {
132
+ clearTimeout(timer);
133
+ const isAbort = error instanceof Error && (error.name === "AbortError" || /aborted|abort/iu.test(error.message));
134
+ const kind = isAbort ? "timeout" : "network";
135
+ if (policy && shouldRetry(kind, attempt, policy)) {
136
+ attempt += 1;
137
+ await sleep(computeBackoffMs({
138
+ attempt,
139
+ policy
140
+ }));
141
+ continue;
142
+ }
143
+ throw new SnowflakeApiError({
144
+ kind,
145
+ status: 0,
146
+ message: isAbort ? `Request to \`${path}\` timed out after ${attemptTimeoutMs}ms` : `Request to \`${path}\` failed: ${error?.message ?? String(error)}`,
147
+ requestId,
148
+ cause: error
149
+ });
150
+ }
151
+ clearTimeout(timer);
152
+ if (response.ok || response.status === 202) return response;
153
+ const parsed = await readResponseBody(response);
154
+ const retryAfterMs = parseRetryAfterHeader(response.headers.get("retry-after"));
155
+ const kind = classifySnowflakeHttpStatus(response.status);
156
+ if (policy && shouldRetry(kind, attempt, policy)) {
157
+ attempt += 1;
158
+ await sleep(computeBackoffMs({
159
+ attempt,
160
+ retryAfterMs,
161
+ policy
162
+ }));
163
+ continue;
164
+ }
165
+ throw toStructuredError({
166
+ response,
167
+ body: parsed,
168
+ requestId,
169
+ retryAfterMs
170
+ });
171
+ }
172
+ }
173
+ async function request(path, init = {}) {
174
+ const response = await requestRaw(path, init);
175
+ if (init.raw) return response;
176
+ if (response.status === 204) return void 0;
177
+ return await readResponseBody(response);
178
+ }
179
+ return {
180
+ host,
181
+ account,
182
+ credentials,
183
+ request,
184
+ requestRaw,
185
+ buildUrl
186
+ };
187
+ }
188
+ function resolveRetryPolicy(override, fallback) {
189
+ if (override === false) return void 0;
190
+ if (override === true || override === void 0) return fallback;
191
+ return override;
192
+ }
193
+ async function readResponseBody(response) {
194
+ if ((response.headers.get("content-type") ?? "").includes("application/json")) return response.json().catch(() => void 0);
195
+ return response.text().catch(() => void 0);
196
+ }
197
+ function toStructuredError(args) {
198
+ const { response, body, requestId, retryAfterMs } = args;
199
+ const kind = classifySnowflakeHttpStatus(response.status);
200
+ const message = extractSnowflakeMessage(body) ?? `Snowflake HTTP ${response.status} (${response.statusText})`;
201
+ const providerCode = extractSnowflakeCode(body);
202
+ const snowflakeRequestId = response.headers.get("x-snowflake-request-id") ?? void 0;
203
+ if (response.status === 422) return new SnowflakeSqlError({
204
+ kind: "sql",
205
+ status: response.status,
206
+ message,
207
+ body,
208
+ providerCode,
209
+ requestId: snowflakeRequestId ?? requestId,
210
+ retryAfterMs,
211
+ sqlState: extractSnowflakeSqlState(body),
212
+ code: providerCode,
213
+ statementHandle: extractSnowflakeStatementHandle(body)
214
+ });
215
+ return new SnowflakeApiError({
216
+ kind,
217
+ status: response.status,
218
+ message,
219
+ body,
220
+ providerCode,
221
+ requestId: snowflakeRequestId ?? requestId,
222
+ retryAfterMs
223
+ });
224
+ }
225
+ function resolveHost(credentials) {
226
+ if (credentials.SNOWFLAKE_HOST) return stripProtocol(credentials.SNOWFLAKE_HOST).replace(/\/+$/u, "");
227
+ const account = credentials.SNOWFLAKE_ACCOUNT.trim();
228
+ const region = credentials.SNOWFLAKE_REGION?.trim();
229
+ if (region && !account.includes(".") && !account.includes("-")) return `${account}.${region}.snowflakecomputing.com`;
230
+ if (/snowflakecomputing\.com$/u.test(account)) return account;
231
+ return `${account}.snowflakecomputing.com`;
232
+ }
233
+ function stripProtocol(host) {
234
+ return host.replace(/^https?:\/\//u, "");
235
+ }
236
+ function toQueryString(query) {
237
+ if (!query) return "";
238
+ const params = new URLSearchParams();
239
+ for (const [key, value] of Object.entries(query)) {
240
+ if (value === void 0 || value === null) continue;
241
+ if (Array.isArray(value)) {
242
+ for (const item of value) params.append(key, String(item));
243
+ continue;
244
+ }
245
+ params.set(key, String(value));
246
+ }
247
+ const qs = params.toString();
248
+ return qs.length > 0 ? `?${qs}` : "";
249
+ }
250
+ function isSnowflakeCredentials(value) {
251
+ if (typeof value !== "object" || value === null) return false;
252
+ const mode = value.mode;
253
+ return mode === "keypair" || mode === "oauth" || mode === "pat" || mode === "basic";
254
+ }
255
+ function base64EncodeString(input) {
256
+ if (typeof btoa === "function") return btoa(unescape(encodeURIComponent(input)));
257
+ /* c8 ignore next */
258
+ return Buffer.from(input, "utf8").toString("base64");
259
+ }
260
+ function pseudoRandomUuid() {
261
+ /* c8 ignore start */
262
+ const bytes = new Uint8Array(16);
263
+ for (let i = 0; i < 16; i += 1) bytes[i] = Math.floor(Math.random() * 256);
264
+ bytes[6] = (bytes[6] ?? 0) & 15 | 64;
265
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
266
+ const hex = [];
267
+ for (const b of bytes) hex.push(b.toString(16).padStart(2, "0"));
268
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
269
+ /* c8 ignore end */
270
+ }
271
+
272
+ //#endregion
273
+ export { createSnowflakeClient, resolveHost };
@@ -0,0 +1,92 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/schemas/common.ts
4
+ /**
5
+ * Cross-domain Zod primitives for the Snowflake integration.
6
+ *
7
+ * These schemas are the single source of truth for identifier shapes,
8
+ * fully-qualified names, statement context, and row / column metadata.
9
+ * Downstream domain files (sql.ts, results.ts, rows.ts, tables.ts, ...)
10
+ * compose them to avoid drift.
11
+ */
12
+ /**
13
+ * Snowflake identifiers are 1-255 chars. Unquoted identifiers are normalized
14
+ * to upper-case; quoted identifiers preserve case. We keep raw validation
15
+ * permissive and let the server reject bad names — a strict regex would
16
+ * forbid unicode-quoted identifiers legitimately used in the wild.
17
+ */
18
+ const snowflakeIdentifier = z.string().min(1, "Snowflake identifier must not be empty").max(255, "Snowflake identifier must be 255 chars or less");
19
+ /**
20
+ * Fully-qualified name: `DATABASE.SCHEMA.NAME` (or subsets). Stored as a
21
+ * single string; we do *not* split/rejoin so callers can pass quoted
22
+ * segments through verbatim.
23
+ */
24
+ const snowflakeFqn = z.string().min(1);
25
+ /**
26
+ * Optional context overrides applied per-statement.
27
+ * Every field is optional — absent values fall back to the connection's
28
+ * session defaults and then to account-level defaults.
29
+ */
30
+ const statementContextSchema = z.object({
31
+ database: snowflakeIdentifier.optional(),
32
+ schema: snowflakeIdentifier.optional(),
33
+ warehouse: snowflakeIdentifier.optional(),
34
+ role: snowflakeIdentifier.optional(),
35
+ timeout: z.number().int().nonnegative().optional(),
36
+ parameters: z.record(z.string(), z.unknown()).optional()
37
+ }).strict();
38
+ /**
39
+ * SQL API v2 supports typed bindings: each binding is an object with a
40
+ * `type` and a `value`. We allow the simple positional shape and the
41
+ * keyed-map shape Snowflake accepts.
42
+ */
43
+ const sqlBindingValueSchema = z.object({
44
+ type: z.string(),
45
+ value: z.union([
46
+ z.string(),
47
+ z.number(),
48
+ z.boolean(),
49
+ z.null()
50
+ ])
51
+ });
52
+ const sqlBindingsSchema = z.record(z.string(), sqlBindingValueSchema).or(z.array(sqlBindingValueSchema));
53
+ /**
54
+ * Loosely-typed record shape for objects returned by `SHOW ...` commands.
55
+ * Snowflake returns positional arrays with a `rowType[]` describing each
56
+ * column — callers either consume the tuple form directly or `hydrateRow`
57
+ * into a `Record<string, unknown>`.
58
+ */
59
+ const snowflakeObjectRowSchema = z.record(z.string(), z.unknown());
60
+ /**
61
+ * Column metadata entry as returned under `resultSetMetaData.rowType`.
62
+ */
63
+ const columnMetaSchema = z.object({
64
+ name: z.string(),
65
+ type: z.string(),
66
+ nullable: z.boolean().optional(),
67
+ length: z.number().optional(),
68
+ precision: z.number().optional(),
69
+ scale: z.number().optional(),
70
+ byteLength: z.number().optional(),
71
+ collation: z.string().nullable().optional(),
72
+ database: z.string().optional(),
73
+ schema: z.string().optional(),
74
+ table: z.string().optional()
75
+ }).catchall(z.unknown());
76
+ /**
77
+ * Partition entry describing a shard of the total result set.
78
+ */
79
+ const partitionInfoSchema = z.object({
80
+ rowCount: z.number(),
81
+ uncompressedSize: z.number().optional(),
82
+ compressedSize: z.number().optional()
83
+ }).catchall(z.unknown());
84
+ const resultSetMetaDataSchema = z.object({
85
+ numRows: z.number().optional(),
86
+ format: z.string().optional(),
87
+ partitionInfo: z.array(partitionInfoSchema).optional(),
88
+ rowType: z.array(columnMetaSchema).optional()
89
+ }).catchall(z.unknown());
90
+
91
+ //#endregion
92
+ export { snowflakeIdentifier as a, sqlBindingsSchema as c, snowflakeFqn as i, statementContextSchema as l, partitionInfoSchema as n, snowflakeObjectRowSchema as o, resultSetMetaDataSchema as r, sqlBindingValueSchema as s, columnMetaSchema as t };
@@ -0,0 +1,2 @@
1
+ import { a as snowflakeAuthModeSchema, c as snowflakeOfficialIntegration, i as snowflake, n as SnowflakeCredentials, o as snowflakeAuthSchema, r as parseSnowflakeCredentials, s as snowflakeBundle, t as SnowflakeAuthMode } from "./integration-CCWMSTlO.mjs";
2
+ export { type SnowflakeAuthMode, type SnowflakeCredentials, parseSnowflakeCredentials, snowflake, snowflakeAuthModeSchema, snowflakeAuthSchema, snowflakeBundle, snowflakeOfficialIntegration };
@@ -0,0 +1,3 @@
1
+ import { a as snowflakeBundle, i as snowflakeAuthSchema, n as snowflake, o as snowflakeOfficialIntegration, r as snowflakeAuthModeSchema, t as parseSnowflakeCredentials } from "./integration-Dptv8L0L.mjs";
2
+
3
+ export { parseSnowflakeCredentials, snowflake, snowflakeAuthModeSchema, snowflakeAuthSchema, snowflakeBundle, snowflakeOfficialIntegration };
@@ -0,0 +1,2 @@
1
+ import { CatalogResult, FindDatabasesOptions, ShowDatabasesOptions, findDatabases, showDatabases } from "./catalog.mjs";
2
+ export { type CatalogResult, type FindDatabasesOptions, type ShowDatabasesOptions, findDatabases, showDatabases };
@@ -0,0 +1,3 @@
1
+ import { findDatabases, showDatabases } from "./catalog.mjs";
2
+
3
+ export { findDatabases, showDatabases };
@@ -0,0 +1,95 @@
1
+ //#region src/errors.ts
2
+ /**
3
+ * Structured Snowflake error. Always thrown by the client on transport or
4
+ * HTTP-level failure, and by higher-level helpers when they wrap those
5
+ * failures with extra context.
6
+ */
7
+ var SnowflakeApiError = class extends Error {
8
+ kind;
9
+ status;
10
+ body;
11
+ providerCode;
12
+ requestId;
13
+ retryAfterMs;
14
+ retryable;
15
+ constructor(init) {
16
+ super(init.message, init.cause !== void 0 ? { cause: init.cause } : void 0);
17
+ this.name = "SnowflakeApiError";
18
+ this.kind = init.kind;
19
+ this.status = init.status;
20
+ this.body = init.body;
21
+ this.providerCode = init.providerCode;
22
+ this.requestId = init.requestId;
23
+ this.retryAfterMs = init.retryAfterMs;
24
+ this.retryable = init.retryable ?? defaultRetryability(init.kind);
25
+ }
26
+ };
27
+ /**
28
+ * SQL-level failure emitted by the SQL API on status 422. Callers should
29
+ * branch on `sqlState` / `code` when they need to recover from known
30
+ * SQL-layer errors (for example `42S02` table-not-found).
31
+ */
32
+ var SnowflakeSqlError = class extends SnowflakeApiError {
33
+ sqlState;
34
+ code;
35
+ statementHandle;
36
+ constructor(init) {
37
+ super({
38
+ ...init,
39
+ kind: "sql"
40
+ });
41
+ this.name = "SnowflakeSqlError";
42
+ this.sqlState = init.sqlState;
43
+ this.code = init.code;
44
+ this.statementHandle = init.statementHandle;
45
+ }
46
+ };
47
+ function defaultRetryability(kind) {
48
+ return kind === "rate_limit" || kind === "server_error" || kind === "timeout" || kind === "network";
49
+ }
50
+ function classifySnowflakeHttpStatus(status) {
51
+ if (status === 401) return "auth";
52
+ if (status === 403) return "auth";
53
+ if (status === 404) return "not_found";
54
+ if (status === 408) return "timeout";
55
+ if (status === 409) return "conflict";
56
+ if (status === 422) return "sql";
57
+ if (status === 429) return "rate_limit";
58
+ if (status >= 500 && status <= 599) return "server_error";
59
+ if (status >= 400 && status <= 499) return "validation";
60
+ return "unknown";
61
+ }
62
+ function isRecord(value) {
63
+ return typeof value === "object" && value !== null;
64
+ }
65
+ function extractSnowflakeMessage(body) {
66
+ if (!isRecord(body)) return void 0;
67
+ if (typeof body.message === "string") return body.message;
68
+ if (typeof body.error === "string") return body.error;
69
+ if (typeof body.errorMessage === "string") return body.errorMessage;
70
+ }
71
+ function extractSnowflakeCode(body) {
72
+ if (!isRecord(body)) return void 0;
73
+ if (typeof body.code === "string") return body.code;
74
+ if (typeof body.errorCode === "string") return body.errorCode;
75
+ }
76
+ function extractSnowflakeSqlState(body) {
77
+ if (!isRecord(body)) return void 0;
78
+ if (typeof body.sqlState === "string") return body.sqlState;
79
+ if (typeof body.sql_state === "string") return body.sql_state;
80
+ }
81
+ function extractSnowflakeStatementHandle(body) {
82
+ if (!isRecord(body)) return void 0;
83
+ if (typeof body.statementHandle === "string") return body.statementHandle;
84
+ if (typeof body.statement_handle === "string") return body.statement_handle;
85
+ }
86
+ function parseRetryAfterHeader(headerValue) {
87
+ if (!headerValue) return void 0;
88
+ const asNumber = Number(headerValue);
89
+ if (Number.isFinite(asNumber) && asNumber >= 0) return asNumber * 1e3;
90
+ const asDate = Date.parse(headerValue);
91
+ if (!Number.isNaN(asDate)) return Math.max(0, asDate - Date.now());
92
+ }
93
+
94
+ //#endregion
95
+ export { extractSnowflakeMessage as a, parseRetryAfterHeader as c, extractSnowflakeCode as i, SnowflakeSqlError as n, extractSnowflakeSqlState as o, classifySnowflakeHttpStatus as r, extractSnowflakeStatementHandle as s, SnowflakeApiError as t };