windmill-client 1.733.1 → 1.735.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.
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DenoS3LightClientSettings, S3ObjectRecord, type S3Object } from "./s3Types";
2
2
  export { type S3Object, type S3ObjectRecord, type S3ObjectURI, } from "./s3Types";
3
- export { datatable, ducklake, type SqlTemplateFunction, type DatatableSqlTemplateFunction, } from "./sqlUtils";
3
+ export { datatable, ducklake, upsertPartition, appendPartition, type SqlTemplateFunction, type DatatableSqlTemplateFunction, type DucklakeMaterializeOptions, type SqlStatement, } from "./sqlUtils";
4
4
  export type Sql = string;
5
5
  export type Email = string;
6
6
  export type Base64 = string;
@@ -13,6 +13,7 @@ export declare function workerHasInternalServer(): boolean;
13
13
  * @param baseUrl - API base URL (defaults to BASE_INTERNAL_URL or BASE_URL env variable)
14
14
  */
15
15
  export declare function setClient(token?: string, baseUrl?: string): void;
16
+ export declare const getEnv: (key: string) => string | undefined;
16
17
  /**
17
18
  * Create a client configuration from env variables
18
19
  * @returns client configuration
package/dist/client.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { OpenAPI } from "./core/OpenAPI.mjs";
2
2
  import { AppService, HelpersService, JobService, KafkaTriggerService, MetricsService, OidcService, ResourceService, UserService, VariableService } from "./services.gen.mjs";
3
- import { datatable, ducklake } from "./sqlUtils.mjs";
3
+ import { appendPartition, datatable, ducklake, upsertPartition } from "./sqlUtils.mjs";
4
4
 
5
5
  //#region src/client.ts
6
6
  const SHARED_FOLDER = "/shared";
@@ -1346,4 +1346,4 @@ async function commitKafkaOffsets(triggerPath, topic, partition, offset) {
1346
1346
  }
1347
1347
 
1348
1348
  //#endregion
1349
- export { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, commitKafkaOffsets, databaseUrlFromResource, deleteS3File, denoS3LightClientSettings, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parallel, parseS3Object, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, resolveDefaultResource, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setInternalState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, uint8ArrayToBase64, usernameToEmail, waitForApproval, waitJob, workerHasInternalServer, workflow, writeS3File };
1349
+ export { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, commitKafkaOffsets, databaseUrlFromResource, deleteS3File, denoS3LightClientSettings, getEnv, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parallel, parseS3Object, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, resolveDefaultResource, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setInternalState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, uint8ArrayToBase64, usernameToEmail, waitForApproval, waitJob, workerHasInternalServer, workflow, writeS3File };
@@ -29,7 +29,7 @@ const OpenAPI = {
29
29
  PASSWORD: void 0,
30
30
  TOKEN: getEnv("WM_TOKEN"),
31
31
  USERNAME: void 0,
32
- VERSION: "1.733.1",
32
+ VERSION: "1.735.0",
33
33
  WITH_CREDENTIALS: true,
34
34
  interceptors: {
35
35
  request: new Interceptors(),
package/dist/index.d.ts CHANGED
@@ -4,8 +4,8 @@ export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI';
4
4
  export * from './services.gen';
5
5
  export * from './types.gen';
6
6
  export type { DenoS3LightClientSettings } from "./s3Types";
7
- export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, type TaskOptions, WorkflowCtx, _workflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, type Sql, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, type DatatableSqlTemplateFunction, type SqlTemplateFunction, type S3Object, type S3ObjectRecord, type S3ObjectURI, commitKafkaOffsets } from "./client";
8
- import { setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, WorkflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, getWorkspace, getStatePath, getInternalState, setInternalState, getResumeEndpoints, getResult, getResultMaybe, resolveDefaultResource, databaseUrlFromResource, base64ToUint8Array, uint8ArrayToBase64, parseS3Object, commitKafkaOffsets } from "./client";
7
+ export { type Base64, setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, type TaskOptions, WorkflowCtx, _workflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, type Sql, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, upsertPartition, appendPartition, type DucklakeMaterializeOptions, type SqlStatement, type DatatableSqlTemplateFunction, type SqlTemplateFunction, type S3Object, type S3ObjectRecord, type S3ObjectURI, commitKafkaOffsets } from "./client";
8
+ import { setClient, getVariable, setVariable, getResource, setResource, getResumeUrls, setState, setProgress, getProgress, getState, getIdToken, denoS3LightClientSettings, loadS3FileStream, loadS3File, writeS3File, deleteS3File, signS3Objects, signS3Object, getPresignedS3PublicUrls, getPresignedS3PublicUrl, task, taskScript, taskFlow, workflow, step, sleep, parallel, waitForApproval, WorkflowCtx, setWorkflowCtx, StepSuspend, runScript, runScriptAsync, runScriptByPath, runScriptByHash, runScriptByPathAsync, runScriptByHashAsync, runFlow, runFlowAsync, waitJob, getRootJobId, setFlowUserState, getFlowUserState, usernameToEmail, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, appendToResultStream, streamResult, datatable, ducklake, upsertPartition, appendPartition, getWorkspace, getStatePath, getInternalState, setInternalState, getResumeEndpoints, getResult, getResultMaybe, resolveDefaultResource, databaseUrlFromResource, base64ToUint8Array, uint8ArrayToBase64, parseS3Object, commitKafkaOffsets } from "./client";
9
9
  import { AdminService, AuditService, FlowService, GranularAclService, GroupService, JobService, ResourceService, VariableService, ScriptService, ScheduleService, SettingsService, UserService, WorkspaceService, TeamsService } from "./services.gen";
10
10
  declare const wmill: {
11
11
  setClient: typeof setClient;
@@ -59,6 +59,8 @@ declare const wmill: {
59
59
  streamResult: typeof streamResult;
60
60
  datatable: typeof datatable;
61
61
  ducklake: typeof ducklake;
62
+ upsertPartition: typeof upsertPartition;
63
+ appendPartition: typeof appendPartition;
62
64
  SHARED_FOLDER: string;
63
65
  getWorkspace: typeof getWorkspace;
64
66
  getStatePath: typeof getStatePath;
package/dist/index.js CHANGED
@@ -126,7 +126,7 @@ const OpenAPI = {
126
126
  PASSWORD: void 0,
127
127
  TOKEN: getEnv$1("WM_TOKEN"),
128
128
  USERNAME: void 0,
129
- VERSION: "1.733.1",
129
+ VERSION: "1.735.0",
130
130
  WITH_CREDENTIALS: true,
131
131
  interceptors: {
132
132
  request: new Interceptors(),
@@ -15005,6 +15005,127 @@ function ducklake(name = "main") {
15005
15005
  let { name: n, schema } = parseName(name);
15006
15006
  return buildSqlTemplateFunction(ducklakeProvider(n, schema));
15007
15007
  }
15008
+ /** Idempotently materialize `selectSql` into a ducklake table for one
15009
+ * partition (or the whole table when `partition` is omitted) — the client-side
15010
+ * equivalent of the `// materialize` engine.
15011
+ * With `uniqueKey` it upserts the slice (delete-by-key + insert); otherwise it
15012
+ * replaces it (whole table → `CREATE OR REPLACE`; partition → delete + insert).
15013
+ * Safe to re-run for the same partition (backfill / failure-recovery).
15014
+ *
15015
+ * Returns a lazy statement — call `.execute()` to run it:
15016
+ * `await wmill.upsertPartition({ table, selectSql, partition }).execute()`. */
15017
+ function upsertPartition(opts) {
15018
+ return finishMaterialize(buildUpsertStatement(opts), opts);
15019
+ }
15020
+ function buildUpsertStatement(opts) {
15021
+ let { name: n, schema } = parseName(opts.ducklake ?? "main");
15022
+ let sql = buildSqlTemplateFunction(ducklakeProvider(n, schema));
15023
+ let pcol = sql.raw(opts.partitionCol ?? "_wm_partition");
15024
+ let t = sql.raw(`dl.${opts.table}`);
15025
+ let body = sql.raw(opts.selectSql);
15026
+ if (opts.partition === void 0) {
15027
+ if (opts.uniqueKey) {
15028
+ let uk = sql.raw(opts.uniqueKey);
15029
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT * FROM (${body}) WHERE false;
15030
+ BEGIN TRANSACTION;
15031
+ DELETE FROM ${t} WHERE ${uk} IN (SELECT ${uk} FROM (${body}));
15032
+ INSERT INTO ${t} SELECT * FROM (${body});
15033
+ COMMIT;`;
15034
+ }
15035
+ return sql`CREATE OR REPLACE TABLE ${t} AS SELECT * FROM (${body});`;
15036
+ }
15037
+ if (opts.uniqueKey) {
15038
+ let uk = sql.raw(opts.uniqueKey);
15039
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT *, CAST(NULL AS VARCHAR) AS ${pcol} FROM (${body}) WHERE false;
15040
+ ALTER TABLE ${t} SET PARTITIONED BY (${pcol});
15041
+ BEGIN TRANSACTION;
15042
+ DELETE FROM ${t} WHERE ${pcol} = ${opts.partition} AND ${uk} IN (SELECT ${uk} FROM (${body}));
15043
+ INSERT INTO ${t} SELECT *, ${opts.partition} AS ${pcol} FROM (${body});
15044
+ COMMIT;`;
15045
+ }
15046
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT *, CAST(NULL AS VARCHAR) AS ${pcol} FROM (${body}) WHERE false;
15047
+ ALTER TABLE ${t} SET PARTITIONED BY (${pcol});
15048
+ BEGIN TRANSACTION;
15049
+ DELETE FROM ${t} WHERE ${pcol} = ${opts.partition};
15050
+ INSERT INTO ${t} SELECT *, ${opts.partition} AS ${pcol} FROM (${body});
15051
+ COMMIT;`;
15052
+ }
15053
+ /** INSERT-only materialization (no dedup/replace) for append-only tables.
15054
+ * Re-running the same partition duplicates rows — use only for immutable
15055
+ * event-log sources.
15056
+ *
15057
+ * Returns a lazy statement — call `.execute()` to run it:
15058
+ * `await wmill.appendPartition({ table, selectSql, partition }).execute()`. */
15059
+ function appendPartition(opts) {
15060
+ return finishMaterialize(buildAppendStatement(opts), opts);
15061
+ }
15062
+ function buildAppendStatement(opts) {
15063
+ let { name: n, schema } = parseName(opts.ducklake ?? "main");
15064
+ let sql = buildSqlTemplateFunction(ducklakeProvider(n, schema));
15065
+ let pcol = sql.raw(opts.partitionCol ?? "_wm_partition");
15066
+ let t = sql.raw(`dl.${opts.table}`);
15067
+ let body = sql.raw(opts.selectSql);
15068
+ if (opts.partition === void 0) return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT * FROM (${body}) WHERE false;
15069
+ INSERT INTO ${t} SELECT * FROM (${body});`;
15070
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT *, CAST(NULL AS VARCHAR) AS ${pcol} FROM (${body}) WHERE false;
15071
+ ALTER TABLE ${t} SET PARTITIONED BY (${pcol});
15072
+ INSERT INTO ${t} SELECT *, ${opts.partition} AS ${pcol} FROM (${body});`;
15073
+ }
15074
+ function finishMaterialize(stmt, opts) {
15075
+ if (getEnv("WM_PIPELINE") !== "true") return stmt;
15076
+ let { name: n, schema } = parseName(opts.ducklake ?? "main");
15077
+ let sql = buildSqlTemplateFunction(ducklakeProvider(n, schema));
15078
+ let t = sql.raw(`dl.${opts.table}`);
15079
+ let pcol = opts.partitionCol ?? "_wm_partition";
15080
+ let where = opts.partition !== void 0 ? sql.raw(`WHERE ${pcol} = '${String(opts.partition).replace(/'/g, "''")}'`) : sql.raw("");
15081
+ let summary = sql`SELECT (SELECT count(*) FROM ${t} ${where}) AS rows, (SELECT max(snapshot_id) FROM ducklake_snapshots('dl')) AS snapshot_id`;
15082
+ let assetPath = schema ? `${n}/${schema}.${opts.table}` : `${n}/${opts.table}`;
15083
+ let partition = opts.partition ?? "";
15084
+ let run = async () => {
15085
+ try {
15086
+ await stmt.execute();
15087
+ } catch (e) {
15088
+ await recordMaterialization(assetPath, partition, "failed", null, null, String(e));
15089
+ throw e;
15090
+ }
15091
+ let snapshot_id = null;
15092
+ let row_count = null;
15093
+ try {
15094
+ let s = await summary.fetchOne();
15095
+ snapshot_id = s?.snapshot_id ?? null;
15096
+ row_count = s?.rows ?? null;
15097
+ } catch {}
15098
+ await recordMaterialization(assetPath, partition, "materialized", snapshot_id, row_count, null);
15099
+ };
15100
+ return {
15101
+ ...stmt,
15102
+ execute: () => run(),
15103
+ fetch: () => run(),
15104
+ fetchOne: () => run(),
15105
+ fetchOneScalar: () => run()
15106
+ };
15107
+ }
15108
+ async function recordMaterialization(assetPath, partition, status, snapshot_id, row_count, error) {
15109
+ try {
15110
+ await fetch(`${OpenAPI.BASE}/w/${getWorkspace()}/assets/record_materialization`, {
15111
+ method: "POST",
15112
+ headers: {
15113
+ "content-type": "application/json",
15114
+ authorization: `Bearer ${OpenAPI.TOKEN}`
15115
+ },
15116
+ body: JSON.stringify({
15117
+ asset_kind: "ducklake",
15118
+ asset_path: assetPath,
15119
+ partition,
15120
+ status,
15121
+ snapshot_id,
15122
+ row_count,
15123
+ job_id: getEnv("WM_JOB_ID") ?? null,
15124
+ error
15125
+ })
15126
+ });
15127
+ } catch {}
15128
+ }
15008
15129
  function inferSqlType(value) {
15009
15130
  if (typeof value === "bigint") return "BIGINT";
15010
15131
  if (typeof value === "number") {
@@ -16449,6 +16570,8 @@ const wmill = {
16449
16570
  streamResult,
16450
16571
  datatable,
16451
16572
  ducklake,
16573
+ upsertPartition,
16574
+ appendPartition,
16452
16575
  SHARED_FOLDER,
16453
16576
  getWorkspace,
16454
16577
  getStatePath,
@@ -16552,6 +16675,7 @@ Object.defineProperty(exports, '_workflowCtx', {
16552
16675
  return _workflowCtx;
16553
16676
  }
16554
16677
  });
16678
+ exports.appendPartition = appendPartition;
16555
16679
  exports.appendToResultStream = appendToResultStream;
16556
16680
  exports.commitKafkaOffsets = commitKafkaOffsets;
16557
16681
  exports.datatable = datatable;
@@ -16597,6 +16721,7 @@ exports.streamResult = streamResult;
16597
16721
  exports.task = task;
16598
16722
  exports.taskFlow = taskFlow;
16599
16723
  exports.taskScript = taskScript;
16724
+ exports.upsertPartition = upsertPartition;
16600
16725
  exports.usernameToEmail = usernameToEmail;
16601
16726
  exports.waitForApproval = waitForApproval;
16602
16727
  exports.waitJob = waitJob;
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import { ApiError } from "./core/ApiError.mjs";
2
2
  import { CancelError, CancelablePromise } from "./core/CancelablePromise.mjs";
3
3
  import { OpenAPI } from "./core/OpenAPI.mjs";
4
4
  import { AdminService, AgentWorkersService, AppService, AssetService, AuditService, AzureTriggerService, CaptureService, ConcurrencyGroupsService, ConfigService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationsService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenapiService, PathAutocompleteService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService } from "./services.gen.mjs";
5
- import { datatable, ducklake } from "./sqlUtils.mjs";
5
+ import { appendPartition, datatable, ducklake, upsertPartition } from "./sqlUtils.mjs";
6
6
  import { SHARED_FOLDER, StepSuspend, WorkflowCtx, _workflowCtx, appendToResultStream, base64ToUint8Array, commitKafkaOffsets, databaseUrlFromResource, deleteS3File, denoS3LightClientSettings, getFlowUserState, getIdToken, getInternalState, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResult, getResultMaybe, getResumeEndpoints, getResumeUrls, getRootJobId, getState, getStatePath, getVariable, getWorkspace, loadS3File, loadS3FileStream, parallel, parseS3Object, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, resolveDefaultResource, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setInternalState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, uint8ArrayToBase64, usernameToEmail, waitForApproval, waitJob, workflow, writeS3File } from "./client.mjs";
7
7
 
8
8
  //#region src/index.ts
@@ -58,6 +58,8 @@ const wmill = {
58
58
  streamResult,
59
59
  datatable,
60
60
  ducklake,
61
+ upsertPartition,
62
+ appendPartition,
61
63
  SHARED_FOLDER,
62
64
  getWorkspace,
63
65
  getStatePath,
@@ -90,4 +92,4 @@ const wmill = {
90
92
  var src_default = wmill;
91
93
 
92
94
  //#endregion
93
- export { AdminService, AgentWorkersService, ApiError, AppService, AssetService, AuditService, AzureTriggerService, CancelError, CancelablePromise, CaptureService, ConcurrencyGroupsService, ConfigService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationsService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenAPI, OpenapiService, PathAutocompleteService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, StepSuspend, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkflowCtx, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService, _workflowCtx, appendToResultStream, commitKafkaOffsets, datatable, src_default as default, deleteS3File, denoS3LightClientSettings, ducklake, getFlowUserState, getIdToken, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResumeUrls, getRootJobId, getState, getVariable, loadS3File, loadS3FileStream, parallel, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, usernameToEmail, waitForApproval, waitJob, workflow, writeS3File };
95
+ export { AdminService, AgentWorkersService, ApiError, AppService, AssetService, AuditService, AzureTriggerService, CancelError, CancelablePromise, CaptureService, ConcurrencyGroupsService, ConfigService, DocumentationService, DraftService, EmailTriggerService, FavoriteService, FlowConversationsService, FlowService, FolderService, GcpTriggerService, GitSyncService, GranularAclService, GroupService, HealthService, HelpersService, HttpTriggerService, IndexSearchService, InputService, IntegrationService, JobService, KafkaTriggerService, McpOauthService, McpService, MetricsService, MqttTriggerService, NativeTriggerService, NatsTriggerService, NpmProxyService, OauthService, OidcService, OpenAPI, OpenapiService, PathAutocompleteService, PostgresTriggerService, RawAppService, ResourceService, ScheduleService, ScriptService, ServiceLogsService, SettingService, SettingsService, SqsTriggerService, StepSuspend, TeamsService, TokenService, TriggerService, UserService, VariableService, VolumeService, WebsocketTriggerService, WorkerService, WorkflowCtx, WorkspaceDependenciesService, WorkspaceIntegrationService, WorkspaceService, _workflowCtx, appendPartition, appendToResultStream, commitKafkaOffsets, datatable, src_default as default, deleteS3File, denoS3LightClientSettings, ducklake, getFlowUserState, getIdToken, getPresignedS3PublicUrl, getPresignedS3PublicUrls, getProgress, getResource, getResumeUrls, getRootJobId, getState, getVariable, loadS3File, loadS3FileStream, parallel, requestInteractiveSlackApproval, requestInteractiveTeamsApproval, runFlow, runFlowAsync, runScript, runScriptAsync, runScriptByHash, runScriptByHashAsync, runScriptByPath, runScriptByPathAsync, setClient, setFlowUserState, setProgress, setResource, setState, setVariable, setWorkflowCtx, signS3Object, signS3Objects, sleep, step, streamResult, task, taskFlow, taskScript, upsertPartition, usernameToEmail, waitForApproval, waitJob, workflow, writeS3File };
@@ -86,4 +86,39 @@ export declare function datatable(name?: string): DatatableSqlTemplateFunction;
86
86
  * let sql = wmill.ducklake("my_lake:analytics")
87
87
  */
88
88
  export declare function ducklake(name?: string): SqlTemplateFunction;
89
+ /** Options for the ducklake materialization helpers. `partition` is bound as a
90
+ * DuckDB arg (never interpolated); `selectSql`, `table`, `schema`, `uniqueKey`
91
+ * are trusted structural SQL inlined via `raw`. */
92
+ export interface DucklakeMaterializeOptions {
93
+ /** ducklake name (default "main"), optionally "name:schema". */
94
+ ducklake?: string;
95
+ /** target table within the ducklake. */
96
+ table: string;
97
+ /** the SELECT producing the rows for this slice. */
98
+ selectSql: string;
99
+ /** the partition value (bound). Omit for a whole-table materialization — no
100
+ * partition column, and replace becomes a `CREATE OR REPLACE TABLE`. */
101
+ partition?: string;
102
+ /** dedup key → upsert in slice (delete-by-key + insert); omit → replace (delete partition + insert). */
103
+ uniqueKey?: string;
104
+ /** physical partition column (default "_wm_partition"). */
105
+ partitionCol?: string;
106
+ }
107
+ /** Idempotently materialize `selectSql` into a ducklake table for one
108
+ * partition (or the whole table when `partition` is omitted) — the client-side
109
+ * equivalent of the `// materialize` engine.
110
+ * With `uniqueKey` it upserts the slice (delete-by-key + insert); otherwise it
111
+ * replaces it (whole table → `CREATE OR REPLACE`; partition → delete + insert).
112
+ * Safe to re-run for the same partition (backfill / failure-recovery).
113
+ *
114
+ * Returns a lazy statement — call `.execute()` to run it:
115
+ * `await wmill.upsertPartition({ table, selectSql, partition }).execute()`. */
116
+ export declare function upsertPartition(opts: DucklakeMaterializeOptions): SqlStatement<any>;
117
+ /** INSERT-only materialization (no dedup/replace) for append-only tables.
118
+ * Re-running the same partition duplicates rows — use only for immutable
119
+ * event-log sources.
120
+ *
121
+ * Returns a lazy statement — call `.execute()` to run it:
122
+ * `await wmill.appendPartition({ table, selectSql, partition }).execute()`. */
123
+ export declare function appendPartition(opts: Omit<DucklakeMaterializeOptions, "uniqueKey">): SqlStatement<any>;
89
124
  export {};
package/dist/sqlUtils.mjs CHANGED
@@ -1,5 +1,6 @@
1
+ import { OpenAPI } from "./core/OpenAPI.mjs";
1
2
  import { JobService } from "./services.gen.mjs";
2
- import { getWorkspace, workerHasInternalServer } from "./client.mjs";
3
+ import { getEnv, getWorkspace, workerHasInternalServer } from "./client.mjs";
3
4
 
4
5
  //#region src/sqlUtils.ts
5
6
  /**
@@ -33,7 +34,7 @@ function ducklakeProvider(name, schema) {
33
34
  };
34
35
  }
35
36
  function buildSqlStatement(provider, content, contentBody, args) {
36
- async function fetch({ resultCollection } = {}) {
37
+ async function fetch$1({ resultCollection } = {}) {
37
38
  let finalContent = content;
38
39
  if (resultCollection) finalContent = `-- result_collection=${resultCollection}\n${finalContent}`;
39
40
  try {
@@ -72,16 +73,16 @@ function buildSqlStatement(provider, content, contentBody, args) {
72
73
  return {
73
74
  content,
74
75
  args,
75
- fetch,
76
- fetchOne: (params) => fetch({
76
+ fetch: fetch$1,
77
+ fetchOne: (params) => fetch$1({
77
78
  ...params,
78
79
  resultCollection: "last_statement_first_row"
79
80
  }),
80
- fetchOneScalar: (params) => fetch({
81
+ fetchOneScalar: (params) => fetch$1({
81
82
  ...params,
82
83
  resultCollection: "last_statement_first_row_scalar"
83
84
  }),
84
- execute: (params) => fetch(params)
85
+ execute: (params) => fetch$1(params)
85
86
  };
86
87
  }
87
88
  function serializeArgValue(v) {
@@ -188,6 +189,127 @@ function ducklake(name = "main") {
188
189
  let { name: n, schema } = parseName(name);
189
190
  return buildSqlTemplateFunction(ducklakeProvider(n, schema));
190
191
  }
192
+ /** Idempotently materialize `selectSql` into a ducklake table for one
193
+ * partition (or the whole table when `partition` is omitted) — the client-side
194
+ * equivalent of the `// materialize` engine.
195
+ * With `uniqueKey` it upserts the slice (delete-by-key + insert); otherwise it
196
+ * replaces it (whole table → `CREATE OR REPLACE`; partition → delete + insert).
197
+ * Safe to re-run for the same partition (backfill / failure-recovery).
198
+ *
199
+ * Returns a lazy statement — call `.execute()` to run it:
200
+ * `await wmill.upsertPartition({ table, selectSql, partition }).execute()`. */
201
+ function upsertPartition(opts) {
202
+ return finishMaterialize(buildUpsertStatement(opts), opts);
203
+ }
204
+ function buildUpsertStatement(opts) {
205
+ let { name: n, schema } = parseName(opts.ducklake ?? "main");
206
+ let sql = buildSqlTemplateFunction(ducklakeProvider(n, schema));
207
+ let pcol = sql.raw(opts.partitionCol ?? "_wm_partition");
208
+ let t = sql.raw(`dl.${opts.table}`);
209
+ let body = sql.raw(opts.selectSql);
210
+ if (opts.partition === void 0) {
211
+ if (opts.uniqueKey) {
212
+ let uk = sql.raw(opts.uniqueKey);
213
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT * FROM (${body}) WHERE false;
214
+ BEGIN TRANSACTION;
215
+ DELETE FROM ${t} WHERE ${uk} IN (SELECT ${uk} FROM (${body}));
216
+ INSERT INTO ${t} SELECT * FROM (${body});
217
+ COMMIT;`;
218
+ }
219
+ return sql`CREATE OR REPLACE TABLE ${t} AS SELECT * FROM (${body});`;
220
+ }
221
+ if (opts.uniqueKey) {
222
+ let uk = sql.raw(opts.uniqueKey);
223
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT *, CAST(NULL AS VARCHAR) AS ${pcol} FROM (${body}) WHERE false;
224
+ ALTER TABLE ${t} SET PARTITIONED BY (${pcol});
225
+ BEGIN TRANSACTION;
226
+ DELETE FROM ${t} WHERE ${pcol} = ${opts.partition} AND ${uk} IN (SELECT ${uk} FROM (${body}));
227
+ INSERT INTO ${t} SELECT *, ${opts.partition} AS ${pcol} FROM (${body});
228
+ COMMIT;`;
229
+ }
230
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT *, CAST(NULL AS VARCHAR) AS ${pcol} FROM (${body}) WHERE false;
231
+ ALTER TABLE ${t} SET PARTITIONED BY (${pcol});
232
+ BEGIN TRANSACTION;
233
+ DELETE FROM ${t} WHERE ${pcol} = ${opts.partition};
234
+ INSERT INTO ${t} SELECT *, ${opts.partition} AS ${pcol} FROM (${body});
235
+ COMMIT;`;
236
+ }
237
+ /** INSERT-only materialization (no dedup/replace) for append-only tables.
238
+ * Re-running the same partition duplicates rows — use only for immutable
239
+ * event-log sources.
240
+ *
241
+ * Returns a lazy statement — call `.execute()` to run it:
242
+ * `await wmill.appendPartition({ table, selectSql, partition }).execute()`. */
243
+ function appendPartition(opts) {
244
+ return finishMaterialize(buildAppendStatement(opts), opts);
245
+ }
246
+ function buildAppendStatement(opts) {
247
+ let { name: n, schema } = parseName(opts.ducklake ?? "main");
248
+ let sql = buildSqlTemplateFunction(ducklakeProvider(n, schema));
249
+ let pcol = sql.raw(opts.partitionCol ?? "_wm_partition");
250
+ let t = sql.raw(`dl.${opts.table}`);
251
+ let body = sql.raw(opts.selectSql);
252
+ if (opts.partition === void 0) return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT * FROM (${body}) WHERE false;
253
+ INSERT INTO ${t} SELECT * FROM (${body});`;
254
+ return sql`CREATE TABLE IF NOT EXISTS ${t} AS SELECT *, CAST(NULL AS VARCHAR) AS ${pcol} FROM (${body}) WHERE false;
255
+ ALTER TABLE ${t} SET PARTITIONED BY (${pcol});
256
+ INSERT INTO ${t} SELECT *, ${opts.partition} AS ${pcol} FROM (${body});`;
257
+ }
258
+ function finishMaterialize(stmt, opts) {
259
+ if (getEnv("WM_PIPELINE") !== "true") return stmt;
260
+ let { name: n, schema } = parseName(opts.ducklake ?? "main");
261
+ let sql = buildSqlTemplateFunction(ducklakeProvider(n, schema));
262
+ let t = sql.raw(`dl.${opts.table}`);
263
+ let pcol = opts.partitionCol ?? "_wm_partition";
264
+ let where = opts.partition !== void 0 ? sql.raw(`WHERE ${pcol} = '${String(opts.partition).replace(/'/g, "''")}'`) : sql.raw("");
265
+ let summary = sql`SELECT (SELECT count(*) FROM ${t} ${where}) AS rows, (SELECT max(snapshot_id) FROM ducklake_snapshots('dl')) AS snapshot_id`;
266
+ let assetPath = schema ? `${n}/${schema}.${opts.table}` : `${n}/${opts.table}`;
267
+ let partition = opts.partition ?? "";
268
+ let run = async () => {
269
+ try {
270
+ await stmt.execute();
271
+ } catch (e) {
272
+ await recordMaterialization(assetPath, partition, "failed", null, null, String(e));
273
+ throw e;
274
+ }
275
+ let snapshot_id = null;
276
+ let row_count = null;
277
+ try {
278
+ let s = await summary.fetchOne();
279
+ snapshot_id = s?.snapshot_id ?? null;
280
+ row_count = s?.rows ?? null;
281
+ } catch {}
282
+ await recordMaterialization(assetPath, partition, "materialized", snapshot_id, row_count, null);
283
+ };
284
+ return {
285
+ ...stmt,
286
+ execute: () => run(),
287
+ fetch: () => run(),
288
+ fetchOne: () => run(),
289
+ fetchOneScalar: () => run()
290
+ };
291
+ }
292
+ async function recordMaterialization(assetPath, partition, status, snapshot_id, row_count, error) {
293
+ try {
294
+ await fetch(`${OpenAPI.BASE}/w/${getWorkspace()}/assets/record_materialization`, {
295
+ method: "POST",
296
+ headers: {
297
+ "content-type": "application/json",
298
+ authorization: `Bearer ${OpenAPI.TOKEN}`
299
+ },
300
+ body: JSON.stringify({
301
+ asset_kind: "ducklake",
302
+ asset_path: assetPath,
303
+ partition,
304
+ status,
305
+ snapshot_id,
306
+ row_count,
307
+ job_id: getEnv("WM_JOB_ID") ?? null,
308
+ error
309
+ })
310
+ });
311
+ } catch {}
312
+ }
191
313
  function inferSqlType(value) {
192
314
  if (typeof value === "bigint") return "BIGINT";
193
315
  if (typeof value === "number") {
@@ -235,4 +357,4 @@ function parseName(name) {
235
357
  }
236
358
 
237
359
  //#endregion
238
- export { datatable, ducklake };
360
+ export { appendPartition, datatable, ducklake, upsertPartition };
@@ -1538,6 +1538,10 @@ export type Script = {
1538
1538
  export type NewScript = {
1539
1539
  path: string;
1540
1540
  parent_hash?: string;
1541
+ /**
1542
+ * When true, the backend resolves the parent to the current deployed head for this path within the transaction (ignoring parent_hash), instead of failing with a "lineage must be linear" error when the supplied parent_hash is stale.
1543
+ */
1544
+ auto_parent?: boolean;
1541
1545
  summary: string;
1542
1546
  description?: string;
1543
1547
  content: string;
@@ -1880,6 +1884,7 @@ export type User = {
1880
1884
  disabled: boolean;
1881
1885
  groups?: Array<(string)>;
1882
1886
  folders: Array<(string)>;
1887
+ folders_read: Array<(string)>;
1883
1888
  folders_owners: Array<(string)>;
1884
1889
  added_via?: (UserSource) | null;
1885
1890
  is_service_account?: boolean;
@@ -7500,6 +7505,7 @@ export type GetLogCleanupStatusResponse = {
7500
7505
  total_jobs: number;
7501
7506
  processed_jobs: number;
7502
7507
  s3_deleted: number;
7508
+ s3_not_found?: number;
7503
7509
  orphans_scanned: number;
7504
7510
  orphans_deleted: number;
7505
7511
  errors: number;
@@ -7908,6 +7914,10 @@ export type CreateAccountData = {
7908
7914
  * Instance name for built-in providers whose client-credentials token URL is instance-templated; substituted into the fixed-host registry template server-side (client_credentials flow only). The token URL is never caller-supplied.
7909
7915
  */
7910
7916
  cc_instance?: string;
7917
+ /**
7918
+ * Bring-your-own token endpoint override (client_credentials flow only). Only honored together with cc_client_id/cc_client_secret and mutually exclusive with cc_instance; ignored/rejected on the shared-instance path.
7919
+ */
7920
+ cc_token_url?: string;
7911
7921
  /**
7912
7922
  * MCP server URL for MCP OAuth token refresh
7913
7923
  */
@@ -7942,6 +7952,10 @@ export type ConnectClientCredentialsData = {
7942
7952
  * Instance name for built-in providers whose client-credentials token URL is instance-templated; substituted into the fixed-host registry template server-side. The token URL is never caller-supplied.
7943
7953
  */
7944
7954
  cc_instance?: string;
7955
+ /**
7956
+ * Bring-your-own token endpoint override. Only honored together with cc_client_id/cc_client_secret and mutually exclusive with cc_instance; rejected on the shared-instance path.
7957
+ */
7958
+ cc_token_url?: string;
7945
7959
  };
7946
7960
  workspace: string;
7947
7961
  };
@@ -18070,6 +18084,7 @@ export type $OpenApiTs = {
18070
18084
  total_jobs: number;
18071
18085
  processed_jobs: number;
18072
18086
  s3_deleted: number;
18087
+ s3_not_found?: number;
18073
18088
  orphans_scanned: number;
18074
18089
  orphans_deleted: number;
18075
18090
  errors: number;
@@ -18895,6 +18910,10 @@ export type $OpenApiTs = {
18895
18910
  * Instance name for built-in providers whose client-credentials token URL is instance-templated; substituted into the fixed-host registry template server-side (client_credentials flow only). The token URL is never caller-supplied.
18896
18911
  */
18897
18912
  cc_instance?: string;
18913
+ /**
18914
+ * Bring-your-own token endpoint override (client_credentials flow only). Only honored together with cc_client_id/cc_client_secret and mutually exclusive with cc_instance; ignored/rejected on the shared-instance path.
18915
+ */
18916
+ cc_token_url?: string;
18898
18917
  /**
18899
18918
  * MCP server URL for MCP OAuth token refresh
18900
18919
  */
@@ -18938,6 +18957,10 @@ export type $OpenApiTs = {
18938
18957
  * Instance name for built-in providers whose client-credentials token URL is instance-templated; substituted into the fixed-host registry template server-side. The token URL is never caller-supplied.
18939
18958
  */
18940
18959
  cc_instance?: string;
18960
+ /**
18961
+ * Bring-your-own token endpoint override. Only honored together with cc_client_id/cc_client_secret and mutually exclusive with cc_instance; rejected on the shared-instance path.
18962
+ */
18963
+ cc_token_url?: string;
18941
18964
  };
18942
18965
  workspace: string;
18943
18966
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "windmill-client",
3
3
  "description": "Windmill SDK client for browsers and Node.js",
4
- "version": "1.733.1",
4
+ "version": "1.735.0",
5
5
  "author": "Ruben Fiszel",
6
6
  "license": "Apache 2.0",
7
7
  "homepage": "https://github.com/windmill-labs/windmill/tree/main/typescript-client#readme",