@keystrokehq/snowflake 0.0.16 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +9 -233
- package/dist/actions/index.cjs +18 -0
- package/dist/actions/index.d.cts +2 -0
- package/dist/actions/index.d.mts +2 -0
- package/dist/actions/index.mjs +2 -0
- package/dist/actions-BGkaZb6a.cjs +801 -0
- package/dist/actions-BGkaZb6a.cjs.map +1 -0
- package/dist/actions-BR_JWhT_.mjs +700 -0
- package/dist/actions-BR_JWhT_.mjs.map +1 -0
- package/dist/index-DUGCZPGQ.d.cts +443 -0
- package/dist/index-DUGCZPGQ.d.cts.map +1 -0
- package/dist/index-RhOmpRxD.d.mts +445 -0
- package/dist/index-RhOmpRxD.d.mts.map +1 -0
- package/dist/index.cjs +34 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +19 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +19 -4
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +15 -5
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -171
- package/dist/accounts/index.d.mts +0 -40
- package/dist/accounts/index.mjs +0 -51
- package/dist/bulk/index.d.mts +0 -71
- package/dist/bulk/index.mjs +0 -65
- package/dist/catalog/index.d.mts +0 -144
- package/dist/catalog/index.mjs +0 -158
- package/dist/client/index.d.mts +0 -44
- package/dist/client/index.mjs +0 -273
- package/dist/common-DfpCwJx5.mjs +0 -92
- package/dist/credential-sets/index.d.mts +0 -3
- package/dist/credential-sets/index.mjs +0 -4
- package/dist/databases/index.d.mts +0 -2
- package/dist/databases/index.mjs +0 -3
- package/dist/errors-60AsF7Su.mjs +0 -95
- package/dist/events/index.d.mts +0 -382
- package/dist/events/index.mjs +0 -291
- package/dist/file-formats/index.d.mts +0 -39
- package/dist/file-formats/index.mjs +0 -48
- package/dist/functions/index.d.mts +0 -53
- package/dist/functions/index.mjs +0 -56
- package/dist/grants/index.d.mts +0 -93
- package/dist/grants/index.mjs +0 -102
- package/dist/operations/index.d.mts +0 -1
- package/dist/operations/index.mjs +0 -1
- package/dist/org-admin/index.d.mts +0 -80
- package/dist/org-admin/index.mjs +0 -79
- package/dist/pipes/index.d.mts +0 -119
- package/dist/pipes/index.mjs +0 -106
- package/dist/procedures/index.d.mts +0 -61
- package/dist/procedures/index.mjs +0 -79
- package/dist/results/index.d.mts +0 -16
- package/dist/results/index.mjs +0 -64
- package/dist/retry-B4-9MZIp.mjs +0 -164
- package/dist/retry-w7cTp1QL.d.mts +0 -10
- package/dist/roles/index.d.mts +0 -60
- package/dist/roles/index.mjs +0 -74
- package/dist/rows/index.d.mts +0 -106
- package/dist/rows/index.mjs +0 -223
- package/dist/schemas/index.d.mts +0 -2
- package/dist/schemas/index.mjs +0 -4
- package/dist/schemas-catalog/index.d.mts +0 -2
- package/dist/schemas-catalog/index.mjs +0 -3
- package/dist/shares/index.d.mts +0 -56
- package/dist/shares/index.mjs +0 -77
- package/dist/snowflake-s3-sns-webhook.credential-set-D6bLAWy5.d.mts +0 -50
- package/dist/snowflake-s3-sns-webhook.credential-set-DzR7oWNK.mjs +0 -44
- package/dist/snowflake.credential-set-BxT7Gf3A.d.mts +0 -114
- package/dist/snowflake.credential-set-DE3gXf-a.mjs +0 -106
- package/dist/sql/index.d.mts +0 -84
- package/dist/sql/index.mjs +0 -209
- package/dist/sql-options-2k5xQ-oS.d.mts +0 -32
- package/dist/sql-options-D6GEa21F.mjs +0 -79
- package/dist/sql-safety-BZpAPsq6.mjs +0 -56
- package/dist/stages/index.d.mts +0 -64
- package/dist/stages/index.mjs +0 -81
- package/dist/statements-BumhMhN4.mjs +0 -81
- package/dist/statements-DJL0qVNA.d.mts +0 -238
- package/dist/status-page/index.d.mts +0 -510
- package/dist/status-page/index.mjs +0 -261
- package/dist/streaming/index.d.mts +0 -70
- package/dist/streaming/index.mjs +0 -56
- package/dist/streams/index.d.mts +0 -71
- package/dist/streams/index.mjs +0 -78
- package/dist/tables/index.d.mts +0 -2
- package/dist/tables/index.mjs +0 -3
- package/dist/tasks/index.d.mts +0 -79
- package/dist/tasks/index.mjs +0 -104
- package/dist/triggers/index.d.mts +0 -381
- package/dist/triggers/index.mjs +0 -1100
- package/dist/users/index.d.mts +0 -61
- package/dist/users/index.mjs +0 -67
- package/dist/verification/index.d.mts +0 -201
- package/dist/verification/index.mjs +0 -512
- package/dist/views/index.d.mts +0 -2
- package/dist/views/index.mjs +0 -3
- package/dist/warehouses/index.d.mts +0 -68
- package/dist/warehouses/index.mjs +0 -101
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { CredentialSet } from "@keystrokehq/core";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
//#region src/credential-sets/snowflake-azure-eventgrid-webhook.credential-set.ts
|
|
5
|
-
const snowflakeAzureEventGridWebhookCredentialSet = new CredentialSet({
|
|
6
|
-
id: "snowflake-azure-eventgrid-webhook",
|
|
7
|
-
exposure: "platform-only",
|
|
8
|
-
name: "Snowflake Auto-Ingest — Azure Event Grid",
|
|
9
|
-
auth: z.object({
|
|
10
|
-
sharedSecret: z.string().optional(),
|
|
11
|
-
sharedSecretHeader: z.string().default("aeg-subscription-secret").optional(),
|
|
12
|
-
expectedTopicArn: z.string().optional()
|
|
13
|
-
})
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region src/credential-sets/snowflake-gcs-pubsub-webhook.credential-set.ts
|
|
18
|
-
const snowflakeGcsPubSubWebhookCredentialSet = new CredentialSet({
|
|
19
|
-
id: "snowflake-gcs-pubsub-webhook",
|
|
20
|
-
exposure: "platform-only",
|
|
21
|
-
name: "Snowflake Auto-Ingest — GCS Pub/Sub",
|
|
22
|
-
auth: z.object({
|
|
23
|
-
expectedAudience: z.string().min(1),
|
|
24
|
-
expectedServiceAccount: z.string().min(1),
|
|
25
|
-
jwksUri: z.string().default("https://www.googleapis.com/oauth2/v3/certs").optional(),
|
|
26
|
-
issuer: z.string().default("https://accounts.google.com").optional()
|
|
27
|
-
})
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
//#endregion
|
|
31
|
-
//#region src/credential-sets/snowflake-s3-sns-webhook.credential-set.ts
|
|
32
|
-
const snowflakeS3SnsWebhookCredentialSet = new CredentialSet({
|
|
33
|
-
id: "snowflake-s3-sns-webhook",
|
|
34
|
-
exposure: "platform-only",
|
|
35
|
-
name: "Snowflake Auto-Ingest — AWS SNS",
|
|
36
|
-
auth: z.object({
|
|
37
|
-
expectedTopicArn: z.string().optional(),
|
|
38
|
-
allowedSigningCertHostPattern: z.string().default("^sns\\.[a-z0-9-]+\\.amazonaws\\.com(\\.cn)?$").optional(),
|
|
39
|
-
autoConfirmSubscriptions: z.enum(["true", "false"]).default("false").optional()
|
|
40
|
-
})
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
//#endregion
|
|
44
|
-
export { snowflakeGcsPubSubWebhookCredentialSet as n, snowflakeAzureEventGridWebhookCredentialSet as r, snowflakeS3SnsWebhookCredentialSet as t };
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { CredentialSet } from "@keystrokehq/core";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { InferCredentialSetAuth } from "@keystrokehq/core/credential-set";
|
|
4
|
-
|
|
5
|
-
//#region src/credential-sets/snowflake.credential-set.d.ts
|
|
6
|
-
/**
|
|
7
|
-
* Public auth schema for Snowflake connections.
|
|
8
|
-
*
|
|
9
|
-
* Modeled as a discriminated union on `mode`. `connection.kind` is `manual`
|
|
10
|
-
* because Keystroke does not run an interactive Snowflake OAuth dance — OAuth
|
|
11
|
-
* mode accepts a bearer token provided by the caller (external IdP /
|
|
12
|
-
* Snowflake-hosted OAuth).
|
|
13
|
-
*/
|
|
14
|
-
declare const snowflakeAuthModeSchema: z.ZodEnum<{
|
|
15
|
-
keypair: "keypair";
|
|
16
|
-
oauth: "oauth";
|
|
17
|
-
pat: "pat";
|
|
18
|
-
basic: "basic";
|
|
19
|
-
}>;
|
|
20
|
-
type SnowflakeAuthMode = z.infer<typeof snowflakeAuthModeSchema>;
|
|
21
|
-
declare const snowflakeAuthSchema: z.ZodObject<{
|
|
22
|
-
mode: z.ZodEnum<{
|
|
23
|
-
keypair: "keypair";
|
|
24
|
-
oauth: "oauth";
|
|
25
|
-
pat: "pat";
|
|
26
|
-
basic: "basic";
|
|
27
|
-
}>;
|
|
28
|
-
SNOWFLAKE_ACCOUNT: z.ZodString;
|
|
29
|
-
SNOWFLAKE_USER: z.ZodOptional<z.ZodString>;
|
|
30
|
-
SNOWFLAKE_PRIVATE_KEY: z.ZodOptional<z.ZodString>;
|
|
31
|
-
SNOWFLAKE_PRIVATE_KEY_PASSPHRASE: z.ZodOptional<z.ZodString>;
|
|
32
|
-
SNOWFLAKE_PAT: z.ZodOptional<z.ZodString>;
|
|
33
|
-
SNOWFLAKE_PASSWORD: z.ZodOptional<z.ZodString>;
|
|
34
|
-
SNOWFLAKE_OAUTH_ACCESS_TOKEN: z.ZodOptional<z.ZodString>;
|
|
35
|
-
SNOWFLAKE_OAUTH_REFRESH_TOKEN: z.ZodOptional<z.ZodString>;
|
|
36
|
-
SNOWFLAKE_OAUTH_CLIENT_ID: z.ZodOptional<z.ZodString>;
|
|
37
|
-
SNOWFLAKE_OAUTH_CLIENT_SECRET: z.ZodOptional<z.ZodString>;
|
|
38
|
-
SNOWFLAKE_OAUTH_TOKEN_URL: z.ZodOptional<z.ZodString>;
|
|
39
|
-
SNOWFLAKE_OAUTH_SCOPES: z.ZodOptional<z.ZodString>;
|
|
40
|
-
SNOWFLAKE_ROLE: z.ZodOptional<z.ZodString>;
|
|
41
|
-
SNOWFLAKE_WAREHOUSE: z.ZodOptional<z.ZodString>;
|
|
42
|
-
SNOWFLAKE_DATABASE: z.ZodOptional<z.ZodString>;
|
|
43
|
-
SNOWFLAKE_SCHEMA: z.ZodOptional<z.ZodString>;
|
|
44
|
-
SNOWFLAKE_HOST: z.ZodOptional<z.ZodString>;
|
|
45
|
-
SNOWFLAKE_REGION: z.ZodOptional<z.ZodString>;
|
|
46
|
-
SNOWFLAKE_PUBLIC_KEY_FP: z.ZodOptional<z.ZodString>;
|
|
47
|
-
}, z.core.$strip>;
|
|
48
|
-
declare const snowflakeCredentialSet: CredentialSet<"snowflake", z.ZodObject<{
|
|
49
|
-
mode: z.ZodEnum<{
|
|
50
|
-
keypair: "keypair";
|
|
51
|
-
oauth: "oauth";
|
|
52
|
-
pat: "pat";
|
|
53
|
-
basic: "basic";
|
|
54
|
-
}>;
|
|
55
|
-
SNOWFLAKE_ACCOUNT: z.ZodString;
|
|
56
|
-
SNOWFLAKE_USER: z.ZodOptional<z.ZodString>;
|
|
57
|
-
SNOWFLAKE_PRIVATE_KEY: z.ZodOptional<z.ZodString>;
|
|
58
|
-
SNOWFLAKE_PRIVATE_KEY_PASSPHRASE: z.ZodOptional<z.ZodString>;
|
|
59
|
-
SNOWFLAKE_PAT: z.ZodOptional<z.ZodString>;
|
|
60
|
-
SNOWFLAKE_PASSWORD: z.ZodOptional<z.ZodString>;
|
|
61
|
-
SNOWFLAKE_OAUTH_ACCESS_TOKEN: z.ZodOptional<z.ZodString>;
|
|
62
|
-
SNOWFLAKE_OAUTH_REFRESH_TOKEN: z.ZodOptional<z.ZodString>;
|
|
63
|
-
SNOWFLAKE_OAUTH_CLIENT_ID: z.ZodOptional<z.ZodString>;
|
|
64
|
-
SNOWFLAKE_OAUTH_CLIENT_SECRET: z.ZodOptional<z.ZodString>;
|
|
65
|
-
SNOWFLAKE_OAUTH_TOKEN_URL: z.ZodOptional<z.ZodString>;
|
|
66
|
-
SNOWFLAKE_OAUTH_SCOPES: z.ZodOptional<z.ZodString>;
|
|
67
|
-
SNOWFLAKE_ROLE: z.ZodOptional<z.ZodString>;
|
|
68
|
-
SNOWFLAKE_WAREHOUSE: z.ZodOptional<z.ZodString>;
|
|
69
|
-
SNOWFLAKE_DATABASE: z.ZodOptional<z.ZodString>;
|
|
70
|
-
SNOWFLAKE_SCHEMA: z.ZodOptional<z.ZodString>;
|
|
71
|
-
SNOWFLAKE_HOST: z.ZodOptional<z.ZodString>;
|
|
72
|
-
SNOWFLAKE_REGION: z.ZodOptional<z.ZodString>;
|
|
73
|
-
SNOWFLAKE_PUBLIC_KEY_FP: z.ZodOptional<z.ZodString>;
|
|
74
|
-
}, z.core.$strip>, {
|
|
75
|
-
id: string;
|
|
76
|
-
kind: "manual";
|
|
77
|
-
label: string;
|
|
78
|
-
input: z.ZodObject<{
|
|
79
|
-
mode: z.ZodEnum<{
|
|
80
|
-
keypair: "keypair";
|
|
81
|
-
oauth: "oauth";
|
|
82
|
-
pat: "pat";
|
|
83
|
-
basic: "basic";
|
|
84
|
-
}>;
|
|
85
|
-
SNOWFLAKE_ACCOUNT: z.ZodString;
|
|
86
|
-
SNOWFLAKE_USER: z.ZodOptional<z.ZodString>;
|
|
87
|
-
SNOWFLAKE_PRIVATE_KEY: z.ZodOptional<z.ZodString>;
|
|
88
|
-
SNOWFLAKE_PRIVATE_KEY_PASSPHRASE: z.ZodOptional<z.ZodString>;
|
|
89
|
-
SNOWFLAKE_PAT: z.ZodOptional<z.ZodString>;
|
|
90
|
-
SNOWFLAKE_PASSWORD: z.ZodOptional<z.ZodString>;
|
|
91
|
-
SNOWFLAKE_OAUTH_ACCESS_TOKEN: z.ZodOptional<z.ZodString>;
|
|
92
|
-
SNOWFLAKE_OAUTH_REFRESH_TOKEN: z.ZodOptional<z.ZodString>;
|
|
93
|
-
SNOWFLAKE_OAUTH_CLIENT_ID: z.ZodOptional<z.ZodString>;
|
|
94
|
-
SNOWFLAKE_OAUTH_CLIENT_SECRET: z.ZodOptional<z.ZodString>;
|
|
95
|
-
SNOWFLAKE_OAUTH_TOKEN_URL: z.ZodOptional<z.ZodString>;
|
|
96
|
-
SNOWFLAKE_OAUTH_SCOPES: z.ZodOptional<z.ZodString>;
|
|
97
|
-
SNOWFLAKE_ROLE: z.ZodOptional<z.ZodString>;
|
|
98
|
-
SNOWFLAKE_WAREHOUSE: z.ZodOptional<z.ZodString>;
|
|
99
|
-
SNOWFLAKE_DATABASE: z.ZodOptional<z.ZodString>;
|
|
100
|
-
SNOWFLAKE_SCHEMA: z.ZodOptional<z.ZodString>;
|
|
101
|
-
SNOWFLAKE_HOST: z.ZodOptional<z.ZodString>;
|
|
102
|
-
SNOWFLAKE_REGION: z.ZodOptional<z.ZodString>;
|
|
103
|
-
SNOWFLAKE_PUBLIC_KEY_FP: z.ZodOptional<z.ZodString>;
|
|
104
|
-
}, z.core.$strip>;
|
|
105
|
-
}[]>;
|
|
106
|
-
type SnowflakeCredentials = InferCredentialSetAuth<typeof snowflakeCredentialSet>;
|
|
107
|
-
/**
|
|
108
|
-
* Parse raw credential values through the full refinement pipeline. Callers
|
|
109
|
-
* (client, operations) should use this instead of the raw object schema so
|
|
110
|
-
* mode-specific invariants are enforced.
|
|
111
|
-
*/
|
|
112
|
-
declare function parseSnowflakeCredentials(input: unknown): SnowflakeCredentials;
|
|
113
|
-
//#endregion
|
|
114
|
-
export { snowflakeAuthSchema as a, snowflakeAuthModeSchema as i, SnowflakeCredentials as n, snowflakeCredentialSet as o, parseSnowflakeCredentials as r, SnowflakeAuthMode as t };
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { CredentialSet } from "@keystrokehq/core";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
//#region src/credential-sets/snowflake.credential-set.ts
|
|
5
|
-
/**
|
|
6
|
-
* Public auth schema for Snowflake connections.
|
|
7
|
-
*
|
|
8
|
-
* Modeled as a discriminated union on `mode`. `connection.kind` is `manual`
|
|
9
|
-
* because Keystroke does not run an interactive Snowflake OAuth dance — OAuth
|
|
10
|
-
* mode accepts a bearer token provided by the caller (external IdP /
|
|
11
|
-
* Snowflake-hosted OAuth).
|
|
12
|
-
*/
|
|
13
|
-
const snowflakeAuthModeSchema = z.enum([
|
|
14
|
-
"keypair",
|
|
15
|
-
"oauth",
|
|
16
|
-
"pat",
|
|
17
|
-
"basic"
|
|
18
|
-
]);
|
|
19
|
-
const baseSnowflakeAuthShape = {
|
|
20
|
-
mode: snowflakeAuthModeSchema,
|
|
21
|
-
SNOWFLAKE_ACCOUNT: z.string().min(1),
|
|
22
|
-
SNOWFLAKE_USER: z.string().min(1).optional(),
|
|
23
|
-
SNOWFLAKE_PRIVATE_KEY: z.string().min(1).optional(),
|
|
24
|
-
SNOWFLAKE_PRIVATE_KEY_PASSPHRASE: z.string().optional(),
|
|
25
|
-
SNOWFLAKE_PAT: z.string().min(1).optional(),
|
|
26
|
-
SNOWFLAKE_PASSWORD: z.string().min(1).optional(),
|
|
27
|
-
SNOWFLAKE_OAUTH_ACCESS_TOKEN: z.string().min(1).optional(),
|
|
28
|
-
SNOWFLAKE_OAUTH_REFRESH_TOKEN: z.string().optional(),
|
|
29
|
-
SNOWFLAKE_OAUTH_CLIENT_ID: z.string().optional(),
|
|
30
|
-
SNOWFLAKE_OAUTH_CLIENT_SECRET: z.string().optional(),
|
|
31
|
-
SNOWFLAKE_OAUTH_TOKEN_URL: z.string().url().optional(),
|
|
32
|
-
SNOWFLAKE_OAUTH_SCOPES: z.string().optional(),
|
|
33
|
-
SNOWFLAKE_ROLE: z.string().optional(),
|
|
34
|
-
SNOWFLAKE_WAREHOUSE: z.string().optional(),
|
|
35
|
-
SNOWFLAKE_DATABASE: z.string().optional(),
|
|
36
|
-
SNOWFLAKE_SCHEMA: z.string().optional(),
|
|
37
|
-
SNOWFLAKE_HOST: z.string().optional(),
|
|
38
|
-
SNOWFLAKE_REGION: z.string().optional(),
|
|
39
|
-
SNOWFLAKE_PUBLIC_KEY_FP: z.string().optional()
|
|
40
|
-
};
|
|
41
|
-
const snowflakeAuthSchema = z.object(baseSnowflakeAuthShape).superRefine((value, ctx) => {
|
|
42
|
-
if (value.mode === "keypair") {
|
|
43
|
-
if (!value.SNOWFLAKE_USER) ctx.addIssue({
|
|
44
|
-
code: z.ZodIssueCode.custom,
|
|
45
|
-
path: ["SNOWFLAKE_USER"],
|
|
46
|
-
message: "SNOWFLAKE_USER is required when mode = \"keypair\""
|
|
47
|
-
});
|
|
48
|
-
if (!value.SNOWFLAKE_PRIVATE_KEY) ctx.addIssue({
|
|
49
|
-
code: z.ZodIssueCode.custom,
|
|
50
|
-
path: ["SNOWFLAKE_PRIVATE_KEY"],
|
|
51
|
-
message: "SNOWFLAKE_PRIVATE_KEY is required when mode = \"keypair\""
|
|
52
|
-
});
|
|
53
|
-
} else if (value.mode === "oauth") {
|
|
54
|
-
if (!value.SNOWFLAKE_OAUTH_ACCESS_TOKEN) ctx.addIssue({
|
|
55
|
-
code: z.ZodIssueCode.custom,
|
|
56
|
-
path: ["SNOWFLAKE_OAUTH_ACCESS_TOKEN"],
|
|
57
|
-
message: "SNOWFLAKE_OAUTH_ACCESS_TOKEN is required when mode = \"oauth\""
|
|
58
|
-
});
|
|
59
|
-
} else if (value.mode === "pat") {
|
|
60
|
-
if (!value.SNOWFLAKE_USER) ctx.addIssue({
|
|
61
|
-
code: z.ZodIssueCode.custom,
|
|
62
|
-
path: ["SNOWFLAKE_USER"],
|
|
63
|
-
message: "SNOWFLAKE_USER is required when mode = \"pat\""
|
|
64
|
-
});
|
|
65
|
-
if (!value.SNOWFLAKE_PAT) ctx.addIssue({
|
|
66
|
-
code: z.ZodIssueCode.custom,
|
|
67
|
-
path: ["SNOWFLAKE_PAT"],
|
|
68
|
-
message: "SNOWFLAKE_PAT is required when mode = \"pat\""
|
|
69
|
-
});
|
|
70
|
-
} else if (value.mode === "basic") {
|
|
71
|
-
if (!value.SNOWFLAKE_USER) ctx.addIssue({
|
|
72
|
-
code: z.ZodIssueCode.custom,
|
|
73
|
-
path: ["SNOWFLAKE_USER"],
|
|
74
|
-
message: "SNOWFLAKE_USER is required when mode = \"basic\""
|
|
75
|
-
});
|
|
76
|
-
if (!value.SNOWFLAKE_PASSWORD) ctx.addIssue({
|
|
77
|
-
code: z.ZodIssueCode.custom,
|
|
78
|
-
path: ["SNOWFLAKE_PASSWORD"],
|
|
79
|
-
message: "SNOWFLAKE_PASSWORD is required when mode = \"basic\""
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
const snowflakeAuthObjectSchema = z.object(baseSnowflakeAuthShape);
|
|
84
|
-
const snowflakeCredentialSet = new CredentialSet({
|
|
85
|
-
id: "snowflake",
|
|
86
|
-
name: "Snowflake",
|
|
87
|
-
description: "Snowflake data cloud: SQL API v2, Snowpipe (file + streaming), warehouses, roles, users, grants, shares, streams, tasks, and administration for Keystroke workflows.",
|
|
88
|
-
auth: snowflakeAuthObjectSchema,
|
|
89
|
-
connections: [{
|
|
90
|
-
id: "manual",
|
|
91
|
-
kind: "manual",
|
|
92
|
-
label: "Snowflake credentials",
|
|
93
|
-
input: snowflakeAuthObjectSchema
|
|
94
|
-
}]
|
|
95
|
-
});
|
|
96
|
-
/**
|
|
97
|
-
* Parse raw credential values through the full refinement pipeline. Callers
|
|
98
|
-
* (client, operations) should use this instead of the raw object schema so
|
|
99
|
-
* mode-specific invariants are enforced.
|
|
100
|
-
*/
|
|
101
|
-
function parseSnowflakeCredentials(input) {
|
|
102
|
-
return snowflakeAuthSchema.parse(input);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
//#endregion
|
|
106
|
-
export { snowflakeCredentialSet as i, snowflakeAuthModeSchema as n, snowflakeAuthSchema as r, parseSnowflakeCredentials as t };
|
package/dist/sql/index.d.mts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { SnowflakeClient } from "../client/index.mjs";
|
|
2
|
-
import { a as SubmitStatementInput, d as HydratedRow, f as PartitionResponse, m as ColumnMeta, n as StatementResponse } from "../statements-DJL0qVNA.mjs";
|
|
3
|
-
//#region src/sql/index.d.ts
|
|
4
|
-
interface SubmitOptions {
|
|
5
|
-
readonly async?: boolean;
|
|
6
|
-
readonly requestId?: string;
|
|
7
|
-
}
|
|
8
|
-
interface SubmitResult {
|
|
9
|
-
readonly response: StatementResponse;
|
|
10
|
-
readonly status: 'done' | 'failed' | 'pending' | 'cancelled';
|
|
11
|
-
readonly httpStatus: number;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Submit a statement. When `async: true` (or the server chooses async) we
|
|
15
|
-
* return the inflated response envelope along with the `pending` status so
|
|
16
|
-
* callers can poll via {@link getStatement} / {@link waitForStatement}.
|
|
17
|
-
*
|
|
18
|
-
* The SQL API itself keys idempotency on the `requestId` query param which
|
|
19
|
-
* {@link SnowflakeClient} auto-populates — callers can override it per
|
|
20
|
-
* request when they need deterministic retries.
|
|
21
|
-
*/
|
|
22
|
-
declare function submitStatement(client: SnowflakeClient, input: SubmitStatementInput, options?: SubmitOptions): Promise<SubmitResult>;
|
|
23
|
-
/**
|
|
24
|
-
* Fetch the current status of a previously submitted async statement. Returns
|
|
25
|
-
* both the envelope and the derived `status` bucket.
|
|
26
|
-
*/
|
|
27
|
-
declare function getStatement(client: SnowflakeClient, handle: string, options?: {
|
|
28
|
-
readonly partition?: number;
|
|
29
|
-
}): Promise<SubmitResult>;
|
|
30
|
-
/**
|
|
31
|
-
* POST `/cancel`. Snowflake responds with `code: 333335` on success — we
|
|
32
|
-
* normalise anything else into a {@link SnowflakeApiError}.
|
|
33
|
-
*/
|
|
34
|
-
declare function cancelStatement(client: SnowflakeClient, handle: string): Promise<void>;
|
|
35
|
-
interface ExecuteSqlOptions extends SubmitOptions {
|
|
36
|
-
readonly pollIntervalMs?: number;
|
|
37
|
-
readonly maxWaitMs?: number;
|
|
38
|
-
readonly hydrate?: boolean;
|
|
39
|
-
readonly now?: () => number;
|
|
40
|
-
readonly sleep?: (ms: number) => Promise<void>;
|
|
41
|
-
}
|
|
42
|
-
interface ExecuteSqlResult<TRow = HydratedRow> {
|
|
43
|
-
readonly handle: string;
|
|
44
|
-
readonly columns: readonly ColumnMeta[];
|
|
45
|
-
readonly rows: readonly TRow[];
|
|
46
|
-
readonly envelope: StatementResponse;
|
|
47
|
-
readonly partitions: number;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Submit + wait + fetch all partitions in one go. The returned rows are
|
|
51
|
-
* hydrated into objects keyed by column name by default; pass
|
|
52
|
-
* `hydrate: false` to get the raw tuple form.
|
|
53
|
-
*/
|
|
54
|
-
declare function executeSql(client: SnowflakeClient, input: SubmitStatementInput, options?: ExecuteSqlOptions): Promise<ExecuteSqlResult<HydratedRow | readonly unknown[]>>;
|
|
55
|
-
/**
|
|
56
|
-
* Composio `SNOWFLAKE_BASIC_RUN_QUERY` parity — requires an explicit
|
|
57
|
-
* database + schema to match the published BASIC shape.
|
|
58
|
-
*/
|
|
59
|
-
declare function runQuery(client: SnowflakeClient, input: {
|
|
60
|
-
readonly statement: string;
|
|
61
|
-
readonly database: string;
|
|
62
|
-
readonly schema_name: string;
|
|
63
|
-
readonly warehouse?: string;
|
|
64
|
-
readonly role?: string;
|
|
65
|
-
}, options?: ExecuteSqlOptions): Promise<ExecuteSqlResult<HydratedRow | readonly unknown[]>>;
|
|
66
|
-
/**
|
|
67
|
-
* Fetch a single partition for a known handle.
|
|
68
|
-
*/
|
|
69
|
-
declare function getStatementResultPartition(client: SnowflakeClient, handle: string, partition: number): Promise<PartitionResponse>;
|
|
70
|
-
/**
|
|
71
|
-
* Async iterator over every partition for a handle. Useful for streaming
|
|
72
|
-
* large result sets into downstream pipelines.
|
|
73
|
-
*/
|
|
74
|
-
declare function iterateStatementResult(client: SnowflakeClient, handle: string, options?: {
|
|
75
|
-
readonly maxPartitions?: number;
|
|
76
|
-
}): AsyncGenerator<PartitionResponse, void, void>;
|
|
77
|
-
/**
|
|
78
|
-
* Blocking helper: polls `getStatement` until the statement reaches a
|
|
79
|
-
* terminal status or the `maxWaitMs` budget elapses. Returns the terminal
|
|
80
|
-
* envelope (throws for `failed` / `cancelled`).
|
|
81
|
-
*/
|
|
82
|
-
declare function waitForStatement(client: SnowflakeClient, handle: string, options?: ExecuteSqlOptions): Promise<StatementResponse>;
|
|
83
|
-
//#endregion
|
|
84
|
-
export { ExecuteSqlOptions, ExecuteSqlResult, SubmitOptions, SubmitResult, cancelStatement, executeSql, getStatement, getStatementResultPartition, iterateStatementResult, runQuery, submitStatement, waitForStatement };
|
package/dist/sql/index.mjs
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { a as submitStatementInputSchema, n as statementResponseSchema, o as partitionResponseSchema, r as statementStatus } from "../statements-BumhMhN4.mjs";
|
|
2
|
-
import { n as SnowflakeSqlError, t as SnowflakeApiError } from "../errors-60AsF7Su.mjs";
|
|
3
|
-
import { hydrateRows } from "../results/index.mjs";
|
|
4
|
-
|
|
5
|
-
//#region src/sql/index.ts
|
|
6
|
-
const STATEMENTS_PATH = "/api/v2/statements";
|
|
7
|
-
/**
|
|
8
|
-
* Submit a statement. When `async: true` (or the server chooses async) we
|
|
9
|
-
* return the inflated response envelope along with the `pending` status so
|
|
10
|
-
* callers can poll via {@link getStatement} / {@link waitForStatement}.
|
|
11
|
-
*
|
|
12
|
-
* The SQL API itself keys idempotency on the `requestId` query param which
|
|
13
|
-
* {@link SnowflakeClient} auto-populates — callers can override it per
|
|
14
|
-
* request when they need deterministic retries.
|
|
15
|
-
*/
|
|
16
|
-
async function submitStatement(client, input, options = {}) {
|
|
17
|
-
const parsed = submitStatementInputSchema.parse(input);
|
|
18
|
-
const query = {};
|
|
19
|
-
if (options.async) query.async = true;
|
|
20
|
-
const response = await client.requestRaw(STATEMENTS_PATH, {
|
|
21
|
-
method: "POST",
|
|
22
|
-
body: parsed,
|
|
23
|
-
query,
|
|
24
|
-
requestId: options.requestId
|
|
25
|
-
});
|
|
26
|
-
const body = await response.json();
|
|
27
|
-
const envelope = statementResponseSchema.parse(body);
|
|
28
|
-
return {
|
|
29
|
-
response: envelope,
|
|
30
|
-
httpStatus: response.status,
|
|
31
|
-
status: statementStatus({
|
|
32
|
-
httpStatus: response.status,
|
|
33
|
-
code: envelope.code
|
|
34
|
-
})
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Fetch the current status of a previously submitted async statement. Returns
|
|
39
|
-
* both the envelope and the derived `status` bucket.
|
|
40
|
-
*/
|
|
41
|
-
async function getStatement(client, handle, options = {}) {
|
|
42
|
-
const query = options.partition !== void 0 ? { partition: options.partition } : void 0;
|
|
43
|
-
const response = await client.requestRaw(`${STATEMENTS_PATH}/${encodeURIComponent(handle)}`, {
|
|
44
|
-
method: "GET",
|
|
45
|
-
query
|
|
46
|
-
});
|
|
47
|
-
const body = await response.json();
|
|
48
|
-
const envelope = statementResponseSchema.parse(body);
|
|
49
|
-
return {
|
|
50
|
-
response: envelope,
|
|
51
|
-
httpStatus: response.status,
|
|
52
|
-
status: statementStatus({
|
|
53
|
-
httpStatus: response.status,
|
|
54
|
-
code: envelope.code
|
|
55
|
-
})
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* POST `/cancel`. Snowflake responds with `code: 333335` on success — we
|
|
60
|
-
* normalise anything else into a {@link SnowflakeApiError}.
|
|
61
|
-
*/
|
|
62
|
-
async function cancelStatement(client, handle) {
|
|
63
|
-
const response = await client.requestRaw(`${STATEMENTS_PATH}/${encodeURIComponent(handle)}/cancel`, {
|
|
64
|
-
method: "POST",
|
|
65
|
-
retry: false
|
|
66
|
-
});
|
|
67
|
-
if (!response.ok) {
|
|
68
|
-
const text = await response.text().catch(() => "");
|
|
69
|
-
throw new SnowflakeApiError({
|
|
70
|
-
kind: "http",
|
|
71
|
-
status: response.status,
|
|
72
|
-
message: `Failed to cancel statement ${handle}: ${text || response.statusText}`
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Submit + wait + fetch all partitions in one go. The returned rows are
|
|
78
|
-
* hydrated into objects keyed by column name by default; pass
|
|
79
|
-
* `hydrate: false` to get the raw tuple form.
|
|
80
|
-
*/
|
|
81
|
-
async function executeSql(client, input, options = {}) {
|
|
82
|
-
const submitted = await submitStatement(client, input, options);
|
|
83
|
-
let envelope = submitted.response;
|
|
84
|
-
let status = submitted.status;
|
|
85
|
-
if (status === "pending") {
|
|
86
|
-
envelope = await waitForStatementEnvelope(client, envelope.statementHandle, options);
|
|
87
|
-
status = statementStatus({
|
|
88
|
-
httpStatus: 200,
|
|
89
|
-
code: envelope.code
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
if (status === "cancelled") throw new SnowflakeSqlError({
|
|
93
|
-
kind: "cancelled",
|
|
94
|
-
status: 200,
|
|
95
|
-
message: envelope.message ?? "Statement was cancelled",
|
|
96
|
-
code: envelope.code,
|
|
97
|
-
sqlState: envelope.sqlState,
|
|
98
|
-
statementHandle: envelope.statementHandle
|
|
99
|
-
});
|
|
100
|
-
if (status === "failed") throw new SnowflakeSqlError({
|
|
101
|
-
kind: "sql",
|
|
102
|
-
status: 422,
|
|
103
|
-
message: envelope.message ?? "Statement failed",
|
|
104
|
-
code: envelope.code,
|
|
105
|
-
sqlState: envelope.sqlState,
|
|
106
|
-
statementHandle: envelope.statementHandle
|
|
107
|
-
});
|
|
108
|
-
const columns = envelope.resultSetMetaData?.rowType ?? [];
|
|
109
|
-
const partitionCount = envelope.resultSetMetaData?.partitionInfo?.length ?? (envelope.data ? 1 : 0);
|
|
110
|
-
const firstRows = envelope.data ?? [];
|
|
111
|
-
const remainder = [];
|
|
112
|
-
for (let i = 1; i < partitionCount; i += 1) {
|
|
113
|
-
const partition = await getStatementResultPartition(client, envelope.statementHandle, i);
|
|
114
|
-
remainder.push(...partition.data ?? []);
|
|
115
|
-
}
|
|
116
|
-
const rawRows = [...firstRows, ...remainder];
|
|
117
|
-
const rows = options.hydrate !== false ? hydrateRows(rawRows, columns) : rawRows;
|
|
118
|
-
return {
|
|
119
|
-
handle: envelope.statementHandle,
|
|
120
|
-
columns,
|
|
121
|
-
rows,
|
|
122
|
-
envelope,
|
|
123
|
-
partitions: Math.max(1, partitionCount)
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Composio `SNOWFLAKE_BASIC_RUN_QUERY` parity — requires an explicit
|
|
128
|
-
* database + schema to match the published BASIC shape.
|
|
129
|
-
*/
|
|
130
|
-
async function runQuery(client, input, options = {}) {
|
|
131
|
-
return executeSql(client, {
|
|
132
|
-
statement: input.statement,
|
|
133
|
-
database: input.database,
|
|
134
|
-
schema: input.schema_name,
|
|
135
|
-
warehouse: input.warehouse,
|
|
136
|
-
role: input.role
|
|
137
|
-
}, options);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Fetch a single partition for a known handle.
|
|
141
|
-
*/
|
|
142
|
-
async function getStatementResultPartition(client, handle, partition) {
|
|
143
|
-
const body = await client.request(`${STATEMENTS_PATH}/${encodeURIComponent(handle)}`, {
|
|
144
|
-
method: "GET",
|
|
145
|
-
query: { partition }
|
|
146
|
-
});
|
|
147
|
-
return partitionResponseSchema.parse(body);
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Async iterator over every partition for a handle. Useful for streaming
|
|
151
|
-
* large result sets into downstream pipelines.
|
|
152
|
-
*/
|
|
153
|
-
async function* iterateStatementResult(client, handle, options = {}) {
|
|
154
|
-
const first = await getStatementResultPartition(client, handle, 0);
|
|
155
|
-
yield first;
|
|
156
|
-
const total = first.resultSetMetaData?.partitionInfo?.length ?? 0;
|
|
157
|
-
const cap = Math.min(total, options.maxPartitions ?? total);
|
|
158
|
-
for (let i = 1; i < cap; i += 1) yield await getStatementResultPartition(client, handle, i);
|
|
159
|
-
}
|
|
160
|
-
async function waitForStatementEnvelope(client, handle, options) {
|
|
161
|
-
const pollIntervalMs = options.pollIntervalMs ?? 500;
|
|
162
|
-
const maxWaitMs = options.maxWaitMs ?? 300 * 1e3;
|
|
163
|
-
const now = options.now ?? (() => Date.now());
|
|
164
|
-
const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
165
|
-
const deadline = now() + maxWaitMs;
|
|
166
|
-
for (;;) {
|
|
167
|
-
const result = await getStatement(client, handle);
|
|
168
|
-
if (result.status !== "pending") return result.response;
|
|
169
|
-
if (now() >= deadline) throw new SnowflakeApiError({
|
|
170
|
-
kind: "timeout",
|
|
171
|
-
status: 0,
|
|
172
|
-
message: `Statement ${handle} did not reach a terminal status within ${maxWaitMs}ms`,
|
|
173
|
-
retryable: false
|
|
174
|
-
});
|
|
175
|
-
await sleep(pollIntervalMs);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Blocking helper: polls `getStatement` until the statement reaches a
|
|
180
|
-
* terminal status or the `maxWaitMs` budget elapses. Returns the terminal
|
|
181
|
-
* envelope (throws for `failed` / `cancelled`).
|
|
182
|
-
*/
|
|
183
|
-
async function waitForStatement(client, handle, options = {}) {
|
|
184
|
-
const envelope = await waitForStatementEnvelope(client, handle, options);
|
|
185
|
-
const status = statementStatus({
|
|
186
|
-
httpStatus: 200,
|
|
187
|
-
code: envelope.code
|
|
188
|
-
});
|
|
189
|
-
if (status === "failed") throw new SnowflakeSqlError({
|
|
190
|
-
kind: "sql",
|
|
191
|
-
status: 422,
|
|
192
|
-
message: envelope.message ?? "Statement failed",
|
|
193
|
-
code: envelope.code,
|
|
194
|
-
sqlState: envelope.sqlState,
|
|
195
|
-
statementHandle: envelope.statementHandle
|
|
196
|
-
});
|
|
197
|
-
if (status === "cancelled") throw new SnowflakeSqlError({
|
|
198
|
-
kind: "cancelled",
|
|
199
|
-
status: 200,
|
|
200
|
-
message: envelope.message ?? "Statement was cancelled",
|
|
201
|
-
code: envelope.code,
|
|
202
|
-
sqlState: envelope.sqlState,
|
|
203
|
-
statementHandle: envelope.statementHandle
|
|
204
|
-
});
|
|
205
|
-
return envelope;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
//#endregion
|
|
209
|
-
export { cancelStatement, executeSql, getStatement, getStatementResultPartition, iterateStatementResult, runQuery, submitStatement, waitForStatement };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
//#region src/sql-options.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Option-list composition helpers for Snowflake DDL/DML.
|
|
4
|
-
*
|
|
5
|
-
* Most CREATE/ALTER statements (stages, file formats, pipes, tasks, COPY
|
|
6
|
-
* options, warehouses) accept option lists like:
|
|
7
|
-
*
|
|
8
|
-
* FILE_FORMAT = (TYPE = 'CSV' FIELD_DELIMITER = '|' SKIP_HEADER = 1)
|
|
9
|
-
* CREDENTIALS = (AWS_KEY_ID = 'abc' AWS_SECRET_KEY = 'xyz')
|
|
10
|
-
* COPY_OPTIONS = (ON_ERROR = 'CONTINUE' PURGE = TRUE)
|
|
11
|
-
*
|
|
12
|
-
* These helpers compose those lists safely:
|
|
13
|
-
* - String values are quoted with {@link quoteLiteral}.
|
|
14
|
-
* - Numbers, booleans, and raw-marked values pass through verbatim.
|
|
15
|
-
* - Nested option maps render as parenthesised sub-lists.
|
|
16
|
-
* - Ordering is preserved in insertion order.
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* A scalar that can appear on the RHS of an option. Pre-built raw SQL can
|
|
20
|
-
* be passed via {@link rawOption} when callers need to inject a keyword
|
|
21
|
-
* (e.g. `AUTO_REFRESH = TRUE`, `ENCRYPTION = (TYPE = 'SNOWFLAKE_SSE')`).
|
|
22
|
-
*/
|
|
23
|
-
type OptionScalar = string | number | bigint | boolean | null | undefined | RawSql | OptionMap | readonly OptionScalar[];
|
|
24
|
-
interface OptionMap {
|
|
25
|
-
readonly [key: string]: OptionScalar;
|
|
26
|
-
}
|
|
27
|
-
/** Marker type for a pre-formatted SQL fragment. */
|
|
28
|
-
interface RawSql {
|
|
29
|
-
readonly __rawSql: string;
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { OptionMap as t };
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { a as quoteLiteral } from "./sql-safety-BZpAPsq6.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/sql-options.ts
|
|
4
|
-
/**
|
|
5
|
-
* Option-list composition helpers for Snowflake DDL/DML.
|
|
6
|
-
*
|
|
7
|
-
* Most CREATE/ALTER statements (stages, file formats, pipes, tasks, COPY
|
|
8
|
-
* options, warehouses) accept option lists like:
|
|
9
|
-
*
|
|
10
|
-
* FILE_FORMAT = (TYPE = 'CSV' FIELD_DELIMITER = '|' SKIP_HEADER = 1)
|
|
11
|
-
* CREDENTIALS = (AWS_KEY_ID = 'abc' AWS_SECRET_KEY = 'xyz')
|
|
12
|
-
* COPY_OPTIONS = (ON_ERROR = 'CONTINUE' PURGE = TRUE)
|
|
13
|
-
*
|
|
14
|
-
* These helpers compose those lists safely:
|
|
15
|
-
* - String values are quoted with {@link quoteLiteral}.
|
|
16
|
-
* - Numbers, booleans, and raw-marked values pass through verbatim.
|
|
17
|
-
* - Nested option maps render as parenthesised sub-lists.
|
|
18
|
-
* - Ordering is preserved in insertion order.
|
|
19
|
-
*/
|
|
20
|
-
function isRawSql(value) {
|
|
21
|
-
return typeof value === "object" && value !== null && typeof value.__rawSql === "string";
|
|
22
|
-
}
|
|
23
|
-
function isOptionMap(value) {
|
|
24
|
-
if (value === null || typeof value !== "object") return false;
|
|
25
|
-
if (Array.isArray(value)) return false;
|
|
26
|
-
if (isRawSql(value)) return false;
|
|
27
|
-
if (value instanceof Date) return false;
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
function formatScalar(value) {
|
|
31
|
-
if (value === void 0) return void 0;
|
|
32
|
-
if (value === null) return "NULL";
|
|
33
|
-
if (isRawSql(value)) return value.__rawSql;
|
|
34
|
-
if (typeof value === "string") return quoteLiteral(value);
|
|
35
|
-
if (typeof value === "number") {
|
|
36
|
-
if (!Number.isFinite(value)) throw new TypeError("Cannot serialise NaN/Infinity as a Snowflake option value");
|
|
37
|
-
return value.toString();
|
|
38
|
-
}
|
|
39
|
-
if (typeof value === "bigint") return value.toString();
|
|
40
|
-
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
41
|
-
if (Array.isArray(value)) return `(${value.map((item) => formatScalar(item)).filter((item) => item !== void 0).join(", ")})`;
|
|
42
|
-
if (isOptionMap(value)) return formatOptionGroup(value);
|
|
43
|
-
throw new TypeError(`Unsupported Snowflake option value: ${typeof value}`);
|
|
44
|
-
}
|
|
45
|
-
/** Render a map like `(KEY = value KEY2 = 'literal')`. Empty maps render as `()`. */
|
|
46
|
-
function formatOptionGroup(map) {
|
|
47
|
-
const parts = [];
|
|
48
|
-
for (const [key, value] of Object.entries(map)) {
|
|
49
|
-
const rendered = formatScalar(value);
|
|
50
|
-
if (rendered === void 0) continue;
|
|
51
|
-
parts.push(`${key.toUpperCase()} = ${rendered}`);
|
|
52
|
-
}
|
|
53
|
-
return `(${parts.join(" ")})`;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Render a map as a space-separated option list (no wrapping parens). This
|
|
57
|
-
* is the form used directly in `CREATE STAGE ... URL='...' CREDENTIALS=(..)`
|
|
58
|
-
* where top-level options sit alongside the object name.
|
|
59
|
-
*/
|
|
60
|
-
function formatOptions(map) {
|
|
61
|
-
const parts = [];
|
|
62
|
-
for (const [key, value] of Object.entries(map)) {
|
|
63
|
-
const rendered = formatScalar(value);
|
|
64
|
-
if (rendered === void 0) continue;
|
|
65
|
-
parts.push(`${key.toUpperCase()} = ${rendered}`);
|
|
66
|
-
}
|
|
67
|
-
return parts.join(" ");
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Render a nested option group as ` KEY = (...)` — returns empty string when
|
|
71
|
-
* the map is undefined so callers can compose optional clauses inline.
|
|
72
|
-
*/
|
|
73
|
-
function renderOptionGroup(key, map) {
|
|
74
|
-
if (!map) return "";
|
|
75
|
-
return ` ${key.toUpperCase()} = ${formatOptionGroup(map)}`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
//#endregion
|
|
79
|
-
export { renderOptionGroup as n, formatOptions as t };
|