windmill-cli 1.505.4 → 1.507.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/esm/conf.js +47 -0
- package/esm/context.js +44 -5
- package/esm/gen/core/OpenAPI.js +1 -1
- package/esm/gen/services.gen.js +19 -0
- package/esm/gitsync-settings.js +812 -0
- package/esm/instance.js +3 -0
- package/esm/main.js +112 -17
- package/esm/store.js +9 -4
- package/esm/sync.js +239 -13
- package/esm/types.js +1 -1
- package/esm/utils.js +31 -0
- package/esm/workspace.js +85 -16
- package/package.json +2 -6
- package/types/conf.d.ts +10 -0
- package/types/conf.d.ts.map +1 -1
- package/types/context.d.ts.map +1 -1
- package/types/gen/services.gen.d.ts +10 -1
- package/types/gen/services.gen.d.ts.map +1 -1
- package/types/gen/types.gen.d.ts +40 -3
- package/types/gen/types.gen.d.ts.map +1 -1
- package/types/gitsync-settings.d.ts +36 -0
- package/types/gitsync-settings.d.ts.map +1 -0
- package/types/instance.d.ts.map +1 -1
- package/types/main.d.ts +7 -2
- package/types/main.d.ts.map +1 -1
- package/types/store.d.ts +2 -2
- package/types/store.d.ts.map +1 -1
- package/types/sync.d.ts +26 -2
- package/types/sync.d.ts.map +1 -1
- package/types/types.d.ts +1 -0
- package/types/types.d.ts.map +1 -1
- package/types/utils.d.ts +4 -0
- package/types/utils.d.ts.map +1 -1
- package/types/workspace.d.ts +3 -3
- package/types/workspace.d.ts.map +1 -1
package/esm/conf.js
CHANGED
|
@@ -12,7 +12,54 @@ export async function readConfigFile() {
|
|
|
12
12
|
return {};
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
// Default sync options - shared across the codebase to prevent duplication
|
|
16
|
+
export const DEFAULT_SYNC_OPTIONS = {
|
|
17
|
+
defaultTs: 'bun',
|
|
18
|
+
includes: ['f/**'],
|
|
19
|
+
excludes: [],
|
|
20
|
+
codebases: [],
|
|
21
|
+
skipVariables: false,
|
|
22
|
+
skipResources: false,
|
|
23
|
+
skipResourceTypes: false,
|
|
24
|
+
skipSecrets: true,
|
|
25
|
+
skipScripts: false,
|
|
26
|
+
skipFlows: false,
|
|
27
|
+
skipApps: false,
|
|
28
|
+
skipFolders: false,
|
|
29
|
+
includeSchedules: false,
|
|
30
|
+
includeTriggers: false,
|
|
31
|
+
includeUsers: false,
|
|
32
|
+
includeGroups: false,
|
|
33
|
+
includeSettings: false,
|
|
34
|
+
includeKey: false
|
|
35
|
+
};
|
|
15
36
|
export async function mergeConfigWithConfigFile(opts) {
|
|
16
37
|
const configFile = await readConfigFile();
|
|
17
38
|
return Object.assign(configFile ?? {}, opts);
|
|
18
39
|
}
|
|
40
|
+
// Get effective settings by merging top-level settings and overrides
|
|
41
|
+
export function getEffectiveSettings(config, baseUrl, workspaceId, repo) {
|
|
42
|
+
// Start with empty object - no defaults
|
|
43
|
+
let effective = {};
|
|
44
|
+
// Merge top-level settings from config (which contains user's chosen defaults)
|
|
45
|
+
Object.keys(config).forEach(key => {
|
|
46
|
+
if (key !== 'overrides' && config[key] !== undefined) {
|
|
47
|
+
effective[key] = config[key];
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
if (!config.overrides) {
|
|
51
|
+
return effective;
|
|
52
|
+
}
|
|
53
|
+
// Construct override keys using the single format
|
|
54
|
+
const workspaceKey = `${baseUrl}:${workspaceId}:*`;
|
|
55
|
+
const repoKey = `${baseUrl}:${workspaceId}:${repo}`;
|
|
56
|
+
// Apply workspace-level overrides
|
|
57
|
+
if (config.overrides[workspaceKey]) {
|
|
58
|
+
Object.assign(effective, config.overrides[workspaceKey]);
|
|
59
|
+
}
|
|
60
|
+
// Apply repository-specific overrides (overrides workspace-level)
|
|
61
|
+
if (config.overrides[repoKey]) {
|
|
62
|
+
Object.assign(effective, config.overrides[repoKey]);
|
|
63
|
+
}
|
|
64
|
+
return effective;
|
|
65
|
+
}
|
package/esm/context.js
CHANGED
|
@@ -10,7 +10,7 @@ async function tryResolveWorkspace(opts) {
|
|
|
10
10
|
if (cache)
|
|
11
11
|
return { isError: false, value: cache };
|
|
12
12
|
if (opts.workspace) {
|
|
13
|
-
const e = await getWorkspaceByName(opts.workspace);
|
|
13
|
+
const e = await getWorkspaceByName(opts.workspace, opts.configDir);
|
|
14
14
|
if (!e) {
|
|
15
15
|
return {
|
|
16
16
|
isError: true,
|
|
@@ -32,8 +32,37 @@ async function tryResolveWorkspace(opts) {
|
|
|
32
32
|
export async function resolveWorkspace(opts) {
|
|
33
33
|
if (opts.baseUrl) {
|
|
34
34
|
if (opts.workspace && opts.token) {
|
|
35
|
+
const normalizedBaseUrl = new URL(opts.baseUrl).toString(); // add trailing slash if not present
|
|
36
|
+
// Try to find existing workspace profile by name, then by workspaceId + remote
|
|
37
|
+
if (opts.workspace) {
|
|
38
|
+
// Try by workspace name first
|
|
39
|
+
let existingWorkspace = await getWorkspaceByName(opts.workspace, opts.configDir);
|
|
40
|
+
// If not found by name, try to find by workspaceId + remote match
|
|
41
|
+
if (!existingWorkspace) {
|
|
42
|
+
const { allWorkspaces } = await import("./workspace.js");
|
|
43
|
+
const workspaces = await allWorkspaces(opts.configDir);
|
|
44
|
+
const matchingWorkspaces = workspaces.filter(w => w.workspaceId === opts.workspace && w.remote === normalizedBaseUrl);
|
|
45
|
+
// Due to uniqueness constraint, there can only be 0 or 1 match
|
|
46
|
+
if (matchingWorkspaces.length === 1) {
|
|
47
|
+
existingWorkspace = matchingWorkspaces[0];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (existingWorkspace) {
|
|
51
|
+
// Validate that the base URL matches the profile's remote
|
|
52
|
+
if (existingWorkspace.remote !== normalizedBaseUrl) {
|
|
53
|
+
log.info(colors.red(`Base URL mismatch: --base-url is ${normalizedBaseUrl} but workspace profile "${opts.workspace}" uses ${existingWorkspace.remote}`));
|
|
54
|
+
return dntShim.Deno.exit(-1);
|
|
55
|
+
}
|
|
56
|
+
// Use the existing workspace profile (preserves workspace name)
|
|
57
|
+
return {
|
|
58
|
+
...existingWorkspace,
|
|
59
|
+
token: opts.token, // Use the provided token
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// No existing profile found, create temporary workspace
|
|
35
64
|
return {
|
|
36
|
-
remote:
|
|
65
|
+
remote: normalizedBaseUrl,
|
|
37
66
|
workspaceId: opts.workspace,
|
|
38
67
|
name: opts.workspace,
|
|
39
68
|
token: opts.token,
|
|
@@ -63,16 +92,21 @@ export async function requireLogin(opts) {
|
|
|
63
92
|
try {
|
|
64
93
|
return await wmill.globalWhoami();
|
|
65
94
|
}
|
|
66
|
-
catch {
|
|
95
|
+
catch (error) {
|
|
96
|
+
// Check for network errors and provide clearer messages
|
|
97
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
98
|
+
if (errorMsg.includes('fetch') || errorMsg.includes('connection') || errorMsg.includes('ECONNREFUSED') || errorMsg.includes('refused')) {
|
|
99
|
+
throw new Error(`Network error: Could not connect to Windmill server at ${workspace.remote}`);
|
|
100
|
+
}
|
|
67
101
|
log.info("! Could not reach API given existing credentials. Attempting to reauth...");
|
|
68
102
|
const newToken = await loginInteractive(workspace.remote);
|
|
69
103
|
if (!newToken) {
|
|
70
|
-
throw new Error("Could not
|
|
104
|
+
throw new Error("Unauthorized: Could not authenticate with the provided credentials");
|
|
71
105
|
}
|
|
72
106
|
removeWorkspace(workspace.name, false, opts);
|
|
73
107
|
workspace.token = newToken;
|
|
74
108
|
addWorkspace(workspace, opts);
|
|
75
|
-
setClient(
|
|
109
|
+
setClient(newToken, workspace.remote.substring(0, workspace.remote.length - 1));
|
|
76
110
|
return await wmill.globalWhoami();
|
|
77
111
|
}
|
|
78
112
|
}
|
|
@@ -86,6 +120,11 @@ export async function fetchVersion(baseUrl) {
|
|
|
86
120
|
}
|
|
87
121
|
}
|
|
88
122
|
const response = await fetch(new URL(new URL(baseUrl).origin + "/api/version"), { headers: requestHeaders, method: "GET" });
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
// Consume response body even on error to avoid resource leak
|
|
125
|
+
await response.text();
|
|
126
|
+
throw new Error(`Failed to fetch version: ${response.status} ${response.statusText}`);
|
|
127
|
+
}
|
|
89
128
|
return await response.text();
|
|
90
129
|
}
|
|
91
130
|
export async function tryResolveVersion(opts) {
|
package/esm/gen/core/OpenAPI.js
CHANGED
package/esm/gen/services.gen.js
CHANGED
|
@@ -2332,6 +2332,25 @@ export const createAccount = (data) => {
|
|
|
2332
2332
|
mediaType: 'application/json'
|
|
2333
2333
|
});
|
|
2334
2334
|
};
|
|
2335
|
+
/**
|
|
2336
|
+
* connect OAuth using client credentials
|
|
2337
|
+
* @param data The data for the request.
|
|
2338
|
+
* @param data.client OAuth client name
|
|
2339
|
+
* @param data.requestBody client credentials flow parameters
|
|
2340
|
+
* @returns TokenResponse OAuth token response
|
|
2341
|
+
* @throws ApiError
|
|
2342
|
+
*/
|
|
2343
|
+
export const connectClientCredentials = (data) => {
|
|
2344
|
+
return __request(OpenAPI, {
|
|
2345
|
+
method: 'POST',
|
|
2346
|
+
url: '/oauth/connect_client_credentials/{client}',
|
|
2347
|
+
path: {
|
|
2348
|
+
client: data.client
|
|
2349
|
+
},
|
|
2350
|
+
body: data.requestBody,
|
|
2351
|
+
mediaType: 'application/json'
|
|
2352
|
+
});
|
|
2353
|
+
};
|
|
2335
2354
|
/**
|
|
2336
2355
|
* refresh token
|
|
2337
2356
|
* @param data The data for the request.
|