@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
package/dist/pipes/index.d.mts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { SnowflakeClient } from "../client/index.mjs";
|
|
2
|
-
import { d as HydratedRow } from "../statements-DJL0qVNA.mjs";
|
|
3
|
-
import { CatalogResult, ShowScopedOptions, showPipes } from "../catalog/index.mjs";
|
|
4
|
-
|
|
5
|
-
//#region src/pipes/index.d.ts
|
|
6
|
-
interface PipeRef {
|
|
7
|
-
readonly database?: string;
|
|
8
|
-
readonly schema?: string;
|
|
9
|
-
readonly name: string;
|
|
10
|
-
}
|
|
11
|
-
interface PipeContext {
|
|
12
|
-
readonly warehouse?: string;
|
|
13
|
-
readonly role?: string;
|
|
14
|
-
}
|
|
15
|
-
interface CreatePipeOptions extends PipeRef, PipeContext {
|
|
16
|
-
readonly orReplace?: boolean;
|
|
17
|
-
readonly ifNotExists?: boolean;
|
|
18
|
-
readonly autoIngest?: boolean;
|
|
19
|
-
/** S3 SNS topic ARN (AUTO_INGEST buckets sending SNS notifications). */
|
|
20
|
-
readonly awsSnsTopic?: string;
|
|
21
|
-
/** Notification integration for GCS / Azure Event Grid ingest. */
|
|
22
|
-
readonly integration?: string;
|
|
23
|
-
/** Notification integration that receives ERRORS (Snowflake error-integration object). */
|
|
24
|
-
readonly errorIntegration?: string;
|
|
25
|
-
readonly comment?: string;
|
|
26
|
-
/** The `COPY INTO ...` body that defines what this pipe loads. */
|
|
27
|
-
readonly copyStatement: string;
|
|
28
|
-
}
|
|
29
|
-
declare function createPipe(client: SnowflakeClient, options: CreatePipeOptions): Promise<void>;
|
|
30
|
-
interface AlterPipeOptions extends PipeRef, PipeContext {
|
|
31
|
-
readonly setPipeExecutionPaused?: boolean;
|
|
32
|
-
readonly comment?: string;
|
|
33
|
-
readonly refresh?: {
|
|
34
|
-
readonly prefix?: string;
|
|
35
|
-
readonly modifiedAfter?: string;
|
|
36
|
-
};
|
|
37
|
-
readonly rename?: PipeRef;
|
|
38
|
-
readonly unset?: readonly string[];
|
|
39
|
-
}
|
|
40
|
-
declare function alterPipe(client: SnowflakeClient, options: AlterPipeOptions): Promise<void>;
|
|
41
|
-
interface DropPipeOptions extends PipeRef, PipeContext {
|
|
42
|
-
readonly ifExists?: boolean;
|
|
43
|
-
}
|
|
44
|
-
declare function dropPipe(client: SnowflakeClient, options: DropPipeOptions): Promise<void>;
|
|
45
|
-
interface DescribePipeOptions extends PipeRef, PipeContext {}
|
|
46
|
-
declare function describePipe(client: SnowflakeClient, options: DescribePipeOptions): Promise<readonly HydratedRow[]>;
|
|
47
|
-
/** Convenience for `ALTER PIPE name REFRESH ...`. */
|
|
48
|
-
declare function refreshPipe(client: SnowflakeClient, options: PipeRef & PipeContext & {
|
|
49
|
-
readonly prefix?: string;
|
|
50
|
-
readonly modifiedAfter?: string;
|
|
51
|
-
}): Promise<void>;
|
|
52
|
-
interface SnowpipeInsertFile {
|
|
53
|
-
readonly path: string;
|
|
54
|
-
readonly size?: number | bigint;
|
|
55
|
-
}
|
|
56
|
-
interface InsertFilesOptions extends PipeRef {
|
|
57
|
-
readonly files: readonly SnowpipeInsertFile[];
|
|
58
|
-
readonly requestId?: string;
|
|
59
|
-
}
|
|
60
|
-
interface InsertFilesResponse {
|
|
61
|
-
readonly requestId: string;
|
|
62
|
-
/** Server-reported ingest batch id (`pipe` field per Snowflake docs). */
|
|
63
|
-
readonly pipe?: string;
|
|
64
|
-
readonly responseCode?: string;
|
|
65
|
-
readonly message?: string;
|
|
66
|
-
readonly skippedFiles?: readonly {
|
|
67
|
-
readonly path: string;
|
|
68
|
-
readonly reason?: string;
|
|
69
|
-
}[];
|
|
70
|
-
}
|
|
71
|
-
declare function insertFiles(client: SnowflakeClient, options: InsertFilesOptions): Promise<InsertFilesResponse>;
|
|
72
|
-
interface InsertReportOptions extends PipeRef {
|
|
73
|
-
readonly beginMark?: string;
|
|
74
|
-
readonly requestId?: string;
|
|
75
|
-
}
|
|
76
|
-
interface InsertReportResponse {
|
|
77
|
-
readonly pipe?: string;
|
|
78
|
-
readonly completeResult?: boolean;
|
|
79
|
-
readonly nextBeginMark?: string;
|
|
80
|
-
readonly files?: readonly {
|
|
81
|
-
readonly path: string;
|
|
82
|
-
readonly stageLocation?: string;
|
|
83
|
-
readonly fileSize?: number;
|
|
84
|
-
readonly timeReceived?: string;
|
|
85
|
-
readonly lastInsertTime?: string;
|
|
86
|
-
readonly rowsInserted?: number;
|
|
87
|
-
readonly rowsParsed?: number;
|
|
88
|
-
readonly errorsSeen?: number;
|
|
89
|
-
readonly errorLimit?: number;
|
|
90
|
-
readonly firstError?: string;
|
|
91
|
-
readonly status?: string;
|
|
92
|
-
}[];
|
|
93
|
-
}
|
|
94
|
-
declare function insertReport(client: SnowflakeClient, options: InsertReportOptions): Promise<InsertReportResponse>;
|
|
95
|
-
interface LoadHistoryScanOptions extends PipeRef {
|
|
96
|
-
readonly startTimeInclusive: string;
|
|
97
|
-
readonly endTimeExclusive: string;
|
|
98
|
-
readonly requestId?: string;
|
|
99
|
-
}
|
|
100
|
-
interface LoadHistoryScanResponse {
|
|
101
|
-
readonly pipe?: string;
|
|
102
|
-
readonly completeResult?: boolean;
|
|
103
|
-
readonly files?: readonly {
|
|
104
|
-
readonly path: string;
|
|
105
|
-
readonly stageLocation?: string;
|
|
106
|
-
readonly fileSize?: number;
|
|
107
|
-
readonly timeReceived?: string;
|
|
108
|
-
readonly lastInsertTime?: string;
|
|
109
|
-
readonly rowsInserted?: number;
|
|
110
|
-
readonly rowsParsed?: number;
|
|
111
|
-
readonly errorsSeen?: number;
|
|
112
|
-
readonly errorLimit?: number;
|
|
113
|
-
readonly firstError?: string;
|
|
114
|
-
readonly status?: string;
|
|
115
|
-
}[];
|
|
116
|
-
}
|
|
117
|
-
declare function loadHistoryScan(client: SnowflakeClient, options: LoadHistoryScanOptions): Promise<LoadHistoryScanResponse>;
|
|
118
|
-
//#endregion
|
|
119
|
-
export { AlterPipeOptions, type CatalogResult, CreatePipeOptions, DescribePipeOptions, DropPipeOptions, InsertFilesOptions, InsertFilesResponse, InsertReportOptions, InsertReportResponse, LoadHistoryScanOptions, LoadHistoryScanResponse, PipeContext, PipeRef, type ShowScopedOptions, SnowpipeInsertFile, alterPipe, createPipe, describePipe, dropPipe, insertFiles, insertReport, loadHistoryScan, refreshPipe, showPipes };
|
package/dist/pipes/index.mjs
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { executeSql } from "../sql/index.mjs";
|
|
2
|
-
import { a as quoteLiteral, i as quoteIdentifier, t as buildFqn } from "../sql-safety-BZpAPsq6.mjs";
|
|
3
|
-
import { showPipes } from "../catalog/index.mjs";
|
|
4
|
-
|
|
5
|
-
//#region src/pipes/index.ts
|
|
6
|
-
function pipeFqn(ref) {
|
|
7
|
-
return buildFqn(ref.database, ref.schema, ref.name);
|
|
8
|
-
}
|
|
9
|
-
function pipeRestPath(ref, required) {
|
|
10
|
-
if (required && (!ref.database || !ref.schema)) throw new Error("Snowpipe REST requires fully-qualified database.schema.pipe (provide `database` and `schema`)");
|
|
11
|
-
return [
|
|
12
|
-
ref.database,
|
|
13
|
-
ref.schema,
|
|
14
|
-
ref.name
|
|
15
|
-
].filter((segment) => segment !== void 0 && segment.length > 0).join(".");
|
|
16
|
-
}
|
|
17
|
-
async function createPipe(client, options) {
|
|
18
|
-
const prefix = `CREATE${options.orReplace ? " OR REPLACE" : ""} PIPE${options.ifNotExists ? " IF NOT EXISTS" : ""}`;
|
|
19
|
-
const auto = options.autoIngest ? " AUTO_INGEST = TRUE" : "";
|
|
20
|
-
const sns = options.awsSnsTopic ? ` AWS_SNS_TOPIC = ${quoteLiteral(options.awsSnsTopic)}` : "";
|
|
21
|
-
const integration = options.integration ? ` INTEGRATION = ${quoteLiteral(options.integration)}` : "";
|
|
22
|
-
const errorIntegration = options.errorIntegration ? ` ERROR_INTEGRATION = ${quoteIdentifier(options.errorIntegration)}` : "";
|
|
23
|
-
const comment = options.comment ? ` COMMENT = ${quoteLiteral(options.comment)}` : "";
|
|
24
|
-
await executeSql(client, {
|
|
25
|
-
statement: `${prefix} ${pipeFqn(options)}${auto}${sns}${integration}${errorIntegration}${comment} AS ${options.copyStatement}`,
|
|
26
|
-
warehouse: options.warehouse,
|
|
27
|
-
role: options.role
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
async function alterPipe(client, options) {
|
|
31
|
-
let tail;
|
|
32
|
-
if (options.rename) tail = `RENAME TO ${pipeFqn(options.rename)}`;
|
|
33
|
-
else if (options.refresh) tail = `REFRESH${options.refresh.prefix ? ` PREFIX = ${quoteLiteral(options.refresh.prefix)}` : ""}${options.refresh.modifiedAfter ? ` MODIFIED_AFTER = ${quoteLiteral(options.refresh.modifiedAfter)}` : ""}`;
|
|
34
|
-
else if (options.setPipeExecutionPaused !== void 0) tail = `SET PIPE_EXECUTION_PAUSED = ${options.setPipeExecutionPaused ? "TRUE" : "FALSE"}`;
|
|
35
|
-
else if (options.comment !== void 0) tail = `SET COMMENT = ${quoteLiteral(options.comment)}`;
|
|
36
|
-
else if (options.unset && options.unset.length > 0) tail = `UNSET ${options.unset.map((k) => k.toUpperCase()).join(", ")}`;
|
|
37
|
-
else throw new Error("alterPipe requires one of: rename / refresh / setPipeExecutionPaused / comment / unset");
|
|
38
|
-
await executeSql(client, {
|
|
39
|
-
statement: `ALTER PIPE ${pipeFqn(options)} ${tail}`,
|
|
40
|
-
warehouse: options.warehouse,
|
|
41
|
-
role: options.role
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
async function dropPipe(client, options) {
|
|
45
|
-
await executeSql(client, {
|
|
46
|
-
statement: `DROP PIPE${options.ifExists ? " IF EXISTS" : ""} ${pipeFqn(options)}`,
|
|
47
|
-
warehouse: options.warehouse,
|
|
48
|
-
role: options.role
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
async function describePipe(client, options) {
|
|
52
|
-
return (await executeSql(client, {
|
|
53
|
-
statement: `DESCRIBE PIPE ${pipeFqn(options)}`,
|
|
54
|
-
warehouse: options.warehouse,
|
|
55
|
-
role: options.role
|
|
56
|
-
})).rows;
|
|
57
|
-
}
|
|
58
|
-
/** Convenience for `ALTER PIPE name REFRESH ...`. */
|
|
59
|
-
async function refreshPipe(client, options) {
|
|
60
|
-
await alterPipe(client, {
|
|
61
|
-
...options,
|
|
62
|
-
refresh: {
|
|
63
|
-
prefix: options.prefix,
|
|
64
|
-
modifiedAfter: options.modifiedAfter
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
async function insertFiles(client, options) {
|
|
69
|
-
if (options.files.length === 0) throw new Error("insertFiles requires at least one file");
|
|
70
|
-
const path = `/v1/data/pipes/${pipeRestPath(options, true)}/insertFiles`;
|
|
71
|
-
const body = { files: options.files.map((f) => ({
|
|
72
|
-
path: f.path,
|
|
73
|
-
...f.size !== void 0 ? { size: typeof f.size === "bigint" ? Number(f.size) : f.size } : {}
|
|
74
|
-
})) };
|
|
75
|
-
return client.request(path, {
|
|
76
|
-
method: "POST",
|
|
77
|
-
body,
|
|
78
|
-
requestId: options.requestId,
|
|
79
|
-
query: options.requestId ? { requestId: options.requestId } : void 0
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
async function insertReport(client, options) {
|
|
83
|
-
const path = `/v1/data/pipes/${pipeRestPath(options, true)}/insertReport`;
|
|
84
|
-
const query = {};
|
|
85
|
-
if (options.beginMark) query.beginMark = options.beginMark;
|
|
86
|
-
if (options.requestId) query.requestId = options.requestId;
|
|
87
|
-
return client.request(path, {
|
|
88
|
-
method: "GET",
|
|
89
|
-
query
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
async function loadHistoryScan(client, options) {
|
|
93
|
-
const path = `/v1/data/pipes/${pipeRestPath(options, true)}/loadHistoryScan`;
|
|
94
|
-
const query = {
|
|
95
|
-
startTimeInclusive: options.startTimeInclusive,
|
|
96
|
-
endTimeExclusive: options.endTimeExclusive
|
|
97
|
-
};
|
|
98
|
-
if (options.requestId) query.requestId = options.requestId;
|
|
99
|
-
return client.request(path, {
|
|
100
|
-
method: "GET",
|
|
101
|
-
query
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
//#endregion
|
|
106
|
-
export { alterPipe, createPipe, describePipe, dropPipe, insertFiles, insertReport, loadHistoryScan, refreshPipe, showPipes };
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { SnowflakeClient } from "../client/index.mjs";
|
|
2
|
-
import { d as HydratedRow, v as SqlBinding } from "../statements-DJL0qVNA.mjs";
|
|
3
|
-
import { ExecuteSqlResult } from "../sql/index.mjs";
|
|
4
|
-
import { t as OptionMap } from "../sql-options-2k5xQ-oS.mjs";
|
|
5
|
-
import { CatalogResult, ShowScopedOptions, showProcedures } from "../catalog/index.mjs";
|
|
6
|
-
import { RowValue } from "../rows/index.mjs";
|
|
7
|
-
|
|
8
|
-
//#region src/procedures/index.d.ts
|
|
9
|
-
interface ProcedureRef {
|
|
10
|
-
readonly database?: string;
|
|
11
|
-
readonly schema?: string;
|
|
12
|
-
readonly name: string;
|
|
13
|
-
}
|
|
14
|
-
interface ProcedureContext {
|
|
15
|
-
readonly warehouse?: string;
|
|
16
|
-
readonly role?: string;
|
|
17
|
-
}
|
|
18
|
-
interface ProcedureArgument {
|
|
19
|
-
readonly name: string;
|
|
20
|
-
readonly type: string;
|
|
21
|
-
readonly defaultExpression?: string;
|
|
22
|
-
}
|
|
23
|
-
type ProcedureLanguage = 'SQL' | 'JAVASCRIPT' | 'PYTHON' | 'JAVA' | 'SCALA';
|
|
24
|
-
type ExecuteAs = 'CALLER' | 'OWNER';
|
|
25
|
-
interface CreateProcedureOptions extends ProcedureRef, ProcedureContext {
|
|
26
|
-
readonly orReplace?: boolean;
|
|
27
|
-
readonly ifNotExists?: boolean;
|
|
28
|
-
readonly secure?: boolean;
|
|
29
|
-
readonly arguments?: readonly ProcedureArgument[];
|
|
30
|
-
readonly returns: string;
|
|
31
|
-
readonly language?: ProcedureLanguage;
|
|
32
|
-
readonly executeAs?: ExecuteAs;
|
|
33
|
-
/** Additional keywords: `STRICT`, `IMMUTABLE`, `VOLATILE`, etc. */
|
|
34
|
-
readonly modifiers?: readonly string[];
|
|
35
|
-
/** Language-specific options: `RUNTIME_VERSION`, `PACKAGES`, `HANDLER`, `IMPORTS`. */
|
|
36
|
-
readonly options?: OptionMap;
|
|
37
|
-
readonly comment?: string;
|
|
38
|
-
readonly as: string;
|
|
39
|
-
readonly dollarQuotedBody?: boolean;
|
|
40
|
-
}
|
|
41
|
-
declare function createProcedure(client: SnowflakeClient, options: CreateProcedureOptions): Promise<void>;
|
|
42
|
-
interface DropProcedureOptions extends ProcedureRef, ProcedureContext {
|
|
43
|
-
readonly ifExists?: boolean;
|
|
44
|
-
readonly arguments?: readonly ProcedureArgument[];
|
|
45
|
-
}
|
|
46
|
-
declare function dropProcedure(client: SnowflakeClient, options: DropProcedureOptions): Promise<void>;
|
|
47
|
-
interface DescribeProcedureOptions extends ProcedureRef, ProcedureContext {
|
|
48
|
-
readonly arguments?: readonly ProcedureArgument[];
|
|
49
|
-
}
|
|
50
|
-
declare function describeProcedure(client: SnowflakeClient, options: DescribeProcedureOptions): Promise<readonly HydratedRow[]>;
|
|
51
|
-
interface CallProcedureOptions extends ProcedureRef, ProcedureContext {
|
|
52
|
-
/** Positional arguments — every value flows through SQL API bindings (`?` placeholders). */
|
|
53
|
-
readonly arguments?: readonly RowValue[];
|
|
54
|
-
/** Pre-built bindings map (takes precedence over `arguments`). */
|
|
55
|
-
readonly bindings?: Readonly<Record<string, SqlBinding>>;
|
|
56
|
-
/** Raw SQL expression list when you need to pass a named function, subquery, or bind-unfriendly value. */
|
|
57
|
-
readonly rawArguments?: readonly string[];
|
|
58
|
-
}
|
|
59
|
-
declare function callProcedure(client: SnowflakeClient, options: CallProcedureOptions): Promise<ExecuteSqlResult<HydratedRow | readonly unknown[]>>;
|
|
60
|
-
//#endregion
|
|
61
|
-
export { CallProcedureOptions, type CatalogResult, CreateProcedureOptions, DescribeProcedureOptions, DropProcedureOptions, ExecuteAs, ProcedureArgument, ProcedureContext, ProcedureLanguage, ProcedureRef, type ShowScopedOptions, callProcedure, createProcedure, describeProcedure, dropProcedure, showProcedures };
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { executeSql } from "../sql/index.mjs";
|
|
2
|
-
import { a as quoteLiteral, t as buildFqn } from "../sql-safety-BZpAPsq6.mjs";
|
|
3
|
-
import { BindingBuilder } from "../rows/index.mjs";
|
|
4
|
-
import { t as formatOptions } from "../sql-options-D6GEa21F.mjs";
|
|
5
|
-
import { showProcedures } from "../catalog/index.mjs";
|
|
6
|
-
|
|
7
|
-
//#region src/procedures/index.ts
|
|
8
|
-
function renderArguments(args) {
|
|
9
|
-
if (!args || args.length === 0) return "()";
|
|
10
|
-
return `(${args.map((a) => {
|
|
11
|
-
const suffix = a.defaultExpression ? ` DEFAULT ${a.defaultExpression}` : "";
|
|
12
|
-
return `${a.name} ${a.type.toUpperCase()}${suffix}`;
|
|
13
|
-
}).join(", ")})`;
|
|
14
|
-
}
|
|
15
|
-
function renderArgumentTypes(args) {
|
|
16
|
-
if (!args || args.length === 0) return "()";
|
|
17
|
-
return `(${args.map((a) => a.type.toUpperCase()).join(", ")})`;
|
|
18
|
-
}
|
|
19
|
-
function renderBody(body, forceDollarQuoted, language) {
|
|
20
|
-
if (forceDollarQuoted ?? (language !== void 0 && language !== "SQL")) {
|
|
21
|
-
if (body.includes("$$")) throw new Error("Procedure body contains \"$$\"; cannot safely dollar-quote.");
|
|
22
|
-
return `$$${body}$$`;
|
|
23
|
-
}
|
|
24
|
-
return body;
|
|
25
|
-
}
|
|
26
|
-
async function createProcedure(client, options) {
|
|
27
|
-
const prefix = `CREATE${options.orReplace ? " OR REPLACE" : ""}${options.secure ? " SECURE" : ""} PROCEDURE${options.ifNotExists ? " IF NOT EXISTS" : ""}`;
|
|
28
|
-
const args = renderArguments(options.arguments);
|
|
29
|
-
const language = options.language ? ` LANGUAGE ${options.language}` : "";
|
|
30
|
-
const executeAs = options.executeAs ? ` EXECUTE AS ${options.executeAs}` : "";
|
|
31
|
-
const modifiers = options.modifiers && options.modifiers.length > 0 ? ` ${options.modifiers.map((m) => m.toUpperCase()).join(" ")}` : "";
|
|
32
|
-
const body = options.options && Object.keys(options.options).length > 0 ? ` ${formatOptions(options.options)}` : "";
|
|
33
|
-
const comment = options.comment ? ` COMMENT = ${quoteLiteral(options.comment)}` : "";
|
|
34
|
-
const rendered = renderBody(options.as, options.dollarQuotedBody, options.language);
|
|
35
|
-
await executeSql(client, {
|
|
36
|
-
statement: `${prefix} ${buildFqn(options.database, options.schema, options.name)}${args} RETURNS ${options.returns}${language}${executeAs}${modifiers}${body}${comment} AS ${rendered}`,
|
|
37
|
-
warehouse: options.warehouse,
|
|
38
|
-
role: options.role
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
async function dropProcedure(client, options) {
|
|
42
|
-
const fqn = buildFqn(options.database, options.schema, options.name);
|
|
43
|
-
await executeSql(client, {
|
|
44
|
-
statement: `DROP PROCEDURE${options.ifExists ? " IF EXISTS" : ""} ${fqn}${renderArgumentTypes(options.arguments)}`,
|
|
45
|
-
warehouse: options.warehouse,
|
|
46
|
-
role: options.role
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
async function describeProcedure(client, options) {
|
|
50
|
-
return (await executeSql(client, {
|
|
51
|
-
statement: `DESCRIBE PROCEDURE ${buildFqn(options.database, options.schema, options.name)}${renderArgumentTypes(options.arguments)}`,
|
|
52
|
-
warehouse: options.warehouse,
|
|
53
|
-
role: options.role
|
|
54
|
-
})).rows;
|
|
55
|
-
}
|
|
56
|
-
async function callProcedure(client, options) {
|
|
57
|
-
const fqn = buildFqn(options.database, options.schema, options.name);
|
|
58
|
-
if (options.rawArguments) return executeSql(client, {
|
|
59
|
-
statement: `CALL ${fqn}(${options.rawArguments.join(", ")})`,
|
|
60
|
-
warehouse: options.warehouse,
|
|
61
|
-
role: options.role,
|
|
62
|
-
bindings: options.bindings
|
|
63
|
-
});
|
|
64
|
-
const builder = new BindingBuilder();
|
|
65
|
-
const placeholders = (options.arguments ?? []).map((a) => builder.add(a));
|
|
66
|
-
const bindings = options.bindings ? {
|
|
67
|
-
...builder.toRecord(),
|
|
68
|
-
...options.bindings
|
|
69
|
-
} : builder.size() > 0 ? builder.toRecord() : void 0;
|
|
70
|
-
return executeSql(client, {
|
|
71
|
-
statement: `CALL ${fqn}(${placeholders.join(", ")})`,
|
|
72
|
-
warehouse: options.warehouse,
|
|
73
|
-
role: options.role,
|
|
74
|
-
bindings
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
//#endregion
|
|
79
|
-
export { callProcedure, createProcedure, describeProcedure, dropProcedure, showProcedures };
|
package/dist/results/index.d.mts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { d as HydratedRow, m as ColumnMeta } from "../statements-DJL0qVNA.mjs";
|
|
2
|
-
//#region src/results/index.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* Hydrate a single positional row into an object keyed by column name.
|
|
5
|
-
* Values are coerced per Snowflake type; unknown / unrepresentable values
|
|
6
|
-
* are passed through verbatim.
|
|
7
|
-
*/
|
|
8
|
-
declare function hydrateRow(row: readonly unknown[], columns: readonly ColumnMeta[]): HydratedRow;
|
|
9
|
-
declare function hydrateRows(rows: readonly (readonly unknown[])[], columns: readonly ColumnMeta[]): HydratedRow[];
|
|
10
|
-
/**
|
|
11
|
-
* Coerce a single raw value (already in whatever shape Snowflake sent it
|
|
12
|
-
* over the wire) into the nearest safe JS primitive / object.
|
|
13
|
-
*/
|
|
14
|
-
declare function hydrateValue(raw: unknown, column: ColumnMeta): unknown;
|
|
15
|
-
//#endregion
|
|
16
|
-
export { hydrateRow, hydrateRows, hydrateValue };
|
package/dist/results/index.mjs
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
//#region src/results/index.ts
|
|
2
|
-
const MAX_SAFE_INT_AS_STRING = String(Number.MAX_SAFE_INTEGER);
|
|
3
|
-
const MIN_SAFE_INT_AS_STRING = String(Number.MIN_SAFE_INTEGER);
|
|
4
|
-
/**
|
|
5
|
-
* Hydrate a single positional row into an object keyed by column name.
|
|
6
|
-
* Values are coerced per Snowflake type; unknown / unrepresentable values
|
|
7
|
-
* are passed through verbatim.
|
|
8
|
-
*/
|
|
9
|
-
function hydrateRow(row, columns) {
|
|
10
|
-
const hydrated = {};
|
|
11
|
-
for (let i = 0; i < columns.length; i += 1) {
|
|
12
|
-
const column = columns[i];
|
|
13
|
-
if (!column) continue;
|
|
14
|
-
hydrated[column.name] = hydrateValue(row[i], column);
|
|
15
|
-
}
|
|
16
|
-
return hydrated;
|
|
17
|
-
}
|
|
18
|
-
function hydrateRows(rows, columns) {
|
|
19
|
-
const hydrated = [];
|
|
20
|
-
for (const row of rows) hydrated.push(hydrateRow(row, columns));
|
|
21
|
-
return hydrated;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Coerce a single raw value (already in whatever shape Snowflake sent it
|
|
25
|
-
* over the wire) into the nearest safe JS primitive / object.
|
|
26
|
-
*/
|
|
27
|
-
function hydrateValue(raw, column) {
|
|
28
|
-
if (raw === null || raw === void 0) return null;
|
|
29
|
-
const type = column.type.toUpperCase();
|
|
30
|
-
if (typeof raw === "string") return coerceString(raw, type, column);
|
|
31
|
-
return raw;
|
|
32
|
-
}
|
|
33
|
-
function coerceString(raw, type, column) {
|
|
34
|
-
if (type === "BOOLEAN") return raw === "true" || raw === "1";
|
|
35
|
-
if (type === "FIXED") return coerceFixed(raw, column);
|
|
36
|
-
if (type === "REAL") {
|
|
37
|
-
const parsed = Number(raw);
|
|
38
|
-
return Number.isFinite(parsed) ? parsed : raw;
|
|
39
|
-
}
|
|
40
|
-
if (type === "BINARY") return raw;
|
|
41
|
-
if (type === "DATE" || type === "TIME" || type.startsWith("TIMESTAMP")) return raw;
|
|
42
|
-
if (type === "OBJECT" || type === "ARRAY" || type === "VARIANT") try {
|
|
43
|
-
return JSON.parse(raw);
|
|
44
|
-
} catch {
|
|
45
|
-
return raw;
|
|
46
|
-
}
|
|
47
|
-
return raw;
|
|
48
|
-
}
|
|
49
|
-
function coerceFixed(raw, column) {
|
|
50
|
-
if ((column.scale ?? 0) > 0) {
|
|
51
|
-
const parsed = Number(raw);
|
|
52
|
-
return Number.isFinite(parsed) ? parsed : raw;
|
|
53
|
-
}
|
|
54
|
-
if (isSafeInteger(raw)) return Number(raw);
|
|
55
|
-
return raw;
|
|
56
|
-
}
|
|
57
|
-
function isSafeInteger(value) {
|
|
58
|
-
if (!/^-?\d+$/u.test(value)) return false;
|
|
59
|
-
if (value.startsWith("-")) return value.length < MIN_SAFE_INT_AS_STRING.length || value.length === MIN_SAFE_INT_AS_STRING.length && value <= MIN_SAFE_INT_AS_STRING;
|
|
60
|
-
return value.length < MAX_SAFE_INT_AS_STRING.length || value.length === MAX_SAFE_INT_AS_STRING.length && value <= MAX_SAFE_INT_AS_STRING;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
//#endregion
|
|
64
|
-
export { hydrateRow, hydrateRows, hydrateValue };
|
package/dist/retry-B4-9MZIp.mjs
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
//#region src/jwt.ts
|
|
2
|
-
/**
|
|
3
|
-
* Snowflake JWT signing + public-key fingerprint (RS256, key-pair auth).
|
|
4
|
-
*
|
|
5
|
-
* Isolate-safe — built on `globalThis.crypto.subtle`, no Node `crypto`
|
|
6
|
-
* imports, no native SDKs. Works in Cloudflare Workers, Node 19+,
|
|
7
|
-
* and any modern V8/JSC isolate.
|
|
8
|
-
*
|
|
9
|
-
* Reference: https://docs.snowflake.com/en/user-guide/key-pair-auth
|
|
10
|
-
*/
|
|
11
|
-
const DEFAULT_JWT_LIFETIME_SECONDS = 3300;
|
|
12
|
-
async function createSnowflakeJwt(input) {
|
|
13
|
-
const now = Math.floor((input.now?.() ?? Date.now()) / 1e3);
|
|
14
|
-
const exp = now + (input.lifetimeSeconds ?? DEFAULT_JWT_LIFETIME_SECONDS);
|
|
15
|
-
const account = normalizeAccountForJwt(input.account).toUpperCase();
|
|
16
|
-
const user = input.user.toUpperCase();
|
|
17
|
-
const privateKey = await importRsaPrivateKey(input.privateKeyPem);
|
|
18
|
-
const fingerprint = input.publicKeyFingerprint ?? await derivePublicKeyFingerprint(privateKey);
|
|
19
|
-
const issuer = `${account}.${user}.${fingerprint}`;
|
|
20
|
-
const subject = `${account}.${user}`;
|
|
21
|
-
const header = {
|
|
22
|
-
alg: "RS256",
|
|
23
|
-
typ: "JWT"
|
|
24
|
-
};
|
|
25
|
-
const payload = {
|
|
26
|
-
iss: issuer,
|
|
27
|
-
sub: subject,
|
|
28
|
-
iat: now,
|
|
29
|
-
exp
|
|
30
|
-
};
|
|
31
|
-
const signingInput = `${base64UrlEncode(JSON.stringify(header))}.${base64UrlEncode(JSON.stringify(payload))}`;
|
|
32
|
-
const signature = await crypto.subtle.sign({ name: "RSASSA-PKCS1-v1_5" }, privateKey, new TextEncoder().encode(signingInput));
|
|
33
|
-
return {
|
|
34
|
-
token: `${signingInput}.${base64UrlEncode(new Uint8Array(signature))}`,
|
|
35
|
-
expiresAt: exp,
|
|
36
|
-
fingerprint,
|
|
37
|
-
issuer,
|
|
38
|
-
subject
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Compute `SHA256:<base64>` fingerprint over the DER-encoded SPKI public key
|
|
43
|
-
* derived from the PKCS#8 private key. Matches Snowflake's
|
|
44
|
-
* `RSA_PUBLIC_KEY_FP` value shown by `DESC USER`.
|
|
45
|
-
*/
|
|
46
|
-
async function derivePublicKeyFingerprint(privateKey) {
|
|
47
|
-
const publicKey = await extractPublicKey(privateKey);
|
|
48
|
-
const spkiDer = await crypto.subtle.exportKey("spki", publicKey);
|
|
49
|
-
const digest = await crypto.subtle.digest("SHA-256", spkiDer);
|
|
50
|
-
return `SHA256:${base64Encode(new Uint8Array(digest))}`;
|
|
51
|
-
}
|
|
52
|
-
async function extractPublicKey(privateKey) {
|
|
53
|
-
const jwk = await crypto.subtle.exportKey("jwk", privateKey);
|
|
54
|
-
const publicJwk = {
|
|
55
|
-
kty: jwk.kty,
|
|
56
|
-
n: jwk.n,
|
|
57
|
-
e: jwk.e,
|
|
58
|
-
alg: jwk.alg,
|
|
59
|
-
ext: true
|
|
60
|
-
};
|
|
61
|
-
return crypto.subtle.importKey("jwk", publicJwk, {
|
|
62
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
63
|
-
hash: "SHA-256"
|
|
64
|
-
}, true, ["verify"]);
|
|
65
|
-
}
|
|
66
|
-
async function importRsaPrivateKey(pem) {
|
|
67
|
-
const armor = peekPemArmor(pem);
|
|
68
|
-
if (!armor) throw new TypeError("SNOWFLAKE_PRIVATE_KEY is not a PEM-encoded key.");
|
|
69
|
-
if (armor.type !== "PRIVATE KEY") throw new TypeError(`Unsupported PEM type "${armor.type}". Expected PKCS#8 PEM ("-----BEGIN PRIVATE KEY-----"). Convert PKCS#1 keys with \`openssl pkcs8 -topk8 -nocrypt\`.`);
|
|
70
|
-
return crypto.subtle.importKey("pkcs8", toArrayBuffer(base64Decode(armor.body)), {
|
|
71
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
72
|
-
hash: "SHA-256"
|
|
73
|
-
}, true, ["sign"]);
|
|
74
|
-
}
|
|
75
|
-
function toArrayBuffer(view) {
|
|
76
|
-
const copy = new Uint8Array(view.byteLength);
|
|
77
|
-
copy.set(view);
|
|
78
|
-
return copy.buffer;
|
|
79
|
-
}
|
|
80
|
-
function peekPemArmor(pem) {
|
|
81
|
-
const match = pem.match(/-----BEGIN ([A-Z ]+)-----([\s\S]*?)-----END \1-----/u);
|
|
82
|
-
if (!match) return void 0;
|
|
83
|
-
const type = match[1]?.trim();
|
|
84
|
-
const body = match[2]?.replace(/\s+/gu, "");
|
|
85
|
-
if (!type || !body) return void 0;
|
|
86
|
-
return {
|
|
87
|
-
type,
|
|
88
|
-
body
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Account identifiers accepted by Snowflake take one of these shapes:
|
|
93
|
-
* - `orgname-accountname` (preferred)
|
|
94
|
-
* - `account_locator.region`
|
|
95
|
-
* - `account_locator.region.aws`
|
|
96
|
-
* - `account_locator` (legacy single-region)
|
|
97
|
-
*
|
|
98
|
-
* The JWT `iss`/`sub` require just the account segment (everything before the
|
|
99
|
-
* first dot for locator-form identifiers) — the org-account hyphen form is
|
|
100
|
-
* passed through as-is.
|
|
101
|
-
*/
|
|
102
|
-
function normalizeAccountForJwt(account) {
|
|
103
|
-
const trimmed = account.trim();
|
|
104
|
-
const firstDot = trimmed.indexOf(".");
|
|
105
|
-
return firstDot === -1 ? trimmed : trimmed.slice(0, firstDot);
|
|
106
|
-
}
|
|
107
|
-
function base64UrlEncode(input) {
|
|
108
|
-
return base64Encode(typeof input === "string" ? new TextEncoder().encode(input) : input).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
|
|
109
|
-
}
|
|
110
|
-
function base64Encode(bytes) {
|
|
111
|
-
let binary = "";
|
|
112
|
-
for (let i = 0; i < bytes.byteLength; i += 1) binary += String.fromCharCode(bytes[i] ?? 0);
|
|
113
|
-
if (typeof btoa === "function") return btoa(binary);
|
|
114
|
-
/* c8 ignore next */
|
|
115
|
-
return Buffer.from(bytes).toString("base64");
|
|
116
|
-
}
|
|
117
|
-
function base64Decode(input) {
|
|
118
|
-
if (typeof atob === "function") {
|
|
119
|
-
const binary = atob(input);
|
|
120
|
-
const bytes = new Uint8Array(binary.length);
|
|
121
|
-
for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
|
|
122
|
-
return bytes;
|
|
123
|
-
}
|
|
124
|
-
/* c8 ignore next */
|
|
125
|
-
return new Uint8Array(Buffer.from(input, "base64"));
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
//#endregion
|
|
129
|
-
//#region src/retry.ts
|
|
130
|
-
const DEFAULT_RETRY_POLICY = {
|
|
131
|
-
maxRetries: 4,
|
|
132
|
-
baseDelayMs: 500,
|
|
133
|
-
maxDelayMs: 2e4,
|
|
134
|
-
jitterMs: 250
|
|
135
|
-
};
|
|
136
|
-
const RETRYABLE_KINDS = new Set([
|
|
137
|
-
"rate_limit",
|
|
138
|
-
"server_error",
|
|
139
|
-
"timeout",
|
|
140
|
-
"network"
|
|
141
|
-
]);
|
|
142
|
-
function shouldRetry(kind, attempt, policy = DEFAULT_RETRY_POLICY) {
|
|
143
|
-
if (attempt >= policy.maxRetries) return false;
|
|
144
|
-
return RETRYABLE_KINDS.has(kind);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Compute the delay (ms) before the next retry. If the server provided a
|
|
148
|
-
* `Retry-After` header we respect it (clamped to `maxDelayMs`). Otherwise we
|
|
149
|
-
* use `baseDelayMs * 2^attempt` with additive jitter, capped at `maxDelayMs`.
|
|
150
|
-
*/
|
|
151
|
-
function computeBackoffMs({ attempt, retryAfterMs, policy = DEFAULT_RETRY_POLICY, random = Math.random }) {
|
|
152
|
-
if (retryAfterMs !== void 0 && retryAfterMs >= 0) return Math.min(retryAfterMs, policy.maxDelayMs);
|
|
153
|
-
const exponent = Math.max(0, attempt - 1);
|
|
154
|
-
const base = policy.baseDelayMs * 2 ** exponent;
|
|
155
|
-
const jitter = policy.jitterMs > 0 ? random() * policy.jitterMs : 0;
|
|
156
|
-
return Math.min(policy.maxDelayMs, Math.floor(base + jitter));
|
|
157
|
-
}
|
|
158
|
-
async function defaultSleep(ms) {
|
|
159
|
-
if (ms <= 0) return;
|
|
160
|
-
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
//#endregion
|
|
164
|
-
export { createSnowflakeJwt as a, shouldRetry as i, computeBackoffMs as n, defaultSleep as r, DEFAULT_RETRY_POLICY as t };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
//#region src/retry.d.ts
|
|
2
|
-
interface RetryPolicy {
|
|
3
|
-
readonly maxRetries: number;
|
|
4
|
-
readonly baseDelayMs: number;
|
|
5
|
-
readonly maxDelayMs: number;
|
|
6
|
-
/** Adds up to `jitterMs` random ms on top of each backoff. */
|
|
7
|
-
readonly jitterMs: number;
|
|
8
|
-
}
|
|
9
|
-
//#endregion
|
|
10
|
-
export { RetryPolicy as t };
|