windmill-client 1.673.0 → 1.674.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2792,6 +2792,51 @@ var SettingService = class {
2792
2792
  });
2793
2793
  }
2794
2794
  /**
2795
+ * test Azure Key Vault connection
2796
+ * @param data The data for the request.
2797
+ * @param data.requestBody Azure Key Vault settings to test
2798
+ * @returns string connection successful
2799
+ * @throws ApiError
2800
+ */
2801
+ static testAzureKvBackend(data) {
2802
+ return request(OpenAPI, {
2803
+ method: "POST",
2804
+ url: "/settings/test_azure_kv_backend",
2805
+ body: data.requestBody,
2806
+ mediaType: "application/json"
2807
+ });
2808
+ }
2809
+ /**
2810
+ * migrate secrets from database to Azure Key Vault
2811
+ * @param data The data for the request.
2812
+ * @param data.requestBody Azure Key Vault settings for migration target
2813
+ * @returns SecretMigrationReport migration report
2814
+ * @throws ApiError
2815
+ */
2816
+ static migrateSecretsToAzureKv(data) {
2817
+ return request(OpenAPI, {
2818
+ method: "POST",
2819
+ url: "/settings/migrate_secrets_to_azure_kv",
2820
+ body: data.requestBody,
2821
+ mediaType: "application/json"
2822
+ });
2823
+ }
2824
+ /**
2825
+ * migrate secrets from Azure Key Vault to database
2826
+ * @param data The data for the request.
2827
+ * @param data.requestBody Azure Key Vault settings for migration source
2828
+ * @returns SecretMigrationReport migration report
2829
+ * @throws ApiError
2830
+ */
2831
+ static migrateSecretsFromAzureKv(data) {
2832
+ return request(OpenAPI, {
2833
+ method: "POST",
2834
+ url: "/settings/migrate_secrets_from_azure_kv",
2835
+ body: data.requestBody,
2836
+ mediaType: "application/json"
2837
+ });
2838
+ }
2839
+ /**
2795
2840
  * get secondary storage names
2796
2841
  * @param data The data for the request.
2797
2842
  * @param data.workspace
@@ -3103,6 +3148,7 @@ var VariableService = class {
3103
3148
  * @param data.broadFilter broad search across multiple fields (case-insensitive substring match)
3104
3149
  * @param data.page which page to return (start at 1, default 1)
3105
3150
  * @param data.perPage number of items to return for a given page (default 30, max 100)
3151
+ * @param data.label Filter by label
3106
3152
  * @returns ListableVariable variable list
3107
3153
  * @throws ApiError
3108
3154
  */
@@ -3118,7 +3164,8 @@ var VariableService = class {
3118
3164
  value: data.value,
3119
3165
  broad_filter: data.broadFilter,
3120
3166
  page: data.page,
3121
- per_page: data.perPage
3167
+ per_page: data.perPage,
3168
+ label: data.label
3122
3169
  }
3123
3170
  });
3124
3171
  }
@@ -3551,6 +3598,7 @@ var ResourceService = class {
3551
3598
  * @param data.description pattern match filter for description field (case-insensitive)
3552
3599
  * @param data.value JSONB subset match filter using base64 encoded JSON
3553
3600
  * @param data.broadFilter broad search across multiple fields (case-insensitive substring match)
3601
+ * @param data.label Filter by label
3554
3602
  * @returns ListableResource resource list
3555
3603
  * @throws ApiError
3556
3604
  */
@@ -3568,7 +3616,8 @@ var ResourceService = class {
3568
3616
  path: data.path,
3569
3617
  description: data.description,
3570
3618
  value: data.value,
3571
- broad_filter: data.broadFilter
3619
+ broad_filter: data.broadFilter,
3620
+ label: data.label
3572
3621
  }
3573
3622
  });
3574
3623
  }
