chore: zod validate env schema (#127)
* chore: zod validate Signed-off-by: Innei <i@innei.in> * feat: replace VITE_BUILD_TYPE with channel in app version * fix: bypass in prod Signed-off-by: Innei <i@innei.in> * fix: update Signed-off-by: Innei <i@innei.in> --------- Signed-off-by: Innei <i@innei.in> Co-authored-by: DIYgod <i@diygod.me>
This commit is contained in:
parent
5e846b9015
commit
42b68a402b
|
|
@ -10,7 +10,6 @@ env:
|
|||
VITE_IMGPROXY_URL: ${{ vars.VITE_IMGPROXY_URL }}
|
||||
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
|
||||
VITE_POSTHOG_KEY: ${{ vars.VITE_POSTHOG_KEY }}
|
||||
VITE_BUILD_TYPE: internal
|
||||
|
||||
jobs:
|
||||
release:
|
||||
|
|
|
|||
|
|
@ -12,16 +12,24 @@ export default defineConfig({
|
|||
resolve: {
|
||||
alias: {
|
||||
"@shared": resolve("src/shared/src"),
|
||||
"@env": resolve("./src/env.ts"),
|
||||
},
|
||||
},
|
||||
},
|
||||
preload: {
|
||||
resolve: {
|
||||
alias: {
|
||||
"@env": resolve("./src/env.ts"),
|
||||
},
|
||||
},
|
||||
},
|
||||
preload: {},
|
||||
renderer: {
|
||||
resolve: {
|
||||
alias: {
|
||||
"@renderer": resolve("src/renderer/src"),
|
||||
"@shared": resolve("src/shared/src"),
|
||||
"@pkg": resolve("./package.json"),
|
||||
"@env": resolve("./src/env.ts"),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
"@sentry/react": "8.9.2",
|
||||
"@sentry/vite-plugin": "2.20.1",
|
||||
"@shikijs/transformers": "1.10.0",
|
||||
"@t3-oss/env-core": "^0.10.1",
|
||||
"@tanstack/query-sync-storage-persister": "5.49.0",
|
||||
"@tanstack/react-query": "5.49.0",
|
||||
"@tanstack/react-query-persist-client": "5.49.0",
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ importers:
|
|||
'@shikijs/transformers':
|
||||
specifier: 1.10.0
|
||||
version: 1.10.0
|
||||
'@t3-oss/env-core':
|
||||
specifier: ^0.10.1
|
||||
version: 0.10.1(typescript@5.5.2)(zod@3.23.8)
|
||||
'@tanstack/query-sync-storage-persister':
|
||||
specifier: 5.49.0
|
||||
version: 5.49.0
|
||||
|
|
@ -2368,6 +2371,15 @@ packages:
|
|||
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
'@t3-oss/env-core@0.10.1':
|
||||
resolution: {integrity: sha512-GcKZiCfWks5CTxhezn9k5zWX3sMDIYf6Kaxy2Gx9YEQftFcz8hDRN56hcbylyAO3t4jQnQ5ifLawINsNgCDpOg==}
|
||||
peerDependencies:
|
||||
typescript: '>=5.0.0'
|
||||
zod: ^3.0.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
'@tailwindcss/container-queries@0.1.1':
|
||||
resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==}
|
||||
peerDependencies:
|
||||
|
|
@ -9163,6 +9175,12 @@ snapshots:
|
|||
dependencies:
|
||||
defer-to-connect: 2.0.1
|
||||
|
||||
'@t3-oss/env-core@0.10.1(typescript@5.5.2)(zod@3.23.8)':
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
optionalDependencies:
|
||||
typescript: 5.5.2
|
||||
|
||||
'@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.4)':
|
||||
dependencies:
|
||||
tailwindcss: 3.4.4
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
import { createEnv } from "@t3-oss/env-core"
|
||||
import { z } from "zod"
|
||||
|
||||
const isDev = "process" in globalThis ? process.env.NODE_ENV === "development" : import.meta.env.DEV
|
||||
export const env = createEnv({
|
||||
clientPrefix: "VITE_",
|
||||
client: {
|
||||
VITE_WEB_URL: z.string().url(),
|
||||
VITE_API_URL: z.string().url(),
|
||||
VITE_IMGPROXY_URL: z.string().url(),
|
||||
VITE_SENTRY_DSN: z.string().optional(),
|
||||
VITE_POSTHOG_KEY: z.string().optional(),
|
||||
},
|
||||
|
||||
emptyStringAsUndefined: true,
|
||||
runtimeEnv: "process" in globalThis ? process.env : import.meta.env,
|
||||
skipValidation: !isDev,
|
||||
})
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import { z } from "zod"
|
||||
|
||||
export const ReleaseTypeSchema = z.enum([
|
||||
"stable",
|
||||
"beta",
|
||||
"internal",
|
||||
])
|
||||
|
||||
export const envBuildType = (process.env.VITE_BUILD_TYPE || "internal")
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
|
||||
export const buildType = ReleaseTypeSchema.parse(envBuildType)
|
||||
|
||||
export const mode = process.env.NODE_ENV
|
||||
export const isDev = mode === "development"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { app } from "electron"
|
||||
import * as semver from "semver"
|
||||
|
||||
export const mode = process.env.NODE_ENV
|
||||
export const isDev = mode === "development"
|
||||
|
||||
export const channel = isDev ? "development" : ((semver.prerelease(app.getVersion())?.[0] as string) || "stable")
|
||||
|
|
@ -7,10 +7,13 @@ import { APP_PROTOCOL, DEEPLINK_SCHEME } from "@shared/constants"
|
|||
import { extractElectronWindowOptions } from "@shared/electron"
|
||||
import { app, BrowserWindow, session } from "electron"
|
||||
|
||||
import { env } from "../env"
|
||||
import { isDev } from "./env"
|
||||
import { initializationApp } from "./init"
|
||||
import { registerUpdater } from "./updater"
|
||||
import { createMainWindow, createWindow } from "./window"
|
||||
|
||||
if (isDev) console.info("[main] env loaded:", env)
|
||||
initializationApp()
|
||||
let mainWindow: BrowserWindow
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { getRendererHandlers } from "@egoist/tipc/main"
|
||||
import { autoUpdater } from "electron-updater"
|
||||
|
||||
import { buildType, isDev } from "../config"
|
||||
import { channel, isDev } from "../env"
|
||||
import { logger } from "../logger"
|
||||
import type { RendererHandlers } from "../renderer-handlers"
|
||||
import { getMainWindow } from "../window"
|
||||
|
|
@ -63,17 +63,17 @@ export const registerUpdater = async () => {
|
|||
const allowAutoUpdate = true
|
||||
|
||||
autoUpdater.autoDownload = false
|
||||
autoUpdater.allowPrerelease = buildType !== "stable"
|
||||
autoUpdater.allowPrerelease = channel !== "stable"
|
||||
autoUpdater.autoInstallOnAppQuit = true
|
||||
autoUpdater.autoRunAppAfterInstall = true
|
||||
|
||||
const feedUrl: Exclude<Parameters<typeof autoUpdater.setFeedURL>[0], string> = {
|
||||
channel: buildType,
|
||||
channel,
|
||||
// hack for custom provider
|
||||
provider: "custom" as "github",
|
||||
repo: "follow",
|
||||
owner: "RSSNext",
|
||||
releaseType: buildType === "stable" ? "release" : "prerelease",
|
||||
releaseType: channel === "stable" ? "release" : "prerelease",
|
||||
// @ts-expect-error hack for custom provider
|
||||
updateProvider: CustomGitHubProvider,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { queryClient } from "@renderer/lib/query-client"
|
|||
import { useEffect, useLayoutEffect } from "react"
|
||||
import { Outlet } from "react-router-dom"
|
||||
|
||||
import { env } from "../../env.js"
|
||||
import { useAppIsReady } from "./atoms/app"
|
||||
import { useUISettingKey } from "./atoms/settings/ui"
|
||||
import { Logo } from "./components/icons/logo"
|
||||
|
|
@ -11,6 +12,9 @@ import { getOS } from "./lib/utils"
|
|||
import { RootProviders } from "./providers/root-providers"
|
||||
import { handlers } from "./tipc"
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
console.info("[renderer] env loaded:", env)
|
||||
}
|
||||
function App() {
|
||||
useEffect(() => {
|
||||
const cleanup = handlers?.invalidateQuery.listen((queryKey) => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { env } from "@env"
|
||||
import type { BrowserOptions } from "@sentry/react"
|
||||
import { FetchError } from "ofetch"
|
||||
|
||||
|
|
@ -5,7 +6,7 @@ export const SentryConfig: BrowserOptions = {
|
|||
// Performance Monitoring
|
||||
tracesSampleRate: 1, // Capture 100% of the transactions
|
||||
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
|
||||
tracePropagationTargets: ["localhost", import.meta.env.VITE_API_URL],
|
||||
tracePropagationTargets: ["localhost", env.VITE_API_URL],
|
||||
// Session Replay
|
||||
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
|
||||
replaysOnErrorSampleRate: 1,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { env } from "@env"
|
||||
import { authConfigManager } from "@hono/auth-js/react"
|
||||
import { repository } from "@pkg"
|
||||
import { browserDB } from "@renderer/database"
|
||||
|
|
@ -65,7 +66,7 @@ export const initializeApp = async () => {
|
|||
|
||||
// Initialize the auth config
|
||||
authConfigManager.setConfig({
|
||||
baseUrl: import.meta.env.VITE_API_URL,
|
||||
baseUrl: env.VITE_API_URL,
|
||||
basePath: "/auth",
|
||||
credentials: "include",
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { env } from "@env"
|
||||
import { getUser } from "@renderer/atoms/user"
|
||||
|
||||
declare global {
|
||||
|
|
@ -9,7 +10,9 @@ declare global {
|
|||
export const initPostHog = async () => {
|
||||
if (import.meta.env.DEV) return
|
||||
const { default: posthog } = await import("posthog-js")
|
||||
posthog.init(import.meta.env.VITE_POSTHOG_KEY, {
|
||||
|
||||
if (env.VITE_POSTHOG_KEY === undefined) return
|
||||
posthog.init(env.VITE_POSTHOG_KEY, {
|
||||
person_profiles: "identified_only",
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { env } from "@env"
|
||||
import { version } from "@pkg"
|
||||
import { channel } from "@renderer/lib/constants"
|
||||
import { useEffect } from "react"
|
||||
import { createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from "react-router-dom"
|
||||
|
||||
|
|
@ -11,8 +13,8 @@ export const initSentry = async () => {
|
|||
import("posthog-js").then((module) => module.default),
|
||||
])
|
||||
Sentry.init({
|
||||
dsn: import.meta.env.VITE_SENTRY_DSN,
|
||||
environment: import.meta.env.VITE_BUILD_TYPE ?? "internal",
|
||||
dsn: env.VITE_SENTRY_DSN,
|
||||
environment: channel,
|
||||
integrations: [
|
||||
Sentry.moduleMetadataIntegration(),
|
||||
Sentry.reactRouterV6BrowserTracingIntegration({
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import * as semver from "semver"
|
||||
|
||||
import { getStorageNS } from "./ns"
|
||||
|
||||
export const levels = {
|
||||
|
|
@ -83,3 +85,5 @@ export const QUERY_PERSIST_KEY = getStorageNS("REACT_QUERY_OFFLINE_CACHE")
|
|||
export const ROUTE_FEED_PENDING = "all"
|
||||
export const ROUTE_ENTRY_PENDING = "pending"
|
||||
export const ROUTE_FEED_IN_FOLDER = "folder-"
|
||||
|
||||
export const channel = import.meta.env.DEV ? "development" : ((semver.prerelease(APP_VERSION)?.[0] as string) || "stable")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { env } from "@env"
|
||||
|
||||
export const getProxyUrl = ({
|
||||
url,
|
||||
width,
|
||||
|
|
@ -6,4 +8,4 @@ export const getProxyUrl = ({
|
|||
url: string
|
||||
width: number
|
||||
height: number
|
||||
}) => `${import.meta.env.VITE_IMGPROXY_URL}/unsafe/${width}x${height}/${encodeURIComponent(url)}`
|
||||
}) => `${env.VITE_IMGPROXY_URL}/unsafe/${width}x${height}/${encodeURIComponent(url)}`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { env } from "@env"
|
||||
|
||||
export const APP_PROTOCOL = import.meta.env.DEV ? "follow-dev" : "follow"
|
||||
export const DEEPLINK_SCHEME = `${APP_PROTOCOL}://`
|
||||
|
||||
// export const WEB_URL = import.meta.env.VITE_VERCEL_URL ?? import.meta.env.VITE_WEB_URL
|
||||
export const WEB_URL = import.meta.env.VITE_WEB_URL
|
||||
export const WEB_URL = env.VITE_WEB_URL
|
||||
|
|
|
|||
|
|
@ -5,17 +5,22 @@
|
|||
"src/main/**/*",
|
||||
"src/preload/**/*",
|
||||
"types/**/*.d.ts",
|
||||
"src/shared/src/**/*"
|
||||
"src/shared/src/**/*",
|
||||
"src/env.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"types": [
|
||||
"electron-vite/node"
|
||||
],
|
||||
"moduleResolution": "Bundler",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@shared/*": [
|
||||
"src/shared/src/*"
|
||||
],
|
||||
"@env": [
|
||||
"./src/env.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@
|
|||
"src/renderer/src/**/*.tsx",
|
||||
"src/preload/*.d.ts",
|
||||
"src/shared/src/**/*",
|
||||
"types/**/*.d.ts"
|
||||
"types/**/*.d.ts",
|
||||
"src/env.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "Bundler",
|
||||
"target": "ES2022",
|
||||
"noUnusedLocals": false,
|
||||
"strict": true,
|
||||
|
|
@ -25,7 +27,8 @@
|
|||
"@shared/*": [
|
||||
"src/shared/src/*"
|
||||
],
|
||||
"@pkg": ["./package.json"]
|
||||
"@pkg": ["./package.json"],
|
||||
"@env": ["./src/env.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ interface ImportMetaEnv {
|
|||
VITE_API_URL: string
|
||||
VITE_IMGPROXY_URL: string
|
||||
VITE_SENTRY_DSN: string
|
||||
VITE_BUILD_TYPE: string
|
||||
VITE_POSTHOG_KEY: string
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export default defineConfig({
|
|||
"@renderer": resolve("src/renderer/src"),
|
||||
"@shared": resolve("src/shared/src"),
|
||||
"@pkg": resolve("./package.json"),
|
||||
"@env": resolve("./src/env.ts"),
|
||||
},
|
||||
},
|
||||
base: "/",
|
||||
|
|
|
|||
Loading…
Reference in New Issue