From 639616ce7352ed617b0de1e390c0f62e76c8a23c Mon Sep 17 00:00:00 2001 From: Wanjohi Date: Fri, 19 Sep 2025 01:25:29 +0300 Subject: [PATCH] feat: Add database --- .env.example | 1 + bun.lock | 24 ++--- cloud/infra/api.ts | 0 cloud/infra/auth.ts | 0 cloud/infra/database.ts | 45 ++++++++++ cloud/infra/k8s.ts | 0 cloud/packages/core/sst-env.d.ts | 2 +- cloud/packages/functions/sst-env.d.ts | 2 +- cloud/packages/maitred/sst-env.d.ts | 2 +- package.json | 2 +- packages/play-standalone/sst-env.d.ts | 9 ++ sst-env.d.ts | 123 +------------------------- sst.config.ts | 13 +-- 13 files changed, 77 insertions(+), 146 deletions(-) delete mode 100644 cloud/infra/api.ts delete mode 100644 cloud/infra/auth.ts create mode 100644 cloud/infra/database.ts delete mode 100644 cloud/infra/k8s.ts create mode 100644 packages/play-standalone/sst-env.d.ts diff --git a/.env.example b/.env.example index bb68773c..392f2afa 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ CLOUDFLARE_API_TOKEN= +NEON_API_TOKEN= diff --git a/bun.lock b/bun.lock index 9a79e044..ef6ac29c 100644 --- a/bun.lock +++ b/bun.lock @@ -4,7 +4,7 @@ "": { "name": "nestri", "dependencies": { - "sst": "^3.17.8", + "sst": "^3.17.13", }, "devDependencies": { "@cloudflare/workers-types": "4.20240821.1", @@ -1125,7 +1125,7 @@ "@types/basic-auth": ["@types/basic-auth@1.1.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-dKcUeixGuZn8pBjcUrf1N7x5K6lWuKuwHHitM2IZ4vwZUDWEhhNtwCWiba8jTA9zn0GQQ+fTFkWpKx8pOU/enw=="], - "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + "@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="], "@types/bunyan": ["@types/bunyan@1.8.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ=="], @@ -2789,23 +2789,23 @@ "ssri": ["ssri@10.0.6", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ=="], - "sst": ["sst@3.17.8", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.17.8", "sst-darwin-x64": "3.17.8", "sst-linux-arm64": "3.17.8", "sst-linux-x64": "3.17.8", "sst-linux-x86": "3.17.8", "sst-win32-arm64": "3.17.8", "sst-win32-x64": "3.17.8", "sst-win32-x86": "3.17.8" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-P/a9/ZsjtQRrTBerBMO1ODaVa5HVTmNLrQNJiYvu2Bgd0ov+vefQeHv6oima8HLlPwpDIPS2gxJk8BZrTZMfCA=="], + "sst": ["sst@3.17.13", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.17.13", "sst-darwin-x64": "3.17.13", "sst-linux-arm64": "3.17.13", "sst-linux-x64": "3.17.13", "sst-linux-x86": "3.17.13", "sst-win32-arm64": "3.17.13", "sst-win32-x64": "3.17.13", "sst-win32-x86": "3.17.13" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-NaNTZL7uk2AsXzPBySQy7aqXlStXorR+bA785NxvCbskwkc44nVSQcEsvX5tdsD6/jrWpw9tDy4sStv2ycLAng=="], - "sst-darwin-arm64": ["sst-darwin-arm64@3.17.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-50P6YRMnZVItZUfB0+NzqMww2mmm4vB3zhTVtWUtGoXeiw78g1AEnVlmS28gYXPHM1P987jTvR7EON9u9ig/Dg=="], + "sst-darwin-arm64": ["sst-darwin-arm64@3.17.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HZaDReT/c+2CcEnFkYjMty63II2ckQrUniiSdoEH6eAWyU1Iy7UwKK4I2GYm+5dy9xeSBaOKga6FMdLqFxIiUg=="], - "sst-darwin-x64": ["sst-darwin-x64@3.17.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-P0pnMHCmpkpcsxkWpilmeoD79LkbkoIcv6H0aeM9ArT/71/JBhvqH+HjMHSJCzni/9uR6er+nH5F+qol0UO6Bw=="], + "sst-darwin-x64": ["sst-darwin-x64@3.17.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-1DlYMrmrI5RY3/Ob039JatgvDKZ5QNtyRkVu0WcnsOvcxFE4dzrCiYKYHg2A+FMDl+H1qcwy2gGA3BTwC9in1w=="], - "sst-linux-arm64": ["sst-linux-arm64@3.17.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-vun54YA/UzprCu9p8BC4rMwFU5Cj9xrHAHYLYUp/yq4H0pfmBIiQM62nsfIKizRThe/TkBFy60EEi9myf6raYA=="], + "sst-linux-arm64": ["sst-linux-arm64@3.17.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-A4+ZamchUdaX0pqvYWZ+r7OP1bruwEj9qgWT5kU7Q5pqaotIsEitYQi0q9nZFKH+5mXYesUwSy5FA+Q8T3X/Rg=="], - "sst-linux-x64": ["sst-linux-x64@3.17.8", "", { "os": "linux", "cpu": "x64" }, "sha512-HqByCaLE2gEJbM20P1QRd+GqDMAiieuU53FaZA1F+AGxQi+kR82NWjrPqFcMj4dMYg8w/TWXuV+G5+PwoUmpDw=="], + "sst-linux-x64": ["sst-linux-x64@3.17.13", "", { "os": "linux", "cpu": "x64" }, "sha512-yhKZc5CojqjB2DnyeVka5jeRb4oc3lBx8Qf6or0w4cs47SBIqyvO0iR/3IeKvRRL1hiEUeUF8r/q83rQo9jZMw=="], - "sst-linux-x86": ["sst-linux-x86@3.17.8", "", { "os": "linux", "cpu": "none" }, "sha512-bCd6QM3MejfSmdvg8I/k+aUJQIZEQJg023qmN78fv00vwlAtfECvY7tjT9E2m3LDp33pXrcRYbFOQzPu+tWFfA=="], + "sst-linux-x86": ["sst-linux-x86@3.17.13", "", { "os": "linux", "cpu": "none" }, "sha512-G1FIUmpUaECB/3CV5EO/y1QmV5mQ8RUkFeZq64oyILEEaMzSWWKz0glHzQ3+p316VE74MzbktiWRqsCKQy8GeA=="], - "sst-win32-arm64": ["sst-win32-arm64@3.17.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-pilx0n8gm4aHJae/vNiqIwZkWF3tdwWzD/ON7hkytw+CVSZ0FXtyFW/yO/+2u3Yw0Kj0lSWPnUqYgm/eHPLwQA=="], + "sst-win32-arm64": ["sst-win32-arm64@3.17.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-9uCiIXmsGoxGeNWgM81x/d6V/vecjoiHXhBUPDGlQ1Dct1SbtHAgaf/g2ec5XwSQb9B/tne4qk81eMlTl83Z1A=="], - "sst-win32-x64": ["sst-win32-x64@3.17.8", "", { "os": "win32", "cpu": "x64" }, "sha512-Jb0FVRyiOtESudF1V8ucW65PuHrx/iOHUamIO0JnbujWNHZBTRPB2QHN1dbewgkueYDaCmyS8lvuIImLwYJnzQ=="], + "sst-win32-x64": ["sst-win32-x64@3.17.13", "", { "os": "win32", "cpu": "x64" }, "sha512-hTuj4rFSCI/9tX4NMUpNJ69Q9td/giekELDRNv03ys8TpJGoGvPT8D6VD1eX7j1CQnOZIgeEphfW9WmCXkLaIA=="], - "sst-win32-x86": ["sst-win32-x86@3.17.8", "", { "os": "win32", "cpu": "none" }, "sha512-oVmFa/PoElQmfnGJlB0w6rPXiYuldiagO6AbrLMT/6oAnWerLQ8Uhv9tJWfMh3xtPLImQLTjxDo1v0AIzEv9QA=="], + "sst-win32-x86": ["sst-win32-x86@3.17.13", "", { "os": "win32", "cpu": "none" }, "sha512-AuMDGux+H1kPckKJ7Szgi04EpBoOKh/v5zFNAPjvWSkcWcGZ+hsBUx3h/FO/AkGK3RnlLMRj4CQQLoa10RSSIg=="], "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="], @@ -3849,7 +3849,7 @@ "@smithy/util-waiter/@smithy/types": ["@smithy/types@4.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA=="], - "@types/bun/bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + "@types/bun/bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="], "@vanilla-extract/css/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], diff --git a/cloud/infra/api.ts b/cloud/infra/api.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/cloud/infra/auth.ts b/cloud/infra/auth.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/cloud/infra/database.ts b/cloud/infra/database.ts new file mode 100644 index 00000000..536dec37 --- /dev/null +++ b/cloud/infra/database.ts @@ -0,0 +1,45 @@ +const dbProject = neon.getProjectOutput({ + id: "curly-fire-59112557", +}); + +const dbBranchId = + $app.stage !== "production" + ? new neon.Branch("NeonBranch", { + parentId: dbProject.defaultBranchId, + projectId: dbProject.id, + name: $app.stage, + }).id + : dbProject.defaultBranchId; + +const dbEndpoint = new neon.Endpoint("NeonEndpoint", { + projectId: dbProject.id, + branchId: dbBranchId, + poolerEnabled: true, + type: "read_write", +}); + +const dbRole = new neon.Role("NeonRole", { + name: `nestri-${$app.stage}-role`, + branchId: dbBranchId, + projectId: dbProject.id, +}); + +const db = new neon.Database( + "NeonDatabase", + { + branchId: dbBranchId, + projectId: dbProject.id, + ownerName: dbRole.name, + name: `nestri-${$app.stage}`, + }, + { dependsOn: [dbRole] }, +); + +export const database = new sst.Linkable("Database", { + properties: { + name: db.name, + user: dbRole.name, + host: dbEndpoint.host, + password: dbRole.password, + }, +}); diff --git a/cloud/infra/k8s.ts b/cloud/infra/k8s.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/cloud/packages/core/sst-env.d.ts b/cloud/packages/core/sst-env.d.ts index b6a7e906..9b9de732 100644 --- a/cloud/packages/core/sst-env.d.ts +++ b/cloud/packages/core/sst-env.d.ts @@ -3,7 +3,7 @@ /* eslint-disable */ /* deno-fmt-ignore-file */ -/// +/// import "sst" export {} \ No newline at end of file diff --git a/cloud/packages/functions/sst-env.d.ts b/cloud/packages/functions/sst-env.d.ts index b6a7e906..9b9de732 100644 --- a/cloud/packages/functions/sst-env.d.ts +++ b/cloud/packages/functions/sst-env.d.ts @@ -3,7 +3,7 @@ /* eslint-disable */ /* deno-fmt-ignore-file */ -/// +/// import "sst" export {} \ No newline at end of file diff --git a/cloud/packages/maitred/sst-env.d.ts b/cloud/packages/maitred/sst-env.d.ts index b6a7e906..9b9de732 100644 --- a/cloud/packages/maitred/sst-env.d.ts +++ b/cloud/packages/maitred/sst-env.d.ts @@ -3,7 +3,7 @@ /* eslint-disable */ /* deno-fmt-ignore-file */ -/// +/// import "sst" export {} \ No newline at end of file diff --git a/package.json b/package.json index 88d1150e..a4f9211f 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,6 @@ "cloud/packages/*" ], "dependencies": { - "sst": "^3.17.8" + "sst": "^3.17.13" } } diff --git a/packages/play-standalone/sst-env.d.ts b/packages/play-standalone/sst-env.d.ts new file mode 100644 index 00000000..b6a7e906 --- /dev/null +++ b/packages/play-standalone/sst-env.d.ts @@ -0,0 +1,9 @@ +/* This file is auto-generated by SST. Do not edit. */ +/* tslint:disable */ +/* eslint-disable */ +/* deno-fmt-ignore-file */ + +/// + +import "sst" +export {} \ No newline at end of file diff --git a/sst-env.d.ts b/sst-env.d.ts index 65e99aa6..f2ab5110 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -6,131 +6,12 @@ import "sst" declare module "sst" { export interface Resource { - "Api": { - "type": "sst.aws.Router" - "url": string - } - "ApiFn": { - "name": string - "type": "sst.aws.Function" - "url": string - } - "Auth": { - "type": "sst.aws.Auth" - "url": string - } - "Bus": { - "arn": string - "name": string - "type": "sst.aws.Bus" - } - "CDNRouter": { - "type": "sst.aws.Router" - "url": string - } "Database": { - "clusterArn": string - "database": string "host": string + "name": string "password": string - "port": number - "reader": string - "secretArn": string - "type": "sst.aws.Aurora" - "username": string - } - "DiscordClientID": { - "type": "sst.sst.Secret" - "value": string - } - "DiscordClientSecret": { - "type": "sst.sst.Secret" - "value": string - } - "Dlq": { - "type": "sst.aws.Queue" - "url": string - } - "Email": { - "configSet": string - "sender": string - "type": "sst.aws.Email" - } - "GithubClientID": { - "type": "sst.sst.Secret" - "value": string - } - "GithubClientSecret": { - "type": "sst.sst.Secret" - "value": string - } - "NestriFamilyMonthly": { - "type": "sst.sst.Secret" - "value": string - } - "NestriFamilyYearly": { - "type": "sst.sst.Secret" - "value": string - } - "NestriFreeMonthly": { - "type": "sst.sst.Secret" - "value": string - } - "NestriProMonthly": { - "type": "sst.sst.Secret" - "value": string - } - "NestriProYearly": { - "type": "sst.sst.Secret" - "value": string - } - "PolarSecret": { - "type": "sst.sst.Secret" - "value": string - } - "PolarWebhookSecret": { - "type": "sst.sst.Secret" - "value": string - } - "Realtime": { - "authorizer": string - "endpoint": string - "type": "sst.aws.Realtime" - } - "RetryQueue": { - "type": "sst.aws.Queue" - "url": string - } - "SteamApiKey": { - "type": "sst.sst.Secret" - "value": string - } - "Storage": { - "name": string - "type": "sst.aws.Bucket" - } - "Urls": { - "api": string - "auth": string - "site": string "type": "sst.sst.Linkable" - } - "VPC": { - "bastion": string - "type": "sst.aws.Vpc" - } - "Web": { - "type": "sst.aws.StaticSite" - "url": string - } - "Zero": { - "service": string - "type": "sst.aws.Service" - "url": string - } - "ZeroStorage": { - "name": string - "type": "sst.aws.Bucket" + "user": string } } } diff --git a/sst.config.ts b/sst.config.ts index 203edd47..453b2bf9 100644 --- a/sst.config.ts +++ b/sst.config.ts @@ -5,22 +5,17 @@ export default $config({ name: "nestri", removal: input?.stage === "production" ? "retain" : "remove", protect: ["production"].includes(input?.stage), - home: "aws", + home: "cloudflare", providers: { - aws: { - region: "us-east-1", - profile: - input.stage === "production" ? "nestri-production" : "nestri-dev", - }, - cloudflare: "6.2.0", + cloudflare: "6.6.0", random: "4.17.0", command: "1.0.2", + neon: "0.9.0", }, }; }, async run() { - const fs = await import("fs") - + const fs = await import("fs"); const outputs = {}; for (const value of fs.readdirSync("./cloud/infra/")) { const result = await import("./cloud/infra/" + value);