@@ -3960,6 +4009,7 @@ var FlowService = class {
3960
4009
  * If true, show only flows with dedicated_worker enabled.
3961
4010
  * If false, show only flows with dedicated_worker disabled.
3962
4011
  *
4012
+ * @param data.label Filter by label
3963
4013
  * @returns unknown All flow
3964
4014
  * @throws ApiError
3965
4015
  */
@@ -3980,7 +4030,8 @@ var FlowService = class {
3980
4030
  include_draft_only: data.includeDraftOnly,
3981
4031
  with_deployment_msg: data.withDeploymentMsg,
3982
4032
  without_description: data.withoutDescription,
3983
- dedicated_worker: data.dedicatedWorker
4033
+ dedicated_worker: data.dedicatedWorker,
4034
+ label: data.label
3984
4035
  }
3985
4036
  });
3986
4037
  }
@@ -4397,6 +4448,7 @@ var AppService = class {
4397
4448
  * @param data.withDeploymentMsg (default false)
4398
4449
  * include deployment message
4399
4450
  *
4451
+ * @param data.label Filter by label
4400
4452
  * @returns ListableApp All apps
4401
4453
  * @throws ApiError
4402
4454
  */
@@ -4414,7 +4466,8 @@ var AppService = class {
4414
4466
  path_exact: data.pathExact,
4415
4467
  starred_only: data.starredOnly,
4416
4468
  include_draft_only: data.includeDraftOnly,
4417
- with_deployment_msg: data.withDeploymentMsg
4469
+ with_deployment_msg: data.withDeploymentMsg,
4470
+ label: data.label
4418
4471
  }
4419
4472
  });
4420
4473
  }
@@ -5021,6 +5074,7 @@ var ScriptService = class {
5021
5074
  * If true, show only scripts with dedicated_worker enabled.
5022
5075
  * If false, show only scripts with dedicated_worker disabled.
5023
5076
  *
5077
+ * @param data.label Filter by label
5024
5078
  * @returns Script All scripts
5025
5079
  * @throws ApiError
5026
5080
  */
@@ -5048,7 +5102,8 @@ var ScriptService = class {
5048
5102
  with_deployment_msg: data.withDeploymentMsg,
5049
5103
  languages: data.languages,
5050
5104
  without_description: data.withoutDescription,
5051
- dedicated_worker: data.dedicatedWorker
5105
+ dedicated_worker: data.dedicatedWorker,
5106
+ label: data.label
5052
5107
  }
5053
5108
  });
5054
5109
  }
@@ -8253,6 +8308,7 @@ var RawAppService = class {
8253
8308
  * @param data.starredOnly (default false)
8254
8309
  * show only the starred items
8255
8310
  *
8311
+ * @param data.label Filter by label
8256
8312
  * @returns ListableRawApp All raw apps
8257
8313
  * @throws ApiError
8258
8314
  */
@@ -8268,7 +8324,8 @@ var RawAppService = class {
8268
8324
  created_by: data.createdBy,
8269
8325
  path_start: data.pathStart,
8270
8326
  path_exact: data.pathExact,
8271
- starred_only: data.starredOnly
8327
+ starred_only: data.starredOnly,
8328
+ label: data.label
8272
8329
  }
8273
8330
  });
8274
8331
  }
@@ -8464,6 +8521,7 @@ var ScheduleService = class {
8464
8521
  * @param data.description pattern match filter for description field (case-insensitive)
8465
8522
  * @param data.summary pattern match filter for summary field (case-insensitive)
8466
8523
  * @param data.broadFilter broad search across multiple fields (case-insensitive substring match)
8524
+ * @param data.label Filter by label
8467
8525
  * @returns Schedule schedule list
8468
8526
  * @throws ApiError
8469
8527
  */
@@ -8482,7 +8540,8 @@ var ScheduleService = class {
8482
8540
  schedule_path: data.schedulePath,
8483
8541
  description: data.description,
8484
8542
  summary: data.summary,
8485
- broad_filter: data.broadFilter
8543
+ broad_filter: data.broadFilter,
8544
+ label: data.label
8486
8545
  }
8487
8546
  });
