From 2368b2bc8fa0094f26d7e2a6934e5e3774d6fff6 Mon Sep 17 00:00:00 2001 From: Daniel Salazar Date: Mon, 6 Apr 2026 11:08:03 -0700 Subject: [PATCH] fix: missing subdomains and worker flags in readdir (#2772) --- package-lock.json | 53 ++++++------ .../deprecated/filesystem/FSNodeContext.js | 13 ++- .../filesystem/hl_operations/hl_readdir.js | 83 +++++++++++++------ 3 files changed, 93 insertions(+), 56 deletions(-) diff --git a/package-lock.json b/package-lock.json index 972b072ed..15489f8d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -514,7 +514,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.1020.0.tgz", "integrity": "sha512-VMrCgPMB5NWA5z5SaGbVVE3rHI7QD0w8357E0hnjPkiJZp6jmfMjNk2fmOmmOnTbZUXStqRK5zvC8c4bUXwMFw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -1682,7 +1681,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -2066,7 +2064,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -2115,7 +2112,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" } @@ -2141,6 +2137,29 @@ "node": ">=10.0.0" } }, + "node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -2148,6 +2167,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -3017,7 +3037,6 @@ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.7.3.tgz", "integrity": "sha512-wxNqWbqokF551WrJ9BIFouU/V5SL1oYCGx1oudcirdhadnQRFH5v1sjgGL7cUV/UsekSycygphdrF2lxBxOYKg==", "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -4868,7 +4887,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -4878,7 +4896,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.49.1.tgz", "integrity": "sha512-kaNl/T7WzyMUQHQlVq7q0oV4Kev6+0xFwqzofryC66jgGMacd0QH5TwfpbUwSTby+SdAdprAe5UKMvBw4tKS5Q==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/api": "^1.0.0" }, @@ -5359,7 +5376,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.40.0.tgz", "integrity": "sha512-8WRuvGnfnbeR9ifGjLN8kklk2fkd0gBT6aN7NHO9zeYF/6qacAViD3bwAKqGXKnJgl39l1EU41I9diqUjamEEQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/api": "^1.0.0" }, @@ -5502,7 +5518,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.40.0.tgz", "integrity": "sha512-8WRuvGnfnbeR9ifGjLN8kklk2fkd0gBT6aN7NHO9zeYF/6qacAViD3bwAKqGXKnJgl39l1EU41I9diqUjamEEQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/api": "^1.0.0" }, @@ -5646,7 +5661,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.40.0.tgz", "integrity": "sha512-8WRuvGnfnbeR9ifGjLN8kklk2fkd0gBT6aN7NHO9zeYF/6qacAViD3bwAKqGXKnJgl39l1EU41I9diqUjamEEQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/api": "^1.0.0" }, @@ -8987,7 +9001,6 @@ "integrity": "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", @@ -9779,7 +9792,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -10673,7 +10685,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -10895,7 +10906,6 @@ "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "license": "MIT", - "peer": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", @@ -12617,7 +12627,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -13276,7 +13285,6 @@ "resolved": "https://registry.npmjs.org/fengari/-/fengari-0.1.5.tgz", "integrity": "sha512-0DS4Nn4rV8qyFlQCpKK8brT61EUtswynrpfFTcgLErcilBIBskSMQ86fO2WVuybr14ywyKdRjv91FiRZwnEuvQ==", "license": "MIT", - "peer": true, "dependencies": { "readline-sync": "^1.4.10", "sprintf-js": "^1.1.3", @@ -15264,7 +15272,6 @@ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.10.1.tgz", "integrity": "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==", "license": "MIT", - "peer": true, "dependencies": { "@ioredis/commands": "1.5.1", "cluster-key-slot": "^1.1.0", @@ -20905,7 +20912,6 @@ "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -21551,7 +21557,6 @@ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz", "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==", "license": "MIT", - "peer": true, "dependencies": { "debug": "~4.4.1", "ws": "~8.18.3" @@ -22915,7 +22920,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -23201,7 +23205,6 @@ "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -23410,7 +23413,6 @@ "integrity": "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/expect": "4.1.2", "@vitest/mocker": "4.1.2", @@ -23538,7 +23540,6 @@ "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -23588,7 +23589,6 @@ "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -23966,7 +23966,6 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", @@ -24479,7 +24478,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -24602,7 +24600,6 @@ "src/backend/node_modules/@opentelemetry/api": { "version": "1.8.0", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -25027,7 +25024,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -25048,7 +25044,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } diff --git a/src/backend/src/deprecated/filesystem/FSNodeContext.js b/src/backend/src/deprecated/filesystem/FSNodeContext.js index bb0cedd99..787e18eef 100644 --- a/src/backend/src/deprecated/filesystem/FSNodeContext.js +++ b/src/backend/src/deprecated/filesystem/FSNodeContext.js @@ -401,7 +401,8 @@ export default class FSNodeContext { this.entry.subdomains = []; this.entry.workers = []; - let subdomains = await db.read( + this.entry.has_website = false; + const subdomains = await db.read( 'SELECT * FROM subdomains WHERE root_dir_id = ? AND user_id = ?', [this.entry.id, user.id], ); @@ -944,6 +945,16 @@ export default class FSNodeContext { fsentry.size = parseInt(fsentry.size); } + if ( ! Array.isArray(fsentry.subdomains) ) { + fsentry.subdomains = []; + } + if ( ! Array.isArray(fsentry.workers) ) { + fsentry.workers = []; + } + if ( typeof fsentry.has_website !== 'boolean' ) { + fsentry.has_website = false; + } + return fsentry; } diff --git a/src/backend/src/deprecated/filesystem/hl_operations/hl_readdir.js b/src/backend/src/deprecated/filesystem/hl_operations/hl_readdir.js index baf345ee0..750dde780 100644 --- a/src/backend/src/deprecated/filesystem/hl_operations/hl_readdir.js +++ b/src/backend/src/deprecated/filesystem/hl_operations/hl_readdir.js @@ -125,8 +125,10 @@ class HLReadDir extends HLFilesystemOperation { } if ( ! no_subdomains ) { - // await this.#batchFetchSubdomains(children, user); - await this.#applySubdomains(children); + const usedPrefetchedSubdomains = await this.#applySubdomains(children); + if ( ! usedPrefetchedSubdomains ) { + await this.#batchFetchSubdomains(children, user); + } } return Promise.all(children.map(async child => { @@ -146,14 +148,29 @@ class HLReadDir extends HLFilesystemOperation { } async #applySubdomains (children) { + let usedPrefetchedSubdomains = false; + for ( const child of children ) { - if ( ! child.subdomains ) return; - if ( child.subdomains.length > 0 ) child.has_website = true; - for ( const subdomain of child.subdomains ) { - subdomain.address = - `${config.protocol}://${subdomain.subdomain}.puter.site`; + const entry = child.entry; + if ( ! entry ) continue; + this.#initializeSubdomainFields(entry); + + const prefetchedSubdomains = child.subdomains ?? entry.subdomains; + if ( prefetchedSubdomains === undefined ) return false; + + usedPrefetchedSubdomains = true; + if ( ! Array.isArray(prefetchedSubdomains) ) continue; + + for ( const subdomain of prefetchedSubdomains ) { + this.#appendSubdomainToEntry({ + entry, + subdomain: subdomain?.subdomain, + uuid: subdomain?.uuid, + }); } } + + return usedPrefetchedSubdomains; } async #batchFetchSubdomains (children, user) { @@ -163,8 +180,7 @@ class HLReadDir extends HLFilesystemOperation { for ( const child of children ) { const entry = child.entry; if ( ! entry ) continue; - entry.subdomains = []; - entry.workers = []; + this.#initializeSubdomainFields(entry); if ( entry.id == null ) continue; childIds.push(entry.id); childById.set(entry.id, child); @@ -184,26 +200,41 @@ class HLReadDir extends HLFilesystemOperation { for ( const row of rows ) { const child = childById.get(row.root_dir_id); if ( ! child ) continue; - - if ( child.entry.is_dir ) { - child.entry.subdomains.push({ - subdomain: row.subdomain, - address: `${config.protocol }://${ row.subdomain }.puter.site`, - uuid: row.uuid, - }); - } else { - const workerName = row.subdomain.split('.').pop(); - child.entry.workers.push({ - subdomain: workerName, - address: `https://${ workerName }.puter.work`, - uuid: row.uuid, - }); - } - - child.entry.has_website = true; + this.#appendSubdomainToEntry({ + entry: child.entry, + subdomain: row.subdomain, + uuid: row.uuid, + }); } } + #initializeSubdomainFields (entry) { + entry.subdomains = []; + entry.workers = []; + entry.has_website = false; + } + + #appendSubdomainToEntry ({ entry, subdomain, uuid }) { + if ( ! subdomain ) return; + + if ( entry.is_dir ) { + entry.subdomains.push({ + subdomain, + address: `${config.protocol}://${subdomain}.puter.site`, + uuid, + }); + } else { + const workerName = subdomain.split('.').pop(); + entry.workers.push({ + subdomain: workerName, + address: `https://${workerName}.puter.work`, + uuid, + }); + } + + entry.has_website = true; + } + async #batchFetchSuggestedApps (children, user) { const entries = []; const targets = [];