fix: missing subdomains and worker flags in readdir (#2772)
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
Notify HeyPuter / notify (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (24.x) (push) Has been cancelled
test / API tests (node env, api-test) (24.x) (push) Has been cancelled
test / puterjs (node env, vitest) (24.x) (push) Has been cancelled

This commit is contained in:
Daniel Salazar
2026-04-06 11:08:03 -07:00
committed by GitHub
parent 649db33763
commit 2368b2bc8f
3 changed files with 93 additions and 56 deletions
+24 -29
View File
@@ -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"
}
@@ -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;
}
@@ -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 = [];