8488
8547
  }
@@ -8661,6 +8720,7 @@ var HttpTriggerService = class {
8661
8720
  * @param data.path filter by path
8662
8721
  * @param data.isFlow
8663
8722
  * @param data.pathStart
8723
+ * @param data.label Filter by label
8664
8724
  * @returns HttpTrigger http trigger list
8665
8725
  * @throws ApiError
8666
8726
  */
@@ -8674,7 +8734,8 @@ var HttpTriggerService = class {
8674
8734
  per_page: data.perPage,
8675
8735
  path: data.path,
8676
8736
  is_flow: data.isFlow,
8677
- path_start: data.pathStart
8737
+ path_start: data.pathStart,
8738
+ label: data.label
8678
8739
  }
8679
8740
  });
8680
8741
  }
@@ -8819,6 +8880,7 @@ var WebsocketTriggerService = class {
8819
8880
  * @param data.path filter by path
8820
8881
  * @param data.isFlow
8821
8882
  * @param data.pathStart
8883
+ * @param data.label Filter by label
8822
8884
  * @returns WebsocketTrigger websocket trigger list
8823
8885
  * @throws ApiError
8824
8886
  */
@@ -8832,7 +8894,8 @@ var WebsocketTriggerService = class {
8832
8894
  per_page: data.perPage,
8833
8895
  path: data.path,
8834
8896
  is_flow: data.isFlow,
8835
- path_start: data.pathStart
8897
+ path_start: data.pathStart,
8898
+ label: data.label
8836
8899
  }
8837
8900
  });
8838
8901
  }
@@ -8977,6 +9040,7 @@ var KafkaTriggerService = class {
8977
9040
  * @param data.path filter by path
8978
9041
  * @param data.isFlow
8979
9042
  * @param data.pathStart
9043
+ * @param data.label Filter by label
8980
9044
  * @returns KafkaTrigger kafka trigger list
8981
9045
  * @throws ApiError
8982
9046
  */
@@ -8990,7 +9054,8 @@ var KafkaTriggerService = class {
8990
9054
  per_page: data.perPage,
8991
9055
  path: data.path,
8992
9056
  is_flow: data.isFlow,
8993
- path_start: data.pathStart
9057
+ path_start: data.pathStart,
9058
+ label: data.label
8994
9059
  }
8995
9060
  });
8996
9061
  }
@@ -9174,6 +9239,7 @@ var NatsTriggerService = class {
9174
9239
  * @param data.path filter by path
9175
9240
  * @param data.isFlow
9176
9241
  * @param data.pathStart
9242
+ * @param data.label Filter by label
9177
9243
  * @returns NatsTrigger nats trigger list
9178
9244
  * @throws ApiError
9179
9245
  */
@@ -9187,7 +9253,8 @@ var NatsTriggerService = class {
9187
9253
  per_page: data.perPage,
9188
9254
  path: data.path,
9189
9255
  is_flow: data.isFlow,
9190
- path_start: data.pathStart
9256
+ path_start: data.pathStart,
9257
+ label: data.label
9191
9258
  }
9192
9259
  });
9193
9260
  }
@@ -9332,6 +9399,7 @@ var SqsTriggerService = class {
9332
9399
  * @param data.path filter by path
9333
9400
  * @param data.isFlow
9334
9401
  * @param data.pathStart
9402
+ * @param data.label Filter by label
9335
9403
  * @returns SqsTrigger sqs trigger list
9336
9404
  * @throws ApiError
9337
9405
  */
@@ -9345,7 +9413,8 @@ var SqsTriggerService = class {
9345
9413
  per_page: data.perPage,
9346
9414
  path: data.path,
9347
9415
  is_flow: data.isFlow,
9348
- path_start: data.pathStart
9416
+ path_start: data.pathStart,
9417
+ label: data.label
9349
9418
  }
9350
9419
  });
9351
9420
  }
