windmill-cli 1.516.0 → 1.518.1
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/dev.js +2 -2
- package/esm/flow.js +2 -44
- package/esm/gen/core/OpenAPI.js +1 -1
- package/esm/main.js +6 -5
- package/esm/metadata.js +39 -226
- package/esm/sync.js +107 -126
- package/esm/windmill-utils-internal/src/gen/types.gen.js +2 -0
- package/esm/windmill-utils-internal/src/inline-scripts/extractor.js +79 -0
- package/esm/windmill-utils-internal/src/inline-scripts/replacer.js +92 -0
- package/esm/windmill-utils-internal/src/parse/parse-schema.js +202 -0
- package/esm/windmill-utils-internal/src/path-utils/path-assigner.js +55 -0
- package/package.json +1 -1
- package/types/dev.d.ts.map +1 -1
- package/types/flow.d.ts +0 -2
- package/types/flow.d.ts.map +1 -1
- package/types/main.d.ts +1 -1
- package/types/main.d.ts.map +1 -1
- package/types/metadata.d.ts +1 -44
- package/types/metadata.d.ts.map +1 -1
- package/types/sync.d.ts +4 -6
- package/types/sync.d.ts.map +1 -1
- package/types/windmill-utils-internal/src/gen/types.gen.d.ts +7320 -0
- package/types/windmill-utils-internal/src/gen/types.gen.d.ts.map +1 -0
- package/types/windmill-utils-internal/src/inline-scripts/extractor.d.ts +34 -0
- package/types/windmill-utils-internal/src/inline-scripts/extractor.d.ts.map +1 -0
- package/types/windmill-utils-internal/src/inline-scripts/replacer.d.ts +17 -0
- package/types/windmill-utils-internal/src/inline-scripts/replacer.d.ts.map +1 -0
- package/types/windmill-utils-internal/src/parse/parse-schema.d.ts +94 -0
- package/types/windmill-utils-internal/src/parse/parse-schema.d.ts.map +1 -0
- package/types/windmill-utils-internal/src/path-utils/path-assigner.d.ts +29 -0
- package/types/windmill-utils-internal/src/path-utils/path-assigner.d.ts.map +1 -0
package/esm/sync.js
CHANGED
|
@@ -13,6 +13,7 @@ import { removePathPrefix } from "./types.js";
|
|
|
13
13
|
import { listSyncCodebases } from "./codebase.js";
|
|
14
14
|
import { generateFlowLockInternal, generateScriptMetadataInternal, readLockfile, } from "./metadata.js";
|
|
15
15
|
import { pushResource } from "./resource.js";
|
|
16
|
+
import { extractInlineScripts as extractInlineScriptsForFlows } from "./windmill-utils-internal/src/inline-scripts/extractor.js";
|
|
16
17
|
// Merge CLI options with effective settings, preserving CLI flags as overrides
|
|
17
18
|
function mergeCliWithEffectiveOptions(cliOpts, effectiveOpts) {
|
|
18
19
|
// overlay CLI options on top (undefined cliOpts won't override effectiveOpts)
|
|
@@ -31,7 +32,7 @@ async function resolveEffectiveSyncOptions(workspace, repositoryPath) {
|
|
|
31
32
|
const applicableRepos = [];
|
|
32
33
|
// Find all repository-specific overrides for this workspace
|
|
33
34
|
for (const key of Object.keys(localConfig.overrides)) {
|
|
34
|
-
if (key.startsWith(prefix) && !key.endsWith(
|
|
35
|
+
if (key.startsWith(prefix) && !key.endsWith(":*")) {
|
|
35
36
|
const repo = key.substring(prefix.length);
|
|
36
37
|
if (repo) {
|
|
37
38
|
applicableRepos.push(repo);
|
|
@@ -48,12 +49,15 @@ async function resolveEffectiveSyncOptions(workspace, repositoryPath) {
|
|
|
48
49
|
const isInteractive = dntShim.Deno.stdin.isTerminal() && dntShim.Deno.stdout.isTerminal();
|
|
49
50
|
if (isInteractive) {
|
|
50
51
|
const choices = [
|
|
51
|
-
{
|
|
52
|
-
|
|
52
|
+
{
|
|
53
|
+
name: "Use top-level settings (no repository-specific override)",
|
|
54
|
+
value: "",
|
|
55
|
+
},
|
|
56
|
+
...applicableRepos.map((repo) => ({ name: repo, value: repo })),
|
|
53
57
|
];
|
|
54
58
|
const selectedRepo = await Select.prompt({
|
|
55
59
|
message: "Multiple repository overrides found. Select which to use:",
|
|
56
|
-
options: choices
|
|
60
|
+
options: choices,
|
|
57
61
|
});
|
|
58
62
|
if (selectedRepo) {
|
|
59
63
|
log.info(`Selected repository: ${selectedRepo}`);
|
|
@@ -62,7 +66,7 @@ async function resolveEffectiveSyncOptions(workspace, repositoryPath) {
|
|
|
62
66
|
}
|
|
63
67
|
else {
|
|
64
68
|
// Non-interactive mode - list options and use top-level
|
|
65
|
-
log.warn(`Multiple repository overrides found: ${applicableRepos.join(
|
|
69
|
+
log.warn(`Multiple repository overrides found: ${applicableRepos.join(", ")}`);
|
|
66
70
|
log.warn(`Running in non-interactive mode. Use --repository flag to specify which one to use.`);
|
|
67
71
|
log.info(`Falling back to top-level settings (no repository-specific overrides applied)`);
|
|
68
72
|
}
|
|
@@ -174,6 +178,8 @@ export async function FSFSElement(p, codebases, ignoreCodebaseChanges) {
|
|
|
174
178
|
return _internal_element(p, (await dntShim.Deno.stat(p)).isDirectory, codebases);
|
|
175
179
|
}
|
|
176
180
|
function prioritizeName(name) {
|
|
181
|
+
if (name == "version")
|
|
182
|
+
return "aaa";
|
|
177
183
|
if (name == "id")
|
|
178
184
|
return "aa";
|
|
179
185
|
if (name == "type")
|
|
@@ -198,6 +204,8 @@ function prioritizeName(name) {
|
|
|
198
204
|
return "al";
|
|
199
205
|
if (name == "lock")
|
|
200
206
|
return "az";
|
|
207
|
+
if (name == "locks")
|
|
208
|
+
return "azz";
|
|
201
209
|
return name;
|
|
202
210
|
}
|
|
203
211
|
export const yamlOptions = {
|
|
@@ -208,43 +216,6 @@ export const yamlOptions = {
|
|
|
208
216
|
noRefs: true,
|
|
209
217
|
skipInvalid: true,
|
|
210
218
|
};
|
|
211
|
-
export function extractInlineScriptsForFlows(modules, pathAssigner) {
|
|
212
|
-
return modules.flatMap((m) => {
|
|
213
|
-
if (m.value.type == "rawscript") {
|
|
214
|
-
const [basePath, ext] = pathAssigner.assignPath(m.summary, m.value.language);
|
|
215
|
-
const path = basePath + ext;
|
|
216
|
-
const content = m.value.content;
|
|
217
|
-
const r = [{ path: path, content: content }];
|
|
218
|
-
m.value.content = "!inline " + path.replaceAll(SEP, "/");
|
|
219
|
-
const lock = m.value.lock;
|
|
220
|
-
if (lock && lock != "") {
|
|
221
|
-
const lockPath = basePath + "lock";
|
|
222
|
-
m.value.lock = "!inline " + lockPath.replaceAll(SEP, "/");
|
|
223
|
-
r.push({ path: lockPath, content: lock });
|
|
224
|
-
}
|
|
225
|
-
return r;
|
|
226
|
-
}
|
|
227
|
-
else if (m.value.type == "forloopflow") {
|
|
228
|
-
return extractInlineScriptsForFlows(m.value.modules, pathAssigner);
|
|
229
|
-
}
|
|
230
|
-
else if (m.value.type == "branchall") {
|
|
231
|
-
return m.value.branches.flatMap((b) => extractInlineScriptsForFlows(b.modules, pathAssigner));
|
|
232
|
-
}
|
|
233
|
-
else if (m.value.type == "whileloopflow") {
|
|
234
|
-
return extractInlineScriptsForFlows(m.value.modules, pathAssigner);
|
|
235
|
-
}
|
|
236
|
-
else if (m.value.type == "branchone") {
|
|
237
|
-
return [
|
|
238
|
-
...m.value.branches.flatMap((b) => extractInlineScriptsForFlows(b.modules, pathAssigner)),
|
|
239
|
-
...extractInlineScriptsForFlows(m.value.default, pathAssigner),
|
|
240
|
-
];
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
return [];
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
const INLINE_SCRIPT = "inline_script";
|
|
248
219
|
export function extractInlineScriptsForApps(rec, pathAssigner) {
|
|
249
220
|
if (!rec) {
|
|
250
221
|
return [];
|
|
@@ -281,76 +252,6 @@ export function extractInlineScriptsForApps(rec, pathAssigner) {
|
|
|
281
252
|
}
|
|
282
253
|
return [];
|
|
283
254
|
}
|
|
284
|
-
export function newPathAssigner(defaultTs) {
|
|
285
|
-
let counter = 0;
|
|
286
|
-
const seen_names = new Set();
|
|
287
|
-
function assignPath(summary, language) {
|
|
288
|
-
let name;
|
|
289
|
-
name = summary?.toLowerCase()?.replaceAll(" ", "_") ?? "";
|
|
290
|
-
let original_name = name;
|
|
291
|
-
if (name == "") {
|
|
292
|
-
original_name = INLINE_SCRIPT;
|
|
293
|
-
name = `${INLINE_SCRIPT}_0`;
|
|
294
|
-
}
|
|
295
|
-
while (seen_names.has(name)) {
|
|
296
|
-
counter++;
|
|
297
|
-
name = `${original_name}_${counter}`;
|
|
298
|
-
}
|
|
299
|
-
seen_names.add(name);
|
|
300
|
-
let ext;
|
|
301
|
-
if (language == "python3")
|
|
302
|
-
ext = "py";
|
|
303
|
-
else if (language == defaultTs || language == "bunnative")
|
|
304
|
-
ext = "ts";
|
|
305
|
-
else if (language == "bun")
|
|
306
|
-
ext = "bun.ts";
|
|
307
|
-
else if (language == "deno")
|
|
308
|
-
ext = "deno.ts";
|
|
309
|
-
else if (language == "go")
|
|
310
|
-
ext = "go";
|
|
311
|
-
else if (language == "bash")
|
|
312
|
-
ext = "sh";
|
|
313
|
-
else if (language == "powershell")
|
|
314
|
-
ext = "ps1";
|
|
315
|
-
else if (language == "postgresql")
|
|
316
|
-
ext = "pg.sql";
|
|
317
|
-
else if (language == "mysql")
|
|
318
|
-
ext = "my.sql";
|
|
319
|
-
else if (language == "bigquery")
|
|
320
|
-
ext = "bq.sql";
|
|
321
|
-
else if (language == "oracledb")
|
|
322
|
-
ext = "odb.sql";
|
|
323
|
-
else if (language == "snowflake")
|
|
324
|
-
ext = "sf.sql";
|
|
325
|
-
else if (language == "mssql")
|
|
326
|
-
ext = "ms.sql";
|
|
327
|
-
else if (language == "graphql")
|
|
328
|
-
ext = "gql";
|
|
329
|
-
else if (language == "nativets")
|
|
330
|
-
ext = "native.ts";
|
|
331
|
-
else if (language == "frontend")
|
|
332
|
-
ext = "frontend.js";
|
|
333
|
-
else if (language == "php")
|
|
334
|
-
ext = "php";
|
|
335
|
-
else if (language == "rust")
|
|
336
|
-
ext = "rs";
|
|
337
|
-
else if (language == "csharp")
|
|
338
|
-
ext = "cs";
|
|
339
|
-
else if (language == "nu")
|
|
340
|
-
ext = "nu";
|
|
341
|
-
else if (language == "ansible")
|
|
342
|
-
ext = "playbook.yml";
|
|
343
|
-
else if (language == "java")
|
|
344
|
-
ext = "java";
|
|
345
|
-
else if (language == "duckdb")
|
|
346
|
-
ext = "duckdb.sql";
|
|
347
|
-
// for related places search: ADD_NEW_LANG
|
|
348
|
-
else
|
|
349
|
-
ext = "no_ext";
|
|
350
|
-
return [`${name}.inline_script.`, ext];
|
|
351
|
-
}
|
|
352
|
-
return { assignPath };
|
|
353
|
-
}
|
|
354
255
|
function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, ignoreCodebaseChanges) {
|
|
355
256
|
async function _internal_file(p, f) {
|
|
356
257
|
const kind = p.endsWith("flow.json")
|
|
@@ -382,7 +283,7 @@ function ZipFSElement(zip, useYaml, defaultTs, resourceTypeToFormatExtension, ig
|
|
|
382
283
|
async *getChildren() {
|
|
383
284
|
if (kind == "flow") {
|
|
384
285
|
const flow = JSON.parse(await f.async("text"));
|
|
385
|
-
const inlineScripts = extractInlineScriptsForFlows(flow.value.modules, newPathAssigner(defaultTs));
|
|
286
|
+
const inlineScripts = extractInlineScriptsForFlows(flow.value.modules, {}, SEP, defaultTs, newPathAssigner(defaultTs));
|
|
386
287
|
for (const s of inlineScripts) {
|
|
387
288
|
yield {
|
|
388
289
|
isDirectory: false,
|
|
@@ -921,7 +822,8 @@ export async function ignoreF(wmillconf) {
|
|
|
921
822
|
wmillconf.includes?.some((i) => minimatch(file, i))) &&
|
|
922
823
|
(!wmillconf?.excludes ||
|
|
923
824
|
wmillconf.excludes.every((i) => !minimatch(file, i))) &&
|
|
924
|
-
(!wmillconf.extraIncludes ||
|
|
825
|
+
(!wmillconf.extraIncludes ||
|
|
826
|
+
wmillconf.extraIncludes.length === 0 ||
|
|
925
827
|
wmillconf.extraIncludes.some((i) => minimatch(file, i))));
|
|
926
828
|
},
|
|
927
829
|
};
|
|
@@ -1045,12 +947,14 @@ export async function pull(opts) {
|
|
|
1045
947
|
if (opts.dryRun && opts.jsonOutput) {
|
|
1046
948
|
const result = {
|
|
1047
949
|
success: true,
|
|
1048
|
-
changes: changes.map(change => ({
|
|
950
|
+
changes: changes.map((change) => ({
|
|
1049
951
|
type: change.name,
|
|
1050
952
|
path: change.path,
|
|
1051
|
-
...(change.name === "edited" && change.codebase
|
|
953
|
+
...(change.name === "edited" && change.codebase
|
|
954
|
+
? { codebase_changed: true }
|
|
955
|
+
: {}),
|
|
1052
956
|
})),
|
|
1053
|
-
total: changes.length
|
|
957
|
+
total: changes.length,
|
|
1054
958
|
};
|
|
1055
959
|
console.log(JSON.stringify(result, null, 2));
|
|
1056
960
|
return;
|
|
@@ -1177,12 +1081,14 @@ export async function pull(opts) {
|
|
|
1177
1081
|
const result = {
|
|
1178
1082
|
success: true,
|
|
1179
1083
|
message: `All ${changes.length} changes applied locally and wmill-lock.yaml updated`,
|
|
1180
|
-
changes: changes.map(change => ({
|
|
1084
|
+
changes: changes.map((change) => ({
|
|
1181
1085
|
type: change.name,
|
|
1182
1086
|
path: change.path,
|
|
1183
|
-
...(change.name === "edited" && change.codebase
|
|
1087
|
+
...(change.name === "edited" && change.codebase
|
|
1088
|
+
? { codebase_changed: true }
|
|
1089
|
+
: {}),
|
|
1184
1090
|
})),
|
|
1185
|
-
total: changes.length
|
|
1091
|
+
total: changes.length,
|
|
1186
1092
|
};
|
|
1187
1093
|
console.log(JSON.stringify(result, null, 2));
|
|
1188
1094
|
}
|
|
@@ -1306,12 +1212,14 @@ export async function push(opts) {
|
|
|
1306
1212
|
if (opts.dryRun && opts.jsonOutput) {
|
|
1307
1213
|
const result = {
|
|
1308
1214
|
success: true,
|
|
1309
|
-
changes: changes.map(change => ({
|
|
1215
|
+
changes: changes.map((change) => ({
|
|
1310
1216
|
type: change.name,
|
|
1311
1217
|
path: change.path,
|
|
1312
|
-
...(change.name === "edited" && change.codebase
|
|
1218
|
+
...(change.name === "edited" && change.codebase
|
|
1219
|
+
? { codebase_changed: true }
|
|
1220
|
+
: {}),
|
|
1313
1221
|
})),
|
|
1314
|
-
total: changes.length
|
|
1222
|
+
total: changes.length,
|
|
1315
1223
|
};
|
|
1316
1224
|
console.log(JSON.stringify(result, null, 2));
|
|
1317
1225
|
return;
|
|
@@ -1599,13 +1507,15 @@ export async function push(opts) {
|
|
|
1599
1507
|
const result = {
|
|
1600
1508
|
success: true,
|
|
1601
1509
|
message: `All ${changes.length} changes pushed to the remote workspace ${workspace.workspaceId} named ${workspace.name}`,
|
|
1602
|
-
changes: changes.map(change => ({
|
|
1510
|
+
changes: changes.map((change) => ({
|
|
1603
1511
|
type: change.name,
|
|
1604
1512
|
path: change.path,
|
|
1605
|
-
...(change.name === "edited" && change.codebase
|
|
1513
|
+
...(change.name === "edited" && change.codebase
|
|
1514
|
+
? { codebase_changed: true }
|
|
1515
|
+
: {}),
|
|
1606
1516
|
})),
|
|
1607
1517
|
total: changes.length,
|
|
1608
|
-
duration_ms: Math.round(performance.now() - start)
|
|
1518
|
+
duration_ms: Math.round(performance.now() - start),
|
|
1609
1519
|
};
|
|
1610
1520
|
console.log(JSON.stringify(result, null, 2));
|
|
1611
1521
|
}
|
|
@@ -1678,4 +1588,75 @@ const command = new Command()
|
|
|
1678
1588
|
.option("--repository <repo:string>", "Specify repository path (e.g., u/user/repo) when multiple repositories exist")
|
|
1679
1589
|
// deno-lint-ignore no-explicit-any
|
|
1680
1590
|
.action(push);
|
|
1591
|
+
const INLINE_SCRIPT = "inline_script";
|
|
1592
|
+
export function newPathAssigner(defaultTs) {
|
|
1593
|
+
let counter = 0;
|
|
1594
|
+
const seen_names = new Set();
|
|
1595
|
+
function assignPath(summary, language) {
|
|
1596
|
+
let name;
|
|
1597
|
+
name = summary?.toLowerCase()?.replaceAll(" ", "_") ?? "";
|
|
1598
|
+
let original_name = name;
|
|
1599
|
+
if (name == "") {
|
|
1600
|
+
original_name = INLINE_SCRIPT;
|
|
1601
|
+
name = `${INLINE_SCRIPT}_0`;
|
|
1602
|
+
}
|
|
1603
|
+
while (seen_names.has(name)) {
|
|
1604
|
+
counter++;
|
|
1605
|
+
name = `${original_name}_${counter}`;
|
|
1606
|
+
}
|
|
1607
|
+
seen_names.add(name);
|
|
1608
|
+
let ext;
|
|
1609
|
+
if (language == "python3")
|
|
1610
|
+
ext = "py";
|
|
1611
|
+
else if (language == defaultTs || language == "bunnative")
|
|
1612
|
+
ext = "ts";
|
|
1613
|
+
else if (language == "bun")
|
|
1614
|
+
ext = "bun.ts";
|
|
1615
|
+
else if (language == "deno")
|
|
1616
|
+
ext = "deno.ts";
|
|
1617
|
+
else if (language == "go")
|
|
1618
|
+
ext = "go";
|
|
1619
|
+
else if (language == "bash")
|
|
1620
|
+
ext = "sh";
|
|
1621
|
+
else if (language == "powershell")
|
|
1622
|
+
ext = "ps1";
|
|
1623
|
+
else if (language == "postgresql")
|
|
1624
|
+
ext = "pg.sql";
|
|
1625
|
+
else if (language == "mysql")
|
|
1626
|
+
ext = "my.sql";
|
|
1627
|
+
else if (language == "bigquery")
|
|
1628
|
+
ext = "bq.sql";
|
|
1629
|
+
else if (language == "oracledb")
|
|
1630
|
+
ext = "odb.sql";
|
|
1631
|
+
else if (language == "snowflake")
|
|
1632
|
+
ext = "sf.sql";
|
|
1633
|
+
else if (language == "mssql")
|
|
1634
|
+
ext = "ms.sql";
|
|
1635
|
+
else if (language == "graphql")
|
|
1636
|
+
ext = "gql";
|
|
1637
|
+
else if (language == "nativets")
|
|
1638
|
+
ext = "native.ts";
|
|
1639
|
+
else if (language == "frontend")
|
|
1640
|
+
ext = "frontend.js";
|
|
1641
|
+
else if (language == "php")
|
|
1642
|
+
ext = "php";
|
|
1643
|
+
else if (language == "rust")
|
|
1644
|
+
ext = "rs";
|
|
1645
|
+
else if (language == "csharp")
|
|
1646
|
+
ext = "cs";
|
|
1647
|
+
else if (language == "nu")
|
|
1648
|
+
ext = "nu";
|
|
1649
|
+
else if (language == "ansible")
|
|
1650
|
+
ext = "playbook.yml";
|
|
1651
|
+
else if (language == "java")
|
|
1652
|
+
ext = "java";
|
|
1653
|
+
else if (language == "duckdb")
|
|
1654
|
+
ext = "duckdb.sql";
|
|
1655
|
+
// for related places search: ADD_NEW_LANG
|
|
1656
|
+
else
|
|
1657
|
+
ext = "no_ext";
|
|
1658
|
+
return [`${name}.inline_script.`, ext];
|
|
1659
|
+
}
|
|
1660
|
+
return { assignPath };
|
|
1661
|
+
}
|
|
1681
1662
|
export default command;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { assignPath } from "../path-utils/path-assigner.js";
|
|
2
|
+
const INLINE_SCRIPT = "inline_script";
|
|
3
|
+
export function extractInlineScripts(modules, mapping = {}, separator = "/", defaultTs, pathAssigner) {
|
|
4
|
+
return modules.flatMap((m) => {
|
|
5
|
+
if (m.value.type == "rawscript") {
|
|
6
|
+
let basePath, ext;
|
|
7
|
+
if (pathAssigner) {
|
|
8
|
+
[basePath, ext] = pathAssigner.assignPath(m.summary, m.value.language);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
[basePath, ext] = assignPath(m.id, m.value.language, defaultTs);
|
|
12
|
+
}
|
|
13
|
+
const path = mapping[m.id] ?? basePath + ext;
|
|
14
|
+
const content = m.value.content;
|
|
15
|
+
const r = [{ path: path, content: content }];
|
|
16
|
+
m.value.content = "!inline " + path.replaceAll(separator, "/");
|
|
17
|
+
const lock = m.value.lock;
|
|
18
|
+
if (lock && lock != "") {
|
|
19
|
+
const lockPath = basePath + "lock";
|
|
20
|
+
m.value.lock = "!inline " + lockPath.replaceAll(separator, "/");
|
|
21
|
+
r.push({ path: lockPath, content: lock });
|
|
22
|
+
}
|
|
23
|
+
return r;
|
|
24
|
+
}
|
|
25
|
+
else if (m.value.type == "forloopflow") {
|
|
26
|
+
return extractInlineScripts(m.value.modules, mapping, separator, defaultTs);
|
|
27
|
+
}
|
|
28
|
+
else if (m.value.type == "branchall") {
|
|
29
|
+
return m.value.branches.flatMap((b) => extractInlineScripts(b.modules, mapping, separator, defaultTs));
|
|
30
|
+
}
|
|
31
|
+
else if (m.value.type == "whileloopflow") {
|
|
32
|
+
return extractInlineScripts(m.value.modules, mapping, separator, defaultTs);
|
|
33
|
+
}
|
|
34
|
+
else if (m.value.type == "branchone") {
|
|
35
|
+
return [
|
|
36
|
+
...m.value.branches.flatMap((b) => extractInlineScripts(b.modules, mapping, separator, defaultTs)),
|
|
37
|
+
...extractInlineScripts(m.value.default, mapping, separator, defaultTs),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Extracts the current mapping of module IDs to file paths from flow modules
|
|
47
|
+
* by analyzing existing inline script references.
|
|
48
|
+
*
|
|
49
|
+
* @param modules - Array of flow modules to analyze (can be undefined)
|
|
50
|
+
* @param mapping - Existing mapping to extend (defaults to empty object)
|
|
51
|
+
* @returns Record mapping module IDs to their corresponding file paths
|
|
52
|
+
*/
|
|
53
|
+
export function extractCurrentMapping(modules, mapping = {}) {
|
|
54
|
+
if (!modules || !Array.isArray(modules)) {
|
|
55
|
+
return mapping;
|
|
56
|
+
}
|
|
57
|
+
modules.forEach((m) => {
|
|
58
|
+
if (!m?.value?.type) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (m.value.type === "rawscript") {
|
|
62
|
+
if (m.value.content && m.value.content.startsWith("!inline ")) {
|
|
63
|
+
mapping[m.id] = m.value.content.trim().split(" ")[1];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else if (m.value.type === "forloopflow" ||
|
|
67
|
+
m.value.type === "whileloopflow") {
|
|
68
|
+
extractCurrentMapping(m.value.modules, mapping);
|
|
69
|
+
}
|
|
70
|
+
else if (m.value.type === "branchall") {
|
|
71
|
+
m.value.branches.forEach((b) => extractCurrentMapping(b.modules, mapping));
|
|
72
|
+
}
|
|
73
|
+
else if (m.value.type === "branchone") {
|
|
74
|
+
m.value.branches.forEach((b) => extractCurrentMapping(b.modules, mapping));
|
|
75
|
+
extractCurrentMapping(m.value.default, mapping);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return mapping;
|
|
79
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replaces inline script references with actual file content from the filesystem.
|
|
3
|
+
* This function recursively processes all flow modules and their nested structures.
|
|
4
|
+
*
|
|
5
|
+
* @param modules - Array of flow modules to process
|
|
6
|
+
* @param fileReader - Function to read file content (typically fs.readFile or similar)
|
|
7
|
+
* @param logger - Optional logger object with info and error methods
|
|
8
|
+
* @param localPath - Base path for resolving relative file paths
|
|
9
|
+
* @param removeLocks - Optional array of paths for which to remove lock files
|
|
10
|
+
* @returns Promise that resolves when all inline scripts have been replaced
|
|
11
|
+
*/
|
|
12
|
+
export async function replaceInlineScripts(modules, fileReader, logger = {
|
|
13
|
+
info: () => { },
|
|
14
|
+
error: () => { },
|
|
15
|
+
}, localPath, separator = "/", removeLocks, renamer, deleter) {
|
|
16
|
+
await Promise.all(modules.map(async (module) => {
|
|
17
|
+
if (!module.value) {
|
|
18
|
+
throw new Error(`Module value is undefined for module ${module.id}`);
|
|
19
|
+
}
|
|
20
|
+
if (module.value.type === "rawscript" && module.value.content && module.value.content.startsWith("!inline")) {
|
|
21
|
+
const path = module.value.content.split(" ")[1];
|
|
22
|
+
const pathPrefix = path.split(".")[0];
|
|
23
|
+
const pathSuffix = path.split(".").slice(1).join(".");
|
|
24
|
+
// new path is the module id with the same suffix
|
|
25
|
+
const newPath = module.id + "." + pathSuffix;
|
|
26
|
+
try {
|
|
27
|
+
module.value.content = await fileReader(path);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
logger.error(`Script file ${path} not found`);
|
|
31
|
+
// try new path
|
|
32
|
+
try {
|
|
33
|
+
module.value.content = await fileReader(newPath);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
logger.error(`Script file ${newPath} not found`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// rename the file if the prefix is different from the module id (fix old naming)
|
|
40
|
+
// if (pathPrefix != module.id && renamer) {
|
|
41
|
+
// logger.info(`Renaming ${path} to ${module.id}.${pathSuffix}`);
|
|
42
|
+
// try {
|
|
43
|
+
// renamer(localPath + path, localPath + module.id + "." + pathSuffix);
|
|
44
|
+
// } catch {
|
|
45
|
+
// logger.info(`Failed to rename ${path} to ${module.id}.${pathSuffix}`);
|
|
46
|
+
// }
|
|
47
|
+
// }
|
|
48
|
+
const lock = module.value.lock;
|
|
49
|
+
if (removeLocks && removeLocks.includes(path)) {
|
|
50
|
+
module.value.lock = undefined;
|
|
51
|
+
// delete the file if the prefix is different from the module id (fix old naming)
|
|
52
|
+
// if (lock && lock != "") {
|
|
53
|
+
// const path = lock.split(" ")[1];
|
|
54
|
+
// const pathPrefix = path.split(".")[0];
|
|
55
|
+
// if (pathPrefix != module.id && deleter) {
|
|
56
|
+
// logger.info(`Deleting ${path}`);
|
|
57
|
+
// try {
|
|
58
|
+
// deleter(localPath + path);
|
|
59
|
+
// } catch {
|
|
60
|
+
// logger.error(`Failed to delete ${path}`);
|
|
61
|
+
// }
|
|
62
|
+
// }
|
|
63
|
+
// }
|
|
64
|
+
}
|
|
65
|
+
else if (lock &&
|
|
66
|
+
typeof lock == "string" &&
|
|
67
|
+
lock.trimStart().startsWith("!inline ")) {
|
|
68
|
+
const path = lock.split(" ")[1];
|
|
69
|
+
try {
|
|
70
|
+
module.value.lock = await fileReader(path.replaceAll("/", separator));
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
logger.error(`Lock file ${path} not found`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else if (module.value.type === "forloopflow" || module.value.type === "whileloopflow") {
|
|
78
|
+
await replaceInlineScripts(module.value.modules, fileReader, logger, localPath, separator, removeLocks);
|
|
79
|
+
}
|
|
80
|
+
else if (module.value.type === "branchall") {
|
|
81
|
+
await Promise.all(module.value.branches.map(async (branch) => {
|
|
82
|
+
await replaceInlineScripts(branch.modules, fileReader, logger, localPath, separator, removeLocks);
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
else if (module.value.type === "branchone") {
|
|
86
|
+
await Promise.all(module.value.branches.map(async (branch) => {
|
|
87
|
+
await replaceInlineScripts(branch.modules, fileReader, logger, localPath, separator, removeLocks);
|
|
88
|
+
}));
|
|
89
|
+
await replaceInlineScripts(module.value.default, fileReader, logger, localPath, separator, removeLocks);
|
|
90
|
+
}
|
|
91
|
+
}));
|
|
92
|
+
}
|