chore: bump windmill-utils-internal to 1.8.3 and drop its workarounds (#11942)

* chore: bump windmill-utils-internal to 1.8.3 and drop frontend workarounds

* chore: resolve windmill-utils-internal 1.8.3 in the frontend lockfile
This commit is contained in:
AlexRV12
2026-10-22 17:12:20 +02:00
committed by GitHub
parent 69f83da9b2
commit 15b0b27877
9 changed files with 35 additions and 102 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "windmill-utils-internal",
"version": "1.7.0",
"version": "1.8.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "windmill-utils-internal",
"version": "1.7.0",
"version": "1.8.3",
"license": "Apache 2.0",
"devDependencies": {
"@types/node": "^24.2.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "windmill-utils-internal",
"version": "1.8.2",
"version": "1.8.3",
"description": "Internal utility functions for Windmill",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
+5 -1
View File
@@ -926,7 +926,11 @@ export async function getItemValue(
path,
decryptSecret: true,
});
return variable.value;
return {
value: variable.value,
is_secret: variable.is_secret,
description: variable.description,
};
} else if (kind === "resource") {
const resource = await provider.getResource({ workspace, path });
// Each workspace resolves its own agent identity, which a deploy never copies.
@@ -190,7 +190,7 @@ export async function replacePathScriptsWithLocal(
}
const localScript = await scriptReader(toolValue.path);
if (localScript) {
(tool as AiAgent["tools"][number]).value = {
(tool as NonNullable<AiAgent["tools"]>[number]).value = {
tool_type: "flowmodule",
type: "rawscript",
content: localScript.content,
@@ -5,7 +5,7 @@ const INLINE_SCRIPT_PREFIX = "inline_script";
/**
* Union type of all supported programming languages in Windmill
*/
export type SupportedLanguage = RawScript["language"] | "frontend" | "bunnative" | "oracledb" | "rust" | "csharp" | "nu" | "ansible" | "java" | "duckdb";
export type SupportedLanguage = RawScript["language"] | "frontend" | "bunnative" | "oracledb" | "rust" | "csharp" | "nu" | "ansible" | "java" | "duckdb" | "dbt";
/**
* Mapping of supported languages to their file extensions
+4 -4
View File
@@ -110,7 +110,7 @@
"windmill-parser-wasm-wac": "1.830.0",
"windmill-parser-wasm-yaml": "1.770.0",
"windmill-sql-datatype-parser-wasm": "1.512.0",
"windmill-utils-internal": "1.8.2",
"windmill-utils-internal": "1.8.3",
"xterm": "^5.3.0",
"xterm-readline": "^1.1.2",
"y-monaco": "^0.1.4",
@@ -14719,9 +14719,9 @@
"integrity": "sha512-uHNL8F72/Tf96xF3hOHnPDjkEyqXw7fNjcPJiUhth9sTQkcwUIoJMOdwm8/cs+j9kKVRJ4tgNYMHEBLylazp6g=="
},
"node_modules/windmill-utils-internal": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/windmill-utils-internal/-/windmill-utils-internal-1.8.2.tgz",
"integrity": "sha512-Otdn4iCE0QiOtMKPdHX5I89oECfZa3vmO2jdLdSETf7MBSv/gw9gvQm3oUQ29ymIHXLeuhQk/ebPD+WYolQJEA==",
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/windmill-utils-internal/-/windmill-utils-internal-1.8.3.tgz",
"integrity": "sha512-Lp8fVM/uHUvO6q01rIODIR46hTQ9D9R9BEiKoZHQqw9NJoy1OxhcsvX4usBbkXff/GbHlkWiQfZXCOn0ozJeKQ==",
"license": "Apache 2.0"
},
"node_modules/word-wrap": {
+1 -1
View File
@@ -177,7 +177,7 @@
"windmill-parser-wasm-wac": "1.830.0",
"windmill-parser-wasm-yaml": "1.770.0",
"windmill-sql-datatype-parser-wasm": "1.512.0",
"windmill-utils-internal": "1.8.2",
"windmill-utils-internal": "1.8.3",
"xterm": "^5.3.0",
"xterm-readline": "^1.1.2",
"y-monaco": "^0.1.4",
@@ -32,8 +32,8 @@ vi.mock('$lib/gen', async (importOriginal) => ({
}
}))
// The deploy runs the published shared package, whose variable body has no `labels`: this
// pins that the adapter still carries them until a version that does is installed.
// The variable body is built by the installed shared package: this pins that a deploy from the
// app sends the source's labels on create and on update.
describe('deploying a variable to another workspace', () => {
it('carries its labels on create and on update', async () => {
for (const workspaceTo of ['lacks-it', 'has-it']) {
+18 -89
View File
@@ -186,30 +186,13 @@ export type AppIdentity = { email: string; permissionedAs: string }
export type DeployConflict = { hit: boolean }
/**
* `deployItem` overrides only the email half of the identity, while the body it builds
* spreads the *source* item — which carries the source workspace's permissioned_as, valid
* nowhere else since usernames are per-workspace. The key is therefore always overwritten:
* with the picked user's principal for a custom choice, and cleared otherwise so the
* backend derives the target's own from the email it is given. The shared `deployItem`
* does the same, but this app consumes the published package, so the rewrite has to exist
* on both sides until that version ships.
*
* An app carries both halves inside its `policy` instead, so it needs both stamped here:
* the published package leaves the policy untouched, and a source principal beside a
* target address is rejected as a pair naming two different accounts.
*
* A group kept as the target identity travels as its synthetic `group-*@windmill.dev`
* address, which an admin-created account holding it would win on the backend: known and
* accepted, see `users::permissioned_as_from_email`.
*
* An agent carries its principal inside its resource value, and is handed the chosen one as a
* principal, as a trigger is. Every read here drops the source's, so a diff never shows it and
* the published `deployItem` copies none; the write then stamps the chosen one, or none, which
* leaves the backend to make it the deployer's.
* `deployItem` takes the identity only as an email and clears the source workspace's
* principal, leaving the backend to derive the target's own from that email. When the user
* picked a specific user, their principal is known here, so it is stamped on the body: on a
* flow or script directly, and inside the `policy` for an app, which holds both halves.
*/
function makeProvider(
onBehalfOfPrincipal?: string,
onBehalfOf?: string,
/**
* Refuse the writes the shared `deployItem` reaches for only when the item already exists in
* the target, turning its silent switch to an update into a failure the caller can act on.
@@ -219,48 +202,16 @@ function makeProvider(
*/
conflict?: DeployConflict
): DeployProvider {
const withPermissionedAs = <T extends Record<string, any>>(requestBody: T): T => ({
...requestBody,
on_behalf_of: onBehalfOfPrincipal
})
const withPermissionedAs = <T extends Record<string, any>>(requestBody: T): T =>
onBehalfOfPrincipal ? { ...requestBody, on_behalf_of: onBehalfOfPrincipal } : requestBody
const withPolicyIdentity = <T extends Record<string, any>>(app: T): T =>
app.policy
? {
...app,
policy: {
...app.policy,
on_behalf_of: onBehalfOfPrincipal,
on_behalf_of_email: onBehalfOf
}
}
onBehalfOfPrincipal && app.policy
? { ...app, policy: { ...app.policy, on_behalf_of: onBehalfOfPrincipal } }
: app
const agents = new Set<string>()
const withAgentIdentity = <T extends Record<string, any>>(requestBody: T, path: string): T =>
agents.has(path) && requestBody.value && typeof requestBody.value === 'object'
? {
...requestBody,
value: onBehalfOf
? { ...requestBody.value, on_behalf_of: onBehalfOf }
: requestBody.value,
preserve_on_behalf_of: onBehalfOf !== undefined
}
: requestBody
const refuseUpdate = (): never => {
if (conflict) conflict.hit = true
throw new Error('item already exists in the target workspace')
}
// The published package builds variable, resource and folder bodies field by field without
// `labels`, so carry the source item's across from the read `deployItem` does just before the
// write. One provider serves one deploy, so the read always belongs to the write that follows.
let sourceLabels: string[] | undefined
const readLabels = <T extends { labels?: string[] }>(item: T): T => {
sourceLabels = item.labels
return item
}
const withLabels = <T extends Record<string, any>>(requestBody: T): T => ({
...requestBody,
labels: sourceLabels
})
return {
existsFlowByPath: (p) => FlowService.existsFlowByPath(p),
existsScriptByPath: (p) => ScriptService.existsScriptByPath(p),
@@ -305,43 +256,21 @@ function makeProvider(
getPublicSecretOfLatestVersionOfApp: (p) => AppService.getPublicSecretOfLatestVersionOfApp(p),
getRawAppData: (p) => AppService.getRawAppData(p),
deleteApp: (p) => AppService.deleteApp(p),
getVariable: (p) => VariableService.getVariable(p).then(readLabels),
createVariable: (p) =>
VariableService.createVariable({ ...p, requestBody: withLabels(p.requestBody) }),
updateVariable: (p) =>
VariableService.updateVariable({ ...p, requestBody: withLabels(p.requestBody) }),
getVariable: (p) => VariableService.getVariable(p),
createVariable: (p) => VariableService.createVariable(p),
updateVariable: (p) => VariableService.updateVariable(p),
deleteVariable: (p) => VariableService.deleteVariable(p),
getResource: async (p) => {
const resource = readLabels(await ResourceService.getResource(p))
if (resource.resource_type !== 'ai_agent' || !resource.value) return resource
agents.add(p.path)
const { on_behalf_of: _, ...value } = resource.value as Record<string, any>
return { ...resource, value }
},
createResource: (p) =>
ResourceService.createResource({
...p,
requestBody: withAgentIdentity(withLabels(p.requestBody), p.requestBody.path)
}),
updateResource: (p) =>
ResourceService.updateResource({
...p,
requestBody: withAgentIdentity(withLabels(p.requestBody), p.path)
}),
getResource: (p) => ResourceService.getResource(p),
createResource: (p) => ResourceService.createResource(p),
updateResource: (p) => ResourceService.updateResource(p),
deleteResource: (p) => ResourceService.deleteResource(p),
getResourceType: (p) => ResourceService.getResourceType(p),
createResourceType: (p) => ResourceService.createResourceType(p),
updateResourceType: (p) => ResourceService.updateResourceType(p),
deleteResourceType: (p) => ResourceService.deleteResourceType(p),
getFolder: (p) => FolderService.getFolder(p).then(readLabels),
createFolder: (p) =>
FolderService.createFolder({ ...p, requestBody: withLabels(p.requestBody) }),
// A folder with no labels reads back without the field, so clearing them needs an explicit [].
updateFolder: (p) =>
FolderService.updateFolder({
...p,
requestBody: { ...p.requestBody, labels: sourceLabels ?? [] }
}),
getFolder: (p) => FolderService.getFolder(p),
createFolder: (p) => FolderService.createFolder(p),
updateFolder: (p) => FolderService.updateFolder(p),
deleteFolder: (p) => FolderService.deleteFolder(p),
// Triggers
existsTriggerByKind: (kind, p) => triggerServiceFor(kind).exists(p),
@@ -483,7 +412,7 @@ export async function deployItem(
const conflict: DeployConflict | undefined = createOnly ? { hit: false } : undefined
const result = await sharedDeployItem(
makeProvider(onBehalfOfPrincipal, onBehalfOf, conflict),
makeProvider(onBehalfOfPrincipal, conflict),
kind as DeployKind,
path,
workspaceFrom,