@@ -9667,6 +9736,7 @@ var NativeTriggerService = class {
9667
9736
  * @param data.perPage number of items to return for a given page (default 30, max 100)
9668
9737
  * @param data.path filter by script path
9669
9738
  * @param data.isFlow filter by is_flow
9739
+ * @param data.label Filter by label
9670
9740
  * @returns NativeTrigger native triggers list
9671
9741
  * @throws ApiError
9672
9742
  */
@@ -9682,7 +9752,8 @@ var NativeTriggerService = class {
9682
9752
  page: data.page,
9683
9753
  per_page: data.perPage,
9684
9754
  path: data.path,
9685
- is_flow: data.isFlow
9755
+ is_flow: data.isFlow,
9756
+ label: data.label
9686
9757
  }
9687
9758
  });
9688
9759
  }
@@ -9899,6 +9970,7 @@ var MqttTriggerService = class {
9899
9970
  * @param data.path filter by path
9900
9971
  * @param data.isFlow
9901
9972
  * @param data.pathStart
9973
+ * @param data.label Filter by label
9902
9974
  * @returns MqttTrigger mqtt trigger list
9903
9975
  * @throws ApiError
9904
9976
  */
@@ -9912,7 +9984,8 @@ var MqttTriggerService = class {
9912
9984
  per_page: data.perPage,
9913
9985
  path: data.path,
9914
9986
  is_flow: data.isFlow,
9915
- path_start: data.pathStart
9987
+ path_start: data.pathStart,
9988
+ label: data.label
9916
9989
  }
9917
9990
  });
9918
9991
  }
@@ -10057,6 +10130,7 @@ var GcpTriggerService = class {
10057
10130
  * @param data.path filter by path
10058
10131
  * @param data.isFlow
10059
10132
  * @param data.pathStart
10133
+ * @param data.label Filter by label
10060
10134
  * @returns GcpTrigger gcp trigger list
10061
10135
  * @throws ApiError
10062
10136
  */
@@ -10070,7 +10144,8 @@ var GcpTriggerService = class {
10070
10144
  per_page: data.perPage,
10071
10145
  path: data.path,
10072
10146
  is_flow: data.isFlow,
10073
- path_start: data.pathStart
10147
+ path_start: data.pathStart,
10148
+ label: data.label
10074
10149
  }
10075
10150
  });
10076
10151
  }
@@ -10510,6 +10585,7 @@ var PostgresTriggerService = class {
10510
10585
  * @param data.path filter by path
10511
10586
  * @param data.isFlow
10512
10587
  * @param data.pathStart
10588
+ * @param data.label Filter by label
10513
10589
  * @returns PostgresTrigger postgres trigger list
10514
10590
  * @throws ApiError
10515
10591
  */
@@ -10523,7 +10599,8 @@ var PostgresTriggerService = class {
10523
10599
  per_page: data.perPage,
10524
10600
  path: data.path,
10525
10601
  is_flow: data.isFlow,
10526
- path_start: data.pathStart
10602
+ path_start: data.pathStart,
10603
+ label: data.label
10527
10604
  }
10528
10605
  });
10529
10606
  }
@@ -10668,6 +10745,7 @@ var EmailTriggerService = class {
10668
10745
  * @param data.path filter by path
10669
10746
  * @param data.isFlow
10670
10747
  * @param data.pathStart
10748
+ * @param data.label Filter by label
10671
10749
  * @returns EmailTrigger email trigger list
10672
10750
  * @throws ApiError
10673
10751
  */
@@ -10681,7 +10759,8 @@ var EmailTriggerService = class {
10681
10759
  per_page: data.perPage,
10682
10760
  path: data.path,
10683
10761
  is_flow: data.isFlow,
10684
- path_start: data.pathStart
10762
+ path_start: data.pathStart,
10763
+ label: data.label
10685
10764
  }
10686
10765
  });
10687
10766
  }
@@ -11387,6 +11466,28 @@ var ConfigService = class {
11387
11466
  url: "/configs/list_available_python_versions"
11388
11467
  });
11389
11468
  }
11469
+ /**
11470
+ * list all workspace dependencies
11471
+ * @returns unknown a list of workspace dependency summaries
11472
+ * @throws ApiError
11473
+ */
11474
+ static listAllWorkspaceDependencies() {
11475
+ return request(OpenAPI, {
11476
+ method: "GET",
11477
+ url: "/configs/list_all_workspace_dependencies"
11478
+ });
11479
+ }
11480
+ /**
11481
+ * list all dedicated scripts with their dependencies
11482
+ * @returns unknown a list of dedicated scripts with workspace dependencies
11483
+ * @throws ApiError
11484
+ */
11485
+ static listAllDedicatedWithDeps() {
11486
+ return request(OpenAPI, {
11487
+ method: "GET",
11488
+ url: "/configs/list_all_dedicated_with_deps"
11489
+ });
11490
+ }
11390
11491
  };
11391
11492
  var AgentWorkersService = class {
11392
11493
  /**
@@ -35,11 +35,22 @@ export type SqlStatement<T> = {
35
35
  */
36
36
  execute(params?: Omit<FetchParams<"last_statement_first_row">, "resultCollection">): Promise<void>;
37
37
  };
38
+ /**
39
+ * Wrapper for raw SQL fragments that should be inlined without parameterization.
40
+ * Created via `sql.raw(value)`.
41
+ */
42
+ export declare class RawSql {
43
+ readonly value: string;
44
+ readonly __brand: "RawSql";
45
+ constructor(value: string);
46
+ }
38
47
  /**
39
48
  * Template tag function for creating SQL statements with parameterized values
40
49
  */
41
50
  export interface SqlTemplateFunction {
42
51
  <T = any>(strings: TemplateStringsArray, ...values: any[]): SqlStatement<T>;
52
+ /** Create a raw SQL fragment that will be inlined without parameterization */
53
+ raw(value: string): RawSql;
43
54
  }
44
55
  export interface DatatableSqlTemplateFunction extends SqlTemplateFunction {
45
56
  query<T = any>(sql: string, ...params: any[]): SqlStatement<T>;
package/dist/sqlUtils.mjs CHANGED
@@ -1,83 +1,96 @@
1
1
  import { JobService } from "./services.gen.mjs";
2
- import { getWorkspace } from "./client.mjs";
2
+ import { getWorkspace, workerHasInternalServer } from "./client.mjs";
3
3
 
4
4
  //#region src/sqlUtils.ts
5
5
  /**
6
- * Create a SQL template function for PostgreSQL/datatable queries
7
- * @param name - Database/datatable name (default: "main")
8
- * @returns SQL template function for building parameterized queries
9
- * @example
10
- * let sql = wmill.datatable()
11
- * let name = 'Robin'
12
- * let age = 21
13
- * await sql`
14
- * SELECT * FROM friends
15
- * WHERE name = ${name} AND age = ${age}::int
16
- * `.fetch()
6
+ * Wrapper for raw SQL fragments that should be inlined without parameterization.
7
+ * Created via `sql.raw(value)`.
17
8
  */
18
- function datatable(name = "main") {
19
- return sqlProviderImpl("datatable", parseName(name));
9
+ var RawSql = class {
10
+ __brand = "RawSql";
11
+ constructor(value) {
12
+ this.value = value;
13
+ }
14
+ };
15
+ function datatableProvider(name, schema) {
16
+ return {
17
+ providerName: "datatable",
18
+ language: "postgresql",
19
+ extraArgs: { database: `datatable://${name}` },
20
+ formatArgDecl: (argNum) => `-- $${argNum} arg${argNum}`,
21
+ formatArgUsage: (argNum, explicitType, inferredType) => explicitType !== void 0 ? `$${argNum}` : `$${argNum}::${inferredType}`,
22
+ preamble: () => schema ? `SET search_path TO "${schema}";\n` : ""
23
+ };
20
24
  }
21
- /**
22
- * Create a SQL template function for DuckDB/ducklake queries
23
- * @param name - DuckDB database name (default: "main")
24
- * @returns SQL template function for building parameterized queries
25
- * @example
26
- * let sql = wmill.ducklake()
27
- * let name = 'Robin'
28
- * let age = 21
29
- * await sql`
30
- * SELECT * FROM friends
31
- * WHERE name = ${name} AND age = ${age}
32
- * `.fetch()
33
- */
34
- function ducklake(name = "main") {
35
- return sqlProviderImpl("ducklake", { name });
25
+ function ducklakeProvider(name) {
26
+ return {
27
+ providerName: "ducklake",
28
+ language: "duckdb",
29
+ extraArgs: {},
30
+ formatArgDecl: (argNum, argType) => `-- $arg${argNum} (${argType})`,
31
+ formatArgUsage: (argNum) => `$arg${argNum}`,
32
+ preamble: () => `ATTACH 'ducklake://${name}' AS dl;USE dl;\n`
33
+ };
36
34
  }
37
- function sqlProviderImpl(provider, { name, schema }) {
35
+ function buildSqlTemplateFunction(provider) {
38
36
  let sqlFn = (strings, ...values) => {
39
- let formatArgDecl = {
40
- datatable: (i) => `-- $${i + 1} arg${i + 1}`,
41
- ducklake: (i) => {
42
- let argType = parseTypeAnnotation(strings[i], strings[i + 1]) || inferSqlType(values[i]);
43
- return `-- $arg${i + 1} (${argType})`;
44
- }
45
- }[provider];
46
- let formatArgUsage = {
47
- datatable: (i) => {
48
- const parsedType = parseTypeAnnotation(strings[i], strings[i + 1]);
49
- if (parsedType !== void 0) return `$${i + 1}`;
50
- let argType = inferSqlType(values[i]);
51
- return `$${i + 1}::${argType}`;
52
- },
53
- ducklake: (i) => `$arg${i + 1}`
54
- }[provider];
55
- let content = values.map((_, i) => formatArgDecl(i)).join("\n") + "\n";
56
- if (provider === "ducklake") content += `ATTACH 'ducklake://${name}' AS dl;USE dl;\n`;
57
- if (schema && provider === "datatable") content += `SET search_path TO "${schema}";\n`;
37
+ let argIndex = 0;
38
+ const valueInfos = values.map((v, i) => {
39
+ if (v instanceof RawSql) return {
40
+ raw: true,
41
+ value: v.value,
42
+ originalIndex: i
43
+ };
44
+ argIndex++;
45
+ return {
46
+ raw: false,
47
+ value: v,
48
+ originalIndex: i,
49
+ argNum: argIndex
50
+ };
51
+ });
52
+ let argDecls = valueInfos.filter((info) => !info.raw).map((info) => {
53
+ let argType = parseTypeAnnotation(strings[info.originalIndex], strings[info.originalIndex + 1]) || inferSqlType(info.value);
54
+ return provider.formatArgDecl(info.argNum, argType);
55
+ });
56
+ let content = argDecls.length ? argDecls.join("\n") + "\n" : "";
57
+ content += provider.preamble();
58
58
  let contentBody = "";
59
59
  for (let i = 0; i < strings.length; i++) {
60
60
  contentBody += strings[i];
61
- if (i !== strings.length - 1) contentBody += formatArgUsage(i);
61
+ if (i < valueInfos.length) {
62
+ let info = valueInfos[i];
63
+ if (info.raw) contentBody += info.value;
64
+ else {
65
+ let explicitType = parseTypeAnnotation(strings[info.originalIndex], strings[info.originalIndex + 1]);
66
+ let inferredType = inferSqlType(info.value);
67
+ contentBody += provider.formatArgUsage(info.argNum, explicitType, inferredType);
68
+ }
69
+ }
62
70
  }
63
71
  content += contentBody;
64
72
  const args = {
65
- ...Object.fromEntries(values.map((v, i) => [`arg${i + 1}`, v])),
66
- ...provider === "datatable" ? { database: `datatable://${name}` } : {}
73
+ ...Object.fromEntries(valueInfos.filter((info) => !info.raw).map((info) => [`arg${info.argNum}`, info.value])),
74
+ ...provider.extraArgs
67
75
  };
68
- const language = {
69
- datatable: "postgresql",
70
- ducklake: "duckdb"
71
- }[provider];
72
76
  async function fetch({ resultCollection } = {}) {
73
77
  if (resultCollection) content = `-- result_collection=${resultCollection}\n${content}`;
74
78
  try {
75
- let result = await JobService.runScriptPreviewInline({
79
+ let result;
80
+ if (workerHasInternalServer()) result = await JobService.runScriptPreviewInline({
81
+ workspace: getWorkspace(),
82
+ requestBody: {
83
+ args,
84
+ content,
85
+ language: provider.language
86
+ }
87
+ });
88
+ else result = await JobService.runScriptPreviewAndWaitResult({
76
89
  workspace: getWorkspace(),
77
90
  requestBody: {
78
91
  args,
79
92
  content,
80
- language
93
+ language: provider.language
81
94
  }
82
95
  });
83
96
  return result;
@@ -88,7 +101,7 @@ function sqlProviderImpl(provider, { name, schema }) {
88
101
  if (body.startsWith("Internal:")) body = body.slice(9).trim();
89
102
  if (body.startsWith("Error:")) body = body.slice(6).trim();
90
103
  if (body.startsWith("datatable")) body = body.slice(9).trim();
91
- err = Error(`${provider} ${body}`);
104
+ err = Error(`${provider.providerName} ${body}`);
92
105
  err.query = contentBody;
93
106
  err.request = e.request;
94
107
  }
@@ -110,12 +123,47 @@ function sqlProviderImpl(provider, { name, schema }) {
110
123
  execute: (params) => fetch(params)
111
124
  };
112
125
  };
113
- if (provider === "datatable") sqlFn.query = (sqlString, ...params) => {
126
+ sqlFn.raw = (value) => new RawSql(value);
127
+ return sqlFn;
128
+ }
129
+ /**
130
+ * Create a SQL template function for PostgreSQL/datatable queries
131
+ * @param name - Database/datatable name (default: "main")
132
+ * @returns SQL template function for building parameterized queries
133
+ * @example
134
+ * let sql = wmill.datatable()
135
+ * let name = 'Robin'
136
+ * let age = 21
137
+ * await sql`
138
+ * SELECT * FROM friends
139
+ * WHERE name = ${name} AND age = ${age}::int
140
+ * `.fetch()
141
+ */
142
+ function datatable(name = "main") {
143
+ let { name: n, schema } = parseName(name);
144
+ let sqlFn = buildSqlTemplateFunction(datatableProvider(n, schema));
145
+ sqlFn.query = (sqlString, ...params) => {
114
146
  let arr = Object.assign([sqlString], { raw: [sqlString] });
115
147
  return sqlFn(arr, ...params);
116
148
  };
117
149
  return sqlFn;
118
150
  }
151
+ /**
152
+ * Create a SQL template function for DuckDB/ducklake queries
153
+ * @param name - DuckDB database name (default: "main")
154
+ * @returns SQL template function for building parameterized queries
155
+ * @example
156
+ * let sql = wmill.ducklake()
157
+ * let name = 'Robin'
158
+ * let age = 21
159
+ * await sql`
160
+ * SELECT * FROM friends
161
+ * WHERE name = ${name} AND age = ${age}
162
+ * `.fetch()
163
+ */
164
+ function ducklake(name = "main") {
165
+ return buildSqlTemplateFunction(ducklakeProvider(name));
166
+ }
119
167
  function inferSqlType(value) {
120
168
  if (typeof value === "number" || typeof value === "bigint") {
121
169
  if (Number.isInteger(value)) return "BIGINT";