mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-12-23 00:21:38 +03:00
Merge pull request #377 from kinode-dao/tm/ui-dev-servers
configure dev servers' proxies; fix blackscreen
This commit is contained in:
commit
553ad00d51
@ -95,7 +95,7 @@ fn make_widget() -> String {
|
|||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
fetch('/main:app_store:sys/apps/listed')
|
fetch('/main:app_store:sys/apps/listed', { credentials: 'include' })
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const container = document.getElementById('latest-apps');
|
const container = document.getElementById('latest-apps');
|
||||||
|
File diff suppressed because one or more lines are too long
@ -14,7 +14,7 @@
|
|||||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
||||||
<script type="module" crossorigin src="/main:app_store:sys/assets/index-Mr04YvPM.js"></script>
|
<script type="module" crossorigin src="/main:app_store:sys/assets/index-I5kjLT9f.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/main:app_store:sys/assets/index-fGthT1qI.css">
|
<link rel="stylesheet" crossorigin href="/main:app_store:sys/assets/index-fGthT1qI.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import Modal from "./Modal";
|
|||||||
import { getAppName } from "../utils/app";
|
import { getAppName } from "../utils/app";
|
||||||
import Loader from "./Loader";
|
import Loader from "./Loader";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import { FaU } from "react-icons/fa6";
|
||||||
|
|
||||||
interface UpdateButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
|
interface UpdateButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||||
app: AppInfo;
|
app: AppInfo;
|
||||||
@ -55,10 +56,12 @@ export default function UpdateButton({ app, isIcon = false, ...props }: UpdateBu
|
|||||||
<button
|
<button
|
||||||
{...props}
|
{...props}
|
||||||
type="button"
|
type="button"
|
||||||
className={classNames("text-sm self-start", props.className)}
|
className={classNames("text-sm self-start", props.className, {
|
||||||
|
'icon clear': isIcon
|
||||||
|
})}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
Update
|
{isIcon ? <FaU /> : 'Update'}
|
||||||
</button>
|
</button>
|
||||||
<Modal show={showModal} hide={() => setShowModal(false)}>
|
<Modal show={showModal} hide={() => setShowModal(false)}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
|
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@
|
|||||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
||||||
<script type="module" crossorigin src="/assets/index-DqBTDSfz.js"></script>
|
<script type="module" crossorigin src="/assets/index-BkgGa32-.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BS5LP50I.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BS5LP50I.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
2
kinode/packages/homepage/ui/dist/index.html
vendored
2
kinode/packages/homepage/ui/dist/index.html
vendored
@ -9,7 +9,7 @@
|
|||||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
||||||
<script type="module" crossorigin src="/assets/index-DqBTDSfz.js"></script>
|
<script type="module" crossorigin src="/assets/index-BkgGa32-.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BS5LP50I.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-BS5LP50I.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ const AllApps: React.FC<{ expanded: boolean }> = ({ expanded }) => {
|
|||||||
})}>
|
})}>
|
||||||
{apps.length === 0
|
{apps.length === 0
|
||||||
? <div>Loading apps...</div>
|
? <div>Loading apps...</div>
|
||||||
: apps.map(app => <AppDisplay app={app} />)}
|
: apps.map(app => <AppDisplay key={app.package_name} app={app} />)}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import { isMobileCheck } from "../utils/dimensions"
|
|||||||
import AppIconPlaceholder from "./AppIconPlaceholder"
|
import AppIconPlaceholder from "./AppIconPlaceholder"
|
||||||
|
|
||||||
interface AppDisplayProps {
|
interface AppDisplayProps {
|
||||||
app: HomepageApp
|
app?: HomepageApp
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppDisplay: React.FC<AppDisplayProps> = ({ app }) => {
|
const AppDisplay: React.FC<AppDisplayProps> = ({ app }) => {
|
||||||
@ -17,15 +17,15 @@ const AppDisplay: React.FC<AppDisplayProps> = ({ app }) => {
|
|||||||
|
|
||||||
return <a
|
return <a
|
||||||
className={classNames("flex-col-center gap-2 relative hover:opacity-90 transition-opacity", {
|
className={classNames("flex-col-center gap-2 relative hover:opacity-90 transition-opacity", {
|
||||||
'cursor-pointer': app.path,
|
'cursor-pointer': app?.path,
|
||||||
'cursor-not-allowed': !app.path,
|
'cursor-not-allowed': !app?.path,
|
||||||
})}
|
})}
|
||||||
id={app.package_name}
|
id={app?.package_name}
|
||||||
href={app.path}
|
href={app?.path}
|
||||||
onMouseEnter={() => setIsHovered(true)}
|
onMouseEnter={() => setIsHovered(true)}
|
||||||
onMouseLeave={() => setIsHovered(false)}
|
onMouseLeave={() => setIsHovered(false)}
|
||||||
>
|
>
|
||||||
{app.base64_icon
|
{app?.base64_icon
|
||||||
? <img
|
? <img
|
||||||
src={app.base64_icon}
|
src={app.base64_icon}
|
||||||
className={classNames('rounded', {
|
className={classNames('rounded', {
|
||||||
@ -34,12 +34,12 @@ const AppDisplay: React.FC<AppDisplayProps> = ({ app }) => {
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
: <AppIconPlaceholder
|
: <AppIconPlaceholder
|
||||||
text={app.state?.our_version || '0'}
|
text={app?.state?.our_version || '0'}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
className="h-16 w-16"
|
className="h-16 w-16"
|
||||||
/>}
|
/>}
|
||||||
<h6>{app.label}</h6>
|
<h6>{app?.label}</h6>
|
||||||
{app.path && isHovered && <button
|
{app?.path && isHovered && <button
|
||||||
className="absolute p-2 -top-2 -right-2 clear text-sm"
|
className="absolute p-2 -top-2 -right-2 clear text-sm"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -5,6 +5,7 @@ import { useEffect, useState } from "react"
|
|||||||
import { isMobileCheck } from "../utils/dimensions"
|
import { isMobileCheck } from "../utils/dimensions"
|
||||||
import classNames from "classnames"
|
import classNames from "classnames"
|
||||||
import { DragDropContext, Draggable, DropResult, Droppable } from 'react-beautiful-dnd'
|
import { DragDropContext, Draggable, DropResult, Droppable } from 'react-beautiful-dnd'
|
||||||
|
import { getFetchUrl } from "../utils/fetch"
|
||||||
|
|
||||||
const AppsDock: React.FC = () => {
|
const AppsDock: React.FC = () => {
|
||||||
const { apps } = useHomepageStore()
|
const { apps } = useHomepageStore()
|
||||||
@ -66,11 +67,12 @@ const AppsDock: React.FC = () => {
|
|||||||
|
|
||||||
console.log({ favoriteApps })
|
console.log({ favoriteApps })
|
||||||
|
|
||||||
fetch('/order', {
|
fetch(getFetchUrl('/order'), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
|
credentials: 'include',
|
||||||
body: JSON.stringify(packageNames)
|
body: JSON.stringify(packageNames)
|
||||||
})
|
})
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
@ -19,6 +19,7 @@ const Widgets = () => {
|
|||||||
package_name={package_name}
|
package_name={package_name}
|
||||||
widget={widget!}
|
widget={widget!}
|
||||||
forceLarge={_appsWithWidgets.length === 1}
|
forceLarge={_appsWithWidgets.length === 1}
|
||||||
|
key={package_name}
|
||||||
/>)}
|
/>)}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import classNames from 'classnames'
|
|||||||
import WidgetsSettingsModal from '../components/WidgetsSettingsModal'
|
import WidgetsSettingsModal from '../components/WidgetsSettingsModal'
|
||||||
|
|
||||||
import valetIcon from '../../public/valet-icon.png'
|
import valetIcon from '../../public/valet-icon.png'
|
||||||
|
import { getFetchUrl } from '../utils/fetch'
|
||||||
|
|
||||||
interface AppStoreApp {
|
interface AppStoreApp {
|
||||||
package: string,
|
package: string,
|
||||||
@ -28,9 +29,9 @@ function Homepage() {
|
|||||||
|
|
||||||
const getAppPathsAndIcons = () => {
|
const getAppPathsAndIcons = () => {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
fetch('/apps').then(res => res.json() as any as HomepageApp[]),
|
fetch(getFetchUrl('/apps'), { credentials: 'include' }).then(res => res.json() as any as HomepageApp[]).catch(() => []),
|
||||||
fetch('/main:app_store:sys/apps').then(res => res.json()),
|
fetch(getFetchUrl('/main:app_store:sys/apps'), { credentials: 'include' }).then(res => res.json()).catch(() => []),
|
||||||
fetch('/version').then(res => res.text())
|
fetch(getFetchUrl('/version'), { credentials: 'include' }).then(res => res.text()).catch(() => '')
|
||||||
]).then(([appsData, appStoreData, version]) => {
|
]).then(([appsData, appStoreData, version]) => {
|
||||||
console.log({ appsData, appStoreData, version })
|
console.log({ appsData, appStoreData, version })
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ function Homepage() {
|
|||||||
}, [our]);
|
}, [our]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch('/our')
|
fetch(getFetchUrl('/our'), { credentials: 'include' })
|
||||||
.then(res => res.text())
|
.then(res => res.text())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.match(/^[a-zA-Z0-9\-\.]+\.[a-zA-Z]+$/)) {
|
if (data.match(/^[a-zA-Z0-9\-\.]+\.[a-zA-Z]+$/)) {
|
||||||
|
12
kinode/packages/homepage/ui/src/utils/fetch.ts
Normal file
12
kinode/packages/homepage/ui/src/utils/fetch.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Prepends or strips '/api/' based on the environment.
|
||||||
|
* @param {string} path The original path.
|
||||||
|
* @return {string} The modified path.
|
||||||
|
*/
|
||||||
|
export function getFetchUrl(path: string) {
|
||||||
|
const isDevelopment = import.meta.env.DEV;
|
||||||
|
if (isDevelopment) {
|
||||||
|
return `/api${path}`;
|
||||||
|
}
|
||||||
|
return path.replace(/^\/api/, '');
|
||||||
|
}
|
12
kinode/packages/homepage/ui/src/vite-env.d.ts
vendored
12
kinode/packages/homepage/ui/src/vite-env.d.ts
vendored
@ -1 +1,13 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_APP_TITLE: string;
|
||||||
|
readonly REACT_APP_MAINNET_RPC_URL: string;
|
||||||
|
readonly REACT_APP_SEPOLIA_RPC_URL: string;
|
||||||
|
readonly VITE_NODE_URL: string;
|
||||||
|
// Add other environment variables as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
@ -8,4 +8,13 @@ export default defineConfig({
|
|||||||
react()
|
react()
|
||||||
],
|
],
|
||||||
// ...
|
// ...
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:8080',
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
File diff suppressed because one or more lines are too long
@ -11,7 +11,7 @@
|
|||||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" />
|
||||||
<script type="module" crossorigin src="/assets/index-iKMNbHhl.js"></script>
|
<script type="module" crossorigin src="/assets/index--NeI-a3U.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-B00cPdAQ.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-B00cPdAQ.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import KinodeHome from "./pages/KinodeHome"
|
|||||||
import ResetNode from "./pages/ResetNode";
|
import ResetNode from "./pages/ResetNode";
|
||||||
import ImportKeyfile from "./pages/ImportKeyfile";
|
import ImportKeyfile from "./pages/ImportKeyfile";
|
||||||
import { UnencryptedIdentity } from "./lib/types";
|
import { UnencryptedIdentity } from "./lib/types";
|
||||||
|
import { getFetchUrl } from "./utils/fetch";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
useProvider,
|
useProvider,
|
||||||
@ -117,7 +118,7 @@ function App() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const infoResponse = await fetch('/info', { method: 'GET' })
|
const infoResponse = await fetch(getFetchUrl('/info'), { method: 'GET', credentials: 'include' })
|
||||||
|
|
||||||
if (infoResponse.status > 399) {
|
if (infoResponse.status > 399) {
|
||||||
console.log('no info, unbooted')
|
console.log('no info, unbooted')
|
||||||
@ -136,7 +137,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const currentChainResponse = await fetch('/current-chain', { method: 'GET' })
|
const currentChainResponse = await fetch(getFetchUrl('/current-chain'), { method: 'GET', credentials: 'include' })
|
||||||
|
|
||||||
if (currentChainResponse.status < 400) {
|
if (currentChainResponse.status < 400) {
|
||||||
const nodeChainId = await currentChainResponse.json()
|
const nodeChainId = await currentChainResponse.json()
|
||||||
|
@ -9,6 +9,7 @@ import { ipToNumber } from "../utils/ipToNumber";
|
|||||||
import DirectCheckbox from "../components/DirectCheckbox";
|
import DirectCheckbox from "../components/DirectCheckbox";
|
||||||
import { KinodeTitle } from "../components/KinodeTitle";
|
import { KinodeTitle } from "../components/KinodeTitle";
|
||||||
import { Tooltip } from "../components/Tooltip";
|
import { Tooltip } from "../components/Tooltip";
|
||||||
|
import { getFetchUrl } from "../utils/fetch";
|
||||||
|
|
||||||
const { useAccounts, useProvider } = hooks;
|
const { useAccounts, useProvider } = hooks;
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ function ClaimOsInvite({
|
|||||||
if (invite !== "") {
|
if (invite !== "") {
|
||||||
const url = process.env.REACT_APP_INVITE_GET + invite;
|
const url = process.env.REACT_APP_INVITE_GET + invite;
|
||||||
|
|
||||||
const response = await fetch(url, { method: "GET" });
|
const response = await fetch(getFetchUrl(url), { method: "GET", credentials: 'include' });
|
||||||
|
|
||||||
if (response!.status === 200) {
|
if (response!.status === 200) {
|
||||||
setInviteValidity("");
|
setInviteValidity("");
|
||||||
@ -80,7 +81,7 @@ function ClaimOsInvite({
|
|||||||
routers
|
routers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} = (await fetch("/generate-networking-info", { method: "POST" }).then(
|
} = (await fetch(getFetchUrl("/generate-networking-info"), { method: "POST", credentials: 'include' }).then(
|
||||||
(res) => res.json()
|
(res) => res.json()
|
||||||
)) as NetworkingInfo;
|
)) as NetworkingInfo;
|
||||||
|
|
||||||
@ -106,9 +107,10 @@ function ClaimOsInvite({
|
|||||||
console.log("BUILDING", networking_key, ipAddress, ws_port, tcp_port, routers);
|
console.log("BUILDING", networking_key, ipAddress, ws_port, tcp_port, routers);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await fetch(process.env.REACT_APP_BUILD_USER_OP_POST!, {
|
response = await fetch(getFetchUrl(process.env.REACT_APP_BUILD_USER_OP_POST!), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
|
credentials: 'include',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name: name + ".os",
|
name: name + ".os",
|
||||||
address: accounts![0],
|
address: accounts![0],
|
||||||
@ -143,9 +145,10 @@ function ClaimOsInvite({
|
|||||||
data.userOperation.signature = signature;
|
data.userOperation.signature = signature;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await fetch(process.env.REACT_APP_BROADCAST_USER_OP_POST!, {
|
response = await fetch(getFetchUrl(process.env.REACT_APP_BROADCAST_USER_OP_POST!), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
|
credentials: 'include',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
userOp: data.userOperation,
|
userOp: data.userOperation,
|
||||||
code: invite,
|
code: invite,
|
||||||
|
@ -9,6 +9,7 @@ import { utils } from "ethers";
|
|||||||
import KinodeHeader from "../components/KnsHeader";
|
import KinodeHeader from "../components/KnsHeader";
|
||||||
import { PageProps } from "../lib/types";
|
import { PageProps } from "../lib/types";
|
||||||
import Loader from "../components/Loader";
|
import Loader from "../components/Loader";
|
||||||
|
import { getFetchUrl } from "../utils/fetch";
|
||||||
|
|
||||||
interface ImportKeyfileProps extends PageProps { }
|
interface ImportKeyfileProps extends PageProps { }
|
||||||
|
|
||||||
@ -36,8 +37,9 @@ function ImportKeyfile({
|
|||||||
|
|
||||||
// const handlePassword = useCallback(async () => {
|
// const handlePassword = useCallback(async () => {
|
||||||
// try {
|
// try {
|
||||||
// const response = await fetch("/vet-keyfile", {
|
// const response = await fetch(getFetchUrl("/vet-keyfile"), {
|
||||||
// method: "POST",
|
// method: "POST",
|
||||||
|
// credentials: 'include',
|
||||||
// headers: { "Content-Type": "application/json" },
|
// headers: { "Content-Type": "application/json" },
|
||||||
// body: JSON.stringify({
|
// body: JSON.stringify({
|
||||||
// keyfile: localKey,
|
// keyfile: localKey,
|
||||||
@ -127,8 +129,9 @@ function ImportKeyfile({
|
|||||||
if (keyErrs.length === 0 && localKey !== "") {
|
if (keyErrs.length === 0 && localKey !== "") {
|
||||||
let hashed_password = utils.sha256(utils.toUtf8Bytes(pw));
|
let hashed_password = utils.sha256(utils.toUtf8Bytes(pw));
|
||||||
|
|
||||||
const response = await fetch("/vet-keyfile", {
|
const response = await fetch(getFetchUrl("/vet-keyfile"), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
credentials: 'include',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
keyfile: localKey,
|
keyfile: localKey,
|
||||||
@ -140,8 +143,9 @@ function ImportKeyfile({
|
|||||||
throw new Error("Incorrect password");
|
throw new Error("Incorrect password");
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await fetch("/import-keyfile", {
|
const result = await fetch(getFetchUrl("/import-keyfile"), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
credentials: 'include',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
keyfile: localKey,
|
keyfile: localKey,
|
||||||
@ -154,7 +158,7 @@ function ImportKeyfile({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
const res = await fetch("/");
|
const res = await fetch(getFetchUrl("/"), { credentials: 'include' });
|
||||||
if (
|
if (
|
||||||
res.status < 300 &&
|
res.status < 300 &&
|
||||||
Number(res.headers.get("content-length")) !== appSizeOnLoad
|
Number(res.headers.get("content-length")) !== appSizeOnLoad
|
||||||
|
@ -13,6 +13,7 @@ import { KinodeTitle } from "../components/KinodeTitle";
|
|||||||
import { isMobileCheck } from "../utils/dimensions";
|
import { isMobileCheck } from "../utils/dimensions";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { generateNetworkingKeys, getNetworkName } from "../utils/chain";
|
import { generateNetworkingKeys, getNetworkName } from "../utils/chain";
|
||||||
|
import { getFetchUrl } from "../utils/fetch";
|
||||||
|
|
||||||
const { useProvider } = hooks;
|
const { useProvider } = hooks;
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ function Login({
|
|||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const infoData = (await fetch("/info", { method: "GET" }).then((res) =>
|
const infoData = (await fetch(getFetchUrl("/info"), { method: "GET", credentials: 'include' }).then((res) =>
|
||||||
res.json()
|
res.json()
|
||||||
)) as UnencryptedIdentity;
|
)) as UnencryptedIdentity;
|
||||||
setRouters(infoData.allowed_routers);
|
setRouters(infoData.allowed_routers);
|
||||||
@ -81,8 +82,9 @@ function Login({
|
|||||||
let hashed_password = utils.sha256(utils.toUtf8Bytes(pw));
|
let hashed_password = utils.sha256(utils.toUtf8Bytes(pw));
|
||||||
|
|
||||||
// Replace this with network key generation
|
// Replace this with network key generation
|
||||||
const response = await fetch("/vet-keyfile", {
|
const response = await fetch(getFetchUrl("/vet-keyfile"), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
credentials: 'include',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ password_hash: hashed_password, keyfile: "" }),
|
body: JSON.stringify({ password_hash: hashed_password, keyfile: "" }),
|
||||||
});
|
});
|
||||||
@ -119,9 +121,10 @@ function Login({
|
|||||||
|
|
||||||
// Login or confirm new keys
|
// Login or confirm new keys
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
reset ? "confirm-change-network-keys" : "login",
|
getFetchUrl(reset ? "confirm-change-network-keys" : "login"),
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
credentials: 'include',
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: reset
|
body: reset
|
||||||
? JSON.stringify({ password_hash: hashed_password, direct })
|
? JSON.stringify({ password_hash: hashed_password, direct })
|
||||||
@ -139,7 +142,7 @@ function Login({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
const res = await fetch("/");
|
const res = await fetch(getFetchUrl("/"), { credentials: 'include' });
|
||||||
if (
|
if (
|
||||||
res.status < 300 &&
|
res.status < 300 &&
|
||||||
Number(res.headers.get("content-length")) !== appSizeOnLoad
|
Number(res.headers.get("content-length")) !== appSizeOnLoad
|
||||||
|
@ -5,6 +5,7 @@ import { utils, providers } from "ethers";
|
|||||||
import { downloadKeyfile } from "../utils/download-keyfile";
|
import { downloadKeyfile } from "../utils/download-keyfile";
|
||||||
import { Tooltip } from "../components/Tooltip";
|
import { Tooltip } from "../components/Tooltip";
|
||||||
import { KinodeTitle } from "../components/KinodeTitle";
|
import { KinodeTitle } from "../components/KinodeTitle";
|
||||||
|
import { getFetchUrl } from "../utils/fetch";
|
||||||
|
|
||||||
type SetPasswordProps = {
|
type SetPasswordProps = {
|
||||||
direct: boolean;
|
direct: boolean;
|
||||||
@ -70,7 +71,7 @@ function SetPassword({
|
|||||||
let signature = await signer?.signMessage(utils.toUtf8Bytes(sig_data));
|
let signature = await signer?.signMessage(utils.toUtf8Bytes(sig_data));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await fetch("/boot", {
|
const result = await fetch(getFetchUrl("/boot"), {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -90,7 +91,7 @@ function SetPassword({
|
|||||||
downloadKeyfile(knsName, base64String);
|
downloadKeyfile(knsName, base64String);
|
||||||
|
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
const res = await fetch("/");
|
const res = await fetch(getFetchUrl("/"), { credentials: 'include' });
|
||||||
|
|
||||||
if (
|
if (
|
||||||
res.status < 300 &&
|
res.status < 300 &&
|
||||||
|
12
kinode/src/register-ui/src/utils/fetch.ts
Normal file
12
kinode/src/register-ui/src/utils/fetch.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Prepends or strips '/api/' based on the environment.
|
||||||
|
* @param {string} path The original path.
|
||||||
|
* @return {string} The modified path.
|
||||||
|
*/
|
||||||
|
export function getFetchUrl(path: string) {
|
||||||
|
const isDevelopment = import.meta.env.DEV;
|
||||||
|
if (isDevelopment) {
|
||||||
|
return `/api${path}`;
|
||||||
|
}
|
||||||
|
return path.replace(/^\/api/, '');
|
||||||
|
}
|
@ -44,29 +44,10 @@ export default defineConfig({
|
|||||||
// ...
|
// ...
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/generate-networking-info': {
|
'/api': {
|
||||||
target: 'http://localhost:8080/generate-networking-info',
|
target: 'http://localhost:8080',
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
'/vet-keyfile': {
|
|
||||||
target: 'http://localhost:8080/vet-keyfile',
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
'/import-keyfile': {
|
|
||||||
target: 'http://localhost:8080/import-keyfile',
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
'/info': {
|
|
||||||
target: 'http://localhost:8080/info',
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
'/current-chain': {
|
|
||||||
target: 'http://localhost:8080/current-chain',
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
'/boot': {
|
|
||||||
target: 'http://localhost:8080/boot',
|
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user