mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	Merge pull request #1927 from Yidadaa/bugfix-0613
feat: #1000 ready to support client-side only
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
				
			|||||||
import { ACCESS_CODE_PREFIX } from "../constant";
 | 
					import { ACCESS_CODE_PREFIX } from "../constant";
 | 
				
			||||||
import { ChatMessage, ModelConfig, ModelType, useAccessStore } from "../store";
 | 
					import { ChatMessage, ModelType, useAccessStore } from "../store";
 | 
				
			||||||
import { ChatGPTApi } from "./platforms/openai";
 | 
					import { ChatGPTApi } from "./platforms/openai";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ROLES = ["system", "user", "assistant"] as const;
 | 
					export const ROLES = ["system", "user", "assistant"] as const;
 | 
				
			||||||
@@ -42,6 +42,27 @@ export abstract class LLMApi {
 | 
				
			|||||||
  abstract usage(): Promise<LLMUsage>;
 | 
					  abstract usage(): Promise<LLMUsage>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ProviderName = "openai" | "azure" | "claude" | "palm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Model {
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  provider: ProviderName;
 | 
				
			||||||
 | 
					  ctxlen: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface ChatProvider {
 | 
				
			||||||
 | 
					  name: ProviderName;
 | 
				
			||||||
 | 
					  apiConfig: {
 | 
				
			||||||
 | 
					    baseUrl: string;
 | 
				
			||||||
 | 
					    apiKey: string;
 | 
				
			||||||
 | 
					    summaryModel: Model;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  models: Model[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  chat: () => void;
 | 
				
			||||||
 | 
					  usage: () => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class ClientApi {
 | 
					export class ClientApi {
 | 
				
			||||||
  public llm: LLMApi;
 | 
					  public llm: LLMApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ import {
 | 
				
			|||||||
import { SideBar } from "./sidebar";
 | 
					import { SideBar } from "./sidebar";
 | 
				
			||||||
import { useAppConfig } from "../store/config";
 | 
					import { useAppConfig } from "../store/config";
 | 
				
			||||||
import { AuthPage } from "./auth";
 | 
					import { AuthPage } from "./auth";
 | 
				
			||||||
 | 
					import { getClientConfig } from "../config/client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function Loading(props: { noLogo?: boolean }) {
 | 
					export function Loading(props: { noLogo?: boolean }) {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
@@ -147,6 +148,10 @@ function Screen() {
 | 
				
			|||||||
export function Home() {
 | 
					export function Home() {
 | 
				
			||||||
  useSwitchTheme();
 | 
					  useSwitchTheme();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    console.log("[Config] got config from build time", getClientConfig());
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!useHasHydrated()) {
 | 
					  if (!useHasHydrated()) {
 | 
				
			||||||
    return <Loading />;
 | 
					    return <Loading />;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { useState, useEffect, useMemo, HTMLProps, useRef } from "react";
 | 
					import { useState, useEffect, useMemo } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import styles from "./settings.module.scss";
 | 
					import styles from "./settings.module.scss";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,6 +45,7 @@ import { ErrorBoundary } from "./error";
 | 
				
			|||||||
import { InputRange } from "./input-range";
 | 
					import { InputRange } from "./input-range";
 | 
				
			||||||
import { useNavigate } from "react-router-dom";
 | 
					import { useNavigate } from "react-router-dom";
 | 
				
			||||||
import { Avatar, AvatarPicker } from "./emoji";
 | 
					import { Avatar, AvatarPicker } from "./emoji";
 | 
				
			||||||
 | 
					import { getClientConfig } from "../config/client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function EditPromptModal(props: { id: number; onClose: () => void }) {
 | 
					function EditPromptModal(props: { id: number; onClose: () => void }) {
 | 
				
			||||||
  const promptStore = usePromptStore();
 | 
					  const promptStore = usePromptStore();
 | 
				
			||||||
@@ -541,6 +542,21 @@ export function Settings() {
 | 
				
			|||||||
              />
 | 
					              />
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
          </ListItem>
 | 
					          </ListItem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          {!accessStore.hideUserApiKey ? (
 | 
				
			||||||
 | 
					            <ListItem
 | 
				
			||||||
 | 
					              title={Locale.Settings.Endpoint.Title}
 | 
				
			||||||
 | 
					              subTitle={Locale.Settings.Endpoint.SubTitle}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              <input
 | 
				
			||||||
 | 
					                type="text"
 | 
				
			||||||
 | 
					                value={accessStore.openaiUrl}
 | 
				
			||||||
 | 
					                onChange={(e) =>
 | 
				
			||||||
 | 
					                  accessStore.updateOpenAiUrl(e.currentTarget.value)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              ></input>
 | 
				
			||||||
 | 
					            </ListItem>
 | 
				
			||||||
 | 
					          ) : null}
 | 
				
			||||||
        </List>
 | 
					        </List>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <List>
 | 
					        <List>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,3 @@
 | 
				
			|||||||
const COMMIT_ID: string = (() => {
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const childProcess = require("child_process");
 | 
					 | 
				
			||||||
    return childProcess
 | 
					 | 
				
			||||||
      .execSync('git log -1 --format="%at000" --date=unix')
 | 
					 | 
				
			||||||
      .toString()
 | 
					 | 
				
			||||||
      .trim();
 | 
					 | 
				
			||||||
  } catch (e) {
 | 
					 | 
				
			||||||
    console.error("[Build Config] No git or not from git repo.");
 | 
					 | 
				
			||||||
    return "unknown";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const getBuildConfig = () => {
 | 
					export const getBuildConfig = () => {
 | 
				
			||||||
  if (typeof process === "undefined") {
 | 
					  if (typeof process === "undefined") {
 | 
				
			||||||
    throw Error(
 | 
					    throw Error(
 | 
				
			||||||
@@ -18,7 +5,23 @@ export const getBuildConfig = () => {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const COMMIT_ID: string = (() => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const childProcess = require("child_process");
 | 
				
			||||||
 | 
					      return childProcess
 | 
				
			||||||
 | 
					        .execSync('git log -1 --format="%at000" --date=unix')
 | 
				
			||||||
 | 
					        .toString()
 | 
				
			||||||
 | 
					        .trim();
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      console.error("[Build Config] No git or not from git repo.");
 | 
				
			||||||
 | 
					      return "unknown";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    commitId: COMMIT_ID,
 | 
					    commitId: COMMIT_ID,
 | 
				
			||||||
 | 
					    buildMode: process.env.BUILD_MODE ?? "standalone",
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type BuildConfig = ReturnType<typeof getBuildConfig>;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								app/config/client.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app/config/client.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import { BuildConfig, getBuildConfig } from "./build";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getClientConfig() {
 | 
				
			||||||
 | 
					  if (typeof document !== "undefined") {
 | 
				
			||||||
 | 
					    // client side
 | 
				
			||||||
 | 
					    return JSON.parse(queryMeta("config")) as BuildConfig;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (typeof process !== "undefined") {
 | 
				
			||||||
 | 
					    // server side
 | 
				
			||||||
 | 
					    return getBuildConfig();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function queryMeta(key: string, defaultValue?: string): string {
 | 
				
			||||||
 | 
					  let ret: string;
 | 
				
			||||||
 | 
					  if (document) {
 | 
				
			||||||
 | 
					    const meta = document.head.querySelector(
 | 
				
			||||||
 | 
					      `meta[name='${key}']`,
 | 
				
			||||||
 | 
					    ) as HTMLMetaElement;
 | 
				
			||||||
 | 
					    ret = meta?.content ?? "";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    ret = defaultValue ?? "";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,6 +10,7 @@ declare global {
 | 
				
			|||||||
      VERCEL?: string;
 | 
					      VERCEL?: string;
 | 
				
			||||||
      HIDE_USER_API_KEY?: string; // disable user's api key input
 | 
					      HIDE_USER_API_KEY?: string; // disable user's api key input
 | 
				
			||||||
      DISABLE_GPT4?: string; // allow user to use gpt-4 or not
 | 
					      DISABLE_GPT4?: string; // allow user to use gpt-4 or not
 | 
				
			||||||
 | 
					      BUILD_MODE?: "standalone" | "export";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ export const UPDATE_URL = `${REPO_URL}#keep-updated`;
 | 
				
			|||||||
export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`;
 | 
					export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`;
 | 
				
			||||||
export const FETCH_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`;
 | 
					export const FETCH_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`;
 | 
				
			||||||
export const RUNTIME_CONFIG_DOM = "danger-runtime-config";
 | 
					export const RUNTIME_CONFIG_DOM = "danger-runtime-config";
 | 
				
			||||||
 | 
					export const DEFAULT_API_HOST = "https://chatgpt.nextweb.fun/api/proxy";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export enum Path {
 | 
					export enum Path {
 | 
				
			||||||
  Home = "/",
 | 
					  Home = "/",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,7 @@ import "./styles/globals.scss";
 | 
				
			|||||||
import "./styles/markdown.scss";
 | 
					import "./styles/markdown.scss";
 | 
				
			||||||
import "./styles/highlight.scss";
 | 
					import "./styles/highlight.scss";
 | 
				
			||||||
import { getBuildConfig } from "./config/build";
 | 
					import { getBuildConfig } from "./config/build";
 | 
				
			||||||
 | 
					import { getClientConfig } from "./config/client";
 | 
				
			||||||
const buildConfig = getBuildConfig();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const metadata = {
 | 
					export const metadata = {
 | 
				
			||||||
  title: "ChatGPT Next Web",
 | 
					  title: "ChatGPT Next Web",
 | 
				
			||||||
@@ -32,7 +31,7 @@ export default function RootLayout({
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <html lang="en">
 | 
					    <html lang="en">
 | 
				
			||||||
      <head>
 | 
					      <head>
 | 
				
			||||||
        <meta name="version" content={buildConfig.commitId} />
 | 
					        <meta name="config" content={JSON.stringify(getClientConfig())} />
 | 
				
			||||||
        <link rel="manifest" href="/site.webmanifest"></link>
 | 
					        <link rel="manifest" href="/site.webmanifest"></link>
 | 
				
			||||||
        <script src="/serviceWorkerRegister.js" defer></script>
 | 
					        <script src="/serviceWorkerRegister.js" defer></script>
 | 
				
			||||||
      </head>
 | 
					      </head>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -180,6 +180,10 @@ const cn = {
 | 
				
			|||||||
      SubTitle: "管理员已开启加密访问",
 | 
					      SubTitle: "管理员已开启加密访问",
 | 
				
			||||||
      Placeholder: "请输入访问密码",
 | 
					      Placeholder: "请输入访问密码",
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    Endpoint: {
 | 
				
			||||||
 | 
					      Title: "接口地址",
 | 
				
			||||||
 | 
					      SubTitle: "除默认地址外,必须包含 http(s)://",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    Model: "模型 (model)",
 | 
					    Model: "模型 (model)",
 | 
				
			||||||
    Temperature: {
 | 
					    Temperature: {
 | 
				
			||||||
      Title: "随机性 (temperature)",
 | 
					      Title: "随机性 (temperature)",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -181,6 +181,10 @@ const en: RequiredLocaleType = {
 | 
				
			|||||||
      SubTitle: "Access control enabled",
 | 
					      SubTitle: "Access control enabled",
 | 
				
			||||||
      Placeholder: "Need Access Code",
 | 
					      Placeholder: "Need Access Code",
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    Endpoint: {
 | 
				
			||||||
 | 
					      Title: "Endpoint",
 | 
				
			||||||
 | 
					      SubTitle: "Custom endpoint must start with http(s)://",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    Model: "Model",
 | 
					    Model: "Model",
 | 
				
			||||||
    Temperature: {
 | 
					    Temperature: {
 | 
				
			||||||
      Title: "Temperature",
 | 
					      Title: "Temperature",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
import { create } from "zustand";
 | 
					import { create } from "zustand";
 | 
				
			||||||
import { persist } from "zustand/middleware";
 | 
					import { persist } from "zustand/middleware";
 | 
				
			||||||
import { StoreKey } from "../constant";
 | 
					import { DEFAULT_API_HOST, StoreKey } from "../constant";
 | 
				
			||||||
import { getHeaders } from "../client/api";
 | 
					import { getHeaders } from "../client/api";
 | 
				
			||||||
import { BOT_HELLO } from "./chat";
 | 
					import { BOT_HELLO } from "./chat";
 | 
				
			||||||
import { ALL_MODELS } from "./config";
 | 
					import { ALL_MODELS } from "./config";
 | 
				
			||||||
 | 
					import { getClientConfig } from "../config/client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface AccessControlStore {
 | 
					export interface AccessControlStore {
 | 
				
			||||||
  accessCode: string;
 | 
					  accessCode: string;
 | 
				
			||||||
@@ -15,6 +16,7 @@ export interface AccessControlStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  updateToken: (_: string) => void;
 | 
					  updateToken: (_: string) => void;
 | 
				
			||||||
  updateCode: (_: string) => void;
 | 
					  updateCode: (_: string) => void;
 | 
				
			||||||
 | 
					  updateOpenAiUrl: (_: string) => void;
 | 
				
			||||||
  enabledAccessControl: () => boolean;
 | 
					  enabledAccessControl: () => boolean;
 | 
				
			||||||
  isAuthorized: () => boolean;
 | 
					  isAuthorized: () => boolean;
 | 
				
			||||||
  fetch: () => void;
 | 
					  fetch: () => void;
 | 
				
			||||||
@@ -22,6 +24,10 @@ export interface AccessControlStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
 | 
					let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const DEFAULT_OPENAI_URL =
 | 
				
			||||||
 | 
					  getClientConfig()?.buildMode === "export" ? DEFAULT_API_HOST : "/api/openai/";
 | 
				
			||||||
 | 
					console.log("[API] default openai url", DEFAULT_OPENAI_URL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useAccessStore = create<AccessControlStore>()(
 | 
					export const useAccessStore = create<AccessControlStore>()(
 | 
				
			||||||
  persist(
 | 
					  persist(
 | 
				
			||||||
    (set, get) => ({
 | 
					    (set, get) => ({
 | 
				
			||||||
@@ -29,7 +35,7 @@ export const useAccessStore = create<AccessControlStore>()(
 | 
				
			|||||||
      accessCode: "",
 | 
					      accessCode: "",
 | 
				
			||||||
      needCode: true,
 | 
					      needCode: true,
 | 
				
			||||||
      hideUserApiKey: false,
 | 
					      hideUserApiKey: false,
 | 
				
			||||||
      openaiUrl: "/api/openai/",
 | 
					      openaiUrl: DEFAULT_OPENAI_URL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      enabledAccessControl() {
 | 
					      enabledAccessControl() {
 | 
				
			||||||
        get().fetch();
 | 
					        get().fetch();
 | 
				
			||||||
@@ -42,6 +48,9 @@ export const useAccessStore = create<AccessControlStore>()(
 | 
				
			|||||||
      updateToken(token: string) {
 | 
					      updateToken(token: string) {
 | 
				
			||||||
        set(() => ({ token }));
 | 
					        set(() => ({ token }));
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					      updateOpenAiUrl(url: string) {
 | 
				
			||||||
 | 
					        set(() => ({ openaiUrl: url }));
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      isAuthorized() {
 | 
					      isAuthorized() {
 | 
				
			||||||
        get().fetch();
 | 
					        get().fetch();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ import { create } from "zustand";
 | 
				
			|||||||
import { persist } from "zustand/middleware";
 | 
					import { persist } from "zustand/middleware";
 | 
				
			||||||
import { FETCH_COMMIT_URL, StoreKey } from "../constant";
 | 
					import { FETCH_COMMIT_URL, StoreKey } from "../constant";
 | 
				
			||||||
import { api } from "../client/api";
 | 
					import { api } from "../client/api";
 | 
				
			||||||
import { showToast } from "../components/ui-lib";
 | 
					import { getClientConfig } from "../config/client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface UpdateStore {
 | 
					export interface UpdateStore {
 | 
				
			||||||
  lastUpdate: number;
 | 
					  lastUpdate: number;
 | 
				
			||||||
@@ -17,20 +17,6 @@ export interface UpdateStore {
 | 
				
			|||||||
  updateUsage: (force?: boolean) => Promise<void>;
 | 
					  updateUsage: (force?: boolean) => Promise<void>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function queryMeta(key: string, defaultValue?: string): string {
 | 
					 | 
				
			||||||
  let ret: string;
 | 
					 | 
				
			||||||
  if (document) {
 | 
					 | 
				
			||||||
    const meta = document.head.querySelector(
 | 
					 | 
				
			||||||
      `meta[name='${key}']`,
 | 
					 | 
				
			||||||
    ) as HTMLMetaElement;
 | 
					 | 
				
			||||||
    ret = meta?.content ?? "";
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    ret = defaultValue ?? "";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ONE_MINUTE = 60 * 1000;
 | 
					const ONE_MINUTE = 60 * 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useUpdateStore = create<UpdateStore>()(
 | 
					export const useUpdateStore = create<UpdateStore>()(
 | 
				
			||||||
@@ -44,7 +30,7 @@ export const useUpdateStore = create<UpdateStore>()(
 | 
				
			|||||||
      version: "unknown",
 | 
					      version: "unknown",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      async getLatestVersion(force = false) {
 | 
					      async getLatestVersion(force = false) {
 | 
				
			||||||
        set(() => ({ version: queryMeta("version") ?? "unknown" }));
 | 
					        set(() => ({ version: getClientConfig()?.commitId ?? "unknown" }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const overTenMins = Date.now() - get().lastUpdate > 10 * ONE_MINUTE;
 | 
					        const overTenMins = Date.now() - get().lastUpdate > 10 * ONE_MINUTE;
 | 
				
			||||||
        if (!force && !overTenMins) return;
 | 
					        if (!force && !overTenMins) return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,27 @@ const nextConfig = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (mode !== "export") {
 | 
					if (mode !== "export") {
 | 
				
			||||||
 | 
					  nextConfig.headers = async () => {
 | 
				
			||||||
 | 
					    return [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        source: "/:path*",
 | 
				
			||||||
 | 
					        headers: [
 | 
				
			||||||
 | 
					          { key: "Access-Control-Allow-Credentials", value: "true" },
 | 
				
			||||||
 | 
					          { key: "Access-Control-Allow-Origin", value: "*" },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            key: "Access-Control-Allow-Methods",
 | 
				
			||||||
 | 
					            value: "GET,OPTIONS,PATCH,DELETE,POST,PUT",
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            key: "Access-Control-Allow-Headers",
 | 
				
			||||||
 | 
					            value:
 | 
				
			||||||
 | 
					              "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  nextConfig.rewrites = async () => {
 | 
					  nextConfig.rewrites = async () => {
 | 
				
			||||||
    const ret = [
 | 
					    const ret = [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@
 | 
				
			|||||||
    "build": "next build",
 | 
					    "build": "next build",
 | 
				
			||||||
    "start": "next start",
 | 
					    "start": "next start",
 | 
				
			||||||
    "lint": "next lint",
 | 
					    "lint": "next lint",
 | 
				
			||||||
 | 
					    "export": "BUILD_MODE=export yarn build",
 | 
				
			||||||
    "prompts": "node ./scripts/fetch-prompts.mjs",
 | 
					    "prompts": "node ./scripts/fetch-prompts.mjs",
 | 
				
			||||||
    "prepare": "husky install",
 | 
					    "prepare": "husky install",
 | 
				
			||||||
    "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev"
 | 
					    "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user