fix
This commit is contained in:
parent
b58490700b
commit
de88c0adcf
|
|
@ -0,0 +1,44 @@
|
|||
declare module "exports" {
|
||||
export const _web: {
|
||||
name: string;
|
||||
url: string;
|
||||
path: string;
|
||||
args: string[];
|
||||
handler: Promise<any>;
|
||||
};
|
||||
export const _upload: {
|
||||
name: string;
|
||||
url: string;
|
||||
path: string;
|
||||
args: string[];
|
||||
handler: Promise<any>;
|
||||
};
|
||||
export const _prasi: {
|
||||
name: string;
|
||||
url: string;
|
||||
path: string;
|
||||
args: any[];
|
||||
handler: Promise<any>;
|
||||
};
|
||||
export const _file: {
|
||||
name: string;
|
||||
url: string;
|
||||
path: string;
|
||||
args: any[];
|
||||
handler: Promise<any>;
|
||||
};
|
||||
export const _api_frm: {
|
||||
name: string;
|
||||
url: string;
|
||||
path: string;
|
||||
args: any[];
|
||||
handler: Promise<any>;
|
||||
};
|
||||
export const _dbs: {
|
||||
name: string;
|
||||
url: string;
|
||||
path: string;
|
||||
args: string[];
|
||||
handler: Promise<any>;
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
export const _web = {
|
||||
name: "_web",
|
||||
url: "/_web/:id/**",
|
||||
path: "app/srv/api/_web.ts",
|
||||
args: ["id","_"],
|
||||
handler: import("./api/_web")
|
||||
}
|
||||
export const _upload = {
|
||||
name: "_upload",
|
||||
url: "/_upload",
|
||||
path: "app/srv/api/_upload.ts",
|
||||
args: ["body"],
|
||||
handler: import("./api/_upload")
|
||||
}
|
||||
export const _prasi = {
|
||||
name: "_prasi",
|
||||
url: "/_prasi/**",
|
||||
path: "app/srv/api/_prasi.ts",
|
||||
args: [],
|
||||
handler: import("./api/_prasi")
|
||||
}
|
||||
export const _file = {
|
||||
name: "_file",
|
||||
url: "/_file/**",
|
||||
path: "app/srv/api/_file.ts",
|
||||
args: [],
|
||||
handler: import("./api/_file")
|
||||
}
|
||||
export const _api_frm = {
|
||||
name: "_api_frm",
|
||||
url: "/_api_frm",
|
||||
path: "app/srv/api/_api_frm.ts",
|
||||
args: [],
|
||||
handler: import("./api/_api_frm")
|
||||
}
|
||||
export const _dbs = {
|
||||
name: "_dbs",
|
||||
url: "/_dbs/:dbName/:action",
|
||||
path: "app/srv/api/_dbs.ts",
|
||||
args: ["dbName","action"],
|
||||
handler: import("./api/_dbs")
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
"@swc/wasm-web": "1.3.94-nightly-20231014.1",
|
||||
"algoliasearch": "^4.20.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"dbgen": "workspace:*",
|
||||
"downshift": "^8.2.2",
|
||||
"esbuild-wasm": "^0.19.4",
|
||||
"idb-keyval": "^6.2.1",
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
"prettier": "3.0.3",
|
||||
"prop-types": "^15.8.1",
|
||||
"quill-delta": "^5.1.0",
|
||||
"radix3": "^1.1.0",
|
||||
"react": "18.2.0",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dnd": "^16.0.1",
|
||||
|
|
@ -52,11 +54,10 @@
|
|||
"tinycolor2": "^1.6.0",
|
||||
"ua-parser-js": "^1.0.36",
|
||||
"uuid": "9.0.1",
|
||||
"web-utils": "workspace:*",
|
||||
"y-pojo": "^0.0.8",
|
||||
"yjs": "^13.6.8",
|
||||
"yjs-types": "^0.0.1",
|
||||
"web-utils": "workspace:*",
|
||||
"dbgen": "workspace:*"
|
||||
"yjs-types": "^0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash.concat": "^4.5.7",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { useEffect } from "react";
|
||||
import { page } from "web-utils";
|
||||
|
||||
export default page({
|
||||
url: "*",
|
||||
url: "**",
|
||||
component: ({}) => {
|
||||
navigate("/login");
|
||||
useEffect(() => {
|
||||
navigate("/login");
|
||||
}, []);
|
||||
return <div>Loading...</div>;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export default page({
|
|||
|
||||
return (
|
||||
<Live
|
||||
mode={"dev"}
|
||||
domain={params.domain}
|
||||
pathname={`/${params._ === "_" ? "" : params._}`}
|
||||
loader={defaultLoader}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
export const all = {
|
||||
url: "**",
|
||||
page: () => import("./page/all"),
|
||||
};
|
||||
export const login = {
|
||||
url: "/login",
|
||||
page: () => import("./page/auth/login"),
|
||||
};
|
||||
|
|
@ -1,25 +1,45 @@
|
|||
import { FC } from "react";
|
||||
|
||||
import { useState } from "react";
|
||||
import { GlobalContext } from "web-utils";
|
||||
|
||||
const w = window as unknown as {
|
||||
prasiContext: any;
|
||||
rootRender: any;
|
||||
};
|
||||
|
||||
w.prasiContext = {
|
||||
global: {},
|
||||
render() {},
|
||||
};
|
||||
import { createRouter } from "radix3";
|
||||
import { FC, Suspense, lazy } from "react";
|
||||
import { GlobalContext, useLocal } from "web-utils";
|
||||
import { Loading } from "../utils/ui/loading";
|
||||
|
||||
export const Root: FC<{}> = ({}) => {
|
||||
const [_, render] = useState({});
|
||||
w.prasiContext.render = () => {
|
||||
render({});
|
||||
};
|
||||
w.rootRender = w.prasiContext.render;
|
||||
const local = useLocal(
|
||||
{
|
||||
router: createRouter<any>({ strictTrailingSlash: true }),
|
||||
Page: null as any,
|
||||
},
|
||||
async () => {
|
||||
const pages = await import("./pages");
|
||||
for (const [_, v] of Object.entries(pages)) {
|
||||
local.router.insert(
|
||||
v.url,
|
||||
lazy(async () => {
|
||||
return { default: (await v.page()).default.component as any };
|
||||
})
|
||||
);
|
||||
}
|
||||
local.render();
|
||||
}
|
||||
);
|
||||
|
||||
prasiContext.render = local.render;
|
||||
const Provider = GlobalContext.Provider as FC<{ value: any; children: any }>;
|
||||
return <Provider value={w.prasiContext}>Hello mantapun alamuko</Provider>;
|
||||
|
||||
const found = local.router.lookup(location.pathname);
|
||||
if (found) {
|
||||
local.Page = found;
|
||||
}
|
||||
|
||||
if (!local.Page) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Provider value={prasiContext}>
|
||||
<Suspense>
|
||||
<local.Page />
|
||||
</Suspense>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import { defineReact, defineWindow } from "web-utils";
|
||||
import { Root } from "./base/root";
|
||||
import "./index.css";
|
||||
import { createAPI, createDB, reloadDBAPI } from "./utils/script/init-api";
|
||||
|
||||
const registerServiceWorker = async () => {
|
||||
if ("serviceWorker" in navigator) {
|
||||
|
|
@ -21,6 +23,18 @@ const registerServiceWorker = async () => {
|
|||
registerServiceWorker();
|
||||
|
||||
const el = document.getElementById("root");
|
||||
|
||||
if (el) {
|
||||
createRoot(el).render(<Root />);
|
||||
(async () => {
|
||||
defineReact();
|
||||
await defineWindow(false);
|
||||
const w = window as any;
|
||||
const base = `${location.protocol}//${location.host}`;
|
||||
|
||||
await reloadDBAPI(base);
|
||||
w.api = createAPI(base);
|
||||
w.db = createDB(base);
|
||||
|
||||
createRoot(el).render(<Root />);
|
||||
})();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { createStore, get, set } from "idb-keyval";
|
||||
import trim from "lodash.trim";
|
||||
import { apiClient, dbClient } from "web-utils";
|
||||
import { createFrameCors } from "web-utils/src/web/iframe-cors";
|
||||
import { createFrameCors } from "web-utils";
|
||||
export const w = window as unknown as {
|
||||
prasiApi: Record<string, any>;
|
||||
apiHeaders: any;
|
||||
|
|
@ -16,6 +16,10 @@ export const createAPI = (url: string) => {
|
|||
w.apiClient = apiClient;
|
||||
}
|
||||
|
||||
if (!w.prasiApi) {
|
||||
w.prasiApi = {};
|
||||
}
|
||||
|
||||
return w.apiClient(w.prasiApi[url]?.apiEntry, url);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"module": "src/index.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "bun run --silent --watch ./pkgs/core/index.ts dev",
|
||||
"dev": "bun clean && bun run --silent --watch ./pkgs/core/index.ts dev",
|
||||
"clean": "rm -rf app/static && rm -rf app/web/.parcel-cache",
|
||||
"prod": "bun run --silent ./pkgs/core/index.ts",
|
||||
"pull": "cd app/db && bun prisma db pull && bun prisma generate",
|
||||
|
|
|
|||
|
|
@ -48,5 +48,5 @@ export const scanApi = async () => {
|
|||
}
|
||||
};
|
||||
await scan(dir(`app/srv/api`));
|
||||
await scan(dir(`pkgs/api`));
|
||||
await scan(dir(`pkgs/core/api`));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,25 +13,18 @@ export const createServer = async () => {
|
|||
async fetch(req) {
|
||||
const url = new URL(req.url);
|
||||
|
||||
if (req.method === "GET") {
|
||||
try {
|
||||
const file = Bun.file(dir(`app/static${url.pathname}`));
|
||||
if (file.type !== "application/octet-stream") {
|
||||
return new Response(file as any);
|
||||
}
|
||||
} catch (e) {}
|
||||
return new Response(Bun.file(dir(`app/static/index.html`)) as any);
|
||||
} else {
|
||||
const api = await serveAPI(url, req);
|
||||
if (api) {
|
||||
return api;
|
||||
}
|
||||
const api = await serveAPI(url, req);
|
||||
if (api) {
|
||||
return api;
|
||||
}
|
||||
|
||||
return new Response(`404 Not Found`, {
|
||||
status: 404,
|
||||
statusText: "Not Found",
|
||||
});
|
||||
try {
|
||||
const file = Bun.file(dir(`app/static${url.pathname}`));
|
||||
if (file.type !== "application/octet-stream") {
|
||||
return new Response(file as any);
|
||||
}
|
||||
} catch (e) {}
|
||||
return new Response(Bun.file(dir(`app/static/index.html`)) as any);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
"main": "src/export.ts",
|
||||
"dependencies": {
|
||||
"@paralleldrive/cuid2": "2.2.0",
|
||||
"@types/hash-sum": "^1.0.0",
|
||||
"goober": "^2.1.13",
|
||||
"hash-sum": "^2.0.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
import { fetchSendApi } from "./client-frame";
|
||||
|
||||
export const apiClient = (
|
||||
api: Record<string, { url: string; args: any[] }>,
|
||||
apiUrl: string
|
||||
) => {
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get: (_, actionName: string) => {
|
||||
const createFn = (actionName: string) => {
|
||||
return function (this: { apiUrl: string } | undefined, ...rest: any) {
|
||||
return new Promise<any>(async (resolve, reject) => {
|
||||
try {
|
||||
let _apiURL = apiUrl;
|
||||
if (typeof this?.apiUrl === "string") {
|
||||
_apiURL = this.apiUrl;
|
||||
}
|
||||
|
||||
if (!api || !api[actionName]) {
|
||||
resolve(null);
|
||||
console.error(
|
||||
`API ${actionName.toString()} not found, existing API: ${Object.keys(
|
||||
api
|
||||
)}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let actionUrl = api[actionName].url;
|
||||
const actionParams = api[actionName].args;
|
||||
if (actionUrl && actionParams) {
|
||||
if (rest.length > 0 && actionParams.length > 0) {
|
||||
for (const [idx, p] of Object.entries(rest)) {
|
||||
const paramName = actionParams[parseInt(idx)];
|
||||
if (actionParams && actionParams.includes(paramName)) {
|
||||
if (
|
||||
!!p &&
|
||||
typeof p !== "string" &&
|
||||
typeof p !== "number"
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
actionUrl = actionUrl.replace(`:${paramName}?`, p + "");
|
||||
actionUrl = actionUrl.replace(`:${paramName}`, p + "");
|
||||
}
|
||||
}
|
||||
|
||||
const url = `${_apiURL}${actionUrl}`;
|
||||
|
||||
const result = await fetchSendApi(url, rest);
|
||||
resolve(result);
|
||||
} else {
|
||||
console.error(`API Not Found: ${actionName.toString()}`);
|
||||
}
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
if (actionName === "then") {
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get: (_, actionName: string) => {
|
||||
return createFn(actionName);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return createFn(actionName);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
import { waitUntil } from "web-utils";
|
||||
import { createFrameCors } from "./client-frame";
|
||||
import hash_sum from "hash-sum";
|
||||
|
||||
export const dbClient = (name: string, dburl?: string) => {
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get(_, table: string) {
|
||||
if (table === "_tables") {
|
||||
return () => {
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action: "definition",
|
||||
table: "*",
|
||||
},
|
||||
dburl
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
if (table === "_definition") {
|
||||
return (table: string) => {
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action: "definition",
|
||||
table,
|
||||
},
|
||||
dburl
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
if (table.startsWith("$")) {
|
||||
return (...params: any[]) => {
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action: "query",
|
||||
table,
|
||||
params,
|
||||
},
|
||||
dburl
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get(_, action: string) {
|
||||
return (...params: any[]) => {
|
||||
if (table === "query") {
|
||||
table = action;
|
||||
action = "query";
|
||||
}
|
||||
return fetchSendDb(
|
||||
name,
|
||||
{
|
||||
name,
|
||||
action,
|
||||
table,
|
||||
params,
|
||||
},
|
||||
dburl
|
||||
);
|
||||
};
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const cachedQueryResult: Record<string, { timestamp: number; result: any }> =
|
||||
{};
|
||||
|
||||
export const fetchSendDb = async (
|
||||
name: string,
|
||||
params: any,
|
||||
dburl?: string
|
||||
) => {
|
||||
const w = typeof window === "object" ? window : (globalThis as any);
|
||||
let url = `/_dbs/${name}`;
|
||||
let frm: Awaited<ReturnType<typeof createFrameCors>>;
|
||||
|
||||
if (params.table) {
|
||||
url += `/${params.table}`;
|
||||
}
|
||||
|
||||
const _base = dburl || w.serverurl;
|
||||
|
||||
if (!w.frmapi) {
|
||||
w.frmapi = {};
|
||||
}
|
||||
|
||||
if (!w.frmapi[_base]) {
|
||||
w.frmapi[_base] = await createFrameCors(_base);
|
||||
}
|
||||
|
||||
frm = w.frmapi[_base];
|
||||
|
||||
if (!frm) {
|
||||
await waitUntil(() => {
|
||||
frm = w.frmapi[_base];
|
||||
return frm;
|
||||
});
|
||||
}
|
||||
|
||||
const hsum = hash_sum(params);
|
||||
const cached = cachedQueryResult[hsum];
|
||||
|
||||
if (!cached || (cached && Date.now() - cached.timestamp > 1000)) {
|
||||
cachedQueryResult[hsum] = {
|
||||
timestamp: Date.now(),
|
||||
result: null,
|
||||
};
|
||||
|
||||
const result = await frm.send(url, params, w.apiHeaders);
|
||||
cachedQueryResult[hsum].result = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
return cached.result;
|
||||
};
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
import { waitUntil } from "web-utils";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
const cuid = createId;
|
||||
|
||||
(BigInt.prototype as any).toJSON = function (): string {
|
||||
return `BigInt::` + this.toString();
|
||||
};
|
||||
|
||||
export const createFrameCors = async (url: string, win?: any) => {
|
||||
let w = window;
|
||||
if (!!win) {
|
||||
w = win;
|
||||
}
|
||||
const document = w.document;
|
||||
|
||||
const id = `__` + url.replace(/\W/g, "");
|
||||
|
||||
if (typeof document !== "undefined" && !document.querySelector(`#${id}`)) {
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.style.display = "none";
|
||||
iframe.id = id;
|
||||
|
||||
const _url = new URL(url);
|
||||
_url.pathname = "/_api_frm";
|
||||
iframe.src = _url.toString();
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
iframe.onload = () => {
|
||||
if (!iframe.contentDocument) {
|
||||
setTimeout(() => {
|
||||
if (!iframe.contentDocument) {
|
||||
reject(
|
||||
`Cannot load iframe ${_url.toString()}. content document not found.`
|
||||
);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
const onInit = (e: any) => {
|
||||
if (e.data === "initialized") {
|
||||
iframe.setAttribute("loaded", "y");
|
||||
w.removeEventListener("message", onInit);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
w.addEventListener("message", onInit);
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
const wm = {} as Record<string, any>;
|
||||
|
||||
const sendRaw = async (
|
||||
input: RequestInfo | URL,
|
||||
init?: RequestInit | undefined
|
||||
) => {
|
||||
if (w.document && w.document.querySelector) {
|
||||
const iframe = w.document.querySelector(`#${id}`) as HTMLIFrameElement;
|
||||
|
||||
if (
|
||||
!iframe ||
|
||||
!iframe.contentWindow ||
|
||||
(iframe && iframe.getAttribute("loaded") !== "y")
|
||||
) {
|
||||
await waitUntil(
|
||||
() =>
|
||||
iframe &&
|
||||
iframe.contentWindow &&
|
||||
iframe.getAttribute("loaded") === "y"
|
||||
);
|
||||
}
|
||||
|
||||
return await new Promise((resolve, reject) => {
|
||||
if (iframe && iframe.contentWindow) {
|
||||
const id = cuid();
|
||||
wm[id] = (e: any) => {
|
||||
if (id === e.data.id) {
|
||||
w.removeEventListener("message", wm[id]);
|
||||
delete wm[id];
|
||||
if (e.data.error) {
|
||||
let err = e.data.error;
|
||||
if (typeof err === "string") {
|
||||
reject(
|
||||
err.replace(
|
||||
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
|
||||
""
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
resolve(e.data.result);
|
||||
}
|
||||
}
|
||||
};
|
||||
w.addEventListener("message", wm[id]);
|
||||
|
||||
let _input = input;
|
||||
if (typeof input === "string") {
|
||||
if (!input.startsWith("http")) {
|
||||
_input = `${url}${input}`;
|
||||
}
|
||||
}
|
||||
iframe.contentWindow.postMessage({ input: _input, init, id }, "*");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
sendRaw,
|
||||
async send(input: string | RequestInfo | URL, data?: any, _headers?: any) {
|
||||
const uri = input.toString();
|
||||
const headers = { ..._headers };
|
||||
|
||||
let body = data;
|
||||
let isFile = false;
|
||||
|
||||
const formatSingle = async (data: any) => {
|
||||
if (!(data instanceof w.FormData || data instanceof w.File)) {
|
||||
headers["content-type"] = "application/json";
|
||||
} else {
|
||||
if (data instanceof w.File) {
|
||||
isFile = true;
|
||||
let ab = await new Promise<ArrayBuffer | undefined>((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", (e) => {
|
||||
resolve(e.target?.result as ArrayBuffer);
|
||||
});
|
||||
reader.readAsArrayBuffer(data);
|
||||
});
|
||||
if (ab) {
|
||||
data = new File([ab], data.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
body = await Promise.all(data.map((e) => formatSingle(e)));
|
||||
} else {
|
||||
body = await formatSingle(data);
|
||||
}
|
||||
if (!isFile) {
|
||||
body = JSON.stringify(body);
|
||||
}
|
||||
|
||||
return await sendRaw(
|
||||
`${url.endsWith("/") ? url : `${url}/`}${
|
||||
uri.startsWith("/") ? uri.substring(1) : uri
|
||||
}`,
|
||||
data
|
||||
? {
|
||||
method: "post",
|
||||
headers,
|
||||
body,
|
||||
}
|
||||
: {}
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchSendApi = async (
|
||||
_url: string,
|
||||
params: any,
|
||||
parentWindow?: any
|
||||
) => {
|
||||
let w: any = typeof window === "object" ? window : globalThis;
|
||||
|
||||
const win = parentWindow || w;
|
||||
let url = _url;
|
||||
let frm: Awaited<ReturnType<typeof createFrameCors>>;
|
||||
if (!win.frmapi) {
|
||||
win.frmapi = {};
|
||||
|
||||
win.frmapi[w.serverurl] = await createFrameCors(w.serverurl, win);
|
||||
}
|
||||
|
||||
frm = win.frmapi[w.serverurl];
|
||||
|
||||
if (url.startsWith("http")) {
|
||||
const purl = new URL(url);
|
||||
if (!win.frmapi[purl.host]) {
|
||||
win.frmapi[purl.host] = await createFrameCors(
|
||||
`${purl.protocol}//${purl.host}`
|
||||
);
|
||||
}
|
||||
|
||||
frm = win.frmapi[purl.host];
|
||||
url = url.substring(`${purl.protocol}//${purl.host}`.length);
|
||||
}
|
||||
if (!win.apiHeaders) {
|
||||
win.apiHeaders = {};
|
||||
}
|
||||
|
||||
if (!frm) {
|
||||
await waitUntil(() => {
|
||||
frm = win.frmapi[w.serverurl];
|
||||
return frm;
|
||||
});
|
||||
}
|
||||
|
||||
return await frm.send(url, params, win.apiHeaders);
|
||||
};
|
||||
|
|
@ -6,6 +6,11 @@ export const defineWindow = async (awaitServerUrl = true) => {
|
|||
|
||||
if (awaitServerUrl) await waitUntil(() => w.__SRV_URL__);
|
||||
|
||||
w.prasiContext = {
|
||||
global: {},
|
||||
render() {},
|
||||
};
|
||||
|
||||
const location = window["location"];
|
||||
|
||||
const host =
|
||||
|
|
@ -70,11 +75,10 @@ export const defineWindow = async (awaitServerUrl = true) => {
|
|||
}
|
||||
|
||||
history.pushState({}, "", _href);
|
||||
if (w.rootRes) w.rootRes.pathname = href;
|
||||
w.pathname = href;
|
||||
|
||||
if (w.rootRender) {
|
||||
w.rootRender();
|
||||
if (w.prasiContext && w.prasiContext.render) {
|
||||
w.prasiContext.render();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,4 +7,7 @@ export * from "./page";
|
|||
export * from "./global";
|
||||
export * from "./define-react";
|
||||
export * from "./define-window";
|
||||
export * from './client-api';
|
||||
export * from './client-frame';
|
||||
export * from './client-db';
|
||||
export const React = _React;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
import goober from "goober";
|
||||
|
||||
declare global {
|
||||
const navigate: (path: string) => void;
|
||||
const params: any;
|
||||
const css: typeof goober.css;
|
||||
const cx: (...arg: string[]) => string;
|
||||
const api: any;
|
||||
const db: any;
|
||||
const prasiContext: any;
|
||||
}
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
|
||||
export const useLocal = <T extends object>(
|
||||
data: T,
|
||||
effect?: (arg: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue