windmill-client 1.672.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.
@@ -2608,6 +2608,21 @@ var SettingService = class {
2608
2608
  });
2609
2609
  }
2610
2610
  /**
2611
+ * restart worker group
2612
+ * Send a restart signal to all workers in the specified worker group. Workers will gracefully shut down and are expected to be restarted by their supervisor. Requires devops role.
2613
+ * @param data The data for the request.
2614
+ * @param data.workerGroup the name of the worker group to restart
2615
+ * @returns string restart signal sent
2616
+ * @throws ApiError
2617
+ */
2618
+ static restartWorkerGroup(data) {
2619
+ return request(OpenAPI, {
2620
+ method: "POST",
2621
+ url: "/settings/restart_worker_group/{worker_group}",
2622
+ path: { worker_group: data.workerGroup }
2623
+ });
2624
+ }
2625
+ /**
2611
2626
  * get telemetry stats with HMAC signature (EE only)
2612
2627
  * @returns unknown telemetry stats JSON with signature
2613
2628
  * @throws ApiError
@@ -2777,6 +2792,51 @@ var SettingService = class {
2777
2792
  });
2778
2793
  }
2779
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
+ /**
2780
2840
  * get secondary storage names
2781
2841
  * @param data The data for the request.
2782
2842
  * @param data.workspace
@@ -3088,6 +3148,7 @@ var VariableService = class {
3088
3148
  * @param data.broadFilter broad search across multiple fields (case-insensitive substring match)
3089
3149
  * @param data.page which page to return (start at 1, default 1)
3090
3150
  * @param data.perPage number of items to return for a given page (default 30, max 100)
3151
+ * @param data.label Filter by label
3091
3152
  * @returns ListableVariable variable list
3092
3153
  * @throws ApiError
3093
3154
  */
@@ -3103,7 +3164,8 @@ var VariableService = class {
3103
3164
  value: data.value,
3104
3165
  broad_filter: data.broadFilter,
3105
3166
  page: data.page,
3106
- per_page: data.perPage
3167
+ per_page: data.perPage,
3168
+ label: data.label
3107
3169
  }
3108
3170
  });
3109
3171
  }
@@ -3536,6 +3598,7 @@ var ResourceService = class {
3536
3598
  * @param data.description pattern match filter for description field (case-insensitive)
3537
3599
  * @param data.value JSONB subset match filter using base64 encoded JSON
3538
3600
  * @param data.broadFilter broad search across multiple fields (case-insensitive substring match)
3601
+ * @param data.label Filter by label
3539
3602
  * @returns ListableResource resource list
3540
3603
  * @throws ApiError
3541
3604
  */
@@ -3553,7 +3616,8 @@ var ResourceService = class {
3553
3616
  path: data.path,
3554
3617
  description: data.description,
3555
3618
  value: data.value,
3556
- broad_filter: data.broadFilter
3619
+ broad_filter: data.broadFilter,
3620
+ label: data.label
3557
3621
  }
3558
3622
  });
3559
3623
  }
@@ -3945,6 +4009,7 @@ var FlowService = class {
3945
4009
  * If true, show only flows with dedicated_worker enabled.
3946
4010
  * If false, show only flows with dedicated_worker disabled.
3947
4011
  *
4012
+ * @param data.label Filter by label
3948
4013
  * @returns unknown All flow
3949
4014
  * @throws ApiError
3950
4015
  */
@@ -3965,7 +4030,8 @@ var FlowService = class {
3965
4030
  include_draft_only: data.includeDraftOnly,
3966
4031
  with_deployment_msg: data.withDeploymentMsg,
3967
4032
  without_description: data.withoutDescription,
3968
- dedicated_worker: data.dedicatedWorker
4033
+ dedicated_worker: data.dedicatedWorker,
4034
+ label: data.label
3969
4035
  }
3970
4036
  });
3971
4037
  }
@@ -4382,6 +4448,7 @@ var AppService = class {
4382
4448
  * @param data.withDeploymentMsg (default false)
4383
4449
  * include deployment message
4384
4450
  *
4451
+ * @param data.label Filter by label
4385
4452
  * @returns ListableApp All apps
4386
4453
  * @throws ApiError
4387
4454
  */
@@ -4399,7 +4466,8 @@ var AppService = class {
4399
4466
  path_exact: data.pathExact,
4400
4467
  starred_only: data.starredOnly,
4401
4468
  include_draft_only: data.includeDraftOnly,
4402
- with_deployment_msg: data.withDeploymentMsg
4469
+ with_deployment_msg: data.withDeploymentMsg,
4470
+ label: data.label
4403
4471
  }
4404
4472
  });
4405
4473
  }
@@ -5006,6 +5074,7 @@ var ScriptService = class {
5006
5074
  * If true, show only scripts with dedicated_worker enabled.
5007
5075
  * If false, show only scripts with dedicated_worker disabled.
5008
5076
  *
5077
+ * @param data.label Filter by label
5009
5078
  * @returns Script All scripts
5010
5079
  * @throws ApiError
5011
5080
  */
@@ -5033,7 +5102,8 @@ var ScriptService = class {
5033
5102
  with_deployment_msg: data.withDeploymentMsg,
5034
5103
  languages: data.languages,
5035
5104
  without_description: data.withoutDescription,
5036
- dedicated_worker: data.dedicatedWorker
5105
+ dedicated_worker: data.dedicatedWorker,
5106
+ label: data.label
5037
5107
  }
5038
5108
  });
5039
5109
  }
@@ -8238,6 +8308,7 @@ var RawAppService = class {
8238
8308
  * @param data.starredOnly (default false)
8239
8309
  * show only the starred items
8240
8310
  *
8311
+ * @param data.label Filter by label
8241
8312
  * @returns ListableRawApp All raw apps
8242
8313
  * @throws ApiError
8243
8314
  */
@@ -8253,7 +8324,8 @@ var RawAppService = class {
8253
8324
  created_by: data.createdBy,
8254
8325
  path_start: data.pathStart,
8255
8326
  path_exact: data.pathExact,
8256
- starred_only: data.starredOnly
8327
+ starred_only: data.starredOnly,
8328
+ label: data.label
8257
8329
  }
8258
8330
  });
8259
8331
  }
@@ -8449,6 +8521,7 @@ var ScheduleService = class {
8449
8521
  * @param data.description pattern match filter for description field (case-insensitive)
8450
8522
  * @param data.summary pattern match filter for summary field (case-insensitive)
8451
8523
  * @param data.broadFilter broad search across multiple fields (case-insensitive substring match)
8524
+ * @param data.label Filter by label
8452
8525
  * @returns Schedule schedule list
8453
8526
  * @throws ApiError
8454
8527
  */
@@ -8467,7 +8540,8 @@ var ScheduleService = class {
8467
8540
  schedule_path: data.schedulePath,
8468
8541
  description: data.description,
8469
8542
  summary: data.summary,
8470
- broad_filter: data.broadFilter
8543
+ broad_filter: data.broadFilter,
8544
+ label: data.label
8471
8545
  }
8472
8546
  });
8473
8547
  }
@@ -8646,6 +8720,7 @@ var HttpTriggerService = class {
8646
8720
  * @param data.path filter by path
8647
8721
  * @param data.isFlow
8648
8722
  * @param data.pathStart
8723
+ * @param data.label Filter by label
8649
8724
  * @returns HttpTrigger http trigger list
8650
8725
  * @throws ApiError
8651
8726
  */
@@ -8659,7 +8734,8 @@ var HttpTriggerService = class {
8659
8734
  per_page: data.perPage,
8660
8735
  path: data.path,
8661
8736
  is_flow: data.isFlow,
8662
- path_start: data.pathStart
8737
+ path_start: data.pathStart,
8738
+ label: data.label
8663
8739
  }
8664
8740
  });
8665
8741
  }
@@ -8804,6 +8880,7 @@ var WebsocketTriggerService = class {
8804
8880
  * @param data.path filter by path
8805
8881
  * @param data.isFlow
8806
8882
  * @param data.pathStart
8883
+ * @param data.label Filter by label
8807
8884
  * @returns WebsocketTrigger websocket trigger list
8808
8885
  * @throws ApiError
8809
8886
  */
@@ -8817,7 +8894,8 @@ var WebsocketTriggerService = class {
8817
8894
  per_page: data.perPage,
8818
8895
  path: data.path,
8819
8896
  is_flow: data.isFlow,
8820
- path_start: data.pathStart
8897
+ path_start: data.pathStart,
8898
+ label: data.label
8821
8899
  }
8822
8900
  });
8823
8901
  }
@@ -8962,6 +9040,7 @@ var KafkaTriggerService = class {
8962
9040
  * @param data.path filter by path
8963
9041
  * @param data.isFlow
8964
9042
  * @param data.pathStart
9043
+ * @param data.label Filter by label
8965
9044
  * @returns KafkaTrigger kafka trigger list
8966
9045
  * @throws ApiError
8967
9046
  */
@@ -8975,7 +9054,8 @@ var KafkaTriggerService = class {
8975
9054
  per_page: data.perPage,
8976
9055
  path: data.path,
8977
9056
  is_flow: data.isFlow,
8978
- path_start: data.pathStart
9057
+ path_start: data.pathStart,
9058
+ label: data.label
8979
9059
  }
8980
9060
  });
8981
9061
  }
@@ -9159,6 +9239,7 @@ var NatsTriggerService = class {
9159
9239
  * @param data.path filter by path
9160
9240
  * @param data.isFlow
9161
9241
  * @param data.pathStart
9242
+ * @param data.label Filter by label
9162
9243
  * @returns NatsTrigger nats trigger list
9163
9244
  * @throws ApiError
9164
9245
  */
@@ -9172,7 +9253,8 @@ var NatsTriggerService = class {
9172
9253
  per_page: data.perPage,
9173
9254
  path: data.path,
9174
9255
  is_flow: data.isFlow,
9175
- path_start: data.pathStart
9256
+ path_start: data.pathStart,
9257
+ label: data.label
9176
9258
  }
9177
9259
  });
