fscr 6.2.6 → 7.3.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.
Files changed (72) hide show
  1. package/README.md +48 -30
  2. package/dist/index.js +502 -186
  3. package/dist/lib/auth/auth-conf.js +49 -45
  4. package/dist/lib/cache/README.md +341 -0
  5. package/dist/lib/cache/cli.js +152 -0
  6. package/dist/lib/cache/file-watcher.js +193 -0
  7. package/dist/lib/cache/index.js +422 -0
  8. package/dist/lib/cache/monitor.js +224 -0
  9. package/dist/lib/commands/doctor.js +225 -0
  10. package/dist/lib/completions/completion.js +342 -0
  11. package/dist/lib/completions/generator.js +152 -0
  12. package/dist/lib/completions/scripts/bash.sh +108 -0
  13. package/dist/lib/completions/scripts/fish.sh +105 -0
  14. package/dist/lib/completions/scripts/powershell.ps1 +168 -0
  15. package/dist/lib/completions/scripts/zsh.sh +124 -0
  16. package/dist/lib/diagnostics/cache.js +121 -0
  17. package/dist/lib/diagnostics/fileSystem.js +236 -0
  18. package/dist/lib/diagnostics/gitCheck.js +41 -0
  19. package/dist/lib/diagnostics/nodeVersion.js +68 -0
  20. package/dist/lib/diagnostics/packageManager.js +64 -0
  21. package/dist/lib/diagnostics/performance.js +141 -0
  22. package/dist/lib/encryption/decryptConfig.js +3 -2
  23. package/dist/lib/encryption/encryption.js +153 -113
  24. package/dist/lib/generators/generateFScripts.js +16 -13
  25. package/dist/lib/generators/generateToc.js +23 -14
  26. package/dist/lib/generators/index.js +1 -1
  27. package/dist/lib/git/pub.js +27 -17
  28. package/dist/lib/git/taskRunner.js +79 -69
  29. package/dist/lib/git/validateNotDev.js +65 -54
  30. package/dist/lib/optionList.js +69 -57
  31. package/dist/lib/parsers/parseScriptsMd.cached.js +208 -0
  32. package/dist/lib/parsers/parseScriptsMd.js +88 -79
  33. package/dist/lib/parsers/parseScriptsPackage.js +4 -3
  34. package/dist/lib/performance/cache.js +199 -0
  35. package/dist/lib/performance/lazy-loader.js +189 -0
  36. package/dist/lib/performance/monitor.js +303 -0
  37. package/dist/lib/plugins/deployment/index.js +113 -0
  38. package/dist/lib/plugins/hooks.js +17 -0
  39. package/dist/lib/plugins/loader.js +91 -0
  40. package/dist/lib/plugins/task-notifier/index.js +72 -0
  41. package/dist/lib/release/bump.js +50 -45
  42. package/dist/lib/release/commitWithMessage.js +80 -52
  43. package/dist/lib/release/publish.js +19 -14
  44. package/dist/lib/release/pushToGit.js +40 -31
  45. package/dist/lib/release/releasenotes.js +116 -97
  46. package/dist/lib/release/seeChangedFiles.js +68 -60
  47. package/dist/lib/release/sort.js +200 -116
  48. package/dist/lib/release/tree.js +161 -147
  49. package/dist/lib/release/validateNotDev.js +52 -44
  50. package/dist/lib/running/index.js +1 -1
  51. package/dist/lib/running/runCLICommand.js +41 -31
  52. package/dist/lib/running/runParallel.js +61 -59
  53. package/dist/lib/running/runSequence.js +55 -53
  54. package/dist/lib/startScripts.js +129 -114
  55. package/dist/lib/taskList.js +97 -90
  56. package/dist/lib/test-files/.fscripts.md +113 -0
  57. package/dist/lib/test-files/.fscripts.test.md +103 -0
  58. package/dist/lib/test-files/.fscriptsb.md +107 -0
  59. package/dist/lib/test-files/.mdtest.md +40 -0
  60. package/dist/lib/test-files/consoleSample.js +13 -9
  61. package/dist/lib/test-files/inputSample.js +17 -14
  62. package/dist/lib/test-files/testConsole.js +1 -1
  63. package/dist/lib/test-files/testInput.js +1 -1
  64. package/dist/lib/upgradePackages.js +56 -46
  65. package/dist/lib/utils/clear.js +16 -13
  66. package/dist/lib/utils/console.js +27 -21
  67. package/dist/lib/utils/encryption.js +55 -13
  68. package/dist/lib/utils/hash.js +128 -0
  69. package/dist/lib/utils/helpers.js +153 -142
  70. package/dist/lib/utils/index.js +1 -1
  71. package/dist/lib/utils/prompt.js +24 -29
  72. package/package.json +11 -29
