-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Shared SST code for example deployments (#2270)
Co-authored-by: Valter Balegas <[email protected]>
- Loading branch information
Showing
29 changed files
with
713 additions
and
1,422 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
module.exports = { | ||
env: { | ||
browser: true, | ||
es2021: true, | ||
node: true, | ||
}, | ||
extends: [ | ||
`eslint:recommended`, | ||
`plugin:@typescript-eslint/recommended`, | ||
`plugin:prettier/recommended`, | ||
], | ||
parserOptions: { | ||
ecmaVersion: 2022, | ||
requireConfigFile: false, | ||
sourceType: `module`, | ||
ecmaFeatures: { | ||
jsx: true, | ||
}, | ||
}, | ||
parser: `@typescript-eslint/parser`, | ||
plugins: [`prettier`], | ||
rules: { | ||
quotes: [`error`, `backtick`], | ||
'no-unused-vars': `off`, | ||
'@typescript-eslint/no-unused-vars': [ | ||
`error`, | ||
{ | ||
argsIgnorePattern: `^_`, | ||
varsIgnorePattern: `^_`, | ||
caughtErrorsIgnorePattern: `^_`, | ||
}, | ||
], | ||
}, | ||
ignorePatterns: [`**/node_modules/**`, `.eslintrc.cjs`], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"semi": false, | ||
"singleQuote": true, | ||
"tabWidth": 2, | ||
"trailingComma": "es5" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { execSync } from 'node:child_process' | ||
import { createNeonDb, getNeonConnectionString } from './neon' | ||
|
||
async function addDatabaseToElectric({ | ||
dbUri, | ||
}: { | ||
dbUri: string | ||
}): Promise<{ id: string; source_secret: string }> { | ||
const adminApi = process.env.ELECTRIC_ADMIN_API | ||
const teamId = process.env.ELECTRIC_TEAM_ID | ||
|
||
if (!adminApi || !teamId) { | ||
throw new Error(`ELECTRIC_ADMIN_API or ELECTRIC_TEAM_ID is not set`) | ||
} | ||
|
||
const adminApiTokenId = process.env.ELECTRIC_ADMIN_API_TOKEN_ID | ||
const adminApiTokenSecret = process.env.ELECTRIC_ADMIN_API_TOKEN_SECRET | ||
if (!adminApiTokenId || !adminApiTokenSecret) { | ||
throw new Error( | ||
`ADMIN_API_TOKEN_CLIENT_ID or ADMIN_API_TOKEN_CLIENT_SECRET is not set` | ||
) | ||
} | ||
|
||
const result = await fetch(`${adminApi}/v1/sources`, { | ||
method: `PUT`, | ||
headers: { | ||
'Content-Type': `application/json`, | ||
'CF-Access-Client-Id': adminApiTokenId, | ||
'CF-Access-Client-Secret': adminApiTokenSecret, | ||
}, | ||
body: JSON.stringify({ | ||
database_url: dbUri, | ||
region: `us-east-1`, | ||
team_id: teamId, | ||
}), | ||
}) | ||
|
||
if (!result.ok) { | ||
throw new Error( | ||
`Could not add database to Electric (${result.status}): ${await result.text()}` | ||
) | ||
} | ||
|
||
return await result.json() | ||
} | ||
|
||
function applyMigrations( | ||
dbUri: string, | ||
migrationsDir: string = `./db/migrations` | ||
) { | ||
execSync(`pnpm exec pg-migrations apply --directory ${migrationsDir}`, { | ||
env: { | ||
...process.env, | ||
DATABASE_URL: dbUri, | ||
}, | ||
}) | ||
} | ||
|
||
export function createDatabaseForCloudElectric({ | ||
dbName, | ||
migrationsDirectory, | ||
}: { | ||
dbName: string | ||
migrationsDirectory: string | ||
}) { | ||
const neonProjectId = process.env.NEON_PROJECT_ID | ||
if (!neonProjectId) { | ||
throw new Error(`NEON_PROJECT_ID is not set`) | ||
} | ||
|
||
const project = neon.getProjectOutput({ | ||
id: neonProjectId, | ||
}) | ||
const { ownerName, dbName: resultingDbName } = createNeonDb({ | ||
projectId: project.id, | ||
branchId: project.defaultBranchId, | ||
dbName, | ||
}) | ||
|
||
const databaseUri = getNeonConnectionString({ | ||
project, | ||
roleName: ownerName, | ||
databaseName: resultingDbName, | ||
pooled: false, | ||
}) | ||
const pooledDatabaseUri = getNeonConnectionString({ | ||
project, | ||
roleName: ownerName, | ||
databaseName: resultingDbName, | ||
pooled: true, | ||
}) | ||
|
||
if (migrationsDirectory) { | ||
databaseUri.apply((uri) => applyMigrations(uri, migrationsDirectory)) | ||
} | ||
|
||
const electricInfo = databaseUri.apply((dbUri) => | ||
addDatabaseToElectric({ dbUri }) | ||
) | ||
|
||
return { | ||
sourceId: electricInfo.id, | ||
sourceSecret: electricInfo.source_secret, | ||
databaseUri, | ||
pooledDatabaseUri, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export function getSharedCluster(serviceName: string): sst.aws.Cluster { | ||
const sharedInfraVpcId = process.env.SHARED_INFRA_VPC_ID | ||
const sharedInfraClusterArn = process.env.SHARED_INFRA_CLUSTER_ARN | ||
if (!sharedInfraVpcId || !sharedInfraClusterArn) { | ||
throw new Error( | ||
`SHARED_INFRA_VPC_ID or SHARED_INFRA_CLUSTER_ARN is not set` | ||
) | ||
} | ||
|
||
return sst.aws.Cluster.get(`${serviceName}-cluster`, { | ||
id: sharedInfraClusterArn, | ||
vpc: sst.aws.Vpc.get(`${serviceName}-vpc`, sharedInfraVpcId), | ||
}) | ||
} | ||
|
||
export const isProduction = () => | ||
$app.stage.toLocaleLowerCase() === `production` |
Oops, something went wrong.