@pixelbyte-software/pixcode 1.54.8 → 1.54.9
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/dist/assets/{index-BU3Z3zrh.js → index-Bm6uAqKU.js} +1 -1
- package/dist/index.html +1 -1
- package/dist-server/server/index.js +39 -2
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/projects.js +16 -6
- package/dist-server/server/projects.js.map +1 -1
- package/package.json +1 -1
- package/server/index.js +41 -2
- package/server/projects.js +17 -7
package/dist/index.html
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
<!-- Prevent zoom on iOS -->
|
|
37
37
|
<meta name="format-detection" content="telephone=no" />
|
|
38
|
-
<script type="module" crossorigin src="/assets/index-
|
|
38
|
+
<script type="module" crossorigin src="/assets/index-Bm6uAqKU.js"></script>
|
|
39
39
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-DB6V5Fl1.js">
|
|
40
40
|
<link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-CIYNS698.js">
|
|
41
41
|
<link rel="modulepreload" crossorigin href="/assets/vendor-xterm-C7tpxJl7.js">
|
|
@@ -1108,6 +1108,10 @@ const FILE_TREE_MAX_ITEMS = Number.parseInt(process.env.PIXCODE_FILE_TREE_MAX_IT
|
|
|
1108
1108
|
const FILE_TREE_MAX_DIRECTORIES = Number.parseInt(process.env.PIXCODE_FILE_TREE_MAX_DIRECTORIES || '', 10) || 1200;
|
|
1109
1109
|
const FILE_TREE_SCAN_MAX_MS = Number.parseInt(process.env.PIXCODE_FILE_TREE_SCAN_MAX_MS || '', 10) || 4000;
|
|
1110
1110
|
const FILE_TREE_MAX_ENTRIES_PER_DIRECTORY = Number.parseInt(process.env.PIXCODE_FILE_TREE_MAX_ENTRIES_PER_DIRECTORY || '', 10) || 1500;
|
|
1111
|
+
const FILE_TREE_MAX_DEPTH_DEFAULT = 5; // was 10, reduced to avoid deep traversal on huge projects
|
|
1112
|
+
const FILE_TREE_CACHE_TTL_MS = 3000; // short-lived cache for rapid successive requests
|
|
1113
|
+
const FILE_TREE_CACHE_MAX_ENTRIES = 50;
|
|
1114
|
+
const fileTreeCache = new Map();
|
|
1111
1115
|
const FILE_TREE_EXCLUDED_ENTRY_NAMES = new Set([
|
|
1112
1116
|
'.cache',
|
|
1113
1117
|
'.git',
|
|
@@ -2964,7 +2968,7 @@ app.get('/api/projects/:projectName/files', authenticateToken, requireProjectAcc
|
|
|
2964
2968
|
catch (e) {
|
|
2965
2969
|
return res.status(404).json({ error: `Project path not found: ${actualPath}` });
|
|
2966
2970
|
}
|
|
2967
|
-
const files = await getFileTree(actualPath,
|
|
2971
|
+
const files = await getFileTree(actualPath, FILE_TREE_MAX_DEPTH_DEFAULT, 0, true);
|
|
2968
2972
|
res.json(filterFileTreeForUser(files, req.user, {
|
|
2969
2973
|
name: req.params.projectName,
|
|
2970
2974
|
projectName: req.params.projectName,
|
|
@@ -4794,6 +4798,26 @@ function permToRwx(perm) {
|
|
|
4794
4798
|
const x = perm & 1 ? 'x' : '-';
|
|
4795
4799
|
return r + w + x;
|
|
4796
4800
|
}
|
|
4801
|
+
// File tree result cache (keyed by path:depth:showHidden, TTL 3s)
|
|
4802
|
+
function readFileTreeCache(cacheKey) {
|
|
4803
|
+
const entry = fileTreeCache.get(cacheKey);
|
|
4804
|
+
if (!entry || entry.expiresAt <= Date.now()) {
|
|
4805
|
+
if (entry)
|
|
4806
|
+
fileTreeCache.delete(cacheKey);
|
|
4807
|
+
// Prune stale entries
|
|
4808
|
+
if (fileTreeCache.size > FILE_TREE_CACHE_MAX_ENTRIES) {
|
|
4809
|
+
const keys = [...fileTreeCache.keys()];
|
|
4810
|
+
for (const k of keys.slice(0, keys.length - FILE_TREE_CACHE_MAX_ENTRIES)) {
|
|
4811
|
+
fileTreeCache.delete(k);
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
return undefined;
|
|
4815
|
+
}
|
|
4816
|
+
return entry.tree;
|
|
4817
|
+
}
|
|
4818
|
+
function writeFileTreeCache(cacheKey, tree) {
|
|
4819
|
+
fileTreeCache.set(cacheKey, { tree, expiresAt: Date.now() + FILE_TREE_CACHE_TTL_MS });
|
|
4820
|
+
}
|
|
4797
4821
|
function createFileTreeScanContext() {
|
|
4798
4822
|
return {
|
|
4799
4823
|
startedAt: Date.now(),
|
|
@@ -4849,6 +4873,13 @@ async function readDirectoryEntriesBounded(dirPath, context) {
|
|
|
4849
4873
|
return entries;
|
|
4850
4874
|
}
|
|
4851
4875
|
async function getFileTree(dirPath, maxDepth = 3, currentDepth = 0, showHidden = true, scanContext = null) {
|
|
4876
|
+
// Check cache on top-level call
|
|
4877
|
+
if (currentDepth === 0 && !scanContext) {
|
|
4878
|
+
const cacheKey = `${path.resolve(dirPath)}:${maxDepth}:${showHidden}`;
|
|
4879
|
+
const cached = readFileTreeCache(cacheKey);
|
|
4880
|
+
if (cached)
|
|
4881
|
+
return cached;
|
|
4882
|
+
}
|
|
4852
4883
|
const context = scanContext || createFileTreeScanContext();
|
|
4853
4884
|
const items = [];
|
|
4854
4885
|
if (!hasFileTreeBudget(context)) {
|
|
@@ -4895,12 +4926,18 @@ async function getFileTree(dirPath, maxDepth = 3, currentDepth = 0, showHidden =
|
|
|
4895
4926
|
}
|
|
4896
4927
|
items.push(item);
|
|
4897
4928
|
}
|
|
4898
|
-
|
|
4929
|
+
const sorted = items.sort((a, b) => {
|
|
4899
4930
|
if (a.type !== b.type) {
|
|
4900
4931
|
return a.type === 'directory' ? -1 : 1;
|
|
4901
4932
|
}
|
|
4902
4933
|
return a.name.localeCompare(b.name);
|
|
4903
4934
|
});
|
|
4935
|
+
// Store in cache on top-level call
|
|
4936
|
+
if (currentDepth === 0 && !scanContext) {
|
|
4937
|
+
const cacheKey = `${path.resolve(dirPath)}:${maxDepth}:${showHidden}`;
|
|
4938
|
+
writeFileTreeCache(cacheKey, sorted);
|
|
4939
|
+
}
|
|
4940
|
+
return sorted;
|
|
4904
4941
|
}
|
|
4905
4942
|
const SERVER_PORT = process.env.SERVER_PORT || 3001;
|
|
4906
4943
|
const HOST = process.env.HOST || '0.0.0.0';
|