diff --git a/.env.development b/.env.development new file mode 100644 index 00000000..f095626b --- /dev/null +++ b/.env.development @@ -0,0 +1,82 @@ + +# Prisma +DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres" + +# Zoekt +ZOEKT_WEBSERVER_URL="http://localhost:6070" +# SHARD_MAX_MATCH_COUNT=10000 +# TOTAL_MAX_MATCH_COUNT=100000 +# The command to use for generating ctags. +CTAGS_COMMAND=ctags +# logging, strict +SRC_TENANT_ENFORCEMENT_MODE=strict + +# Auth.JS +# You can generate a new secret with: +# openssl rand -base64 33 +# @see: https://authjs.dev/getting-started/deployment#auth_secret +AUTH_SECRET="secret" +AUTH_URL="http://localhost:3000" +# AUTH_CREDENTIALS_LOGIN_ENABLED=true +# AUTH_GITHUB_CLIENT_ID="" +# AUTH_GITHUB_CLIENT_SECRET="" +# AUTH_GOOGLE_CLIENT_ID="" +# AUTH_GOOGLE_CLIENT_SECRET="" + +# Email +# EMAIL_FROM="" # The from address for transactional emails. +# SMTP_CONNECTION_URL="" # The SMTP connection URL for transactional emails. + +# PostHog +# POSTHOG_PAPIK="" +# NEXT_PUBLIC_POSTHOG_PAPIK="" + +# Sentry +# SENTRY_BACKEND_DSN="" +# NEXT_PUBLIC_SENTRY_WEBAPP_DSN="" +# SENTRY_ENVIRONMENT="dev" +# NEXT_PUBLIC_SENTRY_ENVIRONMENT="dev" +# SENTRY_AUTH_TOKEN= + +# Logtail +# LOGTAIL_TOKEN="" +# LOGTAIL_HOST="" + +# Redis +REDIS_URL="redis://localhost:6379" + +# Stripe +# STRIPE_SECRET_KEY: z.string().optional(), +# STRIPE_PRODUCT_ID: z.string().optional(), +# STRIPE_WEBHOOK_SECRET: z.string().optional(), + +# Misc + +# Set during docker build of application +# Used to disable env var validation at build time +# DOCKER_BUILD=1 + +# Generated using: +# openssl rand -base64 24 +SOURCEBOT_ENCRYPTION_KEY="secret" + +SOURCEBOT_LOG_LEVEL="debug" # valid values: info, debug, warn, error +SOURCEBOT_TELEMETRY_DISABLED=true # Disables telemetry collection + +# Code-host fallback tokens +# FALLBACK_GITHUB_TOKEN="" +# FALLBACK_GITLAB_TOKEN="" +# FALLBACK_GITEA_TOKEN="" + +# Controls the number of concurrent indexing jobs that can run at once +# INDEX_CONCURRENCY_MULTIPLE= + +# Controls the polling interval for the web app +# NEXT_PUBLIC_POLLING_INTERVAL_MS= + +# Controls the version of the web app +# NEXT_PUBLIC_SOURCEBOT_VERSION= + +# CONFIG_MAX_REPOS_NO_TOKEN= +# SOURCEBOT_ROOT_DOMAIN= +# NODE_ENV= \ No newline at end of file diff --git a/package.json b/package.json index 171f3164..3f573804 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,20 @@ "scripts": { "build": "yarn workspaces run build", "test": "yarn workspaces run test", - "dev": "yarn workspace @sourcebot/db prisma:migrate:dev && cross-env npm-run-all --print-label --parallel dev:zoekt dev:backend dev:web", - "dev:zoekt": "export PATH=\"$PWD/bin:$PATH\" && export SRC_TENANT_ENFORCEMENT_MODE=strict && zoekt-webserver -index .sourcebot/index -rpc", - "dev:backend": "yarn workspace @sourcebot/backend dev:watch", - "dev:web": "yarn workspace @sourcebot/web dev" + + "dev": "yarn dev:prisma:migrate && npm-run-all --print-label --parallel dev:zoekt dev:backend dev:web", + "with-env": "cross-env PATH=\"$PWD/bin:$PATH\" dotenv -e .env.development -c --", + "dev:zoekt": "yarn with-env zoekt-webserver -index .sourcebot/index -rpc", + "dev:backend": "yarn with-env yarn workspace @sourcebot/backend dev:watch", + "dev:web": "yarn with-env yarn workspace @sourcebot/web dev", + + "dev:prisma:migrate": "yarn with-env yarn workspace @sourcebot/db prisma:migrate:dev", + "dev:prisma:studio": "yarn with-env yarn workspace @sourcebot/db prisma:studio", + "dev:prisma:migrate:reset": "yarn with-env yarn workspace @sourcebot/db prisma:migrate:reset" }, "devDependencies": { "cross-env": "^7.0.3", + "dotenv-cli": "^8.0.0", "npm-run-all": "^4.1.5" } } diff --git a/packages/backend/package.json b/packages/backend/package.json index 0c91fbdb..e63c0789 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "dev:watch": "tsc-watch --preserveWatchOutput --onSuccess \"yarn dev --cacheDir ../../.sourcebot\"", - "dev": "export PATH=\"$PWD/../../bin:$PATH\" && export CTAGS_COMMAND=ctags && node ./dist/index.js", + "dev": "node ./dist/index.js", "build": "tsc", "test": "vitest --config ./vitest.config.ts" }, diff --git a/packages/backend/src/env.ts b/packages/backend/src/env.ts index 0673c2a2..6765370f 100644 --- a/packages/backend/src/env.ts +++ b/packages/backend/src/env.ts @@ -2,6 +2,9 @@ import { createEnv } from "@t3-oss/env-core"; import { z } from "zod"; import dotenv from 'dotenv'; +// Booleans are specified as 'true' or 'false' strings. +const booleanSchema = z.enum(["true", "false"]); + dotenv.config({ path: './.env', }); @@ -15,18 +18,17 @@ export const env = createEnv({ server: { SOURCEBOT_ENCRYPTION_KEY: z.string(), SOURCEBOT_LOG_LEVEL: z.enum(["info", "debug", "warn", "error"]).default("info"), - SOURCEBOT_TELEMETRY_DISABLED: z.enum(["true", "false"]).default("false"), + SOURCEBOT_TELEMETRY_DISABLED: booleanSchema.default("false"), SOURCEBOT_INSTALL_ID: z.string().default("unknown"), SOURCEBOT_VERSION: z.string().default("unknown"), POSTHOG_PAPIK: z.string().optional(), - POSTHOG_HOST: z.string().url().default('https://us.i.posthog.com'), FALLBACK_GITHUB_TOKEN: z.string().optional(), FALLBACK_GITLAB_TOKEN: z.string().optional(), FALLBACK_GITEA_TOKEN: z.string().optional(), - REDIS_URL: z.string().url().optional().default("redis://localhost:6379"), + REDIS_URL: z.string().url(), SENTRY_BACKEND_DSN: z.string().optional(), SENTRY_ENVIRONMENT: z.string().optional(), @@ -35,6 +37,7 @@ export const env = createEnv({ LOGTAIL_HOST: z.string().url().optional(), INDEX_CONCURRENCY_MULTIPLE: z.number().optional(), + DATABASE_URL: z.string().url(), }, runtimeEnv: process.env, emptyStringAsUndefined: true, diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 38efd331..fc4c612a 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -9,6 +9,33 @@ import { AppContext } from "./types.js"; import { main } from "./main.js" import { PrismaClient } from "@sourcebot/db"; +// Register handler for normal exit +process.on('exit', (code) => { + console.log(`Process is exiting with code: ${code}`); +}); + +// Register handlers for abnormal terminations +process.on('SIGINT', () => { + console.log('Process interrupted (SIGINT)'); + process.exit(130); +}); + +process.on('SIGTERM', () => { + console.log('Process terminated (SIGTERM)'); + process.exit(143); +}); + +// Register handlers for uncaught exceptions and unhandled rejections +process.on('uncaughtException', (err) => { + console.log(`Uncaught exception: ${err.message}`); + process.exit(1); +}); + +process.on('unhandledRejection', (reason, promise) => { + console.log(`Unhandled rejection at: ${promise}, reason: ${reason}`); + process.exit(1); +}); + const parser = new ArgumentParser({ description: "Sourcebot backend tool", diff --git a/packages/backend/src/posthog.ts b/packages/backend/src/posthog.ts index 1ef64755..15ae92db 100644 --- a/packages/backend/src/posthog.ts +++ b/packages/backend/src/posthog.ts @@ -8,13 +8,13 @@ if (env.POSTHOG_PAPIK) { posthog = new PostHog( env.POSTHOG_PAPIK, { - host: env.POSTHOG_HOST, + host: "https://us.i.posthog.com", } ); } export function captureEvent(event: E, properties: PosthogEventMap[E]) { - if (env.SOURCEBOT_TELEMETRY_DISABLED) { + if (env.SOURCEBOT_TELEMETRY_DISABLED === 'true') { return; } diff --git a/packages/crypto/package.json b/packages/crypto/package.json index cc32c0b4..87abf748 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,7 +1,8 @@ { "name": "@sourcebot/crypto", - "main": "dist/index.js", "version": "0.1.0", + "main": "dist/index.js", + "private": true, "scripts": { "build": "tsc", "postinstall": "yarn build" diff --git a/packages/web/src/app/posthogProvider.tsx b/packages/web/src/app/posthogProvider.tsx index e574769c..404c0ec6 100644 --- a/packages/web/src/app/posthogProvider.tsx +++ b/packages/web/src/app/posthogProvider.tsx @@ -37,7 +37,6 @@ export function PostHogProvider({ children, disabled }: PostHogProviderProps) { posthog.init(env.NEXT_PUBLIC_POSTHOG_PAPIK, { // @see next.config.mjs for path rewrites to the "/ingest" route. api_host: "/ingest", - ui_host: env.NEXT_PUBLIC_POSTHOG_UI_HOST, person_profiles: 'identified_only', capture_pageview: false, // @nocheckin Disable automatic pageview capture if we're not in public demo mode autocapture: false, // Disable automatic event capture diff --git a/packages/web/src/auth.ts b/packages/web/src/auth.ts index 8fb369a2..bcac55b3 100644 --- a/packages/web/src/auth.ts +++ b/packages/web/src/auth.ts @@ -76,7 +76,7 @@ export const getProviders = () => { })); } - if (env.AUTH_CREDENTIALS_LOGIN_ENABLED) { + if (env.AUTH_CREDENTIALS_LOGIN_ENABLED === 'true') { providers.push(Credentials({ credentials: { email: {}, diff --git a/packages/web/src/env.mjs b/packages/web/src/env.mjs index 3224c1a2..702be186 100644 --- a/packages/web/src/env.mjs +++ b/packages/web/src/env.mjs @@ -1,10 +1,13 @@ import { createEnv } from "@t3-oss/env-nextjs"; import { z } from "zod"; +// Booleans are specified as 'true' or 'false' strings. +const booleanSchema = z.enum(["true", "false"]); + export const env = createEnv({ server: { // Zoekt - ZOEKT_WEBSERVER_URL: z.string().url().default('http://localhost:6070'), + ZOEKT_WEBSERVER_URL: z.string().url(), SHARD_MAX_MATCH_COUNT: z.number().default(10000), TOTAL_MAX_MATCH_COUNT: z.number().default(100000), @@ -15,7 +18,7 @@ export const env = createEnv({ AUTH_GOOGLE_CLIENT_ID: z.string().optional(), AUTH_GOOGLE_CLIENT_SECRET: z.string().optional(), AUTH_URL: z.string().url(), - AUTH_CREDENTIALS_LOGIN_ENABLED: z.boolean().default(true), + AUTH_CREDENTIALS_LOGIN_ENABLED: booleanSchema.default('true'), // Email SMTP_CONNECTION_URL: z.string().url().optional(), @@ -30,7 +33,7 @@ export const env = createEnv({ CONFIG_MAX_REPOS_NO_TOKEN: z.number().default(500), SOURCEBOT_ROOT_DOMAIN: z.string().default("localhost:3000"), NODE_ENV: z.enum(["development", "test", "production"]), - SOURCEBOT_TELEMETRY_DISABLED: z.enum(["true", "false"]).default("false"), + SOURCEBOT_TELEMETRY_DISABLED: booleanSchema.default('false'), DATABASE_URL: z.string().url(), }, // @NOTE: Make sure you destructure all client variables in the @@ -38,7 +41,6 @@ export const env = createEnv({ client: { // PostHog NEXT_PUBLIC_POSTHOG_PAPIK: z.string().optional(), - NEXT_PUBLIC_POSTHOG_UI_HOST: z.string().url().default('https://us.posthog.com'), // Misc NEXT_PUBLIC_SOURCEBOT_VERSION: z.string().default('unknown'), @@ -47,7 +49,6 @@ export const env = createEnv({ // For Next.js >= 13.4.4, you only need to destructure client variables: experimental__runtimeEnv: { NEXT_PUBLIC_POSTHOG_PAPIK: process.env.NEXT_PUBLIC_POSTHOG_PAPIK, - NEXT_PUBLIC_POSTHOG_UI_HOST: process.env.NEXT_PUBLIC_POSTHOG_UI_HOST, NEXT_PUBLIC_SOURCEBOT_VERSION: process.env.NEXT_PUBLIC_SOURCEBOT_VERSION, NEXT_PUBLIC_POLLING_INTERVAL_MS: process.env.NEXT_PUBLIC_POLLING_INTERVAL_MS, }, diff --git a/yarn.lock b/yarn.lock index f2c71041..fea2a244 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5096,7 +5096,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -5382,7 +5382,22 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.3" -dotenv@^16.3.1: +dotenv-cli@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-8.0.0.tgz#cea1519f5a06c7372a1428fca4605fcf3d50e1cf" + integrity sha512-aLqYbK7xKOiTMIRf1lDPbI+Y+Ip/wo5k3eyp6ePysVaSqbyxjyK3dK35BTxG+rmd7djf5q2UPs4noPNH+cj0Qw== + dependencies: + cross-spawn "^7.0.6" + dotenv "^16.3.0" + dotenv-expand "^10.0.0" + minimist "^1.2.6" + +dotenv-expand@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" + integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== + +dotenv@^16.3.0, dotenv@^16.3.1: version "16.4.7" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==