@@ -5,67 +5,78 @@ import { boxInform } from "../utils/helpers.js";
5
5
  import git from "git-state";
6
6
  import simple from "simple-git";
7
7
  const pathToCwd = process.cwd();
8
+
8
9
  const newBranch = async name => {
9
- // const last = await new Promise(rzz => {
10
- // git.isGit(pathToCwd, function(exists) {
11
- // if (!exists) return;
10
+ // const last = await new Promise(rzz => {
11
+ // git.isGit(pathToCwd, function(exists) {
12
+ // if (!exists) return;
12
13
 
13
- //
14
- // git.commit(pathToCwd, function(err, result) {
15
- // if (err) throw err;
16
- // rzz(result);
17
- // });
18
- // });
19
- // });
14
+ //
15
+ // git.commit(pathToCwd, function(err, result) {
16
+ // if (err) throw err;
17
+ // rzz(result);
18
+ // });
19
+ // });
20
+ // });
20
21
 
21
- try {
22
- // logInfo(command);
23
- childProcess.execSync(`git -c core.quotepath=false -c log.showSignature=false checkout -b ${name}`, {
24
- stdio: "inherit",
25
- env: Object.assign({}, process.env, {
26
- FORCE_COLOR: true,
27
- PATH: `${path.resolve("node_modules")}:${process.env.PATH}`
28
- })
29
- });
30
- } catch (e) {}
22
+ try {
23
+ // logInfo(command);
24
+ childProcess.execSync(
25
+ `git -c core.quotepath=false -c log.showSignature=false checkout -b ${name}`,
26
+ {
27
+ stdio: "inherit",
28
+ env: Object.assign({}, process.env, {
29
+ FORCE_COLOR: true,
30
+ PATH: `${path.resolve("node_modules")}:${process.env.PATH}`
31
+ })
32
+ }
33
+ );
34
+ } catch (e) {}
31
35
 
32
- // await simple().checkoutLocalBranch(name);
33
- // await simple().checkoutBranch(name, "origin");
34
- boxInform(chalk.green(`New branch ${name} created`, "", 5));
36
+ // await simple().checkoutLocalBranch(name);
37
+ // await simple().checkoutBranch(name, "origin");
38
+ boxInform(chalk.green(`New branch ${name} created`, "", 5));
35
39
  };