9178
9260
  }
@@ -9317,6 +9399,7 @@ var SqsTriggerService = class {
9317
9399
  * @param data.path filter by path
9318
9400
  * @param data.isFlow
9319
9401
  * @param data.pathStart
9402
+ * @param data.label Filter by label
9320
9403
  * @returns SqsTrigger sqs trigger list
9321
9404
  * @throws ApiError
9322
9405
  */
@@ -9330,7 +9413,8 @@ var SqsTriggerService = class {
9330
9413
  per_page: data.perPage,
9331
9414
  path: data.path,
9332
9415
  is_flow: data.isFlow,
9333
- path_start: data.pathStart
9416
+ path_start: data.pathStart,
9417
+ label: data.label
9334
9418
  }
9335
9419
  });
9336
9420
  }
@@ -9652,6 +9736,7 @@ var NativeTriggerService = class {
9652
9736
  * @param data.perPage number of items to return for a given page (default 30, max 100)
9653
9737
  * @param data.path filter by script path
9654
9738
  * @param data.isFlow filter by is_flow
9739
+ * @param data.label Filter by label
9655
9740
  * @returns NativeTrigger native triggers list
9656
9741
  * @throws ApiError
9657
9742
  */
@@ -9667,7 +9752,8 @@ var NativeTriggerService = class {
9667
9752
  page: data.page,
9668
9753
  per_page: data.perPage,
9669
9754
  path: data.path,
9670
- is_flow: data.isFlow
9755
+ is_flow: data.isFlow,
9756
+ label: data.label
9671
9757
  }
9672
9758
  });
9673
9759
  }
@@ -9884,6 +9970,7 @@ var MqttTriggerService = class {
9884
9970
  * @param data.path filter by path
9885
9971
  * @param data.isFlow
9886
9972
  * @param data.pathStart
9973
+ * @param data.label Filter by label
9887
9974
  * @returns MqttTrigger mqtt trigger list
9888
9975
  * @throws ApiError
9889
9976
  */
@@ -9897,7 +9984,8 @@ var MqttTriggerService = class {
9897
9984
  per_page: data.perPage,
9898
9985
  path: data.path,
9899
9986
  is_flow: data.isFlow,
9900
- path_start: data.pathStart
9987
+ path_start: data.pathStart,
9988
+ label: data.label
9901
9989
  }
9902
9990
  });
9903
9991
  }
@@ -10042,6 +10130,7 @@ var GcpTriggerService = class {
10042
10130
  * @param data.path filter by path
10043
10131
  * @param data.isFlow
10044
10132
  * @param data.pathStart
10133
+ * @param data.label Filter by label
10045
10134
  * @returns GcpTrigger gcp trigger list
10046
10135
  * @throws ApiError
10047
10136
  */
@@ -10055,7 +10144,8 @@ var GcpTriggerService = class {
10055
10144
  per_page: data.perPage,
10056
10145
  path: data.path,
10057
10146
  is_flow: data.isFlow,
10058
- path_start: data.pathStart
10147
+ path_start: data.pathStart,
10148
+ label: data.label
10059
10149
  }
10060
10150
  });
10061
10151
  }
@@ -10495,6 +10585,7 @@ var PostgresTriggerService = class {
10495
10585
  * @param data.path filter by path
10496
10586
  * @param data.isFlow
10497
10587
  * @param data.pathStart
10588
+ * @param data.label Filter by label
10498
10589
  * @returns PostgresTrigger postgres trigger list
10499
10590
  * @throws ApiError
10500
10591
  */
@@ -10508,7 +10599,8 @@ var PostgresTriggerService = class {
10508
10599
  per_page: data.perPage,
10509
10600
  path: data.path,
10510
10601
  is_flow: data.isFlow,
10511
- path_start: data.pathStart
10602
+ path_start: data.pathStart,
10603
+ label: data.label
10512
10604
  }
10513
10605
  });
10514
10606
  }
@@ -10653,6 +10745,7 @@ var EmailTriggerService = class {
10653
10745
  * @param data.path filter by path
10654
10746
  * @param data.isFlow
10655
10747
  * @param data.pathStart
10748
+ * @param data.label Filter by label
10656
10749
  * @returns EmailTrigger email trigger list
10657
10750
  * @throws ApiError
10658
10751
  */
@@ -10666,7 +10759,8 @@ var EmailTriggerService = class {
10666
10759
  per_page: data.perPage,
10667
10760
  path: data.path,
10668
10761
  is_flow: data.isFlow,
10669
- path_start: data.pathStart
10762
+ path_start: data.pathStart,
10763
+ label: data.label
10670
10764
  }
10671
10765
  });
10672
10766
  }
@@ -11372,6 +11466,28 @@ var ConfigService = class {
11372
11466
  url: "/configs/list_available_python_versions"
11373
11467
  });
11374
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
+ }
11375
11491
  };
11376
11492
  var AgentWorkersService = class {
11377
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";