windmill-client 1.615.3 → 1.615.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,75 +0,0 @@
1
- type ResultCollection = "last_statement_all_rows" | "last_statement_first_row" | "last_statement_all_rows_scalar" | "last_statement_first_row_scalar" | "all_statements_all_rows" | "all_statements_first_row" | "all_statements_all_rows_scalar" | "all_statements_first_row_scalar" | "legacy";
2
- type FetchParams<ResultCollectionT extends ResultCollection> = {
3
- resultCollection?: ResultCollectionT;
4
- };
5
- type SqlResult<T, ResultCollectionT extends ResultCollection> = ResultCollectionT extends "last_statement_first_row" ? T | null : ResultCollectionT extends "all_statements_first_row" ? T[] : ResultCollectionT extends "last_statement_all_rows" ? T[] : ResultCollectionT extends "all_statements_all_rows" ? T[][] : ResultCollectionT extends "last_statement_all_rows_scalar" ? T[keyof T][] : ResultCollectionT extends "all_statements_all_rows_scalar" ? T[keyof T][][] : ResultCollectionT extends "last_statement_first_row_scalar" ? T[keyof T] | null : ResultCollectionT extends "all_statements_first_row_scalar" ? T[keyof T][] : unknown;
6
- /**
7
- * SQL statement object with query content, arguments, and execution methods
8
- */
9
- export type SqlStatement<T> = {
10
- /** Raw SQL content with formatted arguments */
11
- content: string;
12
- /** Argument values keyed by parameter name */
13
- args: Record<string, any>;
14
- /**
15
- * Execute the SQL query and return results
16
- * @param params - Optional parameters including result collection mode
17
- * @returns Query results based on the result collection mode
18
- */
19
- fetch<ResultCollectionT extends ResultCollection = "last_statement_all_rows">(params?: FetchParams<ResultCollectionT | ResultCollection>): Promise<SqlResult<T, ResultCollectionT>>;
20
- /**
21
- * Execute the SQL query and return only the first row
22
- * @param params - Optional parameters
23
- * @returns First row of the query result
24
- */
25
- fetchOne(params?: Omit<FetchParams<"last_statement_first_row">, "resultCollection">): Promise<SqlResult<T, "last_statement_first_row">>;
26
- /**
27
- * Execute the SQL query and return only the first row as a scalar value
28
- * @param params - Optional parameters
29
- * @returns First row of the query result
30
- */
31
- fetchOneScalar(params?: Omit<FetchParams<"last_statement_first_row_scalar">, "resultCollection">): Promise<SqlResult<T, "last_statement_first_row_scalar">>;
32
- /**
33
- * Execute the SQL query without fetching rows
34
- * @param params - Optional parameters
35
- */
36
- execute(params?: Omit<FetchParams<"last_statement_first_row">, "resultCollection">): Promise<void>;
37
- };
38
- /**
39
- * Template tag function for creating SQL statements with parameterized values
40
- */
41
- export interface SqlTemplateFunction {
42
- <T = any>(strings: TemplateStringsArray, ...values: any[]): SqlStatement<T>;
43
- }
44
- export interface DatatableSqlTemplateFunction extends SqlTemplateFunction {
45
- query<T = any>(sql: string, ...params: any[]): SqlStatement<T>;
46
- }
47
- /**
48
- * Create a SQL template function for PostgreSQL/datatable queries
49
- * @param name - Database/datatable name (default: "main")
50
- * @returns SQL template function for building parameterized queries
51
- * @example
52
- * let sql = wmill.datatable()
53
- * let name = 'Robin'
54
- * let age = 21
55
- * await sql`
56
- * SELECT * FROM friends
57
- * WHERE name = ${name} AND age = ${age}::int
58
- * `.fetch()
59
- */
60
- export declare function datatable(name?: string): DatatableSqlTemplateFunction;
61
- /**
62
- * Create a SQL template function for DuckDB/ducklake queries
63
- * @param name - DuckDB database name (default: "main")
64
- * @returns SQL template function for building parameterized queries
65
- * @example
66
- * let sql = wmill.ducklake()
67
- * let name = 'Robin'
68
- * let age = 21
69
- * await sql`
70
- * SELECT * FROM friends
71
- * WHERE name = ${name} AND age = ${age}
72
- * `.fetch()
73
- */
74
- export declare function ducklake(name?: string): SqlTemplateFunction;
75
- export {};
package/dist/sqlUtils.js DELETED
@@ -1,197 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.datatable = datatable;
13
- exports.ducklake = ducklake;
14
- const client_1 = require("./client");
15
- /**
16
- * Create a SQL template function for PostgreSQL/datatable queries
17
- * @param name - Database/datatable name (default: "main")
18
- * @returns SQL template function for building parameterized queries
19
- * @example
20
- * let sql = wmill.datatable()
21
- * let name = 'Robin'
22
- * let age = 21
23
- * await sql`
24
- * SELECT * FROM friends
25
- * WHERE name = ${name} AND age = ${age}::int
26
- * `.fetch()
27
- */
28
- function datatable(name = "main") {
29
- return sqlProviderImpl("datatable", parseName(name));
30
- }
31
- /**
32
- * Create a SQL template function for DuckDB/ducklake queries
33
- * @param name - DuckDB database name (default: "main")
34
- * @returns SQL template function for building parameterized queries
35
- * @example
36
- * let sql = wmill.ducklake()
37
- * let name = 'Robin'
38
- * let age = 21
39
- * await sql`
40
- * SELECT * FROM friends
41
- * WHERE name = ${name} AND age = ${age}
42
- * `.fetch()
43
- */
44
- function ducklake(name = "main") {
45
- return sqlProviderImpl("ducklake", { name });
46
- }
47
- function sqlProviderImpl(provider, { name, schema }) {
48
- let sqlFn = (strings, ...values) => {
49
- let formatArgDecl = {
50
- datatable: (i) => `-- $${i + 1} arg${i + 1}`,
51
- ducklake: (i) => {
52
- let argType = parseTypeAnnotation(strings[i], strings[i + 1]) ||
53
- inferSqlType(values[i]);
54
- return `-- $arg${i + 1} (${argType})`;
55
- },
56
- }[provider];
57
- let formatArgUsage = {
58
- datatable: (i) => {
59
- const parsedType = parseTypeAnnotation(strings[i], strings[i + 1]);
60
- if (parsedType !== undefined)
61
- return `$${i + 1}`;
62
- let argType = inferSqlType(values[i]);
63
- return `$${i + 1}::${argType}`;
64
- },
65
- ducklake: (i) => `$arg${i + 1}`,
66
- }[provider];
67
- let content = values.map((_, i) => formatArgDecl(i)).join("\n") + "\n";
68
- if (provider === "ducklake")
69
- content += `ATTACH 'ducklake://${name}' AS dl;USE dl;\n`;
70
- if (schema && provider === "datatable") {
71
- content += `SET search_path TO "${schema}";\n`;
72
- }
73
- let contentBody = "";
74
- for (let i = 0; i < strings.length; i++) {
75
- contentBody += strings[i];
76
- if (i !== strings.length - 1)
77
- contentBody += formatArgUsage(i);
78
- }
79
- content += contentBody;
80
- const args = Object.assign(Object.assign({}, Object.fromEntries(values.map((v, i) => [`arg${i + 1}`, v]))), (provider === "datatable" ? { database: `datatable://${name}` } : {}));
81
- const language = {
82
- datatable: "postgresql",
83
- ducklake: "duckdb",
84
- }[provider];
85
- function fetch() {
86
- return __awaiter(this, arguments, void 0, function* ({ resultCollection, } = {}) {
87
- if (resultCollection)
88
- content = `-- result_collection=${resultCollection}\n${content}`;
89
- try {
90
- let result = yield client_1.JobService.runScriptPreviewInline({
91
- workspace: (0, client_1.getWorkspace)(),
92
- requestBody: { args, content, language },
93
- });
94
- return result;
95
- }
96
- catch (e) {
97
- let err = e;
98
- if (e &&
99
- typeof e.body == "string" &&
100
- e.statusText == "Internal Server Error") {
101
- let body = e.body;
102
- if (body.startsWith("Internal:"))
103
- body = body.slice(9).trim();
104
- if (body.startsWith("Error:"))
105
- body = body.slice(6).trim();
106
- if (body.startsWith("datatable"))
107
- body = body.slice(9).trim();
108
- err = Error(`${provider} ${body}`);
109
- err.query = contentBody;
110
- err.request = e.request;
111
- }
112
- throw err;
113
- }
114
- });
115
- }
116
- return {
117
- content,
118
- args,
119
- fetch,
120
- fetchOne: (params) => fetch(Object.assign(Object.assign({}, params), { resultCollection: "last_statement_first_row" })),
121
- fetchOneScalar: (params) => fetch(Object.assign(Object.assign({}, params), { resultCollection: "last_statement_first_row_scalar" })),
122
- execute: (params) => fetch(params),
123
- };
124
- };
125
- if (provider === "datatable") {
126
- sqlFn.query = (sqlString, ...params) => {
127
- // This is less than ideal, did that quickly for a client need.
128
- // TODO: break down the SqlTemplateFunction impl and reuse here properly.
129
- let arr = Object.assign([sqlString], { raw: [sqlString] });
130
- return sqlFn(arr, ...params);
131
- };
132
- }
133
- return sqlFn;
134
- }
135
- // DuckDB executor requires explicit argument types at declaration
136
- // And postgres at argument usage.
137
- // These types exist in both DuckDB and Postgres
138
- // Check that the types exist if you plan to extend this function for other SQL engines.
139
- function inferSqlType(value) {
140
- if (typeof value === "number" || typeof value === "bigint") {
141
- if (Number.isInteger(value))
142
- return "BIGINT";
143
- return "DOUBLE PRECISION";
144
- }
145
- else if (value === null || value === undefined) {
146
- return "TEXT";
147
- }
148
- else if (typeof value === "string") {
149
- return "TEXT";
150
- }
151
- else if (typeof value === "object") {
152
- return "JSON";
153
- }
154
- else if (typeof value === "boolean") {
155
- return "BOOLEAN";
156
- }
157
- else {
158
- return "TEXT";
159
- }
160
- }
161
- // The goal is to detect if the user added a type annotation manually
162
- //
163
- // untyped : sql`SELECT ${x} = 0` => ['SELECT ', ' = 0']
164
- // typed : sql`SELECT ${x}::int = 0` => ['SELECT ', '::int = 0']
165
- // typed : sql`SELECT CAST ( ${x} AS int ) = 0` => ['SELECT CAST ( ', ' AS int ) = 0']
166
- function parseTypeAnnotation(prevTemplateString, nextTemplateString) {
167
- if (!nextTemplateString)
168
- return;
169
- nextTemplateString = nextTemplateString.trimStart();
170
- if (nextTemplateString.startsWith("::")) {
171
- return nextTemplateString.substring(2).trimStart().split(/\s+/)[0];
172
- }
173
- prevTemplateString = prevTemplateString === null || prevTemplateString === void 0 ? void 0 : prevTemplateString.trimEnd();
174
- if ((prevTemplateString === null || prevTemplateString === void 0 ? void 0 : prevTemplateString.endsWith("(")) &&
175
- prevTemplateString
176
- .substring(0, prevTemplateString.length - 1)
177
- .trim()
178
- .toUpperCase()
179
- .endsWith("CAST") &&
180
- nextTemplateString.toUpperCase().startsWith("AS ")) {
181
- return nextTemplateString.substring(2).trimStart().split(/\s+/)[0];
182
- }
183
- }
184
- function parseName(name) {
185
- if (!name)
186
- return { name: "main" };
187
- let [assetName, schemaName] = name.split(":");
188
- if (schemaName) {
189
- return {
190
- name: assetName || "main",
191
- schema: schemaName,
192
- };
193
- }
194
- else {
195
- return { name };
196
- }
197
- }