40
+
36
41
  async function pub() {
37
- return new Promise(resolve => {
38
- inquirer.prompt([{
39
- type: "input",
40
- message: chalk.bold.hex("#38be18")(`Name new feature branch (or type cancel):`),
41
- name: "branchname"
42
- }]).then(async ({
43
- branchname
44
- }) => {
45
- if (branchname !== "Development") await newBranch(branchname);
46
- resolve();
42
+ return new Promise(resolve => {
43
+ inquirer
44
+ .prompt([
45
+ {
46
+ type: "input",
47
+ message: chalk.bold.hex("#38be18")(`Name new feature branch (or type cancel):`),
48
+ name: "branchname"
49
+ }
50
+ ])
51
+ .then(async ({ branchname }) => {
52
+ if (branchname !== "Development") await newBranch(branchname);
53
+ resolve();
54
+ });
47
55
  });
48
- });
49
56
  }
57
+
50
58
  const validateNotInDev = async () => {
51
- await new Promise(async resolve => {
52
- const {
53
- default: git
54
- } = await import("simple-git/promise");
55
- let statusSummary = await git(__dirname).status();
56
- if (statusSummary.current === "Development") {
57
- console.clear();
58
- console.log(boxen(chalk.bold.underline.red("DO NO MAKE CHANGES IN DEV!"), {
59
- padding: 2
60
- }));
61
- await new Promise(resolve1 => setTimeout(() => {
62
- resolve1();
63
- }, 1000));
64
- await pub();
65
- resolve();
66
- } else {
67
- resolve();
68
- }
69
- });
59
+ await new Promise(async resolve => {
60
+ const { default: git } = await import("simple-git/promise");
61
+
62
+ let statusSummary = await git(__dirname).status();
63
+ if (statusSummary.current === "Development") {
64
+ console.clear();
65
+ console.log(
66
+ boxen(chalk.bold.underline.red("DO NO MAKE CHANGES IN DEV!"), {
67
+ padding: 2
68
+ })
69
+ );
70
+ await new Promise(resolve1 =>
71
+ setTimeout(() => {
72
+ resolve1();
73
+ }, 1000)
74
+ );
75
+ await pub();
76
+ resolve();
77
+ } else {
78
+ resolve();
79
+ }
80
+ });
70
81
  };
71
- export default validateNotInDev;
82
+ export default validateNotInDev;
@@ -1,61 +1,73 @@
1
1
  const separator = " ~ ";
2
2
  import chalk from "chalk";
3
3
  import enquirerPkg from "enquirer";
4
- const {
5
- prompt
6
- } = enquirerPkg;
7
- const optionList = async () => {
8
- let choiceCategories = [{
9
- name: "start",
10
- message: "Choose category then task to run"
11
- }, {
12
- name: "list",
13
- message: "Select any task with text autocompletion"
14
- }, {
15
- name: "scripts",
16
- message: "Choose a script from package.json"
17
- }, {
18
- name: "upgrade",
19
- message: "Upgrade all your packages except ones specified by 'ignore-upgrade':[]"
20
- }, {
21
- name: "remote",
22
- message: "Get remote configuration with your fc email"
23
- }, {
24
- name: "bump",
25
- message: "Bump package.json and beautify it!"
26
- }, {
27
- name: "encryption",
28
- message: "Encrypt/Decrypt secret files"
29
- }, {
30
- name: "clear",
31
- message: "Clear recent task history"
32
- }, {
33
- name: "generate",
34
- message: "Generate a sample fscripts.md file from the package.json"
35
- }, {
36
- name: "toc",
37
- message: "Generate updated Table of Contents on top of the fscripts.md file"
38
- }, {
39
- name: "--help",
40
- message: "See full help documentation"
41
- }];
42
- try {
43
- let {
44
- answer
45
- } = await prompt({
46
- type: "select",
47
- name: `answer`,
48
- choiceMessage: e => {
49
- // return JSON.stringify(e)
50
- // return e.message;
51
- return `${chalk.bold.underline(e.name)}${chalk.reset(": \n ")}${chalk.gray.italic(e.message)}`;
52
- },
53
- message: `${chalk.cyan.bold.underline("What category do you want to run?")}`,
54
- choices: choiceCategories
55
- });
56
- return answer;
57
- } catch (e) {
58
- return false;
59
- }
4
+ const { prompt } = enquirerPkg;
5
+ const optionList = async (extraChoices = []) => {
6
+ let choiceCategories = [
7
+ {
8
+ name: "start",
9
+ message: "Choose category then task to run"
10
+ },
11
+ {
12
+ name: "list",
13
+ message: "Select any task with text autocompletion"
14
+ },
15
+ {
16
+ name: "scripts",
17
+ message: "Choose a script from package.json"
18
+ },
19
+ {
20
+ name: "upgrade",
21
+ message: "Upgrade all your packages except ones specified by 'ignore-upgrade':[]"
22
+ },
23
+ {
24
+ name: "remote",
25
+ message: "Get remote configuration with your fc email"
26
+ },
27
+ {
28
+ name: "bump",
29
+ message: "Bump package.json and beautify it!"
30
+ },
31
+ {
32
+ name: "encryption",
33
+ message: "Encrypt/Decrypt secret files"
34
+ },
35
+ {
36
+ name: "clear",
37
+ message: "Clear recent task history"
38
+ },
39
+ {
40
+ name: "generate",
41
+ message: "Generate a sample fscripts.md file from the package.json"
42
+ },
43
+ {
44
+ name: "toc",
45
+ message: "Generate updated Table of Contents on top of the fscripts.md file"
46
+ },
47
+ {
48
+ name: "--help",
49
+ message: "See full help documentation"
50
+ },
51
+ ...extraChoices
52
+ ];
53
+ try {
54
+ let { answer } = await prompt({
55
+ type: "select",
56
+ name: `answer`,
57
+ choiceMessage: (e) => {
58
+ // return JSON.stringify(e)
59
+ // return e.message;
60
+ return `${chalk.bold.underline(e.name)}${chalk.reset(": \n ")}${chalk.gray.italic(
61
+ e.message
62
+ )}`;
63
+ },
64
+ message: `${chalk.cyan.bold.underline("What category do you want to run?")}`,
65
+ choices: choiceCategories
66
+ });
67
+ return answer;
68
+ } catch (e) {
69
+ return false;
70
+ }
60
71
  };
61
- export default optionList;
72
+
73
+ export default optionList;
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Cached version of parseScriptsMd
3
+ * Adds smart caching with TTL and file watching
4
+ */
5
+
6
+ import path from "path";
7
+ import fs from "fs";
8
+ import { getCache } from "../cache/index.js";
9
+ import FileWatcher from "../cache/file-watcher.js";
10
+ import { marked } from "marked";
11
+
12
+ // Initialize cache and file watcher
13
+ let cache = null;
14
+ let fileWatcher = null;
15
+
16
+ /**
17
+ * Get or create cache instance
18
+ */
19
+ function getOrCreateCache() {
20
+ if (!cache) {
21
+ cache = getCache({
22
+ defaultTTL: 300000, // 5 minutes
23
+ maxSize: 100,
24
+ enableStats: true
25
+ });
26
+ }
27
+ return cache;
28
+ }
29
+
30
+ /**
31
+ * Get or create file watcher
32
+ */
33
+ function getOrCreateWatcher() {
34
+ if (!fileWatcher) {
35
+ const cacheInstance = getOrCreateCache();
36
+ fileWatcher = new FileWatcher(cacheInstance, {
37
+ debounceMs: 100
38
+ });
39
+ }
40
+ return fileWatcher;
41
+ }
42
+
43
+ /**
44
+ * Parse markdown content to script structure
45
+ * (Same logic as original parseScriptFile)
46
+ */
47
+ const parse = function(mdContent) {
48
+ let js = marked.lexer(mdContent);
49
+ js = js.filter(e => e.type !== "space");
50
+
51
+ let listMe = js.slice();
52
+ let tempItem = {};
53
+ let currentCategory = "";
54
+ let currentTask = "";
55
+ let taskOrder = 0;
56
+
57
+ listMe.forEach((item, indx) => {
58
+ if (item.type === "heading" && item.depth === 1) {
59
+ taskOrder = 0;
60
+ currentCategory = item.text;
61
+ tempItem[currentCategory] = { name: item.text, tasks: {}, description: "" };
62
+ let descriptor = js[indx + 1];
63
+ if (descriptor && descriptor.type === "paragraph") {
64
+ tempItem[currentCategory].description = descriptor.text;
65
+ }
66
+ } else if (item.type === "heading" && item.depth === 2) {
67
+ currentTask = item.text;
68
+ tempItem[currentCategory].tasks[currentTask] = {
69
+ script: "",
70
+ name: currentTask,
71
+ description: "",
72
+ order: taskOrder
73
+ };
74
+ taskOrder++;
75
+ let descriptor = js[indx + 1];
76
+ let code = js[indx + 2];
77
+ if (descriptor && descriptor.type === "paragraph" && code && code.type === "code") {
78
+ tempItem[currentCategory].tasks[currentTask].description = descriptor.text;
79
+ tempItem[currentCategory].tasks[currentTask].lang = code.lang;
80
+ tempItem[currentCategory].tasks[currentTask].script = code.text;
81
+ } else if (descriptor && descriptor.type === "code") {
82
+ tempItem[currentCategory].tasks[currentTask].lang = descriptor.lang;
83
+ tempItem[currentCategory].tasks[currentTask].script = descriptor.text;
84
+ }
85
+ }
86
+ });
87
+
88
+ let allTasks = [];
89
+ let categories = Object.keys(tempItem).map(catName => {
90
+ let ts = tempItem[catName].tasks;
91
+ let tasksArr = Object.keys(ts).map(tn => ts[tn]);
92
+ allTasks = [...allTasks, ...tasksArr];
93
+ return { name: catName, ...tempItem[catName] };
94
+ });
95
+
96
+ return { categories, allTasks };
97
+ };
98
+
99
+ /**
100
+ * Parse script file with caching
101
+ * @param {Object} options - Options
102
+ * @param {boolean} [options.useCache=true] - Whether to use cache
103
+ * @param {boolean} [options.watchFile=true] - Whether to watch file for changes
104
+ * @returns {Promise<Object|boolean>} Parsed scripts or false
105
+ */
106
+ const parseScriptFile = async (options = {}) => {
107
+ const useCache = options.useCache !== false;
108
+ const watchFile = options.watchFile !== false;
109
+
110
+ const fscriptsPath = path.resolve(process.cwd(), "fscripts.md");
111
+
112
+ // Check if file exists
113
+ if (!fs.existsSync(fscriptsPath)) {
114
+ return false;
115
+ }
116
+
117
+ // Try cache first
118
+ if (useCache) {
119
+ const cacheInstance = getOrCreateCache();
120
+ const cacheKey = cacheInstance.generateFileKey(fscriptsPath);
121
+ const cached = cacheInstance.get(cacheKey);
122
+
123
+ if (cached) {
124
+ // Cache hit - return cached data
125
+ return cached;
126
+ }
127
+
128
+ // Cache miss - parse file
129
+ const data = fs.readFileSync(fscriptsPath, "utf-8");
130
+ if (data === null || data === undefined) {
131
+ return false;
132
+ }
133
+
134
+ // Handle empty file - return empty structure
135
+ if (data === "") {
136
+ const emptyResult = { categories: [], allTasks: [] };
137
+ cacheInstance.set(cacheKey, emptyResult, { filePath: fscriptsPath });
138
+ return emptyResult;
139
+ }
140
+
141
+ let newContent = data.split("<!-- end toc -->");
142
+ newContent = newContent[newContent.length === 2 ? 1 : 0];
143
+ const parsed = parse(newContent);
144
+
145
+ // Store in cache
146
+ cacheInstance.set(cacheKey, parsed, { filePath: fscriptsPath });
147
+
148
+ // Watch file for changes if enabled
149
+ if (watchFile) {
150
+ const watcher = getOrCreateWatcher();
151
+ if (!watcher.isWatching(fscriptsPath)) {
152
+ watcher.watch(fscriptsPath);
153
+ }
154
+ }
155
+
156
+ return parsed;
157
+ } else {
158
+ // No cache - parse directly
159
+ const data = fs.readFileSync(fscriptsPath, "utf-8");
160
+ if (data === null || data === undefined) {
161
+ return false;
162
+ }
163
+
164
+ // Handle empty file - return empty structure
165
+ if (data === "") {
166
+ return { categories: [], allTasks: [] };
167
+ }
168
+
169
+ let newContent = data.split("<!-- end toc -->");
170
+ newContent = newContent[newContent.length === 2 ? 1 : 0];
171
+ return parse(newContent);
172
+ }
173
+ };
174
+
175
+ /**
176
+ * Clear cache manually
177
+ */
178
+ export function clearCache() {
179
+ if (cache) {
180
+ cache.clear();
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Get cache statistics
186
+ */
187
+ export function getCacheStats() {
188
+ if (cache) {
189
+ return cache.getStats();
190
+ }
191
+ return null;
192
+ }
193
+
194
+ /**
195
+ * Destroy cache and watcher (cleanup)
196
+ */
197
+ export function destroyCache() {
198
+ if (fileWatcher) {
199
+ fileWatcher.destroy();
200
+ fileWatcher = null;
201
+ }
202
+ if (cache) {
203
+ cache.destroy();
204
+ cache = null;
205
+ }
206
+ }
207
+
208
+ export default parseScriptFile;
@@ -1,90 +1,99 @@
1
1
  import path from "path";
2
2
  import chalk from "chalk";
3
3
  import fs from "fs";
4
- const flattenObject = (obj, prefix = "") => Object.keys(obj).reduce((acc, k) => {
5
- const pre = prefix.length ? prefix + "." : "";
6
- if (typeof obj[k] === "object") Object.assign(acc, flattenObject(obj[k], pre + k));else acc[pre + k] = obj[k];
7
- return acc;
8
- }, {});
4
+ const flattenObject = (obj, prefix = "") =>
5
+ Object.keys(obj).reduce((acc, k) => {
6
+ const pre = prefix.length ? prefix + "." : "";
7
+ if (typeof obj[k] === "object") Object.assign(acc, flattenObject(obj[k], pre + k));
8
+ else acc[pre + k] = obj[k];
9
+ return acc;
10
+ }, {});
11
+
9
12
  import { marked } from "marked";
10
- let parse = function (mdContent) {
11
- let js = marked.lexer(mdContent);
12
- js = js.filter(e => e.type !== "space");
13
13
 
14
- // let firstHeading = js.findIndex(e => e.type === "heading" && e.depth === 1); //?
15
- let listMe = js.slice();
16
- let tempItem = {};
17
- let currentCategory = "";
18
- let currentTask = "";
19
- let taskOrder = 0;
20
- listMe.forEach((item, indx) => {
21
- if (item.type === "heading" && item.depth === 1) {
22
- taskOrder = 0;
23
- currentCategory = item.text;
24
- tempItem[currentCategory] = {
25
- name: item.text,
26
- tasks: {},
27
- description: ""
28
- };
29
- let descriptor = js[indx + 1];
30
- if (descriptor.type === "paragraph") {
31
- tempItem[currentCategory].description = descriptor.text;
32
- }
33
- } else if (item.type === "heading" && item.depth === 2) {
34
- currentTask = item.text;
35
- tempItem[currentCategory].tasks[currentTask] = {
36
- script: "",
37
- name: currentTask,
38
- description: "",
39
- order: taskOrder
40
- };
41
- taskOrder++;
42
- let descriptor = js[indx + 1];
43
- let code = js[indx + 2];
44
- if (descriptor.type === "paragraph" && code.type === "code") {
45
- tempItem[currentCategory].tasks[currentTask].description = descriptor.text;
46
- tempItem[currentCategory].tasks[currentTask].lang = code.lang;
47
- tempItem[currentCategory].tasks[currentTask].script = code.text;
48
- } else if (descriptor.type === "code") {
49
- // if (descriptor.lang === "javascript") {
50
- // console.info("Console --- ", descriptor);
51
- // }
52
- tempItem[currentCategory].tasks[currentTask].lang = descriptor.lang;
53
- tempItem[currentCategory].tasks[currentTask].script = descriptor.text;
54
- }
55
- }
56
- });
57
- let allTasks = [];
58
- let categories = Object.keys(tempItem).map(catName => {
59
- let ts = tempItem[catName].tasks;
60
- let tasksArr = Object.keys(ts).map(tn => ts[tn]);
61
- allTasks = [...allTasks, ...tasksArr];
62
- return {
63
- name: catName,
64
- ...tempItem[catName]
65
- };
66
- });
67
- return {
68
- categories,
69
- allTasks
70
- };
14
+ let parse = function(mdContent) {
15
+ let js = marked.lexer(mdContent);
16
+ js = js.filter(e => e.type !== "space");
17
+
18
+ // let firstHeading = js.findIndex(e => e.type === "heading" && e.depth === 1); //?
19
+ let listMe = js.slice();
20
+ let tempItem = {};
21
+ let currentCategory = "";
22
+ let currentTask = "";
23
+ let taskOrder = 0;
24
+ listMe.forEach((item, indx) => {
25
+ if (item.type === "heading" && item.depth === 1) {
26
+ taskOrder = 0;
27
+ currentCategory = item.text;
28
+ tempItem[currentCategory] = { name: item.text, tasks: {}, description: "" };
29
+ let descriptor = js[indx + 1];
30
+ if (descriptor.type === "paragraph") {
31
+ tempItem[currentCategory].description = descriptor.text;
32
+ }
33
+ } else if (item.type === "heading" && item.depth === 2) {
34
+ currentTask = item.text;
35
+ tempItem[currentCategory].tasks[currentTask] = {
36
+ script: "",
37
+ name: currentTask,
38
+ description: "",
39
+ order: taskOrder
40
+ };
41
+ taskOrder++;
42
+ let descriptor = js[indx + 1];
43
+ let code = js[indx + 2];
44
+ if (descriptor.type === "paragraph" && code.type === "code") {
45
+ tempItem[currentCategory].tasks[currentTask].description = descriptor.text;
46
+ tempItem[currentCategory].tasks[currentTask].lang = code.lang;
47
+ tempItem[currentCategory].tasks[currentTask].script = code.text;
48
+ } else if (descriptor.type === "code") {
49
+ // if (descriptor.lang === "javascript") {
50
+ // console.info("Console --- ", descriptor);
51
+ // }
52
+ tempItem[currentCategory].tasks[currentTask].lang = descriptor.lang;
53
+ tempItem[currentCategory].tasks[currentTask].script = descriptor.text;
54
+ }
55
+ }
56
+ });
57
+ let allTasks = [];
58
+ let categories = Object.keys(tempItem).map(catName => {
59
+ let ts = tempItem[catName].tasks;
60
+ let tasksArr = Object.keys(ts).map(tn => ts[tn]);
61
+ allTasks = [...allTasks, ...tasksArr];
62
+ return { name: catName, ...tempItem[catName] };
63
+ });
64
+
65
+ return { categories, allTasks };
71
66
  };
72
- const parseScriptFile = async () => {
73
- const data = await fs.readFileSync(path.resolve(process.cwd(), "fscripts.md"), "utf-8");
74
- if (!data) {
75
- // console.warn(
76
- // `${chalk.bold.red("You're missing the fscripts.md file!")}
77
- // ${chalk.green("Please run 'fsr generate' to get started!")}`
78
- // );
79
- //
80
- // process.exit(0);
81
- // return null;
82
- return false;
83
- } else {
67
+ const parseScriptFile = async (options = {}) => {
68
+ // Use caching by default (can be disabled with { useCache: false })
69
+ const useCache = options.useCache !== false;
70
+
71
+ if (useCache) {
72
+ // Import cached version dynamically
73
+ try {
74
+ const { default: cachedParse } = await import('./parseScriptsMd.cached.js');
75
+ return cachedParse(options);
76
+ } catch (error) {
77
+ // Fallback to non-cached version if import fails
78
+ console.warn('Cache module not available, using direct parsing');
79
+ }
80
+ }
81
+
82
+ // Non-cached version (original logic)
83
+ const data = await fs.readFileSync(path.resolve(process.cwd(), "fscripts.md"), "utf-8");
84
+ if (data === null || data === undefined) {
85
+ return false;
86
+ }
87
+
88
+ // Handle empty file - return empty structure
89
+ if (data === "") {
90
+ return { categories: [], allTasks: [] };
91
+ }
92
+
84
93
  // console.warn(`${chalk.bold.green("Located fscripts.md file!")}`);
85
94
  let newContent = data.split("<!-- end toc -->");
86
95
  newContent = newContent[newContent.length === 2 ? 1 : 0];
87
96
  return parse(newContent);
88
- }
89
97
  };
90
- export default parseScriptFile;
98
+
99
+ export default parseScriptFile;
@@ -3,7 +3,8 @@ import chalk from "chalk";
3
3
  const projectPath = path.join(process.cwd(), "./package.json");
4
4
  import { readJson } from "../utils/helpers.js";
5
5
  const parseScriptFile = async () => {
6
- const packageFile = await readJson(projectPath);
7
- return packageFile.scripts;
6
+ const packageFile = await readJson(projectPath);
7
+ return packageFile.scripts;
8
8
  };
9
- export default parseScriptFile;
9
+
10
+ export default parseScriptFile;