From e9d244068cb9fed1a82eccf5f677f5820c8d9a29 Mon Sep 17 00:00:00 2001 From: Daniel Salazar Date: Tue, 14 Jul 2026 16:04:28 -0700 Subject: [PATCH] typeify subdomains wip --- .../{SubdomainStore.js => SubdomainStore.ts} | 67 ++++++++++++++----- 1 file changed, 51 insertions(+), 16 deletions(-) rename src/backend/stores/subdomain/{SubdomainStore.js => SubdomainStore.ts} (89%) diff --git a/src/backend/stores/subdomain/SubdomainStore.js b/src/backend/stores/subdomain/SubdomainStore.ts similarity index 89% rename from src/backend/stores/subdomain/SubdomainStore.js rename to src/backend/stores/subdomain/SubdomainStore.ts index 03f3488eb..91c90c81d 100644 --- a/src/backend/stores/subdomain/SubdomainStore.js +++ b/src/backend/stores/subdomain/SubdomainStore.ts @@ -62,7 +62,16 @@ const NEGATIVE_CACHE_TTL_SECONDS = 10; export class SubdomainStore extends PuterStore { // -- Reads -------------------------------------------------------- - async getByUuid(uuid, { userId, primary = false } = {}) { + async getByUuid( + uuid: string, + { + userId, + primary = false, + }: { + userId?: number | undefined; + primary?: boolean; + } = {}, + ) { const where = userId !== undefined ? 'WHERE `uuid` = ? AND `user_id` = ?' @@ -75,7 +84,7 @@ export class SubdomainStore extends PuterStore { return rows[0] ?? null; } - async getBySubdomain(subdomain) { + async getBySubdomain(subdomain: string) { if (!subdomain) return null; const cacheKey = this.#cacheKey(subdomain); @@ -113,7 +122,7 @@ export class SubdomainStore extends PuterStore { return row; } - async listByUserId(userId, { limit = 500 } = {}) { + async listByUserId(userId: number, { limit = 500 } = {}) { const rows = await this.clients.db.read( `SELECT * FROM \`subdomains\` WHERE \`user_id\` = ? LIMIT ?`, [userId, limit], @@ -129,7 +138,7 @@ export class SubdomainStore extends PuterStore { return rows; } - async existsBySubdomain(subdomain) { + async existsBySubdomain(subdomain: string) { // Reuse the positive/negative cache populated by getBySubdomain — // creation uniqueness checks and the Workers quota path would // otherwise punch through to the DB on every call. @@ -137,7 +146,7 @@ export class SubdomainStore extends PuterStore { return row != null; } - async countByUserId(userId) { + async countByUserId(userId: number) { const rows = await this.clients.db.read( 'SELECT COUNT(*) AS n FROM `subdomains` WHERE `user_id` = ?', [userId], @@ -145,7 +154,7 @@ export class SubdomainStore extends PuterStore { return rows[0]?.n ?? 0; } - async getByDomain(domain) { + async getByDomain(domain: string) { const rows = await this.clients.db.read( 'SELECT * FROM `subdomains` WHERE `domain` = ? LIMIT 1', [domain], @@ -153,14 +162,18 @@ export class SubdomainStore extends PuterStore { return rows[0] ?? null; } - async listByDomain(domain) { + async listByDomain(domain: string) { return this.clients.db.read( 'SELECT * FROM `subdomains` WHERE `domain` = ?', [domain], ); } - async listByUserIdAndPrefix(userId, prefix, extra = {}) { + async listByUserIdAndPrefix( + userId: number, + prefix: string, + extra: { appId?: number } = {}, + ) { if (!userId || prefix == null) return []; const like = `${prefix}%`; @@ -190,6 +203,13 @@ export class SubdomainStore extends PuterStore { associatedAppId = null, appOwner = null, preambleVersion = null, + }: { + userId: number; + subdomain: string; + rootDirId?: number | null; + associatedAppId?: number | null; + appOwner?: number | null; + preambleVersion?: string | null; }) { if (!userId || !subdomain) { throw new Error('create: userId and subdomain are required'); @@ -226,8 +246,16 @@ export class SubdomainStore extends PuterStore { return row; } - async update(uuid, patch, { userId } = {}) { - const allowed = {}; + async update( + uuid: string, + patch: unknown, + { + userId, + }: { + userId?: number | undefined; + } = {}, + ) { + const allowed: unknown = {}; for (const [k, v] of Object.entries(patch)) { if (READ_ONLY_COLUMNS.has(k)) continue; allowed[k] = v; @@ -284,7 +312,14 @@ export class SubdomainStore extends PuterStore { return after; } - async deleteByUuid(uuid, { userId } = {}) { + async deleteByUuid( + uuid: string, + { + userId, + }: { + userId?: number | undefined; + } = {}, + ) { const row = await this.getByUuid(uuid, { userId }); const where = @@ -313,15 +348,15 @@ export class SubdomainStore extends PuterStore { // -- Internals ---------------------------------------------------- - #cacheKey(subdomain) { + #cacheKey(subdomain: string) { return `${CACHE_KEY_PREFIX}:name:${subdomain}`; } - #prefixListTrackerKey(userId) { + #prefixListTrackerKey(userId: number) { return `${CACHE_KEY_PREFIX}:listByUserPrefixKeys:${userId}`; } - async #refreshCache(row) { + async #refreshCache(row: { subdomain?: string }) { if (!row?.subdomain) return; await this.publishCacheKeys({ keys: [this.#cacheKey(row.subdomain)], @@ -336,7 +371,7 @@ export class SubdomainStore extends PuterStore { // renamed subdomain keeps showing up under its old folder in the GUI // (website badge, "associated websites" popover) until the entry's // independent TTL expires. - async #invalidateRootDirEntry(rootDirId) { + async #invalidateRootDirEntry(rootDirId: number | null | undefined) { if (rootDirId == null) return; const id = typeof rootDirId === 'number' ? rootDirId : Number(rootDirId); @@ -350,7 +385,7 @@ export class SubdomainStore extends PuterStore { } } - async #invalidatePrefixListsForUser(userId) { + async #invalidatePrefixListsForUser(userId: number) { if (userId == null) return; const trackerKey = this.#prefixListTrackerKey(userId); let cacheKeys = [];