windmill-cli 1.720.0 → 1.721.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/main.js +178 -7
- package/package.json +1 -1
package/esm/main.js
CHANGED
|
@@ -16772,7 +16772,7 @@ var init_OpenAPI = __esm(() => {
|
|
|
16772
16772
|
PASSWORD: undefined,
|
|
16773
16773
|
TOKEN: getEnv3("WM_TOKEN"),
|
|
16774
16774
|
USERNAME: undefined,
|
|
16775
|
-
VERSION: "1.
|
|
16775
|
+
VERSION: "1.721.0",
|
|
16776
16776
|
WITH_CREDENTIALS: true,
|
|
16777
16777
|
interceptors: {
|
|
16778
16778
|
request: new Interceptors,
|
|
@@ -25304,7 +25304,7 @@ var init_auth = __esm(async () => {
|
|
|
25304
25304
|
});
|
|
25305
25305
|
|
|
25306
25306
|
// src/core/constants.ts
|
|
25307
|
-
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.
|
|
25307
|
+
var WM_FORK_PREFIX = "wm-fork", VERSION = "1.721.0";
|
|
25308
25308
|
|
|
25309
25309
|
// src/utils/git.ts
|
|
25310
25310
|
var exports_git = {};
|
|
@@ -65751,21 +65751,25 @@ var exports_sync = {};
|
|
|
65751
65751
|
__export(exports_sync, {
|
|
65752
65752
|
yamlSortedEntries: () => yamlSortedEntries,
|
|
65753
65753
|
yamlOptions: () => yamlOptions,
|
|
65754
|
+
summarizeCaseRewrites: () => summarizeCaseRewrites,
|
|
65754
65755
|
resolveWsNameForConfigFromFlags: () => resolveWsNameForConfigFromFlags,
|
|
65755
65756
|
readDirRecursiveWithIgnore: () => readDirRecursiveWithIgnore2,
|
|
65756
65757
|
push: () => push4,
|
|
65757
65758
|
pull: () => pull,
|
|
65758
65759
|
isWhitelisted: () => isWhitelisted,
|
|
65760
|
+
isCaseInsensitiveFilesystem: () => isCaseInsensitiveFilesystem,
|
|
65759
65761
|
ignoreF: () => ignoreF,
|
|
65760
65762
|
gitDeploy: () => gitDeploy,
|
|
65761
65763
|
generateDatatablesDocumentation: () => generateDatatablesDocumentation,
|
|
65762
65764
|
generateAgentsDocumentation: () => generateAgentsDocumentation,
|
|
65763
65765
|
findCodebase: () => findCodebase,
|
|
65766
|
+
findCaseInsensitiveCollisions: () => findCaseInsensitiveCollisions,
|
|
65764
65767
|
extractInlineScriptsForApps: () => extractInlineScriptsForApps,
|
|
65765
65768
|
extractFieldsForRawApps: () => extractFieldsForRawApps,
|
|
65766
65769
|
elementsToMap: () => elementsToMap,
|
|
65767
65770
|
default: () => sync_default,
|
|
65768
65771
|
computeWsSpecificFlagOnlyPushes: () => computeWsSpecificFlagOnlyPushes,
|
|
65772
|
+
canonicalizeCaseInsensitiveKeys: () => canonicalizeCaseInsensitiveKeys,
|
|
65769
65773
|
FSFSElement: () => FSFSElement
|
|
65770
65774
|
});
|
|
65771
65775
|
import { writeFile as writeFile7, readdir as readdir4, stat as stat7, rm, copyFile, mkdir as mkdir5 } from "node:fs/promises";
|
|
@@ -66930,11 +66934,178 @@ ${configHint}`);
|
|
|
66930
66934
|
}
|
|
66931
66935
|
return map;
|
|
66932
66936
|
}
|
|
66933
|
-
|
|
66934
|
-
const
|
|
66937
|
+
function findCaseInsensitiveCollisions(paths) {
|
|
66938
|
+
const byLower = new Map;
|
|
66939
|
+
for (const full of paths) {
|
|
66940
|
+
const segs = full.split(/[\\/]/).filter((s) => s.length > 0);
|
|
66941
|
+
let acc = "";
|
|
66942
|
+
for (let i = 0;i < segs.length; i++) {
|
|
66943
|
+
acc = i === 0 ? segs[i] : `${acc}/${segs[i]}`;
|
|
66944
|
+
const lower = acc.toLowerCase();
|
|
66945
|
+
let set = byLower.get(lower);
|
|
66946
|
+
if (!set) {
|
|
66947
|
+
set = new Set;
|
|
66948
|
+
byLower.set(lower, set);
|
|
66949
|
+
}
|
|
66950
|
+
set.add(acc);
|
|
66951
|
+
}
|
|
66952
|
+
}
|
|
66953
|
+
const collidingLowers = new Set;
|
|
66954
|
+
for (const [lower, set] of byLower) {
|
|
66955
|
+
if (set.size > 1)
|
|
66956
|
+
collidingLowers.add(lower);
|
|
66957
|
+
}
|
|
66958
|
+
const collisions = [];
|
|
66959
|
+
for (const lower of collidingLowers) {
|
|
66960
|
+
const parts = lower.split("/");
|
|
66961
|
+
let hasCollidingAncestor = false;
|
|
66962
|
+
for (let i = 1;i < parts.length; i++) {
|
|
66963
|
+
if (collidingLowers.has(parts.slice(0, i).join("/"))) {
|
|
66964
|
+
hasCollidingAncestor = true;
|
|
66965
|
+
break;
|
|
66966
|
+
}
|
|
66967
|
+
}
|
|
66968
|
+
if (!hasCollidingAncestor) {
|
|
66969
|
+
collisions.push([...byLower.get(lower)].sort());
|
|
66970
|
+
}
|
|
66971
|
+
}
|
|
66972
|
+
return collisions;
|
|
66973
|
+
}
|
|
66974
|
+
function canonicalizeCaseInsensitiveKeys(localMap, remoteMap) {
|
|
66975
|
+
const root = { children: new Map };
|
|
66976
|
+
for (const k of Object.keys(remoteMap)) {
|
|
66977
|
+
let node = root;
|
|
66978
|
+
for (const seg of k.split(/[\\/]/)) {
|
|
66979
|
+
if (seg.length === 0)
|
|
66980
|
+
continue;
|
|
66981
|
+
const lk = seg.toLowerCase();
|
|
66982
|
+
let entry = node.children.get(lk);
|
|
66983
|
+
if (!entry) {
|
|
66984
|
+
entry = { canonical: seg, ambiguous: false, node: { children: new Map } };
|
|
66985
|
+
node.children.set(lk, entry);
|
|
66986
|
+
} else if (entry.canonical !== seg) {
|
|
66987
|
+
entry.ambiguous = true;
|
|
66988
|
+
}
|
|
66989
|
+
node = entry.node;
|
|
66990
|
+
}
|
|
66991
|
+
}
|
|
66992
|
+
const out = {};
|
|
66993
|
+
const rewritten = [];
|
|
66994
|
+
for (const [k, v] of Object.entries(localMap)) {
|
|
66995
|
+
const sep3 = k.includes("\\") ? "\\" : "/";
|
|
66996
|
+
const segs = k.split(/[\\/]/);
|
|
66997
|
+
const canonSegs = [];
|
|
66998
|
+
let node = root;
|
|
66999
|
+
let changed = false;
|
|
67000
|
+
for (const seg of segs) {
|
|
67001
|
+
if (seg.length === 0) {
|
|
67002
|
+
canonSegs.push(seg);
|
|
67003
|
+
continue;
|
|
67004
|
+
}
|
|
67005
|
+
const entry = node?.children.get(seg.toLowerCase());
|
|
67006
|
+
if (entry && !entry.ambiguous) {
|
|
67007
|
+
if (entry.canonical !== seg)
|
|
67008
|
+
changed = true;
|
|
67009
|
+
canonSegs.push(entry.canonical);
|
|
67010
|
+
node = entry.node;
|
|
67011
|
+
} else {
|
|
67012
|
+
canonSegs.push(seg);
|
|
67013
|
+
node = undefined;
|
|
67014
|
+
}
|
|
67015
|
+
}
|
|
67016
|
+
const canonKey = canonSegs.join(sep3);
|
|
67017
|
+
if (changed && canonKey !== k) {
|
|
67018
|
+
out[canonKey] = v;
|
|
67019
|
+
rewritten.push({ from: k, to: canonKey });
|
|
67020
|
+
} else {
|
|
67021
|
+
out[k] = v;
|
|
67022
|
+
}
|
|
67023
|
+
}
|
|
67024
|
+
return {
|
|
67025
|
+
map: out,
|
|
67026
|
+
ambiguous: findCaseInsensitiveCollisions(Object.keys(remoteMap)),
|
|
67027
|
+
rewritten
|
|
67028
|
+
};
|
|
67029
|
+
}
|
|
67030
|
+
function summarizeCaseRewrites(rewritten) {
|
|
67031
|
+
const seen = new Set;
|
|
67032
|
+
const out = [];
|
|
67033
|
+
for (const { from, to } of rewritten) {
|
|
67034
|
+
const fromSegs = from.split(/[\\/]/);
|
|
67035
|
+
const toSegs = to.split(/[\\/]/);
|
|
67036
|
+
let i = 0;
|
|
67037
|
+
while (i < fromSegs.length && i < toSegs.length && fromSegs[i] === toSegs[i]) {
|
|
67038
|
+
i++;
|
|
67039
|
+
}
|
|
67040
|
+
const fromPrefix = fromSegs.slice(0, i + 1).join("/");
|
|
67041
|
+
const toPrefix = toSegs.slice(0, i + 1).join("/");
|
|
67042
|
+
const key = `${fromPrefix} -> ${toPrefix}`;
|
|
67043
|
+
if (!seen.has(key)) {
|
|
67044
|
+
seen.add(key);
|
|
67045
|
+
out.push(key);
|
|
67046
|
+
}
|
|
67047
|
+
}
|
|
67048
|
+
return out;
|
|
67049
|
+
}
|
|
67050
|
+
function warnUnrepresentableCaseCollisions(collisions) {
|
|
67051
|
+
if (collisions.length === 0)
|
|
67052
|
+
return;
|
|
67053
|
+
const groups = collisions.map((g) => ` - ${g.join(" <-> ")}`).join(`
|
|
67054
|
+
`);
|
|
67055
|
+
warn(`Found ${collisions.length} path(s) that differ only by letter case:
|
|
67056
|
+
` + `${groups}
|
|
67057
|
+
` + `On case-insensitive filesystems (Windows, default macOS) these collapse ` + `into a single file/directory and cannot both be synced. Rename one side ` + `to a distinct path to make the tree sync reliably across platforms.`);
|
|
67058
|
+
}
|
|
67059
|
+
async function isCaseInsensitiveFilesystem(dir) {
|
|
67060
|
+
const override = (process.env.WMILL_CASE_INSENSITIVE_FS ?? "").trim().toLowerCase();
|
|
67061
|
+
if (override === "true" || override === "1")
|
|
67062
|
+
return true;
|
|
67063
|
+
if (override === "false" || override === "0")
|
|
67064
|
+
return false;
|
|
67065
|
+
if (_caseInsensitiveFsCache !== undefined)
|
|
67066
|
+
return _caseInsensitiveFsCache;
|
|
67067
|
+
let result = false;
|
|
67068
|
+
try {
|
|
67069
|
+
const upper = path10.join(dir, `.wmill-CASEPROBE-${process.pid}.tmp`);
|
|
67070
|
+
const lower = path10.join(dir, `.wmill-caseprobe-${process.pid}.tmp`);
|
|
67071
|
+
await writeFile7(upper, "", "utf-8");
|
|
67072
|
+
try {
|
|
67073
|
+
await stat7(lower);
|
|
67074
|
+
result = true;
|
|
67075
|
+
} catch {
|
|
67076
|
+
result = false;
|
|
67077
|
+
}
|
|
67078
|
+
await rm(upper).catch(() => {});
|
|
67079
|
+
await rm(lower).catch(() => {});
|
|
67080
|
+
} catch {
|
|
67081
|
+
result = false;
|
|
67082
|
+
}
|
|
67083
|
+
_caseInsensitiveFsCache = result;
|
|
67084
|
+
return result;
|
|
67085
|
+
}
|
|
67086
|
+
async function compareDynFSElement(els1, els2, ignore, json, skips, ignoreMetadataDeletion, codebases, ignoreCodebaseChanges, specificItems, branchOverride, isEls1Remote, caseInsensitiveFs) {
|
|
67087
|
+
let [m1, m2] = els2 ? await Promise.all([
|
|
66935
67088
|
elementsToMap(els1, ignore, json, skips, specificItems, branchOverride, isEls1Remote),
|
|
66936
67089
|
elementsToMap(els2, ignore, json, skips, specificItems, branchOverride, !isEls1Remote)
|
|
66937
67090
|
]) : [await elementsToMap(els1, ignore, json, skips, specificItems, branchOverride, isEls1Remote), {}];
|
|
67091
|
+
if (els2 && isEls1Remote !== undefined) {
|
|
67092
|
+
const remoteMap = isEls1Remote ? m1 : m2;
|
|
67093
|
+
warnUnrepresentableCaseCollisions(findCaseInsensitiveCollisions(Object.keys(remoteMap)));
|
|
67094
|
+
if (caseInsensitiveFs) {
|
|
67095
|
+
const { map, rewritten } = canonicalizeCaseInsensitiveKeys(isEls1Remote ? m2 : m1, remoteMap);
|
|
67096
|
+
if (isEls1Remote) {
|
|
67097
|
+
m2 = map;
|
|
67098
|
+
} else {
|
|
67099
|
+
m1 = map;
|
|
67100
|
+
}
|
|
67101
|
+
const summary = summarizeCaseRewrites(rewritten);
|
|
67102
|
+
if (summary.length > 0) {
|
|
67103
|
+
info(`Reconciled ${summary.length} local path(s) to the server's casing ` + `(case-insensitive filesystem):
|
|
67104
|
+
` + summary.map((s) => ` ${s}`).join(`
|
|
67105
|
+
`));
|
|
67106
|
+
}
|
|
67107
|
+
}
|
|
67108
|
+
}
|
|
66938
67109
|
const changes = [];
|
|
66939
67110
|
function parseYaml(k, v) {
|
|
66940
67111
|
if (k.endsWith(".script.yaml")) {
|
|
@@ -67374,7 +67545,7 @@ async function pull(opts) {
|
|
|
67374
67545
|
const zipFile = await downloadZip(workspace, opts.plainSecrets, opts.skipVariables, opts.skipResources, opts.skipResourceTypes, opts.skipSecrets, opts.includeSchedules, opts.includeTriggers, opts.includeUsers, opts.includeGroups, opts.includeSettings, opts.includeKey, opts.skipWorkspaceDependencies, opts.defaultTs);
|
|
67375
67546
|
const remote = ZipFSElement(zipFile, !opts.json, opts.defaultTs ?? "bun", resourceTypeToFormatExtension, resourceTypeToIsFileset, true, parseSyncBehavior(opts.syncBehavior) >= 1);
|
|
67376
67547
|
const local = !opts.stateful ? await FSFSElement(process.cwd(), codebases, true) : await FSFSElement(path10.join(process.cwd(), ".wmill"), [], true);
|
|
67377
|
-
const { changes, localMap } = await compareDynFSElement(remote, local, await ignoreF(opts), opts.json ?? false, opts, false, codebases, true, specificItems, wsNameForFiles, true);
|
|
67548
|
+
const { changes, localMap } = await compareDynFSElement(remote, local, await ignoreF(opts), opts.json ?? false, opts, false, codebases, true, specificItems, wsNameForFiles, true, await isCaseInsensitiveFilesystem(process.cwd()));
|
|
67378
67549
|
info(`remote (${workspace.name}) -> local: ${changes.length} changes to apply`);
|
|
67379
67550
|
if (wsSpecificMerge.serverItems && wsSpecificMerge.serverItems.length > 0) {
|
|
67380
67551
|
const changedPaths = new Set(changes.map((c) => c.path));
|
|
@@ -67737,7 +67908,7 @@ Push aborted: ${lockIssues.length} script(s) missing locks.`));
|
|
|
67737
67908
|
} catch {}
|
|
67738
67909
|
const remote = ZipFSElement(await downloadZip(workspace, opts.plainSecrets, opts.skipVariables, opts.skipResources, opts.skipResourceTypes, opts.skipSecrets, opts.includeSchedules, opts.includeTriggers, opts.includeUsers, opts.includeGroups, opts.includeSettings, opts.includeKey, opts.skipWorkspaceDependencies, opts.defaultTs), !opts.json, opts.defaultTs ?? "bun", resourceTypeToFormatExtension, resourceTypeToIsFileset, false, parseSyncBehavior(opts.syncBehavior) >= 1);
|
|
67739
67910
|
const local = await FSFSElement(path10.join(process.cwd(), ""), codebases, false);
|
|
67740
|
-
const { changes, localMap } = await compareDynFSElement(local, remote, await ignoreF(opts), opts.json ?? false, opts, true, codebases, false, specificItems, wsNameForFiles, false);
|
|
67911
|
+
const { changes, localMap } = await compareDynFSElement(local, remote, await ignoreF(opts), opts.json ?? false, opts, true, codebases, false, specificItems, wsNameForFiles, false, await isCaseInsensitiveFilesystem(process.cwd()));
|
|
67741
67912
|
const wsSpecificFlagOnly = computeWsSpecificFlagOnlyPushes(localMap, localSpecificItems, serverWsSpecificItems);
|
|
67742
67913
|
for (const item of wsSpecificFlagOnly) {
|
|
67743
67914
|
if (changes.some((c) => c.path === item.filePath))
|
|
@@ -68523,7 +68694,7 @@ Done! All ${changes.length} changes pushed to the remote workspace ${workspace.w
|
|
|
68523
68694
|
}
|
|
68524
68695
|
}
|
|
68525
68696
|
}
|
|
68526
|
-
var import_yaml11, branchDeprecationWarned = false, yamlOptions, isNotWmillFile = (p, isDirectory2) => {
|
|
68697
|
+
var import_yaml11, branchDeprecationWarned = false, yamlOptions, _caseInsensitiveFsCache, isNotWmillFile = (p, isDirectory2) => {
|
|
68527
68698
|
if (p.endsWith(SEP9)) {
|
|
68528
68699
|
return false;
|
|
68529
68700
|
}
|